tapimo 0.5.3 → 0.7.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 +15830 -7220
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +9 -1
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +4 -0
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +5 -0
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +1011 -412
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +4 -0
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +2 -1
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/early-access.d.ts +148 -0
- package/dist/admin/apps/early-access.d.ts.map +1 -0
- package/dist/admin/apps/early-access.js +133 -0
- package/dist/admin/apps/early-access.js.map +1 -0
- package/dist/admin/apps/organizations.d.ts +124 -1
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +97 -6
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +526 -1
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +214 -1
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +95 -75
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +20 -0
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +18 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +36 -7
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +6260 -4924
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +11 -6
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.js +194 -16
- package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +71 -0
- package/dist/apps/data/FxOracle.d.ts.map +1 -0
- package/dist/apps/data/FxOracle.js +97 -0
- package/dist/apps/data/FxOracle.js.map +1 -0
- package/dist/apps/data/index.d.ts +1 -0
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +1 -0
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +3599 -1382
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +250 -88
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +872 -251
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/addresses.js +11 -9
- package/dist/apps/data/routes/addresses.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +77 -26
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +88 -45
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +39 -39
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/exchanges.d.ts +856 -105
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +518 -76
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +81 -67
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +76 -91
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/funding.d.ts +80 -36
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +65 -31
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +392 -315
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +152 -77
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +167 -174
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +15 -13
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +277 -536
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +96 -77
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +157 -81
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +272 -130
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +307 -0
- package/dist/apps/data/routes/valuation.d.ts.map +1 -0
- package/dist/apps/data/routes/valuation.js +292 -0
- package/dist/apps/data/routes/valuation.js.map +1 -0
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +7 -5
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +103 -123
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +124 -25
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/index.d.ts +2 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +2 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +8554 -1692
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +12 -1
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +7 -0
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +17 -3
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +157 -162
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +31 -23
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +232 -0
- package/dist/apps/management/routes/faucet.d.ts.map +1 -0
- package/dist/apps/management/routes/faucet.js +154 -0
- package/dist/apps/management/routes/faucet.js.map +1 -0
- package/dist/apps/management/routes/invitations.d.ts +60 -60
- package/dist/apps/management/routes/invite-links.d.ts +49 -20
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +26 -1
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +6 -6
- package/dist/apps/management/routes/orgs.d.ts +42 -42
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +5 -0
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +44 -44
- package/dist/apps/management/routes/usage.d.ts +3 -0
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +4 -0
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
- package/dist/apps/management/routes/verified-token-requests.js +271 -0
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
- package/dist/apps/management/routes/webhooks.d.ts +6977 -0
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
- package/dist/apps/management/routes/webhooks.js +573 -0
- package/dist/apps/management/routes/webhooks.js.map +1 -0
- package/dist/apps/mpp/App.d.ts +363 -0
- package/dist/apps/mpp/App.d.ts.map +1 -0
- package/dist/apps/mpp/App.js +72 -0
- package/dist/apps/mpp/App.js.map +1 -0
- package/dist/apps/mpp/Mpp.d.ts +178 -0
- package/dist/apps/mpp/Mpp.d.ts.map +1 -0
- package/dist/apps/mpp/Mpp.js +183 -0
- package/dist/apps/mpp/Mpp.js.map +1 -0
- package/dist/apps/mpp/index.d.ts +3 -0
- package/dist/apps/mpp/index.d.ts.map +1 -0
- package/dist/apps/mpp/index.js +3 -0
- package/dist/apps/mpp/index.js.map +1 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +56 -9
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/db/Db.d.ts +6 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +110 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +53 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -0
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earlyAccess.d.ts +50 -0
- package/dist/db/tables/earlyAccess.d.ts.map +1 -0
- package/dist/db/tables/earlyAccess.js +63 -0
- package/dist/db/tables/earlyAccess.js.map +1 -0
- package/dist/db/tables/enabledBillingSources.d.ts +73 -0
- package/dist/db/tables/enabledBillingSources.d.ts.map +1 -0
- package/dist/db/tables/enabledBillingSources.js +69 -0
- package/dist/db/tables/enabledBillingSources.js.map +1 -0
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/invitations.js +3 -0
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/inviteLinks.d.ts +10 -2
- package/dist/db/tables/inviteLinks.d.ts.map +1 -1
- package/dist/db/tables/inviteLinks.js +10 -1
- package/dist/db/tables/inviteLinks.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +5 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +13 -2
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +2 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokenRequests.js +120 -0
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +16 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +1 -16
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +17 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +37 -5
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +11 -2
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +14 -47
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/FundingQuotes.d.ts +147 -47
- package/dist/internal/FundingQuotes.d.ts.map +1 -1
- package/dist/internal/FundingQuotes.js +119 -33
- package/dist/internal/FundingQuotes.js.map +1 -1
- package/dist/internal/Log.d.ts +37 -5
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +52 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +24 -0
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +2 -2
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +3 -0
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +2 -2
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +12 -4
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +14 -5
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +23 -5
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Value.d.ts +18 -0
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js +11 -1
- package/dist/internal/Value.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +10 -1
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +24 -3
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +34 -8
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +7 -2
- package/src/App.test.ts +9 -4
- package/src/App.ts +23 -3
- package/src/Client.test-d.ts +733 -20
- package/src/Scope.ts +5 -0
- package/src/admin/App.test.ts +4 -0
- package/src/admin/App.ts +4 -0
- package/src/admin/apps/early-access.test.ts +125 -0
- package/src/admin/apps/early-access.ts +176 -0
- package/src/admin/apps/organizations.test.ts +86 -2
- package/src/admin/apps/organizations.ts +155 -31
- package/src/admin/apps/scopes.test.ts +5 -0
- package/src/admin/apps/verified-tokens.test.ts +201 -0
- package/src/admin/apps/verified-tokens.ts +532 -286
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/lib/early-access.ts +63 -0
- package/src/admin/ui/src/lib/organizations.test.ts +81 -1
- package/src/admin/ui/src/lib/organizations.ts +92 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
- package/src/admin/ui/src/routeTree.gen.ts +33 -2
- package/src/admin/ui/src/routes/__root.tsx +2 -1
- package/src/admin/ui/src/routes/api-keys.tsx +1 -1
- package/src/admin/ui/src/routes/early-access.tsx +162 -0
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +103 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
- package/src/admin/ui.generated.ts +95 -94
- package/src/analytics/Analytics.test.ts +83 -0
- package/src/analytics/Analytics.ts +20 -0
- package/src/analytics/tables/requestEvents.ts +60 -7
- package/src/apps/composition.test.ts +11 -2
- package/src/apps/data/App.test.ts +1 -1
- package/src/apps/data/App.ts +22 -14
- package/src/apps/data/FundingQuoteProviders.test.ts +297 -4
- package/src/apps/data/FundingQuoteProviders.ts +255 -29
- package/src/apps/data/FxOracle.test.ts +118 -0
- package/src/apps/data/FxOracle.ts +153 -0
- package/src/apps/data/index.ts +1 -0
- package/src/apps/data/routes/activities.test.ts +177 -3
- package/src/apps/data/routes/activities.ts +441 -132
- package/src/apps/data/routes/addresses.ts +19 -9
- package/src/apps/data/routes/balances.test.ts +148 -11
- package/src/apps/data/routes/balances.ts +140 -51
- package/src/apps/data/routes/exchanges.test.ts +544 -9
- package/src/apps/data/routes/exchanges.ts +690 -103
- package/src/apps/data/routes/fee-amm.test.ts +47 -23
- package/src/apps/data/routes/fee-amm.ts +98 -119
- package/src/apps/data/routes/funding.test.ts +113 -8
- package/src/apps/data/routes/funding.ts +77 -51
- package/src/apps/data/routes/receipts.test.ts +129 -23
- package/src/apps/data/routes/receipts.ts +205 -100
- package/src/apps/data/routes/tokens.test.ts +43 -0
- package/src/apps/data/routes/tokens.ts +28 -13
- package/src/apps/data/routes/transactions.test.ts +72 -19
- package/src/apps/data/routes/transactions.ts +162 -92
- package/src/apps/data/routes/transfers.test.ts +341 -31
- package/src/apps/data/routes/transfers.ts +358 -158
- package/src/apps/data/routes/valuation.test.ts +437 -0
- package/src/apps/data/routes/valuation.ts +423 -0
- package/src/apps/data/routes/verified-tokens.ts +14 -2
- package/src/apps/data/routes/webhooks.test.ts +56 -8
- package/src/apps/data/routes/webhooks.ts +144 -27
- package/src/apps/index.ts +2 -1
- package/src/apps/management/App.ts +13 -0
- package/src/apps/management/routes/api-keys.test.ts +14 -0
- package/src/apps/management/routes/api-keys.ts +27 -3
- package/src/apps/management/routes/billing.test.ts +152 -20
- package/src/apps/management/routes/billing.ts +34 -18
- package/src/apps/management/routes/faucet.test.ts +87 -0
- package/src/apps/management/routes/faucet.ts +201 -0
- package/src/apps/management/routes/invite-links.test.ts +117 -0
- package/src/apps/management/routes/invite-links.ts +43 -1
- package/src/apps/management/routes/me.test.ts +9 -99
- package/src/apps/management/routes/orgs.test.ts +45 -2
- package/src/apps/management/routes/orgs.ts +6 -0
- package/src/apps/management/routes/scopes.test.ts +1 -0
- package/src/apps/management/routes/usage.test.ts +6 -0
- package/src/apps/management/routes/usage.ts +7 -0
- package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
- package/src/apps/management/routes/verified-token-requests.ts +397 -0
- package/src/apps/management/routes/webhooks.test.ts +426 -0
- package/src/apps/management/routes/webhooks.ts +672 -0
- package/src/apps/mpp/App.ts +86 -0
- package/src/apps/mpp/Mpp.test.ts +193 -0
- package/src/apps/mpp/Mpp.ts +353 -0
- package/src/apps/mpp/index.ts +2 -0
- package/src/apps/mpp/internal/Adapter.ts +11 -0
- package/src/apps/mpp/internal/Error.ts +9 -0
- package/src/apps/mpp/internal/Idempotency.ts +7 -0
- package/src/apps/mpp/internal/Screening.ts +10 -0
- package/src/apps/relay/App.test.ts +88 -6
- package/src/apps/relay/App.ts +61 -9
- package/src/db/Db.test.ts +19 -0
- package/src/db/Db.ts +125 -0
- package/src/db/Schema.ts +68 -0
- package/src/db/tables/earlyAccess.ts +86 -0
- package/src/db/tables/enabledBillingSources.test.ts +303 -0
- package/src/db/tables/enabledBillingSources.ts +118 -0
- package/src/db/tables/invitations.ts +3 -0
- package/src/db/tables/inviteLinks.ts +22 -3
- package/src/db/tables/organizations.test.ts +103 -0
- package/src/db/tables/organizations.ts +18 -2
- package/src/db/tables/sponsoredTransactions.ts +4 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
- package/src/db/tables/verifiedTokenRequests.ts +182 -0
- package/src/db/tables/webhookSubscriptions.ts +31 -0
- package/src/handlers/internal/utils.ts +22 -6
- package/src/handlers/relay.errors.test.ts +153 -0
- package/src/handlers/relay.ts +42 -7
- package/src/internal/Auth.test.ts +3 -3
- package/src/internal/Auth.ts +15 -47
- package/src/internal/FundingQuotes.test.ts +161 -6
- package/src/internal/FundingQuotes.ts +141 -39
- package/src/internal/Log.test-d.ts +21 -0
- package/src/internal/Log.test.ts +141 -0
- package/src/internal/Log.ts +93 -6
- package/src/internal/MetricSink.test.ts +215 -0
- package/src/internal/MetricSink.ts +24 -0
- package/src/internal/OpenApi.ts +3 -0
- package/src/internal/Response.test.ts +28 -0
- package/src/internal/Response.ts +12 -4
- package/src/internal/Schema.ts +50 -5
- package/src/internal/Value.test.ts +20 -0
- package/src/internal/Value.ts +24 -1
- package/src/internal/VerifiedTokens.ts +9 -1
- package/src/internal/Webhooks.test.ts +140 -0
- package/src/internal/Webhooks.ts +53 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Hono, type Context } from 'hono'
|
|
2
2
|
import { Address, Hex } from 'ox'
|
|
3
3
|
import { type Log, parseEventLogs, zeroAddress } from 'viem'
|
|
4
|
+
import { token as viem_Token } from 'viem/actions'
|
|
4
5
|
import { Abis, Addresses } from 'viem/tempo'
|
|
5
6
|
import * as z from 'zod/mini'
|
|
6
7
|
|
|
@@ -17,12 +18,21 @@ import type * as Tidx from '../../../internal/Tidx.js'
|
|
|
17
18
|
import * as Timing from '../../../internal/Timing.js'
|
|
18
19
|
import * as Ttl from '../../../internal/Ttl.js'
|
|
19
20
|
import * as Value from '../../../internal/Value.js'
|
|
21
|
+
import * as VerifiedTokens from '../../../internal/VerifiedTokens.js'
|
|
22
|
+
import * as FxOracle from '../FxOracle.js'
|
|
20
23
|
import * as Tokens from './tokens.js'
|
|
21
24
|
import * as Transfers from './transfers.js'
|
|
25
|
+
import * as Valuation from './valuation.js'
|
|
22
26
|
|
|
23
27
|
/** Example transaction hash surfaced in OpenAPI docs. */
|
|
24
28
|
const exampleHash = '0x4845ae2098724ab26a5d89370dce5124d044be6a5acc164afc348662de67d474'
|
|
25
29
|
|
|
30
|
+
const tokenFields = ['token.logoUri', 'token.verified'] as const
|
|
31
|
+
|
|
32
|
+
// TIP-20 tokens live at deterministic `0x20c0…` addresses. Other contracts
|
|
33
|
+
// can emit the same `Transfer` signature but do not expose TIP-20 metadata.
|
|
34
|
+
const tip20AddressPrefix = '0x20c0'
|
|
35
|
+
|
|
26
36
|
/** Zod schemas owned by the activity handlers. */
|
|
27
37
|
export namespace schema {
|
|
28
38
|
/** A signer: the literal `self`, or the access-key address that signed. */
|
|
@@ -32,20 +42,50 @@ export namespace schema {
|
|
|
32
42
|
z.describe('Who signed the activity: `self`, or the access-key address used to sign it.'),
|
|
33
43
|
)
|
|
34
44
|
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*/
|
|
41
|
-
export const Token = Transfers.schema.SourceToken
|
|
45
|
+
/** A token with required RPC metadata and optional curated fields. */
|
|
46
|
+
export const Token = Schema.describe(
|
|
47
|
+
Tokens.schema.TokenReference,
|
|
48
|
+
'A token referenced by an activity item.',
|
|
49
|
+
)
|
|
42
50
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
/** A token amount carrying its nominal value in the requested denomination. */
|
|
52
|
+
const ValuedAmount = z.extend(Schema.TokenAmount, {
|
|
53
|
+
valuation: z
|
|
54
|
+
.optional(z.nullable(Valuation.schema.Value))
|
|
55
|
+
.check(
|
|
56
|
+
z.describe(
|
|
57
|
+
'The amount’s nominal value in the requested `denomination`. `null` when the token is ' +
|
|
58
|
+
'unverified, its display currency has no rate, or rates were unavailable.',
|
|
59
|
+
),
|
|
60
|
+
),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
/** Self-contained amount for a destination token. */
|
|
64
|
+
const DestinationAmount = ValuedAmount.check(
|
|
65
|
+
z.describe('Amount associated with `destinationToken`.'),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
/** Self-contained amount for a refunded token. */
|
|
69
|
+
const RefundAmount = ValuedAmount.check(z.describe('Amount associated with `refund`.'))
|
|
70
|
+
|
|
71
|
+
/** Self-contained amount for a source token. */
|
|
72
|
+
const SourceAmount = ValuedAmount.check(z.describe('Amount associated with `sourceToken`.'))
|
|
73
|
+
|
|
74
|
+
/** Page-level resources: valuation rate provenance. */
|
|
75
|
+
export const Meta = z
|
|
76
|
+
.object({
|
|
77
|
+
pricing: z
|
|
78
|
+
.optional(Valuation.schema.Pricing)
|
|
79
|
+
.check(
|
|
80
|
+
z.describe(
|
|
81
|
+
'Rate provenance for amount valuations. Present when conversion rates were ' +
|
|
82
|
+
'consulted; absent when every value was identity-valued or rates were unavailable.',
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
})
|
|
86
|
+
.check(z.describe('Page-level resources attached to this response.'))
|
|
87
|
+
|
|
88
|
+
/** A token transfer with subject-relative direction and signer fields. */
|
|
49
89
|
export const Transfer = z
|
|
50
90
|
.object({
|
|
51
91
|
attribution: z
|
|
@@ -64,11 +104,18 @@ export namespace schema {
|
|
|
64
104
|
z.describe('Block number where this transfer was included.'),
|
|
65
105
|
z.meta({ examples: [12345678] }),
|
|
66
106
|
),
|
|
107
|
+
destinationAmount: z
|
|
108
|
+
.optional(DestinationAmount)
|
|
109
|
+
.check(
|
|
110
|
+
z.describe(
|
|
111
|
+
'Amount delivered to the recipient for a cross-token transfer. Omitted with `destinationToken` for a same-token transfer.',
|
|
112
|
+
),
|
|
113
|
+
),
|
|
67
114
|
destinationToken: z
|
|
68
115
|
.optional(Token)
|
|
69
116
|
.check(
|
|
70
117
|
z.describe(
|
|
71
|
-
'Token
|
|
118
|
+
'Token delivered to the recipient when it differs from the source token. Omitted for a same-token transfer.',
|
|
72
119
|
),
|
|
73
120
|
),
|
|
74
121
|
direction: z
|
|
@@ -90,7 +137,8 @@ export namespace schema {
|
|
|
90
137
|
'For outbound transfers, who signed it: `self` or the access-key address. Omitted for inbound transfers.',
|
|
91
138
|
),
|
|
92
139
|
),
|
|
93
|
-
|
|
140
|
+
sourceAmount: SourceAmount,
|
|
141
|
+
sourceToken: Token.check(z.describe('Token that moved in the transfer.')),
|
|
94
142
|
timestamp: z
|
|
95
143
|
.iso.datetime()
|
|
96
144
|
.check(z.describe('Block timestamp for the transfer.'), z.meta({ examples: ['2024-01-01T00:00:00Z'] })), // prettier-ignore
|
|
@@ -98,7 +146,16 @@ export namespace schema {
|
|
|
98
146
|
z.describe('Transaction hash that contains this transfer.'),
|
|
99
147
|
),
|
|
100
148
|
})
|
|
101
|
-
.check(
|
|
149
|
+
.check(
|
|
150
|
+
z.refine(
|
|
151
|
+
(data) => (data.destinationToken === undefined) === (data.destinationAmount === undefined),
|
|
152
|
+
{
|
|
153
|
+
error: '`destinationAmount` and `destinationToken` must be returned together.',
|
|
154
|
+
path: ['destinationAmount'],
|
|
155
|
+
},
|
|
156
|
+
),
|
|
157
|
+
z.describe('One token transfer involving the requested address.'),
|
|
158
|
+
)
|
|
102
159
|
|
|
103
160
|
/**
|
|
104
161
|
* One transaction log, decoded into a known Tempo event when possible. The
|
|
@@ -193,9 +250,7 @@ export namespace schema {
|
|
|
193
250
|
.object({
|
|
194
251
|
...base,
|
|
195
252
|
data: Transfer.check(
|
|
196
|
-
z.describe(
|
|
197
|
-
'Transfer details, using the `/transfers` shape plus feed-only fields such as direction and signer.',
|
|
198
|
-
),
|
|
253
|
+
z.describe('Transfer details with feed-relative direction and signer fields.'),
|
|
199
254
|
),
|
|
200
255
|
type: z
|
|
201
256
|
.literal('transfer')
|
|
@@ -208,7 +263,8 @@ export namespace schema {
|
|
|
208
263
|
data: z
|
|
209
264
|
.object({
|
|
210
265
|
recipient: Schema.Address.check(z.describe('Address that received the transfer.')),
|
|
211
|
-
|
|
266
|
+
sourceAmount: SourceAmount,
|
|
267
|
+
sourceToken: Token.check(z.describe('Token that was minted.')),
|
|
212
268
|
})
|
|
213
269
|
.check(z.describe('A token mint activity.')),
|
|
214
270
|
type: z
|
|
@@ -223,7 +279,8 @@ export namespace schema {
|
|
|
223
279
|
.object({
|
|
224
280
|
sender: Schema.Address.check(z.describe('Address whose token balance was burned.')),
|
|
225
281
|
signer: Signer,
|
|
226
|
-
|
|
282
|
+
sourceAmount: SourceAmount,
|
|
283
|
+
sourceToken: Token.check(z.describe('Token that was burned.')),
|
|
227
284
|
})
|
|
228
285
|
.check(z.describe('A token burn activity.')),
|
|
229
286
|
type: z
|
|
@@ -236,8 +293,10 @@ export namespace schema {
|
|
|
236
293
|
...base,
|
|
237
294
|
data: z
|
|
238
295
|
.object({
|
|
296
|
+
destinationAmount: DestinationAmount,
|
|
239
297
|
destinationToken: Token.check(z.describe('Token the address received in the swap.')),
|
|
240
298
|
signer: Signer,
|
|
299
|
+
sourceAmount: SourceAmount,
|
|
241
300
|
sourceToken: Token.check(z.describe('Token the address sent into the swap.')),
|
|
242
301
|
})
|
|
243
302
|
.check(
|
|
@@ -256,9 +315,8 @@ export namespace schema {
|
|
|
256
315
|
data: z
|
|
257
316
|
.object({
|
|
258
317
|
signer: Signer,
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
),
|
|
318
|
+
sourceAmount: SourceAmount,
|
|
319
|
+
sourceToken: Token.check(z.describe('Token approved for spending.')),
|
|
262
320
|
spender: Schema.Address.check(
|
|
263
321
|
z.describe('Address allowed to spend the approved amount.'),
|
|
264
322
|
),
|
|
@@ -277,9 +335,18 @@ export namespace schema {
|
|
|
277
335
|
refund: z
|
|
278
336
|
.optional(Token)
|
|
279
337
|
.check(z.describe('Token refunded to the address when the session closed, if any.')),
|
|
338
|
+
refundAmount: z
|
|
339
|
+
.optional(RefundAmount)
|
|
340
|
+
.check(z.describe('Amount refunded to the address when the session closed, if any.')),
|
|
280
341
|
signer: Signer,
|
|
281
342
|
})
|
|
282
|
-
.check(
|
|
343
|
+
.check(
|
|
344
|
+
z.refine((data) => (data.refund === undefined) === (data.refundAmount === undefined), {
|
|
345
|
+
error: '`refundAmount` and `refund` must be returned together.',
|
|
346
|
+
path: ['refundAmount'],
|
|
347
|
+
}),
|
|
348
|
+
z.describe('A payment-channel session close activity.'),
|
|
349
|
+
),
|
|
283
350
|
type: z
|
|
284
351
|
.literal('session-closed')
|
|
285
352
|
.check(z.describe('Activity type that tells you which `data` shape this entry uses.')),
|
|
@@ -354,7 +421,8 @@ export namespace schema {
|
|
|
354
421
|
z.describe('Address whose blocked balance was burned by policy.'),
|
|
355
422
|
),
|
|
356
423
|
signer: Signer,
|
|
357
|
-
|
|
424
|
+
sourceAmount: SourceAmount,
|
|
425
|
+
sourceToken: Token.check(z.describe('Token that was burned.')),
|
|
358
426
|
})
|
|
359
427
|
.check(
|
|
360
428
|
z.describe(
|
|
@@ -377,9 +445,8 @@ export namespace schema {
|
|
|
377
445
|
),
|
|
378
446
|
payer: Schema.Address.check(z.describe('Address that funds the channel.')),
|
|
379
447
|
signer: Signer,
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
),
|
|
448
|
+
sourceAmount: SourceAmount,
|
|
449
|
+
sourceToken: Token.check(z.describe('Token locked into the channel.')),
|
|
383
450
|
})
|
|
384
451
|
.check(z.describe('A payment channel was opened and funded.')),
|
|
385
452
|
type: z
|
|
@@ -394,7 +461,8 @@ export namespace schema {
|
|
|
394
461
|
.object({
|
|
395
462
|
channelId: Schema.Hex.check(z.describe('Identifier of the payment channel.')),
|
|
396
463
|
signer: Signer,
|
|
397
|
-
|
|
464
|
+
sourceAmount: SourceAmount,
|
|
465
|
+
sourceToken: Token.check(z.describe('Token added to the channel deposit.')),
|
|
398
466
|
})
|
|
399
467
|
.check(z.describe('A payment channel deposit was topped up.')),
|
|
400
468
|
type: z
|
|
@@ -411,7 +479,8 @@ export namespace schema {
|
|
|
411
479
|
payee: Schema.Address.check(z.describe('Address that received the settled payment.')),
|
|
412
480
|
payer: Schema.Address.check(z.describe('Address that funded the channel.')),
|
|
413
481
|
signer: Signer,
|
|
414
|
-
|
|
482
|
+
sourceAmount: SourceAmount,
|
|
483
|
+
sourceToken: Token.check(z.describe('Token paid out in this settlement.')),
|
|
415
484
|
})
|
|
416
485
|
.check(z.describe('An incremental payment-channel settlement to the payee.')),
|
|
417
486
|
type: z
|
|
@@ -431,13 +500,30 @@ export namespace schema {
|
|
|
431
500
|
payer: Schema.Address.check(z.describe('Address that funded the channel.')),
|
|
432
501
|
refund: z
|
|
433
502
|
.optional(Token)
|
|
434
|
-
.check(z.describe('Token
|
|
503
|
+
.check(z.describe('Token refunded to the payer on close, if any.')),
|
|
504
|
+
refundAmount: z
|
|
505
|
+
.optional(RefundAmount)
|
|
506
|
+
.check(z.describe('Amount refunded to the payer on close, if any.')),
|
|
435
507
|
signer: Signer,
|
|
508
|
+
sourceAmount: z
|
|
509
|
+
.optional(SourceAmount)
|
|
510
|
+
.check(z.describe('Final amount paid to the payee on close, if any.')),
|
|
436
511
|
sourceToken: z
|
|
437
512
|
.optional(Token)
|
|
438
|
-
.check(z.describe('Token
|
|
513
|
+
.check(z.describe('Token paid out to the payee on close, if any.')),
|
|
439
514
|
})
|
|
440
515
|
.check(
|
|
516
|
+
z.refine((data) => (data.refund === undefined) === (data.refundAmount === undefined), {
|
|
517
|
+
error: '`refundAmount` and `refund` must be returned together.',
|
|
518
|
+
path: ['refundAmount'],
|
|
519
|
+
}),
|
|
520
|
+
z.refine(
|
|
521
|
+
(data) => (data.sourceToken === undefined) === (data.sourceAmount === undefined),
|
|
522
|
+
{
|
|
523
|
+
error: '`sourceAmount` and `sourceToken` must be returned together.',
|
|
524
|
+
path: ['sourceAmount'],
|
|
525
|
+
},
|
|
526
|
+
),
|
|
441
527
|
z.describe(
|
|
442
528
|
'A payment channel was closed, paying out the payee and refunding the payer.',
|
|
443
529
|
),
|
|
@@ -475,7 +561,8 @@ export namespace schema {
|
|
|
475
561
|
.enum(['bid', 'ask'])
|
|
476
562
|
.check(z.describe('Order side: `bid` buys the base token, `ask` sells it.'), z.meta({ examples: ['bid'] })), // prettier-ignore
|
|
477
563
|
signer: Signer,
|
|
478
|
-
|
|
564
|
+
sourceAmount: SourceAmount,
|
|
565
|
+
sourceToken: Token.check(z.describe('Token escrowed for the order.')),
|
|
479
566
|
tick: z
|
|
480
567
|
.number()
|
|
481
568
|
.check(
|
|
@@ -512,7 +599,8 @@ export namespace schema {
|
|
|
512
599
|
data: z
|
|
513
600
|
.object({
|
|
514
601
|
signer: Signer,
|
|
515
|
-
|
|
602
|
+
sourceAmount: SourceAmount,
|
|
603
|
+
sourceToken: Token.check(z.describe('Token used for the distributed fees.')),
|
|
516
604
|
validator: Schema.Address.check(
|
|
517
605
|
z.describe('Validator that received the distributed fees.'),
|
|
518
606
|
),
|
|
@@ -528,11 +616,11 @@ export namespace schema {
|
|
|
528
616
|
...base,
|
|
529
617
|
data: z
|
|
530
618
|
.object({
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
),
|
|
619
|
+
destinationAmount: DestinationAmount,
|
|
620
|
+
destinationToken: Token.check(z.describe('Token received from the fee AMM.')),
|
|
534
621
|
signer: Signer,
|
|
535
|
-
|
|
622
|
+
sourceAmount: SourceAmount,
|
|
623
|
+
sourceToken: Token.check(z.describe('Token sent into the fee AMM.')),
|
|
536
624
|
swapper: Schema.Address.check(z.describe('Address that performed the rebalance swap.')),
|
|
537
625
|
})
|
|
538
626
|
.check(z.describe('A fee-AMM rebalance swap between a validator and user token.')),
|
|
@@ -548,7 +636,8 @@ export namespace schema {
|
|
|
548
636
|
.object({
|
|
549
637
|
funder: Schema.Address.check(z.describe('Address that funded the reward pool.')),
|
|
550
638
|
signer: Signer,
|
|
551
|
-
|
|
639
|
+
sourceAmount: SourceAmount,
|
|
640
|
+
sourceToken: Token.check(z.describe('Token added to the reward pool.')),
|
|
552
641
|
})
|
|
553
642
|
.check(z.describe('A token reward pool was funded.')),
|
|
554
643
|
type: z
|
|
@@ -583,9 +672,8 @@ export namespace schema {
|
|
|
583
672
|
z.describe('Public key of the access key whose limit changed.'),
|
|
584
673
|
),
|
|
585
674
|
signer: Signer,
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
),
|
|
675
|
+
sourceAmount: SourceAmount,
|
|
676
|
+
sourceToken: Token.check(z.describe('Token whose spending limit was updated.')),
|
|
589
677
|
})
|
|
590
678
|
.check(z.describe('An access key’s per-token spending limit was updated.')),
|
|
591
679
|
type: z
|
|
@@ -636,7 +724,8 @@ export namespace schema {
|
|
|
636
724
|
.enum(['bid', 'ask'])
|
|
637
725
|
.check(z.describe('Side of the flipped order: `bid` buys the base token, `ask` sells it.'), z.meta({ examples: ['bid'] })), // prettier-ignore
|
|
638
726
|
signer: Signer,
|
|
639
|
-
|
|
727
|
+
sourceAmount: SourceAmount,
|
|
728
|
+
sourceToken: Token.check(z.describe('Token the flipped order rests with.')),
|
|
640
729
|
tick: z
|
|
641
730
|
.number()
|
|
642
731
|
.check(
|
|
@@ -1292,6 +1381,17 @@ export namespace schema {
|
|
|
1292
1381
|
.union([...items, Group])
|
|
1293
1382
|
.check(z.describe('Either one activity item, or a grouped set of access-key activity items.'))
|
|
1294
1383
|
|
|
1384
|
+
/** Optional token fields that require sources beyond RPC metadata. */
|
|
1385
|
+
export const Include = z
|
|
1386
|
+
.enum(tokenFields)
|
|
1387
|
+
.check(z.describe('Additional token fields to include in activity responses.'))
|
|
1388
|
+
|
|
1389
|
+
/** Parses comma-separated optional token fields. */
|
|
1390
|
+
export const includeQuery = Schema.includeQuery(
|
|
1391
|
+
Include,
|
|
1392
|
+
'Comma-separated token fields to include, such as `token.logoUri,token.verified`.',
|
|
1393
|
+
)
|
|
1394
|
+
|
|
1295
1395
|
/** Schemas for the getAddressActivities operation. */
|
|
1296
1396
|
export namespace getAddressActivities {
|
|
1297
1397
|
/** Path parameters for address activity requests. */
|
|
@@ -1308,6 +1408,7 @@ export namespace schema {
|
|
|
1308
1408
|
.strictObject({
|
|
1309
1409
|
chainId: Schema.ChainIdQuery,
|
|
1310
1410
|
cursor: Schema.Cursor,
|
|
1411
|
+
denomination: Schema.Denomination,
|
|
1311
1412
|
// Folding is opt-in: by default every item is returned at the root.
|
|
1312
1413
|
group: z
|
|
1313
1414
|
._default(Schema.booleanQuery(), false)
|
|
@@ -1317,6 +1418,7 @@ export namespace schema {
|
|
|
1317
1418
|
),
|
|
1318
1419
|
z.meta({ examples: [true] }),
|
|
1319
1420
|
),
|
|
1421
|
+
include: includeQuery,
|
|
1320
1422
|
limit: Schema.Limit,
|
|
1321
1423
|
// Raw-log capture is opt-in: it can add a large `events` array to every
|
|
1322
1424
|
// item, so the default feed stays lean.
|
|
@@ -1344,6 +1446,9 @@ export namespace schema {
|
|
|
1344
1446
|
export const Response = z
|
|
1345
1447
|
.object({
|
|
1346
1448
|
data: z.array(Entry).check(z.describe('Activity feed entries for the address.')),
|
|
1449
|
+
meta: z
|
|
1450
|
+
.optional(schema.Meta)
|
|
1451
|
+
.check(z.describe('Page-level resources, such as valuation rate provenance.')),
|
|
1347
1452
|
nextCursor: Schema.NextCursor,
|
|
1348
1453
|
})
|
|
1349
1454
|
.check(z.describe('A page of human-readable activity for the address.'))
|
|
@@ -1366,6 +1471,8 @@ export namespace schema {
|
|
|
1366
1471
|
export const Query = z
|
|
1367
1472
|
.strictObject({
|
|
1368
1473
|
chainId: Schema.ChainIdQuery,
|
|
1474
|
+
denomination: Schema.Denomination,
|
|
1475
|
+
include: includeQuery,
|
|
1369
1476
|
// Raw-log capture is opt-in: it can add a large `events` array to every
|
|
1370
1477
|
// item, so the default response stays lean.
|
|
1371
1478
|
logs: z
|
|
@@ -1388,12 +1495,15 @@ export namespace schema {
|
|
|
1388
1495
|
export const Response = z
|
|
1389
1496
|
.object({
|
|
1390
1497
|
data: z.array(Item).check(z.describe('Activity items classified from the transaction.')),
|
|
1498
|
+
meta: z
|
|
1499
|
+
.optional(schema.Meta)
|
|
1500
|
+
.check(z.describe('Page-level resources, such as valuation rate provenance.')),
|
|
1391
1501
|
})
|
|
1392
1502
|
.check(z.describe('The human-readable activity that happened on a transaction.'))
|
|
1393
1503
|
}
|
|
1394
1504
|
}
|
|
1395
1505
|
|
|
1396
|
-
/** A token
|
|
1506
|
+
/** A token in the public resource shape (derived from {@link schema.Token}). */
|
|
1397
1507
|
export type Token = z.output<typeof schema.Token>
|
|
1398
1508
|
|
|
1399
1509
|
/** A single classified activity item (derived from {@link schema.Item}). */
|
|
@@ -1402,14 +1512,36 @@ export type Item = z.output<typeof schema.Item>
|
|
|
1402
1512
|
/** A single activity item, or a folded access-key group (derived from {@link schema.Entry}). */
|
|
1403
1513
|
export type Entry = z.output<typeof schema.Entry>
|
|
1404
1514
|
|
|
1515
|
+
type AmountKey = 'destinationAmount' | 'refundAmount' | 'sourceAmount'
|
|
1516
|
+
type TokenKey = 'destinationToken' | 'refund' | 'sourceToken'
|
|
1517
|
+
|
|
1518
|
+
/** Token fields available before RPC metadata resolution. */
|
|
1519
|
+
type UnenrichedToken = {
|
|
1520
|
+
address: Token['address']
|
|
1521
|
+
amount: z.output<typeof Schema.DecimalString>
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
type UnenrichedData<data> = {
|
|
1525
|
+
[key in keyof data as key extends AmountKey ? never : key]: key extends TokenKey
|
|
1526
|
+
? UnenrichedToken | Extract<data[key], undefined>
|
|
1527
|
+
: data[key]
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/** A classified item whose token stubs have not been enriched with structured amounts. */
|
|
1531
|
+
type UnenrichedItem = {
|
|
1532
|
+
[type in Item['type']]: Omit<Extract<Item, { type: type }>, 'data'> & {
|
|
1533
|
+
data: UnenrichedData<Extract<Item, { type: type }>['data']>
|
|
1534
|
+
}
|
|
1535
|
+
}[Item['type']]
|
|
1536
|
+
|
|
1405
1537
|
/**
|
|
1406
1538
|
* A classified item before {@link list} stamps its display {@link Item.title}.
|
|
1407
1539
|
* Internal classifiers build these; `list` derives `title` from `type` via
|
|
1408
1540
|
* {@link titleByType}, so each branch never repeats the human label.
|
|
1409
1541
|
*/
|
|
1410
1542
|
type RawItem = {
|
|
1411
|
-
[type in
|
|
1412
|
-
}[
|
|
1543
|
+
[type in UnenrichedItem['type']]: Omit<Extract<UnenrichedItem, { type: type }>, 'title'>
|
|
1544
|
+
}[UnenrichedItem['type']]
|
|
1413
1545
|
|
|
1414
1546
|
/**
|
|
1415
1547
|
* Human-readable label for each activity {@link Item.type}, mirroring the per-variant
|
|
@@ -1572,6 +1704,12 @@ const maxGroupSize = 50
|
|
|
1572
1704
|
/** Token-bearing keys on an item's `data` payload, walked for enrichment. */
|
|
1573
1705
|
const tokenKeys = ['destinationToken', 'refund', 'sourceToken'] as const
|
|
1574
1706
|
|
|
1707
|
+
const amountKeyByTokenKey = {
|
|
1708
|
+
destinationToken: 'destinationAmount',
|
|
1709
|
+
refund: 'refundAmount',
|
|
1710
|
+
sourceToken: 'sourceAmount',
|
|
1711
|
+
} as const
|
|
1712
|
+
|
|
1575
1713
|
/** The base fields ({@link schema.base}) every activity item carries. */
|
|
1576
1714
|
type Base = {
|
|
1577
1715
|
id: string
|
|
@@ -1665,7 +1803,8 @@ type TxGroup = {
|
|
|
1665
1803
|
* consecutive access-key-signed items into `group` entries. Pagination uses the
|
|
1666
1804
|
* same `(block_num, tx_idx)` keyset cursor the pipeline emits.
|
|
1667
1805
|
*/
|
|
1668
|
-
export function addresses() {
|
|
1806
|
+
export function addresses(options: addresses.Options = {}) {
|
|
1807
|
+
const oracle = options.fx?.oracle ?? FxOracle.ecb()
|
|
1669
1808
|
return new Hono<App.Environment>().get(
|
|
1670
1809
|
'/v1/addresses/:address/activities',
|
|
1671
1810
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
@@ -1682,7 +1821,7 @@ export function addresses() {
|
|
|
1682
1821
|
'Get a human-readable feed of what an address has been doing onchain, including payments sent and received, swaps, approvals, and more.',
|
|
1683
1822
|
operationId: 'getAddressActivities',
|
|
1684
1823
|
responses: OpenApi.responses({
|
|
1685
|
-
errors: { 502: 'Tempo could not read activity data from
|
|
1824
|
+
errors: { 502: 'Tempo could not read activity or token data from an upstream service.' },
|
|
1686
1825
|
success: {
|
|
1687
1826
|
description: 'A page of address activity entries.',
|
|
1688
1827
|
schema: schema.getAddressActivities.Response,
|
|
@@ -1712,38 +1851,42 @@ export function addresses() {
|
|
|
1712
1851
|
const { address } = c.req.valid('param')
|
|
1713
1852
|
const query = c.req.valid('query')
|
|
1714
1853
|
|
|
1715
|
-
// Cursor pages
|
|
1716
|
-
|
|
1717
|
-
// default.
|
|
1718
|
-
if (query.cursor !== undefined) Cache.setPolicy(c, Cache.policies.immutable)
|
|
1854
|
+
// Cursor pages carry current valuations and curated verification data.
|
|
1855
|
+
if (query.cursor !== undefined) Cache.setPolicy(c, Cache.policies.metadata)
|
|
1719
1856
|
|
|
1720
1857
|
try {
|
|
1721
1858
|
const chainId = query.chainId ?? c.get('chainId')
|
|
1722
1859
|
const provider = tidx({ chainId, tidx: c.get('getTidx')(chainId) })
|
|
1723
|
-
const { items, nextCursor } = await Timing.time(
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1860
|
+
const { items: unenrichedItems, nextCursor } = await Timing.time(
|
|
1861
|
+
c,
|
|
1862
|
+
'address_activities',
|
|
1863
|
+
() =>
|
|
1864
|
+
Store.memoize(
|
|
1865
|
+
() =>
|
|
1866
|
+
list(provider, {
|
|
1867
|
+
address: address as Hex.Hex,
|
|
1868
|
+
cursor: query.cursor,
|
|
1869
|
+
group: query.group,
|
|
1870
|
+
limit: query.limit,
|
|
1871
|
+
logs: query.logs,
|
|
1872
|
+
store: c.get('store'),
|
|
1873
|
+
}),
|
|
1874
|
+
{
|
|
1875
|
+
key: `activities:v1:${chainId}:${address.toLowerCase()}:${query.group ?? false}:${query.logs ?? false}:${query.cursor ?? 'head'}:${query.limit}`,
|
|
1732
1876
|
store: c.get('store'),
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
store: c.get('store'),
|
|
1737
|
-
ttl: Ttl.seconds(15),
|
|
1738
|
-
},
|
|
1739
|
-
),
|
|
1877
|
+
ttl: Ttl.seconds(15),
|
|
1878
|
+
},
|
|
1879
|
+
),
|
|
1740
1880
|
)
|
|
1741
1881
|
|
|
1742
|
-
//
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1882
|
+
// Build immutable token and structured amount copies from RPC metadata.
|
|
1883
|
+
const { items, rates } = await enrichTokens(c, {
|
|
1884
|
+
chainId,
|
|
1885
|
+
denomination: query.denomination ?? 'USD',
|
|
1886
|
+
include: query.include,
|
|
1887
|
+
items: unenrichedItems,
|
|
1888
|
+
oracle,
|
|
1889
|
+
})
|
|
1747
1890
|
|
|
1748
1891
|
// Fold consecutive access-key-signed items into `group` entries only
|
|
1749
1892
|
// when requested; otherwise every item is returned at the root.
|
|
@@ -1752,17 +1895,28 @@ export function addresses() {
|
|
|
1752
1895
|
return c.json(
|
|
1753
1896
|
Response.validated(schema.getAddressActivities.Response, {
|
|
1754
1897
|
data,
|
|
1898
|
+
...(rates ? { meta: { pricing: Valuation.pricing(rates, oracle) } } : {}),
|
|
1755
1899
|
nextCursor,
|
|
1756
1900
|
}),
|
|
1757
1901
|
200,
|
|
1758
1902
|
)
|
|
1759
1903
|
} catch (cause) {
|
|
1904
|
+
if (cause instanceof Valuation.UnsupportedDenominationError)
|
|
1905
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
1760
1906
|
return Response.upstream(c, cause)
|
|
1761
1907
|
}
|
|
1762
1908
|
},
|
|
1763
1909
|
)
|
|
1764
1910
|
}
|
|
1765
1911
|
|
|
1912
|
+
export declare namespace addresses {
|
|
1913
|
+
/** Options for the address-scoped activity handlers. */
|
|
1914
|
+
type Options = {
|
|
1915
|
+
/** FX configuration backing amount valuation. */
|
|
1916
|
+
fx?: Valuation.addresses.Fx | undefined
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1766
1920
|
/**
|
|
1767
1921
|
* Creates transaction-scoped activity handlers, mounted under the
|
|
1768
1922
|
* `/transactions` composer. Exposes `GET /:transactionHash/activities`.
|
|
@@ -1773,7 +1927,8 @@ export function addresses() {
|
|
|
1773
1927
|
* classified item(s) — usually one headline activity — with the full per-tx
|
|
1774
1928
|
* event set available via `logs=true`.
|
|
1775
1929
|
*/
|
|
1776
|
-
export function transactions() {
|
|
1930
|
+
export function transactions(options: transactions.Options = {}) {
|
|
1931
|
+
const oracle = options.fx?.oracle ?? FxOracle.ecb()
|
|
1777
1932
|
return new Hono<App.Environment>().get(
|
|
1778
1933
|
'/v1/transactions/:transactionHash/activities',
|
|
1779
1934
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
@@ -1795,7 +1950,7 @@ export function transactions() {
|
|
|
1795
1950
|
description: 'No mined transaction was found for that hash.',
|
|
1796
1951
|
codes: ['transaction_not_found'],
|
|
1797
1952
|
},
|
|
1798
|
-
502: 'Tempo could not read activity data from
|
|
1953
|
+
502: 'Tempo could not read activity or token data from an upstream service.',
|
|
1799
1954
|
},
|
|
1800
1955
|
success: {
|
|
1801
1956
|
description: 'The classified activity for the transaction.',
|
|
@@ -1806,10 +1961,8 @@ export function transactions() {
|
|
|
1806
1961
|
tags: ['Activities'],
|
|
1807
1962
|
}),
|
|
1808
1963
|
Cache.response<App.Environment>({
|
|
1809
|
-
//
|
|
1810
|
-
//
|
|
1811
|
-
// is not cached with a long header that would mask the eventual result;
|
|
1812
|
-
// the handler upgrades the 200 to `immutable` below.
|
|
1964
|
+
// Default to no-store so a 404 does not mask the eventual mined result.
|
|
1965
|
+
// Successful responses use the metadata policy for current valuations.
|
|
1813
1966
|
cacheControl: Cache.policies.noStore,
|
|
1814
1967
|
name: 'tempo-api:transactions:v1',
|
|
1815
1968
|
key: (c) => Cache.urlKey(c, schema.getTransactionActivities.Query),
|
|
@@ -1832,7 +1985,7 @@ export function transactions() {
|
|
|
1832
1985
|
const chainId = query.chainId ?? c.get('chainId')
|
|
1833
1986
|
|
|
1834
1987
|
try {
|
|
1835
|
-
const
|
|
1988
|
+
const unenrichedItems = await Timing.time(c, 'transaction_activities', () =>
|
|
1836
1989
|
Store.memoize(
|
|
1837
1990
|
() =>
|
|
1838
1991
|
getTransactionActivities({
|
|
@@ -1850,31 +2003,49 @@ export function transactions() {
|
|
|
1850
2003
|
),
|
|
1851
2004
|
)
|
|
1852
2005
|
|
|
1853
|
-
if (
|
|
2006
|
+
if (unenrichedItems === null)
|
|
1854
2007
|
return Response.error(c, {
|
|
1855
2008
|
code: 'transaction_not_found',
|
|
1856
2009
|
message: 'Transaction not found',
|
|
1857
2010
|
status: 404,
|
|
1858
2011
|
})
|
|
1859
2012
|
|
|
1860
|
-
//
|
|
1861
|
-
Cache.setPolicy(c, Cache.policies.
|
|
2013
|
+
// Mined activity still carries current valuations and verification data.
|
|
2014
|
+
Cache.setPolicy(c, Cache.policies.metadata)
|
|
1862
2015
|
|
|
1863
|
-
//
|
|
1864
|
-
|
|
1865
|
-
|
|
2016
|
+
// Build immutable token and structured amount copies from RPC metadata.
|
|
2017
|
+
const { items, rates } = await enrichTokens(c, {
|
|
2018
|
+
chainId,
|
|
2019
|
+
denomination: query.denomination ?? 'USD',
|
|
2020
|
+
include: query.include,
|
|
2021
|
+
items: unenrichedItems,
|
|
2022
|
+
oracle,
|
|
2023
|
+
})
|
|
1866
2024
|
|
|
1867
2025
|
return c.json(
|
|
1868
|
-
Response.validated(schema.getTransactionActivities.Response, {
|
|
2026
|
+
Response.validated(schema.getTransactionActivities.Response, {
|
|
2027
|
+
data: items,
|
|
2028
|
+
...(rates ? { meta: { pricing: Valuation.pricing(rates, oracle) } } : {}),
|
|
2029
|
+
}),
|
|
1869
2030
|
200,
|
|
1870
2031
|
)
|
|
1871
2032
|
} catch (cause) {
|
|
2033
|
+
if (cause instanceof Valuation.UnsupportedDenominationError)
|
|
2034
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
1872
2035
|
return Response.upstream(c, cause)
|
|
1873
2036
|
}
|
|
1874
2037
|
},
|
|
1875
2038
|
)
|
|
1876
2039
|
}
|
|
1877
2040
|
|
|
2041
|
+
export declare namespace transactions {
|
|
2042
|
+
/** Options for the transaction-scoped activity handlers. */
|
|
2043
|
+
type Options = {
|
|
2044
|
+
/** FX configuration backing amount valuation. */
|
|
2045
|
+
fx?: Valuation.addresses.Fx | undefined
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
1878
2049
|
/**
|
|
1879
2050
|
* Classifies the activity for a single transaction. Fetches the transaction's
|
|
1880
2051
|
* receipt (for its block position, sender, and fee payer) and its logs, then
|
|
@@ -1887,7 +2058,7 @@ export function transactions() {
|
|
|
1887
2058
|
*/
|
|
1888
2059
|
export async function getTransactionActivities(
|
|
1889
2060
|
options: getTransactionActivities.Options,
|
|
1890
|
-
): Promise<
|
|
2061
|
+
): Promise<UnenrichedItem[] | null> {
|
|
1891
2062
|
const { chainId, logs = false, tidx: tidxClient } = options
|
|
1892
2063
|
const hash = options.transactionHash.toLowerCase()
|
|
1893
2064
|
|
|
@@ -1979,7 +2150,7 @@ export async function list(provider: Provider, options: list.Options): Promise<l
|
|
|
1979
2150
|
const fingerprintMap = await Mpp.fingerprintMap({ store: options.store }).catch(() => ({}))
|
|
1980
2151
|
|
|
1981
2152
|
let currentCursor: string | undefined = cursor
|
|
1982
|
-
const allItems:
|
|
2153
|
+
const allItems: UnenrichedItem[] = []
|
|
1983
2154
|
let hasMore = false
|
|
1984
2155
|
let lastGroup: TxGroup | undefined
|
|
1985
2156
|
|
|
@@ -2005,7 +2176,7 @@ export async function list(provider: Provider, options: list.Options): Promise<l
|
|
|
2005
2176
|
lastGroup = page[page.length - 1]
|
|
2006
2177
|
|
|
2007
2178
|
const enough = group
|
|
2008
|
-
?
|
|
2179
|
+
? groupByAccessKeyItems(allItems).length >= minGroupEntries
|
|
2009
2180
|
: allItems.length >= limit
|
|
2010
2181
|
if (enough || !hasMore) break
|
|
2011
2182
|
|
|
@@ -2015,8 +2186,8 @@ export async function list(provider: Provider, options: list.Options): Promise<l
|
|
|
2015
2186
|
let nextCursor: string | null = null
|
|
2016
2187
|
if (hasMore && lastGroup) nextCursor = provider.cursorForGroup(lastGroup)
|
|
2017
2188
|
|
|
2018
|
-
// Items carry
|
|
2019
|
-
//
|
|
2189
|
+
// Items carry private `address`/`amount` stubs; the caller splits them into
|
|
2190
|
+
// public token references and structured amounts via {@link enrichTokens}.
|
|
2020
2191
|
return { items: allItems, nextCursor }
|
|
2021
2192
|
}
|
|
2022
2193
|
|
|
@@ -2038,7 +2209,7 @@ export declare namespace list {
|
|
|
2038
2209
|
}
|
|
2039
2210
|
/** Result of {@link list}. */
|
|
2040
2211
|
type ReturnType = {
|
|
2041
|
-
items:
|
|
2212
|
+
items: UnenrichedItem[]
|
|
2042
2213
|
nextCursor: string | null
|
|
2043
2214
|
}
|
|
2044
2215
|
}
|
|
@@ -3661,13 +3832,13 @@ function transfer(
|
|
|
3661
3832
|
blockNumber: number,
|
|
3662
3833
|
data: {
|
|
3663
3834
|
attribution?: string | undefined
|
|
3664
|
-
destinationToken?:
|
|
3835
|
+
destinationToken?: UnenrichedToken | undefined
|
|
3665
3836
|
direction: 'in' | 'out'
|
|
3666
3837
|
memo?: string | undefined
|
|
3667
3838
|
recipient: Address.Address
|
|
3668
3839
|
sender: Address.Address
|
|
3669
3840
|
signer?: 'self' | Address.Address | undefined
|
|
3670
|
-
sourceToken:
|
|
3841
|
+
sourceToken: UnenrichedToken
|
|
3671
3842
|
},
|
|
3672
3843
|
): Extract<RawItem, { type: 'transfer' }> {
|
|
3673
3844
|
return {
|
|
@@ -3792,75 +3963,187 @@ function lowerOrNull(value: unknown): Address.Address | null {
|
|
|
3792
3963
|
return text ? (text.toLowerCase() as Address.Address) : null
|
|
3793
3964
|
}
|
|
3794
3965
|
|
|
3795
|
-
/** Builds a stub
|
|
3796
|
-
function token(amount: bigint | undefined, address: Address.Address):
|
|
3966
|
+
/** Builds a token stub whose metadata is filled by {@link enrichItem}. */
|
|
3967
|
+
function token(amount: bigint | undefined, address: Address.Address): UnenrichedToken {
|
|
3797
3968
|
return { address: address.toLowerCase() as Address.Address, amount: (amount ?? 0n).toString() }
|
|
3798
3969
|
}
|
|
3799
3970
|
|
|
3800
3971
|
/** Collects every token address referenced by an item's `data`. */
|
|
3801
|
-
function collectTokens(item:
|
|
3802
|
-
const data = item.data as Partial<Record<(typeof tokenKeys)[number],
|
|
3972
|
+
function collectTokens(item: UnenrichedItem, set: Set<Address.Address>) {
|
|
3973
|
+
const data = item.data as Partial<Record<(typeof tokenKeys)[number], UnenrichedToken>>
|
|
3803
3974
|
for (const key of tokenKeys) {
|
|
3804
3975
|
const t = data[key]
|
|
3805
3976
|
if (t) set.add(t.address.toLowerCase() as Address.Address)
|
|
3806
3977
|
}
|
|
3807
3978
|
}
|
|
3808
3979
|
|
|
3809
|
-
/** Resolved token
|
|
3810
|
-
type ResolvedToken =
|
|
3980
|
+
/** Resolved token fields keyed by lowercased address. */
|
|
3981
|
+
type ResolvedToken = {
|
|
3982
|
+
currency: string
|
|
3983
|
+
decimals: number
|
|
3984
|
+
logoUri?: string | undefined
|
|
3985
|
+
name: string
|
|
3986
|
+
symbol: string
|
|
3987
|
+
verified?: boolean | undefined
|
|
3988
|
+
}
|
|
3811
3989
|
|
|
3812
|
-
/**
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3990
|
+
/** Resolves TIP-20 metadata or the standard ERC-20 subset used by activity transfers. */
|
|
3991
|
+
function getActivityTokenMetadata(
|
|
3992
|
+
c: Context<App.Environment>,
|
|
3993
|
+
options: getActivityTokenMetadata.Options,
|
|
3994
|
+
): Promise<Omit<ResolvedToken, 'verified'>> {
|
|
3995
|
+
const { address, chainId } = options
|
|
3996
|
+
if (address.startsWith(tip20AddressPrefix))
|
|
3997
|
+
return Tokens.getTokenMetadata(c, { address, chainId })
|
|
3998
|
+
|
|
3999
|
+
return Store.memoize(
|
|
4000
|
+
async () => {
|
|
4001
|
+
const metadata = await viem_Token.getMetadata(c.get('getClient')(chainId), { token: address })
|
|
4002
|
+
// ERC-20 has no currency field; its symbol is the amount's unit label.
|
|
4003
|
+
return {
|
|
4004
|
+
currency: metadata.symbol,
|
|
4005
|
+
decimals: metadata.decimals,
|
|
4006
|
+
name: metadata.name,
|
|
4007
|
+
symbol: metadata.symbol,
|
|
4008
|
+
}
|
|
4009
|
+
},
|
|
4010
|
+
{ key: `token:erc20:v1:${chainId}:${address}:metadata`, store: c.get('store'), ttl: Ttl.minutes(1) }, // prettier-ignore
|
|
4011
|
+
)
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
declare namespace getActivityTokenMetadata {
|
|
4015
|
+
type Options = {
|
|
4016
|
+
/** Token contract address. */
|
|
4017
|
+
address: Address.Address
|
|
4018
|
+
/** Source chain id. */
|
|
4019
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
|
|
4023
|
+
/** Resolves core metadata into immutable items. Optional logo and verification sources are best-effort. */
|
|
4024
|
+
async function enrichTokens(
|
|
4025
|
+
c: Context<App.Environment>,
|
|
4026
|
+
options: enrichTokens.Options,
|
|
4027
|
+
): Promise<{ items: Item[]; rates: FxOracle.RateSet | undefined }> {
|
|
4028
|
+
const { chainId, denomination, include, items, oracle } = options
|
|
3822
4029
|
const addresses = new Set<Address.Address>()
|
|
3823
4030
|
for (const item of items) collectTokens(item, addresses)
|
|
3824
|
-
|
|
4031
|
+
// Valuation keys off the curated snapshot; a snapshot failure degrades the
|
|
4032
|
+
// values to `null` rather than failing the feed.
|
|
4033
|
+
const snapshot =
|
|
4034
|
+
addresses.size > 0
|
|
4035
|
+
? await VerifiedTokens.snapshot(c, chainId).catch(() => undefined)
|
|
4036
|
+
: undefined
|
|
4037
|
+
const rates = await Valuation.ratesFor(c, {
|
|
4038
|
+
currencies: snapshot
|
|
4039
|
+
? [...addresses].flatMap((address) => {
|
|
4040
|
+
const held = snapshot.byAddress.get(address)?.currency
|
|
4041
|
+
return held === undefined ? [] : [held]
|
|
4042
|
+
})
|
|
4043
|
+
: [],
|
|
4044
|
+
denomination,
|
|
4045
|
+
oracle,
|
|
4046
|
+
})
|
|
4047
|
+
if (addresses.size === 0) return { items: items as Item[], rates }
|
|
4048
|
+
|
|
4049
|
+
const includeLogoUri = include.includes('token.logoUri')
|
|
4050
|
+
const includeVerified = include.includes('token.verified')
|
|
3825
4051
|
|
|
3826
4052
|
const resolved = await Timing.time(c, 'tokens', () =>
|
|
3827
4053
|
Promise.all(
|
|
3828
|
-
[...addresses].map((address) =>
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
4054
|
+
[...addresses].map(async (address) => {
|
|
4055
|
+
const [logoUri, metadata] = await Promise.all([
|
|
4056
|
+
includeLogoUri
|
|
4057
|
+
? Tokens.getTokenLogo(c, { address, chainId }).catch(() => undefined)
|
|
4058
|
+
: undefined,
|
|
4059
|
+
getActivityTokenMetadata(c, { address, chainId }),
|
|
4060
|
+
])
|
|
4061
|
+
return [
|
|
4062
|
+
address.toLowerCase(),
|
|
4063
|
+
{
|
|
4064
|
+
currency: metadata.currency,
|
|
4065
|
+
decimals: metadata.decimals,
|
|
4066
|
+
logoUri: includeLogoUri
|
|
4067
|
+
? (logoUri ?? snapshot?.byAddress.get(address)?.logoUri ?? metadata.logoUri)
|
|
4068
|
+
: undefined,
|
|
4069
|
+
name: metadata.name,
|
|
4070
|
+
symbol: metadata.symbol,
|
|
4071
|
+
verified: includeVerified && snapshot ? snapshot.byAddress.has(address) : undefined,
|
|
4072
|
+
},
|
|
4073
|
+
] as const
|
|
4074
|
+
}),
|
|
3833
4075
|
),
|
|
3834
4076
|
)
|
|
3835
4077
|
const byAddress = new Map(resolved)
|
|
3836
|
-
|
|
4078
|
+
return {
|
|
4079
|
+
items: items.map((item) => enrichItem(item, byAddress, { denomination, rates, snapshot })),
|
|
4080
|
+
rates,
|
|
4081
|
+
}
|
|
3837
4082
|
}
|
|
3838
4083
|
|
|
3839
4084
|
declare namespace enrichTokens {
|
|
3840
4085
|
type Options = {
|
|
3841
4086
|
chainId: z.output<typeof Schema.ChainId>
|
|
3842
|
-
|
|
4087
|
+
/** Currency the amount valuations are denominated in (uppercase). */
|
|
4088
|
+
denomination: string
|
|
4089
|
+
include: readonly z.output<typeof schema.Include>[]
|
|
4090
|
+
items: readonly UnenrichedItem[]
|
|
4091
|
+
/** FX rate oracle backing amount valuation. */
|
|
4092
|
+
oracle: FxOracle.Oracle
|
|
3843
4093
|
}
|
|
3844
4094
|
}
|
|
3845
4095
|
|
|
3846
|
-
/**
|
|
3847
|
-
function enrichItem(
|
|
3848
|
-
|
|
4096
|
+
/** Returns an enriched copy of an item without mutating its cached token stubs. */
|
|
4097
|
+
function enrichItem(
|
|
4098
|
+
item: UnenrichedItem,
|
|
4099
|
+
byAddress: Map<string, ResolvedToken>,
|
|
4100
|
+
valuation: enrichItem.Valuation,
|
|
4101
|
+
): Item {
|
|
4102
|
+
const source = item.data as Partial<Record<(typeof tokenKeys)[number], UnenrichedToken>>
|
|
4103
|
+
const data: Record<string, unknown> = { ...item.data }
|
|
3849
4104
|
for (const key of tokenKeys) {
|
|
3850
|
-
const t =
|
|
4105
|
+
const t = source[key]
|
|
3851
4106
|
if (!t) continue
|
|
3852
4107
|
const meta = byAddress.get(t.address.toLowerCase())
|
|
3853
|
-
if (!meta)
|
|
3854
|
-
|
|
3855
|
-
|
|
4108
|
+
if (!meta) throw new Error(`Token metadata unavailable for ${t.address}`)
|
|
4109
|
+
|
|
4110
|
+
data[amountKeyByTokenKey[key]] = {
|
|
4111
|
+
...Value.tokenAmount({
|
|
4112
|
+
baseUnits: t.amount,
|
|
4113
|
+
currency: meta.currency,
|
|
4114
|
+
decimals: meta.decimals,
|
|
4115
|
+
}),
|
|
4116
|
+
// Valued via the curated display currency, never the on-chain metadata.
|
|
4117
|
+
valuation: Valuation.valuationFor({
|
|
4118
|
+
amount: BigInt(t.amount),
|
|
4119
|
+
denomination: valuation.denomination,
|
|
4120
|
+
rates: valuation.rates,
|
|
4121
|
+
token: valuation.snapshot?.byAddress.get(t.address.toLowerCase()),
|
|
4122
|
+
}),
|
|
4123
|
+
}
|
|
3856
4124
|
data[key] = {
|
|
3857
|
-
|
|
4125
|
+
address: t.address,
|
|
3858
4126
|
currency: meta.currency,
|
|
3859
4127
|
decimals: meta.decimals,
|
|
4128
|
+
...(meta.logoUri !== undefined ? { logoUri: meta.logoUri } : {}),
|
|
3860
4129
|
name: meta.name,
|
|
3861
4130
|
symbol: meta.symbol,
|
|
4131
|
+
...(meta.verified !== undefined ? { verified: meta.verified } : {}),
|
|
3862
4132
|
}
|
|
3863
4133
|
}
|
|
4134
|
+
return { ...item, data } as Item
|
|
4135
|
+
}
|
|
4136
|
+
|
|
4137
|
+
declare namespace enrichItem {
|
|
4138
|
+
/** Valuation inputs threaded from {@link enrichTokens}. */
|
|
4139
|
+
type Valuation = {
|
|
4140
|
+
/** Currency the amount valuations are denominated in (uppercase). */
|
|
4141
|
+
denomination: string
|
|
4142
|
+
/** Oracle rate set, when loaded. */
|
|
4143
|
+
rates: FxOracle.RateSet | undefined
|
|
4144
|
+
/** Compiled verified-token snapshot, when available. */
|
|
4145
|
+
snapshot: VerifiedTokens.Snapshot | undefined
|
|
4146
|
+
}
|
|
3864
4147
|
}
|
|
3865
4148
|
|
|
3866
4149
|
/**
|
|
@@ -3869,8 +4152,31 @@ function enrichItem(item: Item, byAddress: Map<string, ResolvedToken | undefined
|
|
|
3869
4152
|
* Must be called once over the full, timestamp-sorted item list.
|
|
3870
4153
|
*/
|
|
3871
4154
|
export function groupByAccessKey(items: Item[]): Entry[] {
|
|
3872
|
-
|
|
3873
|
-
|
|
4155
|
+
return groupByAccessKeyItems(items)
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4158
|
+
type GroupableItem = {
|
|
4159
|
+
data: object
|
|
4160
|
+
id: string
|
|
4161
|
+
perspective: 'incoming' | 'outgoing'
|
|
4162
|
+
timestamp: string
|
|
4163
|
+
}
|
|
4164
|
+
|
|
4165
|
+
type GroupedItem<item extends GroupableItem> =
|
|
4166
|
+
| item
|
|
4167
|
+
| {
|
|
4168
|
+
data: { items: item[]; signer: Address.Address }
|
|
4169
|
+
id: string
|
|
4170
|
+
perspective: 'incoming' | 'outgoing'
|
|
4171
|
+
timestamp: string
|
|
4172
|
+
title: 'Group'
|
|
4173
|
+
type: 'group'
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4176
|
+
/** Groups items while preserving whether their token data has been enriched. */
|
|
4177
|
+
function groupByAccessKeyItems<item extends GroupableItem>(items: item[]): GroupedItem<item>[] {
|
|
4178
|
+
const entries: GroupedItem<item>[] = []
|
|
4179
|
+
let currentGroup: { items: item[]; signer: Address.Address } | null = null
|
|
3874
4180
|
|
|
3875
4181
|
for (const item of items) {
|
|
3876
4182
|
const itemSigner = signerOf(item)
|
|
@@ -3903,12 +4209,15 @@ export function groupByAccessKey(items: Item[]): Entry[] {
|
|
|
3903
4209
|
}
|
|
3904
4210
|
|
|
3905
4211
|
/** The access-key signer of an item, or `self` when it has no access-key signer. */
|
|
3906
|
-
function signerOf(item:
|
|
4212
|
+
function signerOf(item: GroupableItem): 'self' | Address.Address {
|
|
3907
4213
|
return (item.data as { signer?: 'self' | Address.Address }).signer ?? 'self'
|
|
3908
4214
|
}
|
|
3909
4215
|
|
|
3910
4216
|
/** Unwraps single-item groups; otherwise wraps the items in a `group` entry. */
|
|
3911
|
-
function flushGroup(group: {
|
|
4217
|
+
function flushGroup<item extends GroupableItem>(group: {
|
|
4218
|
+
items: item[]
|
|
4219
|
+
signer: Address.Address
|
|
4220
|
+
}): GroupedItem<item> {
|
|
3912
4221
|
if (group.items.length === 1) return group.items[0]!
|
|
3913
4222
|
const firstItem = group.items[0]!
|
|
3914
4223
|
const lastItem = group.items[group.items.length - 1]!
|