tapimo 0.10.1 → 0.11.0
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/App.d.ts +5249 -3572
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -76
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +2 -144
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +74 -74
- package/dist/admin/apps/earn-vaults.d.ts +1 -1
- package/dist/admin/apps/organizations.d.ts +3 -3
- package/dist/admin/apps/verified-tokens.d.ts +74 -74
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +206 -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/data/App.d.ts +3618 -2954
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +7 -2
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +1 -1
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +55 -27
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +11 -11
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +2 -6
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +5 -5
- package/dist/apps/data/routes/earn.d.ts +4 -4
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +63 -34
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +8 -4
- 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 +26 -26
- package/dist/apps/data/routes/receipts.d.ts +240 -239
- 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/tokenlist.d.ts +12 -12
- package/dist/apps/data/routes/tokens.d.ts +4 -4
- 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/transactions.d.ts +282 -282
- package/dist/apps/data/routes/transfers.d.ts +13 -13
- 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/valuation.d.ts +21 -21
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1519 -643
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +134 -740
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +3 -3
- package/dist/apps/funding/App.d.ts +233 -0
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +331 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +207 -11
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +33 -33
- package/dist/apps/management/App.d.ts +793 -16
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +50 -50
- package/dist/apps/management/routes/faucet.d.ts +2 -2
- package/dist/apps/management/routes/invite-links.d.ts +42 -42
- package/dist/apps/management/routes/members.d.ts +2 -2
- package/dist/apps/management/routes/projects.d.ts +40 -40
- package/dist/apps/management/routes/webhooks.d.ts +1031 -59
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +27 -4
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +53 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +7 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +9 -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 +3 -1
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +4 -0
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +33 -69
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +63 -100
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/internal/Auth.d.ts +0 -26
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +0 -33
- 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 +50 -116
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +60 -106
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/Schema.d.ts +3 -1
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +4 -2
- package/dist/internal/Schema.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/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 +1 -55
- package/dist/internal/WebhookTransfer.d.ts.map +1 -1
- package/dist/internal/WebhookTransfer.js +1 -239
- package/dist/internal/WebhookTransfer.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +85 -44
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +94 -73
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/DepositWebhook.d.ts +25 -0
- package/dist/internal/funding/DepositWebhook.d.ts.map +1 -0
- package/dist/internal/funding/DepositWebhook.js +74 -0
- package/dist/internal/funding/DepositWebhook.js.map +1 -0
- package/dist/internal/funding/Reconciliation.d.ts +6 -0
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
- package/dist/internal/funding/Reconciliation.js +42 -10
- package/dist/internal/funding/Reconciliation.js.map +1 -1
- package/dist/internal/funding/index.d.ts +1 -0
- package/dist/internal/funding/index.d.ts.map +1 -1
- package/dist/internal/funding/index.js +1 -0
- package/dist/internal/funding/index.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/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
- package/dist/internal/webhookDestinations/slack.js +16 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/package.json +1 -1
- package/src/App.test.ts +30 -0
- package/src/App.ts +3 -0
- package/src/Client.test-d.ts +55 -2
- package/src/Webhooks.ts +2 -221
- package/src/analytics/Analytics.test.ts +34 -0
- package/src/analytics/Analytics.ts +206 -0
- package/src/analytics/tables/requestEvents.ts +6 -0
- package/src/apps/composition.test.ts +1 -0
- package/src/apps/data/App.ts +10 -2
- package/src/apps/data/routes/activities.test.ts +107 -11
- package/src/apps/data/routes/activities.ts +64 -32
- package/src/apps/data/routes/balances.ts +2 -6
- package/src/apps/data/routes/earn.ts +64 -34
- package/src/apps/data/routes/exchanges.test.ts +8 -3
- package/src/apps/data/routes/exchanges.ts +134 -82
- package/src/apps/data/routes/receipts.ts +16 -14
- package/src/apps/data/routes/tokens.ts +3 -2
- package/src/apps/data/routes/transactions.bench.ts +8 -0
- package/src/apps/data/routes/transfers.ts +36 -10
- package/src/apps/data/routes/webhooks.test.ts +179 -1497
- package/src/apps/data/routes/webhooks.ts +172 -975
- package/src/apps/funding/routes/deposit-addresses.test.ts +216 -2
- package/src/apps/funding/routes/deposit-addresses.ts +254 -18
- package/src/apps/funding/routes/transfers.test.ts +17 -2
- package/src/apps/management/routes/webhooks.test.ts +79 -1
- package/src/apps/management/routes/webhooks.ts +40 -4
- package/src/db/Db.test.ts +1 -5
- package/src/db/Db.ts +59 -0
- package/src/db/Schema.ts +13 -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/organizations.test.ts +5 -2
- package/src/db/tables/webhookQueueEvents.ts +7 -1
- package/src/db/tables/webhookSubscriptions.ts +89 -138
- package/src/internal/Auth.test.ts +0 -48
- package/src/internal/Auth.ts +0 -59
- 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/Log.test.ts +3 -1
- package/src/internal/Log.ts +14 -0
- package/src/internal/MetricSink.test.ts +75 -358
- package/src/internal/MetricSink.ts +117 -246
- package/src/internal/Schema.test.ts +18 -0
- package/src/internal/Schema.ts +13 -2
- package/src/internal/Tidx.ts +5 -4
- package/src/internal/Viem.test.ts +4 -0
- package/src/internal/Viem.ts +6 -4
- package/src/internal/WebhookTransfer.ts +1 -351
- package/src/internal/Webhooks.test.ts +111 -139
- package/src/internal/Webhooks.ts +181 -105
- package/src/internal/funding/DepositWebhook.test.ts +131 -0
- package/src/internal/funding/DepositWebhook.ts +101 -0
- package/src/internal/funding/Reconciliation.test.ts +14 -0
- package/src/internal/funding/Reconciliation.ts +161 -86
- package/src/internal/funding/index.test.ts +1 -0
- package/src/internal/funding/index.ts +1 -0
- package/src/internal/index.test.ts +1 -0
- package/src/internal/index.ts +1 -0
- package/src/internal/webhookDestinations/slack.ts +15 -0
- package/src/Webhooks.bench.ts +0 -714
- package/src/Webhooks.memory.bench.ts +0 -250
- package/src/Webhooks.test.ts +0 -146
package/src/Webhooks.ts
CHANGED
|
@@ -1,229 +1,10 @@
|
|
|
1
|
-
import * as AppWebhooks from './apps/data/routes/webhooks.js'
|
|
2
|
-
import * as Db from './db/Db.js'
|
|
3
|
-
import * as core_Webhooks from './internal/Webhooks.js'
|
|
4
|
-
import * as MetricSink from './internal/MetricSink.js'
|
|
5
|
-
import * as Store from './internal/Store.js'
|
|
6
|
-
import type * as Metrics from './Metrics.js'
|
|
7
|
-
import * as Viem from './internal/Viem.js'
|
|
8
|
-
|
|
9
|
-
/** How often a poller reclaims expired rows, independent of tick cadence. */
|
|
10
|
-
const pruneIntervalMs = 60_000
|
|
11
|
-
|
|
12
1
|
// Re-export the runtime-agnostic primitives (subscriptions, signing, delivery,
|
|
13
2
|
// `deliverAndRecord`, cursors, …) so consumers reach everything through one
|
|
14
|
-
// `Webhooks` namespace.
|
|
15
|
-
// `createPoller` below.
|
|
3
|
+
// `Webhooks` namespace.
|
|
16
4
|
export * from './internal/Webhooks.js'
|
|
17
5
|
|
|
18
6
|
// Re-export the webhook resource's zod schemas so consumers can validate and
|
|
19
7
|
// type delivery bodies: `Webhooks.schema.Envelope` (a discriminated union on
|
|
20
8
|
// `type`), plus the per-event `TransferEvent` / `TransactionEvent` / `PingEvent`
|
|
21
9
|
// payloads. Infer a type with `z.infer<typeof Webhooks.schema.Envelope>`.
|
|
22
|
-
export { eventTypes, schema } from './apps/data/routes/webhooks.js'
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Builds a webhook poller bound to a state store and chain config.
|
|
26
|
-
*
|
|
27
|
-
* This is the entry point a host runtime drives from chain-head notifications
|
|
28
|
-
* or a timer. Each {@link Poller.tick} scans active subscriptions from their
|
|
29
|
-
* cursors up to `head - confirmations` and dispatches matching events.
|
|
30
|
-
*
|
|
31
|
-
* Every onchain event type scans a confirmed window directly over JSON-RPC, so
|
|
32
|
-
* the poller builds memoized viem clients via {@link Viem.createGetClient}. The
|
|
33
|
-
* poller keeps `App.create` a pure Hono app: it constructs its own clients
|
|
34
|
-
* instead of reaching into app internals, and owns no request state.
|
|
35
|
-
*/
|
|
36
|
-
export function createPoller(options: createPoller.Options): createPoller.Poller {
|
|
37
|
-
// Persistent memoize cache for token metadata, shared across ticks (the
|
|
38
|
-
// webhook state store used to double-duty as this cache).
|
|
39
|
-
const cache = options.cache ?? Store.memory()
|
|
40
|
-
const getClient = Viem.createGetClient({
|
|
41
|
-
defaultChainId: options.defaultChainId,
|
|
42
|
-
rpc: options.rpc,
|
|
43
|
-
})
|
|
44
|
-
// Chain-head ticks run about once per block, so the janitor is throttled here
|
|
45
|
-
// rather than issuing deletes per block. Reads filter expiry at query time, so
|
|
46
|
-
// reclaiming late only costs space.
|
|
47
|
-
let prunedAt: number | undefined
|
|
48
|
-
|
|
49
|
-
const metrics = options.metrics ? MetricSink.webhooks(options.metrics) : undefined
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
async tick(input = {}) {
|
|
53
|
-
const chainId = input.chainId ?? options.defaultChainId ?? Viem.defaultChainId
|
|
54
|
-
|
|
55
|
-
// Wrap the transport so each enqueue (or inline delivery) emits a timed
|
|
56
|
-
// `webhook:enqueue` metric. The wrapper preserves the dispatch contract: it
|
|
57
|
-
// returns the underlying result unchanged and is a no-op when no metrics
|
|
58
|
-
// backend is configured.
|
|
59
|
-
const inner = input.dispatch ?? options.dispatch
|
|
60
|
-
const innerBatch =
|
|
61
|
-
input.dispatchBatch ?? (input.dispatch === undefined ? options.dispatchBatch : undefined)
|
|
62
|
-
const dispatch =
|
|
63
|
-
metrics && inner
|
|
64
|
-
? async (dispatchable: AppWebhooks.poll.Dispatchable) => {
|
|
65
|
-
const start = Date.now()
|
|
66
|
-
const result = await inner(dispatchable)
|
|
67
|
-
metrics.record({
|
|
68
|
-
chainId: dispatchable.envelope.chainId,
|
|
69
|
-
durationMs: Date.now() - start,
|
|
70
|
-
eventType: dispatchable.envelope.type,
|
|
71
|
-
ok: result.ok,
|
|
72
|
-
type: 'webhook:enqueue',
|
|
73
|
-
})
|
|
74
|
-
return result
|
|
75
|
-
}
|
|
76
|
-
: inner
|
|
77
|
-
const dispatchBatch = innerBatch
|
|
78
|
-
? async (
|
|
79
|
-
dispatchables: readonly AppWebhooks.poll.Dispatchable[],
|
|
80
|
-
context: AppWebhooks.poll.DispatchContext,
|
|
81
|
-
) => {
|
|
82
|
-
const start = Date.now()
|
|
83
|
-
const result = await innerBatch(dispatchables, context)
|
|
84
|
-
const durationMs = Date.now() - start
|
|
85
|
-
for (const dispatchable of dispatchables)
|
|
86
|
-
metrics?.record({
|
|
87
|
-
chainId: dispatchable.envelope.chainId,
|
|
88
|
-
durationMs,
|
|
89
|
-
eventType: dispatchable.envelope.type,
|
|
90
|
-
ok: result.ok,
|
|
91
|
-
type: 'webhook:enqueue',
|
|
92
|
-
})
|
|
93
|
-
return result
|
|
94
|
-
}
|
|
95
|
-
: undefined
|
|
96
|
-
|
|
97
|
-
// Resolve per tick so Workers factories build a fresh Hyperdrive-pooled
|
|
98
|
-
// connection each run.
|
|
99
|
-
const db = Db.get(options.db)
|
|
100
|
-
const now = input.now ?? options.now
|
|
101
|
-
if (prunedAt === undefined || Date.now() - prunedAt >= pruneIntervalMs) {
|
|
102
|
-
prunedAt = Date.now()
|
|
103
|
-
await core_Webhooks.pruneExpired(db, { now }).catch(() => {})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const start = Date.now()
|
|
107
|
-
let cursorLagBlocks: number | undefined
|
|
108
|
-
try {
|
|
109
|
-
const result = await AppWebhooks.poll({
|
|
110
|
-
batchSize: input.batchSize ?? options.batchSize,
|
|
111
|
-
cache,
|
|
112
|
-
chainId,
|
|
113
|
-
client: getClient(chainId),
|
|
114
|
-
confirmations: input.confirmations ?? options.confirmations,
|
|
115
|
-
db,
|
|
116
|
-
dispatch,
|
|
117
|
-
dispatchBatch,
|
|
118
|
-
eventTypes: input.eventTypes ?? options.eventTypes,
|
|
119
|
-
...(input.headBlockNumber === undefined
|
|
120
|
-
? {}
|
|
121
|
-
: { headBlockNumber: input.headBlockNumber }),
|
|
122
|
-
maxBlocks: input.maxBlocks ?? options.maxBlocks,
|
|
123
|
-
now,
|
|
124
|
-
signal: input.signal,
|
|
125
|
-
...(metrics
|
|
126
|
-
? {
|
|
127
|
-
onCursorLag(blocks: number) {
|
|
128
|
-
cursorLagBlocks = blocks
|
|
129
|
-
},
|
|
130
|
-
onScanCheckpoint(checkpoint: AppWebhooks.poll.ScanCheckpoint) {
|
|
131
|
-
metrics.record({ chainId, type: 'webhook:poll-scan', ...checkpoint })
|
|
132
|
-
// Ship the start boundary before the RPC allocation can terminate the isolate.
|
|
133
|
-
metrics.flush()
|
|
134
|
-
},
|
|
135
|
-
onStage(stage: AppWebhooks.poll.Stage) {
|
|
136
|
-
metrics.record({ chainId, type: 'webhook:poll', ...stage })
|
|
137
|
-
},
|
|
138
|
-
onSubscriptions(count: number) {
|
|
139
|
-
metrics.record({ chainId, count, type: 'webhook:poll-subscriptions' })
|
|
140
|
-
},
|
|
141
|
-
}
|
|
142
|
-
: {}),
|
|
143
|
-
})
|
|
144
|
-
metrics?.record({
|
|
145
|
-
cursorLagBlocks,
|
|
146
|
-
meta: { durationMs: Date.now() - start, outcome: 'ok' },
|
|
147
|
-
result,
|
|
148
|
-
type: 'webhook:tick',
|
|
149
|
-
})
|
|
150
|
-
return result
|
|
151
|
-
} catch (error) {
|
|
152
|
-
metrics?.record({
|
|
153
|
-
cursorLagBlocks,
|
|
154
|
-
meta: { chainId, durationMs: Date.now() - start, outcome: 'error' },
|
|
155
|
-
result: undefined,
|
|
156
|
-
type: 'webhook:tick',
|
|
157
|
-
})
|
|
158
|
-
throw error
|
|
159
|
-
} finally {
|
|
160
|
-
metrics?.flush()
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export declare namespace createPoller {
|
|
167
|
-
/** A row to dispatch, paired with its owning subscription. */
|
|
168
|
-
type Dispatchable = AppWebhooks.poll.Dispatchable
|
|
169
|
-
|
|
170
|
-
/** Delivery transport: hands a matched event to a queue or delivers inline. */
|
|
171
|
-
type Dispatch = NonNullable<AppWebhooks.poll.Options['dispatch']>
|
|
172
|
-
|
|
173
|
-
/** Batch delivery transport: confirms all rows together or leaves their cursor unchanged. */
|
|
174
|
-
type DispatchBatch = NonNullable<AppWebhooks.poll.Options['dispatchBatch']>
|
|
175
|
-
|
|
176
|
-
/** Summary counters returned by {@link Poller.tick}. */
|
|
177
|
-
type Result = AppWebhooks.poll.Result
|
|
178
|
-
|
|
179
|
-
/** Knobs shared by every {@link Poller.tick}; each is overridable per tick. */
|
|
180
|
-
type Defaults = {
|
|
181
|
-
/** Max matching rows scanned per subscription per tick (default 200). */
|
|
182
|
-
batchSize?: number | undefined
|
|
183
|
-
/** Reorg-safety window: only emit blocks this far behind head (default 1). */
|
|
184
|
-
confirmations?: number | undefined
|
|
185
|
-
/**
|
|
186
|
-
* Delivery transport. Defaults to inline `deliverAndRecord` (self-host); on
|
|
187
|
-
* Cloudflare pass a Queue producer so retry/backoff/DLQ are native.
|
|
188
|
-
*/
|
|
189
|
-
dispatch?: Dispatch | undefined
|
|
190
|
-
/** Batch delivery transport used when the runtime can enqueue multiple rows atomically. */
|
|
191
|
-
dispatchBatch?: DispatchBatch | undefined
|
|
192
|
-
/** Event types to poll (default all). */
|
|
193
|
-
eventTypes?: AppWebhooks.poll.Options['eventTypes']
|
|
194
|
-
/** Backfill cap: most blocks an RPC scanner inspects per tick (default 1000). */
|
|
195
|
-
maxBlocks?: number | undefined
|
|
196
|
-
/** Clock for envelope timestamps; injectable for tests. */
|
|
197
|
-
now?: (() => Date) | undefined
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/** Options for {@link createPoller}. */
|
|
201
|
-
type Options = Defaults & {
|
|
202
|
-
/** Cache for token metadata shared across ticks. */
|
|
203
|
-
cache?: Store.Store | undefined
|
|
204
|
-
/** Database holding subscriptions + cursors, or a factory resolved per tick (Workers/Hyperdrive). */
|
|
205
|
-
db: Db.Source
|
|
206
|
-
/** Tempo chain id polled when a tick omits one. */
|
|
207
|
-
defaultChainId?: Viem.ChainId | undefined
|
|
208
|
-
/** Metrics backend; emits `webhook:tick` per tick and `webhook:enqueue` per dispatch. */
|
|
209
|
-
metrics?: Metrics.Metrics | undefined
|
|
210
|
-
/** RPC options for the viem clients that scan chain events. */
|
|
211
|
-
rpc?: Viem.getClient.Rpc | undefined
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/** Per-tick overrides; falls back to the {@link Options} defaults. */
|
|
215
|
-
type TickOptions = Defaults & {
|
|
216
|
-
/** Chain to poll this tick (default `options.defaultChainId`). */
|
|
217
|
-
chainId?: Viem.ChainId | undefined
|
|
218
|
-
/** Chain head to work back from; resolved from RPC when omitted. */
|
|
219
|
-
headBlockNumber?: bigint | number | undefined
|
|
220
|
-
/** Stops scanning and dispatch when the caller loses its execution lease. */
|
|
221
|
-
signal?: AbortSignal | undefined
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** A chain-head-driven webhook poller. */
|
|
225
|
-
type Poller = {
|
|
226
|
-
/** Runs one poll tick, resolving the RPC head when not supplied. */
|
|
227
|
-
tick(options?: TickOptions): Promise<Result>
|
|
228
|
-
}
|
|
229
|
-
}
|
|
10
|
+
export { enrichEventData, eventTypes, scanBlock, schema } from './apps/data/routes/webhooks.js'
|
|
@@ -5,10 +5,12 @@ import * as RequestEvents from './tables/requestEvents.js'
|
|
|
5
5
|
const context = { enabled: true, environment: 'test', service: 'api' }
|
|
6
6
|
|
|
7
7
|
const entry = {
|
|
8
|
+
chainId: 4217,
|
|
8
9
|
duration: 12.3,
|
|
9
10
|
level: 'info',
|
|
10
11
|
method: 'GET',
|
|
11
12
|
path: '/v1/transactions',
|
|
13
|
+
query: 'include=receipt&limit=10',
|
|
12
14
|
requestId: 'req-1',
|
|
13
15
|
route: '/v1/transactions',
|
|
14
16
|
status: 200,
|
|
@@ -25,6 +27,7 @@ const clickHouse = {
|
|
|
25
27
|
/** Baseline stored row for insert/queue tests. */
|
|
26
28
|
const row = {
|
|
27
29
|
billing_active: null,
|
|
30
|
+
chain_id: 4217,
|
|
28
31
|
duration_ms: 12.3,
|
|
29
32
|
environment: 'test',
|
|
30
33
|
error_code: null,
|
|
@@ -34,6 +37,7 @@ const row = {
|
|
|
34
37
|
org_id: null,
|
|
35
38
|
project_id: null,
|
|
36
39
|
principal_type: 'unknown',
|
|
40
|
+
query: 'include=receipt&limit=10',
|
|
37
41
|
rate_limit_scope: null,
|
|
38
42
|
request_id: 'req-1',
|
|
39
43
|
route: '/v1/transactions',
|
|
@@ -183,6 +187,7 @@ describe('migrations', () => {
|
|
|
183
187
|
const sql = Analytics.migrations.map((migration) => migration.sql).join('\n')
|
|
184
188
|
for (const column of Object.keys(row)) expect(sql).toContain(column)
|
|
185
189
|
expect(sql).toContain('timings Map(String, Float64)')
|
|
190
|
+
expect(sql).toContain('query String')
|
|
186
191
|
})
|
|
187
192
|
|
|
188
193
|
test('the migrations declare query benchmark history', () => {
|
|
@@ -192,6 +197,22 @@ describe('migrations', () => {
|
|
|
192
197
|
expect(sql).toContain('rpc_url String')
|
|
193
198
|
expect(sql).toContain('tidx_url String')
|
|
194
199
|
})
|
|
200
|
+
|
|
201
|
+
test('the migrations declare the endpoint latency view', () => {
|
|
202
|
+
const sql = Analytics.migrations.map((migration) => migration.sql).join('\n')
|
|
203
|
+
const latest = Analytics.migrations[Analytics.migrations.length - 1]!
|
|
204
|
+
expect(sql).toContain('CREATE OR REPLACE VIEW endpoint_latency_results')
|
|
205
|
+
expect(sql).toContain("'production' AS source")
|
|
206
|
+
expect(sql).toContain("'benchmark' AS source")
|
|
207
|
+
expect(sql).toContain("if(result.metric = 'benchmark', 'request', result.metric) AS metric")
|
|
208
|
+
expect(sql).toContain("if(status >= 200 AND status < 300, 'success', 'error') AS outcome")
|
|
209
|
+
expect(sql).toContain("WHERE result.metric != 'request'")
|
|
210
|
+
expect(sql).toContain('arrayZip(mapKeys(timings), mapValues(timings))')
|
|
211
|
+
expect(latest.name).toBe('0011_endpoint_latency_query')
|
|
212
|
+
expect(latest.sql).toContain("environment = 'production' AND service = 'cadent-api'")
|
|
213
|
+
expect(latest.sql).toContain("coalesce(request_id, '') AS request_id")
|
|
214
|
+
expect(latest.sql).toContain('query AS variant')
|
|
215
|
+
})
|
|
195
216
|
})
|
|
196
217
|
|
|
197
218
|
describe('get', () => {
|
|
@@ -213,6 +234,7 @@ describe('createQueueSink', () => {
|
|
|
213
234
|
const row = send.mock.calls[0]![0]
|
|
214
235
|
expect({
|
|
215
236
|
billing_active: row.billing_active,
|
|
237
|
+
chain_id: row.chain_id,
|
|
216
238
|
duration_ms: row.duration_ms,
|
|
217
239
|
environment: row.environment,
|
|
218
240
|
error_code: row.error_code,
|
|
@@ -222,6 +244,7 @@ describe('createQueueSink', () => {
|
|
|
222
244
|
org_id: row.org_id,
|
|
223
245
|
principal_type: row.principal_type,
|
|
224
246
|
project_id: row.project_id,
|
|
247
|
+
query: row.query,
|
|
225
248
|
rate_limit_scope: row.rate_limit_scope,
|
|
226
249
|
request_id: row.request_id,
|
|
227
250
|
route: row.route,
|
|
@@ -235,6 +258,7 @@ describe('createQueueSink', () => {
|
|
|
235
258
|
}).toMatchInlineSnapshot(`
|
|
236
259
|
{
|
|
237
260
|
"billing_active": null,
|
|
261
|
+
"chain_id": 4217,
|
|
238
262
|
"duration_ms": 12.3,
|
|
239
263
|
"environment": "test",
|
|
240
264
|
"error_code": null,
|
|
@@ -244,6 +268,7 @@ describe('createQueueSink', () => {
|
|
|
244
268
|
"org_id": null,
|
|
245
269
|
"principal_type": "unknown",
|
|
246
270
|
"project_id": null,
|
|
271
|
+
"query": "include=receipt&limit=10",
|
|
247
272
|
"rate_limit_scope": null,
|
|
248
273
|
"request_id": "req-1",
|
|
249
274
|
"route": "/v1/transactions",
|
|
@@ -270,6 +295,15 @@ describe('createQueueSink', () => {
|
|
|
270
295
|
expect(send.mock.calls[0]![0].timings).toMatchInlineSnapshot(`{}`)
|
|
271
296
|
})
|
|
272
297
|
|
|
298
|
+
test('stores an empty query when the request has no query string', async () => {
|
|
299
|
+
const send = vi.fn<(message: Analytics.Event) => Promise<void>>().mockResolvedValue(undefined)
|
|
300
|
+
const sink = Analytics.createQueueSink({ send })(context)
|
|
301
|
+
|
|
302
|
+
await sink({ ...entry, query: undefined })
|
|
303
|
+
|
|
304
|
+
expect(send.mock.calls[0]![0].query).toMatchInlineSnapshot(`""`)
|
|
305
|
+
})
|
|
306
|
+
|
|
273
307
|
test('retries a failed send once with the same row', async () => {
|
|
274
308
|
const send = vi
|
|
275
309
|
.fn<(message: Analytics.Event) => Promise<void>>()
|
|
@@ -120,6 +120,7 @@ export const migrations: readonly Migration[] = [
|
|
|
120
120
|
timestamp DateTime64(3, 'UTC'),
|
|
121
121
|
service LowCardinality(String),
|
|
122
122
|
environment LowCardinality(String),
|
|
123
|
+
chain_id Nullable(UInt32),
|
|
123
124
|
method LowCardinality(String),
|
|
124
125
|
route LowCardinality(String),
|
|
125
126
|
status UInt16,
|
|
@@ -129,6 +130,7 @@ export const migrations: readonly Migration[] = [
|
|
|
129
130
|
key_environment Nullable(String),
|
|
130
131
|
org_id Nullable(String),
|
|
131
132
|
project_id Nullable(String),
|
|
133
|
+
query String,
|
|
132
134
|
rate_limit_scope Nullable(String),
|
|
133
135
|
error_code Nullable(String),
|
|
134
136
|
rpc_error_code Nullable(Int32),
|
|
@@ -203,6 +205,8 @@ export const migrations: readonly Migration[] = [
|
|
|
203
205
|
git_ref LowCardinality(String),
|
|
204
206
|
chain_id UInt32,
|
|
205
207
|
chain LowCardinality(String),
|
|
208
|
+
method LowCardinality(String),
|
|
209
|
+
route LowCardinality(String),
|
|
206
210
|
query String,
|
|
207
211
|
metric LowCardinality(String),
|
|
208
212
|
mean_ms Float64,
|
|
@@ -218,6 +222,208 @@ export const migrations: readonly Migration[] = [
|
|
|
218
222
|
ORDER BY (chain_id, query, metric, timestamp, run_id)
|
|
219
223
|
`,
|
|
220
224
|
},
|
|
225
|
+
{
|
|
226
|
+
name: '0006_endpoint_latency_dimensions',
|
|
227
|
+
// Patches production while fresh preview tables skip the unavailable ALTER.
|
|
228
|
+
guard: `
|
|
229
|
+
SELECT toUInt8(count() = 1) FROM system.columns
|
|
230
|
+
WHERE database = currentDatabase()
|
|
231
|
+
AND table = 'request_events'
|
|
232
|
+
AND name = 'chain_id'
|
|
233
|
+
`,
|
|
234
|
+
sql: `
|
|
235
|
+
ALTER TABLE request_events
|
|
236
|
+
ADD COLUMN IF NOT EXISTS chain_id Nullable(UInt32) AFTER environment
|
|
237
|
+
`,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: '0007_query_benchmark_dimensions',
|
|
241
|
+
// Patches production while fresh preview tables skip the unavailable ALTER.
|
|
242
|
+
guard: `
|
|
243
|
+
SELECT toUInt8(count() = 2) FROM system.columns
|
|
244
|
+
WHERE database = currentDatabase()
|
|
245
|
+
AND table = 'query_benchmark_results'
|
|
246
|
+
AND name IN ('method', 'route')
|
|
247
|
+
`,
|
|
248
|
+
sql: `
|
|
249
|
+
ALTER TABLE query_benchmark_results
|
|
250
|
+
ADD COLUMN IF NOT EXISTS method LowCardinality(String) AFTER chain,
|
|
251
|
+
ADD COLUMN IF NOT EXISTS route LowCardinality(String) AFTER method
|
|
252
|
+
`,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: '0008_endpoint_latency_results',
|
|
256
|
+
sql: `
|
|
257
|
+
CREATE OR REPLACE VIEW endpoint_latency_results AS
|
|
258
|
+
SELECT
|
|
259
|
+
timestamp,
|
|
260
|
+
'production' AS source,
|
|
261
|
+
chain_id,
|
|
262
|
+
method,
|
|
263
|
+
route AS endpoint,
|
|
264
|
+
'' AS variant,
|
|
265
|
+
toNullable(status) AS status,
|
|
266
|
+
if(status >= 200 AND status < 300, 'success', 'error') AS outcome,
|
|
267
|
+
measurement.1 AS metric,
|
|
268
|
+
measurement.2 AS mean_ms,
|
|
269
|
+
measurement.2 AS min_ms,
|
|
270
|
+
measurement.2 AS max_ms,
|
|
271
|
+
toUInt64(1) AS samples,
|
|
272
|
+
'' AS run_id,
|
|
273
|
+
'' AS git_sha
|
|
274
|
+
FROM request_events
|
|
275
|
+
ARRAY JOIN arrayConcat(
|
|
276
|
+
[('request', duration_ms)],
|
|
277
|
+
arrayFilter(
|
|
278
|
+
measurement -> measurement.1 != 'request',
|
|
279
|
+
arrayZip(mapKeys(timings), mapValues(timings))
|
|
280
|
+
)
|
|
281
|
+
) AS measurement
|
|
282
|
+
WHERE environment = 'production' AND service = 'api'
|
|
283
|
+
|
|
284
|
+
UNION ALL
|
|
285
|
+
|
|
286
|
+
SELECT
|
|
287
|
+
timestamp,
|
|
288
|
+
'benchmark' AS source,
|
|
289
|
+
toNullable(chain_id) AS chain_id,
|
|
290
|
+
method,
|
|
291
|
+
if(route = '', query, route) AS endpoint,
|
|
292
|
+
query AS variant,
|
|
293
|
+
CAST(NULL, 'Nullable(UInt16)') AS status,
|
|
294
|
+
'success' AS outcome,
|
|
295
|
+
if(result.metric = 'benchmark', 'request', result.metric) AS metric,
|
|
296
|
+
mean_ms,
|
|
297
|
+
min_ms,
|
|
298
|
+
max_ms,
|
|
299
|
+
toUInt64(samples) AS samples,
|
|
300
|
+
run_id,
|
|
301
|
+
git_sha
|
|
302
|
+
FROM query_benchmark_results AS result
|
|
303
|
+
WHERE result.metric != 'request'
|
|
304
|
+
`,
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: '0009_endpoint_latency_production_service',
|
|
308
|
+
sql: `
|
|
309
|
+
CREATE OR REPLACE VIEW endpoint_latency_results AS
|
|
310
|
+
SELECT
|
|
311
|
+
timestamp,
|
|
312
|
+
'production' AS source,
|
|
313
|
+
chain_id,
|
|
314
|
+
method,
|
|
315
|
+
route AS endpoint,
|
|
316
|
+
'' AS variant,
|
|
317
|
+
toNullable(status) AS status,
|
|
318
|
+
if(status >= 200 AND status < 300, 'success', 'error') AS outcome,
|
|
319
|
+
measurement.1 AS metric,
|
|
320
|
+
measurement.2 AS mean_ms,
|
|
321
|
+
measurement.2 AS min_ms,
|
|
322
|
+
measurement.2 AS max_ms,
|
|
323
|
+
toUInt64(1) AS samples,
|
|
324
|
+
'' AS run_id,
|
|
325
|
+
'' AS git_sha
|
|
326
|
+
FROM request_events
|
|
327
|
+
ARRAY JOIN arrayConcat(
|
|
328
|
+
[('request', duration_ms)],
|
|
329
|
+
arrayFilter(
|
|
330
|
+
measurement -> measurement.1 != 'request',
|
|
331
|
+
arrayZip(mapKeys(timings), mapValues(timings))
|
|
332
|
+
)
|
|
333
|
+
) AS measurement
|
|
334
|
+
WHERE environment = 'production' AND service = 'cadent-api'
|
|
335
|
+
|
|
336
|
+
UNION ALL
|
|
337
|
+
|
|
338
|
+
SELECT
|
|
339
|
+
timestamp,
|
|
340
|
+
'benchmark' AS source,
|
|
341
|
+
toNullable(chain_id) AS chain_id,
|
|
342
|
+
method,
|
|
343
|
+
if(route = '', query, route) AS endpoint,
|
|
344
|
+
query AS variant,
|
|
345
|
+
CAST(NULL, 'Nullable(UInt16)') AS status,
|
|
346
|
+
'success' AS outcome,
|
|
347
|
+
if(result.metric = 'benchmark', 'request', result.metric) AS metric,
|
|
348
|
+
mean_ms,
|
|
349
|
+
min_ms,
|
|
350
|
+
max_ms,
|
|
351
|
+
toUInt64(samples) AS samples,
|
|
352
|
+
run_id,
|
|
353
|
+
git_sha
|
|
354
|
+
FROM query_benchmark_results AS result
|
|
355
|
+
WHERE result.metric != 'request'
|
|
356
|
+
`,
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
name: '0010_request_events_query',
|
|
360
|
+
// Patches tables created before redacted request queries entered the baseline.
|
|
361
|
+
// Fresh tables skip this ALTER, allowing scoped preview users to migrate.
|
|
362
|
+
guard: `
|
|
363
|
+
SELECT toUInt8(count() = 1) FROM system.columns
|
|
364
|
+
WHERE database = currentDatabase()
|
|
365
|
+
AND table = 'request_events'
|
|
366
|
+
AND name = 'query'
|
|
367
|
+
`,
|
|
368
|
+
sql: `
|
|
369
|
+
ALTER TABLE request_events
|
|
370
|
+
ADD COLUMN IF NOT EXISTS query String AFTER project_id
|
|
371
|
+
`,
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
name: '0011_endpoint_latency_query',
|
|
375
|
+
sql: `
|
|
376
|
+
CREATE OR REPLACE VIEW endpoint_latency_results AS
|
|
377
|
+
SELECT
|
|
378
|
+
timestamp,
|
|
379
|
+
'production' AS source,
|
|
380
|
+
chain_id,
|
|
381
|
+
method,
|
|
382
|
+
route AS endpoint,
|
|
383
|
+
query AS variant,
|
|
384
|
+
toNullable(status) AS status,
|
|
385
|
+
if(status >= 200 AND status < 300, 'success', 'error') AS outcome,
|
|
386
|
+
measurement.1 AS metric,
|
|
387
|
+
measurement.2 AS mean_ms,
|
|
388
|
+
measurement.2 AS min_ms,
|
|
389
|
+
measurement.2 AS max_ms,
|
|
390
|
+
toUInt64(1) AS samples,
|
|
391
|
+
coalesce(request_id, '') AS request_id,
|
|
392
|
+
'' AS run_id,
|
|
393
|
+
'' AS git_sha
|
|
394
|
+
FROM request_events
|
|
395
|
+
ARRAY JOIN arrayConcat(
|
|
396
|
+
[('request', duration_ms)],
|
|
397
|
+
arrayFilter(
|
|
398
|
+
measurement -> measurement.1 != 'request',
|
|
399
|
+
arrayZip(mapKeys(timings), mapValues(timings))
|
|
400
|
+
)
|
|
401
|
+
) AS measurement
|
|
402
|
+
WHERE environment = 'production' AND service = 'cadent-api'
|
|
403
|
+
|
|
404
|
+
UNION ALL
|
|
405
|
+
|
|
406
|
+
SELECT
|
|
407
|
+
timestamp,
|
|
408
|
+
'benchmark' AS source,
|
|
409
|
+
toNullable(chain_id) AS chain_id,
|
|
410
|
+
method,
|
|
411
|
+
if(route = '', query, route) AS endpoint,
|
|
412
|
+
query AS variant,
|
|
413
|
+
CAST(NULL, 'Nullable(UInt16)') AS status,
|
|
414
|
+
'success' AS outcome,
|
|
415
|
+
if(result.metric = 'benchmark', 'request', result.metric) AS metric,
|
|
416
|
+
mean_ms,
|
|
417
|
+
min_ms,
|
|
418
|
+
max_ms,
|
|
419
|
+
toUInt64(samples) AS samples,
|
|
420
|
+
'' AS request_id,
|
|
421
|
+
run_id,
|
|
422
|
+
git_sha
|
|
423
|
+
FROM query_benchmark_results AS result
|
|
424
|
+
WHERE result.metric != 'request'
|
|
425
|
+
`,
|
|
426
|
+
},
|
|
221
427
|
]
|
|
222
428
|
|
|
223
429
|
/**
|
|
@@ -10,6 +10,8 @@ export type Table = {
|
|
|
10
10
|
* billing gate for sandbox: only `1` rows bill.
|
|
11
11
|
*/
|
|
12
12
|
billing_active: number | null
|
|
13
|
+
/** Tempo chain selected for the request. */
|
|
14
|
+
chain_id: number | null
|
|
13
15
|
/** Total request duration in milliseconds. */
|
|
14
16
|
duration_ms: number
|
|
15
17
|
/** Deployment environment that served the request. */
|
|
@@ -28,6 +30,8 @@ export type Table = {
|
|
|
28
30
|
project_id: string | null
|
|
29
31
|
/** Caller principal kind. */
|
|
30
32
|
principal_type: 'api_key' | 'public' | 'session' | 'super_admin' | 'unknown'
|
|
33
|
+
/** Redacted request query string, without a leading `?`. */
|
|
34
|
+
query: string
|
|
31
35
|
/** Rate-limit bucket scope, when a rate limit was applied. */
|
|
32
36
|
rate_limit_scope: string | null
|
|
33
37
|
/** Numeric JSON-RPC error code when every failed response shares one code. */
|
|
@@ -557,6 +561,7 @@ function event(entry: Log.Entry, context: Metrics.cloudflare.Context): Table {
|
|
|
557
561
|
const principal = entry.principal
|
|
558
562
|
return {
|
|
559
563
|
billing_active: principal?.type === 'api_key' ? Number(principal.billingActive === true) : null,
|
|
564
|
+
chain_id: entry.chainId ?? null,
|
|
560
565
|
duration_ms: entry.duration,
|
|
561
566
|
environment: context.environment ?? 'unknown',
|
|
562
567
|
error_code: entry.errorCode ?? null,
|
|
@@ -566,6 +571,7 @@ function event(entry: Log.Entry, context: Metrics.cloudflare.Context): Table {
|
|
|
566
571
|
org_id: principal?.type === 'api_key' ? (principal.orgId ?? null) : null,
|
|
567
572
|
project_id: principal?.type === 'api_key' ? (principal.projectId ?? null) : null,
|
|
568
573
|
principal_type: principal?.type ?? 'unknown',
|
|
574
|
+
query: entry.query ?? '',
|
|
569
575
|
rate_limit_scope: entry.rateLimit?.scope ?? null,
|
|
570
576
|
request_id: entry.requestId ?? null,
|
|
571
577
|
route: entry.route,
|
package/src/apps/data/App.ts
CHANGED
|
@@ -224,7 +224,13 @@ export function data(options: data.Options = {}) {
|
|
|
224
224
|
.route('/', transactionActivities({ fx: options.fx }))
|
|
225
225
|
.route('/', transfers({ fx: options.fx }))
|
|
226
226
|
.route('/', verifiedTokens())
|
|
227
|
-
.route(
|
|
227
|
+
.route(
|
|
228
|
+
'/',
|
|
229
|
+
webhooks({
|
|
230
|
+
applicationEventTypes: webhook?.applicationEventTypes ?? [],
|
|
231
|
+
enabled: options.webhook !== false,
|
|
232
|
+
}),
|
|
233
|
+
)
|
|
228
234
|
.route('/', zones())
|
|
229
235
|
.route('/', rpc())
|
|
230
236
|
.route('/', coingecko())
|
|
@@ -237,6 +243,8 @@ export function data(options: data.Options = {}) {
|
|
|
237
243
|
indexerHandlers: indexerRouteHandlers,
|
|
238
244
|
rpcOnlyHandlers: rpcOnlyRouteHandlers,
|
|
239
245
|
})
|
|
246
|
+
if (selection.matched && !selection.conflict && !selection.invalid)
|
|
247
|
+
c.set('chainId', selection.chainId)
|
|
240
248
|
return (
|
|
241
249
|
selection.matched &&
|
|
242
250
|
!selection.conflict &&
|
|
@@ -443,7 +451,7 @@ function webhooksBlock() {
|
|
|
443
451
|
'tempo-event-id',
|
|
444
452
|
'A unique, stable id for this event (`evt_…`). The same event may be delivered more than once, so use this id to skip duplicates.',
|
|
445
453
|
),
|
|
446
|
-
header('tempo-event-type', 'What happened: `token:transfer`, `transaction:included`, `log:emitted`, `block:created`, or `ping`.'), // prettier-ignore
|
|
454
|
+
header('tempo-event-type', 'What happened: `token:transfer`, `transaction:included`, `log:emitted`, `block:created`, `funding:deposit.updated`, or `ping`.'), // prettier-ignore
|
|
447
455
|
],
|
|
448
456
|
requestBody: {
|
|
449
457
|
content: { 'application/json': { schema: envelope } },
|