tapimo 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApiKey.d.ts +2 -1
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKeys.d.ts +4 -2
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +26 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +6007 -5003
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +1 -0
- package/dist/App.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -1
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +6 -6
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +91 -84
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +22 -13
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +6 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +4 -2
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +69 -69
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +232 -0
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +4 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +2 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/Zones.d.ts +4266 -82
- package/dist/apps/Zones.d.ts.map +1 -1
- package/dist/apps/Zones.js +27 -8
- package/dist/apps/Zones.js.map +1 -1
- package/dist/apps/data/App.d.ts +3467 -2696
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +2 -0
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +2999 -100
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +340 -2
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +514 -0
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +26 -26
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +7 -3
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +4 -4
- package/dist/apps/data/routes/earn.d.ts +75 -75
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +65 -36
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +124 -120
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +115 -77
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +24 -24
- package/dist/apps/data/routes/indexer.d.ts +2 -1
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +3 -2
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +4 -3
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +15 -14
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +5 -1
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +12 -12
- package/dist/apps/data/routes/tokens.d.ts +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +4 -3
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +25 -7
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +37 -37
- package/dist/apps/data/routes/webhooks.d.ts +71 -1
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +177 -23
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.js +1 -1
- package/dist/apps/data/routes/zones.js.map +1 -1
- package/dist/apps/funding/App.d.ts +322 -89
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +375 -45
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +208 -12
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +32 -32
- package/dist/apps/funding/routes/transfers.js +1 -1
- package/dist/apps/funding/routes/transfers.js.map +1 -1
- package/dist/apps/management/App.d.ts +418 -418
- package/dist/apps/management/routes/api-keys.d.ts +50 -50
- package/dist/apps/management/routes/billing.d.ts +72 -72
- package/dist/apps/management/routes/billing.js +1 -1
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +8 -8
- package/dist/apps/management/routes/faucet.js +2 -2
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +42 -42
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +14 -14
- package/dist/apps/management/routes/projects.d.ts +40 -40
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/webhooks.d.ts +49 -49
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +4 -1
- package/dist/apps/mcp.js.map +1 -1
- package/dist/db/Db.d.ts +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +90 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +19 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +24 -0
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/fundingDepositAddresses.d.ts +20 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -1
- package/dist/db/tables/fundingDepositAddresses.js +17 -0
- package/dist/db/tables/fundingDepositAddresses.js.map +1 -1
- package/dist/db/tables/fundingDeposits.d.ts +41 -0
- package/dist/db/tables/fundingDeposits.d.ts.map +1 -1
- package/dist/db/tables/fundingDeposits.js +69 -0
- package/dist/db/tables/fundingDeposits.js.map +1 -1
- package/dist/db/tables/webhookQueueEvents.d.ts +122 -0
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -0
- package/dist/db/tables/webhookQueueEvents.js +160 -0
- package/dist/db/tables/webhookQueueEvents.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +2 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +10 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/internal/Auth.d.ts +3 -26
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +6 -37
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Credential.d.ts +27 -0
- package/dist/internal/Credential.d.ts.map +1 -0
- package/dist/internal/Credential.js +34 -0
- package/dist/internal/Credential.js.map +1 -0
- package/dist/internal/EarnRates.js +11 -7
- package/dist/internal/EarnRates.js.map +1 -1
- package/dist/internal/Log.d.ts +8 -0
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +4 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts +51 -0
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +54 -2
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +4 -6
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +15 -14
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +2 -1
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +57 -18
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +4 -3
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +2 -2
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Value.d.ts +2 -0
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js +25 -0
- package/dist/internal/Value.js.map +1 -1
- package/dist/internal/Viem.d.ts +4 -3
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +3 -2
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/WebhookTransfer.d.ts +20 -0
- package/dist/internal/WebhookTransfer.d.ts.map +1 -1
- package/dist/internal/WebhookTransfer.js +7 -4
- package/dist/internal/WebhookTransfer.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +141 -0
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +139 -10
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/providers/relay.d.ts +3 -4
- package/dist/internal/funding/providers/relay.d.ts.map +1 -1
- package/dist/internal/funding/providers/relay.js +59 -8
- package/dist/internal/funding/providers/relay.js.map +1 -1
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1 -0
- package/dist/internal/index.js.map +1 -1
- package/package.json +3 -3
- package/src/ApiKeys.test.ts +20 -0
- package/src/ApiKeys.ts +28 -1
- package/src/App.test.ts +40 -8
- package/src/App.ts +1 -0
- package/src/Client.test-d.ts +34 -1
- package/src/Webhooks.ts +20 -18
- package/src/admin/apps/api-keys.test.ts +9 -0
- package/src/admin/apps/api-keys.ts +15 -0
- package/src/admin/ui/src/lib/query-client.ts +3 -2
- package/src/admin/ui/src/routes/api-keys.tsx +31 -9
- package/src/admin/ui.generated.ts +69 -69
- package/src/analytics/Analytics.test.ts +42 -0
- package/src/analytics/Analytics.ts +232 -0
- package/src/analytics/tables/requestEvents.ts +6 -0
- package/src/apps/Zones.test.ts +20 -3
- package/src/apps/Zones.ts +28 -8
- package/src/apps/composition.test.ts +2 -0
- package/src/apps/data/App.test.ts +2 -2
- package/src/apps/data/App.ts +2 -0
- package/src/apps/data/routes/activities.bench.ts +41 -0
- package/src/apps/data/routes/activities.test.ts +103 -2
- package/src/apps/data/routes/activities.ts +401 -2
- package/src/apps/data/routes/balances.bench.ts +21 -0
- package/src/apps/data/routes/balances.ts +7 -3
- package/src/apps/data/routes/blocks.bench.ts +34 -0
- package/src/apps/data/routes/coingecko.bench.ts +53 -0
- package/src/apps/data/routes/earn.bench.ts +71 -0
- package/src/apps/data/routes/earn.ts +66 -36
- package/src/apps/data/routes/exchanges.bench.ts +85 -0
- package/src/apps/data/routes/exchanges.test.ts +8 -3
- package/src/apps/data/routes/exchanges.ts +134 -82
- package/src/apps/data/routes/fee-amm.bench.ts +13 -0
- package/src/apps/data/routes/indexer.bench.ts +8 -0
- package/src/apps/data/routes/indexer.test.ts +2 -1
- package/src/apps/data/routes/indexer.ts +3 -2
- package/src/apps/data/routes/receipts.bench.ts +39 -0
- package/src/apps/data/routes/receipts.ts +16 -14
- package/src/apps/data/routes/rpc.bench.ts +14 -0
- package/src/apps/data/routes/rpc.test.ts +27 -0
- package/src/apps/data/routes/rpc.ts +5 -1
- package/src/apps/data/routes/tokenlist.bench.ts +3 -0
- package/src/apps/data/routes/tokens.bench.ts +76 -0
- package/src/apps/data/routes/tokens.ts +3 -2
- package/src/apps/data/routes/transactions.bench.ts +48 -0
- package/src/apps/data/routes/transfers.bench.ts +28 -0
- package/src/apps/data/routes/transfers.ts +36 -10
- package/src/apps/data/routes/valuation.bench.ts +14 -0
- package/src/apps/data/routes/verified-tokens.bench.ts +8 -0
- package/src/apps/data/routes/webhooks.bench.ts +26 -0
- package/src/apps/data/routes/webhooks.scan.test.ts +326 -0
- package/src/apps/data/routes/webhooks.test.ts +53 -6
- package/src/apps/data/routes/webhooks.ts +252 -24
- package/src/apps/data/routes/zones.bench.ts +32 -0
- package/src/apps/data/routes/zones.test.ts +1 -1
- package/src/apps/data/routes/zones.ts +1 -1
- package/src/apps/funding/routes/chains.test.ts +1 -1
- package/src/apps/funding/routes/deposit-addresses.test.ts +217 -3
- package/src/apps/funding/routes/deposit-addresses.ts +255 -19
- package/src/apps/funding/routes/providers.test.ts +1 -1
- package/src/apps/funding/routes/quotes.test.ts +1 -1
- package/src/apps/funding/routes/transfers.test.ts +20 -8
- package/src/apps/funding/routes/transfers.ts +1 -1
- package/src/apps/management/routes/billing.ts +1 -1
- package/src/apps/management/routes/faucet.ts +2 -2
- package/src/apps/management/routes/me.test.ts +31 -0
- package/src/apps/mcp.ts +4 -1
- package/src/db/Db.ts +117 -0
- package/src/db/Schema.ts +32 -0
- package/src/db/tables/fundingDepositAddresses.test.ts +28 -0
- package/src/db/tables/fundingDepositAddresses.ts +39 -0
- package/src/db/tables/fundingDeposits.test.ts +82 -0
- package/src/db/tables/fundingDeposits.ts +130 -0
- package/src/db/tables/webhookQueueEvents.ts +285 -0
- package/src/db/tables/webhookSubscriptions.ts +15 -0
- package/src/internal/Auth.test.ts +61 -98
- package/src/internal/Auth.ts +9 -63
- package/src/internal/Credential.test.ts +51 -0
- package/src/internal/Credential.ts +58 -0
- package/src/internal/EarnRates.ts +13 -7
- package/src/internal/EarnVaults.test.ts +2 -2
- package/src/internal/Log.test.ts +3 -1
- package/src/internal/Log.ts +14 -0
- package/src/internal/MetricSink.test.ts +108 -2
- package/src/internal/MetricSink.ts +112 -2
- package/src/internal/RateLimit.test.ts +23 -18
- package/src/internal/RateLimit.ts +23 -15
- package/src/internal/Store.test.ts +99 -13
- package/src/internal/Store.ts +52 -17
- package/src/internal/Tidx.test.ts +4 -4
- package/src/internal/Tidx.ts +5 -4
- package/src/internal/Value.test.ts +25 -0
- package/src/internal/Value.ts +29 -0
- package/src/internal/Viem.test.ts +4 -0
- package/src/internal/Viem.ts +6 -4
- package/src/internal/WebhookTransfer.test.ts +89 -0
- package/src/internal/WebhookTransfer.ts +11 -7
- package/src/internal/Webhooks.test.ts +488 -0
- package/src/internal/Webhooks.ts +291 -10
- package/src/internal/funding/Provider.test.ts +1 -1
- package/src/internal/funding/providers/index.test.ts +73 -3
- package/src/internal/funding/providers/relay.test.ts +1 -5
- package/src/internal/funding/providers/relay.ts +56 -12
- package/src/internal/index.test.ts +1 -0
- package/src/internal/index.ts +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Db, Webhooks as Core } from 'tapimo'
|
|
1
|
+
import { type Db, Store, Webhooks as Core } from 'tapimo'
|
|
2
2
|
import * as z from 'zod/mini'
|
|
3
3
|
|
|
4
4
|
import * as Cursor from '../../../internal/Cursor.js'
|
|
@@ -1522,7 +1522,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
1522
1522
|
"logIndex": 0,
|
|
1523
1523
|
"recipient": "0x9e39034aae71fb89f66061a2602eb6efec271754",
|
|
1524
1524
|
"sender": "0xe7687128b0a808c2831ff94d4f7b2fb35c65af38",
|
|
1525
|
-
"timestamp": "2026-01-14T18:38:03.
|
|
1525
|
+
"timestamp": "2026-01-14T18:38:03.685Z",
|
|
1526
1526
|
"token": {
|
|
1527
1527
|
"decimals": 6,
|
|
1528
1528
|
"symbol": "QKSUSD",
|
|
@@ -1540,6 +1540,52 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
1540
1540
|
`)
|
|
1541
1541
|
})
|
|
1542
1542
|
|
|
1543
|
+
test('delivers collision-shaped token metadata from a cache hit', async () => {
|
|
1544
|
+
const db = TestApp.database()
|
|
1545
|
+
const subscription = await createTransferSubscription(db)
|
|
1546
|
+
await Core.setCursor(db, subscription.id, windowCursor)
|
|
1547
|
+
const cache = Store.memory()
|
|
1548
|
+
const address = '0x20c00000000000000000000071de0cd31ab0d105'
|
|
1549
|
+
await Store.memoize(
|
|
1550
|
+
async () => ({
|
|
1551
|
+
currency: 'USD',
|
|
1552
|
+
decimals: 6,
|
|
1553
|
+
name: 'Collision token',
|
|
1554
|
+
symbol: '123#__bigint',
|
|
1555
|
+
}),
|
|
1556
|
+
{
|
|
1557
|
+
key: `webhook:token-meta:v2:42431:${address}`,
|
|
1558
|
+
store: cache,
|
|
1559
|
+
ttl: 60_000,
|
|
1560
|
+
},
|
|
1561
|
+
)
|
|
1562
|
+
const bodies: string[] = []
|
|
1563
|
+
const fetch = (async (_input, init) => {
|
|
1564
|
+
bodies.push(typeof init?.body === 'string' ? init.body : '')
|
|
1565
|
+
return new Response(null, { status: 200 })
|
|
1566
|
+
}) satisfies typeof globalThis.fetch
|
|
1567
|
+
|
|
1568
|
+
const result = await Webhooks.poll({
|
|
1569
|
+
cache,
|
|
1570
|
+
chainId: 42431,
|
|
1571
|
+
client,
|
|
1572
|
+
db,
|
|
1573
|
+
dispatch: ({ envelope, subscription }) =>
|
|
1574
|
+
Core.deliverAndRecord(db, subscription, envelope, { fetch }),
|
|
1575
|
+
eventTypes: ['token:transfer'],
|
|
1576
|
+
headBlockNumber: windowHead,
|
|
1577
|
+
})
|
|
1578
|
+
|
|
1579
|
+
const payloads = bodies.map((body) => Webhooks.schema.Envelope.parse(JSON.parse(body)))
|
|
1580
|
+
const delivered = payloads.find(
|
|
1581
|
+
(payload) => payload.type === 'token:transfer' && payload.data.address === address,
|
|
1582
|
+
)
|
|
1583
|
+
expect(result.dispatched).toBe(2)
|
|
1584
|
+
expect(delivered?.type === 'token:transfer' ? delivered.data.token?.symbol : undefined).toBe(
|
|
1585
|
+
'123#__bigint',
|
|
1586
|
+
)
|
|
1587
|
+
})
|
|
1588
|
+
|
|
1543
1589
|
test('scans event types concurrently without increasing scan bounds', async () => {
|
|
1544
1590
|
const db = TestApp.database()
|
|
1545
1591
|
const transfer = await createTransferSubscription(db)
|
|
@@ -1605,7 +1651,8 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
1605
1651
|
chainId: 42431,
|
|
1606
1652
|
client,
|
|
1607
1653
|
db,
|
|
1608
|
-
dispatchBatch: async (dispatchables) => {
|
|
1654
|
+
dispatchBatch: async (dispatchables, context) => {
|
|
1655
|
+
expect(context.db).toBe(db)
|
|
1609
1656
|
batches.push([...dispatchables])
|
|
1610
1657
|
return { ok: true }
|
|
1611
1658
|
},
|
|
@@ -2070,7 +2117,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
2070
2117
|
"topic0": "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
|
2071
2118
|
},
|
|
2072
2119
|
"logIndex": 0,
|
|
2073
|
-
"timestamp": "2026-01-14T18:38:03.
|
|
2120
|
+
"timestamp": "2026-01-14T18:38:03.685Z",
|
|
2074
2121
|
"topics": [
|
|
2075
2122
|
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
|
2076
2123
|
"0x000000000000000000000000e7687128b0a808c2831ff94d4f7b2fb35c65af38",
|
|
@@ -2113,7 +2160,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
2113
2160
|
"blockNumber": 1000002,
|
|
2114
2161
|
"data": "0x0000000000000000000000000000000000000000000000000000000000002710",
|
|
2115
2162
|
"logIndex": 0,
|
|
2116
|
-
"timestamp": "2026-01-14T18:38:03.
|
|
2163
|
+
"timestamp": "2026-01-14T18:38:03.685Z",
|
|
2117
2164
|
"topics": [
|
|
2118
2165
|
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
|
|
2119
2166
|
"0x000000000000000000000000e7687128b0a808c2831ff94d4f7b2fb35c65af38",
|
|
@@ -2290,7 +2337,7 @@ describe.skipIf(Runtime.get().mode === 'localnet')('poll', () => {
|
|
|
2290
2337
|
"miner": "0x0000000000000000000000000000000000000000",
|
|
2291
2338
|
"number": 1000002,
|
|
2292
2339
|
"parentHash": "0xa406dff9c51cc2abbef3a811f0499e99a568bf781019f129ab45dca1df0e43e5",
|
|
2293
|
-
"timestamp": "2026-01-14T18:38:03.
|
|
2340
|
+
"timestamp": "2026-01-14T18:38:03.685Z",
|
|
2294
2341
|
"transactionCount": 52,
|
|
2295
2342
|
}
|
|
2296
2343
|
`)
|
|
@@ -664,7 +664,7 @@ export namespace schema {
|
|
|
664
664
|
.datetime()
|
|
665
665
|
.check(
|
|
666
666
|
z.describe('Block timestamp as an ISO 8601 string.'),
|
|
667
|
-
z.meta({ examples: ['2026-01-14T18:38:03.
|
|
667
|
+
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
668
668
|
),
|
|
669
669
|
token: z.optional(
|
|
670
670
|
z
|
|
@@ -790,7 +790,7 @@ export namespace schema {
|
|
|
790
790
|
.datetime()
|
|
791
791
|
.check(
|
|
792
792
|
z.describe('When the block was produced, as an ISO 8601 timestamp.'),
|
|
793
|
-
z.meta({ examples: ['2026-01-14T18:38:03.
|
|
793
|
+
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
794
794
|
),
|
|
795
795
|
topics: z.array(Schema.Hash).check(
|
|
796
796
|
z.describe('Log topics, starting with the event signature hash (topic 0).'),
|
|
@@ -881,7 +881,7 @@ export namespace schema {
|
|
|
881
881
|
.datetime()
|
|
882
882
|
.check(
|
|
883
883
|
z.describe('When the block was produced, as an ISO 8601 timestamp.'),
|
|
884
|
-
z.meta({ examples: ['2026-01-14T18:38:03.
|
|
884
|
+
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
885
885
|
),
|
|
886
886
|
})
|
|
887
887
|
.check(z.describe('Payload for a `block:created` event (a new block header).'))
|
|
@@ -2276,16 +2276,11 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
2276
2276
|
// Token metadata is best-effort for webhooks: transfers use it for display,
|
|
2277
2277
|
// while transactions expose fee-token references without blocking delivery.
|
|
2278
2278
|
const enrichStartedAt = Date.now()
|
|
2279
|
-
const data =
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
cache: cache_metadata,
|
|
2285
|
-
chainId,
|
|
2286
|
-
client,
|
|
2287
|
-
})
|
|
2288
|
-
: item.data
|
|
2279
|
+
const data = await enrichEventData(eventType, item.data, {
|
|
2280
|
+
cache: cache_metadata,
|
|
2281
|
+
chainId,
|
|
2282
|
+
client,
|
|
2283
|
+
})
|
|
2289
2284
|
durations.enrich += Date.now() - enrichStartedAt
|
|
2290
2285
|
observed.add('enrich')
|
|
2291
2286
|
options.signal?.throwIfAborted()
|
|
@@ -2303,7 +2298,7 @@ export async function poll(options: poll.Options): Promise<poll.Result> {
|
|
|
2303
2298
|
const dispatchables: poll.Dispatchable[] = []
|
|
2304
2299
|
for (const item of page.items) dispatchables.push(await buildDispatchable(item))
|
|
2305
2300
|
options.signal?.throwIfAborted()
|
|
2306
|
-
const delivered = await dispatchBatch(dispatchables)
|
|
2301
|
+
const delivered = await dispatchBatch(dispatchables, { db })
|
|
2307
2302
|
if (delivered.ok) {
|
|
2308
2303
|
accepted = page.items.at(-1)?.cursor
|
|
2309
2304
|
result.dispatched += dispatchables.length
|
|
@@ -2406,7 +2401,9 @@ export declare namespace poll {
|
|
|
2406
2401
|
*/
|
|
2407
2402
|
dispatch?: ((input: Dispatchable) => Promise<Webhooks.Result>) | undefined
|
|
2408
2403
|
/** Batch delivery transport. A successful result confirms every row in the input. */
|
|
2409
|
-
dispatchBatch?:
|
|
2404
|
+
dispatchBatch?:
|
|
2405
|
+
| ((input: readonly Dispatchable[], context: DispatchContext) => Promise<Webhooks.Result>)
|
|
2406
|
+
| undefined
|
|
2410
2407
|
/** Event types to poll (default all). */
|
|
2411
2408
|
eventTypes?: readonly EventType[] | undefined
|
|
2412
2409
|
/** Current chain head; the poller emits up to `head - confirmations`. */
|
|
@@ -2426,6 +2423,12 @@ export declare namespace poll {
|
|
|
2426
2423
|
/** Stops scanning and dispatch when the caller loses its execution lease. */
|
|
2427
2424
|
signal?: AbortSignal | undefined
|
|
2428
2425
|
}
|
|
2426
|
+
|
|
2427
|
+
/** Runtime context shared with a batch delivery transport. */
|
|
2428
|
+
type DispatchContext = {
|
|
2429
|
+
/** Database instance already resolved for this poll. */
|
|
2430
|
+
db: Db.Db
|
|
2431
|
+
}
|
|
2429
2432
|
/** Summary counters for one poll tick. */
|
|
2430
2433
|
type Result = {
|
|
2431
2434
|
/** Chain that was polled. */
|
|
@@ -3066,6 +3069,32 @@ function decodeScanLog(log: ScanLog, event: AbiEvent): ScanLog {
|
|
|
3066
3069
|
}
|
|
3067
3070
|
}
|
|
3068
3071
|
|
|
3072
|
+
/**
|
|
3073
|
+
* Attaches best-effort token metadata to one matched row before delivery.
|
|
3074
|
+
* Transfers gain display metadata; transactions resolve their fee token.
|
|
3075
|
+
*/
|
|
3076
|
+
export async function enrichEventData(
|
|
3077
|
+
eventType: EventType,
|
|
3078
|
+
data: unknown,
|
|
3079
|
+
options: enrichEventData.Options,
|
|
3080
|
+
): Promise<unknown> {
|
|
3081
|
+
if (eventType === 'token:transfer') return withTokenMetadata(data, options)
|
|
3082
|
+
if (eventType === 'transaction:included') return withFeeTokenMetadata(data, options)
|
|
3083
|
+
return data
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
export declare namespace enrichEventData {
|
|
3087
|
+
/** Metadata lookup dependencies. */
|
|
3088
|
+
type Options = {
|
|
3089
|
+
/** Memoization store for token metadata (5 minute TTL). */
|
|
3090
|
+
cache: Store.Store
|
|
3091
|
+
/** Chain the row was produced on. */
|
|
3092
|
+
chainId: number
|
|
3093
|
+
/** Client for `token.getMetadata` reads. */
|
|
3094
|
+
client: Viem.getClient.ReturnType
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3069
3098
|
/** Scans contract logs for one subscription, then re-checks every filter in memory. */
|
|
3070
3099
|
async function scanLogs(options: {
|
|
3071
3100
|
batchSize: number
|
|
@@ -3124,7 +3153,12 @@ async function scanLogs(options: {
|
|
|
3124
3153
|
if (blockNumber === undefined || logIndex === undefined) continue
|
|
3125
3154
|
if (atOrBefore(blockNumber, logIndex, window.skip)) continue
|
|
3126
3155
|
if (!matchesLog(log, f, event)) continue
|
|
3127
|
-
const data = toLogEvent(
|
|
3156
|
+
const data = toLogEvent(
|
|
3157
|
+
log,
|
|
3158
|
+
Value.blockToIso(await cache.header(blockNumber)),
|
|
3159
|
+
f.signature,
|
|
3160
|
+
event,
|
|
3161
|
+
)
|
|
3128
3162
|
if (data) {
|
|
3129
3163
|
items.push({ cursor: [data.blockNumber, data.logIndex], data })
|
|
3130
3164
|
if (items.length >= batchSize) return { hasMore: true, items }
|
|
@@ -3178,12 +3212,6 @@ function matchesLog(
|
|
|
3178
3212
|
|
|
3179
3213
|
// block:created (getBlock)
|
|
3180
3214
|
|
|
3181
|
-
/** Converts a viem block's `timestamp` (seconds) to an ISO 8601 string. */
|
|
3182
|
-
function blockIso(block: RpcBlock | undefined): string | undefined {
|
|
3183
|
-
if (!block || typeof block.timestamp !== 'bigint') return undefined
|
|
3184
|
-
return new Date(Number(block.timestamp) * 1000).toISOString()
|
|
3185
|
-
}
|
|
3186
|
-
|
|
3187
3215
|
type BlockEventData = {
|
|
3188
3216
|
number: number
|
|
3189
3217
|
hash: string
|
|
@@ -3203,7 +3231,7 @@ function toBlockEvent(block: RpcBlock): BlockEventData | undefined {
|
|
|
3203
3231
|
const miner = Schema.Address.safeParse(block.miner)
|
|
3204
3232
|
const gasUsed = typeof block.gasUsed === 'bigint' ? Number(block.gasUsed) : undefined
|
|
3205
3233
|
const gasLimit = typeof block.gasLimit === 'bigint' ? Number(block.gasLimit) : undefined
|
|
3206
|
-
const timestamp =
|
|
3234
|
+
const timestamp = Value.blockToIso(block)
|
|
3207
3235
|
const transactionCount = Array.isArray(block.transactions) ? block.transactions.length : 0
|
|
3208
3236
|
if (
|
|
3209
3237
|
number === undefined ||
|
|
@@ -3318,6 +3346,9 @@ async function scanTxs(options: {
|
|
|
3318
3346
|
? (block['transactions'] as unknown[])
|
|
3319
3347
|
: []
|
|
3320
3348
|
const timestamp = asString(block['timestamp'])
|
|
3349
|
+
// A transaction's own `blockTimestamp` is seconds-only, so the delivered
|
|
3350
|
+
// timestamp comes from the enclosing block, which carries milliseconds.
|
|
3351
|
+
const blockTime = Value.blockToIso(block)
|
|
3321
3352
|
for (let offset = 0; offset < transactions.length; offset++) {
|
|
3322
3353
|
const transaction = transactions[offset] as Record<string, unknown>
|
|
3323
3354
|
const transactionIndex = Value.hexToNumber(transaction['transactionIndex']) ?? offset
|
|
@@ -3325,7 +3356,8 @@ async function scanTxs(options: {
|
|
|
3325
3356
|
if (!matchesTx(transaction, f, includeCalls, timestamp, blockNumber)) continue
|
|
3326
3357
|
const parsed = Transactions.schema.Rpc.Transaction.safeParse(transaction)
|
|
3327
3358
|
if (!parsed.success) continue
|
|
3328
|
-
const
|
|
3359
|
+
const humanized = Transactions.humanizeTransaction(parsed.data)
|
|
3360
|
+
const data = blockTime === undefined ? humanized : { ...humanized, timestamp: blockTime }
|
|
3329
3361
|
items.push({ cursor: [blockNumber, transactionIndex], data })
|
|
3330
3362
|
if (items.length >= batchSize) return { hasMore: true, items }
|
|
3331
3363
|
}
|
|
@@ -3482,6 +3514,202 @@ function unauthorized(c: Context<App.Environment>) {
|
|
|
3482
3514
|
})
|
|
3483
3515
|
}
|
|
3484
3516
|
|
|
3517
|
+
// Pure per-block scanning (no RPC, no cursors, no pagination).
|
|
3518
|
+
|
|
3519
|
+
// Pure over its inputs: the caller fetches the raw block (with transactions)
|
|
3520
|
+
// and its logs; enrichment happens downstream. Rows require a parsable block number.
|
|
3521
|
+
/**
|
|
3522
|
+
* Matches one fetched block against a subscription set, producing the rows
|
|
3523
|
+
* each event type delivers. Invalid stored filters fail closed into `invalid`.
|
|
3524
|
+
*/
|
|
3525
|
+
export function scanBlock<const subscription extends scanBlock.Subscription>(
|
|
3526
|
+
options: scanBlock.Options<subscription>,
|
|
3527
|
+
): scanBlock.Result<subscription> {
|
|
3528
|
+
const { block, logs, subscriptions } = options
|
|
3529
|
+
const blockNumber = Value.hexToNumber(block['number'])
|
|
3530
|
+
const timestamp = Value.blockToIso(block)
|
|
3531
|
+
const header = toScanHeader(block)
|
|
3532
|
+
const viemLogs = logs.map(fromRpcLog)
|
|
3533
|
+
const matches: scanBlock.Match<subscription>[] = []
|
|
3534
|
+
const invalid: scanBlock.Invalid<subscription>[] = []
|
|
3535
|
+
|
|
3536
|
+
for (const subscription of subscriptions) {
|
|
3537
|
+
const filters = (() => {
|
|
3538
|
+
try {
|
|
3539
|
+
return parseFilters(subscription.eventType, subscription.filters)
|
|
3540
|
+
} catch (error) {
|
|
3541
|
+
invalid.push({ error, subscription })
|
|
3542
|
+
return undefined
|
|
3543
|
+
}
|
|
3544
|
+
})()
|
|
3545
|
+
if (filters === undefined) continue
|
|
3546
|
+
const matched = matches.length
|
|
3547
|
+
const push = (data: unknown, logIndex: number) => {
|
|
3548
|
+
if (blockNumber !== undefined) matches.push({ blockNumber, data, logIndex, subscription })
|
|
3549
|
+
}
|
|
3550
|
+
|
|
3551
|
+
// A throwing matcher invalidates only this subscription, rolling back any
|
|
3552
|
+
// rows it matched before the failure.
|
|
3553
|
+
try {
|
|
3554
|
+
switch (subscription.eventType) {
|
|
3555
|
+
case 'block:created': {
|
|
3556
|
+
const f = filters as z.output<typeof schema.BlockFilters>
|
|
3557
|
+
if (!matchesBlock(header, f)) break
|
|
3558
|
+
const data = toBlockEvent(header)
|
|
3559
|
+
if (data) push(data, 0)
|
|
3560
|
+
break
|
|
3561
|
+
}
|
|
3562
|
+
case 'log:emitted': {
|
|
3563
|
+
const f = filters as z.output<typeof schema.LogFilters>
|
|
3564
|
+
const event = parseEvent(f.signature)
|
|
3565
|
+
if (f.signature && (!event || !/^[A-Za-z_]\w*$/.test(event.name))) {
|
|
3566
|
+
invalid.push({
|
|
3567
|
+
error: new Webhooks.InvalidFilterError('log:emitted', [
|
|
3568
|
+
{ message: 'Unsupported event signature.', path: ['signature'] },
|
|
3569
|
+
]),
|
|
3570
|
+
subscription,
|
|
3571
|
+
})
|
|
3572
|
+
break
|
|
3573
|
+
}
|
|
3574
|
+
// Validate arg names up front so a bad filter fails closed even
|
|
3575
|
+
// when the block has no decodable logs.
|
|
3576
|
+
const unknown =
|
|
3577
|
+
event && f.args
|
|
3578
|
+
? Object.keys(f.args).find(
|
|
3579
|
+
(name) => !event.inputs.some((input) => input.name === name),
|
|
3580
|
+
)
|
|
3581
|
+
: undefined
|
|
3582
|
+
if (unknown !== undefined) {
|
|
3583
|
+
invalid.push({
|
|
3584
|
+
error: new Webhooks.InvalidFilterError('log:emitted', [
|
|
3585
|
+
{ message: `Unknown event argument: ${unknown}.`, path: ['args', unknown] },
|
|
3586
|
+
]),
|
|
3587
|
+
subscription,
|
|
3588
|
+
})
|
|
3589
|
+
break
|
|
3590
|
+
}
|
|
3591
|
+
for (const log of viemLogs) {
|
|
3592
|
+
const decoded = event ? decodeScanLog(log, event) : log
|
|
3593
|
+
const logIndex = decoded.logIndex ?? undefined
|
|
3594
|
+
if (logIndex === undefined) continue
|
|
3595
|
+
if (!matchesLog(decoded, f, event)) continue
|
|
3596
|
+
const data = toLogEvent(decoded, timestamp, f.signature, event)
|
|
3597
|
+
if (data) push(data, logIndex)
|
|
3598
|
+
}
|
|
3599
|
+
break
|
|
3600
|
+
}
|
|
3601
|
+
case 'token:transfer': {
|
|
3602
|
+
if (timestamp === undefined) break
|
|
3603
|
+
const f = filters as WebhookTransfer.Filters
|
|
3604
|
+
for (const log of logs) {
|
|
3605
|
+
const data = WebhookTransfer.decode(log, timestamp)
|
|
3606
|
+
if (!data || !WebhookTransfer.matches(data, f)) continue
|
|
3607
|
+
push(data, data.logIndex)
|
|
3608
|
+
}
|
|
3609
|
+
break
|
|
3610
|
+
}
|
|
3611
|
+
case 'transaction:included': {
|
|
3612
|
+
const f = filters as z.output<typeof schema.TxFilters>
|
|
3613
|
+
const includeCalls = f.includeCalls ?? true
|
|
3614
|
+
const transactions = Array.isArray(block['transactions'])
|
|
3615
|
+
? (block['transactions'] as unknown[])
|
|
3616
|
+
: []
|
|
3617
|
+
const rawTimestamp = asString(block['timestamp'])
|
|
3618
|
+
for (let offset = 0; offset < transactions.length; offset++) {
|
|
3619
|
+
const transaction = transactions[offset]
|
|
3620
|
+
if (!transaction || typeof transaction !== 'object') continue
|
|
3621
|
+
const tx = transaction as Record<string, unknown>
|
|
3622
|
+
const transactionIndex = Value.hexToNumber(tx['transactionIndex']) ?? offset
|
|
3623
|
+
if (!matchesTx(tx, f, includeCalls, rawTimestamp, blockNumber ?? 0)) continue
|
|
3624
|
+
const parsed = Transactions.schema.Rpc.Transaction.safeParse(tx)
|
|
3625
|
+
if (!parsed.success) continue
|
|
3626
|
+
const humanized = Transactions.humanizeTransaction(parsed.data)
|
|
3627
|
+
// A transaction's own timestamp is seconds-only; the enclosing
|
|
3628
|
+
// block carries milliseconds.
|
|
3629
|
+
push(
|
|
3630
|
+
timestamp === undefined ? humanized : { ...humanized, timestamp },
|
|
3631
|
+
transactionIndex,
|
|
3632
|
+
)
|
|
3633
|
+
}
|
|
3634
|
+
break
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
} catch (error) {
|
|
3638
|
+
matches.length = matched
|
|
3639
|
+
invalid.push({ error, subscription })
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
return { invalid, matches }
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
/** Normalizes a raw RPC header to the viem-shaped fields the block matchers read. */
|
|
3646
|
+
function toScanHeader(block: Record<string, unknown>): RpcBlock {
|
|
3647
|
+
const quantity = (value: unknown) => {
|
|
3648
|
+
try {
|
|
3649
|
+
return typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint'
|
|
3650
|
+
? BigInt(value)
|
|
3651
|
+
: undefined
|
|
3652
|
+
} catch {
|
|
3653
|
+
return undefined
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
return {
|
|
3657
|
+
...block,
|
|
3658
|
+
gasLimit: quantity(block['gasLimit']),
|
|
3659
|
+
gasUsed: quantity(block['gasUsed']),
|
|
3660
|
+
number: quantity(block['number']),
|
|
3661
|
+
timestamp: quantity(block['timestamp']),
|
|
3662
|
+
} as RpcBlock
|
|
3663
|
+
}
|
|
3664
|
+
|
|
3665
|
+
export declare namespace scanBlock {
|
|
3666
|
+
/** The subscription fields matching consumes; extra fields flow through. */
|
|
3667
|
+
type Subscription = {
|
|
3668
|
+
/** Event type selecting the matcher and payload shape. */
|
|
3669
|
+
eventType: EventType
|
|
3670
|
+
/** Stored filter predicates, validated fail-closed per event type. */
|
|
3671
|
+
filters: Record<string, unknown>
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
/** One fetched block plus the subscriptions to match it against. */
|
|
3675
|
+
type Options<subscription extends Subscription> = {
|
|
3676
|
+
/** Raw `eth_getBlockByNumber(_, true)` result: header plus raw transactions. */
|
|
3677
|
+
block: Record<string, unknown>
|
|
3678
|
+
/** Raw `eth_getLogs` entries for exactly this block, in log order. */
|
|
3679
|
+
logs: readonly RpcLog[]
|
|
3680
|
+
/** Active subscriptions for the chain; any mix of event types. */
|
|
3681
|
+
subscriptions: readonly subscription[]
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3684
|
+
/** One deliverable row for one subscription. */
|
|
3685
|
+
type Match<subscription extends Subscription> = {
|
|
3686
|
+
/** Block the row was produced from. */
|
|
3687
|
+
blockNumber: number
|
|
3688
|
+
/** Payload the matching read endpoint returns (pre-enrichment). */
|
|
3689
|
+
data: unknown
|
|
3690
|
+
/** Row position within the block (log or transaction index; 0 for blocks). */
|
|
3691
|
+
logIndex: number
|
|
3692
|
+
/** The matched subscription, passed through verbatim. */
|
|
3693
|
+
subscription: subscription
|
|
3694
|
+
}
|
|
3695
|
+
|
|
3696
|
+
/** A subscription whose stored filters failed validation. */
|
|
3697
|
+
type Invalid<subscription extends Subscription> = {
|
|
3698
|
+
/** The validation failure. */
|
|
3699
|
+
error: unknown
|
|
3700
|
+
/** The subscription with invalid filters. */
|
|
3701
|
+
subscription: subscription
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3704
|
+
/** Matches plus fail-closed filter rejections. */
|
|
3705
|
+
type Result<subscription extends Subscription> = {
|
|
3706
|
+
/** Subscriptions skipped because their stored filters failed validation. */
|
|
3707
|
+
invalid: readonly Invalid<subscription>[]
|
|
3708
|
+
/** Deliverable rows in subscription order, block order within each type. */
|
|
3709
|
+
matches: readonly Match<subscription>[]
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3485
3713
|
class BlockUnavailableError extends Error {
|
|
3486
3714
|
override name = 'Webhooks.BlockUnavailableError'
|
|
3487
3715
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as Tidx from '../../../internal/Tidx.js'
|
|
2
|
+
import * as Viem from '../../../internal/Viem.js'
|
|
3
|
+
import * as TestApp from '../../../../test/App.js'
|
|
4
|
+
import * as QueryBench from '../../../../test/QueryBench.js'
|
|
5
|
+
|
|
6
|
+
const senderTag = `0x${'00'.repeat(32)}`
|
|
7
|
+
const zoneChainIds = {
|
|
8
|
+
4217: 421_700_002,
|
|
9
|
+
42431: 424_310_002,
|
|
10
|
+
} as const
|
|
11
|
+
|
|
12
|
+
QueryBench.bench({
|
|
13
|
+
chainId: false,
|
|
14
|
+
name: 'listZoneWithdrawals',
|
|
15
|
+
path: {
|
|
16
|
+
4217: `/v1/zones/withdrawals/${senderTag}?chainId=${zoneChainIds[4217]}`,
|
|
17
|
+
42431: `/v1/zones/withdrawals/${senderTag}?chainId=${zoneChainIds[42431]}`,
|
|
18
|
+
},
|
|
19
|
+
zones: ({ chainId }) => {
|
|
20
|
+
const rpcUrl = Viem.resolveUrl(process.env.RPC_URL, chainId) ?? Viem.url[chainId]
|
|
21
|
+
const tidxUrl = Viem.resolveUrl(process.env.TIDX_URL, chainId) ?? Tidx.url[chainId]
|
|
22
|
+
if (!rpcUrl || !tidxUrl) throw new Error(`Missing Zone upstream for chain ${chainId}.`)
|
|
23
|
+
return [
|
|
24
|
+
TestApp.zone({
|
|
25
|
+
chainId: zoneChainIds[chainId],
|
|
26
|
+
rpcUrl,
|
|
27
|
+
sourceChainId: chainId,
|
|
28
|
+
tidxUrl,
|
|
29
|
+
}),
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
})
|
|
@@ -43,7 +43,7 @@ export namespace schema {
|
|
|
43
43
|
.strictObject({
|
|
44
44
|
chainId: Schema.ChainId.check(
|
|
45
45
|
z.describe('The chain id of the Zone where the withdrawal originated.'),
|
|
46
|
-
z.meta({ examples: [
|
|
46
|
+
z.meta({ examples: [1_424_310_001] }),
|
|
47
47
|
),
|
|
48
48
|
})
|
|
49
49
|
.check(z.describe('Query parameters used to select the originating Zone.'))
|
|
@@ -22,7 +22,7 @@ const providers = [
|
|
|
22
22
|
integratorId: '0xdead',
|
|
23
23
|
userAddress: '0x1111111111111111111111111111111111111111',
|
|
24
24
|
}),
|
|
25
|
-
Relay.relay({
|
|
25
|
+
Relay.relay({ userAddresses: TestFunding.relayQuoteUsers }),
|
|
26
26
|
Rhino.rhino(),
|
|
27
27
|
Squid.squid({
|
|
28
28
|
integratorId: 'squid-integrator-id',
|