tapimo 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApiKeys.d.ts +24 -7
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +17 -5
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +12104 -7861
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +191 -128
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +10 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +17 -4
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts +19 -8
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +25 -9
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -1
- package/dist/admin/App.d.ts +601 -20
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +12 -2
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +94 -11
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +141 -32
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +1069 -0
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -0
- package/dist/admin/apps/earn-vaults.js +409 -0
- package/dist/admin/apps/earn-vaults.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +166 -166
- 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 -95
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +2 -0
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +18 -2
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +22 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +59 -39
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/Zones.d.ts +8335 -0
- package/dist/apps/Zones.d.ts.map +1 -0
- package/dist/apps/Zones.js +38 -0
- package/dist/apps/Zones.js.map +1 -0
- package/dist/apps/data/App.d.ts +14377 -10165
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +91 -19
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +1 -1
- package/dist/apps/data/FxOracle.d.ts.map +1 -1
- package/dist/apps/data/index.d.ts +0 -1
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +0 -1
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +32 -32
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +130 -65
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +312 -312
- package/dist/apps/data/routes/balances.d.ts +18 -18
- package/dist/apps/data/routes/balances.js +5 -5
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
- package/dist/apps/data/routes/coingecko.js +62 -35
- package/dist/apps/data/routes/coingecko.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +2144 -0
- package/dist/apps/data/routes/earn.d.ts.map +1 -0
- package/dist/apps/data/routes/earn.js +947 -0
- package/dist/apps/data/routes/earn.js.map +1 -0
- package/dist/apps/data/routes/exchanges.d.ts +1231 -324
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +656 -193
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +59 -8
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/funding.d.ts +4092 -387
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +1403 -256
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +19 -2
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +265 -265
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +11 -11
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +5 -5
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +211 -22
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +49 -9
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +116 -88
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +198 -91
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +55 -55
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +78 -39
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +78 -29
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +165 -67
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +10 -10
- package/dist/apps/data/routes/valuation.js +2 -2
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +34 -9
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +5 -3
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +175 -65
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +281 -0
- package/dist/apps/data/routes/zones.d.ts.map +1 -0
- package/dist/apps/data/routes/zones.js +252 -0
- package/dist/apps/data/routes/zones.js.map +1 -0
- package/dist/apps/docs/reference.js +6 -5
- package/dist/apps/docs/reference.js.map +1 -1
- package/dist/apps/index.d.ts +2 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +2 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +670 -670
- package/dist/apps/management/Billing.d.ts +8 -0
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +12 -0
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/Error.d.ts +12 -0
- package/dist/apps/management/Error.d.ts.map +1 -0
- package/dist/apps/management/Error.js +10 -0
- package/dist/apps/management/Error.js.map +1 -0
- package/dist/apps/management/routes/api-keys.d.ts +5 -5
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +2 -8
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +119 -119
- package/dist/apps/management/routes/faucet.d.ts +35 -35
- package/dist/apps/management/routes/invitations.d.ts +62 -62
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +4 -10
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +30 -30
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +78 -78
- package/dist/apps/management/routes/orgs.d.ts +48 -48
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +2 -8
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +9 -9
- package/dist/apps/management/routes/scopes.js +2 -2
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +80 -80
- package/dist/apps/management/routes/verified-token-requests.d.ts +36 -36
- package/dist/apps/management/routes/webhooks.d.ts +50 -50
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +15 -3
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/App.d.ts +55 -56
- package/dist/apps/mpp/App.d.ts.map +1 -1
- package/dist/apps/mpp/App.js +192 -27
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/Mpp.d.ts +0 -20
- package/dist/apps/mpp/Mpp.d.ts.map +1 -1
- package/dist/apps/mpp/Mpp.js +0 -24
- package/dist/apps/mpp/Mpp.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +40 -0
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Adapter.js +66 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -0
- package/dist/apps/mpp/internal/Error.d.ts +4 -0
- package/dist/apps/mpp/internal/Error.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Error.js +41 -0
- package/dist/apps/mpp/internal/Error.js.map +1 -0
- package/dist/apps/mpp/internal/Idempotency.d.ts +33 -0
- package/dist/apps/mpp/internal/Idempotency.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Idempotency.js +28 -0
- package/dist/apps/mpp/internal/Idempotency.js.map +1 -0
- package/dist/apps/mpp/internal/Policy.d.ts +46 -0
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Policy.js +57 -0
- package/dist/apps/mpp/internal/Policy.js.map +1 -0
- package/dist/apps/mpp/internal/ScreenManager.d.ts +27 -0
- package/dist/apps/mpp/internal/ScreenManager.d.ts.map +1 -0
- package/dist/apps/mpp/internal/ScreenManager.js +18 -0
- package/dist/apps/mpp/internal/ScreenManager.js.map +1 -0
- package/dist/apps/mpp/internal/Screening.d.ts +35 -0
- package/dist/apps/mpp/internal/Screening.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Screening.js +20 -0
- package/dist/apps/mpp/internal/Screening.js.map +1 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts +36 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Sponsorship.js +103 -0
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -0
- package/dist/apps/mpp/internal/Utils.d.ts +7 -0
- package/dist/apps/mpp/internal/Utils.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Utils.js +24 -0
- package/dist/apps/mpp/internal/Utils.js.map +1 -0
- package/dist/apps/relay/App.js +184 -24
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +16 -7
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/db/Db.d.ts +20 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +342 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +921 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +269 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +68 -0
- package/dist/db/tables/earnVaults.d.ts.map +1 -0
- package/dist/db/tables/earnVaults.js +72 -0
- package/dist/db/tables/earnVaults.js.map +1 -0
- package/dist/db/tables/fundingCatalog.d.ts +56 -0
- package/dist/db/tables/fundingCatalog.d.ts.map +1 -0
- package/dist/db/tables/fundingCatalog.js +85 -0
- package/dist/db/tables/fundingCatalog.js.map +1 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts +159 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -0
- package/dist/db/tables/fundingDepositAddresses.js +206 -0
- package/dist/db/tables/fundingDepositAddresses.js.map +1 -0
- package/dist/db/tables/fundingDeposits.d.ts +115 -0
- package/dist/db/tables/fundingDeposits.d.ts.map +1 -0
- package/dist/db/tables/fundingDeposits.js +100 -0
- package/dist/db/tables/fundingDeposits.js.map +1 -0
- package/dist/db/tables/fundingIdempotency.d.ts +91 -0
- package/dist/db/tables/fundingIdempotency.d.ts.map +1 -0
- package/dist/db/tables/fundingIdempotency.js +103 -0
- package/dist/db/tables/fundingIdempotency.js.map +1 -0
- package/dist/db/tables/fundingTransferEvents.d.ts +12 -0
- package/dist/db/tables/fundingTransferEvents.d.ts.map +1 -0
- package/dist/db/tables/fundingTransferEvents.js +18 -0
- package/dist/db/tables/fundingTransferEvents.js.map +1 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts +15 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -0
- package/dist/db/tables/fundingTransferTransactions.js +27 -0
- package/dist/db/tables/fundingTransferTransactions.js.map +1 -0
- package/dist/db/tables/fundingTransfers.d.ts +82 -0
- package/dist/db/tables/fundingTransfers.d.ts.map +1 -0
- package/dist/db/tables/fundingTransfers.js +89 -0
- package/dist/db/tables/fundingTransfers.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +8 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +35 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +8 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +16 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +13 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +16 -0
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +4 -2
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +14 -4
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +8 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +16 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokens.d.ts +14 -7
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokens.js +9 -7
- package/dist/db/tables/verifiedTokens.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +31 -1
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +24 -3
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/relay.js +108 -108
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +26 -0
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +35 -2
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +16 -10
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/Cursor.js +1 -1
- package/dist/internal/Cursor.js.map +1 -1
- package/dist/internal/EarnRates.d.ts +89 -0
- package/dist/internal/EarnRates.d.ts.map +1 -0
- package/dist/internal/EarnRates.js +266 -0
- package/dist/internal/EarnRates.js.map +1 -0
- package/dist/internal/EarnVaults.d.ts +171 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -0
- package/dist/internal/EarnVaults.js +547 -0
- package/dist/internal/EarnVaults.js.map +1 -0
- package/dist/internal/EdgeCache.d.ts +9 -2
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +36 -9
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Id.d.ts +11 -0
- package/dist/internal/Id.d.ts.map +1 -1
- package/dist/internal/Id.js +13 -0
- package/dist/internal/Id.js.map +1 -1
- package/dist/internal/Idempotency.d.ts +83 -0
- package/dist/internal/Idempotency.d.ts.map +1 -0
- package/dist/internal/Idempotency.js +113 -0
- package/dist/internal/Idempotency.js.map +1 -0
- package/dist/internal/Log.d.ts +64 -9
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +29 -7
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +47 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +1 -1
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +3 -0
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Provider.d.ts +14 -0
- package/dist/internal/Provider.d.ts.map +1 -0
- package/dist/internal/Provider.js +5 -0
- package/dist/internal/Provider.js.map +1 -0
- package/dist/internal/Schema.d.ts +8 -3
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +24 -13
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +35 -0
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +43 -24
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +79 -11
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Viem.d.ts +82 -65
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +83 -12
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/WebhookDestination.d.ts.map +1 -1
- package/dist/internal/WebhookDestination.js +34 -28
- package/dist/internal/WebhookDestination.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +9 -0
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +15 -10
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/exchange/Provider.d.ts +219 -0
- package/dist/internal/exchange/Provider.d.ts.map +1 -0
- package/dist/internal/exchange/Provider.js +117 -0
- package/dist/internal/exchange/Provider.js.map +1 -0
- package/dist/internal/exchange/index.d.ts +2 -0
- package/dist/internal/exchange/index.d.ts.map +1 -0
- package/dist/internal/exchange/index.js +2 -0
- package/dist/internal/exchange/index.js.map +1 -0
- package/dist/internal/exchange/providers/uniswap.d.ts +57 -0
- package/dist/internal/exchange/providers/uniswap.d.ts.map +1 -0
- package/dist/internal/exchange/providers/uniswap.js +553 -0
- package/dist/internal/exchange/providers/uniswap.js.map +1 -0
- package/dist/internal/funding/Action.d.ts +55 -0
- package/dist/internal/funding/Action.d.ts.map +1 -0
- package/dist/internal/funding/Action.js +74 -0
- package/dist/internal/funding/Action.js.map +1 -0
- package/dist/internal/funding/Catalog.d.ts +107 -0
- package/dist/internal/funding/Catalog.d.ts.map +1 -0
- package/dist/internal/funding/Catalog.js +270 -0
- package/dist/internal/funding/Catalog.js.map +1 -0
- package/dist/internal/funding/Chain.d.ts +76 -0
- package/dist/internal/funding/Chain.d.ts.map +1 -0
- package/dist/internal/funding/Chain.js +38 -0
- package/dist/internal/funding/Chain.js.map +1 -0
- package/dist/internal/funding/Deposit.d.ts +366 -0
- package/dist/internal/funding/Deposit.d.ts.map +1 -0
- package/dist/internal/funding/Deposit.js +286 -0
- package/dist/internal/funding/Deposit.js.map +1 -0
- package/dist/internal/funding/DepositAddress.d.ts +345 -0
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -0
- package/dist/internal/funding/DepositAddress.js +189 -0
- package/dist/internal/funding/DepositAddress.js.map +1 -0
- package/dist/internal/funding/Evidence.d.ts +52 -0
- package/dist/internal/funding/Evidence.d.ts.map +1 -0
- package/dist/internal/funding/Evidence.js +314 -0
- package/dist/internal/funding/Evidence.js.map +1 -0
- package/dist/internal/funding/Provider.d.ts +1186 -0
- package/dist/internal/funding/Provider.d.ts.map +1 -0
- package/dist/internal/funding/Provider.js +1081 -0
- package/dist/internal/funding/Provider.js.map +1 -0
- package/dist/internal/funding/Reconciliation.d.ts +113 -0
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -0
- package/dist/internal/funding/Reconciliation.js +676 -0
- package/dist/internal/funding/Reconciliation.js.map +1 -0
- package/dist/internal/funding/Route.d.ts +21 -0
- package/dist/internal/funding/Route.d.ts.map +1 -0
- package/dist/internal/funding/Route.js +5 -0
- package/dist/internal/funding/Route.js.map +1 -0
- package/dist/internal/funding/Subsidy.d.ts +113 -0
- package/dist/internal/funding/Subsidy.d.ts.map +1 -0
- package/dist/internal/funding/Subsidy.js +138 -0
- package/dist/internal/funding/Subsidy.js.map +1 -0
- package/dist/internal/funding/Token.d.ts +41 -0
- package/dist/internal/funding/Token.d.ts.map +1 -0
- package/dist/internal/funding/Token.js +22 -0
- package/dist/internal/funding/Token.js.map +1 -0
- package/dist/internal/funding/Transfer.d.ts +643 -0
- package/dist/internal/funding/Transfer.d.ts.map +1 -0
- package/dist/internal/funding/Transfer.js +332 -0
- package/dist/internal/funding/Transfer.js.map +1 -0
- package/dist/internal/funding/index.d.ts +13 -0
- package/dist/internal/funding/index.d.ts.map +1 -0
- package/dist/internal/funding/index.js +13 -0
- package/dist/internal/funding/index.js.map +1 -0
- package/dist/internal/funding/providers/across.d.ts +21 -0
- package/dist/internal/funding/providers/across.d.ts.map +1 -0
- package/dist/internal/funding/providers/across.js +117 -0
- package/dist/internal/funding/providers/across.js.map +1 -0
- package/dist/internal/funding/providers/relay.d.ts +46 -0
- package/dist/internal/funding/providers/relay.d.ts.map +1 -0
- package/dist/internal/funding/providers/relay.js +464 -0
- package/dist/internal/funding/providers/relay.js.map +1 -0
- package/dist/internal/funding/providers/rhino.d.ts +15 -0
- package/dist/internal/funding/providers/rhino.d.ts.map +1 -0
- package/dist/internal/funding/providers/rhino.js +116 -0
- package/dist/internal/funding/providers/rhino.js.map +1 -0
- package/dist/internal/funding/providers/squid.d.ts +19 -0
- package/dist/internal/funding/providers/squid.d.ts.map +1 -0
- package/dist/internal/funding/providers/squid.js +120 -0
- package/dist/internal/funding/providers/squid.js.map +1 -0
- package/dist/internal/funding/providers/symbiosis.d.ts +20 -0
- package/dist/internal/funding/providers/symbiosis.d.ts.map +1 -0
- package/dist/internal/funding/providers/symbiosis.js +176 -0
- package/dist/internal/funding/providers/symbiosis.js.map +1 -0
- package/dist/internal/index.d.ts +5 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +5 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/webhookDestinations/url.js +61 -57
- package/dist/internal/webhookDestinations/url.js.map +1 -1
- package/dist/providers/index.d.ts +43 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +19 -0
- package/dist/providers/index.js.map +1 -0
- package/package.json +9 -4
- package/src/ApiKeys.test.ts +11 -7
- package/src/ApiKeys.ts +37 -9
- package/src/App.test.ts +85 -10
- package/src/App.ts +224 -137
- package/src/Assets.ts +29 -4
- package/src/Client.test-d.ts +650 -30
- package/src/Scope.test.ts +19 -0
- package/src/Scope.ts +28 -11
- package/src/Webhooks.test.ts +25 -0
- package/src/Webhooks.ts +1 -1
- package/src/admin/App.test.ts +9 -2
- package/src/admin/App.ts +32 -9
- package/src/admin/apps/api-keys.test.ts +167 -23
- package/src/admin/apps/api-keys.ts +166 -28
- package/src/admin/apps/earn-vaults.test.ts +338 -0
- package/src/admin/apps/earn-vaults.ts +572 -0
- package/src/admin/apps/scopes.test.ts +16 -1
- package/src/admin/ui/plugin.ts +2 -2
- package/src/admin/ui/src/components/EarnVaultForm.tsx +137 -0
- package/src/admin/ui/src/components/MobileProfile.tsx +2 -2
- package/src/admin/ui/src/components/Page.tsx +1 -1
- package/src/admin/ui/src/components/ThemeToggle.tsx +1 -1
- package/src/admin/ui/src/lib/api-keys.ts +37 -7
- package/src/admin/ui/src/lib/client.ts +1 -1
- package/src/admin/ui/src/lib/config.ts +1 -1
- package/src/admin/ui/src/lib/early-access.ts +8 -9
- package/src/admin/ui/src/lib/earn-vaults.ts +207 -0
- package/src/admin/ui/src/lib/format.ts +13 -0
- package/src/admin/ui/src/lib/organizations.test.ts +14 -4
- package/src/admin/ui/src/lib/organizations.ts +7 -1
- package/src/admin/ui/src/lib/response.ts +22 -0
- package/src/admin/ui/src/lib/scopes.test.ts +19 -11
- package/src/admin/ui/src/lib/scopes.ts +28 -7
- package/src/admin/ui/src/lib/verified-tokens.ts +10 -9
- package/src/admin/ui/src/routeTree.gen.ts +70 -7
- package/src/admin/ui/src/router.tsx +2 -2
- package/src/admin/ui/src/routes/__root.tsx +9 -8
- package/src/admin/ui/src/routes/api-keys.tsx +475 -64
- package/src/admin/ui/src/routes/early-access.tsx +5 -12
- package/src/admin/ui/src/routes/earn.vaults.tsx +348 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +154 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +190 -0
- package/src/admin/ui/src/routes/organizations.tsx +4 -7
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +56 -54
- package/src/admin/ui/src/routes/verified-tokens.tsx +4 -4
- package/src/admin/ui/vite.config.ts +4 -1
- package/src/admin/ui.generated.ts +189 -95
- package/src/analytics/Analytics.test.ts +69 -10
- package/src/analytics/Analytics.ts +20 -1
- package/src/analytics/tables/requestEvents.ts +79 -37
- package/src/apps/Zones.test.ts +33 -0
- package/src/apps/Zones.ts +40 -0
- package/src/apps/composition.test.ts +84 -1
- package/src/apps/data/App.test.ts +38 -9
- package/src/apps/data/App.ts +96 -33
- package/src/apps/data/FxOracle.ts +1 -1
- package/src/apps/data/index.ts +0 -1
- package/src/apps/data/routes/activities.test.ts +82 -6
- package/src/apps/data/routes/activities.ts +131 -71
- package/src/apps/data/routes/balances.test.ts +50 -37
- package/src/apps/data/routes/balances.ts +5 -5
- package/src/apps/data/routes/blocks.test.ts +2 -0
- package/src/apps/data/routes/coingecko.test.ts +22 -0
- package/src/apps/data/routes/coingecko.ts +84 -48
- package/src/apps/data/routes/earn.test.ts +1108 -0
- package/src/apps/data/routes/earn.ts +1391 -0
- package/src/apps/data/routes/exchanges.test.ts +82 -33
- package/src/apps/data/routes/exchanges.ts +842 -227
- package/src/apps/data/routes/fee-amm.test.ts +4 -6
- package/src/apps/data/routes/fee-amm.ts +69 -12
- package/src/apps/data/routes/funding.test.ts +2712 -221
- package/src/apps/data/routes/funding.ts +1604 -387
- package/src/apps/data/routes/indexer.test.ts +43 -34
- package/src/apps/data/routes/indexer.ts +19 -2
- package/src/apps/data/routes/receipts.test.ts +5 -3
- package/src/apps/data/routes/receipts.ts +13 -11
- package/src/apps/data/routes/rpc.test.ts +446 -28
- package/src/apps/data/routes/rpc.ts +243 -25
- package/src/apps/data/routes/tokenlist.test.ts +15 -0
- package/src/apps/data/routes/tokenlist.ts +88 -22
- package/src/apps/data/routes/tokens.ts +262 -86
- package/src/apps/data/routes/transactions.test.ts +2 -0
- package/src/apps/data/routes/transactions.ts +77 -42
- package/src/apps/data/routes/transfers.test.ts +166 -4
- package/src/apps/data/routes/transfers.ts +216 -78
- package/src/apps/data/routes/valuation.test.ts +62 -9
- package/src/apps/data/routes/valuation.ts +2 -2
- package/src/apps/data/routes/verified-tokens.test.ts +51 -0
- package/src/apps/data/routes/verified-tokens.ts +52 -15
- package/src/apps/data/routes/webhooks.test.ts +432 -33
- package/src/apps/data/routes/webhooks.ts +189 -79
- package/src/apps/data/routes/zones.test.ts +473 -0
- package/src/apps/data/routes/zones.ts +338 -0
- package/src/apps/docs/reference.ts +8 -6
- package/src/apps/index.ts +2 -1
- package/src/apps/management/Billing.test.ts +29 -0
- package/src/apps/management/Billing.ts +23 -0
- package/src/apps/management/Error.ts +12 -0
- package/src/apps/management/routes/api-keys.test.ts +5 -3
- package/src/apps/management/routes/api-keys.ts +2 -9
- package/src/apps/management/routes/invitations.ts +4 -11
- package/src/apps/management/routes/orgs.ts +2 -9
- package/src/apps/management/routes/scopes.test.ts +7 -2
- package/src/apps/management/routes/scopes.ts +2 -2
- package/src/apps/management/routes/webhooks.test.ts +6 -1
- package/src/apps/management/routes/webhooks.ts +15 -3
- package/src/apps/mpp/App.ts +276 -29
- package/src/apps/mpp/Mpp.test.ts +631 -26
- package/src/apps/mpp/Mpp.ts +0 -42
- package/src/apps/mpp/internal/Adapter.ts +108 -3
- package/src/apps/mpp/internal/Error.test.ts +33 -0
- package/src/apps/mpp/internal/Error.ts +44 -6
- package/src/apps/mpp/internal/Idempotency.test.ts +213 -0
- package/src/apps/mpp/internal/Idempotency.ts +59 -5
- package/src/apps/mpp/internal/Policy.test.ts +122 -0
- package/src/apps/mpp/internal/Policy.ts +98 -0
- package/src/apps/mpp/internal/ScreenManager.test.ts +68 -0
- package/src/apps/mpp/internal/ScreenManager.ts +41 -0
- package/src/apps/mpp/internal/Screening.ts +40 -3
- package/src/apps/mpp/internal/Sponsorship.ts +144 -0
- package/src/apps/mpp/internal/Utils.ts +30 -0
- package/src/apps/relay/App.test.ts +495 -64
- package/src/apps/relay/App.ts +234 -24
- package/src/apps/relay/Sponsorships.test.ts +51 -0
- package/src/apps/relay/Sponsorships.ts +19 -7
- package/src/db/Db.ts +439 -0
- package/src/db/Schema.ts +325 -2
- package/src/db/tables/earnVaults.test.ts +185 -0
- package/src/db/tables/earnVaults.ts +151 -0
- package/src/db/tables/fundingCatalog.test.ts +108 -0
- package/src/db/tables/fundingCatalog.ts +157 -0
- package/src/db/tables/fundingDepositAddresses.test.ts +580 -0
- package/src/db/tables/fundingDepositAddresses.ts +376 -0
- package/src/db/tables/fundingDeposits.test.ts +261 -0
- package/src/db/tables/fundingDeposits.ts +229 -0
- package/src/db/tables/fundingIdempotency.test.ts +182 -0
- package/src/db/tables/fundingIdempotency.ts +180 -0
- package/src/db/tables/fundingTransferEvents.ts +28 -0
- package/src/db/tables/fundingTransferTransactions.test.ts +69 -0
- package/src/db/tables/fundingTransferTransactions.ts +37 -0
- package/src/db/tables/fundingTransfers.test.ts +89 -0
- package/src/db/tables/fundingTransfers.ts +153 -0
- package/src/db/tables/organizations.test.ts +88 -0
- package/src/db/tables/organizations.ts +42 -1
- package/src/db/tables/projects.ts +16 -0
- package/src/db/tables/requestUsage.ts +23 -0
- package/src/db/tables/sponsoredTransactions.test.ts +52 -2
- package/src/db/tables/sponsoredTransactions.ts +18 -6
- package/src/db/tables/users.ts +16 -0
- package/src/db/tables/verifiedTokens.ts +19 -14
- package/src/db/tables/webhookSubscriptions.ts +58 -3
- package/src/handlers/relay.test.ts +2 -0
- package/src/handlers/relay.ts +95 -99
- package/src/internal/Auth.test.ts +48 -0
- package/src/internal/Auth.ts +61 -2
- package/src/internal/Cache.ts +13 -9
- package/src/internal/Cursor.test.ts +2 -2
- package/src/internal/Cursor.ts +1 -1
- package/src/internal/EarnRates.test.ts +125 -0
- package/src/internal/EarnRates.ts +409 -0
- package/src/internal/EarnVaults.test.ts +195 -0
- package/src/internal/EarnVaults.ts +876 -0
- package/src/internal/EdgeCache.test.ts +37 -5
- package/src/internal/EdgeCache.ts +39 -7
- package/src/internal/Id.ts +14 -0
- package/src/internal/Idempotency.test.ts +109 -0
- package/src/internal/Idempotency.ts +237 -0
- package/src/internal/Log.test-d.ts +41 -8
- package/src/internal/Log.test.ts +189 -8
- package/src/internal/Log.ts +124 -17
- package/src/internal/MetricSink.test.ts +244 -4
- package/src/internal/MetricSink.ts +51 -1
- package/src/internal/OpenApi.ts +3 -0
- package/src/internal/Provider.test.ts +17 -0
- package/src/internal/Provider.ts +17 -0
- package/src/internal/Schema.test.ts +13 -0
- package/src/internal/Schema.ts +41 -24
- package/src/internal/Store.test.ts +25 -0
- package/src/internal/Store.ts +46 -0
- package/src/internal/Tidx.local.test.ts +78 -3
- package/src/internal/Tidx.test.ts +212 -18
- package/src/internal/Tidx.ts +112 -32
- package/src/internal/VerifiedTokens.test.ts +15 -0
- package/src/internal/Viem.test.ts +170 -17
- package/src/internal/Viem.ts +111 -28
- package/src/internal/WebhookDestination.ts +25 -23
- package/src/internal/Webhooks.test.ts +59 -0
- package/src/internal/Webhooks.ts +34 -10
- package/src/internal/exchange/Provider.test.ts +216 -0
- package/src/internal/exchange/Provider.ts +326 -0
- package/src/internal/exchange/index.test.ts +6 -0
- package/src/internal/exchange/index.ts +1 -0
- package/src/internal/exchange/providers/uniswap.test.ts +122 -0
- package/src/internal/exchange/providers/uniswap.ts +682 -0
- package/src/internal/funding/Action.test.ts +138 -0
- package/src/internal/funding/Action.ts +117 -0
- package/src/internal/funding/Catalog.test.ts +311 -0
- package/src/internal/funding/Catalog.ts +347 -0
- package/src/internal/funding/Chain.test.ts +79 -0
- package/src/internal/funding/Chain.ts +120 -0
- package/src/internal/funding/Deposit.test.ts +26 -0
- package/src/internal/funding/Deposit.ts +453 -0
- package/src/internal/funding/DepositAddress.test.ts +18 -0
- package/src/internal/funding/DepositAddress.ts +312 -0
- package/src/internal/funding/Evidence.test.ts +297 -0
- package/src/internal/funding/Evidence.ts +430 -0
- package/src/internal/funding/Provider.test.ts +1328 -0
- package/src/internal/funding/Provider.ts +1796 -0
- package/src/internal/funding/Reconciliation.local.test.ts +504 -0
- package/src/internal/funding/Reconciliation.test.ts +2020 -0
- package/src/internal/funding/Reconciliation.ts +930 -0
- package/src/internal/funding/Route.test.ts +66 -0
- package/src/internal/funding/Route.ts +29 -0
- package/src/internal/funding/Subsidy.local.test.ts +152 -0
- package/src/internal/funding/Subsidy.test.ts +75 -0
- package/src/internal/funding/Subsidy.ts +260 -0
- package/src/internal/funding/Token.test.ts +47 -0
- package/src/internal/funding/Token.ts +59 -0
- package/src/internal/funding/Transfer.test.ts +369 -0
- package/src/internal/funding/Transfer.ts +522 -0
- package/src/internal/funding/index.test.ts +20 -0
- package/src/internal/funding/index.ts +12 -0
- package/src/internal/funding/providers/across.ts +149 -0
- package/src/{apps/data/FundingQuoteProviders.test.ts → internal/funding/providers/index.test.ts} +178 -157
- package/src/internal/funding/providers/relay.test.ts +474 -0
- package/src/internal/funding/providers/relay.ts +559 -0
- package/src/internal/funding/providers/rhino.ts +139 -0
- package/src/internal/funding/providers/squid.ts +151 -0
- package/src/internal/funding/providers/symbiosis.ts +221 -0
- package/src/internal/index.test.ts +5 -1
- package/src/internal/index.ts +5 -1
- package/src/internal/webhookDestinations/url.ts +49 -45
- package/src/providers/index.test.ts +14 -0
- package/src/providers/index.ts +54 -0
- package/dist/apps/data/FundingQuoteProviders.d.ts +0 -174
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +0 -1
- package/dist/apps/data/FundingQuoteProviders.js +0 -775
- package/dist/apps/data/FundingQuoteProviders.js.map +0 -1
- package/dist/internal/FundingQuotes.d.ts +0 -864
- package/dist/internal/FundingQuotes.d.ts.map +0 -1
- package/dist/internal/FundingQuotes.js +0 -672
- package/dist/internal/FundingQuotes.js.map +0 -1
- package/src/apps/data/FundingQuoteProviders.ts +0 -1043
- package/src/internal/FundingQuotes.test.ts +0 -456
- package/src/internal/FundingQuotes.ts +0 -944
package/src/internal/Cache.ts
CHANGED
|
@@ -140,7 +140,7 @@ export function response<environment extends Env>(
|
|
|
140
140
|
let res = result instanceof Response ? new Response(result.body, result) : c.res
|
|
141
141
|
if (
|
|
142
142
|
result instanceof Response &&
|
|
143
|
-
|
|
143
|
+
Etag.matches(res.headers.get('ETag'), c.req.header('If-None-Match'))
|
|
144
144
|
)
|
|
145
145
|
res = notModified(res)
|
|
146
146
|
|
|
@@ -158,7 +158,9 @@ export function response<environment extends Env>(
|
|
|
158
158
|
|
|
159
159
|
// `markCacheable` lets the edge layer pay its store lookup only on routes
|
|
160
160
|
// that mount this middleware; everything else skips the read.
|
|
161
|
-
return EdgeCache.markCacheable(middleware
|
|
161
|
+
return EdgeCache.markCacheable(middleware, {
|
|
162
|
+
key: options.key as (c: Context) => Promise<string> | string,
|
|
163
|
+
})
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
export declare namespace response {
|
|
@@ -214,9 +216,15 @@ export function urlKey<
|
|
|
214
216
|
return url.toString()
|
|
215
217
|
}
|
|
216
218
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
219
|
+
namespace Etag {
|
|
220
|
+
export function matches(etag: string | null, ifNoneMatch: string | undefined) {
|
|
221
|
+
if (!etag || !ifNoneMatch) return false
|
|
222
|
+
return ifNoneMatch.split(/,\s*/).some((tag) => stripWeak(tag) === stripWeak(etag))
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function stripWeak(etag: string) {
|
|
226
|
+
return etag.replace(/^W\//, '')
|
|
227
|
+
}
|
|
220
228
|
}
|
|
221
229
|
|
|
222
230
|
function notModified(response: Response) {
|
|
@@ -248,10 +256,6 @@ function setCacheHeaders(
|
|
|
248
256
|
headers.set('Vary', Array.from(vary.values()).join(', '))
|
|
249
257
|
}
|
|
250
258
|
|
|
251
|
-
function stripWeak(etag: string) {
|
|
252
|
-
return etag.replace(/^W\//, '')
|
|
253
|
-
}
|
|
254
|
-
|
|
255
259
|
// Derive the shared-cache policy from a route's client `Cache-Control`. A
|
|
256
260
|
// positive `s-maxage`/`max-age` (and no `no-store`/`no-cache`) is what makes a
|
|
257
261
|
// route eligible for the anonymous edge cache; the `private` directive only
|
|
@@ -19,10 +19,10 @@ describe('Cursor', () => {
|
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
test('round-trips a timestamp/id tuple', () => {
|
|
22
|
-
const token = Cursor.encode(['2026-01-01T00:00:00.000Z', '
|
|
22
|
+
const token = Cursor.encode(['2026-01-01T00:00:00.000Z', 'source:transaction-0'])
|
|
23
23
|
expect(Cursor.decode(token, ['timestamp', 'id'])).toEqual([
|
|
24
24
|
'2026-01-01T00:00:00.000Z',
|
|
25
|
-
'
|
|
25
|
+
'source:transaction-0',
|
|
26
26
|
])
|
|
27
27
|
})
|
|
28
28
|
|
package/src/internal/Cursor.ts
CHANGED
|
@@ -138,7 +138,7 @@ function isValid(value: unknown, field: Field): boolean {
|
|
|
138
138
|
case 'address':
|
|
139
139
|
return typeof value === 'string' && /^0x[0-9a-fA-F]{40}$/.test(value)
|
|
140
140
|
case 'id':
|
|
141
|
-
return typeof value === 'string' && /^[A-Za-z0-
|
|
141
|
+
return typeof value === 'string' && /^[A-Za-z0-9:_-]+$/.test(value)
|
|
142
142
|
case 'timestamp':
|
|
143
143
|
return typeof value === 'string' && !Number.isNaN(Date.parse(value))
|
|
144
144
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as EarnRates from './EarnRates.js'
|
|
2
|
+
|
|
3
|
+
describe('schema.Window', () => {
|
|
4
|
+
test('stays absent when omitted', () => {
|
|
5
|
+
expect(EarnRates.schema.Window.parse(undefined)).toBeUndefined()
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('accepts every selectable window and nothing else', () => {
|
|
9
|
+
expect(
|
|
10
|
+
['1h', '1d', '7d', '30d'].map((value) => EarnRates.schema.Window.parse(value)),
|
|
11
|
+
).toStrictEqual(['1h', '1d', '7d', '30d'])
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('rejects windows outside the selectable set', () => {
|
|
15
|
+
expect(
|
|
16
|
+
['0h', '24h', '36h', '168h', '7x', '1w', '-1d', '1.5d', '721h', '31d', '90d', ''].map(
|
|
17
|
+
(value) => EarnRates.schema.Window.safeParse(value).success,
|
|
18
|
+
),
|
|
19
|
+
).toStrictEqual([
|
|
20
|
+
false,
|
|
21
|
+
false,
|
|
22
|
+
false,
|
|
23
|
+
false,
|
|
24
|
+
false,
|
|
25
|
+
false,
|
|
26
|
+
false,
|
|
27
|
+
false,
|
|
28
|
+
false,
|
|
29
|
+
false,
|
|
30
|
+
false,
|
|
31
|
+
false,
|
|
32
|
+
])
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
describe('asOf', () => {
|
|
37
|
+
test('rounds down to a fifteen-minute UTC bucket', () => {
|
|
38
|
+
vi.useFakeTimers()
|
|
39
|
+
try {
|
|
40
|
+
vi.setSystemTime(new Date('2026-07-21T09:14:59.999Z'))
|
|
41
|
+
const inBucket = EarnRates.asOf()
|
|
42
|
+
vi.setSystemTime(new Date('2026-07-21T09:29:59.000Z'))
|
|
43
|
+
expect([inBucket, EarnRates.asOf()]).toMatchInlineSnapshot(`
|
|
44
|
+
[
|
|
45
|
+
"2026-07-21T09:00:00.000Z",
|
|
46
|
+
"2026-07-21T09:15:00.000Z",
|
|
47
|
+
]
|
|
48
|
+
`)
|
|
49
|
+
} finally {
|
|
50
|
+
vi.useRealTimers()
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('withholds the newest thirty seconds', () => {
|
|
55
|
+
vi.useFakeTimers()
|
|
56
|
+
try {
|
|
57
|
+
vi.setSystemTime(new Date('2026-07-21T09:15:20.000Z'))
|
|
58
|
+
expect(EarnRates.asOf()).toMatchInlineSnapshot(`"2026-07-21T09:00:00.000Z"`)
|
|
59
|
+
} finally {
|
|
60
|
+
vi.useRealTimers()
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
describe('annualize', () => {
|
|
66
|
+
const day = 24 * 60 * 60
|
|
67
|
+
|
|
68
|
+
test('annualizes share-price growth over the measured window', () => {
|
|
69
|
+
expect([
|
|
70
|
+
EarnRates.annualize({
|
|
71
|
+
end: { price: 1_010_000n, timestamp: 7 * day },
|
|
72
|
+
start: { price: 1_000_000n, timestamp: 0 },
|
|
73
|
+
}),
|
|
74
|
+
EarnRates.annualize({
|
|
75
|
+
end: { price: 1_000_500n, timestamp: 30 * day },
|
|
76
|
+
start: { price: 1_000_000n, timestamp: 0 },
|
|
77
|
+
}),
|
|
78
|
+
]).toMatchInlineSnapshot(`
|
|
79
|
+
[
|
|
80
|
+
"0.680075",
|
|
81
|
+
"0.006100",
|
|
82
|
+
]
|
|
83
|
+
`)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('reports a drawdown as a negative ratio', () => {
|
|
87
|
+
expect(
|
|
88
|
+
EarnRates.annualize({
|
|
89
|
+
end: { price: 990_000n, timestamp: 30 * day },
|
|
90
|
+
start: { price: 1_000_000n, timestamp: 0 },
|
|
91
|
+
}),
|
|
92
|
+
).toMatchInlineSnapshot(`"-0.115099"`)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('leaves an unmeasurable window unannualized', () => {
|
|
96
|
+
expect([
|
|
97
|
+
// Reversed and zero-length windows.
|
|
98
|
+
EarnRates.annualize({
|
|
99
|
+
end: { price: 1_000_000n, timestamp: 0 },
|
|
100
|
+
start: { price: 1_000_000n, timestamp: day },
|
|
101
|
+
}),
|
|
102
|
+
EarnRates.annualize({
|
|
103
|
+
end: { price: 1_000_000n, timestamp: 0 },
|
|
104
|
+
start: { price: 1_000_000n, timestamp: 0 },
|
|
105
|
+
}),
|
|
106
|
+
// A vault with no starting price has no growth to measure.
|
|
107
|
+
EarnRates.annualize({
|
|
108
|
+
end: { price: 1_000_000n, timestamp: day },
|
|
109
|
+
start: { price: 0n, timestamp: 0 },
|
|
110
|
+
}),
|
|
111
|
+
// Growth too steep to express as a decimal ratio.
|
|
112
|
+
EarnRates.annualize({
|
|
113
|
+
end: { price: 1_010_000n, timestamp: 3600 },
|
|
114
|
+
start: { price: 1_000_000n, timestamp: 0 },
|
|
115
|
+
}),
|
|
116
|
+
]).toMatchInlineSnapshot(`
|
|
117
|
+
[
|
|
118
|
+
null,
|
|
119
|
+
null,
|
|
120
|
+
null,
|
|
121
|
+
null,
|
|
122
|
+
]
|
|
123
|
+
`)
|
|
124
|
+
})
|
|
125
|
+
})
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import type { Address } from 'viem'
|
|
2
|
+
import * as z from 'zod/mini'
|
|
3
|
+
|
|
4
|
+
import * as Schema from './Schema.js'
|
|
5
|
+
import * as Store from './Store.js'
|
|
6
|
+
import type * as Tidx from './Tidx.js'
|
|
7
|
+
import * as Ttl from './Ttl.js'
|
|
8
|
+
import * as Value from './Value.js'
|
|
9
|
+
import type * as Viem from './Viem.js'
|
|
10
|
+
|
|
11
|
+
const migratedSignature =
|
|
12
|
+
'event EngineMigrated(address indexed oldEngine,address indexed newEngine,uint256 oldEngineShares,uint256 assetsMoved,uint256 newEngineShares,uint256 totalEarnShares,uint256 anchorEngineShares,uint256 anchorEarnShares)'
|
|
13
|
+
|
|
14
|
+
/** Identifier of the rate calculation, versioned so a change is visible to callers. */
|
|
15
|
+
const methodology = 'share-price-growth-annualized:v1' as const
|
|
16
|
+
|
|
17
|
+
/** Width of the UTC bucket every measurement is anchored to. */
|
|
18
|
+
const bucketWidth = Ttl.minutes(15)
|
|
19
|
+
|
|
20
|
+
/** Withheld from the anchor so an unconfirmed head block cannot move a boundary. */
|
|
21
|
+
const confirmationDelay = Ttl.seconds(30)
|
|
22
|
+
|
|
23
|
+
/** Default window, used when the caller does not select one. */
|
|
24
|
+
const defaultWindow = '7d'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Selectable measurement windows. A closed set bounds both the rate cache and
|
|
28
|
+
* the historical read volume: every distinct window is its own cache entry and
|
|
29
|
+
* its own pair of boundary reads.
|
|
30
|
+
*/
|
|
31
|
+
const windows = ['1h', '1d', '7d', '30d'] as const
|
|
32
|
+
|
|
33
|
+
/** Length of every selectable window in whole hours. */
|
|
34
|
+
const windowHours = {
|
|
35
|
+
'1h': 1,
|
|
36
|
+
'1d': 24,
|
|
37
|
+
'7d': 24 * 7,
|
|
38
|
+
'30d': 24 * 30,
|
|
39
|
+
} as const satisfies Record<Window, number>
|
|
40
|
+
|
|
41
|
+
/** Longest selectable window, which also bounds the migration scan. */
|
|
42
|
+
const maxWindowHours = Math.max(...Object.values(windowHours))
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Row cap on the migration scan. Engine migrations are rare, so a scan that
|
|
46
|
+
* fills the cap cannot be trusted to be complete and resets every window.
|
|
47
|
+
*/
|
|
48
|
+
const migrationScanLimit = 500
|
|
49
|
+
|
|
50
|
+
/** Decimal places of the returned ratio, matching the API's value precision. */
|
|
51
|
+
const netPrecision = 6
|
|
52
|
+
|
|
53
|
+
/** `Number.toFixed` switches to exponential notation here, which the ratio contract forbids. */
|
|
54
|
+
const netCeiling = 1e21
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Shares quoted at both boundaries. Large so the assets-per-share ratio is not
|
|
58
|
+
* quantized by asset base units; the amount cancels in the ratio.
|
|
59
|
+
*/
|
|
60
|
+
const quotedShares = 10n ** 18n
|
|
61
|
+
|
|
62
|
+
const secondsPerYear = 365 * 24 * 60 * 60
|
|
63
|
+
|
|
64
|
+
/** Zod schemas owned by the Earn rate resolver. */
|
|
65
|
+
export namespace schema {
|
|
66
|
+
/** Annualized share-price growth over one measurement window. */
|
|
67
|
+
export const Apy = z
|
|
68
|
+
.strictObject({
|
|
69
|
+
asOf: z.iso
|
|
70
|
+
.datetime()
|
|
71
|
+
.check(
|
|
72
|
+
z.describe('UTC instant the rate was measured to, rounded to a 15-minute bucket.'),
|
|
73
|
+
z.meta({ examples: ['2026-07-21T09:00:00.000Z'] }),
|
|
74
|
+
),
|
|
75
|
+
methodology: z
|
|
76
|
+
.literal(methodology)
|
|
77
|
+
.check(
|
|
78
|
+
z.describe('Identifier of the calculation that produced this rate.'),
|
|
79
|
+
z.meta({ examples: [methodology] }),
|
|
80
|
+
),
|
|
81
|
+
net: z
|
|
82
|
+
.string()
|
|
83
|
+
.check(
|
|
84
|
+
z.regex(/^-?\d+(\.\d+)?$/),
|
|
85
|
+
z.describe('Annualized fee-aware share-price growth, as a decimal ratio.'),
|
|
86
|
+
z.meta({ examples: ['0.041200'] }),
|
|
87
|
+
),
|
|
88
|
+
window: z
|
|
89
|
+
.enum(windows)
|
|
90
|
+
.check(z.describe('Window this rate covers.'), z.meta({ examples: [defaultWindow] })),
|
|
91
|
+
})
|
|
92
|
+
.check(z.describe('Annualized share-price growth over one measurement window.'))
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Measurement window selected by a request. Stays absent when omitted so a
|
|
96
|
+
* caller who never asked for a rate is distinguishable from one who selected
|
|
97
|
+
* the default window.
|
|
98
|
+
*/
|
|
99
|
+
export const Window = z
|
|
100
|
+
.optional(z.enum(windows))
|
|
101
|
+
.check(
|
|
102
|
+
z.describe(
|
|
103
|
+
'Rate measurement window. Selecting a window includes `apy`, which measures `7d` on its own.',
|
|
104
|
+
),
|
|
105
|
+
z.meta({ examples: [defaultWindow] }),
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Annualized share-price growth over one measurement window. */
|
|
110
|
+
export type Apy = z.output<typeof schema.Apy>
|
|
111
|
+
|
|
112
|
+
/** Selectable rate measurement window. */
|
|
113
|
+
export type Window = (typeof windows)[number]
|
|
114
|
+
|
|
115
|
+
/** Returns the confirmed 15-minute UTC bucket rates are measured to. */
|
|
116
|
+
export function asOf(): string {
|
|
117
|
+
const anchor = Math.floor((Date.now() - confirmationDelay) / bucketWidth) * bucketWidth
|
|
118
|
+
return new Date(anchor).toISOString()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Resolves the annualized rate of every vault on a page, keyed by lowercase
|
|
123
|
+
* vault address. A vault maps to `null` when its rate cannot be measured.
|
|
124
|
+
*/
|
|
125
|
+
export async function resolve(options: resolve.Options): Promise<Map<string, Apy | null>> {
|
|
126
|
+
const { chainId, store } = options
|
|
127
|
+
const window = options.window ?? defaultWindow
|
|
128
|
+
const vaults = [...new Set(options.vaults.map((vault) => Schema.Address.parse(vault)))]
|
|
129
|
+
if (vaults.length === 0) return new Map()
|
|
130
|
+
|
|
131
|
+
const measuredAt = asOf()
|
|
132
|
+
let pending: Promise<Measurement | undefined> | undefined
|
|
133
|
+
// Boundary blocks, the migration scan, and both quote batches load once per
|
|
134
|
+
// page, and only when a vault misses its cached rate. Rate enrichment never
|
|
135
|
+
// fails a page, so an unreadable window leaves every vault unmeasured.
|
|
136
|
+
const measure = () =>
|
|
137
|
+
(pending ??= measurePage({ ...options, measuredAt, vaults, window }).catch(() => undefined))
|
|
138
|
+
|
|
139
|
+
const entries = await Promise.all(
|
|
140
|
+
vaults.map(async (vault) => {
|
|
141
|
+
const apy = await Store.memoize(
|
|
142
|
+
async () => {
|
|
143
|
+
const measured = await measure()
|
|
144
|
+
const net = measured?.rates.get(vault)
|
|
145
|
+
if (net === undefined || measured === undefined) return null
|
|
146
|
+
// Labelled with the boundaries' own instant: cached boundaries can
|
|
147
|
+
// predate this request's bucket, and the label must match the prices.
|
|
148
|
+
return { asOf: measured.measuredAt, methodology, net, window }
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
// Keyed without the bucket so the entry is revisited and lazily
|
|
152
|
+
// evicted; `fx:v1:<oracle>` sets the same stable-key precedent. The
|
|
153
|
+
// cached value keeps the `asOf` it was measured at.
|
|
154
|
+
key: `earn-apy:v1:${chainId}:${vault}:${window}`,
|
|
155
|
+
store,
|
|
156
|
+
ttl: bucketWidth,
|
|
157
|
+
},
|
|
158
|
+
)
|
|
159
|
+
return [vault, apy] as const
|
|
160
|
+
}),
|
|
161
|
+
)
|
|
162
|
+
return new Map(entries)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export declare namespace resolve {
|
|
166
|
+
/** Options for resolving a page of Earn vault rates. */
|
|
167
|
+
type Options = {
|
|
168
|
+
/** Chain containing the vaults. */
|
|
169
|
+
chainId: number
|
|
170
|
+
/** Resolves the RPC client used for historical share-price quotes. */
|
|
171
|
+
getClient: Viem.GetClient
|
|
172
|
+
/** Resolves the indexer client used for block and migration history. */
|
|
173
|
+
getTidx: Tidx.GetClient
|
|
174
|
+
/** Cache backing measured rates. */
|
|
175
|
+
store: Store.Store
|
|
176
|
+
/** Vault addresses appearing on the page. */
|
|
177
|
+
vaults: readonly Address[]
|
|
178
|
+
/** Canonical measurement window, defaulting to `7d`. */
|
|
179
|
+
window?: Window | undefined
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Annualizes share-price growth between two measured boundaries. Returns `null`
|
|
185
|
+
* for a degenerate window, a zero starting price, or growth too extreme to
|
|
186
|
+
* express as a decimal ratio.
|
|
187
|
+
*/
|
|
188
|
+
export function annualize(options: annualize.Options): string | null {
|
|
189
|
+
const { end, start } = options
|
|
190
|
+
const elapsed = end.timestamp - start.timestamp
|
|
191
|
+
if (elapsed <= 0 || start.price <= 0n) return null
|
|
192
|
+
const net = (Number(end.price) / Number(start.price)) ** (secondsPerYear / elapsed) - 1
|
|
193
|
+
if (!Number.isFinite(net) || Math.abs(net) >= netCeiling) return null
|
|
194
|
+
return net.toFixed(netPrecision)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export declare namespace annualize {
|
|
198
|
+
/** One measured boundary of the window. */
|
|
199
|
+
type Boundary = {
|
|
200
|
+
/** Assets quoted for the shared share amount, in asset base units. */
|
|
201
|
+
price: bigint
|
|
202
|
+
/** Block timestamp, in seconds. */
|
|
203
|
+
timestamp: number
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Options for annualizing measured share-price growth. */
|
|
207
|
+
type Options = {
|
|
208
|
+
/** Newer boundary of the window. */
|
|
209
|
+
end: Boundary
|
|
210
|
+
/** Older boundary of the window. */
|
|
211
|
+
start: Boundary
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
type Block = {
|
|
216
|
+
number: bigint
|
|
217
|
+
timestamp: number
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
type Boundaries = {
|
|
221
|
+
end: Block
|
|
222
|
+
/** Instant these boundaries were resolved for, which may predate the caller's. */
|
|
223
|
+
measuredAt: string
|
|
224
|
+
start: Block
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
type Migration = {
|
|
228
|
+
blockNumber: bigint
|
|
229
|
+
vault: string
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function measurePage(options: measurePage.Options): Promise<Measurement | undefined> {
|
|
233
|
+
const endAt = Date.parse(options.measuredAt)
|
|
234
|
+
const boundaries = await boundaryBlocks({
|
|
235
|
+
...options,
|
|
236
|
+
endAt,
|
|
237
|
+
startAt: endAt - windowHours[options.window] * Ttl.hour(1),
|
|
238
|
+
})
|
|
239
|
+
if (!boundaries) return undefined
|
|
240
|
+
const { end, measuredAt, start } = boundaries
|
|
241
|
+
|
|
242
|
+
const client = options.getClient(options.chainId)
|
|
243
|
+
const quote = (blockNumber: bigint, vault: Address) =>
|
|
244
|
+
client.earn.getRedeemQuote({ blockNumber, shareAmount: quotedShares, vault }).then(
|
|
245
|
+
(price) => price,
|
|
246
|
+
() => undefined,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
const rates = new Map<string, string>()
|
|
250
|
+
await Promise.all(
|
|
251
|
+
options.vaults.map(async (vault) => {
|
|
252
|
+
// Concurrent quotes collapse into one deployless multicall per block.
|
|
253
|
+
const [startPrice, endPrice] = await Promise.all([
|
|
254
|
+
quote(start.number, vault),
|
|
255
|
+
quote(end.number, vault),
|
|
256
|
+
])
|
|
257
|
+
if (startPrice === undefined || endPrice === undefined) return
|
|
258
|
+
const net = annualize({
|
|
259
|
+
end: { price: endPrice, timestamp: end.timestamp },
|
|
260
|
+
start: { price: startPrice, timestamp: start.timestamp },
|
|
261
|
+
})
|
|
262
|
+
if (net !== null) rates.set(vault, net)
|
|
263
|
+
}),
|
|
264
|
+
)
|
|
265
|
+
if (rates.size === 0) return { measuredAt, rates }
|
|
266
|
+
|
|
267
|
+
// A migration inside the window bridges two different yield engines, so the
|
|
268
|
+
// window resets instead of reporting growth across the swap. Scanned only
|
|
269
|
+
// once a rate exists for it to invalidate.
|
|
270
|
+
const migrations = await recentMigrations(options)
|
|
271
|
+
if (!migrations) return undefined
|
|
272
|
+
for (const { blockNumber, vault } of migrations)
|
|
273
|
+
if (blockNumber > start.number && blockNumber <= end.number) rates.delete(vault)
|
|
274
|
+
return { measuredAt, rates }
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Rates for one page, labelled with the instant their prices were read at. */
|
|
278
|
+
type Measurement = {
|
|
279
|
+
measuredAt: string
|
|
280
|
+
rates: ReadonlyMap<string, string>
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
declare namespace measurePage {
|
|
284
|
+
type Options = resolve.Options & {
|
|
285
|
+
/** Anchor instant the window ends at. */
|
|
286
|
+
measuredAt: string
|
|
287
|
+
/** Canonical measurement window, resolved from the request or the default. */
|
|
288
|
+
window: Window
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Resolves the last indexed block at or before each end of the window. Returns
|
|
294
|
+
* undefined when either boundary is missing, both land on one block, or the
|
|
295
|
+
* indexer lags a boundary.
|
|
296
|
+
*/
|
|
297
|
+
async function boundaryBlocks(options: boundaryBlocks.Options): Promise<Boundaries | undefined> {
|
|
298
|
+
const { chainId, endAt, startAt, window } = options
|
|
299
|
+
const endInstant = new Date(endAt).toISOString()
|
|
300
|
+
const startInstant = new Date(startAt).toISOString()
|
|
301
|
+
const measured = await Store.memoize(
|
|
302
|
+
async () => {
|
|
303
|
+
// `blocks` indexes every block, empty ones included, so the last row at or
|
|
304
|
+
// before an instant is the exact boundary. Both boundaries share one
|
|
305
|
+
// request because the indexer sheds load by request count, not rows read.
|
|
306
|
+
const result = await options.getTidx(chainId).fetch({
|
|
307
|
+
chainId,
|
|
308
|
+
query: `
|
|
309
|
+
(SELECT num, timestamp FROM blocks WHERE timestamp <= '${endInstant}' ORDER BY num DESC LIMIT 1)
|
|
310
|
+
UNION ALL
|
|
311
|
+
(SELECT num, timestamp FROM blocks WHERE timestamp <= '${startInstant}' ORDER BY num DESC LIMIT 1)
|
|
312
|
+
` as string,
|
|
313
|
+
})
|
|
314
|
+
const rows = result.rows.flatMap((row) => {
|
|
315
|
+
const number = Value.toIntegerString(row['num'])
|
|
316
|
+
const timestamp = Value.toIsoDateTime(row['timestamp'])
|
|
317
|
+
return number === undefined || timestamp === undefined
|
|
318
|
+
? []
|
|
319
|
+
: [{ number, timestamp: Math.floor(Date.parse(timestamp) / 1000) }]
|
|
320
|
+
})
|
|
321
|
+
// The instants travel with the rows so a hit from an earlier bucket is
|
|
322
|
+
// judged, and labelled, against the instants it was resolved for.
|
|
323
|
+
return { endAt, rows, startAt }
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
key: `earn-apy:v1:${chainId}:blocks:${window}`,
|
|
327
|
+
store: options.store,
|
|
328
|
+
ttl: bucketWidth,
|
|
329
|
+
},
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
// The window start precedes indexed history whenever a boundary is missing;
|
|
333
|
+
// the newer boundary always resolves once the older one does.
|
|
334
|
+
const [end, start] = [...measured.rows].sort((a, b) =>
|
|
335
|
+
BigInt(a.number) < BigInt(b.number) ? 1 : -1,
|
|
336
|
+
)
|
|
337
|
+
if (!end || !start || end.number === start.number) return undefined
|
|
338
|
+
// A boundary further behind its instant than one bucket means the indexer is
|
|
339
|
+
// lagging, and the measured elapsed time would not match the window.
|
|
340
|
+
if (measured.endAt - end.timestamp * 1000 > bucketWidth) return undefined
|
|
341
|
+
if (measured.startAt - start.timestamp * 1000 > bucketWidth) return undefined
|
|
342
|
+
return {
|
|
343
|
+
end: { number: BigInt(end.number), timestamp: end.timestamp },
|
|
344
|
+
measuredAt: new Date(measured.endAt).toISOString(),
|
|
345
|
+
start: { number: BigInt(start.number), timestamp: start.timestamp },
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
declare namespace boundaryBlocks {
|
|
350
|
+
type Options = Pick<resolve.Options, 'chainId' | 'getTidx' | 'store'> & {
|
|
351
|
+
/** Instant the window ends at, in milliseconds. */
|
|
352
|
+
endAt: number
|
|
353
|
+
/** Instant the window starts at, in milliseconds. */
|
|
354
|
+
startAt: number
|
|
355
|
+
/** Window these boundaries span, used as the cache identity. */
|
|
356
|
+
window: Window
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Engine migrations indexed over the longest selectable window, so one scan
|
|
362
|
+
* serves every window and page anchored to the same instant. Returns undefined
|
|
363
|
+
* when the scan filled its row cap and a migration may be missing.
|
|
364
|
+
*/
|
|
365
|
+
async function recentMigrations(
|
|
366
|
+
options: recentMigrations.Options,
|
|
367
|
+
): Promise<readonly Migration[] | undefined> {
|
|
368
|
+
const { chainId, measuredAt } = options
|
|
369
|
+
// One bucket of slack because this scan and the boundaries expire
|
|
370
|
+
// independently; scanning further back only resets more windows.
|
|
371
|
+
const since = new Date(
|
|
372
|
+
Date.parse(measuredAt) - maxWindowHours * Ttl.hour(1) - bucketWidth,
|
|
373
|
+
).toISOString()
|
|
374
|
+
const migrations = await Store.memoize(
|
|
375
|
+
async () => {
|
|
376
|
+
// The emitting `address` is the vault; page and window filtering happens
|
|
377
|
+
// on the scanned rows so this stays one query per anchor.
|
|
378
|
+
const result = await options.getTidx(chainId).fetch({
|
|
379
|
+
chainId,
|
|
380
|
+
query: `
|
|
381
|
+
SELECT address, block_num
|
|
382
|
+
FROM EngineMigrated
|
|
383
|
+
WHERE block_timestamp > '${since}' AND block_timestamp <= '${measuredAt}'
|
|
384
|
+
ORDER BY block_num DESC
|
|
385
|
+
LIMIT ${migrationScanLimit + 1}
|
|
386
|
+
` as string,
|
|
387
|
+
signatures: [migratedSignature],
|
|
388
|
+
})
|
|
389
|
+
const rows: readonly Record<string, unknown>[] = result.rows
|
|
390
|
+
if (rows.length > migrationScanLimit) return null
|
|
391
|
+
return rows.flatMap((row) => {
|
|
392
|
+
const blockNumber = Value.toIntegerString(row['block_num'])
|
|
393
|
+
const vault = Value.toText(row['address'])
|
|
394
|
+
return blockNumber && vault ? [{ blockNumber, vault: vault.toLowerCase() }] : []
|
|
395
|
+
})
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
key: `earn-apy:v1:${chainId}:migrations`,
|
|
399
|
+
store: options.store,
|
|
400
|
+
ttl: bucketWidth,
|
|
401
|
+
},
|
|
402
|
+
)
|
|
403
|
+
if (!migrations) return undefined
|
|
404
|
+
return migrations.map(({ blockNumber, vault }) => ({ blockNumber: BigInt(blockNumber), vault }))
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
declare namespace recentMigrations {
|
|
408
|
+
type Options = Pick<measurePage.Options, 'chainId' | 'getTidx' | 'measuredAt' | 'store'>
|
|
409
|
+
}
|