import { Hash } from 'ox' import { TxEnvelopeTempo } from 'ox/tempo' import type * as Db from '../../db/Db.js' import * as Organizations from '../../db/tables/organizations.js' import * as Projects from '../../db/tables/projects.js' import * as SponsoredTransactions from '../../db/tables/sponsoredTransactions.js' import * as Deposit from '../../internal/routes/Deposit.js' import * as DepositAddress from '../../internal/routes/DepositAddress.js' import * as Transfer from '../../internal/routes/Transfer.js' import * as TestAdmin from '../../../test/Admin.js' import * as TestApp from '../../../test/App.js' import * as TestRoutes from '../../../test/Routes.js' import * as TestTempo from '../../../test/Tempo.js' import * as AdminSubsidies from './subsidies.js' describe('GET /subsidies/transactions', () => { test('lists managed fee-payer transactions with attribution and amounts', async () => { const { client, db } = TestAdmin.setup() const { organization, project } = await seedAttribution(db) const feePayer = TestTempo.accounts[0] const sender = TestTempo.accounts[1] const serialized = await sender.signTransaction({ calls: [{ to: `0x${'30'.repeat(20)}`, value: 0n }], chainId: 4217, feePayer, feeToken: `0x${'20'.repeat(20)}`, gas: 50_000n, maxFeePerGas: 1n, maxPriorityFeePerGas: 0n, nonce: 0, nonceKey: 0, }) const envelope = TxEnvelopeTempo.deserialize(serialized as TxEnvelopeTempo.Serialized) if (!envelope.from) throw new Error('Expected a recoverable sender.') const transaction = await SponsoredTransactions.upsert(db, { apiKeyId: 'key_admin_subsidies', billable: true, chainId: 4217, currency: 'usd', environment: 'production', feeMax: '50000', feeToken: `0x${'20'.repeat(20)}`, orgId: organization.id, projectId: project.id, signPayload: TxEnvelopeTempo.getFeePayerSignPayload(envelope, { sender: envelope.from }), transaction: serialized, transactionHash: Hash.keccak256(serialized), }) await SponsoredTransactions.finalize(db, transaction.id, { feeAmount: '12345', finalizedAt: '2026-09-03T00:01:00.000Z', }) const response = await client.subsidies.transactions.$get({ query: {} }) const body = await TestApp.json(response, AdminSubsidies.schema.listTransactions.Response) expect(response.status).toBe(200) expect(body.data).toEqual([ expect.objectContaining({ feeAmount: { baseUnits: '12345', currency: 'USD', decimals: 6, formatted: '0.012345' }, // prettier-ignore feeMaximum: { baseUnits: '50000', currency: 'USD', decimals: 6, formatted: '0.05' }, // prettier-ignore id: transaction.id, organization: { id: organization.id, name: organization.name }, project: { id: project.id, name: project.name }, status: 'finalized', subsidizerAccount: feePayer.address.toLowerCase(), }), ]) }) }) describe('GET /subsidies/routes', () => { test('lists inbound deposits and outbound transfers with recorded subsidies', async () => { const { client, db } = TestAdmin.setup() const { organization, project } = await seedAttribution(db) const subsidizer = TestTempo.accounts[0] const settlementTransaction = await subsidizer.signTransaction({ calls: [{ to: `0x${'40'.repeat(20)}`, value: 0n }], chainId: 4217, feeToken: `0x${'20'.repeat(20)}`, gas: 50_000n, maxFeePerGas: 1n, maxPriorityFeePerGas: 0n, nonce: 1, nonceKey: 0, }) const settlementTransactionHash = Hash.keccak256(settlementTransaction) const address = await DepositAddress.create(db, { deliveryStrategy: 'tempo', environment: 'production', now: new Date('2026-09-03T00:00:00.000Z'), orgId: organization.id, projectId: project.id, providerOutputToken: TestRoutes.providerOutputToken(), providerRequestIds: ['provider_address_request'], snapshot: TestRoutes.depositAddressSnapshot({ subsidize: true }), }) await Deposit.create(db, { now: new Date('2026-09-03T00:01:00.000Z'), providerRequestId: 'provider_plain', snapshot: TestRoutes.depositSnapshot(address.id), sourceTransactionHash: '11'.repeat(32), }) const deposit = await Deposit.create(db, { now: new Date('2026-09-03T00:02:00.000Z'), providerRequestId: 'provider_subsidized', providerSubsidy: { amount: { baseUnits: '23838', currency: 'USD', decimals: 6, formatted: '0.023838' }, // prettier-ignore provider: 'relay', token: address.snapshot.sourceToken, }, providerTransactionHashes: [`0x${'44'.repeat(32)}`], settlementTransaction, settlementTransactionHash, snapshot: TestRoutes.depositSnapshot(address.id), sourceTransactionHash: '22'.repeat(32), subsidyAmount: { baseUnits: '0', currency: 'USD', decimals: 6, formatted: '0', }, }) const route = TestRoutes.transferSnapshot() const transfer = await Transfer.create(db, { apiKeyId: 'key_admin_subsidies', environment: 'production', orgId: organization.id, projectId: project.id, snapshot: TestRoutes.transferSnapshot({ destinationChain: route.sourceChain, destinationToken: route.sourceToken, sourceChain: route.destinationChain, sourceToken: route.destinationToken, }), }) const subsidyTransactionHash = `0x${'55'.repeat(32)}` const subsidized = await Transfer.transition(db, { expectedVersion: transfer.version, id: transfer.id, status: 'processing', subsidyAccount: subsidizer.address, subsidyAmount: { baseUnits: '12000', currency: 'USD', decimals: 6, formatted: '0.012', }, subsidyChainId: route.sourceChain.id, subsidyTransactionHash, }) if (subsidized.type !== 'applied') throw new Error('Expected outbound subsidy.') const additionalTransfers = [] for (let index = 0; index < 4; index++) { const record = await Transfer.create(db, { apiKeyId: 'key_admin_subsidies', environment: 'production', orgId: organization.id, projectId: project.id, snapshot: TestRoutes.transferSnapshot(), }) const result = await Transfer.transition(db, { expectedVersion: record.version, id: record.id, subsidyAmount: { baseUnits: String(index + 1), currency: 'USD', decimals: 6, formatted: `0.00000${index + 1}`, }, }) if (result.type !== 'applied') throw new Error('Expected paginated subsidy.') additionalTransfers.push(record) } await Transfer.create(db, { apiKeyId: 'key_admin_subsidies', environment: 'production', orgId: organization.id, projectId: project.id, snapshot: TestRoutes.transferSnapshot(), }) const response = await client.subsidies.routes.$get({ query: {} }) const body = await TestApp.json(response, AdminSubsidies.schema.listRoutes.Response) expect(response.status).toBe(200) expect(body.data).toEqual( expect.arrayContaining([ expect.objectContaining({ direction: 'inbound', id: deposit.id, organization: { id: organization.id, name: organization.name }, project: { id: project.id, name: project.name }, subsidies: [ { amount: { baseUnits: '23838', currency: 'USD', decimals: 6, formatted: '0.023838' }, // prettier-ignore provider: 'relay', token: address.snapshot.sourceToken, }, ], subsidizerAccount: subsidizer.address.toLowerCase(), subsidyTransaction: { chainId: address.snapshot.destinationChain.id, transactionRef: settlementTransactionHash, }, }), expect.objectContaining({ direction: 'outbound', id: transfer.id, organization: { id: organization.id, name: organization.name }, project: { id: project.id, name: project.name }, subsidies: [ { amount: { baseUnits: '12000', currency: 'USD', decimals: 6, formatted: '0.012' }, // prettier-ignore provider: 'tempo', token: route.sourceToken, }, ], subsidizerAccount: subsidizer.address.toLowerCase(), subsidyTransaction: { chainId: route.sourceChain.id, transactionRef: subsidyTransactionHash, }, }), ]), ) expect(body.data).toHaveLength(6) const firstResponse = await client.subsidies.routes.$get({ query: { limit: '5' } }) const first = await TestApp.json(firstResponse, AdminSubsidies.schema.listRoutes.Response) expect(first.nextCursor).toEqual(expect.any(String)) const secondResponse = await client.subsidies.routes.$get({ query: { cursor: first.nextCursor!, limit: '5' }, }) const second = await TestApp.json(secondResponse, AdminSubsidies.schema.listRoutes.Response) expect([...first.data, ...second.data].map(({ id }) => id).sort()).toEqual( [deposit.id, transfer.id, ...additionalTransfers.map(({ id }) => id)].sort(), ) }) test('paginates case-sensitive transfer ids in database order', async () => { const { client, db } = TestAdmin.setup() const { organization, project } = await seedAttribution(db) const updatedAt = new Date('2026-09-03T00:03:00.000Z') vi.useFakeTimers({ now: updatedAt, toFake: ['Date'] }) try { const ids = [ `rtr_202609030000000_${'A'.repeat(24)}`, `rtr_202609030000000_${'B'.repeat(24)}`, `rtr_202609030000000_${'C'.repeat(24)}`, `rtr_202609030000000_${'a'.repeat(24)}`, `rtr_202609030000000_${'b'.repeat(24)}`, `rtr_202609030000000_${'c'.repeat(24)}`, ] for (const id of ids) { const record = await Transfer.create(db, { apiKeyId: 'key_admin_subsidies', environment: 'production', id, orgId: organization.id, projectId: project.id, snapshot: TestRoutes.transferSnapshot(), }) const result = await Transfer.transition(db, { expectedVersion: record.version, id: record.id, subsidyAmount: { baseUnits: '1', currency: 'USD', decimals: 6, formatted: '0.000001', }, }) if (result.type !== 'applied') throw new Error('Expected subsidized transfer.') } const firstResponse = await client.subsidies.routes.$get({ query: { limit: '5' } }) const first = await TestApp.json(firstResponse, AdminSubsidies.schema.listRoutes.Response) const secondResponse = await client.subsidies.routes.$get({ query: { cursor: first.nextCursor!, limit: '5' }, }) const second = await TestApp.json(secondResponse, AdminSubsidies.schema.listRoutes.Response) expect([...first.data, ...second.data].map(({ id }) => id)).toEqual([ ids[5], ids[4], ids[3], ids[2], ids[1], ids[0], ]) } finally { vi.useRealTimers() } }) }) async function seedAttribution(db: Db.Db) { const organization = await Organizations.create(db, { id: 'org_admin_subsidies', name: 'Acme', }) const project = await Projects.create(db, { name: 'Checkout', orgId: organization.id }) return { organization, project } }