import { sql } from 'kysely' import * as DepositAddress from '../../internal/funding/DepositAddress.js' import * as TestApp from '../../../test/App.js' import * as TestFunding from '../../../test/Funding.js' import * as Db from '../Db.js' import * as FundingDepositAddresses from './fundingDepositAddresses.js' const db = TestApp.database() const owner = { environment: 'production', orgId: 'org_deposit_addresses' } as const let counter = 0 function seed(input: Partial = {}) { const index = counter++ const now = new Date(Date.UTC(2026, 0, 1, 0, 0, index)) const { snapshot, ...rest } = input return DepositAddress.create(db, { apiKeyId: 'key_test', deliveryStrategy: 'provider', environment: owner.environment, id: DepositAddress.generateId(now), now, orgId: owner.orgId, providerOutputToken: TestFunding.providerOutputToken(), snapshot: TestFunding.depositAddressSnapshot({ provider: { id: `relay_${index}`, name: 'Relay' }, recipient: `0x${index.toString(16).padStart(40, '0')}`, ...snapshot, }), ...rest, }) } describe('getOwned', () => { test('returns owned addresses and hides foreign ownership', async () => { const record = await seed() expect((await FundingDepositAddresses.getOwned(db, owner, record.id))?.id).toBe(record.id) expect( await FundingDepositAddresses.getOwned(db, { ...owner, orgId: 'org_other' }, record.id), ).toBeUndefined() expect( await FundingDepositAddresses.getOwned(db, { ...owner, projectId: 'prj_other' }, record.id), ).toBeUndefined() }) }) describe('subsidize migration', () => { test('backfills legacy snapshots and remains safe to rerun', async () => { const record = await seed({ snapshot: TestFunding.depositAddressSnapshot({ subsidize: true }), }) await sql`UPDATE funding_deposit_addresses SET snapshot = snapshot - 'subsidize' WHERE id = ${record.id}`.execute( db.kysely, ) const migration = Db.migrations.find( (candidate) => candidate.name === '0106_funding_deposit_addresses_snapshot_subsidize', ) if (!migration) throw new Error('Expected the snapshot subsidy migration.') const legacy = await FundingDepositAddresses.get(db, record.id) if (!legacy) throw new Error('Expected a legacy funding deposit address.') for (let run = 0; run < 2; run++) await migration.up(db.kysely).execute() const migrated = await FundingDepositAddresses.get(db, record.id) if (!migrated) throw new Error('Expected a migrated funding deposit address.') expect({ legacyPublic: DepositAddress.toPublic(legacy), migratedSnapshot: migrated.snapshot, }).toMatchInlineSnapshot( { legacyPublic: { createdAt: expect.any(String), id: expect.any(String), updatedAt: expect.any(String), }, }, ` { "legacyPublic": { "address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "createdAt": Any, "destinationChain": { "addressFormat": "hex", "id": "eip155:4217", "kind": "evm", "name": "Tempo", }, "destinationToken": { "address": "0x20c00000000000000000000014f22ca97301eb73", "currency": "USD", "decimals": 6, "name": "USDT0", "standard": "TIP-20", "symbol": "USDT0", "tokenKey": "eip155:4217/erc20:0x20c00000000000000000000014f22ca97301eb73", "verified": true, }, "id": Any, "provider": { "id": "relay", "name": "Relay", }, "recipient": "0x1111111111111111111111111111111111111111", "refundAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "sourceChain": { "addressFormat": "base58check", "id": "tron:0x2b6653dc", "kind": "tron", "name": "Tron", }, "sourceToken": { "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "currency": "USD", "decimals": 6, "name": "Tether USD", "standard": "TRC-20", "symbol": "USDT", "tokenKey": "tron:0x2b6653dc/trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "verified": true, }, "status": "active", "subsidize": true, "updatedAt": Any, }, "migratedSnapshot": { "address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "destinationChain": { "addressFormat": "hex", "id": "eip155:4217", "kind": "evm", "name": "Tempo", }, "destinationToken": { "address": "0x20c00000000000000000000014f22ca97301eb73", "currency": "USD", "decimals": 6, "name": "USDT0", "standard": "TIP-20", "symbol": "USDT0", "tokenKey": "eip155:4217/erc20:0x20c00000000000000000000014f22ca97301eb73", "verified": true, }, "provider": { "id": "relay", "name": "Relay", }, "recipient": "0x1111111111111111111111111111111111111111", "refundAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "sourceChain": { "addressFormat": "base58check", "id": "tron:0x2b6653dc", "kind": "tron", "name": "Tron", }, "sourceToken": { "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "currency": "USD", "decimals": 6, "name": "Tether USD", "standard": "TRC-20", "symbol": "USDT", "tokenKey": "tron:0x2b6653dc/trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "verified": true, }, "subsidize": true, }, } `, ) }) }) describe('getMatching', () => { test('matches the owner, route, recipient, and refund address', async () => { const record = await seed() const match: FundingDepositAddresses.Match = { destinationTokenKey: record.destinationTokenKey, environment: record.environment, orgId: record.orgId, recipient: record.recipient, refundAddress: record.refundAddress, sourceChainId: record.sourceChainId, sourceTokenKey: record.sourceTokenKey, subsidize: record.subsidize, } expect((await FundingDepositAddresses.getMatching(db, match))?.id).toBe(record.id) expect( await FundingDepositAddresses.getMatching(db, { ...match, refundAddress: 'TWrong' }), ).toBeUndefined() }) }) describe('claimDue', () => { test('claims due addresses once and reclaims an expired lease with a new fence', async () => { const record = await seed() const now = '2027-01-01T00:00:00.000Z' const first = await FundingDepositAddresses.claimDue(db, { leaseUntil: '2027-01-01T00:01:00.000Z', limit: 10, now, providerId: record.providerId, }) const blocked = await FundingDepositAddresses.claimDue(db, { leaseUntil: '2027-01-01T00:02:00.000Z', limit: 10, now, providerId: record.providerId, }) const reclaimed = await FundingDepositAddresses.claimDue(db, { leaseUntil: '2027-01-01T00:03:00.000Z', limit: 10, now: '2027-01-01T00:01:00.000Z', providerId: record.providerId, }) expect({ blocked, first, reclaimed }).toMatchInlineSnapshot( { first: [ { id: expect.any(String), providerOutputToken: expect.any(Object), snapshot: expect.any(Object), }, ], reclaimed: [ { id: expect.any(String), providerOutputToken: expect.any(Object), snapshot: expect.any(Object), }, ], }, ` { "blocked": [], "first": [ { "address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "apiKeyId": "key_test", "createdAt": "2026-01-01T00:00:03.000Z", "deliveryStrategy": "provider", "destinationTokenKey": "eip155:4217/erc20:0x20c00000000000000000000014f22ca97301eb73", "environment": "production", "id": Any, "lastPolledAt": null, "nextPollAt": "2026-01-01T00:00:03.000Z", "orgId": "org_deposit_addresses", "pollFailureCount": 0, "pollLeaseUntil": "2027-01-01T00:01:00.000Z", "pollLeaseVersion": 1, "projectId": null, "providerId": "relay_3", "providerOutputToken": Any, "providerRequestIds": [], "providerState": null, "recipient": "0x0000000000000000000000000000000000000003", "refundAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "snapshot": Any, "sourceChainId": "tron:0x2b6653dc", "sourceTokenKey": "tron:0x2b6653dc/trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "status": "active", "subsidize": false, "updatedAt": "2026-01-01T00:00:03.000Z", "version": 1, }, ], "reclaimed": [ { "address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "apiKeyId": "key_test", "createdAt": "2026-01-01T00:00:03.000Z", "deliveryStrategy": "provider", "destinationTokenKey": "eip155:4217/erc20:0x20c00000000000000000000014f22ca97301eb73", "environment": "production", "id": Any, "lastPolledAt": null, "nextPollAt": "2026-01-01T00:00:03.000Z", "orgId": "org_deposit_addresses", "pollFailureCount": 0, "pollLeaseUntil": "2027-01-01T00:03:00.000Z", "pollLeaseVersion": 2, "projectId": null, "providerId": "relay_3", "providerOutputToken": Any, "providerRequestIds": [], "providerState": null, "recipient": "0x0000000000000000000000000000000000000003", "refundAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "snapshot": Any, "sourceChainId": "tron:0x2b6653dc", "sourceTokenKey": "tron:0x2b6653dc/trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "status": "active", "subsidize": false, "updatedAt": "2026-01-01T00:00:03.000Z", "version": 1, }, ], } `, ) }) }) describe('completePoll', () => { test('persists reconciliation state only for the current lease', async () => { const record = await seed() const [claim] = await FundingDepositAddresses.claimDue(db, { leaseUntil: '2027-01-01T00:01:00.000Z', limit: 1, now: '2027-01-01T00:00:00.000Z', providerId: record.providerId, }) if (!claim) throw new Error('Expected a claimed address.') const completed = await FundingDepositAddresses.completePoll(db, { id: record.id, lastPolledAt: '2027-01-01T00:00:10.000Z', nextPollAt: '2027-01-01T00:01:10.000Z', pollLeaseVersion: claim.pollLeaseVersion, providerRequestIds: ['relay-request', 'relay-child'], providerState: { highWater: '2027-01-01T00:00:05.000Z' }, }) const stale = await FundingDepositAddresses.completePoll(db, { id: record.id, lastPolledAt: '2027-01-01T00:00:20.000Z', nextPollAt: '2027-01-01T00:01:20.000Z', pollLeaseVersion: claim.pollLeaseVersion - 1, providerRequestIds: [], providerState: null, }) expect({ completed, stale }).toMatchInlineSnapshot( { completed: { id: expect.any(String), providerOutputToken: expect.any(Object), snapshot: expect.any(Object), }, }, ` { "completed": { "address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "apiKeyId": "key_test", "createdAt": "2026-01-01T00:00:04.000Z", "deliveryStrategy": "provider", "destinationTokenKey": "eip155:4217/erc20:0x20c00000000000000000000014f22ca97301eb73", "environment": "production", "id": Any, "lastPolledAt": "2027-01-01T00:00:10.000Z", "nextPollAt": "2027-01-01T00:01:10.000Z", "orgId": "org_deposit_addresses", "pollFailureCount": 0, "pollLeaseUntil": null, "pollLeaseVersion": 1, "projectId": null, "providerId": "relay_4", "providerOutputToken": Any, "providerRequestIds": [ "relay-request", "relay-child", ], "providerState": { "highWater": "2027-01-01T00:00:05.000Z", }, "recipient": "0x0000000000000000000000000000000000000004", "refundAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "snapshot": Any, "sourceChainId": "tron:0x2b6653dc", "sourceTokenKey": "tron:0x2b6653dc/trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "status": "active", "subsidize": false, "updatedAt": "2026-01-01T00:00:04.000Z", "version": 1, }, "stale": undefined, } `, ) }) }) describe('failPoll', () => { test('increments failures and releases only the current lease', async () => { const record = await seed() const [claim] = await FundingDepositAddresses.claimDue(db, { leaseUntil: '2027-01-01T00:01:00.000Z', limit: 1, now: '2027-01-01T00:00:00.000Z', providerId: record.providerId, }) if (!claim) throw new Error('Expected a claimed address.') const failed = await FundingDepositAddresses.failPoll(db, { id: record.id, nextPollAt: '2027-01-01T00:00:30.000Z', pollLeaseVersion: claim.pollLeaseVersion, }) const stale = await FundingDepositAddresses.failPoll(db, { id: record.id, nextPollAt: '2027-01-01T00:00:40.000Z', pollLeaseVersion: claim.pollLeaseVersion - 1, }) expect({ failed, stale }).toMatchInlineSnapshot( { failed: { id: expect.any(String), providerOutputToken: expect.any(Object), snapshot: expect.any(Object), }, }, ` { "failed": { "address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "apiKeyId": "key_test", "createdAt": "2026-01-01T00:00:05.000Z", "deliveryStrategy": "provider", "destinationTokenKey": "eip155:4217/erc20:0x20c00000000000000000000014f22ca97301eb73", "environment": "production", "id": Any, "lastPolledAt": null, "nextPollAt": "2027-01-01T00:00:30.000Z", "orgId": "org_deposit_addresses", "pollFailureCount": 1, "pollLeaseUntil": null, "pollLeaseVersion": 1, "projectId": null, "providerId": "relay_5", "providerOutputToken": Any, "providerRequestIds": [], "providerState": null, "recipient": "0x0000000000000000000000000000000000000005", "refundAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8", "snapshot": Any, "sourceChainId": "tron:0x2b6653dc", "sourceTokenKey": "tron:0x2b6653dc/trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "status": "active", "subsidize": false, "updatedAt": "2026-01-01T00:00:05.000Z", "version": 1, }, "stale": undefined, } `, ) }) }) describe('insertOrGet', () => { test('returns the existing address for an identical reusable identity', async () => { const record = await seed() const match: FundingDepositAddresses.Match = { destinationTokenKey: record.destinationTokenKey, environment: record.environment, orgId: record.orgId, recipient: record.recipient, refundAddress: record.refundAddress, sourceChainId: record.sourceChainId, sourceTokenKey: record.sourceTokenKey, subsidize: record.subsidize, } const duplicate = { ...record, id: DepositAddress.generateId(new Date('2027-01-01')) } await expect( FundingDepositAddresses.insertOrGet(db, { match, record: duplicate }), ).resolves.toMatchObject({ id: record.id, }) }) test('rejects a provider address assigned to another reusable identity', async () => { const provider = { id: `relay_collision_${counter}`, name: 'Relay' } const first = await seed({ snapshot: TestFunding.depositAddressSnapshot({ provider, recipient: `0x${'cd'.repeat(20)}`, }), }) const recipient = `0x${'ab'.repeat(20)}` const record: FundingDepositAddresses.Record = { ...first, id: DepositAddress.generateId(new Date('2027-01-01')), orgId: 'org_other', recipient, snapshot: { ...first.snapshot, recipient }, } const match: FundingDepositAddresses.Match = { destinationTokenKey: record.destinationTokenKey, environment: record.environment, orgId: record.orgId, recipient: record.recipient, refundAddress: record.refundAddress, sourceChainId: record.sourceChainId, sourceTokenKey: record.sourceTokenKey, subsidize: record.subsidize, } await expect( FundingDepositAddresses.insertOrGet(db, { match, record }), ).rejects.toThrowErrorMatchingInlineSnapshot(`[FundingDepositAddresses.ConflictError]`) expect((await FundingDepositAddresses.get(db, first.id))?.id).toBe(first.id) }) }) describe('insert', () => { test('prevents one provider address from belonging to two resources', async () => { const provider = { id: `relay_unique_${counter}`, name: 'Relay' } const first = await seed({ snapshot: TestFunding.depositAddressSnapshot({ provider }) }) await expect( seed({ snapshot: TestFunding.depositAddressSnapshot({ provider }), orgId: 'org_other' }), ).rejects.toMatchObject({ code: '23505' }) expect((await FundingDepositAddresses.get(db, first.id))?.id).toBe(first.id) }) }) describe('update', () => { test('applies allowed transitions once against the expected version', async () => { const record = await seed() const applied = await DepositAddress.transition(db, { expectedVersion: 1, id: record.id, status: 'action-required', }) expect(applied.type).toBe('applied') expect( await DepositAddress.transition(db, { expectedVersion: 1, id: record.id, status: 'action-required', }), ).toMatchObject({ type: 'stale' }) }) }) describe('toPublic', () => { test('omits private provider and ownership state', async () => { const record = await seed({ providerRequestIds: ['relay-request'], providerState: { correlation: 'private' }, }) expect(DepositAddress.toPublic(record)).not.toMatchObject({ apiKeyId: expect.anything(), deliveryStrategy: expect.anything(), providerOutputToken: expect.anything(), providerRequestIds: expect.anything(), providerState: expect.anything(), }) }) }) describe('renewPoll', () => { test('extends only the current active lease', async () => { const record = await seed() const [claim] = await FundingDepositAddresses.claimDue(db, { leaseUntil: '2027-01-01T00:01:00.000Z', limit: 1, now: '2027-01-01T00:00:00.000Z', providerId: record.providerId, }) if (!claim) throw new Error('Expected a claimed address.') const renewed = await FundingDepositAddresses.renewPoll(db, { id: claim.id, leaseUntil: '2027-01-01T00:02:00.000Z', pollLeaseVersion: claim.pollLeaseVersion, }) const stale = await FundingDepositAddresses.renewPoll(db, { id: claim.id, leaseUntil: '2027-01-01T00:03:00.000Z', pollLeaseVersion: claim.pollLeaseVersion - 1, }) expect({ renewed, stale }).toMatchInlineSnapshot(` { "renewed": true, "stale": false, } `) }) }) describe('list', () => { test('pages organization addresses and narrows project-attributed owners', async () => { const listOwner = { environment: owner.environment, orgId: 'org_address_list' } as const const first = await seed({ orgId: listOwner.orgId }) const project = await seed({ orgId: listOwner.orgId, projectId: 'prj_address_list' }) const sibling = await seed({ orgId: listOwner.orgId, projectId: 'prj_address_sibling' }) await seed({ orgId: 'org_address_list_foreign' }) await seed({ environment: 'sandbox', orgId: listOwner.orgId }) const page = await FundingDepositAddresses.list(db, { limit: 2, owner: listOwner }) expect(page.map((record) => record.id)).toEqual([sibling.id, project.id]) const rest = await FundingDepositAddresses.list(db, { cursor: { createdAt: project.createdAt, id: project.id }, limit: 2, owner: listOwner, }) expect(rest.map((record) => record.id)).toEqual([first.id]) expect( ( await FundingDepositAddresses.list(db, { limit: 10, owner: { ...listOwner, projectId: 'prj_address_list' }, }) ).map((record) => record.id), ).toEqual([project.id]) }) })