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
|
@@ -376,7 +376,7 @@ export var schema;
|
|
|
376
376
|
sender: Schema.Address.check(z.describe('Address that sent the transfer.'), z.meta({ examples: ['0xe7687128b0a808c2831ff94d4f7b2fb35c65af38'] })),
|
|
377
377
|
timestamp: z.iso
|
|
378
378
|
.datetime()
|
|
379
|
-
.check(z.describe('Block timestamp as an ISO 8601 string.'), z.meta({ examples: ['2026-01-14T18:38:03.
|
|
379
|
+
.check(z.describe('Block timestamp as an ISO 8601 string.'), z.meta({ examples: ['2026-01-14T18:38:03.685Z'] })),
|
|
380
380
|
token: z.optional(z
|
|
381
381
|
.object({
|
|
382
382
|
decimals: z
|
|
@@ -444,7 +444,7 @@ export var schema;
|
|
|
444
444
|
.check(z.int(), z.nonnegative(), z.describe('Index of the log within its block.'), z.meta({ examples: [0] })),
|
|
445
445
|
timestamp: z.iso
|
|
446
446
|
.datetime()
|
|
447
|
-
.check(z.describe('When the block was produced, as an ISO 8601 timestamp.'), z.meta({ examples: ['2026-01-14T18:38:03.
|
|
447
|
+
.check(z.describe('When the block was produced, as an ISO 8601 timestamp.'), z.meta({ examples: ['2026-01-14T18:38:03.685Z'] })),
|
|
448
448
|
topics: z.array(Schema.Hash).check(z.describe('Log topics, starting with the event signature hash (topic 0).'), z.meta({
|
|
449
449
|
examples: [
|
|
450
450
|
[
|
|
@@ -486,7 +486,7 @@ export var schema;
|
|
|
486
486
|
.check(z.int(), z.nonnegative(), z.describe('Number of transactions included in this block.'), z.meta({ examples: [3] })),
|
|
487
487
|
timestamp: z.iso
|
|
488
488
|
.datetime()
|
|
489
|
-
.check(z.describe('When the block was produced, as an ISO 8601 timestamp.'), z.meta({ examples: ['2026-01-14T18:38:03.
|
|
489
|
+
.check(z.describe('When the block was produced, as an ISO 8601 timestamp.'), z.meta({ examples: ['2026-01-14T18:38:03.685Z'] })),
|
|
490
490
|
})
|
|
491
491
|
.check(z.describe('Payload for a `block:created` event (a new block header).'));
|
|
492
492
|
/** A `ping` (synthetic test-delivery) payload, sent by `POST /webhooks/:id/ping`. */
|
|
@@ -1659,15 +1659,11 @@ export async function poll(options) {
|
|
|
1659
1659
|
// Token metadata is best-effort for webhooks: transfers use it for display,
|
|
1660
1660
|
// while transactions expose fee-token references without blocking delivery.
|
|
1661
1661
|
const enrichStartedAt = Date.now();
|
|
1662
|
-
const data = eventType
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
chainId,
|
|
1668
|
-
client,
|
|
1669
|
-
})
|
|
1670
|
-
: item.data;
|
|
1662
|
+
const data = await enrichEventData(eventType, item.data, {
|
|
1663
|
+
cache: cache_metadata,
|
|
1664
|
+
chainId,
|
|
1665
|
+
client,
|
|
1666
|
+
});
|
|
1671
1667
|
durations.enrich += Date.now() - enrichStartedAt;
|
|
1672
1668
|
observed.add('enrich');
|
|
1673
1669
|
options.signal?.throwIfAborted();
|
|
@@ -1685,7 +1681,7 @@ export async function poll(options) {
|
|
|
1685
1681
|
for (const item of page.items)
|
|
1686
1682
|
dispatchables.push(await buildDispatchable(item));
|
|
1687
1683
|
options.signal?.throwIfAborted();
|
|
1688
|
-
const delivered = await dispatchBatch(dispatchables);
|
|
1684
|
+
const delivered = await dispatchBatch(dispatchables, { db });
|
|
1689
1685
|
if (delivered.ok) {
|
|
1690
1686
|
accepted = page.items.at(-1)?.cursor;
|
|
1691
1687
|
result.dispatched += dispatchables.length;
|
|
@@ -2237,6 +2233,17 @@ function decodeScanLog(log, event) {
|
|
|
2237
2233
|
return log;
|
|
2238
2234
|
}
|
|
2239
2235
|
}
|
|
2236
|
+
/**
|
|
2237
|
+
* Attaches best-effort token metadata to one matched row before delivery.
|
|
2238
|
+
* Transfers gain display metadata; transactions resolve their fee token.
|
|
2239
|
+
*/
|
|
2240
|
+
export async function enrichEventData(eventType, data, options) {
|
|
2241
|
+
if (eventType === 'token:transfer')
|
|
2242
|
+
return withTokenMetadata(data, options);
|
|
2243
|
+
if (eventType === 'transaction:included')
|
|
2244
|
+
return withFeeTokenMetadata(data, options);
|
|
2245
|
+
return data;
|
|
2246
|
+
}
|
|
2240
2247
|
/** Scans contract logs for one subscription, then re-checks every filter in memory. */
|
|
2241
2248
|
async function scanLogs(options) {
|
|
2242
2249
|
const { batchSize, cache, client, cursor, filters, maxBlocks, safeBlock } = options;
|
|
@@ -2286,7 +2293,7 @@ async function scanLogs(options) {
|
|
|
2286
2293
|
continue;
|
|
2287
2294
|
if (!matchesLog(log, f, event))
|
|
2288
2295
|
continue;
|
|
2289
|
-
const data = toLogEvent(log,
|
|
2296
|
+
const data = toLogEvent(log, Value.blockToIso(await cache.header(blockNumber)), f.signature, event);
|
|
2290
2297
|
if (data) {
|
|
2291
2298
|
items.push({ cursor: [data.blockNumber, data.logIndex], data });
|
|
2292
2299
|
if (items.length >= batchSize)
|
|
@@ -2338,13 +2345,6 @@ function matchesLog(log, f, event) {
|
|
|
2338
2345
|
}
|
|
2339
2346
|
return true;
|
|
2340
2347
|
}
|
|
2341
|
-
// block:created (getBlock)
|
|
2342
|
-
/** Converts a viem block's `timestamp` (seconds) to an ISO 8601 string. */
|
|
2343
|
-
function blockIso(block) {
|
|
2344
|
-
if (!block || typeof block.timestamp !== 'bigint')
|
|
2345
|
-
return undefined;
|
|
2346
|
-
return new Date(Number(block.timestamp) * 1000).toISOString();
|
|
2347
|
-
}
|
|
2348
2348
|
/** Builds the delivered `block:created` payload from a viem block header. */
|
|
2349
2349
|
function toBlockEvent(block) {
|
|
2350
2350
|
const number = block.number === null ? undefined : Number(block.number);
|
|
@@ -2353,7 +2353,7 @@ function toBlockEvent(block) {
|
|
|
2353
2353
|
const miner = Schema.Address.safeParse(block.miner);
|
|
2354
2354
|
const gasUsed = typeof block.gasUsed === 'bigint' ? Number(block.gasUsed) : undefined;
|
|
2355
2355
|
const gasLimit = typeof block.gasLimit === 'bigint' ? Number(block.gasLimit) : undefined;
|
|
2356
|
-
const timestamp =
|
|
2356
|
+
const timestamp = Value.blockToIso(block);
|
|
2357
2357
|
const transactionCount = Array.isArray(block.transactions) ? block.transactions.length : 0;
|
|
2358
2358
|
if (number === undefined ||
|
|
2359
2359
|
!hash.success ||
|
|
@@ -2449,6 +2449,9 @@ async function scanTxs(options) {
|
|
|
2449
2449
|
? block['transactions']
|
|
2450
2450
|
: [];
|
|
2451
2451
|
const timestamp = asString(block['timestamp']);
|
|
2452
|
+
// A transaction's own `blockTimestamp` is seconds-only, so the delivered
|
|
2453
|
+
// timestamp comes from the enclosing block, which carries milliseconds.
|
|
2454
|
+
const blockTime = Value.blockToIso(block);
|
|
2452
2455
|
for (let offset = 0; offset < transactions.length; offset++) {
|
|
2453
2456
|
const transaction = transactions[offset];
|
|
2454
2457
|
const transactionIndex = Value.hexToNumber(transaction['transactionIndex']) ?? offset;
|
|
@@ -2459,7 +2462,8 @@ async function scanTxs(options) {
|
|
|
2459
2462
|
const parsed = Transactions.schema.Rpc.Transaction.safeParse(transaction);
|
|
2460
2463
|
if (!parsed.success)
|
|
2461
2464
|
continue;
|
|
2462
|
-
const
|
|
2465
|
+
const humanized = Transactions.humanizeTransaction(parsed.data);
|
|
2466
|
+
const data = blockTime === undefined ? humanized : { ...humanized, timestamp: blockTime };
|
|
2463
2467
|
items.push({ cursor: [blockNumber, transactionIndex], data });
|
|
2464
2468
|
if (items.length >= batchSize)
|
|
2465
2469
|
return { hasMore: true, items };
|
|
@@ -2608,6 +2612,156 @@ function unauthorized(c) {
|
|
|
2608
2612
|
status: 401,
|
|
2609
2613
|
});
|
|
2610
2614
|
}
|
|
2615
|
+
// Pure per-block scanning (no RPC, no cursors, no pagination).
|
|
2616
|
+
// Pure over its inputs: the caller fetches the raw block (with transactions)
|
|
2617
|
+
// and its logs; enrichment happens downstream. Rows require a parsable block number.
|
|
2618
|
+
/**
|
|
2619
|
+
* Matches one fetched block against a subscription set, producing the rows
|
|
2620
|
+
* each event type delivers. Invalid stored filters fail closed into `invalid`.
|
|
2621
|
+
*/
|
|
2622
|
+
export function scanBlock(options) {
|
|
2623
|
+
const { block, logs, subscriptions } = options;
|
|
2624
|
+
const blockNumber = Value.hexToNumber(block['number']);
|
|
2625
|
+
const timestamp = Value.blockToIso(block);
|
|
2626
|
+
const header = toScanHeader(block);
|
|
2627
|
+
const viemLogs = logs.map(fromRpcLog);
|
|
2628
|
+
const matches = [];
|
|
2629
|
+
const invalid = [];
|
|
2630
|
+
for (const subscription of subscriptions) {
|
|
2631
|
+
const filters = (() => {
|
|
2632
|
+
try {
|
|
2633
|
+
return parseFilters(subscription.eventType, subscription.filters);
|
|
2634
|
+
}
|
|
2635
|
+
catch (error) {
|
|
2636
|
+
invalid.push({ error, subscription });
|
|
2637
|
+
return undefined;
|
|
2638
|
+
}
|
|
2639
|
+
})();
|
|
2640
|
+
if (filters === undefined)
|
|
2641
|
+
continue;
|
|
2642
|
+
const matched = matches.length;
|
|
2643
|
+
const push = (data, logIndex) => {
|
|
2644
|
+
if (blockNumber !== undefined)
|
|
2645
|
+
matches.push({ blockNumber, data, logIndex, subscription });
|
|
2646
|
+
};
|
|
2647
|
+
// A throwing matcher invalidates only this subscription, rolling back any
|
|
2648
|
+
// rows it matched before the failure.
|
|
2649
|
+
try {
|
|
2650
|
+
switch (subscription.eventType) {
|
|
2651
|
+
case 'block:created': {
|
|
2652
|
+
const f = filters;
|
|
2653
|
+
if (!matchesBlock(header, f))
|
|
2654
|
+
break;
|
|
2655
|
+
const data = toBlockEvent(header);
|
|
2656
|
+
if (data)
|
|
2657
|
+
push(data, 0);
|
|
2658
|
+
break;
|
|
2659
|
+
}
|
|
2660
|
+
case 'log:emitted': {
|
|
2661
|
+
const f = filters;
|
|
2662
|
+
const event = parseEvent(f.signature);
|
|
2663
|
+
if (f.signature && (!event || !/^[A-Za-z_]\w*$/.test(event.name))) {
|
|
2664
|
+
invalid.push({
|
|
2665
|
+
error: new Webhooks.InvalidFilterError('log:emitted', [
|
|
2666
|
+
{ message: 'Unsupported event signature.', path: ['signature'] },
|
|
2667
|
+
]),
|
|
2668
|
+
subscription,
|
|
2669
|
+
});
|
|
2670
|
+
break;
|
|
2671
|
+
}
|
|
2672
|
+
// Validate arg names up front so a bad filter fails closed even
|
|
2673
|
+
// when the block has no decodable logs.
|
|
2674
|
+
const unknown = event && f.args
|
|
2675
|
+
? Object.keys(f.args).find((name) => !event.inputs.some((input) => input.name === name))
|
|
2676
|
+
: undefined;
|
|
2677
|
+
if (unknown !== undefined) {
|
|
2678
|
+
invalid.push({
|
|
2679
|
+
error: new Webhooks.InvalidFilterError('log:emitted', [
|
|
2680
|
+
{ message: `Unknown event argument: ${unknown}.`, path: ['args', unknown] },
|
|
2681
|
+
]),
|
|
2682
|
+
subscription,
|
|
2683
|
+
});
|
|
2684
|
+
break;
|
|
2685
|
+
}
|
|
2686
|
+
for (const log of viemLogs) {
|
|
2687
|
+
const decoded = event ? decodeScanLog(log, event) : log;
|
|
2688
|
+
const logIndex = decoded.logIndex ?? undefined;
|
|
2689
|
+
if (logIndex === undefined)
|
|
2690
|
+
continue;
|
|
2691
|
+
if (!matchesLog(decoded, f, event))
|
|
2692
|
+
continue;
|
|
2693
|
+
const data = toLogEvent(decoded, timestamp, f.signature, event);
|
|
2694
|
+
if (data)
|
|
2695
|
+
push(data, logIndex);
|
|
2696
|
+
}
|
|
2697
|
+
break;
|
|
2698
|
+
}
|
|
2699
|
+
case 'token:transfer': {
|
|
2700
|
+
if (timestamp === undefined)
|
|
2701
|
+
break;
|
|
2702
|
+
const f = filters;
|
|
2703
|
+
for (const log of logs) {
|
|
2704
|
+
const data = WebhookTransfer.decode(log, timestamp);
|
|
2705
|
+
if (!data || !WebhookTransfer.matches(data, f))
|
|
2706
|
+
continue;
|
|
2707
|
+
push(data, data.logIndex);
|
|
2708
|
+
}
|
|
2709
|
+
break;
|
|
2710
|
+
}
|
|
2711
|
+
case 'transaction:included': {
|
|
2712
|
+
const f = filters;
|
|
2713
|
+
const includeCalls = f.includeCalls ?? true;
|
|
2714
|
+
const transactions = Array.isArray(block['transactions'])
|
|
2715
|
+
? block['transactions']
|
|
2716
|
+
: [];
|
|
2717
|
+
const rawTimestamp = asString(block['timestamp']);
|
|
2718
|
+
for (let offset = 0; offset < transactions.length; offset++) {
|
|
2719
|
+
const transaction = transactions[offset];
|
|
2720
|
+
if (!transaction || typeof transaction !== 'object')
|
|
2721
|
+
continue;
|
|
2722
|
+
const tx = transaction;
|
|
2723
|
+
const transactionIndex = Value.hexToNumber(tx['transactionIndex']) ?? offset;
|
|
2724
|
+
if (!matchesTx(tx, f, includeCalls, rawTimestamp, blockNumber ?? 0))
|
|
2725
|
+
continue;
|
|
2726
|
+
const parsed = Transactions.schema.Rpc.Transaction.safeParse(tx);
|
|
2727
|
+
if (!parsed.success)
|
|
2728
|
+
continue;
|
|
2729
|
+
const humanized = Transactions.humanizeTransaction(parsed.data);
|
|
2730
|
+
// A transaction's own timestamp is seconds-only; the enclosing
|
|
2731
|
+
// block carries milliseconds.
|
|
2732
|
+
push(timestamp === undefined ? humanized : { ...humanized, timestamp }, transactionIndex);
|
|
2733
|
+
}
|
|
2734
|
+
break;
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
catch (error) {
|
|
2739
|
+
matches.length = matched;
|
|
2740
|
+
invalid.push({ error, subscription });
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
return { invalid, matches };
|
|
2744
|
+
}
|
|
2745
|
+
/** Normalizes a raw RPC header to the viem-shaped fields the block matchers read. */
|
|
2746
|
+
function toScanHeader(block) {
|
|
2747
|
+
const quantity = (value) => {
|
|
2748
|
+
try {
|
|
2749
|
+
return typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint'
|
|
2750
|
+
? BigInt(value)
|
|
2751
|
+
: undefined;
|
|
2752
|
+
}
|
|
2753
|
+
catch {
|
|
2754
|
+
return undefined;
|
|
2755
|
+
}
|
|
2756
|
+
};
|
|
2757
|
+
return {
|
|
2758
|
+
...block,
|
|
2759
|
+
gasLimit: quantity(block['gasLimit']),
|
|
2760
|
+
gasUsed: quantity(block['gasUsed']),
|
|
2761
|
+
number: quantity(block['number']),
|
|
2762
|
+
timestamp: quantity(block['timestamp']),
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2611
2765
|
class BlockUnavailableError extends Error {
|
|
2612
2766
|
name = 'Webhooks.BlockUnavailableError';
|
|
2613
2767
|
constructor(blockNumber) {
|