tapimo 0.10.2 → 0.12.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 +4896 -2166
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +2 -2
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +15 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +7 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Webhooks.d.ts +0 -75
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +1 -143
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +127 -78
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +115 -1
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +59 -6
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +3 -3
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +4 -2
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +83 -83
- 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 +151 -151
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/data/App.d.ts +5924 -4310
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +61 -9
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +62 -0
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
- package/dist/apps/data/ZoneSelection.js +44 -0
- package/dist/apps/data/ZoneSelection.js.map +1 -0
- package/dist/apps/data/routes/activities.d.ts +2368 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +423 -114
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +131 -0
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +25 -25
- package/dist/apps/data/routes/balances.js +1 -1
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +1 -1
- package/dist/apps/data/routes/blocks.js +1 -1
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +135 -10
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +157 -25
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +829 -123
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +16 -13
- 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/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +9 -11
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +54 -54
- package/dist/apps/data/routes/receipts.js +1 -1
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.js +24 -10
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +12 -12
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +16 -15
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +17 -3
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +34 -15
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +1 -1
- package/dist/apps/data/routes/transactions.js +1 -1
- package/dist/apps/data/routes/transactions.js.map +1 -1
- 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 +7 -9
- 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 +1011 -151
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +126 -739
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +15 -15
- package/dist/apps/funding/App.d.ts +27 -27
- package/dist/apps/funding/routes/chains.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.js +5 -4
- package/dist/apps/funding/routes/chains.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +18 -18
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +8 -8
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/providers.d.ts.map +1 -1
- package/dist/apps/funding/routes/providers.js +3 -2
- package/dist/apps/funding/routes/providers.js.map +1 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
- package/dist/apps/funding/routes/quotes.js +2 -2
- package/dist/apps/funding/routes/quotes.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +33 -33
- package/dist/apps/management/App.d.ts +1433 -322
- 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 +19 -6
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +154 -94
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +76 -30
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +103 -30
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +91 -32
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +12 -12
- package/dist/apps/management/routes/faucet.d.ts.map +1 -1
- package/dist/apps/management/routes/faucet.js +23 -12
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +46 -13
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +79 -29
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +128 -83
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +100 -41
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +5 -5
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +14 -10
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +68 -47
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +37 -18
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +48 -8
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +48 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +130 -68
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +72 -21
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +8 -5
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +38 -38
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +41 -31
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +34 -6
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +36 -17
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +1186 -197
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +106 -38
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +12 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/db/Db.d.ts +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +61 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +30 -2
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +28 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +5 -0
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +10 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
- package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
- package/dist/db/tables/webhookQueueCompletions.js +32 -0
- package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
- package/dist/db/tables/webhookQueueEvents.d.ts +16 -20
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +68 -43
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +47 -72
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +92 -105
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/internal/Auth.d.ts +8 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +13 -3
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +11 -7
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +41 -2
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +167 -0
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/MetricSink.d.ts +35 -125
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +50 -121
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +26 -22
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +128 -39
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +13 -8
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +16 -5
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +8 -8
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +10 -9
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +15 -6
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +45 -15
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +2 -0
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +16 -4
- package/dist/internal/Tidx.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 +112 -56
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +124 -93
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/Deposit.d.ts +2 -2
- package/dist/internal/funding/Deposit.d.ts.map +1 -1
- package/dist/internal/funding/Deposit.js +9 -8
- package/dist/internal/funding/Deposit.js.map +1 -1
- package/dist/internal/funding/DepositAddress.d.ts +4 -4
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
- package/dist/internal/funding/DepositAddress.js +9 -8
- package/dist/internal/funding/DepositAddress.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/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +13 -12
- package/dist/internal/funding/Provider.js.map +1 -1
- 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/funding/providers/stargate.d.ts +19 -0
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
- package/dist/internal/funding/providers/stargate.js +143 -0
- package/dist/internal/funding/providers/stargate.js.map +1 -0
- 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/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +2 -2
- package/src/App.test.ts +48 -0
- package/src/App.ts +7 -2
- package/src/Assets.test.ts +18 -0
- package/src/Assets.ts +22 -0
- package/src/Client.test-d.ts +287 -17
- package/src/Webhooks.ts +1 -220
- package/src/admin/apps/earn-vaults.test.ts +143 -0
- package/src/admin/apps/earn-vaults.ts +83 -6
- package/src/admin/apps/organizations.ts +6 -2
- package/src/admin/ui/src/routes/api-keys.tsx +36 -0
- package/src/admin/ui.generated.ts +151 -189
- package/src/apps/data/App.test.ts +31 -0
- package/src/apps/data/App.ts +64 -10
- package/src/apps/data/ZoneSelection.test.ts +196 -0
- package/src/apps/data/ZoneSelection.ts +108 -0
- package/src/apps/data/routes/activities.test.ts +435 -12
- package/src/apps/data/routes/activities.ts +562 -125
- package/src/apps/data/routes/balances.ts +1 -1
- package/src/apps/data/routes/blocks.ts +1 -1
- package/src/apps/data/routes/earn.test.ts +183 -23
- package/src/apps/data/routes/earn.ts +225 -29
- package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
- package/src/apps/data/routes/exchanges.test.ts +31 -1
- package/src/apps/data/routes/exchanges.ts +19 -15
- package/src/apps/data/routes/fee-amm.ts +18 -11
- package/src/apps/data/routes/receipts.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +75 -0
- package/src/apps/data/routes/rpc.ts +23 -9
- package/src/apps/data/routes/tokenlist.ts +21 -18
- package/src/apps/data/routes/tokens.test.ts +29 -0
- package/src/apps/data/routes/tokens.ts +38 -15
- package/src/apps/data/routes/transactions.ts +1 -1
- package/src/apps/data/routes/transfers.test.ts +3 -3
- package/src/apps/data/routes/transfers.ts +12 -9
- package/src/apps/data/routes/webhooks.test.ts +179 -1497
- package/src/apps/data/routes/webhooks.ts +156 -976
- package/src/apps/data/routes/zones.test.ts +19 -13
- package/src/apps/funding/routes/chains.test.ts +211 -7
- package/src/apps/funding/routes/chains.ts +19 -12
- package/src/apps/funding/routes/deposit-addresses.test.ts +394 -0
- package/src/apps/funding/routes/deposit-addresses.ts +84 -72
- package/src/apps/funding/routes/providers.ts +9 -5
- package/src/apps/funding/routes/quotes.test.ts +46 -0
- package/src/apps/funding/routes/quotes.ts +8 -5
- package/src/apps/funding/routes/transfers.test.ts +35 -32
- package/src/apps/management/Billing.test.ts +26 -0
- package/src/apps/management/Billing.ts +24 -7
- package/src/apps/management/routes/api-keys.test.ts +178 -0
- package/src/apps/management/routes/api-keys.ts +203 -144
- package/src/apps/management/routes/billing.test.ts +209 -0
- package/src/apps/management/routes/billing.ts +254 -177
- package/src/apps/management/routes/faucet.test.ts +39 -0
- package/src/apps/management/routes/faucet.ts +75 -41
- package/src/apps/management/routes/invitations.test.ts +216 -0
- package/src/apps/management/routes/invitations.ts +186 -109
- package/src/apps/management/routes/invite-links.test.ts +263 -1
- package/src/apps/management/routes/invite-links.ts +295 -214
- package/src/apps/management/routes/me.test.ts +49 -0
- package/src/apps/management/routes/me.ts +42 -32
- package/src/apps/management/routes/members.test.ts +124 -1
- package/src/apps/management/routes/members.ts +81 -51
- package/src/apps/management/routes/orgs.test.ts +176 -0
- package/src/apps/management/routes/orgs.ts +101 -59
- package/src/apps/management/routes/projects.test.ts +183 -0
- package/src/apps/management/routes/projects.ts +124 -60
- package/src/apps/management/routes/scopes.test.ts +44 -0
- package/src/apps/management/routes/scopes.ts +37 -28
- package/src/apps/management/routes/usage.test.ts +92 -0
- package/src/apps/management/routes/usage.ts +186 -151
- package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
- package/src/apps/management/routes/verified-token-requests.ts +166 -133
- package/src/apps/management/routes/webhooks.test.ts +313 -1
- package/src/apps/management/routes/webhooks.ts +220 -71
- package/src/apps/mpp/internal/Adapter.ts +13 -1
- package/src/db/Db.test.ts +42 -5
- package/src/db/Db.ts +85 -0
- package/src/db/Schema.ts +41 -3
- package/src/db/tables/earnVaults.test.ts +22 -0
- package/src/db/tables/earnVaults.ts +11 -1
- package/src/db/tables/organizations.test.ts +5 -2
- package/src/db/tables/webhookDeliveries.ts +13 -0
- package/src/db/tables/webhookQueueCompletions.ts +55 -0
- package/src/db/tables/webhookQueueEvents.ts +97 -57
- package/src/db/tables/webhookSubscriptions.ts +134 -144
- package/src/internal/Auth.ts +23 -5
- package/src/internal/Cache.ts +14 -7
- package/src/internal/EarnVaults.capabilities.test.ts +33 -0
- package/src/internal/EarnVaults.test.ts +79 -0
- package/src/internal/EarnVaults.ts +277 -0
- package/src/internal/MetricSink.test.ts +41 -373
- package/src/internal/MetricSink.ts +92 -273
- package/src/internal/OpenApi.ts +165 -49
- package/src/internal/Response.test.ts +95 -0
- package/src/internal/Response.ts +40 -2
- package/src/internal/Schema.test.ts +34 -0
- package/src/internal/Schema.ts +20 -9
- package/src/internal/Store.test.ts +186 -0
- package/src/internal/Store.ts +57 -17
- package/src/internal/Tidx.test.ts +19 -0
- package/src/internal/Tidx.ts +16 -4
- package/src/internal/WebhookTransfer.ts +1 -351
- package/src/internal/Webhooks.test.ts +222 -145
- package/src/internal/Webhooks.ts +234 -135
- package/src/internal/funding/Deposit.ts +71 -64
- package/src/internal/funding/DepositAddress.ts +50 -43
- package/src/internal/funding/DepositWebhook.test.ts +131 -0
- package/src/internal/funding/DepositWebhook.ts +101 -0
- package/src/internal/funding/Provider.ts +164 -142
- 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/funding/providers/index.test.ts +185 -0
- package/src/internal/funding/providers/stargate.ts +184 -0
- package/src/internal/webhookDestinations/slack.ts +15 -0
- package/src/providers/index.test.ts +1 -0
- package/src/providers/index.ts +9 -0
- package/src/Webhooks.bench.ts +0 -714
- package/src/Webhooks.memory.bench.ts +0 -250
- package/src/Webhooks.test.ts +0 -146
|
@@ -22,6 +22,7 @@ import * as Ttl from '../../../internal/Ttl.js'
|
|
|
22
22
|
import * as Value from '../../../internal/Value.js'
|
|
23
23
|
import * as VerifiedTokens from '../../../internal/VerifiedTokens.js'
|
|
24
24
|
import * as FxOracle from '../FxOracle.js'
|
|
25
|
+
import * as ZoneSelection from '../ZoneSelection.js'
|
|
25
26
|
import * as Tokens from './tokens.js'
|
|
26
27
|
import * as Transfers from './transfers.js'
|
|
27
28
|
import * as Valuation from './valuation.js'
|
|
@@ -29,7 +30,7 @@ import * as Valuation from './valuation.js'
|
|
|
29
30
|
/** Example transaction hash surfaced in OpenAPI docs. */
|
|
30
31
|
const exampleHash = '0x4845ae2098724ab26a5d89370dce5124d044be6a5acc164afc348662de67d474'
|
|
31
32
|
|
|
32
|
-
const
|
|
33
|
+
const includeFields = ['token.logoUri', 'token.verified', 'zones'] as const
|
|
33
34
|
|
|
34
35
|
// TIP-20 tokens live at deterministic `0x20c0…` addresses. Other contracts
|
|
35
36
|
// can emit the same `Transfer` signature but do not expose TIP-20 metadata.
|
|
@@ -202,6 +203,12 @@ export namespace schema {
|
|
|
202
203
|
* transfer's `direction`/`memo`/`attribution`/`signer`) the resource lacks.
|
|
203
204
|
*/
|
|
204
205
|
const base = {
|
|
206
|
+
chainId: z
|
|
207
|
+
.optional(Schema.ChainId)
|
|
208
|
+
.check(
|
|
209
|
+
z.describe('Chain id containing this activity. Returned for multi-Zone requests.'),
|
|
210
|
+
z.meta({ examples: [421700001] }),
|
|
211
|
+
),
|
|
205
212
|
perspective: z
|
|
206
213
|
.enum(['incoming', 'outgoing'])
|
|
207
214
|
.check(
|
|
@@ -989,9 +996,7 @@ export namespace schema {
|
|
|
989
996
|
logoUri: z.string().check(
|
|
990
997
|
z.describe('New logo URL for the token.'),
|
|
991
998
|
z.meta({
|
|
992
|
-
examples: [
|
|
993
|
-
'https://api.tempo.xyz/data/4217/icons/0x20c0000000000000000000008f5425160ebe5525.svg',
|
|
994
|
-
],
|
|
999
|
+
examples: [Tokens.tokenExample.logoUri],
|
|
995
1000
|
}),
|
|
996
1001
|
),
|
|
997
1002
|
signer: Signer,
|
|
@@ -1482,6 +1487,12 @@ export namespace schema {
|
|
|
1482
1487
|
/** A folded access-key group: consecutive same-signer items on one UTC day. */
|
|
1483
1488
|
export const Group = z
|
|
1484
1489
|
.object({
|
|
1490
|
+
chainId: z
|
|
1491
|
+
.optional(Schema.ChainId)
|
|
1492
|
+
.check(
|
|
1493
|
+
z.describe('Chain id containing this activity group. Returned for multi-Zone requests.'),
|
|
1494
|
+
z.meta({ examples: [421700001] }),
|
|
1495
|
+
),
|
|
1485
1496
|
data: z
|
|
1486
1497
|
.object({
|
|
1487
1498
|
items: z.array(Item).check(z.describe('Activity items included in this group.')),
|
|
@@ -1523,15 +1534,15 @@ export namespace schema {
|
|
|
1523
1534
|
.union([...items, Group])
|
|
1524
1535
|
.check(z.describe('Either one activity item, or a grouped set of access-key activity items.'))
|
|
1525
1536
|
|
|
1526
|
-
/** Optional
|
|
1537
|
+
/** Optional activity resources and selection modes. */
|
|
1527
1538
|
export const Include = z
|
|
1528
|
-
.enum(
|
|
1529
|
-
.check(z.describe('Additional
|
|
1539
|
+
.enum(includeFields)
|
|
1540
|
+
.check(z.describe('Additional activity resources and selection modes to include.'))
|
|
1530
1541
|
|
|
1531
|
-
/** Parses comma-separated optional
|
|
1542
|
+
/** Parses comma-separated optional activity resources and selection modes. */
|
|
1532
1543
|
export const includeQuery = Schema.includeQuery(
|
|
1533
1544
|
Include,
|
|
1534
|
-
'Comma-separated
|
|
1545
|
+
'Comma-separated activity options, such as `zones,token.logoUri,token.verified`.',
|
|
1535
1546
|
)
|
|
1536
1547
|
|
|
1537
1548
|
/** Schemas for the getAddressActivities operation. */
|
|
@@ -1636,6 +1647,10 @@ export namespace schema {
|
|
|
1636
1647
|
*/
|
|
1637
1648
|
export const Response = z
|
|
1638
1649
|
.object({
|
|
1650
|
+
chainId: Schema.ChainId.check(
|
|
1651
|
+
z.describe('Chain id containing the transaction.'),
|
|
1652
|
+
z.meta({ examples: [4217] }),
|
|
1653
|
+
),
|
|
1639
1654
|
data: z.array(Item).check(z.describe('Activity items classified from the transaction.')),
|
|
1640
1655
|
meta: z
|
|
1641
1656
|
.optional(schema.Meta)
|
|
@@ -1991,7 +2006,7 @@ export function addresses(options: addresses.Options = {}) {
|
|
|
1991
2006
|
tags: ['Activities'],
|
|
1992
2007
|
}),
|
|
1993
2008
|
Cache.response<App.Environment>({
|
|
1994
|
-
cacheControl: Cache.policies.
|
|
2009
|
+
cacheControl: Cache.policies.noStore,
|
|
1995
2010
|
name: 'tempo-api:addresses:v1',
|
|
1996
2011
|
key: (c) => Cache.urlKey(c, schema.getAddressActivities.Query),
|
|
1997
2012
|
}),
|
|
@@ -2011,19 +2026,19 @@ export function addresses(options: addresses.Options = {}) {
|
|
|
2011
2026
|
const { address } = c.req.valid('param')
|
|
2012
2027
|
const query = c.req.valid('query')
|
|
2013
2028
|
|
|
2014
|
-
|
|
2015
|
-
|
|
2029
|
+
if (!query.include.includes('zones'))
|
|
2030
|
+
Cache.setPolicy(
|
|
2031
|
+
c,
|
|
2032
|
+
query.cursor === undefined ? Cache.policies.feed : Cache.policies.metadata,
|
|
2033
|
+
)
|
|
2016
2034
|
|
|
2017
2035
|
try {
|
|
2018
2036
|
const chainId = query.chainId ?? c.get('chainId')
|
|
2019
|
-
const
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
'address_activities',
|
|
2023
|
-
() =>
|
|
2024
|
-
Store.memoize(
|
|
2037
|
+
const listed = await Timing.time(c, 'address_activities', async () => {
|
|
2038
|
+
if (!query.include.includes('zones')) {
|
|
2039
|
+
const result = await Store.memoize(
|
|
2025
2040
|
() =>
|
|
2026
|
-
list(
|
|
2041
|
+
list(tidx({ chainId, tidx: c.get('getTidx')(chainId) }), {
|
|
2027
2042
|
address: address as Hex.Hex,
|
|
2028
2043
|
cursor: query.cursor,
|
|
2029
2044
|
group: query.group,
|
|
@@ -2036,18 +2051,54 @@ export function addresses(options: addresses.Options = {}) {
|
|
|
2036
2051
|
store: c.get('store'),
|
|
2037
2052
|
ttl: Ttl.seconds(15),
|
|
2038
2053
|
},
|
|
2039
|
-
)
|
|
2040
|
-
|
|
2054
|
+
)
|
|
2055
|
+
return { chainId, kind: 'chain' as const, ...result }
|
|
2056
|
+
}
|
|
2041
2057
|
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2058
|
+
const zoneChainIds = c.get('zoneChainIds')
|
|
2059
|
+
if (!zoneChainIds) throw new Error('Inferred Zone selection was not resolved.')
|
|
2060
|
+
const result = await Store.memoize(
|
|
2061
|
+
() =>
|
|
2062
|
+
listZones({
|
|
2063
|
+
address: address as Hex.Hex,
|
|
2064
|
+
cursor: query.cursor,
|
|
2065
|
+
group: query.group,
|
|
2066
|
+
limit: query.limit,
|
|
2067
|
+
logs: query.logs,
|
|
2068
|
+
providers: zoneChainIds.map((zoneChainId) => ({
|
|
2069
|
+
chainId: zoneChainId,
|
|
2070
|
+
provider: tidx({
|
|
2071
|
+
chainId: zoneChainId,
|
|
2072
|
+
tidx: c.get('getTidx')(zoneChainId),
|
|
2073
|
+
}),
|
|
2074
|
+
})),
|
|
2075
|
+
store: c.get('store'),
|
|
2076
|
+
}),
|
|
2077
|
+
{
|
|
2078
|
+
key: `activities:zones:v1:${zoneChainIds.join(',')}:${address.toLowerCase()}:${query.group ?? false}:${query.logs ?? false}:${query.cursor ?? 'head'}:${query.limit}`,
|
|
2079
|
+
store: c.get('store'),
|
|
2080
|
+
ttl: Ttl.seconds(15),
|
|
2081
|
+
},
|
|
2082
|
+
)
|
|
2083
|
+
return { kind: 'zones' as const, ...result }
|
|
2049
2084
|
})
|
|
2050
2085
|
|
|
2086
|
+
const { items, rates } =
|
|
2087
|
+
listed.kind === 'zones'
|
|
2088
|
+
? await enrichZoneTokens(c, {
|
|
2089
|
+
denomination: query['valuation.currency'],
|
|
2090
|
+
include: query.include,
|
|
2091
|
+
items: listed.items,
|
|
2092
|
+
oracle,
|
|
2093
|
+
})
|
|
2094
|
+
: await enrichTokens(c, {
|
|
2095
|
+
chainId: listed.chainId,
|
|
2096
|
+
denomination: query['valuation.currency'],
|
|
2097
|
+
include: query.include,
|
|
2098
|
+
items: listed.items,
|
|
2099
|
+
oracle,
|
|
2100
|
+
})
|
|
2101
|
+
|
|
2051
2102
|
// Fold consecutive access-key-signed items into `group` entries only
|
|
2052
2103
|
// when requested; otherwise every item is returned at the root.
|
|
2053
2104
|
const data = query.group ? groupByAccessKey(items) : items
|
|
@@ -2056,7 +2107,7 @@ export function addresses(options: addresses.Options = {}) {
|
|
|
2056
2107
|
Response.validated(schema.getAddressActivities.Response, {
|
|
2057
2108
|
data,
|
|
2058
2109
|
...(rates ? { meta: { valuation: Valuation.pricing(rates, oracle) } } : {}),
|
|
2059
|
-
nextCursor,
|
|
2110
|
+
nextCursor: listed.nextCursor,
|
|
2060
2111
|
}),
|
|
2061
2112
|
200,
|
|
2062
2113
|
)
|
|
@@ -2110,6 +2161,10 @@ export function transactions(options: transactions.Options = {}) {
|
|
|
2110
2161
|
description: 'No mined transaction was found for that hash.',
|
|
2111
2162
|
codes: ['transaction_not_found'],
|
|
2112
2163
|
},
|
|
2164
|
+
409: {
|
|
2165
|
+
description: 'More than one readable Zone contains that transaction hash.',
|
|
2166
|
+
codes: ['transaction_ambiguous'],
|
|
2167
|
+
},
|
|
2113
2168
|
502: 'Tempo could not read activity or token data from an upstream service.',
|
|
2114
2169
|
},
|
|
2115
2170
|
success: {
|
|
@@ -2142,48 +2197,123 @@ export function transactions(options: transactions.Options = {}) {
|
|
|
2142
2197
|
|
|
2143
2198
|
const { transactionHash } = c.req.valid('param')
|
|
2144
2199
|
const query = c.req.valid('query')
|
|
2145
|
-
const chainId = query.chainId ?? c.get('chainId')
|
|
2146
2200
|
|
|
2147
2201
|
try {
|
|
2148
|
-
const
|
|
2149
|
-
|
|
2150
|
-
()
|
|
2151
|
-
|
|
2152
|
-
chainId,
|
|
2153
|
-
|
|
2202
|
+
const result = await Timing.time(c, 'transaction_activities', async () => {
|
|
2203
|
+
const selected = await (async () => {
|
|
2204
|
+
if (!query.include.includes('zones'))
|
|
2205
|
+
return {
|
|
2206
|
+
chainId: query.chainId ?? c.get('chainId'),
|
|
2207
|
+
kind: 'selected' as const,
|
|
2208
|
+
receipt: null,
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
const zoneChainIds = c.get('zoneChainIds')
|
|
2212
|
+
if (!zoneChainIds) throw new Error('Inferred Zone selection was not resolved.')
|
|
2213
|
+
// Cache only positive resolution. Missing transactions must remain
|
|
2214
|
+
// visible as soon as their Zone indexer catches up.
|
|
2215
|
+
const match = await Store.memoize(
|
|
2216
|
+
async () => {
|
|
2217
|
+
const probes: readonly ZoneSelection.uniqueMatch.Probe<TransactionReceipt>[] =
|
|
2218
|
+
await Promise.all(
|
|
2219
|
+
zoneChainIds.map(async (chainId) => {
|
|
2220
|
+
try {
|
|
2221
|
+
return {
|
|
2222
|
+
chainId,
|
|
2223
|
+
value: await getTransactionReceipt({
|
|
2224
|
+
chainId,
|
|
2225
|
+
tidx: c.get('getTidx')(chainId),
|
|
2226
|
+
transactionHash,
|
|
2227
|
+
}),
|
|
2228
|
+
}
|
|
2229
|
+
} catch (cause) {
|
|
2230
|
+
return { cause, chainId }
|
|
2231
|
+
}
|
|
2232
|
+
}),
|
|
2233
|
+
)
|
|
2234
|
+
return ZoneSelection.uniqueMatch<TransactionReceipt>(probes)
|
|
2235
|
+
},
|
|
2236
|
+
{
|
|
2237
|
+
key: `activities:zones:v1:${zoneChainIds.join(',')}:tx:${transactionHash.toLowerCase()}`,
|
|
2238
|
+
shouldCache: (match) => match.kind === 'selected',
|
|
2154
2239
|
store: c.get('store'),
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2240
|
+
ttl: Ttl.seconds(15),
|
|
2241
|
+
},
|
|
2242
|
+
)
|
|
2243
|
+
if (match.kind === 'failed') {
|
|
2244
|
+
c.set(
|
|
2245
|
+
'providerFailures',
|
|
2246
|
+
match.failures.map(({ cause, chainId }) => ({
|
|
2247
|
+
...Tidx.providerFailure(cause),
|
|
2248
|
+
chainId,
|
|
2249
|
+
})),
|
|
2250
|
+
)
|
|
2251
|
+
throw match.failures[0]!.cause
|
|
2252
|
+
}
|
|
2253
|
+
if (match.kind !== 'selected') return match
|
|
2254
|
+
return { chainId: match.chainId, kind: 'selected' as const, receipt: match.value }
|
|
2255
|
+
})()
|
|
2256
|
+
|
|
2257
|
+
if (selected.kind !== 'selected') return selected
|
|
2258
|
+
const { chainId } = selected
|
|
2259
|
+
const unenrichedItems = await Store.memoize(
|
|
2260
|
+
() =>
|
|
2261
|
+
selected.receipt === null
|
|
2262
|
+
? getTransactionActivities({
|
|
2263
|
+
chainId,
|
|
2264
|
+
logs: query.logs,
|
|
2265
|
+
store: c.get('store'),
|
|
2266
|
+
tidx: c.get('getTidx')(chainId),
|
|
2267
|
+
transactionHash,
|
|
2268
|
+
})
|
|
2269
|
+
: classifyTransactionActivities({
|
|
2270
|
+
chainId,
|
|
2271
|
+
logs: query.logs,
|
|
2272
|
+
receipt: selected.receipt,
|
|
2273
|
+
store: c.get('store'),
|
|
2274
|
+
tidx: c.get('getTidx')(chainId),
|
|
2275
|
+
transactionHash,
|
|
2276
|
+
}),
|
|
2158
2277
|
{
|
|
2159
2278
|
key: `activities:v1:${chainId}:tx:${transactionHash.toLowerCase()}:${query.logs ?? false}`,
|
|
2160
2279
|
store: c.get('store'),
|
|
2161
2280
|
ttl: Ttl.seconds(15),
|
|
2162
2281
|
},
|
|
2163
|
-
)
|
|
2164
|
-
|
|
2282
|
+
)
|
|
2283
|
+
return unenrichedItems === null
|
|
2284
|
+
? ({ kind: 'not_found' } as const)
|
|
2285
|
+
: ({ chainId, items: unenrichedItems, kind: 'found' } as const)
|
|
2286
|
+
})
|
|
2165
2287
|
|
|
2166
|
-
if (
|
|
2288
|
+
if (result.kind === 'not_found')
|
|
2167
2289
|
return Response.error(c, {
|
|
2168
2290
|
code: 'transaction_not_found',
|
|
2169
2291
|
message: 'Transaction not found',
|
|
2170
2292
|
status: 404,
|
|
2171
2293
|
})
|
|
2294
|
+
if (result.kind === 'ambiguous')
|
|
2295
|
+
return Response.error(c, {
|
|
2296
|
+
code: 'transaction_ambiguous',
|
|
2297
|
+
message: 'Transaction hash matched more than one readable Zone',
|
|
2298
|
+
status: 409,
|
|
2299
|
+
})
|
|
2172
2300
|
|
|
2173
2301
|
// Mined activity can carry current valuations and verification data.
|
|
2174
|
-
Cache.setPolicy(c, Cache.policies.metadata)
|
|
2302
|
+
if (!query.include.includes('zones')) Cache.setPolicy(c, Cache.policies.metadata)
|
|
2303
|
+
c.set('chainId', result.chainId)
|
|
2175
2304
|
|
|
2176
2305
|
// Build immutable token and structured amount copies from RPC metadata.
|
|
2177
2306
|
const { items, rates } = await enrichTokens(c, {
|
|
2178
|
-
chainId,
|
|
2307
|
+
chainId: result.chainId,
|
|
2179
2308
|
denomination: query['valuation.currency'],
|
|
2180
2309
|
include: query.include,
|
|
2181
|
-
items:
|
|
2310
|
+
items: result.items,
|
|
2182
2311
|
oracle,
|
|
2183
2312
|
})
|
|
2184
2313
|
|
|
2185
2314
|
return c.json(
|
|
2186
2315
|
Response.validated(schema.getTransactionActivities.Response, {
|
|
2316
|
+
chainId: result.chainId,
|
|
2187
2317
|
data: items,
|
|
2188
2318
|
...(rates ? { meta: { valuation: Valuation.pricing(rates, oracle) } } : {}),
|
|
2189
2319
|
}),
|
|
@@ -2219,7 +2349,15 @@ export declare namespace transactions {
|
|
|
2219
2349
|
export async function getTransactionActivities(
|
|
2220
2350
|
options: getTransactionActivities.Options,
|
|
2221
2351
|
): Promise<UnenrichedItem[] | null> {
|
|
2222
|
-
const
|
|
2352
|
+
const receipt = await getTransactionReceipt(options)
|
|
2353
|
+
if (!receipt) return null
|
|
2354
|
+
return classifyTransactionActivities({ ...options, receipt })
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
async function getTransactionReceipt(
|
|
2358
|
+
options: getTransactionReceipt.Options,
|
|
2359
|
+
): Promise<TransactionReceipt | null> {
|
|
2360
|
+
const { chainId, tidx: tidxClient } = options
|
|
2223
2361
|
const hash = options.transactionHash.toLowerCase()
|
|
2224
2362
|
|
|
2225
2363
|
// The `receipts` table is indexed by `tx_hash`, so this point lookup needs no
|
|
@@ -2234,9 +2372,33 @@ export async function getTransactionActivities(
|
|
|
2234
2372
|
const receipt = receiptResult.rows[0]
|
|
2235
2373
|
if (!receipt) return null
|
|
2236
2374
|
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2375
|
+
return {
|
|
2376
|
+
blockNum: Number(Value.toNumber(receipt['block_num'])),
|
|
2377
|
+
feePayer: lowerOrNull(receipt['fee_payer']),
|
|
2378
|
+
txSender: lowerOrNull(receipt['from']),
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
declare namespace getTransactionReceipt {
|
|
2383
|
+
type Options = Pick<getTransactionActivities.Options, 'chainId' | 'tidx' | 'transactionHash'>
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
type TransactionReceipt = {
|
|
2387
|
+
/** Block number containing the transaction. */
|
|
2388
|
+
blockNum: number
|
|
2389
|
+
/** Account that paid the transaction fee, when indexed. */
|
|
2390
|
+
feePayer: Address.Address | null
|
|
2391
|
+
/** Account that sent the transaction, when indexed. */
|
|
2392
|
+
txSender: Address.Address | null
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
async function classifyTransactionActivities(
|
|
2396
|
+
options: classifyTransactionActivities.Options,
|
|
2397
|
+
): Promise<UnenrichedItem[]> {
|
|
2398
|
+
const { chainId, logs = false, receipt, tidx: tidxClient } = options
|
|
2399
|
+
const hash = options.transactionHash.toLowerCase()
|
|
2400
|
+
const { blockNum, feePayer, txSender } = receipt
|
|
2401
|
+
const fingerprintMap_promise = Mpp.fingerprintMap({ store: options.store }).catch(() => ({}))
|
|
2240
2402
|
|
|
2241
2403
|
// `logs` is sorted by block position, so a bare `tx_hash =` scans to genesis;
|
|
2242
2404
|
// pair it with the receipt's block number (see `embedReceipts` in receipts.ts).
|
|
@@ -2269,7 +2431,7 @@ export async function getTransactionActivities(
|
|
|
2269
2431
|
|
|
2270
2432
|
// Best-effort MPP service directory: a fetch failure yields an empty map, so
|
|
2271
2433
|
// enrichment never blocks classification.
|
|
2272
|
-
const fingerprintMap = await
|
|
2434
|
+
const fingerprintMap = await fingerprintMap_promise
|
|
2273
2435
|
|
|
2274
2436
|
// Anchor the viewer on the transaction sender: the sender initiated every
|
|
2275
2437
|
// activity in the transaction, so `perspective` is `outgoing` and `signer`
|
|
@@ -2279,6 +2441,13 @@ export async function getTransactionActivities(
|
|
|
2279
2441
|
return classifyGroup(group, viewer, fingerprintMap, logs).map(withTitle)
|
|
2280
2442
|
}
|
|
2281
2443
|
|
|
2444
|
+
declare namespace classifyTransactionActivities {
|
|
2445
|
+
type Options = getTransactionActivities.Options & {
|
|
2446
|
+
/** Indexed receipt fields used to bound the log lookup. */
|
|
2447
|
+
receipt: TransactionReceipt
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2282
2451
|
export declare namespace getTransactionActivities {
|
|
2283
2452
|
/** Options for {@link getTransactionActivities}. */
|
|
2284
2453
|
type Options = {
|
|
@@ -2298,8 +2467,8 @@ export declare namespace getTransactionActivities {
|
|
|
2298
2467
|
/**
|
|
2299
2468
|
* Lists classified activity for an address by running the shared pipeline
|
|
2300
2469
|
* (`groupByTx` → `classifyGroup` → `enrichItem`) over rows from a
|
|
2301
|
-
* {@link Provider}. Returns
|
|
2302
|
-
*
|
|
2470
|
+
* {@link Provider}. Returns classified items plus the next cursor; callers run
|
|
2471
|
+
* {@link groupByAccessKey} over the result.
|
|
2303
2472
|
*/
|
|
2304
2473
|
export async function list(provider: Provider, options: list.Options): Promise<list.ReturnType> {
|
|
2305
2474
|
const { address, cursor, group = false, limit = 20, logs = false } = options
|
|
@@ -2307,7 +2476,7 @@ export async function list(provider: Provider, options: list.Options): Promise<l
|
|
|
2307
2476
|
|
|
2308
2477
|
// Best-effort MPP service directory: a fetch failure yields an empty map, so
|
|
2309
2478
|
// enrichment never blocks the feed.
|
|
2310
|
-
const
|
|
2479
|
+
const fingerprintMap_promise = Mpp.fingerprintMap({ store: options.store }).catch(() => ({}))
|
|
2311
2480
|
|
|
2312
2481
|
let currentCursor: string | undefined = cursor
|
|
2313
2482
|
const allItems: UnenrichedItem[] = []
|
|
@@ -2326,6 +2495,7 @@ export async function list(provider: Provider, options: list.Options): Promise<l
|
|
|
2326
2495
|
hasMore = txGroups.length > limit
|
|
2327
2496
|
const page = txGroups.slice(0, limit)
|
|
2328
2497
|
|
|
2498
|
+
const fingerprintMap = await fingerprintMap_promise
|
|
2329
2499
|
if (page.length === 0) break
|
|
2330
2500
|
|
|
2331
2501
|
allItems.push(
|
|
@@ -2374,6 +2544,175 @@ export declare namespace list {
|
|
|
2374
2544
|
}
|
|
2375
2545
|
}
|
|
2376
2546
|
|
|
2547
|
+
const zoneCursorVersion = 1
|
|
2548
|
+
|
|
2549
|
+
type ZonePageState = {
|
|
2550
|
+
/** Zone chain id backing this page state. */
|
|
2551
|
+
chainId: number
|
|
2552
|
+
/** Whether the current buffer reaches the end of this Zone feed. */
|
|
2553
|
+
exhausted: boolean
|
|
2554
|
+
/** Unconsumed transaction groups already fetched from this Zone. */
|
|
2555
|
+
groups: TxGroup[]
|
|
2556
|
+
/** Activity data source for this Zone. */
|
|
2557
|
+
provider: Provider
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
/**
|
|
2561
|
+
* Lists address activity across multiple Zones in one stable timestamp-ordered
|
|
2562
|
+
* feed. Its opaque cursor retains each Zone provider's native continuation.
|
|
2563
|
+
*/
|
|
2564
|
+
export async function listZones(options: listZones.Options): Promise<listZones.ReturnType> {
|
|
2565
|
+
const { address, cursor, limit = 20, logs = false, providers, store } = options
|
|
2566
|
+
const group = options.group ?? false
|
|
2567
|
+
const orderedProviders = [...providers].sort((a, b) => a.chainId - b.chainId)
|
|
2568
|
+
const chainIds = orderedProviders.map(({ chainId }) => chainId)
|
|
2569
|
+
const cursors = decodeZoneCursor(cursor, chainIds)
|
|
2570
|
+
const viewer = address.toLowerCase() as Address.Address
|
|
2571
|
+
const fingerprintMap_promise = Mpp.fingerprintMap({ store }).catch(() => ({}))
|
|
2572
|
+
const states: ZonePageState[] = orderedProviders.map(({ chainId, provider }) => ({
|
|
2573
|
+
chainId,
|
|
2574
|
+
exhausted: false,
|
|
2575
|
+
groups: [],
|
|
2576
|
+
provider,
|
|
2577
|
+
}))
|
|
2578
|
+
const allItems: listZones.Item[] = []
|
|
2579
|
+
let hasMore = false
|
|
2580
|
+
|
|
2581
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
2582
|
+
await Promise.all(
|
|
2583
|
+
states.map(async (state) => {
|
|
2584
|
+
if (state.exhausted || state.groups.length > 0) return
|
|
2585
|
+
const { rows } = await state.provider.fetchRows({
|
|
2586
|
+
address: viewer,
|
|
2587
|
+
cursor: cursors.get(state.chainId),
|
|
2588
|
+
limit,
|
|
2589
|
+
})
|
|
2590
|
+
const groups = groupByTx(rows).slice(0, limit + 1)
|
|
2591
|
+
state.exhausted = groups.length <= limit
|
|
2592
|
+
state.groups.push(...groups)
|
|
2593
|
+
}),
|
|
2594
|
+
)
|
|
2595
|
+
const candidates = states
|
|
2596
|
+
.flatMap((state) => state.groups.map((txGroup) => ({ state, txGroup })))
|
|
2597
|
+
.sort((a, b) => {
|
|
2598
|
+
if (a.txGroup.blockTimestamp !== b.txGroup.blockTimestamp)
|
|
2599
|
+
return b.txGroup.blockTimestamp - a.txGroup.blockTimestamp
|
|
2600
|
+
if (a.state.chainId !== b.state.chainId) return a.state.chainId - b.state.chainId
|
|
2601
|
+
if (a.txGroup.blockNum !== b.txGroup.blockNum)
|
|
2602
|
+
return b.txGroup.blockNum - a.txGroup.blockNum
|
|
2603
|
+
return b.txGroup.txIdx - a.txGroup.txIdx
|
|
2604
|
+
})
|
|
2605
|
+
const page = candidates.slice(0, limit)
|
|
2606
|
+
const fingerprintMap = await fingerprintMap_promise
|
|
2607
|
+
if (page.length === 0) break
|
|
2608
|
+
|
|
2609
|
+
for (const { state, txGroup } of page) {
|
|
2610
|
+
state.groups.splice(state.groups.indexOf(txGroup), 1)
|
|
2611
|
+
cursors.set(state.chainId, state.provider.cursorForGroup(txGroup))
|
|
2612
|
+
allItems.push(
|
|
2613
|
+
...classifyGroup(txGroup, viewer, fingerprintMap, logs).map((item) => ({
|
|
2614
|
+
...withTitle(item),
|
|
2615
|
+
chainId: state.chainId,
|
|
2616
|
+
})),
|
|
2617
|
+
)
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
hasMore = states.some((state) => !state.exhausted || state.groups.length > 0)
|
|
2621
|
+
const enough = group
|
|
2622
|
+
? groupByAccessKeyItems(allItems).length >= minGroupEntries
|
|
2623
|
+
: allItems.length >= limit
|
|
2624
|
+
if (enough || !hasMore) break
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
// A consumed sentinel proves only that the provider may have more rows.
|
|
2628
|
+
// Probe drained buffers so `nextCursor` remains the end-of-list signal.
|
|
2629
|
+
await Promise.all(
|
|
2630
|
+
states.map(async (state) => {
|
|
2631
|
+
if (state.exhausted || state.groups.length > 0) return
|
|
2632
|
+
const { rows } = await state.provider.fetchRows({
|
|
2633
|
+
address: viewer,
|
|
2634
|
+
cursor: cursors.get(state.chainId),
|
|
2635
|
+
limit: 1,
|
|
2636
|
+
})
|
|
2637
|
+
const group = groupByTx(rows)[0]
|
|
2638
|
+
if (group) state.groups.push(group)
|
|
2639
|
+
else state.exhausted = true
|
|
2640
|
+
}),
|
|
2641
|
+
)
|
|
2642
|
+
hasMore = states.some((state) => !state.exhausted || state.groups.length > 0)
|
|
2643
|
+
|
|
2644
|
+
return {
|
|
2645
|
+
items: allItems,
|
|
2646
|
+
nextCursor: hasMore ? encodeZoneCursor(cursors, chainIds) : null,
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
export declare namespace listZones {
|
|
2651
|
+
/** One Zone activity provider. */
|
|
2652
|
+
type ChainProvider = {
|
|
2653
|
+
/** Zone chain id. */
|
|
2654
|
+
chainId: number
|
|
2655
|
+
/** Activity data source for the Zone. */
|
|
2656
|
+
provider: Provider
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
/** A classified item tagged with its Zone chain id. */
|
|
2660
|
+
type Item = UnenrichedItem & {
|
|
2661
|
+
/** Zone chain id containing the activity. */
|
|
2662
|
+
chainId: number
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
/** Options for {@link listZones}. */
|
|
2666
|
+
type Options = {
|
|
2667
|
+
/** Subject account address. */
|
|
2668
|
+
address: Address.Address
|
|
2669
|
+
/** Opaque multi-Zone cursor from a previous page. */
|
|
2670
|
+
cursor?: string | undefined
|
|
2671
|
+
/** Whether the caller will fold access-key items. */
|
|
2672
|
+
group?: boolean | undefined
|
|
2673
|
+
/** Target number of transaction groups per page. */
|
|
2674
|
+
limit?: number | undefined
|
|
2675
|
+
/** Attach each item's full transaction event capture. */
|
|
2676
|
+
logs?: boolean | undefined
|
|
2677
|
+
/** Zone providers participating in the merged feed. */
|
|
2678
|
+
providers: readonly ChainProvider[]
|
|
2679
|
+
/** Cache store for the MPP fingerprint-directory lookup. */
|
|
2680
|
+
store: Store.Store
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
/** Multi-Zone classified page before token enrichment. */
|
|
2684
|
+
type ReturnType = {
|
|
2685
|
+
/** Timestamp-ordered, chain-tagged activity items. */
|
|
2686
|
+
items: Item[]
|
|
2687
|
+
/** Opaque continuation for every Zone, or null at the end. */
|
|
2688
|
+
nextCursor: string | null
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
function decodeZoneCursor(cursor: string | undefined, chainIds: readonly number[]) {
|
|
2693
|
+
const fields: Cursor.Field[] = ['int']
|
|
2694
|
+
for (const _chainId of chainIds) fields.push('int', 'id')
|
|
2695
|
+
const decoded = cursor ? Cursor.decode(cursor, fields) : undefined
|
|
2696
|
+
const cursors = new Map<number, string>()
|
|
2697
|
+
if (!decoded || decoded[0] !== zoneCursorVersion) return cursors
|
|
2698
|
+
|
|
2699
|
+
for (let index = 0; index < chainIds.length; index++) {
|
|
2700
|
+
const chainId = chainIds[index]!
|
|
2701
|
+
const offset = index * 2 + 1
|
|
2702
|
+
if (decoded[offset] !== chainId) return new Map()
|
|
2703
|
+
const value = decoded[offset + 1] as string
|
|
2704
|
+
if (value !== 'head') cursors.set(chainId, value)
|
|
2705
|
+
}
|
|
2706
|
+
return cursors
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
function encodeZoneCursor(cursors: ReadonlyMap<number, string>, chainIds: readonly number[]) {
|
|
2710
|
+
return Cursor.encode([
|
|
2711
|
+
zoneCursorVersion,
|
|
2712
|
+
...chainIds.flatMap((chainId) => [chainId, cursors.get(chainId) ?? 'head']),
|
|
2713
|
+
])
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2377
2716
|
/**
|
|
2378
2717
|
* Creates a TIDX-backed {@link Provider} that runs three sub-queries in
|
|
2379
2718
|
* parallel and merges them:
|
|
@@ -2727,15 +3066,46 @@ function classifyFromLogs(
|
|
|
2727
3066
|
viewer: Address.Address
|
|
2728
3067
|
},
|
|
2729
3068
|
): RawItem[] {
|
|
2730
|
-
const
|
|
3069
|
+
const decoded = decodeRows(rows)
|
|
3070
|
+
const items = (() => {
|
|
3071
|
+
try {
|
|
3072
|
+
return classifyFromLogsCore(rows, ctx, decoded)
|
|
3073
|
+
} catch {
|
|
3074
|
+
// Indexed logs can match a known signature without satisfying that event's expected shape.
|
|
3075
|
+
return [
|
|
3076
|
+
unknown(ctx.itemBase(Math.min(...rows.map((row) => row.logIdx))), {
|
|
3077
|
+
events: buildTxEvents(rows, decoded),
|
|
3078
|
+
signer: signerForRows(rows, { fallback: ctx.signer, viewer: ctx.viewer }),
|
|
3079
|
+
}),
|
|
3080
|
+
]
|
|
3081
|
+
}
|
|
3082
|
+
})()
|
|
2731
3083
|
// When the caller requested raw logs, attach the full per-transaction log set
|
|
2732
3084
|
// (decoded when possible) to every classified item so no co-located log is
|
|
2733
3085
|
// hidden behind the headline. `unknown` items already carry it.
|
|
2734
3086
|
if (!ctx.includeLogs) return items
|
|
2735
|
-
const events = buildTxEvents(rows,
|
|
3087
|
+
const events = buildTxEvents(rows, decoded)
|
|
2736
3088
|
return items.map((item) => (item.type === 'unknown' ? item : { ...item, events }))
|
|
2737
3089
|
}
|
|
2738
3090
|
|
|
3091
|
+
/** Resolves an access-key signer from raw rows, falling back to the transaction signer. */
|
|
3092
|
+
function signerForRows(
|
|
3093
|
+
rows: readonly Row[],
|
|
3094
|
+
options: { fallback: 'self' | Address.Address; viewer: Address.Address },
|
|
3095
|
+
) {
|
|
3096
|
+
const accessKeySpendRow = rows.find(
|
|
3097
|
+
(row) =>
|
|
3098
|
+
row.selector === accessKeySpendSelector &&
|
|
3099
|
+
Address.isEqual(row.logAddress, Addresses.accountKeychain),
|
|
3100
|
+
)
|
|
3101
|
+
const accessKeySigner = accessKeySpendRow?.topic2
|
|
3102
|
+
? (`0x${accessKeySpendRow.topic2.slice(-40)}`.toLowerCase() as Address.Address)
|
|
3103
|
+
: null
|
|
3104
|
+
return accessKeySigner && !Address.isEqual(accessKeySigner, options.viewer)
|
|
3105
|
+
? accessKeySigner
|
|
3106
|
+
: options.fallback
|
|
3107
|
+
}
|
|
3108
|
+
|
|
2739
3109
|
/** Classifies a Q1 (log-bearing) group via `parseEventLogs`, picking one headline item. */
|
|
2740
3110
|
function classifyFromLogsCore(
|
|
2741
3111
|
rows: Row[],
|
|
@@ -2746,24 +3116,11 @@ function classifyFromLogsCore(
|
|
|
2746
3116
|
signer: 'self' | Address.Address
|
|
2747
3117
|
viewer: Address.Address
|
|
2748
3118
|
},
|
|
3119
|
+
events = decodeRows(rows),
|
|
2749
3120
|
): RawItem[] {
|
|
2750
3121
|
const { blockNum, fingerprintMap, itemBase, viewer } = ctx
|
|
2751
3122
|
|
|
2752
|
-
|
|
2753
|
-
// is the access-key publicKey. Use it as the signer so successive access-key
|
|
2754
|
-
// actions group together.
|
|
2755
|
-
const accessKeySpendRow = rows.find(
|
|
2756
|
-
(r) =>
|
|
2757
|
-
r.selector === accessKeySpendSelector &&
|
|
2758
|
-
Address.isEqual(r.logAddress, Addresses.accountKeychain),
|
|
2759
|
-
)
|
|
2760
|
-
const accessKeySigner = accessKeySpendRow?.topic2
|
|
2761
|
-
? (`0x${accessKeySpendRow.topic2.slice(-40)}`.toLowerCase() as Address.Address)
|
|
2762
|
-
: null
|
|
2763
|
-
const signer: 'self' | Address.Address =
|
|
2764
|
-
accessKeySigner && !Address.isEqual(accessKeySigner, viewer) ? accessKeySigner : ctx.signer
|
|
2765
|
-
|
|
2766
|
-
const events = decodeRows(rows)
|
|
3123
|
+
const signer = signerForRows(rows, { fallback: ctx.signer, viewer })
|
|
2767
3124
|
|
|
2768
3125
|
const minLogIndex = Math.min(...rows.map((r) => r.logIdx))
|
|
2769
3126
|
|
|
@@ -3251,6 +3608,14 @@ function classifyFromLogsCore(
|
|
|
3251
3608
|
const approvalEvent = finalEvents.find(
|
|
3252
3609
|
(e) =>
|
|
3253
3610
|
e.eventName === 'Approval' &&
|
|
3611
|
+
// ERC-721 uses the same selector but indexes its token ID as topic3. In
|
|
3612
|
+
// non-strict mode viem otherwise decodes the missing ERC-20 amount as zero.
|
|
3613
|
+
rows.some(
|
|
3614
|
+
(row) =>
|
|
3615
|
+
row.logIdx === e.logIndex &&
|
|
3616
|
+
row.topic3 === null &&
|
|
3617
|
+
/^0x[0-9a-fA-F]{64}$/.test(row.data ?? ''),
|
|
3618
|
+
) &&
|
|
3254
3619
|
!Address.isEqual((e.args as { spender: Address.Address }).spender, Addresses.zoneOutbox),
|
|
3255
3620
|
)
|
|
3256
3621
|
if (approvalEvent) {
|
|
@@ -4338,21 +4703,27 @@ function unknown(
|
|
|
4338
4703
|
|
|
4339
4704
|
/** Decodes a group's raw rows into `viem/tempo` events via `parseEventLogs` (non-strict). */
|
|
4340
4705
|
function decodeRows(rows: readonly Row[]) {
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4706
|
+
return rows.flatMap((r) => {
|
|
4707
|
+
const log: Log = {
|
|
4708
|
+
address: r.logAddress as `0x${string}`,
|
|
4709
|
+
blockHash: '0x0' as Hex.Hex,
|
|
4710
|
+
blockNumber: BigInt(r.blockNum),
|
|
4711
|
+
data: (r.data ?? '0x') as Hex.Hex,
|
|
4712
|
+
logIndex: r.logIdx,
|
|
4713
|
+
removed: false,
|
|
4714
|
+
topics: [r.selector, r.topic1, r.topic2, r.topic3].filter(Boolean) as [Hex.Hex, ...Hex.Hex[]],
|
|
4715
|
+
transactionHash: r.txHash as `0x${string}`,
|
|
4716
|
+
transactionIndex: r.txIdx,
|
|
4717
|
+
}
|
|
4718
|
+
try {
|
|
4719
|
+
return parseEventLogs({
|
|
4720
|
+
abi: [...Abis.abis, ...Abis.earnRouter, ...Abis.earnVault],
|
|
4721
|
+
logs: [log],
|
|
4722
|
+
strict: false,
|
|
4723
|
+
})
|
|
4724
|
+
} catch {
|
|
4725
|
+
return []
|
|
4726
|
+
}
|
|
4356
4727
|
})
|
|
4357
4728
|
}
|
|
4358
4729
|
|
|
@@ -4489,49 +4860,63 @@ async function enrichTokens(
|
|
|
4489
4860
|
for (const item of items) collectTokens(item, addresses)
|
|
4490
4861
|
const includeLogoUri = include.includes('token.logoUri')
|
|
4491
4862
|
const includeVerified = include.includes('token.verified')
|
|
4863
|
+
const resolved_promise =
|
|
4864
|
+
addresses.size > 0
|
|
4865
|
+
? Timing.time(c, 'tokens', () =>
|
|
4866
|
+
Promise.all(
|
|
4867
|
+
[...addresses].map(async (address) => {
|
|
4868
|
+
const [logoUri, metadata] = await Promise.all([
|
|
4869
|
+
includeLogoUri
|
|
4870
|
+
? Tokens.getTokenLogo(c, { address, chainId }).catch(() => undefined)
|
|
4871
|
+
: undefined,
|
|
4872
|
+
getActivityTokenMetadata(c, { address, chainId }),
|
|
4873
|
+
])
|
|
4874
|
+
return { address: address.toLowerCase(), logoUri, metadata }
|
|
4875
|
+
}),
|
|
4876
|
+
),
|
|
4877
|
+
)
|
|
4878
|
+
: undefined
|
|
4492
4879
|
// Curated data is needed only for requested valuation or token fields.
|
|
4493
|
-
const
|
|
4880
|
+
const snapshot_promise =
|
|
4494
4881
|
addresses.size > 0 && (denomination !== undefined || includeLogoUri || includeVerified)
|
|
4495
|
-
?
|
|
4496
|
-
: undefined
|
|
4497
|
-
const
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4882
|
+
? VerifiedTokens.snapshot(c, chainId).catch(() => undefined)
|
|
4883
|
+
: Promise.resolve(undefined)
|
|
4884
|
+
const rates_promise = (async () => {
|
|
4885
|
+
if (!denomination) return undefined
|
|
4886
|
+
const snapshot = await snapshot_promise
|
|
4887
|
+
return Valuation.ratesFor(c, {
|
|
4888
|
+
currencies: snapshot
|
|
4889
|
+
? [...addresses].flatMap((address) => {
|
|
4890
|
+
const held = snapshot.byAddress.get(address)?.currency
|
|
4891
|
+
return held === undefined ? [] : [held]
|
|
4892
|
+
})
|
|
4893
|
+
: [],
|
|
4894
|
+
denomination,
|
|
4895
|
+
oracle,
|
|
4896
|
+
})
|
|
4897
|
+
})()
|
|
4898
|
+
if (!resolved_promise) return { items: items as Item[], rates: await rates_promise }
|
|
4899
|
+
|
|
4900
|
+
const [resolved_raw, rates, snapshot] = await Promise.all([
|
|
4901
|
+
resolved_promise,
|
|
4902
|
+
rates_promise,
|
|
4903
|
+
snapshot_promise,
|
|
4904
|
+
])
|
|
4905
|
+
const resolved = resolved_raw.map(
|
|
4906
|
+
({ address, logoUri, metadata }) =>
|
|
4907
|
+
[
|
|
4908
|
+
address,
|
|
4909
|
+
{
|
|
4910
|
+
currency: metadata.currency,
|
|
4911
|
+
decimals: metadata.decimals,
|
|
4912
|
+
logoUri: includeLogoUri
|
|
4913
|
+
? (logoUri ?? snapshot?.byAddress.get(address)?.logoUri ?? metadata.logoUri)
|
|
4517
4914
|
: undefined,
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
currency: metadata.currency,
|
|
4524
|
-
decimals: metadata.decimals,
|
|
4525
|
-
logoUri: includeLogoUri
|
|
4526
|
-
? (logoUri ?? snapshot?.byAddress.get(address)?.logoUri ?? metadata.logoUri)
|
|
4527
|
-
: undefined,
|
|
4528
|
-
name: metadata.name,
|
|
4529
|
-
symbol: metadata.symbol,
|
|
4530
|
-
verified: includeVerified && snapshot ? snapshot.byAddress.has(address) : undefined,
|
|
4531
|
-
},
|
|
4532
|
-
] as const
|
|
4533
|
-
}),
|
|
4534
|
-
),
|
|
4915
|
+
name: metadata.name,
|
|
4916
|
+
symbol: metadata.symbol,
|
|
4917
|
+
verified: includeVerified && snapshot ? snapshot.byAddress.has(address) : undefined,
|
|
4918
|
+
},
|
|
4919
|
+
] as const,
|
|
4535
4920
|
)
|
|
4536
4921
|
const byAddress = new Map(resolved)
|
|
4537
4922
|
return {
|
|
@@ -4552,6 +4937,54 @@ declare namespace enrichTokens {
|
|
|
4552
4937
|
}
|
|
4553
4938
|
}
|
|
4554
4939
|
|
|
4940
|
+
/** Resolves token metadata on each item's source Zone without changing feed order. */
|
|
4941
|
+
async function enrichZoneTokens(
|
|
4942
|
+
c: Context<App.Environment>,
|
|
4943
|
+
options: enrichZoneTokens.Options,
|
|
4944
|
+
): Promise<{ items: Item[]; rates: FxOracle.RateSet | undefined }> {
|
|
4945
|
+
const byChain = new Map<number, listZones.Item[]>()
|
|
4946
|
+
for (const item of options.items) {
|
|
4947
|
+
const items = byChain.get(item.chainId) ?? []
|
|
4948
|
+
items.push(item)
|
|
4949
|
+
byChain.set(item.chainId, items)
|
|
4950
|
+
}
|
|
4951
|
+
const results = await Promise.all(
|
|
4952
|
+
[...byChain].map(async ([chainId, items]) => ({
|
|
4953
|
+
chainId,
|
|
4954
|
+
...(await enrichTokens(c, {
|
|
4955
|
+
chainId,
|
|
4956
|
+
denomination: options.denomination,
|
|
4957
|
+
include: options.include,
|
|
4958
|
+
items,
|
|
4959
|
+
oracle: options.oracle,
|
|
4960
|
+
})),
|
|
4961
|
+
})),
|
|
4962
|
+
)
|
|
4963
|
+
type Bucket = { index: number; items: Item[] }
|
|
4964
|
+
const buckets = new Map<number, Bucket>()
|
|
4965
|
+
for (const result of results) buckets.set(result.chainId, { index: 0, items: result.items })
|
|
4966
|
+
return {
|
|
4967
|
+
items: options.items.map((item) => {
|
|
4968
|
+
const bucket = buckets.get(item.chainId)!
|
|
4969
|
+
return bucket.items[bucket.index++]!
|
|
4970
|
+
}),
|
|
4971
|
+
rates: results.find((result) => result.rates !== undefined)?.rates,
|
|
4972
|
+
}
|
|
4973
|
+
}
|
|
4974
|
+
|
|
4975
|
+
declare namespace enrichZoneTokens {
|
|
4976
|
+
type Options = {
|
|
4977
|
+
/** Currency the amount valuations are denominated in. */
|
|
4978
|
+
denomination?: string | undefined
|
|
4979
|
+
/** Optional token fields to resolve. */
|
|
4980
|
+
include: readonly z.output<typeof schema.Include>[]
|
|
4981
|
+
/** Chain-tagged items awaiting token enrichment. */
|
|
4982
|
+
items: readonly listZones.Item[]
|
|
4983
|
+
/** FX rate oracle backing amount valuation. */
|
|
4984
|
+
oracle: FxOracle.Oracle
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
|
|
4555
4988
|
/** Returns an enriched copy of an item without mutating its cached token stubs. */
|
|
4556
4989
|
function enrichItem(
|
|
4557
4990
|
item: UnenrichedItem,
|
|
@@ -4619,6 +5052,7 @@ export function groupByAccessKey(items: Item[]): Entry[] {
|
|
|
4619
5052
|
}
|
|
4620
5053
|
|
|
4621
5054
|
type GroupableItem = {
|
|
5055
|
+
chainId?: number | undefined
|
|
4622
5056
|
data: object
|
|
4623
5057
|
id: string
|
|
4624
5058
|
perspective: 'incoming' | 'outgoing'
|
|
@@ -4628,6 +5062,7 @@ type GroupableItem = {
|
|
|
4628
5062
|
type GroupedItem<item extends GroupableItem> =
|
|
4629
5063
|
| item
|
|
4630
5064
|
| {
|
|
5065
|
+
chainId?: number | undefined
|
|
4631
5066
|
data: { items: item[]; signer: Address.Address }
|
|
4632
5067
|
id: string
|
|
4633
5068
|
perspective: 'incoming' | 'outgoing'
|
|
@@ -4646,6 +5081,7 @@ function groupByAccessKeyItems<item extends GroupableItem>(items: item[]): Group
|
|
|
4646
5081
|
if (itemSigner !== 'self') {
|
|
4647
5082
|
if (
|
|
4648
5083
|
currentGroup &&
|
|
5084
|
+
currentGroup.items[0]!.chainId === item.chainId &&
|
|
4649
5085
|
Address.isEqual(currentGroup.signer, itemSigner) &&
|
|
4650
5086
|
sameCalendarDay(currentGroup.items[0]!.timestamp, item.timestamp)
|
|
4651
5087
|
) {
|
|
@@ -4685,6 +5121,7 @@ function flushGroup<item extends GroupableItem>(group: {
|
|
|
4685
5121
|
const firstItem = group.items[0]!
|
|
4686
5122
|
const lastItem = group.items[group.items.length - 1]!
|
|
4687
5123
|
return {
|
|
5124
|
+
...(firstItem.chainId === undefined ? {} : { chainId: firstItem.chainId }),
|
|
4688
5125
|
data: { items: group.items, signer: group.signer },
|
|
4689
5126
|
perspective: firstItem.perspective,
|
|
4690
5127
|
id: `${firstItem.id}..${lastItem.id}:${group.items.length}`,
|