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
|
@@ -19,12 +19,13 @@ import * as Ttl from '../../../internal/Ttl.js';
|
|
|
19
19
|
import * as Value from '../../../internal/Value.js';
|
|
20
20
|
import * as VerifiedTokens from '../../../internal/VerifiedTokens.js';
|
|
21
21
|
import * as FxOracle from '../FxOracle.js';
|
|
22
|
+
import * as ZoneSelection from '../ZoneSelection.js';
|
|
22
23
|
import * as Tokens from './tokens.js';
|
|
23
24
|
import * as Transfers from './transfers.js';
|
|
24
25
|
import * as Valuation from './valuation.js';
|
|
25
26
|
/** Example transaction hash surfaced in OpenAPI docs. */
|
|
26
27
|
const exampleHash = '0x4845ae2098724ab26a5d89370dce5124d044be6a5acc164afc348662de67d474';
|
|
27
|
-
const
|
|
28
|
+
const includeFields = ['token.logoUri', 'token.verified', 'zones'];
|
|
28
29
|
// TIP-20 tokens live at deterministic `0x20c0…` addresses. Other contracts
|
|
29
30
|
// can emit the same `Transfer` signature but do not expose TIP-20 metadata.
|
|
30
31
|
const tip20AddressPrefix = '0x20c0';
|
|
@@ -130,6 +131,9 @@ export var schema;
|
|
|
130
131
|
* transfer's `direction`/`memo`/`attribution`/`signer`) the resource lacks.
|
|
131
132
|
*/
|
|
132
133
|
const base = {
|
|
134
|
+
chainId: z
|
|
135
|
+
.optional(Schema.ChainId)
|
|
136
|
+
.check(z.describe('Chain id containing this activity. Returned for multi-Zone requests.'), z.meta({ examples: [421700001] })),
|
|
133
137
|
perspective: z
|
|
134
138
|
.enum(['incoming', 'outgoing'])
|
|
135
139
|
.check(z.describe('Your role in the transaction: `outgoing` when you sent or paid for it, `incoming` when it happened to you (someone else initiated it). For a `transfer`, `data.direction` is the finer-grained token-flow view.')),
|
|
@@ -820,9 +824,7 @@ export var schema;
|
|
|
820
824
|
data: z
|
|
821
825
|
.object({
|
|
822
826
|
logoUri: z.string().check(z.describe('New logo URL for the token.'), z.meta({
|
|
823
|
-
examples: [
|
|
824
|
-
'https://api.tempo.xyz/data/4217/icons/0x20c0000000000000000000008f5425160ebe5525.svg',
|
|
825
|
-
],
|
|
827
|
+
examples: [Tokens.tokenExample.logoUri],
|
|
826
828
|
})),
|
|
827
829
|
signer: Signer,
|
|
828
830
|
updater: Schema.Address.check(z.describe('Address that changed the logo.')),
|
|
@@ -1261,6 +1263,9 @@ export var schema;
|
|
|
1261
1263
|
/** A folded access-key group: consecutive same-signer items on one UTC day. */
|
|
1262
1264
|
schema.Group = z
|
|
1263
1265
|
.object({
|
|
1266
|
+
chainId: z
|
|
1267
|
+
.optional(Schema.ChainId)
|
|
1268
|
+
.check(z.describe('Chain id containing this activity group. Returned for multi-Zone requests.'), z.meta({ examples: [421700001] })),
|
|
1264
1269
|
data: z
|
|
1265
1270
|
.object({
|
|
1266
1271
|
items: z.array(schema.Item).check(z.describe('Activity items included in this group.')),
|
|
@@ -1288,12 +1293,12 @@ export var schema;
|
|
|
1288
1293
|
schema.Entry = z
|
|
1289
1294
|
.union([...schema.items, schema.Group])
|
|
1290
1295
|
.check(z.describe('Either one activity item, or a grouped set of access-key activity items.'));
|
|
1291
|
-
/** Optional
|
|
1296
|
+
/** Optional activity resources and selection modes. */
|
|
1292
1297
|
schema.Include = z
|
|
1293
|
-
.enum(
|
|
1294
|
-
.check(z.describe('Additional
|
|
1295
|
-
/** Parses comma-separated optional
|
|
1296
|
-
schema.includeQuery = Schema.includeQuery(schema.Include, 'Comma-separated
|
|
1298
|
+
.enum(includeFields)
|
|
1299
|
+
.check(z.describe('Additional activity resources and selection modes to include.'));
|
|
1300
|
+
/** Parses comma-separated optional activity resources and selection modes. */
|
|
1301
|
+
schema.includeQuery = Schema.includeQuery(schema.Include, 'Comma-separated activity options, such as `zones,token.logoUri,token.verified`.');
|
|
1297
1302
|
/** Schemas for the getAddressActivities operation. */
|
|
1298
1303
|
let getAddressActivities;
|
|
1299
1304
|
(function (getAddressActivities) {
|
|
@@ -1368,6 +1373,7 @@ export var schema;
|
|
|
1368
1373
|
*/
|
|
1369
1374
|
getTransactionActivities.Response = z
|
|
1370
1375
|
.object({
|
|
1376
|
+
chainId: Schema.ChainId.check(z.describe('Chain id containing the transaction.'), z.meta({ examples: [4217] })),
|
|
1371
1377
|
data: z.array(schema.Item).check(z.describe('Activity items classified from the transaction.')),
|
|
1372
1378
|
meta: z
|
|
1373
1379
|
.optional(schema.Meta)
|
|
@@ -1599,7 +1605,7 @@ export function addresses(options = {}) {
|
|
|
1599
1605
|
summary: 'List address activities',
|
|
1600
1606
|
tags: ['Activities'],
|
|
1601
1607
|
}), Cache.response({
|
|
1602
|
-
cacheControl: Cache.policies.
|
|
1608
|
+
cacheControl: Cache.policies.noStore,
|
|
1603
1609
|
name: 'tempo-api:addresses:v1',
|
|
1604
1610
|
key: (c) => Cache.urlKey(c, schema.getAddressActivities.Query),
|
|
1605
1611
|
}), async (c) => {
|
|
@@ -1617,39 +1623,71 @@ export function addresses(options = {}) {
|
|
|
1617
1623
|
});
|
|
1618
1624
|
const { address } = c.req.valid('param');
|
|
1619
1625
|
const query = c.req.valid('query');
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
Cache.setPolicy(c, Cache.policies.metadata);
|
|
1626
|
+
if (!query.include.includes('zones'))
|
|
1627
|
+
Cache.setPolicy(c, query.cursor === undefined ? Cache.policies.feed : Cache.policies.metadata);
|
|
1623
1628
|
try {
|
|
1624
1629
|
const chainId = query.chainId ?? c.get('chainId');
|
|
1625
|
-
const
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1630
|
+
const listed = await Timing.time(c, 'address_activities', async () => {
|
|
1631
|
+
if (!query.include.includes('zones')) {
|
|
1632
|
+
const result = await Store.memoize(() => list(tidx({ chainId, tidx: c.get('getTidx')(chainId) }), {
|
|
1633
|
+
address: address,
|
|
1634
|
+
cursor: query.cursor,
|
|
1635
|
+
group: query.group,
|
|
1636
|
+
limit: query.limit,
|
|
1637
|
+
logs: query.logs,
|
|
1638
|
+
store: c.get('store'),
|
|
1639
|
+
}), {
|
|
1640
|
+
key: `activities:v1:${chainId}:${address.toLowerCase()}:${query.group ?? false}:${query.logs ?? false}:${query.cursor ?? 'head'}:${query.limit}`,
|
|
1641
|
+
store: c.get('store'),
|
|
1642
|
+
ttl: Ttl.seconds(15),
|
|
1643
|
+
});
|
|
1644
|
+
return { chainId, kind: 'chain', ...result };
|
|
1645
|
+
}
|
|
1646
|
+
const zoneChainIds = c.get('zoneChainIds');
|
|
1647
|
+
if (!zoneChainIds)
|
|
1648
|
+
throw new Error('Inferred Zone selection was not resolved.');
|
|
1649
|
+
const result = await Store.memoize(() => listZones({
|
|
1650
|
+
address: address,
|
|
1651
|
+
cursor: query.cursor,
|
|
1652
|
+
group: query.group,
|
|
1653
|
+
limit: query.limit,
|
|
1654
|
+
logs: query.logs,
|
|
1655
|
+
providers: zoneChainIds.map((zoneChainId) => ({
|
|
1656
|
+
chainId: zoneChainId,
|
|
1657
|
+
provider: tidx({
|
|
1658
|
+
chainId: zoneChainId,
|
|
1659
|
+
tidx: c.get('getTidx')(zoneChainId),
|
|
1660
|
+
}),
|
|
1661
|
+
})),
|
|
1662
|
+
store: c.get('store'),
|
|
1663
|
+
}), {
|
|
1664
|
+
key: `activities:zones:v1:${zoneChainIds.join(',')}:${address.toLowerCase()}:${query.group ?? false}:${query.logs ?? false}:${query.cursor ?? 'head'}:${query.limit}`,
|
|
1665
|
+
store: c.get('store'),
|
|
1666
|
+
ttl: Ttl.seconds(15),
|
|
1667
|
+
});
|
|
1668
|
+
return { kind: 'zones', ...result };
|
|
1645
1669
|
});
|
|
1670
|
+
const { items, rates } = listed.kind === 'zones'
|
|
1671
|
+
? await enrichZoneTokens(c, {
|
|
1672
|
+
denomination: query['valuation.currency'],
|
|
1673
|
+
include: query.include,
|
|
1674
|
+
items: listed.items,
|
|
1675
|
+
oracle,
|
|
1676
|
+
})
|
|
1677
|
+
: await enrichTokens(c, {
|
|
1678
|
+
chainId: listed.chainId,
|
|
1679
|
+
denomination: query['valuation.currency'],
|
|
1680
|
+
include: query.include,
|
|
1681
|
+
items: listed.items,
|
|
1682
|
+
oracle,
|
|
1683
|
+
});
|
|
1646
1684
|
// Fold consecutive access-key-signed items into `group` entries only
|
|
1647
1685
|
// when requested; otherwise every item is returned at the root.
|
|
1648
1686
|
const data = query.group ? groupByAccessKey(items) : items;
|
|
1649
1687
|
return c.json(Response.validated(schema.getAddressActivities.Response, {
|
|
1650
1688
|
data,
|
|
1651
1689
|
...(rates ? { meta: { valuation: Valuation.pricing(rates, oracle) } } : {}),
|
|
1652
|
-
nextCursor,
|
|
1690
|
+
nextCursor: listed.nextCursor,
|
|
1653
1691
|
}), 200);
|
|
1654
1692
|
}
|
|
1655
1693
|
catch (cause) {
|
|
@@ -1686,6 +1724,10 @@ export function transactions(options = {}) {
|
|
|
1686
1724
|
description: 'No mined transaction was found for that hash.',
|
|
1687
1725
|
codes: ['transaction_not_found'],
|
|
1688
1726
|
},
|
|
1727
|
+
409: {
|
|
1728
|
+
description: 'More than one readable Zone contains that transaction hash.',
|
|
1729
|
+
codes: ['transaction_ambiguous'],
|
|
1730
|
+
},
|
|
1689
1731
|
502: 'Tempo could not read activity or token data from an upstream service.',
|
|
1690
1732
|
},
|
|
1691
1733
|
success: {
|
|
@@ -1716,36 +1758,107 @@ export function transactions(options = {}) {
|
|
|
1716
1758
|
});
|
|
1717
1759
|
const { transactionHash } = c.req.valid('param');
|
|
1718
1760
|
const query = c.req.valid('query');
|
|
1719
|
-
const chainId = query.chainId ?? c.get('chainId');
|
|
1720
1761
|
try {
|
|
1721
|
-
const
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1762
|
+
const result = await Timing.time(c, 'transaction_activities', async () => {
|
|
1763
|
+
const selected = await (async () => {
|
|
1764
|
+
if (!query.include.includes('zones'))
|
|
1765
|
+
return {
|
|
1766
|
+
chainId: query.chainId ?? c.get('chainId'),
|
|
1767
|
+
kind: 'selected',
|
|
1768
|
+
receipt: null,
|
|
1769
|
+
};
|
|
1770
|
+
const zoneChainIds = c.get('zoneChainIds');
|
|
1771
|
+
if (!zoneChainIds)
|
|
1772
|
+
throw new Error('Inferred Zone selection was not resolved.');
|
|
1773
|
+
// Cache only positive resolution. Missing transactions must remain
|
|
1774
|
+
// visible as soon as their Zone indexer catches up.
|
|
1775
|
+
const match = await Store.memoize(async () => {
|
|
1776
|
+
const probes = await Promise.all(zoneChainIds.map(async (chainId) => {
|
|
1777
|
+
try {
|
|
1778
|
+
return {
|
|
1779
|
+
chainId,
|
|
1780
|
+
value: await getTransactionReceipt({
|
|
1781
|
+
chainId,
|
|
1782
|
+
tidx: c.get('getTidx')(chainId),
|
|
1783
|
+
transactionHash,
|
|
1784
|
+
}),
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
catch (cause) {
|
|
1788
|
+
return { cause, chainId };
|
|
1789
|
+
}
|
|
1790
|
+
}));
|
|
1791
|
+
return ZoneSelection.uniqueMatch(probes);
|
|
1792
|
+
}, {
|
|
1793
|
+
key: `activities:zones:v1:${zoneChainIds.join(',')}:tx:${transactionHash.toLowerCase()}`,
|
|
1794
|
+
shouldCache: (match) => match.kind === 'selected',
|
|
1795
|
+
store: c.get('store'),
|
|
1796
|
+
ttl: Ttl.seconds(15),
|
|
1797
|
+
});
|
|
1798
|
+
if (match.kind === 'failed') {
|
|
1799
|
+
c.set('providerFailures', match.failures.map(({ cause, chainId }) => ({
|
|
1800
|
+
...Tidx.providerFailure(cause),
|
|
1801
|
+
chainId,
|
|
1802
|
+
})));
|
|
1803
|
+
throw match.failures[0].cause;
|
|
1804
|
+
}
|
|
1805
|
+
if (match.kind !== 'selected')
|
|
1806
|
+
return match;
|
|
1807
|
+
return { chainId: match.chainId, kind: 'selected', receipt: match.value };
|
|
1808
|
+
})();
|
|
1809
|
+
if (selected.kind !== 'selected')
|
|
1810
|
+
return selected;
|
|
1811
|
+
const { chainId } = selected;
|
|
1812
|
+
const unenrichedItems = await Store.memoize(() => selected.receipt === null
|
|
1813
|
+
? getTransactionActivities({
|
|
1814
|
+
chainId,
|
|
1815
|
+
logs: query.logs,
|
|
1816
|
+
store: c.get('store'),
|
|
1817
|
+
tidx: c.get('getTidx')(chainId),
|
|
1818
|
+
transactionHash,
|
|
1819
|
+
})
|
|
1820
|
+
: classifyTransactionActivities({
|
|
1821
|
+
chainId,
|
|
1822
|
+
logs: query.logs,
|
|
1823
|
+
receipt: selected.receipt,
|
|
1824
|
+
store: c.get('store'),
|
|
1825
|
+
tidx: c.get('getTidx')(chainId),
|
|
1826
|
+
transactionHash,
|
|
1827
|
+
}), {
|
|
1828
|
+
key: `activities:v1:${chainId}:tx:${transactionHash.toLowerCase()}:${query.logs ?? false}`,
|
|
1829
|
+
store: c.get('store'),
|
|
1830
|
+
ttl: Ttl.seconds(15),
|
|
1831
|
+
});
|
|
1832
|
+
return unenrichedItems === null
|
|
1833
|
+
? { kind: 'not_found' }
|
|
1834
|
+
: { chainId, items: unenrichedItems, kind: 'found' };
|
|
1835
|
+
});
|
|
1836
|
+
if (result.kind === 'not_found')
|
|
1733
1837
|
return Response.error(c, {
|
|
1734
1838
|
code: 'transaction_not_found',
|
|
1735
1839
|
message: 'Transaction not found',
|
|
1736
1840
|
status: 404,
|
|
1737
1841
|
});
|
|
1842
|
+
if (result.kind === 'ambiguous')
|
|
1843
|
+
return Response.error(c, {
|
|
1844
|
+
code: 'transaction_ambiguous',
|
|
1845
|
+
message: 'Transaction hash matched more than one readable Zone',
|
|
1846
|
+
status: 409,
|
|
1847
|
+
});
|
|
1738
1848
|
// Mined activity can carry current valuations and verification data.
|
|
1739
|
-
|
|
1849
|
+
if (!query.include.includes('zones'))
|
|
1850
|
+
Cache.setPolicy(c, Cache.policies.metadata);
|
|
1851
|
+
c.set('chainId', result.chainId);
|
|
1740
1852
|
// Build immutable token and structured amount copies from RPC metadata.
|
|
1741
1853
|
const { items, rates } = await enrichTokens(c, {
|
|
1742
|
-
chainId,
|
|
1854
|
+
chainId: result.chainId,
|
|
1743
1855
|
denomination: query['valuation.currency'],
|
|
1744
1856
|
include: query.include,
|
|
1745
|
-
items:
|
|
1857
|
+
items: result.items,
|
|
1746
1858
|
oracle,
|
|
1747
1859
|
});
|
|
1748
1860
|
return c.json(Response.validated(schema.getTransactionActivities.Response, {
|
|
1861
|
+
chainId: result.chainId,
|
|
1749
1862
|
data: items,
|
|
1750
1863
|
...(rates ? { meta: { valuation: Valuation.pricing(rates, oracle) } } : {}),
|
|
1751
1864
|
}), 200);
|
|
@@ -1768,7 +1881,13 @@ export function transactions(options = {}) {
|
|
|
1768
1881
|
* Items carry stub tokens; the caller enriches them via {@link enrichTokens}.
|
|
1769
1882
|
*/
|
|
1770
1883
|
export async function getTransactionActivities(options) {
|
|
1771
|
-
const
|
|
1884
|
+
const receipt = await getTransactionReceipt(options);
|
|
1885
|
+
if (!receipt)
|
|
1886
|
+
return null;
|
|
1887
|
+
return classifyTransactionActivities({ ...options, receipt });
|
|
1888
|
+
}
|
|
1889
|
+
async function getTransactionReceipt(options) {
|
|
1890
|
+
const { chainId, tidx: tidxClient } = options;
|
|
1772
1891
|
const hash = options.transactionHash.toLowerCase();
|
|
1773
1892
|
// The `receipts` table is indexed by `tx_hash`, so this point lookup needs no
|
|
1774
1893
|
// block bound; it also yields the block number the `logs` lookup requires.
|
|
@@ -1781,9 +1900,17 @@ export async function getTransactionActivities(options) {
|
|
|
1781
1900
|
const receipt = receiptResult.rows[0];
|
|
1782
1901
|
if (!receipt)
|
|
1783
1902
|
return null;
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1903
|
+
return {
|
|
1904
|
+
blockNum: Number(Value.toNumber(receipt['block_num'])),
|
|
1905
|
+
feePayer: lowerOrNull(receipt['fee_payer']),
|
|
1906
|
+
txSender: lowerOrNull(receipt['from']),
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
async function classifyTransactionActivities(options) {
|
|
1910
|
+
const { chainId, logs = false, receipt, tidx: tidxClient } = options;
|
|
1911
|
+
const hash = options.transactionHash.toLowerCase();
|
|
1912
|
+
const { blockNum, feePayer, txSender } = receipt;
|
|
1913
|
+
const fingerprintMap_promise = Mpp.fingerprintMap({ store: options.store }).catch(() => ({}));
|
|
1787
1914
|
// `logs` is sorted by block position, so a bare `tx_hash =` scans to genesis;
|
|
1788
1915
|
// pair it with the receipt's block number (see `embedReceipts` in receipts.ts).
|
|
1789
1916
|
const logsResult = await tidxClient.fetch({
|
|
@@ -1812,7 +1939,7 @@ export async function getTransactionActivities(options) {
|
|
|
1812
1939
|
return [];
|
|
1813
1940
|
// Best-effort MPP service directory: a fetch failure yields an empty map, so
|
|
1814
1941
|
// enrichment never blocks classification.
|
|
1815
|
-
const fingerprintMap = await
|
|
1942
|
+
const fingerprintMap = await fingerprintMap_promise;
|
|
1816
1943
|
// Anchor the viewer on the transaction sender: the sender initiated every
|
|
1817
1944
|
// activity in the transaction, so `perspective` is `outgoing` and `signer`
|
|
1818
1945
|
// resolves to `self`. Fall back to the zero address when the sender is absent.
|
|
@@ -1823,15 +1950,15 @@ export async function getTransactionActivities(options) {
|
|
|
1823
1950
|
/**
|
|
1824
1951
|
* Lists classified activity for an address by running the shared pipeline
|
|
1825
1952
|
* (`groupByTx` → `classifyGroup` → `enrichItem`) over rows from a
|
|
1826
|
-
* {@link Provider}. Returns
|
|
1827
|
-
*
|
|
1953
|
+
* {@link Provider}. Returns classified items plus the next cursor; callers run
|
|
1954
|
+
* {@link groupByAccessKey} over the result.
|
|
1828
1955
|
*/
|
|
1829
1956
|
export async function list(provider, options) {
|
|
1830
1957
|
const { address, cursor, group = false, limit = 20, logs = false } = options;
|
|
1831
1958
|
const viewer = address.toLowerCase();
|
|
1832
1959
|
// Best-effort MPP service directory: a fetch failure yields an empty map, so
|
|
1833
1960
|
// enrichment never blocks the feed.
|
|
1834
|
-
const
|
|
1961
|
+
const fingerprintMap_promise = Mpp.fingerprintMap({ store: options.store }).catch(() => ({}));
|
|
1835
1962
|
let currentCursor = cursor;
|
|
1836
1963
|
const allItems = [];
|
|
1837
1964
|
let hasMore = false;
|
|
@@ -1846,6 +1973,7 @@ export async function list(provider, options) {
|
|
|
1846
1973
|
const txGroups = grouped.slice(0, limit + 1);
|
|
1847
1974
|
hasMore = txGroups.length > limit;
|
|
1848
1975
|
const page = txGroups.slice(0, limit);
|
|
1976
|
+
const fingerprintMap = await fingerprintMap_promise;
|
|
1849
1977
|
if (page.length === 0)
|
|
1850
1978
|
break;
|
|
1851
1979
|
allItems.push(...page.flatMap((txGroup) => classifyGroup(txGroup, viewer, fingerprintMap, logs).map(withTitle)));
|
|
@@ -1865,6 +1993,117 @@ export async function list(provider, options) {
|
|
|
1865
1993
|
// public token references and structured amounts via {@link enrichTokens}.
|
|
1866
1994
|
return { items: allItems, nextCursor };
|
|
1867
1995
|
}
|
|
1996
|
+
const zoneCursorVersion = 1;
|
|
1997
|
+
/**
|
|
1998
|
+
* Lists address activity across multiple Zones in one stable timestamp-ordered
|
|
1999
|
+
* feed. Its opaque cursor retains each Zone provider's native continuation.
|
|
2000
|
+
*/
|
|
2001
|
+
export async function listZones(options) {
|
|
2002
|
+
const { address, cursor, limit = 20, logs = false, providers, store } = options;
|
|
2003
|
+
const group = options.group ?? false;
|
|
2004
|
+
const orderedProviders = [...providers].sort((a, b) => a.chainId - b.chainId);
|
|
2005
|
+
const chainIds = orderedProviders.map(({ chainId }) => chainId);
|
|
2006
|
+
const cursors = decodeZoneCursor(cursor, chainIds);
|
|
2007
|
+
const viewer = address.toLowerCase();
|
|
2008
|
+
const fingerprintMap_promise = Mpp.fingerprintMap({ store }).catch(() => ({}));
|
|
2009
|
+
const states = orderedProviders.map(({ chainId, provider }) => ({
|
|
2010
|
+
chainId,
|
|
2011
|
+
exhausted: false,
|
|
2012
|
+
groups: [],
|
|
2013
|
+
provider,
|
|
2014
|
+
}));
|
|
2015
|
+
const allItems = [];
|
|
2016
|
+
let hasMore = false;
|
|
2017
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
2018
|
+
await Promise.all(states.map(async (state) => {
|
|
2019
|
+
if (state.exhausted || state.groups.length > 0)
|
|
2020
|
+
return;
|
|
2021
|
+
const { rows } = await state.provider.fetchRows({
|
|
2022
|
+
address: viewer,
|
|
2023
|
+
cursor: cursors.get(state.chainId),
|
|
2024
|
+
limit,
|
|
2025
|
+
});
|
|
2026
|
+
const groups = groupByTx(rows).slice(0, limit + 1);
|
|
2027
|
+
state.exhausted = groups.length <= limit;
|
|
2028
|
+
state.groups.push(...groups);
|
|
2029
|
+
}));
|
|
2030
|
+
const candidates = states
|
|
2031
|
+
.flatMap((state) => state.groups.map((txGroup) => ({ state, txGroup })))
|
|
2032
|
+
.sort((a, b) => {
|
|
2033
|
+
if (a.txGroup.blockTimestamp !== b.txGroup.blockTimestamp)
|
|
2034
|
+
return b.txGroup.blockTimestamp - a.txGroup.blockTimestamp;
|
|
2035
|
+
if (a.state.chainId !== b.state.chainId)
|
|
2036
|
+
return a.state.chainId - b.state.chainId;
|
|
2037
|
+
if (a.txGroup.blockNum !== b.txGroup.blockNum)
|
|
2038
|
+
return b.txGroup.blockNum - a.txGroup.blockNum;
|
|
2039
|
+
return b.txGroup.txIdx - a.txGroup.txIdx;
|
|
2040
|
+
});
|
|
2041
|
+
const page = candidates.slice(0, limit);
|
|
2042
|
+
const fingerprintMap = await fingerprintMap_promise;
|
|
2043
|
+
if (page.length === 0)
|
|
2044
|
+
break;
|
|
2045
|
+
for (const { state, txGroup } of page) {
|
|
2046
|
+
state.groups.splice(state.groups.indexOf(txGroup), 1);
|
|
2047
|
+
cursors.set(state.chainId, state.provider.cursorForGroup(txGroup));
|
|
2048
|
+
allItems.push(...classifyGroup(txGroup, viewer, fingerprintMap, logs).map((item) => ({
|
|
2049
|
+
...withTitle(item),
|
|
2050
|
+
chainId: state.chainId,
|
|
2051
|
+
})));
|
|
2052
|
+
}
|
|
2053
|
+
hasMore = states.some((state) => !state.exhausted || state.groups.length > 0);
|
|
2054
|
+
const enough = group
|
|
2055
|
+
? groupByAccessKeyItems(allItems).length >= minGroupEntries
|
|
2056
|
+
: allItems.length >= limit;
|
|
2057
|
+
if (enough || !hasMore)
|
|
2058
|
+
break;
|
|
2059
|
+
}
|
|
2060
|
+
// A consumed sentinel proves only that the provider may have more rows.
|
|
2061
|
+
// Probe drained buffers so `nextCursor` remains the end-of-list signal.
|
|
2062
|
+
await Promise.all(states.map(async (state) => {
|
|
2063
|
+
if (state.exhausted || state.groups.length > 0)
|
|
2064
|
+
return;
|
|
2065
|
+
const { rows } = await state.provider.fetchRows({
|
|
2066
|
+
address: viewer,
|
|
2067
|
+
cursor: cursors.get(state.chainId),
|
|
2068
|
+
limit: 1,
|
|
2069
|
+
});
|
|
2070
|
+
const group = groupByTx(rows)[0];
|
|
2071
|
+
if (group)
|
|
2072
|
+
state.groups.push(group);
|
|
2073
|
+
else
|
|
2074
|
+
state.exhausted = true;
|
|
2075
|
+
}));
|
|
2076
|
+
hasMore = states.some((state) => !state.exhausted || state.groups.length > 0);
|
|
2077
|
+
return {
|
|
2078
|
+
items: allItems,
|
|
2079
|
+
nextCursor: hasMore ? encodeZoneCursor(cursors, chainIds) : null,
|
|
2080
|
+
};
|
|
2081
|
+
}
|
|
2082
|
+
function decodeZoneCursor(cursor, chainIds) {
|
|
2083
|
+
const fields = ['int'];
|
|
2084
|
+
for (const _chainId of chainIds)
|
|
2085
|
+
fields.push('int', 'id');
|
|
2086
|
+
const decoded = cursor ? Cursor.decode(cursor, fields) : undefined;
|
|
2087
|
+
const cursors = new Map();
|
|
2088
|
+
if (!decoded || decoded[0] !== zoneCursorVersion)
|
|
2089
|
+
return cursors;
|
|
2090
|
+
for (let index = 0; index < chainIds.length; index++) {
|
|
2091
|
+
const chainId = chainIds[index];
|
|
2092
|
+
const offset = index * 2 + 1;
|
|
2093
|
+
if (decoded[offset] !== chainId)
|
|
2094
|
+
return new Map();
|
|
2095
|
+
const value = decoded[offset + 1];
|
|
2096
|
+
if (value !== 'head')
|
|
2097
|
+
cursors.set(chainId, value);
|
|
2098
|
+
}
|
|
2099
|
+
return cursors;
|
|
2100
|
+
}
|
|
2101
|
+
function encodeZoneCursor(cursors, chainIds) {
|
|
2102
|
+
return Cursor.encode([
|
|
2103
|
+
zoneCursorVersion,
|
|
2104
|
+
...chainIds.flatMap((chainId) => [chainId, cursors.get(chainId) ?? 'head']),
|
|
2105
|
+
]);
|
|
2106
|
+
}
|
|
1868
2107
|
/**
|
|
1869
2108
|
* Creates a TIDX-backed {@link Provider} that runs three sub-queries in
|
|
1870
2109
|
* parallel and merges them:
|
|
@@ -2174,28 +2413,44 @@ function classifyGroup(group, viewer, fingerprintMap, includeLogs = false) {
|
|
|
2174
2413
|
}
|
|
2175
2414
|
/** Classifies a Q1 (log-bearing) group via `parseEventLogs`. */
|
|
2176
2415
|
function classifyFromLogs(rows, ctx) {
|
|
2177
|
-
const
|
|
2416
|
+
const decoded = decodeRows(rows);
|
|
2417
|
+
const items = (() => {
|
|
2418
|
+
try {
|
|
2419
|
+
return classifyFromLogsCore(rows, ctx, decoded);
|
|
2420
|
+
}
|
|
2421
|
+
catch {
|
|
2422
|
+
// Indexed logs can match a known signature without satisfying that event's expected shape.
|
|
2423
|
+
return [
|
|
2424
|
+
unknown(ctx.itemBase(Math.min(...rows.map((row) => row.logIdx))), {
|
|
2425
|
+
events: buildTxEvents(rows, decoded),
|
|
2426
|
+
signer: signerForRows(rows, { fallback: ctx.signer, viewer: ctx.viewer }),
|
|
2427
|
+
}),
|
|
2428
|
+
];
|
|
2429
|
+
}
|
|
2430
|
+
})();
|
|
2178
2431
|
// When the caller requested raw logs, attach the full per-transaction log set
|
|
2179
2432
|
// (decoded when possible) to every classified item so no co-located log is
|
|
2180
2433
|
// hidden behind the headline. `unknown` items already carry it.
|
|
2181
2434
|
if (!ctx.includeLogs)
|
|
2182
2435
|
return items;
|
|
2183
|
-
const events = buildTxEvents(rows,
|
|
2436
|
+
const events = buildTxEvents(rows, decoded);
|
|
2184
2437
|
return items.map((item) => (item.type === 'unknown' ? item : { ...item, events }));
|
|
2185
2438
|
}
|
|
2186
|
-
/**
|
|
2187
|
-
function
|
|
2188
|
-
const
|
|
2189
|
-
|
|
2190
|
-
// is the access-key publicKey. Use it as the signer so successive access-key
|
|
2191
|
-
// actions group together.
|
|
2192
|
-
const accessKeySpendRow = rows.find((r) => r.selector === accessKeySpendSelector &&
|
|
2193
|
-
Address.isEqual(r.logAddress, Addresses.accountKeychain));
|
|
2439
|
+
/** Resolves an access-key signer from raw rows, falling back to the transaction signer. */
|
|
2440
|
+
function signerForRows(rows, options) {
|
|
2441
|
+
const accessKeySpendRow = rows.find((row) => row.selector === accessKeySpendSelector &&
|
|
2442
|
+
Address.isEqual(row.logAddress, Addresses.accountKeychain));
|
|
2194
2443
|
const accessKeySigner = accessKeySpendRow?.topic2
|
|
2195
2444
|
? `0x${accessKeySpendRow.topic2.slice(-40)}`.toLowerCase()
|
|
2196
2445
|
: null;
|
|
2197
|
-
|
|
2198
|
-
|
|
2446
|
+
return accessKeySigner && !Address.isEqual(accessKeySigner, options.viewer)
|
|
2447
|
+
? accessKeySigner
|
|
2448
|
+
: options.fallback;
|
|
2449
|
+
}
|
|
2450
|
+
/** Classifies a Q1 (log-bearing) group via `parseEventLogs`, picking one headline item. */
|
|
2451
|
+
function classifyFromLogsCore(rows, ctx, events = decodeRows(rows)) {
|
|
2452
|
+
const { blockNum, fingerprintMap, itemBase, viewer } = ctx;
|
|
2453
|
+
const signer = signerForRows(rows, { fallback: ctx.signer, viewer });
|
|
2199
2454
|
const minLogIndex = Math.min(...rows.map((r) => r.logIdx));
|
|
2200
2455
|
// Payment-channel settlement: a CloseRequested topic plus an optional refund
|
|
2201
2456
|
// transfer back to the viewer.
|
|
@@ -2564,6 +2819,11 @@ function classifyFromLogsCore(rows, ctx) {
|
|
|
2564
2819
|
}
|
|
2565
2820
|
// Approval (excluding zone-outbox spenders).
|
|
2566
2821
|
const approvalEvent = finalEvents.find((e) => e.eventName === 'Approval' &&
|
|
2822
|
+
// ERC-721 uses the same selector but indexes its token ID as topic3. In
|
|
2823
|
+
// non-strict mode viem otherwise decodes the missing ERC-20 amount as zero.
|
|
2824
|
+
rows.some((row) => row.logIdx === e.logIndex &&
|
|
2825
|
+
row.topic3 === null &&
|
|
2826
|
+
/^0x[0-9a-fA-F]{64}$/.test(row.data ?? '')) &&
|
|
2567
2827
|
!Address.isEqual(e.args.spender, Addresses.zoneOutbox));
|
|
2568
2828
|
if (approvalEvent) {
|
|
2569
2829
|
const args = approvalEvent.args;
|
|
@@ -3433,21 +3693,28 @@ function unknown(base, data) {
|
|
|
3433
3693
|
}
|
|
3434
3694
|
/** Decodes a group's raw rows into `viem/tempo` events via `parseEventLogs` (non-strict). */
|
|
3435
3695
|
function decodeRows(rows) {
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3696
|
+
return rows.flatMap((r) => {
|
|
3697
|
+
const log = {
|
|
3698
|
+
address: r.logAddress,
|
|
3699
|
+
blockHash: '0x0',
|
|
3700
|
+
blockNumber: BigInt(r.blockNum),
|
|
3701
|
+
data: (r.data ?? '0x'),
|
|
3702
|
+
logIndex: r.logIdx,
|
|
3703
|
+
removed: false,
|
|
3704
|
+
topics: [r.selector, r.topic1, r.topic2, r.topic3].filter(Boolean),
|
|
3705
|
+
transactionHash: r.txHash,
|
|
3706
|
+
transactionIndex: r.txIdx,
|
|
3707
|
+
};
|
|
3708
|
+
try {
|
|
3709
|
+
return parseEventLogs({
|
|
3710
|
+
abi: [...Abis.abis, ...Abis.earnRouter, ...Abis.earnVault],
|
|
3711
|
+
logs: [log],
|
|
3712
|
+
strict: false,
|
|
3713
|
+
});
|
|
3714
|
+
}
|
|
3715
|
+
catch {
|
|
3716
|
+
return [];
|
|
3717
|
+
}
|
|
3451
3718
|
});
|
|
3452
3719
|
}
|
|
3453
3720
|
/**
|
|
@@ -3550,12 +3817,26 @@ async function enrichTokens(c, options) {
|
|
|
3550
3817
|
collectTokens(item, addresses);
|
|
3551
3818
|
const includeLogoUri = include.includes('token.logoUri');
|
|
3552
3819
|
const includeVerified = include.includes('token.verified');
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3820
|
+
const resolved_promise = addresses.size > 0
|
|
3821
|
+
? Timing.time(c, 'tokens', () => Promise.all([...addresses].map(async (address) => {
|
|
3822
|
+
const [logoUri, metadata] = await Promise.all([
|
|
3823
|
+
includeLogoUri
|
|
3824
|
+
? Tokens.getTokenLogo(c, { address, chainId }).catch(() => undefined)
|
|
3825
|
+
: undefined,
|
|
3826
|
+
getActivityTokenMetadata(c, { address, chainId }),
|
|
3827
|
+
]);
|
|
3828
|
+
return { address: address.toLowerCase(), logoUri, metadata };
|
|
3829
|
+
})))
|
|
3556
3830
|
: undefined;
|
|
3557
|
-
|
|
3558
|
-
|
|
3831
|
+
// Curated data is needed only for requested valuation or token fields.
|
|
3832
|
+
const snapshot_promise = addresses.size > 0 && (denomination !== undefined || includeLogoUri || includeVerified)
|
|
3833
|
+
? VerifiedTokens.snapshot(c, chainId).catch(() => undefined)
|
|
3834
|
+
: Promise.resolve(undefined);
|
|
3835
|
+
const rates_promise = (async () => {
|
|
3836
|
+
if (!denomination)
|
|
3837
|
+
return undefined;
|
|
3838
|
+
const snapshot = await snapshot_promise;
|
|
3839
|
+
return Valuation.ratesFor(c, {
|
|
3559
3840
|
currencies: snapshot
|
|
3560
3841
|
? [...addresses].flatMap((address) => {
|
|
3561
3842
|
const held = snapshot.byAddress.get(address)?.currency;
|
|
@@ -3564,37 +3845,63 @@ async function enrichTokens(c, options) {
|
|
|
3564
3845
|
: [],
|
|
3565
3846
|
denomination,
|
|
3566
3847
|
oracle,
|
|
3567
|
-
})
|
|
3568
|
-
|
|
3569
|
-
if (
|
|
3570
|
-
return { items: items, rates };
|
|
3571
|
-
const
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3848
|
+
});
|
|
3849
|
+
})();
|
|
3850
|
+
if (!resolved_promise)
|
|
3851
|
+
return { items: items, rates: await rates_promise };
|
|
3852
|
+
const [resolved_raw, rates, snapshot] = await Promise.all([
|
|
3853
|
+
resolved_promise,
|
|
3854
|
+
rates_promise,
|
|
3855
|
+
snapshot_promise,
|
|
3856
|
+
]);
|
|
3857
|
+
const resolved = resolved_raw.map(({ address, logoUri, metadata }) => [
|
|
3858
|
+
address,
|
|
3859
|
+
{
|
|
3860
|
+
currency: metadata.currency,
|
|
3861
|
+
decimals: metadata.decimals,
|
|
3862
|
+
logoUri: includeLogoUri
|
|
3863
|
+
? (logoUri ?? snapshot?.byAddress.get(address)?.logoUri ?? metadata.logoUri)
|
|
3575
3864
|
: undefined,
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
currency: metadata.currency,
|
|
3582
|
-
decimals: metadata.decimals,
|
|
3583
|
-
logoUri: includeLogoUri
|
|
3584
|
-
? (logoUri ?? snapshot?.byAddress.get(address)?.logoUri ?? metadata.logoUri)
|
|
3585
|
-
: undefined,
|
|
3586
|
-
name: metadata.name,
|
|
3587
|
-
symbol: metadata.symbol,
|
|
3588
|
-
verified: includeVerified && snapshot ? snapshot.byAddress.has(address) : undefined,
|
|
3589
|
-
},
|
|
3590
|
-
];
|
|
3591
|
-
})));
|
|
3865
|
+
name: metadata.name,
|
|
3866
|
+
symbol: metadata.symbol,
|
|
3867
|
+
verified: includeVerified && snapshot ? snapshot.byAddress.has(address) : undefined,
|
|
3868
|
+
},
|
|
3869
|
+
]);
|
|
3592
3870
|
const byAddress = new Map(resolved);
|
|
3593
3871
|
return {
|
|
3594
3872
|
items: items.map((item) => enrichItem(item, byAddress, { denomination, rates, snapshot })),
|
|
3595
3873
|
rates,
|
|
3596
3874
|
};
|
|
3597
3875
|
}
|
|
3876
|
+
/** Resolves token metadata on each item's source Zone without changing feed order. */
|
|
3877
|
+
async function enrichZoneTokens(c, options) {
|
|
3878
|
+
const byChain = new Map();
|
|
3879
|
+
for (const item of options.items) {
|
|
3880
|
+
const items = byChain.get(item.chainId) ?? [];
|
|
3881
|
+
items.push(item);
|
|
3882
|
+
byChain.set(item.chainId, items);
|
|
3883
|
+
}
|
|
3884
|
+
const results = await Promise.all([...byChain].map(async ([chainId, items]) => ({
|
|
3885
|
+
chainId,
|
|
3886
|
+
...(await enrichTokens(c, {
|
|
3887
|
+
chainId,
|
|
3888
|
+
denomination: options.denomination,
|
|
3889
|
+
include: options.include,
|
|
3890
|
+
items,
|
|
3891
|
+
oracle: options.oracle,
|
|
3892
|
+
})),
|
|
3893
|
+
})));
|
|
3894
|
+
const buckets = new Map();
|
|
3895
|
+
for (const result of results)
|
|
3896
|
+
buckets.set(result.chainId, { index: 0, items: result.items });
|
|
3897
|
+
return {
|
|
3898
|
+
items: options.items.map((item) => {
|
|
3899
|
+
const bucket = buckets.get(item.chainId);
|
|
3900
|
+
return bucket.items[bucket.index++];
|
|
3901
|
+
}),
|
|
3902
|
+
rates: results.find((result) => result.rates !== undefined)?.rates,
|
|
3903
|
+
};
|
|
3904
|
+
}
|
|
3598
3905
|
/** Returns an enriched copy of an item without mutating its cached token stubs. */
|
|
3599
3906
|
function enrichItem(item, byAddress, valuation) {
|
|
3600
3907
|
const source = item.data;
|
|
@@ -3652,6 +3959,7 @@ function groupByAccessKeyItems(items) {
|
|
|
3652
3959
|
const itemSigner = signerOf(item);
|
|
3653
3960
|
if (itemSigner !== 'self') {
|
|
3654
3961
|
if (currentGroup &&
|
|
3962
|
+
currentGroup.items[0].chainId === item.chainId &&
|
|
3655
3963
|
Address.isEqual(currentGroup.signer, itemSigner) &&
|
|
3656
3964
|
sameCalendarDay(currentGroup.items[0].timestamp, item.timestamp)) {
|
|
3657
3965
|
currentGroup.items.push(item);
|
|
@@ -3689,6 +3997,7 @@ function flushGroup(group) {
|
|
|
3689
3997
|
const firstItem = group.items[0];
|
|
3690
3998
|
const lastItem = group.items[group.items.length - 1];
|
|
3691
3999
|
return {
|
|
4000
|
+
...(firstItem.chainId === undefined ? {} : { chainId: firstItem.chainId }),
|
|
3692
4001
|
data: { items: group.items, signer: group.signer },
|
|
3693
4002
|
perspective: firstItem.perspective,
|
|
3694
4003
|
id: `${firstItem.id}..${lastItem.id}:${group.items.length}`,
|