import * as NodeBuffer from 'node:buffer' import { AbiEvent } from 'ox' import * as FundingDeposits from '../../db/tables/fundingDeposits.js' import * as TestApp from '../../../test/App.js' import * as TestFunding from '../../../test/Funding.js' import * as TestRelay from '../../../test/Relay.js' import * as DepositAddress from './DepositAddress.js' import * as Reconciliation from './Reconciliation.js' import * as SourceObservation from './SourceObservation.js' import * as Relay from './providers/relay.js' const transferEvent = AbiEvent.from( 'event Transfer(address indexed from, address indexed to, uint256 value)', ) describe('scan', () => { test('finds confirmed transfers into active routes', async () => { const route = TestFunding.transferSnapshot() const address = `0x${'44'.repeat(20)}` const sender = `0x${'55'.repeat(20)}` const transactionHash = `0x${'aa'.repeat(32)}` const requests: unknown[] = [] const server = await TestRelay.createServer(async (request, response) => { const chunks: Uint8Array[] = [] for await (const chunk of request) chunks.push(chunk) const body = JSON.parse(NodeBuffer.Buffer.concat(chunks).toString()) as { id: number method: string } requests.push(body) const result = body.method === 'eth_blockNumber' ? '0x10' : [ { address: route.sourceToken.address, blockHash: `0x${'bb'.repeat(32)}`, blockNumber: '0x10', data: `0x${1_000_000n.toString(16).padStart(64, '0')}`, logIndex: '0x2', removed: false, topics: [ AbiEvent.getSelector(transferEvent), topicAddress(sender), topicAddress(address), ], transactionHash, transactionIndex: '0x0', }, ] response.writeHead(200, { 'content-type': 'application/json' }) response.end(JSON.stringify({ id: body.id, jsonrpc: '2.0', result })) }) try { const result = await SourceObservation.scan({ chainId: route.sourceChain.id, routes: [{ address, id: 'fda_source_observation' }], rpcUrls: [server.url], tokenAddress: route.sourceToken.address, }) expect({ requests, result }).toMatchInlineSnapshot(` { "requests": [ { "id": 0, "jsonrpc": "2.0", "method": "eth_blockNumber", }, { "id": 1, "jsonrpc": "2.0", "method": "eth_getLogs", "params": [ { "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "fromBlock": "0x1", "toBlock": "0x10", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", null, [ "0x0000000000000000000000004444444444444444444444444444444444444444", ], ], }, ], }, ], "result": { "cursor": 16n, "head": 16n, "observations": [ { "addressId": "fda_source_observation", "amount": "1000000", "blockNumber": 16n, "chainId": "eip155:8453", "sender": "0x5555555555555555555555555555555555555555", "tokenAddress": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "transferIndex": 2, }, ], }, } `) } finally { await server.closeAsync() } }) }) describe('observe', () => { test('creates one chain-detected deposit and attaches the Relay request later', async () => { const database = TestApp.databaseFactory() const route = TestFunding.transferSnapshot() const providerAddress = `0x${'44'.repeat(20)}` const sender = `0x${'55'.repeat(20)}` const sourceTransactionHash = `0x${'aa'.repeat(32)}` const address = await DepositAddress.create(database(), { apiKeyId: 'key_source_observation', deliveryStrategy: 'provider', environment: 'production', id: 'fda_source_observation', now: new Date('2026-01-01T00:00:00.000Z'), orgId: 'org_source_observation', providerOutputToken: route.destinationToken, snapshot: { address: providerAddress, destinationChain: route.destinationChain, destinationToken: route.destinationToken, provider: route.provider, recipient: route.recipient, refundAddress: `0x${'66'.repeat(20)}`, sourceChain: route.sourceChain, sourceToken: route.sourceToken, subsidize: false, }, }) const input = { addressId: address.id, amount: '1000000', chainId: route.sourceChain.id, now: new Date('2026-01-01T00:00:01.000Z'), recipient: providerAddress, sender, tokenAddress: route.sourceToken.address, transactionHash: sourceTransactionHash, transferIndex: 2, } const [first, second] = await Promise.all([ SourceObservation.observe(database(), input), SourceObservation.observe(database(), input), ]) const routes = await SourceObservation.listRoutes(database(), { providerId: 'relay', sourceChainId: route.sourceChain.id, sourceTokenKey: route.sourceToken.tokenKey, }) const server = await TestRelay.createServer((request, response) => { request.resume() response.writeHead(200, { 'content-type': 'application/json' }) response.end(JSON.stringify({ requests: [] })) }) const dispatches: Parameters[] = [] try { const tracker = Reconciliation.createTracker({ db: database, dispatch: async (...parameters) => { dispatches.push(parameters) }, providers: [Relay.relay({ apiKey: 'relay-api-key', baseUrl: server.url })], verifyTransfers: async () => [], }) const pending = await tracker.reconcile({ addressId: address.id, trigger: 'chain', type: 'funding:deposit-address:reconcile', }) const reconciled = await Reconciliation.reconcileRequest(database(), { address, request: { createdAt: '2026-01-01T00:00:02.000Z', destinationTransactionHashes: [], id: 'relay-source-request', refundTransactionHashes: [], sourceTransactionHashes: [sourceTransactionHash], status: 'pending', updatedAt: '2026-01-01T00:00:03.000Z', }, trigger: 'chain', verifyTransfers: async () => [ { amount: '1000000', sender, transactionHash: sourceTransactionHash, transferIndex: 2, }, ], }) const [record] = await FundingDeposits.listBySourceTransaction(database(), { depositAddressId: address.id, sourceTransactionHash, }) expect({ dispatches, outcomes: [first.type, second.type].toSorted(), pending, reconciled, record: record ? { detectionTrigger: record.detectionTrigger, providerRequestId: record.providerRequestId, providerRequestIds: record.providerRequestIds, providerTransferIndex: record.providerTransferIndex, sourceAmount: record.snapshot.sourceAmount, sourceTransferIndex: record.sourceTransferIndex, status: record.status, } : undefined, routes, sameDeposit: (() => { if (first.type === 'ignored' || second.type === 'ignored') return false return first.record.id === second.record.id })(), }).toMatchInlineSnapshot( { dispatches: [[{ addressId: expect.any(String) }, { delaySeconds: 1 }]], }, ` { "dispatches": [ [ { "addressId": Any, "followUp": { "attempt": 0, "kind": "provider", }, "trigger": "chain", "type": "funding:deposit-address:reconcile", }, { "delaySeconds": 1, }, ], ], "outcomes": [ "created", "existing", ], "pending": { "created": 0, "type": "completed", "updated": 0, }, "reconciled": { "created": 0, "terminal": false, "updated": 1, }, "record": { "detectionTrigger": "chain", "providerRequestId": "relay-source-request", "providerRequestIds": [ "relay-source-request", ], "providerTransferIndex": 0, "sourceAmount": { "baseUnits": "1000000", "currency": "USD", "decimals": 6, "formatted": "1", }, "sourceTransferIndex": 2, "status": "bridging", }, "routes": [ { "address": "0x4444444444444444444444444444444444444444", "id": "fda_source_observation", }, ], "sameDeposit": true, } `, ) } finally { await server.closeAsync() } }) }) function topicAddress(address: string) { return `0x${address.slice(2).toLowerCase().padStart(64, '0')}` }