tapimo 0.5.0 → 0.5.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/App.d.ts +4854 -4829
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +20 -2
- package/dist/App.js.map +1 -1
- package/dist/Assets.js +3 -3
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +1 -2
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -1
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +5 -10
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +6 -34
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +3 -3
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +4 -1
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +6 -34
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +2 -2
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +2 -2
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +33 -33
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/data/App.d.ts +1398 -1405
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +25 -38
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts +108 -3
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.js +409 -2
- package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +245 -245
- package/dist/apps/data/routes/blocks.d.ts +123 -123
- package/dist/apps/data/routes/funding.d.ts +236 -146
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +23 -12
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +9 -2
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +31 -31
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/transactions.d.ts +281 -281
- package/dist/apps/data/routes/transfers.d.ts +66 -73
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +21 -27
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
- package/dist/apps/data/routes/webhooks.d.ts +35 -35
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +176 -42
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/management/App.d.ts +520 -504
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +5 -4
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +120 -120
- package/dist/apps/management/routes/billing.d.ts +211 -211
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +1 -1
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +72 -72
- package/dist/apps/management/routes/invite-links.d.ts +159 -159
- package/dist/apps/management/routes/me.d.ts +17 -17
- package/dist/apps/management/routes/members.d.ts +80 -80
- package/dist/apps/management/routes/orgs.d.ts +59 -43
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +18 -1
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +109 -109
- package/dist/apps/management/routes/scopes.d.ts +11 -11
- package/dist/apps/management/routes/usage.d.ts +79 -79
- package/dist/apps/mcp.js +2 -2
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/relay/App.d.ts +2 -2
- package/dist/apps/relay/App.js +2 -2
- package/dist/apps/relay/Sponsorships.d.ts +3 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +15 -1
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +4 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.js +1 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +6 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +26 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +2 -11
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +1 -20
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +2 -1
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +52 -10
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/internal/Auth.d.ts +4 -0
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +15 -8
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +9 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +12 -3
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/FundingQuotes.d.ts +176 -56
- package/dist/internal/FundingQuotes.d.ts.map +1 -1
- package/dist/internal/FundingQuotes.js +100 -5
- package/dist/internal/FundingQuotes.js.map +1 -1
- package/dist/internal/Log.d.ts +18 -12
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +2 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +2 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +4 -4
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Tidx.d.ts +9 -3
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +13 -7
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Viem.d.ts +14 -1
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +19 -1
- package/dist/internal/Viem.js.map +1 -1
- package/package.json +7 -2
- package/src/ApiKeys.test.ts +2 -0
- package/src/App.test.ts +15 -4
- package/src/App.ts +31 -5
- package/src/Assets.ts +3 -3
- package/src/Client.test-d.ts +30 -3
- package/src/Scope.ts +4 -2
- package/src/Webhooks.ts +5 -10
- package/src/admin/apps/api-keys.test.ts +27 -0
- package/src/admin/apps/api-keys.ts +8 -1
- package/src/admin/apps/scopes.test.ts +7 -2
- package/src/admin/apps/scopes.ts +2 -2
- package/src/admin/ui/src/components/Dialog.tsx +8 -2
- package/src/admin/ui/src/lib/scopes.test.ts +19 -0
- package/src/admin/ui/src/lib/scopes.ts +12 -0
- package/src/admin/ui/src/routes/api-keys.tsx +128 -27
- package/src/admin/ui.generated.ts +33 -33
- package/src/apps/composition.test.ts +77 -0
- package/src/apps/data/App.ts +25 -45
- package/src/apps/data/FundingQuoteProviders.test.ts +615 -5
- package/src/apps/data/FundingQuoteProviders.ts +570 -4
- package/src/apps/data/routes/funding.test.ts +181 -7
- package/src/apps/data/routes/funding.ts +27 -12
- package/src/apps/data/routes/indexer.test.ts +82 -20
- package/src/apps/data/routes/indexer.ts +8 -2
- package/src/apps/data/routes/tokens.test.ts +54 -0
- package/src/apps/data/routes/transfers.test.ts +73 -1
- package/src/apps/data/routes/transfers.ts +24 -30
- package/src/apps/data/routes/webhooks.test.ts +203 -0
- package/src/apps/data/routes/webhooks.ts +191 -54
- package/src/apps/management/Billing.test.ts +52 -3
- package/src/apps/management/Billing.ts +5 -4
- package/src/apps/management/routes/billing.ts +6 -1
- package/src/apps/management/routes/orgs.ts +19 -1
- package/src/apps/mcp.test.ts +18 -0
- package/src/apps/mcp.ts +2 -2
- package/src/apps/relay/App.test.ts +6 -5
- package/src/apps/relay/App.ts +2 -2
- package/src/apps/relay/Sponsorships.test.ts +2 -2
- package/src/apps/relay/Sponsorships.ts +24 -1
- package/src/db/Db.test.ts +5 -5
- package/src/db/Db.ts +4 -0
- package/src/db/Schema.ts +1 -1
- package/src/db/tables/billingSettings.test.ts +2 -2
- package/src/db/tables/organizations.test.ts +32 -2
- package/src/db/tables/organizations.ts +28 -0
- package/src/db/tables/requestUsage.ts +3 -23
- package/src/db/tables/sponsoredTransactions.test.ts +60 -2
- package/src/db/tables/sponsoredTransactions.ts +67 -21
- package/src/db/tables/stripeCustomers.test.ts +2 -2
- package/src/internal/Auth.test.ts +63 -10
- package/src/internal/Auth.ts +21 -9
- package/src/internal/Cache.test.ts +19 -0
- package/src/internal/Cache.ts +13 -1
- package/src/internal/EdgeCache.test.ts +40 -0
- package/src/internal/EdgeCache.ts +11 -3
- package/src/internal/FundingQuotes.test.ts +130 -3
- package/src/internal/FundingQuotes.ts +113 -6
- package/src/internal/Log.ts +21 -14
- package/src/internal/RateLimit.test.ts +12 -0
- package/src/internal/RateLimit.ts +4 -4
- package/src/internal/Tidx.test.ts +48 -0
- package/src/internal/Tidx.ts +21 -7
- package/src/internal/Viem.test.ts +46 -0
- package/src/internal/Viem.ts +34 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
-
import { parseAbiItem } from 'viem';
|
|
2
|
+
import { decodeEventLog, encodeEventTopics, parseAbiItem } from 'viem';
|
|
3
3
|
import * as z from 'zod/mini';
|
|
4
4
|
import * as Auth from '../../../internal/Auth.js';
|
|
5
5
|
import * as Cache from '../../../internal/Cache.js';
|
|
@@ -23,6 +23,8 @@ const defaultMaxPerOwner = 100;
|
|
|
23
23
|
* paid-once / deliver-forever mismatch. API-key-owned subscriptions have no TTL.
|
|
24
24
|
*/
|
|
25
25
|
const mppTtlMs = 30 * 24 * 60 * 60 * 1_000;
|
|
26
|
+
const redactedBetterstackToken = '[redacted]';
|
|
27
|
+
const redactedSlackUrl = 'https://hooks.slack.com/…';
|
|
26
28
|
/**
|
|
27
29
|
* The subscribable webhook event types, in alphabetical order. The source of
|
|
28
30
|
* truth for the event-type *set*: the {@link EventType} union and the route zod
|
|
@@ -69,15 +71,13 @@ export var schema;
|
|
|
69
71
|
const Url = z
|
|
70
72
|
.url()
|
|
71
73
|
.check(z.describe('Your HTTPS endpoint where Tempo sends signed event POSTs.'), z.meta({ examples: ['https://example.com/webhooks'] }));
|
|
72
|
-
const SlackUrl = z
|
|
73
|
-
.url()
|
|
74
|
-
.check(z.describe('Your Slack incoming-webhook URL (`https://hooks.slack.com/services/…`).'), z.meta({ examples: ['https://hooks.slack.com/services/T000/B000/XXXXXXXX'] }));
|
|
74
|
+
const SlackUrl = z.url().check(z.refine((url) => url !== redactedSlackUrl, { error: 'A Slack webhook URL is required.' }), z.describe('Your Slack incoming-webhook URL (`https://hooks.slack.com/services/…`).'), z.meta({ examples: ['https://hooks.slack.com/services/T000/B000/XXXXXXXX'] }));
|
|
75
75
|
const BetterstackUrl = z
|
|
76
76
|
.url()
|
|
77
77
|
.check(z.describe('Your Better Stack source ingest host URL (`https://<host>.betterstackdata.com`).'), z.meta({ examples: ['https://s1234567.eu-nbg-2.betterstackdata.com'] }));
|
|
78
|
-
const BetterstackToken = z
|
|
79
|
-
.
|
|
80
|
-
|
|
78
|
+
const BetterstackToken = z.string().check(z.minLength(1), z.refine((token) => token !== redactedBetterstackToken, {
|
|
79
|
+
error: 'A Better Stack source token is required.',
|
|
80
|
+
}), z.describe('Your Better Stack source token (sent as `Authorization: Bearer …`).'), z.meta({ examples: ['FczKcxEhjEDE58dBX7XaeX1q'] }));
|
|
81
81
|
/**
|
|
82
82
|
* Where matched events are delivered: a `url` destination (a signed event POST
|
|
83
83
|
* to your HTTPS endpoint), a `slack` destination (a formatted message posted to
|
|
@@ -101,6 +101,25 @@ export var schema;
|
|
|
101
101
|
}),
|
|
102
102
|
])
|
|
103
103
|
.check(z.describe('Delivery destination: an HTTPS URL, a Slack incoming-webhook URL, or a Better Stack source.'));
|
|
104
|
+
const PublicDestination = z
|
|
105
|
+
.discriminatedUnion('type', [
|
|
106
|
+
z.object({
|
|
107
|
+
type: z.literal('url'),
|
|
108
|
+
url: Url,
|
|
109
|
+
}),
|
|
110
|
+
z.object({
|
|
111
|
+
type: z.literal('slack'),
|
|
112
|
+
url: z.literal(redactedSlackUrl).check(z.describe('Redacted Slack webhook URL.')),
|
|
113
|
+
}),
|
|
114
|
+
z.object({
|
|
115
|
+
token: z
|
|
116
|
+
.literal(redactedBetterstackToken)
|
|
117
|
+
.check(z.describe('Redacted Better Stack source token.')),
|
|
118
|
+
type: z.literal('betterstack'),
|
|
119
|
+
url: BetterstackUrl,
|
|
120
|
+
}),
|
|
121
|
+
])
|
|
122
|
+
.check(z.describe('Delivery destination with bearer credentials redacted.'));
|
|
104
123
|
/**
|
|
105
124
|
* Equality / membership operator for a filterable field. A consumer can pass a
|
|
106
125
|
* bare value (shorthand for exact equality, the common case) or an operator
|
|
@@ -238,9 +257,8 @@ export var schema;
|
|
|
238
257
|
error: 'Pass `signature` or `topic0`, not both.',
|
|
239
258
|
}), z.refine((f) => !f.args || f.signature, {
|
|
240
259
|
error: '`args` requires `signature` to decode the event.',
|
|
241
|
-
}), z.refine((f) =>
|
|
242
|
-
|
|
243
|
-
error: 'Addressless log filters must include an event signature or topic0 plus at least one indexed topic or argument.',
|
|
260
|
+
}), z.refine((f) => hasLogPushdown(f), {
|
|
261
|
+
error: 'Log filters must include a pushdown-capable address or an event/topic0 anchor plus an indexed topic or argument.',
|
|
244
262
|
}));
|
|
245
263
|
/**
|
|
246
264
|
* `block:created` subscription filters. All optional and AND-combined; unlike
|
|
@@ -289,7 +307,7 @@ export var schema;
|
|
|
289
307
|
createdAt: z.iso
|
|
290
308
|
.datetime()
|
|
291
309
|
.check(z.describe('When the subscription was created, as an ISO 8601 timestamp.'), z.meta({ examples: ['2024-01-01T00:00:00Z'] })),
|
|
292
|
-
destination:
|
|
310
|
+
destination: PublicDestination,
|
|
293
311
|
eventType: schema.EventType.check(z.meta({ examples: ['token:transfer'] })),
|
|
294
312
|
expiresAt: z
|
|
295
313
|
.optional(z.iso.datetime())
|
|
@@ -596,7 +614,9 @@ export var schema;
|
|
|
596
614
|
])
|
|
597
615
|
.check(z.describe('Details for creating a webhook subscription.'));
|
|
598
616
|
createWebhook.Response = z
|
|
599
|
-
.
|
|
617
|
+
.object({
|
|
618
|
+
...schema.Subscription.shape,
|
|
619
|
+
destination: Destination,
|
|
600
620
|
secret: z
|
|
601
621
|
.string()
|
|
602
622
|
.check(z.describe('HMAC signing secret (`whsec_…`) used to verify Tempo webhook signatures. It is shown once when you create the webhook, so store it now.'), z.meta({ examples: ['whsec_abc123'] })),
|
|
@@ -1586,6 +1606,8 @@ export function matchesOperator(value, op, kind = 'string') {
|
|
|
1586
1606
|
return o['in'].some((v) => operandEquals(value, v, kind));
|
|
1587
1607
|
if ('not' in o)
|
|
1588
1608
|
return !operandEquals(value, o['not'], kind);
|
|
1609
|
+
if ('eq' in o && kind === 'string')
|
|
1610
|
+
return operandEquals(value, o['eq'], kind);
|
|
1589
1611
|
// Comparison object: AND-combine whichever of eq/gt/gte/lt/lte are present.
|
|
1590
1612
|
const n = toBig(value);
|
|
1591
1613
|
let ok = true;
|
|
@@ -1739,33 +1761,124 @@ function toLogEvent(log, timestamp, signature, event) {
|
|
|
1739
1761
|
event: { name: event.name, signature, topic0: topic0.data },
|
|
1740
1762
|
};
|
|
1741
1763
|
}
|
|
1764
|
+
/** Narrows an exact or membership operator into an RPC filter value. */
|
|
1765
|
+
function pushValue(op) {
|
|
1766
|
+
const value = (() => {
|
|
1767
|
+
if (typeof op !== 'object' || op === null)
|
|
1768
|
+
return op;
|
|
1769
|
+
const operator = op;
|
|
1770
|
+
if ('eq' in operator)
|
|
1771
|
+
return operator['eq'];
|
|
1772
|
+
if (Array.isArray(operator['in']) && operator['in'].length > 0)
|
|
1773
|
+
return operator['in'];
|
|
1774
|
+
return undefined;
|
|
1775
|
+
})();
|
|
1776
|
+
const scalar = (item) => ['bigint', 'boolean', 'number', 'string'].includes(typeof item);
|
|
1777
|
+
if (scalar(value))
|
|
1778
|
+
return value;
|
|
1779
|
+
if (Array.isArray(value) && value.length > 0 && value.every(scalar))
|
|
1780
|
+
return value;
|
|
1781
|
+
return undefined;
|
|
1782
|
+
}
|
|
1783
|
+
/** Narrows an `eq`/`in` operator into a hex RPC filter value. */
|
|
1784
|
+
function pushHex(op) {
|
|
1785
|
+
const value = pushValue(op);
|
|
1786
|
+
if (typeof value === 'string')
|
|
1787
|
+
return value;
|
|
1788
|
+
if (Array.isArray(value) && value.every((item) => typeof item === 'string'))
|
|
1789
|
+
return value;
|
|
1790
|
+
return undefined;
|
|
1791
|
+
}
|
|
1742
1792
|
/** Narrows an `eq`/`in` address operator into the `getLogs` address pushdown. */
|
|
1743
1793
|
function pushAddress(op) {
|
|
1744
|
-
|
|
1794
|
+
return pushHex(op);
|
|
1795
|
+
}
|
|
1796
|
+
/** Parses a human-readable event signature without letting refinements throw. */
|
|
1797
|
+
function parseEvent(signature) {
|
|
1798
|
+
if (!signature)
|
|
1745
1799
|
return undefined;
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1800
|
+
try {
|
|
1801
|
+
const item = parseAbiItem(signature);
|
|
1802
|
+
return item.type === 'event' ? item : undefined;
|
|
1803
|
+
}
|
|
1804
|
+
catch {
|
|
1805
|
+
return undefined;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
/** Returns exact indexed arguments that viem can push into `eth_getLogs`. */
|
|
1809
|
+
function pushEventArgs(args, event) {
|
|
1810
|
+
const pushed = {};
|
|
1811
|
+
for (const [name, op] of Object.entries(args ?? {})) {
|
|
1812
|
+
const input = event.inputs.find((item) => item.indexed && item.name === name);
|
|
1813
|
+
const value = pushValue(op);
|
|
1814
|
+
if (input && value !== undefined)
|
|
1815
|
+
pushed[name] = value;
|
|
1816
|
+
}
|
|
1817
|
+
return pushed;
|
|
1818
|
+
}
|
|
1819
|
+
/** Checks that the accepted filter has a selective `eth_getLogs` representation. */
|
|
1820
|
+
function hasLogPushdown(f) {
|
|
1821
|
+
if (pushAddress(f.address) !== undefined)
|
|
1822
|
+
return true;
|
|
1823
|
+
const secondaryTopic = [f.topic1, f.topic2, f.topic3].some((topic) => pushHex(topic) !== undefined);
|
|
1824
|
+
const event = parseEvent(f.signature);
|
|
1825
|
+
if (event && !event.anonymous)
|
|
1826
|
+
return secondaryTopic || Object.keys(pushEventArgs(f.args, event)).length > 0;
|
|
1827
|
+
return pushHex(f.topic0) !== undefined && secondaryTopic;
|
|
1828
|
+
}
|
|
1829
|
+
/** Builds raw topic filters, preserving null wildcards between constrained positions. */
|
|
1830
|
+
function pushTopics(f, event) {
|
|
1831
|
+
const topics = [
|
|
1832
|
+
event ? encodeEventTopics({ abi: [event] })[0] : pushHex(f.topic0),
|
|
1833
|
+
pushHex(f.topic1),
|
|
1834
|
+
pushHex(f.topic2),
|
|
1835
|
+
pushHex(f.topic3),
|
|
1836
|
+
];
|
|
1837
|
+
while (topics.at(-1) === undefined)
|
|
1838
|
+
topics.pop();
|
|
1839
|
+
return topics.map((topic) => topic ?? null);
|
|
1840
|
+
}
|
|
1841
|
+
/** Converts one raw JSON-RPC log into the viem-shaped scanner input. */
|
|
1842
|
+
function fromRpcLog(log) {
|
|
1843
|
+
return {
|
|
1844
|
+
address: log.address,
|
|
1845
|
+
blockNumber: log.blockNumber === null ? null : BigInt(log.blockNumber),
|
|
1846
|
+
data: log.data,
|
|
1847
|
+
logIndex: Value.hexToNumber(log.logIndex) ?? null,
|
|
1848
|
+
topics: log.topics,
|
|
1849
|
+
transactionHash: log.transactionHash,
|
|
1850
|
+
transactionIndex: Value.hexToNumber(log.transactionIndex) ?? null,
|
|
1851
|
+
};
|
|
1852
|
+
}
|
|
1853
|
+
/** Best-effort decodes a raw log using the subscription event. */
|
|
1854
|
+
function decodeScanLog(log, event) {
|
|
1855
|
+
try {
|
|
1856
|
+
const decoded = decodeEventLog({
|
|
1857
|
+
abi: [event],
|
|
1858
|
+
data: log.data,
|
|
1859
|
+
strict: false,
|
|
1860
|
+
topics: log.topics,
|
|
1861
|
+
});
|
|
1862
|
+
return {
|
|
1863
|
+
...log,
|
|
1864
|
+
args: decoded.args,
|
|
1865
|
+
eventName: decoded.eventName,
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
1868
|
+
catch {
|
|
1869
|
+
return log;
|
|
1754
1870
|
}
|
|
1755
|
-
// `not`/range forms can't be pushed; widen here, re-check in JS.
|
|
1756
|
-
return undefined;
|
|
1757
1871
|
}
|
|
1758
1872
|
/**
|
|
1759
|
-
* Scans contract event logs over the confirmed window via
|
|
1760
|
-
* then re-checks **every** filter in JS
|
|
1761
|
-
* `not`, ranges,
|
|
1873
|
+
* Scans contract event logs over the confirmed window via `eth_getLogs`,
|
|
1874
|
+
* then re-checks **every** filter in JS. Operators the RPC cannot express
|
|
1875
|
+
* (`not`, ranges, non-indexed `args`) still apply. Two modes:
|
|
1762
1876
|
* - **raw** (no `signature`): `topic0..3` are matched directly.
|
|
1763
|
-
* - **decoded** (`signature` present):
|
|
1764
|
-
*
|
|
1765
|
-
* decodes `args` — which the JS pass then matches by name.
|
|
1877
|
+
* - **decoded** (`signature` present): the selector, raw topics, and supported
|
|
1878
|
+
* indexed `args` are pushed down before the JS pass matches decoded values.
|
|
1766
1879
|
*
|
|
1767
|
-
*
|
|
1768
|
-
* re-checked in JS over the narrow window.
|
|
1880
|
+
* Exact and membership address/topic operators are pushed down to the node;
|
|
1881
|
+
* all operators are re-checked in JS over the narrow window.
|
|
1769
1882
|
*/
|
|
1770
1883
|
async function scanLogs(options) {
|
|
1771
1884
|
const { cache, client, cursor, filters, maxBlocks, safeBlock } = options;
|
|
@@ -1773,26 +1886,35 @@ async function scanLogs(options) {
|
|
|
1773
1886
|
const window = scanWindow(cursor, safeBlock, maxBlocks);
|
|
1774
1887
|
if (!window)
|
|
1775
1888
|
return { items: [], scannedThrough: undefined };
|
|
1776
|
-
const event =
|
|
1777
|
-
if (
|
|
1889
|
+
const event = parseEvent(f.signature);
|
|
1890
|
+
if (f.signature && (!event || !/^[A-Za-z_]\w*$/.test(event.name)))
|
|
1778
1891
|
throw new Webhooks.InvalidFilterError('log:emitted', [
|
|
1779
1892
|
{ message: 'Unsupported event signature.', path: ['signature'] },
|
|
1780
1893
|
]);
|
|
1781
1894
|
const address = pushAddress(f.address);
|
|
1782
1895
|
const fromBlock = BigInt(window.from);
|
|
1783
1896
|
const toBlock = BigInt(window.to);
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1897
|
+
const topics = pushTopics(f, event);
|
|
1898
|
+
const hasRawTopics = topics.slice(1).some((topic) => topic !== null);
|
|
1899
|
+
const args = event ? pushEventArgs(f.args, event) : {};
|
|
1900
|
+
const logs = (!event || hasRawTopics
|
|
1901
|
+
? (await rpc(client, 'eth_getLogs', [
|
|
1902
|
+
{
|
|
1903
|
+
...(address ? { address } : {}),
|
|
1904
|
+
fromBlock: blockTag(window.from),
|
|
1905
|
+
...(topics.length > 0 ? { topics } : {}),
|
|
1906
|
+
toBlock: blockTag(window.to),
|
|
1907
|
+
},
|
|
1908
|
+
]))
|
|
1909
|
+
.map(fromRpcLog)
|
|
1910
|
+
.map((log) => (event ? decodeScanLog(log, event) : log))
|
|
1911
|
+
: await client.getLogs({
|
|
1786
1912
|
...(address ? { address } : {}),
|
|
1913
|
+
...(Object.keys(args).length > 0 ? { args: args } : {}),
|
|
1787
1914
|
event,
|
|
1788
1915
|
fromBlock,
|
|
1789
1916
|
strict: false,
|
|
1790
1917
|
toBlock,
|
|
1791
|
-
})
|
|
1792
|
-
: await client.getLogs({
|
|
1793
|
-
...(address ? { address } : {}),
|
|
1794
|
-
fromBlock,
|
|
1795
|
-
toBlock,
|
|
1796
1918
|
}));
|
|
1797
1919
|
logs.sort((a, b) => {
|
|
1798
1920
|
const ab = Number(a.blockNumber ?? 0n);
|
|
@@ -2077,7 +2199,7 @@ function toPublic(subscription) {
|
|
|
2077
2199
|
chainId: subscription.chainId,
|
|
2078
2200
|
...(subscription.context === undefined ? {} : { context: subscription.context }),
|
|
2079
2201
|
createdAt: subscription.createdAt,
|
|
2080
|
-
destination: subscription.destination,
|
|
2202
|
+
destination: redactDestination(subscription.destination),
|
|
2081
2203
|
eventType: subscription.eventType,
|
|
2082
2204
|
...(subscription.expiresAt === undefined ? {} : { expiresAt: subscription.expiresAt }),
|
|
2083
2205
|
failureCount: subscription.failureCount,
|
|
@@ -2092,7 +2214,19 @@ function toPublic(subscription) {
|
|
|
2092
2214
|
}
|
|
2093
2215
|
/** Public read shape plus the one-time signing secret (creation only). */
|
|
2094
2216
|
function toCreated(subscription) {
|
|
2095
|
-
return {
|
|
2217
|
+
return {
|
|
2218
|
+
...toPublic(subscription),
|
|
2219
|
+
destination: subscription.destination,
|
|
2220
|
+
secret: subscription.secret,
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2223
|
+
/** Redacts bearer credentials from the destination returned by read endpoints. */
|
|
2224
|
+
function redactDestination(destination) {
|
|
2225
|
+
if (destination.type === 'slack')
|
|
2226
|
+
return { ...destination, url: redactedSlackUrl };
|
|
2227
|
+
if (destination.type === 'betterstack')
|
|
2228
|
+
return { ...destination, token: redactedBetterstackToken };
|
|
2229
|
+
return destination;
|
|
2096
2230
|
}
|
|
2097
2231
|
function mutationError(c, cause) {
|
|
2098
2232
|
if (cause instanceof Webhooks.InvalidUrlError)
|