Skip to content

Instantly share code, notes, and snippets.

@ezynda3
Created October 22, 2025 10:45
Show Gist options
  • Select an option

  • Save ezynda3/c66e299c0b9f1627ed92440a647fbc74 to your computer and use it in GitHub Desktop.

Select an option

Save ezynda3/c66e299c0b9f1627ed92440a647fbc74 to your computer and use it in GitHub Desktop.
Mongo DB TS Helpers
import { config } from 'dotenv'
import { MongoClient } from 'mongodb'
import { consola } from 'consola'
import { type Address, type Hex } from 'viem'
import { getRPCEnvVarName } from '../script/utils/network.js'
import {
type ISafeTxDocument,
type ISafeTransaction,
OperationTypeEnum,
storeTransactionInMongoDB,
getNextNonce,
getPendingTransactionsByNetwork,
getSafeMongoCollection,
} from '../script/deploy/safe/safe-utils.js'
config()
interface IRpcEndpoint {
url: string
priority: number
isActive?: boolean
network: string
environment?: string
}
const TEST_NETWORK = 'testnetwork'
const TEST_CHAIN_ID = 999999
const TEST_SAFE_ADDRESS =
'0x1234567890123456789012345678901234567890' as Address
const TEST_RPC_URL = 'https://test-rpc.example.com'
const TEST_PROPOSER = '0x0987654321098765432109876543210987654321' as Address
async function testRpcEndpoints(client: MongoClient) {
consola.info('Testing RPC Endpoints CRUD operations...')
const db = client.db('sc_public')
const collection = db.collection('RpcEndpoints')
const testChainName = `test_chain_${Date.now()}`
consola.info('1. CREATE: Adding new RPC endpoint')
const newRpcEndpoint = {
url: TEST_RPC_URL,
priority: 1,
environment: 'production',
}
await collection.updateOne(
{ chainName: testChainName },
{
$set: { lastUpdated: new Date() },
$push: { rpcs: newRpcEndpoint } as any,
},
{ upsert: true }
)
consola.success(`✓ Created RPC endpoint for ${testChainName}`)
consola.info('2. READ: Fetching RPC endpoint')
const doc = await collection.findOne({ chainName: testChainName })
if (!doc || !doc.rpcs || doc.rpcs.length === 0)
throw new Error('Failed to read RPC endpoint')
consola.success(`✓ Read RPC endpoint: ${doc.rpcs[0].url}`)
consola.info('3. UPDATE: Updating RPC endpoint priority')
const newPriority = 10
await collection.updateOne(
{ chainName: testChainName },
{
$set: {
lastUpdated: new Date(),
'rpcs.0.priority': newPriority,
},
}
)
const updatedDoc = await collection.findOne({ chainName: testChainName })
if (!updatedDoc || updatedDoc.rpcs[0].priority !== newPriority)
throw new Error('Failed to update RPC endpoint priority')
consola.success(`✓ Updated priority to ${newPriority}`)
consola.info('4. DELETE: Removing RPC endpoint')
const deleteResult = await collection.deleteOne({ chainName: testChainName })
if (deleteResult.deletedCount !== 1)
throw new Error('Failed to delete RPC endpoint')
consola.success(`✓ Deleted RPC endpoint for ${testChainName}`)
}
async function testPendingTransactions(client: MongoClient) {
consola.info('\nTesting PendingTransactions CRUD operations...')
const db = client.db('sc_private')
const pendingTransactions = db.collection<ISafeTxDocument>(
'pendingTransactions'
)
const testNetwork = `${TEST_NETWORK}_${Date.now()}`
const testNonce = 42n
consola.info('1. CREATE: Storing new pending transaction')
const safeTx: ISafeTransaction = {
data: {
to: '0xabcdef1234567890abcdef1234567890abcdef12' as Address,
value: 0n,
data: '0x1234' as Hex,
operation: OperationTypeEnum.Call,
nonce: testNonce,
},
signatures: new Map(),
}
const safeTxHash = '0xhash123' as Hex
const insertResult = await storeTransactionInMongoDB(
pendingTransactions,
TEST_SAFE_ADDRESS,
testNetwork,
TEST_CHAIN_ID,
safeTx,
safeTxHash,
TEST_PROPOSER
)
if (!insertResult.insertedId)
throw new Error('Failed to create pending transaction')
consola.success(
`✓ Created pending transaction with ID: ${insertResult.insertedId}`
)
consola.info('2. READ: Fetching pending transaction')
const txDoc = await pendingTransactions.findOne({
_id: insertResult.insertedId,
})
if (!txDoc) throw new Error('Failed to read pending transaction')
consola.success(`✓ Read pending transaction for network: ${txDoc.network}`)
consola.info('3. UPDATE: Adding signature to transaction')
const testSignature = {
signer: TEST_PROPOSER,
data: '0xsignature123' as Hex,
}
await pendingTransactions.updateOne(
{ _id: insertResult.insertedId },
{
$set: {
[`safeTx.signatures.${TEST_PROPOSER.toLowerCase()}`]: testSignature,
},
}
)
const updatedTxDoc = await pendingTransactions.findOne({
_id: insertResult.insertedId,
})
if (
!updatedTxDoc ||
!updatedTxDoc.safeTx.signatures ||
!updatedTxDoc.safeTx.signatures[TEST_PROPOSER.toLowerCase()]
)
throw new Error('Failed to update transaction with signature')
consola.success(`✓ Updated transaction with signature from ${TEST_PROPOSER}`)
consola.info('4. Testing helper functions')
consola.info('4a. Testing getNextNonce')
const nextNonce = await getNextNonce(
pendingTransactions,
TEST_SAFE_ADDRESS,
testNetwork,
TEST_CHAIN_ID,
testNonce
)
if (nextNonce !== testNonce + 1n)
throw new Error(
`getNextNonce failed: expected ${testNonce + 1n}, got ${nextNonce}`
)
consola.success(`✓ getNextNonce returned correct value: ${nextNonce}`)
consola.info(
'4b. Creating second transaction for getPendingTransactionsByNetwork test'
)
const safeTx2: ISafeTransaction = {
data: {
to: '0xfedcba0987654321fedcba0987654321fedcba09' as Address,
value: 100n,
data: '0x5678' as Hex,
operation: OperationTypeEnum.Call,
nonce: testNonce + 1n,
},
signatures: new Map(),
}
const insertResult2 = await storeTransactionInMongoDB(
pendingTransactions,
TEST_SAFE_ADDRESS,
testNetwork,
TEST_CHAIN_ID,
safeTx2,
'0xhash456' as Hex,
TEST_PROPOSER
)
if (!insertResult2.insertedId)
throw new Error('Failed to create second pending transaction')
consola.info('4c. Testing getPendingTransactionsByNetwork')
const txsByNetwork = await getPendingTransactionsByNetwork(
pendingTransactions,
[testNetwork]
)
if (!txsByNetwork[testNetwork] || txsByNetwork[testNetwork].length !== 2)
throw new Error(
`getPendingTransactionsByNetwork failed: expected 2 transactions, got ${
txsByNetwork[testNetwork]?.length || 0
}`
)
consola.success(
`✓ getPendingTransactionsByNetwork returned ${txsByNetwork[testNetwork].length} transactions`
)
consola.info('4d. Testing transaction sorting by nonce')
const sortedTxs = txsByNetwork[testNetwork]
if (sortedTxs[0].safeTx.data.nonce >= sortedTxs[1].safeTx.data.nonce)
throw new Error('Transactions not sorted by nonce')
consola.success(`✓ Transactions correctly sorted by nonce`)
consola.info('5. UPDATE: Marking transaction as executed')
await pendingTransactions.updateOne(
{ _id: insertResult.insertedId },
{ $set: { status: 'executed' } }
)
const executedTxDoc = await pendingTransactions.findOne({
_id: insertResult.insertedId,
})
if (!executedTxDoc || executedTxDoc.status !== 'executed')
throw new Error('Failed to mark transaction as executed')
consola.success(`✓ Marked transaction as executed`)
consola.info('6. DELETE: Removing test transactions')
const deleteResult = await pendingTransactions.deleteMany({
network: testNetwork,
})
if (deleteResult.deletedCount !== 2)
throw new Error(
`Failed to delete all test transactions: deleted ${deleteResult.deletedCount}, expected 2`
)
consola.success(`✓ Deleted ${deleteResult.deletedCount} test transactions`)
}
async function testFetchRpcsHelper() {
consola.info('\nTesting fetch-rpcs helper functions...')
const MONGODB_URI = process.env.MONGODB_URI
if (!MONGODB_URI)
throw new Error('MONGODB_URI is not defined in the environment')
const client = new MongoClient(MONGODB_URI)
try {
await client.connect()
const db = client.db('sc_public')
const collection = db.collection('RpcEndpoints')
const testChainName = `test_fetch_${Date.now()}`
consola.info('1. Setting up test RPC endpoints')
await collection.insertOne({
chainName: testChainName,
rpcs: [
{
url: 'https://rpc1.example.com',
priority: 2,
isActive: true,
},
{
url: 'https://rpc2.example.com',
priority: 5,
isActive: true,
},
{
url: 'https://rpc3.example.com',
priority: 1,
isActive: false,
},
],
lastUpdated: new Date(),
})
consola.info('2. Fetching and verifying sorting')
const docs = await collection.find({ chainName: testChainName }).toArray()
let validEndpoints: IRpcEndpoint[] = []
for (const doc of docs) {
if (doc?.chainName && Array.isArray(doc?.rpcs)) {
validEndpoints = doc.rpcs.filter((r: any) => !!r.url)
validEndpoints.sort((a, b) => b.priority - a.priority)
}
}
if (validEndpoints.length !== 3)
throw new Error(`Expected 3 endpoints, got ${validEndpoints.length}`)
if (validEndpoints[0].priority !== 5)
throw new Error(
`Expected highest priority 5, got ${validEndpoints[0].priority}`
)
consola.success(`✓ RPC endpoints correctly sorted by priority (descending)`)
consola.info('3. Testing getRPCEnvVarName helper')
const envVarName = getRPCEnvVarName(testChainName)
const expectedName = `ETH_NODE_URI_${testChainName
.toUpperCase()
.replace(/-/g, '_')}`
if (envVarName !== expectedName)
throw new Error(
`getRPCEnvVarName failed: expected ${expectedName}, got ${envVarName}`
)
consola.success(`✓ getRPCEnvVarName returned: ${envVarName}`)
consola.info('4. Cleanup')
await collection.deleteOne({ chainName: testChainName })
consola.success(`✓ Cleaned up test data`)
} finally {
await client.close()
}
}
async function testSafeMongoCollection() {
consola.info('\nTesting getSafeMongoCollection helper...')
consola.info('1. Testing getSafeMongoCollection')
const { client, pendingTransactions } = await getSafeMongoCollection()
try {
const collectionName = pendingTransactions.collectionName
if (collectionName !== 'pendingTransactions')
throw new Error(
`Expected collection name 'pendingTransactions', got '${collectionName}'`
)
consola.success(`✓ getSafeMongoCollection returned correct collection`)
consola.info('2. Verifying database connection')
const dbName = pendingTransactions.dbName
if (dbName !== 'sc_private')
throw new Error(`Expected database name 'sc_private', got '${dbName}'`)
consola.success(`✓ Connected to correct database: ${dbName}`)
} finally {
await client.close()
}
}
async function runTests() {
consola.start('Starting MongoDB Integration Tests\n')
const MONGODB_URI = process.env.MONGODB_URI
if (!MONGODB_URI) {
consola.error('MONGODB_URI is not defined in the environment')
consola.info('Please set MONGODB_URI in your .env file')
process.exit(1)
}
consola.info(`Connecting to MongoDB...`)
const client = new MongoClient(MONGODB_URI)
try {
await client.connect()
consola.success('✓ Connected to MongoDB\n')
await testRpcEndpoints(client)
await testPendingTransactions(client)
await testFetchRpcsHelper()
await testSafeMongoCollection()
consola.success('\n✅ All tests passed!')
} catch (error) {
consola.error('\n❌ Test failed:', error)
process.exit(1)
} finally {
await client.close()
consola.info('\nClosed MongoDB connection')
}
}
runTests()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment