import { nanoid } from 'nanoid' import { TxEnvelopeTempo } from 'ox/tempo' import type { Client } from 'viem' import * as Runtime from '../../../test/runtime.js' import * as Db from '../../db/Db.js' import * as Organizations from '../../db/tables/organizations.js' import * as SponsoredTransactions from '../../db/tables/sponsoredTransactions.js' import * as Sponsorships from './Sponsorships.js' const create = () => Db.postgres({ connectionString: Runtime.postgresUrl, schema: `t_${nanoid()}` }) /** Baseline insert input; tests override per case. */ const input = { apiKeyId: 'key_1', billable: true, chainId: 42431, environment: 'production', orgId: 'org_1', projectId: 'prj_1', signPayload: `0x${'bb'.repeat(32)}`, transaction: `0x76${'cc'.repeat(16)}`, transactionHash: `0x${'aa'.repeat(32)}`, } satisfies SponsoredTransactions.upsert.Input /** Stubs the receipt lookup: hashes present in `receipts` resolve, others null. */ function client(receipts: Record): Client { return { request: async ({ params }: { params: readonly [string] }) => receipts[params[0]] ?? null, } as never } describe('finalize', () => { test('behavior: finalizes mined rows with gasUsed × effectiveGasPrice', async () => { const db = create() await db.migrate() const record = await SponsoredTransactions.upsert(db, input) const result = await Sponsorships.finalize(db, { getClient: () => client({ [input.transactionHash]: { effectiveGasPrice: '0x3', gasUsed: '0x5208' } }), }) expect(result).toMatchInlineSnapshot(` { "errors": 0, "failed": 0, "finalized": 1, "pending": 0, } `) const finalized = await SponsoredTransactions.get(db, record.id) expect(finalized?.status).toMatchInlineSnapshot(`"finalized"`) // 21000 gas × 3 = 63000 base units. expect(finalized?.feeAmount).toMatchInlineSnapshot(`"1"`) expect(finalized?.finalizedAt).not.toBeNull() await db.close() }) test('behavior: leaves young unmined rows pending', async () => { const db = create() await db.migrate() const record = await SponsoredTransactions.upsert(db, input) const result = await Sponsorships.finalize(db, { getClient: () => client({}) }) expect(result).toMatchInlineSnapshot(` { "errors": 0, "failed": 0, "finalized": 0, "pending": 1, } `) expect((await SponsoredTransactions.get(db, record.id))?.status).toMatchInlineSnapshot( `"pending"`, ) await db.close() }) test('behavior: hash-less fill intents settle by TTL without a receipt lookup', async () => { const db = create() await db.migrate() const { transactionHash: _, ...intent } = input const record = await SponsoredTransactions.upsert(db, intent) // Young intent: left pending; the stub client would throw if queried. const young = await Sponsorships.finalize(db, { getClient: () => { throw new Error('unexpected receipt lookup for a hash-less intent') }, }) expect(young).toMatchInlineSnapshot(` { "errors": 0, "failed": 0, "finalized": 0, "pending": 1, } `) // Past the TTL: fails with no fee. const settled = await Sponsorships.finalize(db, { getClient: () => { throw new Error('unexpected receipt lookup for a hash-less intent') }, now: () => new Date(Date.now() + 2 * 3_600_000), }) expect(settled).toMatchInlineSnapshot(` { "errors": 0, "failed": 1, "finalized": 0, "pending": 0, } `) expect((await SponsoredTransactions.get(db, record.id))?.status).toMatchInlineSnapshot( `"failed"`, ) await db.close() }) test('behavior: fails unmined rows past the pending TTL', async () => { const db = create() await db.migrate() const record = await SponsoredTransactions.upsert(db, input) const result = await Sponsorships.finalize(db, { getClient: () => client({}), now: () => new Date(Date.now() + 2 * 3_600_000), }) expect(result).toMatchInlineSnapshot(` { "errors": 0, "failed": 1, "finalized": 0, "pending": 0, } `) const failed = await SponsoredTransactions.get(db, record.id) expect(failed?.status).toMatchInlineSnapshot(`"failed"`) expect(failed?.feeAmount).toBeNull() await db.close() }) test('behavior: an erroring receipt lookup leaves the row pending, even past the TTL', async () => { const db = create() await db.migrate() const record = await SponsoredTransactions.upsert(db, input) const result = await Sponsorships.finalize(db, { getClient: () => ({ request: async () => { throw new Error('rpc outage') }, }) as never, now: () => new Date(Date.now() + 2 * 3_600_000), }) expect(result).toMatchInlineSnapshot(` { "errors": 1, "failed": 0, "finalized": 0, "pending": 1, } `) expect((await SponsoredTransactions.get(db, record.id))?.status).toMatchInlineSnapshot( `"pending"`, ) await db.close() }) test('behavior: an erroring receipt lookup fails past the error TTL', async () => { const db = create() await db.migrate() const record = await SponsoredTransactions.upsert(db, input) const result = await Sponsorships.finalize(db, { getClient: () => ({ request: async () => { throw new Error('rpc outage') }, }) as never, now: () => new Date(Date.now() + 25 * 3_600_000), }) expect(result).toMatchInlineSnapshot(` { "errors": 1, "failed": 1, "finalized": 0, "pending": 0, } `) expect((await SponsoredTransactions.get(db, record.id))?.status).toMatchInlineSnapshot( `"failed"`, ) await db.close() }) test('behavior: batchSize caps rows processed per pass', async () => { const db = create() await db.migrate() await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b1'.repeat(32)}`, transactionHash: `0x${'a1'.repeat(32)}` }) // prettier-ignore await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b2'.repeat(32)}`, transactionHash: `0x${'a2'.repeat(32)}` }) // prettier-ignore // Both hashes are mined so the outcome is order-independent. const receipts = { [`0x${'a1'.repeat(32)}`]: { effectiveGasPrice: '0x1', gasUsed: '0x1' }, [`0x${'a2'.repeat(32)}`]: { effectiveGasPrice: '0x1', gasUsed: '0x1' }, } const result = await Sponsorships.finalize(db, { batchSize: 1, getClient: () => client(receipts), }) expect(result).toMatchInlineSnapshot(` { "errors": 0, "failed": 0, "finalized": 1, "pending": 0, } `) expect(await SponsoredTransactions.listPending(db)).toHaveLength(1) await db.close() }) }) describe('reconcile', () => { const sender = '0x407368320192a21238825437c02c2e2a34ffc38d' const minedHash = `0x${'dd'.repeat(32)}` /** The mined sponsored envelope, in ox form. */ const mined = TxEnvelopeTempo.from({ calls: [{ data: '0x', to: '0x20c0000000000000000000000000000000000001', value: 0n }], chainId: 42431, gas: 100_000n, maxFeePerGas: 1_000_000n, maxPriorityFeePerGas: 0n, nonce: 0n, nonceKey: 0n, }) /** The intent's identity, computed exactly as the recording sites do. */ const signPayload = TxEnvelopeTempo.getFeePayerSignPayload(mined, { sender }) /** Fakes the node: `eth_getRawTransactionByHash` serves the mined bytes. */ const rpc = { request: async () => TxEnvelopeTempo.serialize(mined), } as never as Client /** Fakes the indexer: the fee payer's recent transactions. */ const tidx = (rows: readonly { from: string; hash: string }[]) => ({ fetch: async () => ({ rows }) }) as never test('behavior: matches intents by sign payload and fills the hash', async () => { const db = create() await db.migrate() const { transactionHash: _, ...rest } = input const intent = await SponsoredTransactions.upsert(db, { ...rest, signPayload }) const result = await Sponsorships.reconcile(db, { feePayer: '0xFee0000000000000000000000000000000000000', getClient: () => rpc, getTidx: () => tidx([{ from: sender, hash: minedHash }]), }) expect(result).toMatchInlineSnapshot(` { "errors": 0, "matched": 1, "scanned": 1, } `) const matched = await SponsoredTransactions.get(db, intent.id) expect(matched?.transactionHash).toBe(minedHash) expect(matched?.status).toMatchInlineSnapshot(`"pending"`) await db.close() }) test('behavior: recovers recently failed intents by sign payload', async () => { const db = create() await db.migrate() await Organizations.create(db, { id: 'org_1', name: 'One' }) const { transactionHash: _, ...rest } = input const intent = await SponsoredTransactions.upsert(db, { ...rest, signPayload }) await SponsoredTransactions.fail(db, intent.id, '2026-01-01T00:00:00.000Z') vi.useFakeTimers({ now: new Date('2026-01-01T00:01:00.000Z') }) const result = await (async () => { try { return await Sponsorships.reconcile(db, { feePayer: '0xFee0000000000000000000000000000000000000', getClient: () => rpc, getTidx: () => tidx([{ from: sender, hash: minedHash }]), }) } finally { vi.useRealTimers() } })() expect(result).toMatchInlineSnapshot(` { "errors": 0, "matched": 1, "scanned": 1, } `) const matched = await SponsoredTransactions.get(db, intent.id) expect(matched?.transactionHash).toBe(minedHash) expect(matched?.status).toMatchInlineSnapshot(`"pending"`) expect(matched?.finalizedAt).toBeNull() await db.close() }) test('behavior: spend-limit refusals are not operational errors', async () => { const db = create() await db.migrate() await Organizations.create(db, { id: 'org_1', name: 'One' }) const { transactionHash: _, ...rest } = input const intent = await SponsoredTransactions.upsert(db, { ...rest, signPayload }) await SponsoredTransactions.fail(db, intent.id, '2026-01-01T00:00:00.000Z') vi.useFakeTimers({ now: new Date('2026-01-01T00:01:00.000Z') }) const result = await (async () => { try { return await Sponsorships.reconcile(db, { feePayer: '0xFee0000000000000000000000000000000000000', getClient: () => rpc, getTidx: () => tidx([{ from: sender, hash: minedHash }]), limitFor: async () => ({ chainIds: [42431], max: -1n, since: '2025-01-01T00:00:00.000Z', }), }) } finally { vi.useRealTimers() } })() expect(result).toMatchInlineSnapshot(` { "errors": 0, "matched": 0, "scanned": 1, } `) expect((await SponsoredTransactions.get(db, intent.id))?.transactionHash).toBeNull() await db.close() }) test('behavior: unmatched candidates leave intents pending', async () => { const db = create() await db.migrate() const { transactionHash: _, ...rest } = input const intent = await SponsoredTransactions.upsert(db, { ...rest, signPayload: `0x${'ee'.repeat(32)}` }) // prettier-ignore const result = await Sponsorships.reconcile(db, { feePayer: '0xFee0000000000000000000000000000000000000', getClient: () => rpc, getTidx: () => tidx([{ from: sender, hash: minedHash }]), }) expect(result).toMatchInlineSnapshot(` { "errors": 0, "matched": 0, "scanned": 1, } `) expect((await SponsoredTransactions.get(db, intent.id))?.transactionHash).toBeNull() await db.close() }) test('behavior: queries on-chain candidates oldest first', async () => { const db = create() await db.migrate() const { transactionHash: _, ...rest } = input await SponsoredTransactions.upsert(db, { ...rest, signPayload }) let query: string | undefined await Sponsorships.reconcile(db, { candidateCap: 17, feePayer: '0xFee0000000000000000000000000000000000000', getClient: () => rpc, getTidx: () => ({ fetch: async (options: { query: string }) => { query = options.query return { rows: [] } }, }) as never, }) expect( query?.replace(/block_timestamp >= '[^']+'/, "block_timestamp >= ''"), ).toMatchInlineSnapshot( `"SELECT hash, "from" FROM txs WHERE fee_payer = '0xfee0000000000000000000000000000000000000' AND block_timestamp >= '' ORDER BY block_timestamp ASC LIMIT 17"`, ) await db.close() }) test('behavior: an indexer error leaves intents for the next pass', async () => { const db = create() await db.migrate() const { transactionHash: _, ...rest } = input await SponsoredTransactions.upsert(db, { ...rest, signPayload }) const result = await Sponsorships.reconcile(db, { feePayer: '0xFee0000000000000000000000000000000000000', getClient: () => rpc, getTidx: () => ({ fetch: async () => { throw new Error('indexer outage') }, }) as never, }) expect(result).toMatchInlineSnapshot(` { "errors": 1, "matched": 0, "scanned": 0, } `) expect(await SponsoredTransactions.listIntents(db)).toHaveLength(1) await db.close() }) })