tapimo 0.13.0 → 0.15.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/README.md +7 -4
- package/dist/ApiKey.js +1 -1
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +95 -14
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +360 -49
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +21383 -18056
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +301 -22
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +2 -1
- package/dist/Assets.js.map +1 -1
- package/dist/Handler.d.ts +0 -1
- package/dist/Handler.d.ts.map +1 -1
- package/dist/Handler.js +0 -1
- package/dist/Handler.js.map +1 -1
- package/dist/Scope.d.ts +13 -5
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +16 -5
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.js +2 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +3936 -1337
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +26 -5
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +159 -7
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +95 -43
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +1446 -0
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +465 -8
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +344 -3
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +288 -10
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/routes-support.d.ts +95 -0
- package/dist/admin/apps/routes-support.d.ts.map +1 -0
- package/dist/admin/apps/routes-support.js +151 -0
- package/dist/admin/apps/routes-support.js.map +1 -0
- package/dist/admin/apps/routes.d.ts +2764 -0
- package/dist/admin/apps/routes.d.ts.map +1 -0
- package/dist/admin/apps/routes.js +728 -0
- package/dist/admin/apps/routes.js.map +1 -0
- package/dist/admin/apps/subsidies.d.ts +501 -0
- package/dist/admin/apps/subsidies.d.ts.map +1 -0
- package/dist/admin/apps/subsidies.js +384 -0
- package/dist/admin/apps/subsidies.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +16 -16
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +3 -3
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +129 -69
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +5 -2
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +31 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +2 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +10 -1
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/analytics/tables/routesLifecycleIntervals.d.ts +72 -0
- package/dist/analytics/tables/routesLifecycleIntervals.d.ts.map +1 -0
- package/dist/analytics/tables/routesLifecycleIntervals.js +56 -0
- package/dist/analytics/tables/routesLifecycleIntervals.js.map +1 -0
- package/dist/apps/Zones.d.ts +21 -12526
- package/dist/apps/Zones.d.ts.map +1 -1
- package/dist/apps/Zones.js +40 -8
- package/dist/apps/Zones.js.map +1 -1
- package/dist/apps/data/App.d.ts +4310 -2548
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +86 -26
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +364 -34
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +495 -190
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +94 -22
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +37 -37
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
- package/dist/apps/data/routes/coingecko.js +47 -21
- package/dist/apps/data/routes/coingecko.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +1641 -352
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +1561 -120
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +15 -0
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +180 -114
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +5 -0
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +49 -38
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +125 -0
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +83 -27
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +507 -33
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +266 -156
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +47 -15
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +68 -11
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +95 -93
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +26 -14
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +16 -0
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +9 -7
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +4 -4
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +64 -20
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +1210 -70
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +301 -163
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts.map +1 -1
- package/dist/apps/data/routes/zones.js +20 -12
- package/dist/apps/data/routes/zones.js.map +1 -1
- package/dist/apps/docs/reference.js +2 -2
- package/dist/apps/docs/reference.js.map +1 -1
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +1 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +4119 -3297
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +5 -14
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +49 -8
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +221 -26
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +174 -72
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +43 -15
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +364 -78
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +274 -49
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +6 -6
- package/dist/apps/management/routes/faucet.js +1 -1
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +99 -24
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +117 -13
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +42 -42
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +6 -2
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +36 -20
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +52 -12
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +40 -40
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +6 -1
- 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 +4 -1
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/usage.js +21 -4
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +16 -16
- package/dist/apps/management/routes/webhooks.d.ts +931 -215
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +71 -25
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mcp.d.ts +1 -1
- package/dist/apps/mcp.js +7 -7
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/mpp/App.d.ts.map +1 -1
- package/dist/apps/mpp/App.js +35 -7
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +2 -0
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +30 -1
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts +22 -4
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +24 -6
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts +3 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -3
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +2 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +177 -26
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +5 -3
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +232 -25
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/{funding → routes}/Access.d.ts +4 -4
- package/dist/apps/routes/Access.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/Access.js +4 -4
- package/dist/apps/routes/Access.js.map +1 -0
- package/dist/apps/{funding → routes}/App.d.ts +841 -136
- package/dist/apps/{funding → routes}/App.d.ts.map +1 -1
- package/dist/apps/{funding → routes}/App.js +17 -17
- package/dist/apps/routes/App.js.map +1 -0
- package/dist/apps/routes/Inventory.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/Inventory.js +2 -2
- package/dist/apps/routes/Inventory.js.map +1 -0
- package/dist/apps/routes/index.d.ts +2 -0
- package/dist/apps/routes/index.d.ts.map +1 -0
- package/dist/apps/routes/index.js +2 -0
- package/dist/apps/routes/index.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/chains.d.ts +7 -7
- package/dist/apps/routes/routes/chains.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/routes/chains.js +25 -25
- package/dist/apps/routes/routes/chains.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/deposit-addresses.d.ts +123 -59
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/routes/deposit-addresses.js +498 -223
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/providers.d.ts +8 -8
- package/dist/apps/routes/routes/providers.d.ts.map +1 -0
- package/dist/apps/routes/routes/providers.js +57 -0
- package/dist/apps/routes/routes/providers.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/quotes.d.ts +19 -16
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/routes/quotes.js +55 -38
- package/dist/apps/routes/routes/quotes.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/transfers.d.ts +957 -71
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -0
- package/dist/apps/routes/routes/transfers.js +1140 -0
- package/dist/apps/routes/routes/transfers.js.map +1 -0
- package/dist/cli/Cli.d.ts +30 -0
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/commands/admin.d.ts +36 -0
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +273 -0
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/cloudflare.d.ts +16 -14
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +26 -21
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +63 -21
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +1052 -15
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +785 -133
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +590 -162
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts +4 -0
- package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts.map +1 -0
- package/dist/db/tables/apiKeyAdmissionBootstraps.js +2 -0
- package/dist/db/tables/apiKeyAdmissionBootstraps.js.map +1 -0
- package/dist/db/tables/apiKeyAdmissions.d.ts +73 -0
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -0
- package/dist/db/tables/apiKeyAdmissions.js +142 -0
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.d.ts +4 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.d.ts.map +1 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.js +2 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.js.map +1 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +20 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -0
- package/dist/db/tables/apiKeyOwnerTombstones.js +57 -0
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -0
- package/dist/db/tables/apiKeyRevocations.d.ts +21 -0
- package/dist/db/tables/apiKeyRevocations.d.ts.map +1 -0
- package/dist/db/tables/apiKeyRevocations.js +98 -0
- package/dist/db/tables/apiKeyRevocations.js.map +1 -0
- package/dist/db/tables/authAccounts.d.ts +47 -0
- package/dist/db/tables/authAccounts.d.ts.map +1 -0
- package/dist/db/tables/authAccounts.js +72 -0
- package/dist/db/tables/authAccounts.js.map +1 -0
- package/dist/db/tables/authSessions.d.ts +12 -0
- package/dist/db/tables/authSessions.d.ts.map +1 -0
- package/dist/db/tables/authSessions.js +2 -0
- package/dist/db/tables/authSessions.js.map +1 -0
- package/dist/db/tables/authVerifications.d.ts +12 -0
- package/dist/db/tables/authVerifications.d.ts.map +1 -0
- package/dist/db/tables/authVerifications.js +2 -0
- package/dist/db/tables/authVerifications.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +17 -1
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/invitations.js +123 -43
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/memberships.d.ts +8 -0
- package/dist/db/tables/memberships.d.ts.map +1 -1
- package/dist/db/tables/memberships.js +51 -2
- package/dist/db/tables/memberships.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +51 -5
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +135 -47
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +27 -1
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +38 -3
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardAccounts.d.ts +86 -0
- package/dist/db/tables/rewardAccounts.d.ts.map +1 -0
- package/dist/db/tables/rewardAccounts.js +88 -0
- package/dist/db/tables/rewardAccounts.js.map +1 -0
- package/dist/db/tables/rewardCampaignDistributors.d.ts +36 -0
- package/dist/db/tables/rewardCampaignDistributors.d.ts.map +1 -0
- package/dist/db/tables/rewardCampaignDistributors.js +30 -0
- package/dist/db/tables/rewardCampaignDistributors.js.map +1 -0
- package/dist/db/tables/rewardCampaigns.d.ts +171 -0
- package/dist/db/tables/rewardCampaigns.d.ts.map +1 -0
- package/dist/db/tables/rewardCampaigns.js +392 -0
- package/dist/db/tables/rewardCampaigns.js.map +1 -0
- package/dist/db/tables/rewardCredits.d.ts +53 -0
- package/dist/db/tables/rewardCredits.d.ts.map +1 -0
- package/dist/db/tables/rewardCredits.js +63 -0
- package/dist/db/tables/rewardCredits.js.map +1 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +61 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -0
- package/dist/db/tables/rewardEligibilityAssociations.js +103 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -0
- package/dist/db/tables/rewardRuns.d.ts +188 -0
- package/dist/db/tables/rewardRuns.d.ts.map +1 -0
- package/dist/db/tables/rewardRuns.js +278 -0
- package/dist/db/tables/rewardRuns.js.map +1 -0
- package/dist/db/tables/rewardTransactionAttempts.d.ts +100 -0
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -0
- package/dist/db/tables/rewardTransactionAttempts.js +163 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -0
- package/dist/db/tables/routesCatalog.d.ts +58 -0
- package/dist/db/tables/routesCatalog.d.ts.map +1 -0
- package/dist/db/tables/{fundingCatalog.js → routesCatalog.js} +19 -19
- package/dist/db/tables/routesCatalog.js.map +1 -0
- package/dist/db/tables/routesDepositAddresses.d.ts +476 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -0
- package/dist/db/tables/routesDepositAddresses.js +587 -0
- package/dist/db/tables/routesDepositAddresses.js.map +1 -0
- package/dist/db/tables/{fundingDepositRequestObservations.d.ts → routesDepositRequestObservations.d.ts} +6 -6
- package/dist/db/tables/routesDepositRequestObservations.d.ts.map +1 -0
- package/dist/db/tables/{fundingDepositRequestObservations.js → routesDepositRequestObservations.js} +6 -6
- package/dist/db/tables/routesDepositRequestObservations.js.map +1 -0
- package/dist/db/tables/{fundingDeposits.d.ts → routesDeposits.d.ts} +210 -22
- package/dist/db/tables/routesDeposits.d.ts.map +1 -0
- package/dist/db/tables/routesDeposits.js +576 -0
- package/dist/db/tables/routesDeposits.js.map +1 -0
- package/dist/db/tables/routesIdempotency.d.ts +166 -0
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -0
- package/dist/db/tables/routesIdempotency.js +330 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -0
- package/dist/db/tables/routesSubsidies.d.ts +27 -0
- package/dist/db/tables/routesSubsidies.d.ts.map +1 -0
- package/dist/db/tables/routesSubsidies.js +45 -0
- package/dist/db/tables/routesSubsidies.js.map +1 -0
- package/dist/db/tables/{fundingTransferEvents.d.ts → routesTransferEvents.d.ts} +3 -3
- package/dist/db/tables/routesTransferEvents.d.ts.map +1 -0
- package/dist/db/tables/{fundingTransferEvents.js → routesTransferEvents.js} +3 -3
- package/dist/db/tables/routesTransferEvents.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +19 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.js +17 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts +51 -0
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -0
- package/dist/db/tables/routesTransferSubsidyNonces.js +82 -0
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -0
- package/dist/db/tables/routesTransferTransactions.d.ts +77 -0
- package/dist/db/tables/routesTransferTransactions.d.ts.map +1 -0
- package/dist/db/tables/routesTransferTransactions.js +86 -0
- package/dist/db/tables/routesTransferTransactions.js.map +1 -0
- package/dist/db/tables/routesTransfers.d.ts +319 -0
- package/dist/db/tables/routesTransfers.d.ts.map +1 -0
- package/dist/db/tables/routesTransfers.js +372 -0
- package/dist/db/tables/routesTransfers.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +112 -13
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +241 -38
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/sponsorshipAttributions.d.ts +69 -0
- package/dist/db/tables/sponsorshipAttributions.d.ts.map +1 -0
- package/dist/db/tables/sponsorshipAttributions.js +77 -0
- package/dist/db/tables/sponsorshipAttributions.js.map +1 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.d.ts +22 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.d.ts.map +1 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.js +45 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.js.map +1 -0
- package/dist/db/tables/stripeCustomers.d.ts +11 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -1
- package/dist/db/tables/stripeCustomers.js +13 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -1
- package/dist/db/tables/users.d.ts +17 -1
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +47 -2
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +5 -1
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +22 -10
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +50 -15
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/executionError.d.ts +2 -2
- package/dist/handlers/internal/executionError.d.ts.map +1 -1
- package/dist/handlers/internal/executionError.js +1 -2
- package/dist/handlers/internal/executionError.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +4 -232
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +11 -537
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +19 -8
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +13 -9
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/relay.d.ts +9 -12
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +81 -85
- package/dist/handlers/relay.js.map +1 -1
- package/dist/index.d.ts +0 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +1 -1
- package/dist/internal/AssetResponse.d.ts +12 -0
- package/dist/internal/AssetResponse.d.ts.map +1 -0
- package/dist/internal/AssetResponse.js +21 -0
- package/dist/internal/AssetResponse.js.map +1 -0
- package/dist/internal/Auth.d.ts +48 -12
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +603 -175
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +1488 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -0
- package/dist/internal/BetterAuth.js +253 -0
- package/dist/internal/BetterAuth.js.map +1 -0
- package/dist/internal/Cache.d.ts +2 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +2 -0
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnRates.d.ts +26 -3
- package/dist/internal/EarnRates.d.ts.map +1 -1
- package/dist/internal/EarnRates.js +84 -19
- package/dist/internal/EarnRates.js.map +1 -1
- package/dist/internal/EarnSharePrices.d.ts +120 -0
- package/dist/internal/EarnSharePrices.d.ts.map +1 -0
- package/dist/internal/EarnSharePrices.js +179 -0
- package/dist/internal/EarnSharePrices.js.map +1 -0
- package/dist/internal/EarnVaults.d.ts +4 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +31 -14
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/Email.d.ts +37 -0
- package/dist/internal/Email.d.ts.map +1 -0
- package/dist/internal/Email.js +16 -0
- package/dist/internal/Email.js.map +1 -0
- package/dist/internal/Log.d.ts +32 -28
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +18 -11
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts +3 -0
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +67 -8
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/Mpp.d.ts.map +1 -1
- package/dist/internal/Mpp.js +20 -25
- package/dist/internal/Mpp.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +26 -3
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +25 -10
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Provider.d.ts +1 -1
- package/dist/internal/Provider.d.ts.map +1 -1
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +13 -1
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +16 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +59 -8
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +9 -2
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +78 -11
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Timing.d.ts +26 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +63 -5
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/VercelOidc.d.ts +94 -0
- package/dist/internal/VercelOidc.d.ts.map +1 -0
- package/dist/internal/VercelOidc.js +128 -0
- package/dist/internal/VercelOidc.js.map +1 -0
- package/dist/internal/VerifiedTokens.d.ts +2 -8
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +24 -24
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Viem.d.ts +46 -2068
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +171 -11
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +12 -4
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +9 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/ZoneRpc.d.ts +7 -0
- package/dist/internal/ZoneRpc.d.ts.map +1 -0
- package/dist/internal/ZoneRpc.js +49 -0
- package/dist/internal/ZoneRpc.js.map +1 -0
- package/dist/internal/index.d.ts +3 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +3 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/rewards/Audit.d.ts +88 -0
- package/dist/internal/rewards/Audit.d.ts.map +1 -0
- package/dist/internal/rewards/Audit.js +134 -0
- package/dist/internal/rewards/Audit.js.map +1 -0
- package/dist/internal/rewards/Campaigns.d.ts +572 -0
- package/dist/internal/rewards/Campaigns.d.ts.map +1 -0
- package/dist/internal/rewards/Campaigns.js +531 -0
- package/dist/internal/rewards/Campaigns.js.map +1 -0
- package/dist/internal/rewards/Credits.d.ts +76 -0
- package/dist/internal/rewards/Credits.d.ts.map +1 -0
- package/dist/internal/rewards/Credits.js +95 -0
- package/dist/internal/rewards/Credits.js.map +1 -0
- package/dist/internal/rewards/Events.d.ts +100 -0
- package/dist/internal/rewards/Events.d.ts.map +1 -0
- package/dist/internal/rewards/Events.js +340 -0
- package/dist/internal/rewards/Events.js.map +1 -0
- package/dist/internal/rewards/Projection.d.ts +237 -0
- package/dist/internal/rewards/Projection.d.ts.map +1 -0
- package/dist/internal/rewards/Projection.js +616 -0
- package/dist/internal/rewards/Projection.js.map +1 -0
- package/dist/internal/rewards/Rates.d.ts +44 -0
- package/dist/internal/rewards/Rates.d.ts.map +1 -0
- package/dist/internal/rewards/Rates.js +60 -0
- package/dist/internal/rewards/Rates.js.map +1 -0
- package/dist/internal/rewards/Read.d.ts +158 -0
- package/dist/internal/rewards/Read.d.ts.map +1 -0
- package/dist/internal/rewards/Read.js +292 -0
- package/dist/internal/rewards/Read.js.map +1 -0
- package/dist/internal/rewards/Runner.d.ts +164 -0
- package/dist/internal/rewards/Runner.d.ts.map +1 -0
- package/dist/internal/rewards/Runner.js +1778 -0
- package/dist/internal/rewards/Runner.js.map +1 -0
- package/dist/internal/rewards/Signer.d.ts +224 -0
- package/dist/internal/rewards/Signer.d.ts.map +1 -0
- package/dist/internal/rewards/Signer.js +135 -0
- package/dist/internal/rewards/Signer.js.map +1 -0
- package/dist/internal/rewards/index.d.ts +15 -0
- package/dist/internal/rewards/index.d.ts.map +1 -0
- package/dist/internal/rewards/index.js +15 -0
- package/dist/internal/rewards/index.js.map +1 -0
- package/dist/internal/{funding → routes}/Action.d.ts +12 -1
- package/dist/internal/routes/Action.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Action.js +17 -9
- package/dist/internal/routes/Action.js.map +1 -0
- package/dist/internal/{funding → routes}/Catalog.d.ts +20 -20
- package/dist/internal/routes/Catalog.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Catalog.js +29 -29
- package/dist/internal/routes/Catalog.js.map +1 -0
- package/dist/internal/{funding → routes}/Chain.d.ts +10 -10
- package/dist/internal/routes/Chain.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Chain.js +3 -3
- package/dist/internal/routes/Chain.js.map +1 -0
- package/dist/internal/{funding → routes}/Deposit.d.ts +45 -23
- package/dist/internal/routes/Deposit.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Deposit.js +60 -27
- package/dist/internal/routes/Deposit.js.map +1 -0
- package/dist/internal/{funding → routes}/DepositAddress.d.ts +56 -27
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/DepositAddress.js +95 -33
- package/dist/internal/routes/DepositAddress.js.map +1 -0
- package/dist/internal/{funding → routes}/DepositWebhook.d.ts +4 -4
- package/dist/internal/routes/DepositWebhook.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/DepositWebhook.js +4 -3
- package/dist/internal/routes/DepositWebhook.js.map +1 -0
- package/dist/internal/routes/Economics.d.ts +25 -0
- package/dist/internal/routes/Economics.d.ts.map +1 -0
- package/dist/internal/routes/Economics.js +28 -0
- package/dist/internal/routes/Economics.js.map +1 -0
- package/dist/internal/{funding → routes}/Evidence.d.ts +3 -3
- package/dist/internal/routes/Evidence.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Evidence.js +9 -17
- package/dist/internal/routes/Evidence.js.map +1 -0
- package/dist/internal/routes/Observability.d.ts +154 -0
- package/dist/internal/routes/Observability.d.ts.map +1 -0
- package/dist/internal/routes/Observability.js +389 -0
- package/dist/internal/routes/Observability.js.map +1 -0
- package/dist/internal/{funding → routes}/Provider.d.ts +350 -104
- package/dist/internal/routes/Provider.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Provider.js +233 -97
- package/dist/internal/routes/Provider.js.map +1 -0
- package/dist/internal/{funding → routes}/Reconciliation.d.ts +11 -6
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Reconciliation.js +408 -158
- package/dist/internal/routes/Reconciliation.js.map +1 -0
- package/dist/internal/routes/Route.d.ts +21 -0
- package/dist/internal/routes/Route.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Route.js +1 -1
- package/dist/internal/routes/Route.js.map +1 -0
- package/dist/internal/{funding → routes}/SourceObservation.d.ts +6 -6
- package/dist/internal/routes/SourceObservation.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/SourceObservation.js +13 -15
- package/dist/internal/routes/SourceObservation.js.map +1 -0
- package/dist/internal/{funding → routes}/Subsidy.d.ts +48 -3
- package/dist/internal/routes/Subsidy.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Subsidy.js +43 -3
- package/dist/internal/routes/Subsidy.js.map +1 -0
- package/dist/internal/{funding → routes}/Token.d.ts +4 -4
- package/dist/internal/routes/Token.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Token.js +3 -3
- package/dist/internal/routes/Token.js.map +1 -0
- package/dist/internal/{funding → routes}/Transfer.d.ts +324 -34
- package/dist/internal/routes/Transfer.d.ts.map +1 -0
- package/dist/internal/routes/Transfer.js +728 -0
- package/dist/internal/routes/Transfer.js.map +1 -0
- package/dist/internal/routes/TransferReconciliation.d.ts +55 -0
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -0
- package/dist/internal/routes/TransferReconciliation.js +422 -0
- package/dist/internal/routes/TransferReconciliation.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +201 -0
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TransferSubsidy.js +256 -0
- package/dist/internal/routes/TransferSubsidy.js.map +1 -0
- package/dist/internal/routes/TransferWebhook.d.ts +21 -0
- package/dist/internal/routes/TransferWebhook.d.ts.map +1 -0
- package/dist/internal/routes/TransferWebhook.js +43 -0
- package/dist/internal/routes/TransferWebhook.js.map +1 -0
- package/dist/internal/{funding → routes}/index.d.ts +3 -0
- package/dist/internal/routes/index.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/index.js +3 -0
- package/dist/internal/routes/index.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/across.d.ts +4 -4
- package/dist/internal/routes/providers/across.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/across.js +13 -13
- package/dist/internal/routes/providers/across.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/relay.d.ts +21 -12
- package/dist/internal/routes/providers/relay.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/relay.js +197 -122
- package/dist/internal/routes/providers/relay.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/rhino.d.ts +4 -4
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/rhino.js +10 -10
- package/dist/internal/routes/providers/rhino.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/squid.d.ts +4 -4
- package/dist/internal/routes/providers/squid.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/squid.js +14 -14
- package/dist/internal/routes/providers/squid.js.map +1 -0
- package/dist/internal/routes/providers/stargate.d.ts +165 -0
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -0
- package/dist/internal/routes/providers/stargate.js +898 -0
- package/dist/internal/routes/providers/stargate.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/symbiosis.d.ts +4 -4
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/symbiosis.js +30 -20
- package/dist/internal/routes/providers/symbiosis.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
- package/dist/internal/webhookDestinations/slack.js +22 -6
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/dist/providers/index.d.ts +12 -12
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +12 -12
- package/dist/providers/index.js.map +1 -1
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +19 -0
- package/dist/server.js.map +1 -0
- package/package.json +15 -4
- package/src/ApiKey.ts +1 -1
- package/src/ApiKeys.test.ts +1033 -3
- package/src/ApiKeys.ts +489 -48
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +216 -25
- package/src/App.ts +335 -31
- package/src/Assets.test.ts +2 -2
- package/src/Assets.ts +3 -1
- package/src/Auth.test-d.ts +1 -1
- package/src/Client.test-d.ts +611 -101
- package/src/Handler.ts +0 -1
- package/src/OpenApi.contract.test.ts +195 -0
- package/src/Scope.ts +17 -5
- package/src/Webhooks.ts +2 -2
- package/src/admin/App.test.ts +30 -2
- package/src/admin/App.ts +42 -6
- package/src/admin/apps/api-keys.test.ts +267 -5
- package/src/admin/apps/api-keys.ts +100 -50
- package/src/admin/apps/earn-vaults.test.ts +158 -0
- package/src/admin/apps/earn-vaults.ts +681 -7
- package/src/admin/apps/organizations.test.ts +342 -1
- package/src/admin/apps/organizations.ts +368 -8
- package/src/admin/apps/routes-support.test.ts +200 -0
- package/src/admin/apps/routes-support.ts +201 -0
- package/src/admin/apps/routes.test.ts +450 -0
- package/src/admin/apps/routes.ts +896 -0
- package/src/admin/apps/scopes.test.ts +15 -5
- package/src/admin/apps/subsidies.test.ts +306 -0
- package/src/admin/apps/subsidies.ts +457 -0
- package/src/admin/apps/verified-tokens.test.ts +8 -3
- package/src/admin/apps/verified-tokens.ts +3 -3
- package/src/admin/ui/plugin.ts +1 -2
- package/src/admin/ui/src/components/RewardCampaignForm.tsx +1009 -0
- package/src/admin/ui/src/lib/config.ts +11 -2
- package/src/admin/ui/src/lib/earn-vaults.ts +2 -2
- package/src/admin/ui/src/lib/organizations.test.ts +147 -3
- package/src/admin/ui/src/lib/organizations.ts +136 -0
- package/src/admin/ui/src/lib/query-client.ts +1 -1
- package/src/admin/ui/src/lib/reward-campaigns.ts +136 -0
- package/src/admin/ui/src/lib/routes.test.ts +88 -0
- package/src/admin/ui/src/lib/routes.ts +304 -0
- package/src/admin/ui/src/lib/subsidies.ts +75 -0
- package/src/admin/ui/src/routeTree.gen.ts +63 -0
- package/src/admin/ui/src/routes/__root.tsx +12 -1
- package/src/admin/ui/src/routes/api-keys.tsx +196 -84
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +105 -70
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +334 -2
- package/src/admin/ui/src/routes/routes.tsx +1615 -0
- package/src/admin/ui/src/routes/routes_.support.tsx +248 -0
- package/src/admin/ui/src/routes/subsidies.tsx +799 -0
- package/src/admin/ui.generated.ts +144 -69
- package/src/analytics/Analytics.test.ts +108 -18
- package/src/analytics/Analytics.ts +38 -6
- package/src/analytics/tables/requestEvents.test.ts +100 -0
- package/src/analytics/tables/requestEvents.ts +10 -1
- package/src/analytics/tables/routesLifecycleIntervals.ts +140 -0
- package/src/apps/Zones.test.ts +18 -3
- package/src/apps/Zones.ts +55 -8
- package/src/apps/composition.test.ts +68 -59
- package/src/apps/data/App.test.ts +154 -2
- package/src/apps/data/App.ts +102 -33
- package/src/apps/data/routes/activities.test.ts +419 -7
- package/src/apps/data/routes/activities.ts +683 -216
- package/src/apps/data/routes/balances.test.ts +2 -2
- package/src/apps/data/routes/blocks.test.ts +46 -1
- package/src/apps/data/routes/coingecko.test.ts +419 -1
- package/src/apps/data/routes/coingecko.ts +309 -253
- package/src/apps/data/routes/earn.discovery.test.ts +274 -0
- package/src/apps/data/routes/earn.test.ts +1661 -29
- package/src/apps/data/routes/earn.ts +2314 -328
- package/src/apps/data/routes/exchanges.test.ts +752 -30
- package/src/apps/data/routes/exchanges.ts +954 -753
- package/src/apps/data/routes/fee-amm.test.ts +224 -0
- package/src/apps/data/routes/fee-amm.ts +208 -178
- package/src/apps/data/routes/indexer.test.ts +389 -0
- package/src/apps/data/routes/indexer.ts +165 -69
- package/src/apps/data/routes/receipts.test.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +352 -8
- package/src/apps/data/routes/rpc.ts +407 -219
- package/src/apps/data/routes/rpc.zone.test.ts +340 -0
- package/src/apps/data/routes/tokenlist.test.ts +285 -0
- package/src/apps/data/routes/tokenlist.ts +173 -88
- package/src/apps/data/routes/tokens.test.ts +93 -3
- package/src/apps/data/routes/tokens.ts +39 -23
- package/src/apps/data/routes/transactions.test.ts +1 -1
- package/src/apps/data/routes/transfers.test.ts +56 -24
- package/src/apps/data/routes/transfers.ts +19 -8
- package/src/apps/data/routes/valuation.test.ts +1 -1
- package/src/apps/data/routes/verified-tokens.test.ts +345 -0
- package/src/apps/data/routes/verified-tokens.ts +99 -29
- package/src/apps/data/routes/webhooks.test.ts +659 -81
- package/src/apps/data/routes/webhooks.ts +1104 -817
- package/src/apps/data/routes/zones.test.ts +148 -71
- package/src/apps/data/routes/zones.ts +71 -55
- package/src/apps/docs/reference.ts +2 -2
- package/src/apps/index.ts +1 -1
- package/src/apps/management/App.ts +9 -51
- package/src/apps/management/Billing.test.ts +375 -14
- package/src/apps/management/Billing.ts +283 -34
- package/src/apps/management/routes/api-keys.test.ts +269 -7
- package/src/apps/management/routes/api-keys.ts +61 -20
- package/src/apps/management/routes/billing.test.ts +477 -15
- package/src/apps/management/routes/billing.ts +377 -50
- package/src/apps/management/routes/faucet.test.ts +1 -1
- package/src/apps/management/routes/faucet.ts +1 -1
- package/src/apps/management/routes/invitations.test.ts +270 -3
- package/src/apps/management/routes/invitations.ts +185 -15
- package/src/apps/management/routes/invoicePreview.test.ts +549 -0
- package/src/apps/management/routes/me.test.ts +246 -5
- package/src/apps/management/routes/me.ts +7 -2
- package/src/apps/management/routes/members.test.ts +108 -0
- package/src/apps/management/routes/orgs.test.ts +191 -3
- package/src/apps/management/routes/orgs.ts +58 -11
- package/src/apps/management/routes/projects.test.ts +33 -3
- package/src/apps/management/routes/projects.ts +6 -1
- package/src/apps/management/routes/scopes.test.ts +30 -2
- package/src/apps/management/routes/scopes.ts +4 -1
- package/src/apps/management/routes/usage.test.ts +32 -0
- package/src/apps/management/routes/usage.ts +22 -4
- package/src/apps/management/routes/webhooks.test.ts +49 -26
- package/src/apps/management/routes/webhooks.ts +93 -38
- package/src/apps/mcp.test.ts +6 -6
- package/src/apps/mcp.ts +7 -7
- package/src/apps/mpp/App.ts +37 -7
- package/src/apps/mpp/Mpp.test.ts +49 -8
- package/src/apps/mpp/Mpp.zone.test.ts +219 -0
- package/src/apps/mpp/internal/Adapter.ts +34 -0
- package/src/apps/mpp/internal/Policy.test.ts +86 -31
- package/src/apps/mpp/internal/Policy.ts +49 -7
- package/src/apps/mpp/internal/Sponsorship.test.ts +207 -0
- package/src/apps/mpp/internal/Sponsorship.ts +9 -3
- package/src/apps/relay/App.test.ts +1024 -38
- package/src/apps/relay/App.ts +228 -32
- package/src/apps/relay/App.zone-billing.test.ts +257 -0
- package/src/apps/relay/Sponsorships.test.ts +67 -4
- package/src/apps/relay/Sponsorships.ts +253 -29
- package/src/apps/relay/Sponsorships.zone.test.ts +102 -0
- package/src/apps/{funding → routes}/Access.ts +6 -6
- package/src/apps/routes/App.test.ts +165 -0
- package/src/apps/routes/App.ts +96 -0
- package/src/apps/{funding → routes}/Inventory.ts +2 -2
- package/src/apps/routes/index.ts +1 -0
- package/src/apps/{funding → routes}/routes/chains.test.ts +66 -66
- package/src/apps/{funding → routes}/routes/chains.ts +23 -23
- package/src/apps/{funding → routes}/routes/deposit-addresses.test.ts +1362 -462
- package/src/apps/{funding → routes}/routes/deposit-addresses.ts +568 -248
- package/src/apps/{funding → routes}/routes/providers.test.ts +27 -33
- package/src/apps/{funding → routes}/routes/providers.ts +23 -23
- package/src/apps/{funding → routes}/routes/quotes.test.ts +298 -41
- package/src/apps/{funding → routes}/routes/quotes.ts +57 -40
- package/src/apps/routes/routes/transfers.test.ts +2876 -0
- package/src/apps/routes/routes/transfers.ts +1332 -0
- package/src/cli/Cli.test.ts +1 -1
- package/src/cli/commands/admin.test.ts +748 -1
- package/src/cli/commands/admin.ts +278 -0
- package/src/cloudflare.ts +52 -47
- package/src/db/Db.test.ts +245 -2
- package/src/db/Db.ts +1511 -34
- package/src/db/Schema.ts +744 -228
- package/src/db/tables/apiKeyAdmissionBootstraps.ts +4 -0
- package/src/db/tables/apiKeyAdmissions.ts +218 -0
- package/src/db/tables/apiKeyOwnerAdmissions.ts +4 -0
- package/src/db/tables/apiKeyOwnerTombstones.ts +81 -0
- package/src/db/tables/apiKeyRevocations.test.ts +74 -0
- package/src/db/tables/apiKeyRevocations.ts +121 -0
- package/src/db/tables/authAccounts.ts +105 -0
- package/src/db/tables/authSessions.ts +13 -0
- package/src/db/tables/authVerifications.ts +13 -0
- package/src/db/tables/invitations.ts +142 -45
- package/src/db/tables/memberships.ts +79 -3
- package/src/db/tables/organizations.test.ts +725 -7
- package/src/db/tables/organizations.ts +182 -49
- package/src/db/tables/projects.test.ts +71 -0
- package/src/db/tables/projects.ts +59 -4
- package/src/db/tables/requestUsage.ts +4 -1
- package/src/db/tables/rewardAccounts.ts +178 -0
- package/src/db/tables/rewardCampaignDistributors.ts +68 -0
- package/src/db/tables/rewardCampaigns.test.ts +1388 -0
- package/src/db/tables/rewardCampaigns.ts +647 -0
- package/src/db/tables/rewardCredits.ts +110 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +271 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +184 -0
- package/src/db/tables/rewardRuns.ts +514 -0
- package/src/db/tables/rewardTransactionAttempts.ts +272 -0
- package/src/db/tables/routesCatalog.test.ts +185 -0
- package/src/db/tables/routesCatalog.ts +163 -0
- package/src/db/tables/routesDepositAddresses.test.ts +1048 -0
- package/src/db/tables/routesDepositAddresses.ts +1008 -0
- package/src/db/tables/{fundingDepositRequestObservations.test.ts → routesDepositRequestObservations.test.ts} +13 -14
- package/src/db/tables/{fundingDepositRequestObservations.ts → routesDepositRequestObservations.ts} +10 -10
- package/src/db/tables/{fundingDeposits.test.ts → routesDeposits.test.ts} +316 -46
- package/src/db/tables/routesDeposits.ts +1062 -0
- package/src/db/tables/routesIdempotency.test.ts +796 -0
- package/src/db/tables/routesIdempotency.ts +496 -0
- package/src/db/tables/routesSubsidies.test.ts +120 -0
- package/src/db/tables/routesSubsidies.ts +71 -0
- package/src/db/tables/{fundingTransferEvents.ts → routesTransferEvents.ts} +4 -4
- package/src/db/tables/routesTransferSubsidies.ts +38 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +124 -0
- package/src/db/tables/routesTransferTransactions.test.ts +195 -0
- package/src/db/tables/routesTransferTransactions.ts +158 -0
- package/src/db/tables/routesTransfers.test.ts +338 -0
- package/src/db/tables/routesTransfers.ts +662 -0
- package/src/db/tables/sponsoredTransactions.test.ts +563 -1
- package/src/db/tables/sponsoredTransactions.ts +386 -42
- package/src/db/tables/sponsorshipAttributions.test.ts +160 -0
- package/src/db/tables/sponsorshipAttributions.ts +168 -0
- package/src/db/tables/sponsorshipReconciliationCursors.test.ts +115 -0
- package/src/db/tables/sponsorshipReconciliationCursors.ts +67 -0
- package/src/db/tables/stripeCustomers.test.ts +85 -0
- package/src/db/tables/stripeCustomers.ts +24 -0
- package/src/db/tables/users.test.ts +129 -0
- package/src/db/tables/users.ts +49 -3
- package/src/db/tables/webhookQueueEvents.ts +8 -1
- package/src/db/tables/webhookSubscriptions.ts +103 -21
- package/src/handlers/internal/executionError.ts +3 -4
- package/src/handlers/internal/multisig.ts +13 -816
- package/src/handlers/internal/sponsorship.ts +26 -10
- package/src/handlers/relay.test-d.ts +9 -1
- package/src/handlers/relay.test.ts +823 -3
- package/src/handlers/relay.ts +127 -107
- package/src/index.test-d.ts +7 -0
- package/src/index.ts +0 -17
- package/src/internal/AssetResponse.ts +26 -0
- package/src/internal/Auth.test.ts +1564 -9
- package/src/internal/Auth.ts +833 -239
- package/src/internal/BetterAuth.test.ts +242 -0
- package/src/internal/BetterAuth.ts +349 -0
- package/src/internal/Cache.ts +2 -0
- package/src/internal/EarnRates.test.ts +17 -0
- package/src/internal/EarnRates.ts +124 -31
- package/src/internal/EarnSharePrices.test.ts +182 -0
- package/src/internal/EarnSharePrices.ts +313 -0
- package/src/internal/EarnVaults.test.ts +21 -0
- package/src/internal/EarnVaults.ts +37 -15
- package/src/internal/Email.ts +54 -0
- package/src/internal/Idempotency.test.ts +2 -2
- package/src/internal/Log.test-d.ts +10 -7
- package/src/internal/Log.test.ts +114 -16
- package/src/internal/Log.ts +55 -40
- package/src/internal/MetricSink.test.ts +313 -26
- package/src/internal/MetricSink.ts +73 -8
- package/src/internal/Mpp.test.ts +31 -0
- package/src/internal/Mpp.ts +21 -24
- package/src/internal/OpenApi.ts +45 -12
- package/src/internal/Provider.test.ts +1 -1
- package/src/internal/Provider.ts +1 -1
- package/src/internal/RateLimit.test.ts +21 -3
- package/src/internal/RateLimit.ts +12 -1
- package/src/internal/Store.test-d.ts +1 -1
- package/src/internal/Store.test.ts +151 -8
- package/src/internal/Store.ts +76 -9
- package/src/internal/Tidx.test.ts +59 -8
- package/src/internal/Tidx.ts +86 -14
- package/src/internal/Timing.test.ts +77 -0
- package/src/internal/Timing.ts +83 -6
- package/src/internal/VercelOidc.test.ts +188 -0
- package/src/internal/VercelOidc.ts +193 -0
- package/src/internal/VerifiedTokens.test.ts +60 -6
- package/src/internal/VerifiedTokens.ts +21 -24
- package/src/internal/Viem.batch.test.ts +80 -0
- package/src/internal/Viem.test.ts +201 -2
- package/src/internal/Viem.ts +249 -17
- package/src/internal/Webhooks.test.ts +125 -1
- package/src/internal/Webhooks.ts +22 -4
- package/src/internal/ZoneRpc.ts +50 -0
- package/src/internal/exchange/Provider.test.ts +2 -2
- package/src/internal/index.test.ts +3 -1
- package/src/internal/index.ts +3 -1
- package/src/internal/rewards/Audit.ts +231 -0
- package/src/internal/rewards/Campaigns.test.ts +1234 -0
- package/src/internal/rewards/Campaigns.ts +1205 -0
- package/src/internal/rewards/Credits.ts +165 -0
- package/src/internal/rewards/Events.local.test.ts +113 -0
- package/src/internal/rewards/Events.test.ts +152 -0
- package/src/internal/rewards/Events.ts +468 -0
- package/src/internal/rewards/Projection.test.ts +681 -0
- package/src/internal/rewards/Projection.ts +987 -0
- package/src/internal/rewards/Rates.test.ts +171 -0
- package/src/internal/rewards/Rates.ts +110 -0
- package/src/internal/rewards/Read.test.ts +501 -0
- package/src/internal/rewards/Read.ts +476 -0
- package/src/internal/rewards/Runner.checkpoint.test.ts +80 -0
- package/src/internal/rewards/Runner.states.test.ts +188 -0
- package/src/internal/rewards/Runner.test.ts +90 -0
- package/src/internal/rewards/Runner.ts +2229 -0
- package/src/internal/rewards/Signer.test.ts +79 -0
- package/src/internal/rewards/Signer.ts +180 -0
- package/src/internal/rewards/index.ts +14 -0
- package/src/internal/{funding → routes}/Action.test.ts +63 -14
- package/src/internal/{funding → routes}/Action.ts +35 -8
- package/src/internal/{funding → routes}/Catalog.test.ts +3 -3
- package/src/internal/{funding → routes}/Catalog.ts +39 -39
- package/src/internal/{funding → routes}/Chain.test.ts +1 -1
- package/src/internal/{funding → routes}/Chain.ts +11 -11
- package/src/internal/{funding → routes}/Deposit.test.ts +1 -1
- package/src/internal/{funding → routes}/Deposit.ts +93 -45
- package/src/internal/{funding → routes}/DepositAddress.test.ts +11 -3
- package/src/internal/{funding → routes}/DepositAddress.ts +132 -53
- package/src/internal/{funding → routes}/DepositWebhook.test.ts +61 -18
- package/src/internal/{funding → routes}/DepositWebhook.ts +9 -8
- package/src/internal/routes/Economics.test.ts +42 -0
- package/src/internal/routes/Economics.ts +47 -0
- package/src/internal/{funding → routes}/Evidence.test.ts +6 -6
- package/src/internal/{funding → routes}/Evidence.ts +11 -22
- package/src/internal/routes/Observability.test.ts +636 -0
- package/src/internal/routes/Observability.ts +668 -0
- package/src/internal/{funding → routes}/Provider.test.ts +489 -153
- package/src/internal/{funding → routes}/Provider.ts +531 -185
- package/src/internal/{funding → routes}/Reconciliation.local.test.ts +84 -12
- package/src/internal/{funding → routes}/Reconciliation.test.ts +1213 -279
- package/src/internal/{funding → routes}/Reconciliation.ts +501 -203
- package/src/internal/routes/Reconciliation.unattributed.test.ts +250 -0
- package/src/internal/{funding → routes}/Route.ts +7 -7
- package/src/internal/{funding → routes}/SourceObservation.test.ts +13 -14
- package/src/internal/{funding → routes}/SourceObservation.ts +18 -22
- package/src/internal/{funding → routes}/Subsidy.local.test.ts +7 -7
- package/src/internal/routes/Subsidy.test.ts +169 -0
- package/src/internal/{funding → routes}/Subsidy.ts +86 -6
- package/src/internal/{funding → routes}/Token.test.ts +1 -1
- package/src/internal/{funding → routes}/Token.ts +5 -5
- package/src/internal/routes/Transfer.test.ts +1199 -0
- package/src/internal/routes/Transfer.ts +1206 -0
- package/src/internal/routes/TransferReconciliation.test.ts +731 -0
- package/src/internal/routes/TransferReconciliation.ts +527 -0
- package/src/internal/routes/TransferSubsidy.test.ts +172 -0
- package/src/internal/routes/TransferSubsidy.ts +447 -0
- package/src/internal/routes/TransferWebhook.test.ts +128 -0
- package/src/internal/routes/TransferWebhook.ts +67 -0
- package/src/internal/{funding → routes}/index.test.ts +6 -3
- package/src/internal/{funding → routes}/index.ts +3 -0
- package/src/internal/{funding → routes}/providers/across.ts +16 -16
- package/src/internal/{funding → routes}/providers/index.test.ts +157 -44
- package/src/internal/{funding → routes}/providers/relay.test.ts +165 -32
- package/src/internal/{funding → routes}/providers/relay.ts +231 -136
- package/src/internal/{funding → routes}/providers/rhino.ts +16 -16
- package/src/internal/{funding → routes}/providers/squid.ts +17 -17
- package/src/internal/routes/providers/stargate.test.ts +728 -0
- package/src/internal/routes/providers/stargate.ts +1276 -0
- package/src/internal/{funding → routes}/providers/symbiosis.ts +64 -24
- package/src/internal/webhookDestinations/slack.ts +20 -5
- package/src/providers/index.ts +13 -13
- package/src/server.ts +18 -0
- package/dist/apps/funding/Access.d.ts.map +0 -1
- package/dist/apps/funding/Access.js.map +0 -1
- package/dist/apps/funding/App.js.map +0 -1
- package/dist/apps/funding/Inventory.d.ts.map +0 -1
- package/dist/apps/funding/Inventory.js.map +0 -1
- package/dist/apps/funding/ProviderAttempts.d.ts +0 -5
- package/dist/apps/funding/ProviderAttempts.d.ts.map +0 -1
- package/dist/apps/funding/ProviderAttempts.js +0 -24
- package/dist/apps/funding/ProviderAttempts.js.map +0 -1
- package/dist/apps/funding/index.d.ts +0 -2
- package/dist/apps/funding/index.d.ts.map +0 -1
- package/dist/apps/funding/index.js +0 -2
- package/dist/apps/funding/index.js.map +0 -1
- package/dist/apps/funding/routes/chains.d.ts.map +0 -1
- package/dist/apps/funding/routes/chains.js.map +0 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +0 -1
- package/dist/apps/funding/routes/deposit-addresses.js.map +0 -1
- package/dist/apps/funding/routes/providers.d.ts.map +0 -1
- package/dist/apps/funding/routes/providers.js +0 -57
- package/dist/apps/funding/routes/providers.js.map +0 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +0 -1
- package/dist/apps/funding/routes/quotes.js.map +0 -1
- package/dist/apps/funding/routes/transfers.d.ts.map +0 -1
- package/dist/apps/funding/routes/transfers.js +0 -622
- package/dist/apps/funding/routes/transfers.js.map +0 -1
- package/dist/db/tables/fundingCatalog.d.ts +0 -58
- package/dist/db/tables/fundingCatalog.d.ts.map +0 -1
- package/dist/db/tables/fundingCatalog.js.map +0 -1
- package/dist/db/tables/fundingDepositAddresses.d.ts +0 -192
- package/dist/db/tables/fundingDepositAddresses.d.ts.map +0 -1
- package/dist/db/tables/fundingDepositAddresses.js +0 -235
- package/dist/db/tables/fundingDepositAddresses.js.map +0 -1
- package/dist/db/tables/fundingDepositRequestObservations.d.ts.map +0 -1
- package/dist/db/tables/fundingDepositRequestObservations.js.map +0 -1
- package/dist/db/tables/fundingDeposits.d.ts.map +0 -1
- package/dist/db/tables/fundingDeposits.js +0 -295
- package/dist/db/tables/fundingDeposits.js.map +0 -1
- package/dist/db/tables/fundingIdempotency.d.ts +0 -91
- package/dist/db/tables/fundingIdempotency.d.ts.map +0 -1
- package/dist/db/tables/fundingIdempotency.js +0 -103
- package/dist/db/tables/fundingIdempotency.js.map +0 -1
- package/dist/db/tables/fundingTransferEvents.d.ts.map +0 -1
- package/dist/db/tables/fundingTransferEvents.js.map +0 -1
- package/dist/db/tables/fundingTransferTransactions.d.ts +0 -15
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +0 -1
- package/dist/db/tables/fundingTransferTransactions.js +0 -27
- package/dist/db/tables/fundingTransferTransactions.js.map +0 -1
- package/dist/db/tables/fundingTransfers.d.ts +0 -82
- package/dist/db/tables/fundingTransfers.d.ts.map +0 -1
- package/dist/db/tables/fundingTransfers.js +0 -89
- package/dist/db/tables/fundingTransfers.js.map +0 -1
- package/dist/internal/funding/Action.d.ts.map +0 -1
- package/dist/internal/funding/Action.js.map +0 -1
- package/dist/internal/funding/Catalog.d.ts.map +0 -1
- package/dist/internal/funding/Catalog.js.map +0 -1
- package/dist/internal/funding/Chain.d.ts.map +0 -1
- package/dist/internal/funding/Chain.js.map +0 -1
- package/dist/internal/funding/Deposit.d.ts.map +0 -1
- package/dist/internal/funding/Deposit.js.map +0 -1
- package/dist/internal/funding/DepositAddress.d.ts.map +0 -1
- package/dist/internal/funding/DepositAddress.js.map +0 -1
- package/dist/internal/funding/DepositWebhook.d.ts.map +0 -1
- package/dist/internal/funding/DepositWebhook.js.map +0 -1
- package/dist/internal/funding/Evidence.d.ts.map +0 -1
- package/dist/internal/funding/Evidence.js.map +0 -1
- package/dist/internal/funding/Provider.d.ts.map +0 -1
- package/dist/internal/funding/Provider.js.map +0 -1
- package/dist/internal/funding/Reconciliation.d.ts.map +0 -1
- package/dist/internal/funding/Reconciliation.js.map +0 -1
- package/dist/internal/funding/Route.d.ts +0 -21
- package/dist/internal/funding/Route.d.ts.map +0 -1
- package/dist/internal/funding/Route.js.map +0 -1
- package/dist/internal/funding/SourceObservation.d.ts.map +0 -1
- package/dist/internal/funding/SourceObservation.js.map +0 -1
- package/dist/internal/funding/Subsidy.d.ts.map +0 -1
- package/dist/internal/funding/Subsidy.js.map +0 -1
- package/dist/internal/funding/Token.d.ts.map +0 -1
- package/dist/internal/funding/Token.js.map +0 -1
- package/dist/internal/funding/Transfer.d.ts.map +0 -1
- package/dist/internal/funding/Transfer.js +0 -334
- package/dist/internal/funding/Transfer.js.map +0 -1
- package/dist/internal/funding/index.d.ts.map +0 -1
- package/dist/internal/funding/index.js.map +0 -1
- package/dist/internal/funding/providers/across.d.ts.map +0 -1
- package/dist/internal/funding/providers/across.js.map +0 -1
- package/dist/internal/funding/providers/relay.d.ts.map +0 -1
- package/dist/internal/funding/providers/relay.js.map +0 -1
- package/dist/internal/funding/providers/rhino.d.ts.map +0 -1
- package/dist/internal/funding/providers/rhino.js.map +0 -1
- package/dist/internal/funding/providers/squid.d.ts.map +0 -1
- package/dist/internal/funding/providers/squid.js.map +0 -1
- package/dist/internal/funding/providers/stargate.d.ts +0 -38
- package/dist/internal/funding/providers/stargate.d.ts.map +0 -1
- package/dist/internal/funding/providers/stargate.js +0 -277
- package/dist/internal/funding/providers/stargate.js.map +0 -1
- package/dist/internal/funding/providers/symbiosis.d.ts.map +0 -1
- package/dist/internal/funding/providers/symbiosis.js.map +0 -1
- package/src/apps/funding/App.test.ts +0 -78
- package/src/apps/funding/App.ts +0 -78
- package/src/apps/funding/ProviderAttempts.ts +0 -26
- package/src/apps/funding/index.ts +0 -1
- package/src/apps/funding/routes/transfers.test.ts +0 -1638
- package/src/apps/funding/routes/transfers.ts +0 -721
- package/src/db/tables/fundingCatalog.test.ts +0 -122
- package/src/db/tables/fundingCatalog.ts +0 -163
- package/src/db/tables/fundingDepositAddresses.test.ts +0 -608
- package/src/db/tables/fundingDepositAddresses.ts +0 -443
- package/src/db/tables/fundingDeposits.ts +0 -572
- package/src/db/tables/fundingIdempotency.test.ts +0 -182
- package/src/db/tables/fundingIdempotency.ts +0 -180
- package/src/db/tables/fundingTransferTransactions.test.ts +0 -69
- package/src/db/tables/fundingTransferTransactions.ts +0 -37
- package/src/db/tables/fundingTransfers.test.ts +0 -89
- package/src/db/tables/fundingTransfers.ts +0 -153
- package/src/handlers/internal/multisig.test.ts +0 -818
- package/src/internal/funding/Subsidy.test.ts +0 -75
- package/src/internal/funding/Transfer.test.ts +0 -369
- package/src/internal/funding/Transfer.ts +0 -545
- package/src/internal/funding/providers/stargate.test.ts +0 -163
- package/src/internal/funding/providers/stargate.ts +0 -409
- /package/dist/apps/{funding → routes}/Inventory.d.ts +0 -0
- /package/src/internal/{funding → routes}/Route.test.ts +0 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { type Context, Hono } from 'hono'
|
|
2
2
|
import { Value as core_Value } from 'ox'
|
|
3
|
-
import type
|
|
3
|
+
import { Abis, type Actions } from 'viem/tempo'
|
|
4
4
|
import {
|
|
5
5
|
type Chain,
|
|
6
6
|
ContractFunctionExecutionError,
|
|
7
7
|
ContractFunctionRevertedError,
|
|
8
8
|
ContractFunctionZeroDataError,
|
|
9
|
+
isAddress,
|
|
10
|
+
parseAbi,
|
|
11
|
+
parseUnits,
|
|
9
12
|
zeroAddress,
|
|
10
13
|
} from 'viem'
|
|
11
14
|
import * as z from 'zod/mini'
|
|
@@ -14,12 +17,18 @@ import type * as App from '../../../App.js'
|
|
|
14
17
|
import * as Scope from '../../../Scope.js'
|
|
15
18
|
import * as Db from '../../../db/Db.js'
|
|
16
19
|
import * as core_EarnVaults from '../../../db/tables/earnVaults.js'
|
|
20
|
+
import * as RewardCampaignDistributors from '../../../db/tables/rewardCampaignDistributors.js'
|
|
21
|
+
import * as RewardCampaigns from '../../../db/tables/rewardCampaigns.js'
|
|
22
|
+
import * as RewardEligibilityAssociations from '../../../db/tables/rewardEligibilityAssociations.js'
|
|
17
23
|
import * as Auth from '../../../internal/Auth.js'
|
|
18
24
|
import * as Cache from '../../../internal/Cache.js'
|
|
19
25
|
import * as Cursor from '../../../internal/Cursor.js'
|
|
20
26
|
import * as EarnRates from '../../../internal/EarnRates.js'
|
|
27
|
+
import * as EarnSharePrices from '../../../internal/EarnSharePrices.js'
|
|
21
28
|
import * as EarnVaults from '../../../internal/EarnVaults.js'
|
|
29
|
+
import type * as Log from '../../../internal/Log.js'
|
|
22
30
|
import * as OpenApi from '../../../internal/OpenApi.js'
|
|
31
|
+
import * as RewardRead from '../../../internal/rewards/Read.js'
|
|
23
32
|
import * as Response from '../../../internal/Response.js'
|
|
24
33
|
import * as Schema from '../../../internal/Schema.js'
|
|
25
34
|
import * as Store from '../../../internal/Store.js'
|
|
@@ -28,6 +37,7 @@ import * as Timing from '../../../internal/Timing.js'
|
|
|
28
37
|
import * as Ttl from '../../../internal/Ttl.js'
|
|
29
38
|
import * as Value from '../../../internal/Value.js'
|
|
30
39
|
import * as VerifiedTokens from '../../../internal/VerifiedTokens.js'
|
|
40
|
+
import * as Viem from '../../../internal/Viem.js'
|
|
31
41
|
import * as FxOracle from '../FxOracle.js'
|
|
32
42
|
import * as Tokens from './tokens.js'
|
|
33
43
|
import * as Valuation from './valuation.js'
|
|
@@ -35,6 +45,27 @@ import * as Valuation from './valuation.js'
|
|
|
35
45
|
const deployedSignature =
|
|
36
46
|
'event EarnStackDeployed(address indexed earnVault,address indexed earnShare,address indexed earnFees,address engine,address asset,address owner,bytes32 deploymentId,address emergencyGuardian,address asyncJanitor,uint8 migrationMode,bytes32 earnShareSalt,bytes32 controlConfigHash,bytes32 feeConfigHash,bytes32 earnFeesSalt)'
|
|
37
47
|
|
|
48
|
+
// Historical factories for this signature, verified against upstream deployments
|
|
49
|
+
// and compiled EarnFactory releases. See docs/earn-discovery.md before updating.
|
|
50
|
+
const deploymentFactories: Record<number, readonly string[]> = {
|
|
51
|
+
4217: [
|
|
52
|
+
'0x5b972d2490d06e436982fab77612fd9987f097d0',
|
|
53
|
+
'0x75b20eafdbd3dd974d00b573fd72852ab0237afd',
|
|
54
|
+
],
|
|
55
|
+
42431: [
|
|
56
|
+
'0x0f9ccbc97563a179f5f0886f89ee51c9185f6ec4',
|
|
57
|
+
'0x2aa26b7e24e6f1fb2d539d527b8f1bb5cacfa288',
|
|
58
|
+
'0x4990c74ae874f2b0fd4938662e2cdb8ca4c27887',
|
|
59
|
+
'0x518d4fbd5334bb7ff67c6ebcb67a7d60e1ef8d5d',
|
|
60
|
+
'0x6742345070be5a20ce05f53b6d08d071162c0ef8',
|
|
61
|
+
'0x846b8479d64691ff61c05137dc580a1ecdc188c5',
|
|
62
|
+
'0xb4944264260a6412351d64653f65d2c27d9cb038',
|
|
63
|
+
'0xb4ecb65a57e3585c3699c1617c2abb5de35a697d',
|
|
64
|
+
'0xb5e53c6b17c6f3a380ad94f5417c5e541dfeefac',
|
|
65
|
+
'0xe8fd5b183021ba3f6d3197c5b4238c93561b1b7a',
|
|
66
|
+
],
|
|
67
|
+
}
|
|
68
|
+
|
|
38
69
|
const depositedSignature =
|
|
39
70
|
'event Deposited(address indexed caller,address indexed receiver,uint256 assets,uint256 earnShares)'
|
|
40
71
|
|
|
@@ -56,12 +87,19 @@ const redeemRequestedSignature =
|
|
|
56
87
|
const venueSharesDepositedSignature =
|
|
57
88
|
'event VenueSharesDeposited(address indexed caller,address indexed receiver,uint256 requestedVenueShares,uint256 receivedVenueShares,uint256 earnShares)'
|
|
58
89
|
|
|
90
|
+
const unspentReturnedSignature =
|
|
91
|
+
'event UnspentReturned(address indexed treasury,uint256 earnShares)'
|
|
92
|
+
|
|
59
93
|
const maxScannedDeployments = 250
|
|
60
94
|
const scanLimit = 50
|
|
61
95
|
|
|
62
96
|
// Concurrent metadata reads in one macrotask collapse into one deployless
|
|
63
97
|
// multicall; an await between small chunks keeps each call under the RPC limit.
|
|
64
98
|
const tokenReadChunkSize = 20
|
|
99
|
+
const tempoStateAddress = '0x1c00000000000000000000000000000000000000'
|
|
100
|
+
const tempoStateAbi = parseAbi(['function tempoBlockNumber() view returns (uint64)'])
|
|
101
|
+
const zonePortalAbi = parseAbi(['function lastSyncedTempoBlockNumber() view returns (uint64)'])
|
|
102
|
+
const tokenPositionAbi = parseAbi(['function balanceOf(address account) view returns (uint256)'])
|
|
65
103
|
/** Block boundary that includes all indexed history. */
|
|
66
104
|
const beforeFirstBlockNumber = -1
|
|
67
105
|
|
|
@@ -71,6 +109,13 @@ const tvlDenomination = 'USD'
|
|
|
71
109
|
/** `Valuation.valuationFor` floors to 6 dp, so 6 is the precision a valued amount carries. */
|
|
72
110
|
const tvlDecimals = 6
|
|
73
111
|
|
|
112
|
+
function toRewardEligibilityAssociation(record: RewardEligibilityAssociations.Record) {
|
|
113
|
+
return {
|
|
114
|
+
...record,
|
|
115
|
+
id: `${record.vaultAddress}-${record.walletAddress}`,
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
74
119
|
/** Returns the smallest useful live-discovery batch. */
|
|
75
120
|
export function discoveryBatchLimit(options: discoveryBatchLimit.Options): number {
|
|
76
121
|
const needed = options.limit + 1 - options.matches
|
|
@@ -109,6 +154,118 @@ export declare namespace hasZoneAccess {
|
|
|
109
154
|
|
|
110
155
|
/** Zod schemas owned by the public Earn-vault resource. */
|
|
111
156
|
export namespace schema {
|
|
157
|
+
/** Schemas for the registerRewardEligibility operation. */
|
|
158
|
+
export namespace registerRewardEligibility {
|
|
159
|
+
/** Wallet and vault association to register for reward eligibility. */
|
|
160
|
+
export const Body = z
|
|
161
|
+
.strictObject({
|
|
162
|
+
chainId: Schema.ChainId.check(
|
|
163
|
+
z.describe('Chain containing the Earn vault.'),
|
|
164
|
+
z.meta({ examples: [4217] }),
|
|
165
|
+
),
|
|
166
|
+
transactionHash: z.optional(Schema.hash(`0x${'33'.repeat(32)}`)),
|
|
167
|
+
vaultAddress: Schema.Address.check(
|
|
168
|
+
z.describe('Earn vault contract address.'),
|
|
169
|
+
z.meta({ examples: ['0x59d27987bc7cc1521bba5f688a170c65840cbf43'] }),
|
|
170
|
+
),
|
|
171
|
+
walletAddress: Schema.Address.check(
|
|
172
|
+
z.describe('Wallet to register for rewards.'),
|
|
173
|
+
z.meta({ examples: ['0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6'] }),
|
|
174
|
+
),
|
|
175
|
+
})
|
|
176
|
+
.check(z.describe('Reward eligibility registration.'))
|
|
177
|
+
|
|
178
|
+
/** Persisted reward eligibility association. */
|
|
179
|
+
export const Association = z
|
|
180
|
+
.strictObject({
|
|
181
|
+
chainId: Schema.ChainId,
|
|
182
|
+
firstRegisteredAt: z.iso
|
|
183
|
+
.datetime()
|
|
184
|
+
.check(
|
|
185
|
+
z.describe('When the association was first registered.'),
|
|
186
|
+
z.meta({ examples: ['2026-08-25T20:00:00.000Z'] }),
|
|
187
|
+
),
|
|
188
|
+
id: z.string().check(
|
|
189
|
+
z.describe('Stable reward eligibility association identifier.'),
|
|
190
|
+
z.meta({
|
|
191
|
+
examples: [
|
|
192
|
+
'0x59d27987bc7cc1521bba5f688a170c65840cbf43-0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6',
|
|
193
|
+
],
|
|
194
|
+
}),
|
|
195
|
+
),
|
|
196
|
+
latestRegisteredAt: z.iso
|
|
197
|
+
.datetime()
|
|
198
|
+
.check(
|
|
199
|
+
z.describe('When the association was most recently registered.'),
|
|
200
|
+
z.meta({ examples: ['2026-08-25T20:00:00.000Z'] }),
|
|
201
|
+
),
|
|
202
|
+
registrationOrder: z
|
|
203
|
+
.string()
|
|
204
|
+
.check(
|
|
205
|
+
z.regex(/^\d+$/),
|
|
206
|
+
z.describe('Monotonic registration order.'),
|
|
207
|
+
z.meta({ examples: ['42'] }),
|
|
208
|
+
),
|
|
209
|
+
transactionHash: z.optional(Schema.hash(`0x${'33'.repeat(32)}`)),
|
|
210
|
+
vaultAddress: Schema.Address,
|
|
211
|
+
walletAddress: Schema.Address,
|
|
212
|
+
})
|
|
213
|
+
.check(z.describe('Persisted reward eligibility association.'))
|
|
214
|
+
|
|
215
|
+
/** Persisted reward eligibility registration result. */
|
|
216
|
+
export const Response = z
|
|
217
|
+
.strictObject({
|
|
218
|
+
association: Association,
|
|
219
|
+
created: z
|
|
220
|
+
.boolean()
|
|
221
|
+
.check(
|
|
222
|
+
z.describe('Whether this request created the association.'),
|
|
223
|
+
z.meta({ examples: [true] }),
|
|
224
|
+
),
|
|
225
|
+
})
|
|
226
|
+
.check(z.describe('Persisted reward eligibility registration result.'))
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Schemas for the getRewardEligibility operation. */
|
|
230
|
+
export namespace getRewardEligibility {
|
|
231
|
+
const Limit = z
|
|
232
|
+
._default(
|
|
233
|
+
z.pipe(
|
|
234
|
+
z.coerce.number().check(z.int(), z.gte(Schema.minLimit)),
|
|
235
|
+
z.transform((value) => Math.min(value, 100)),
|
|
236
|
+
),
|
|
237
|
+
10,
|
|
238
|
+
)
|
|
239
|
+
.check(
|
|
240
|
+
z.describe(
|
|
241
|
+
'How many items to return per page (5 to 100, default 10). Use `nextCursor` to fetch more.',
|
|
242
|
+
),
|
|
243
|
+
z.meta({ examples: [10] }),
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
/** Selects one chain and vault eligibility snapshot page. */
|
|
247
|
+
export const Query = z
|
|
248
|
+
.strictObject({
|
|
249
|
+
chainId: Schema.ChainId.check(z.describe('Chain containing the Earn vault.')),
|
|
250
|
+
cursor: Schema.Cursor,
|
|
251
|
+
limit: Limit,
|
|
252
|
+
vaultAddress: Schema.Address.check(z.describe('Earn vault contract address.')),
|
|
253
|
+
})
|
|
254
|
+
.check(z.describe('Reward eligibility page selector.'))
|
|
255
|
+
|
|
256
|
+
/** One page of eligible wallets at the cursor's fixed checkpoint. */
|
|
257
|
+
export const Response = z
|
|
258
|
+
.strictObject({
|
|
259
|
+
chainId: Schema.ChainId,
|
|
260
|
+
data: z
|
|
261
|
+
.array(Schema.Address)
|
|
262
|
+
.check(z.describe('Eligible wallet addresses in registration order.')),
|
|
263
|
+
nextCursor: Schema.NextCursor,
|
|
264
|
+
vaultAddress: Schema.Address,
|
|
265
|
+
})
|
|
266
|
+
.check(z.describe('A fixed-snapshot page of eligible wallet addresses.'))
|
|
267
|
+
}
|
|
268
|
+
|
|
112
269
|
const capability = z
|
|
113
270
|
.enum([
|
|
114
271
|
'asyncRedeem',
|
|
@@ -126,25 +283,28 @@ export namespace schema {
|
|
|
126
283
|
.enum(['erc4626', 'veda'])
|
|
127
284
|
.check(z.describe('Inferred vault engine type.'), z.meta({ examples: ['erc4626'] }))
|
|
128
285
|
|
|
129
|
-
const engine =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
286
|
+
const engine = OpenApi.component(
|
|
287
|
+
Schema.describe(
|
|
288
|
+
z.strictObject({
|
|
289
|
+
address: Schema.Address.check(
|
|
290
|
+
z.describe('Current vault engine contract address.'),
|
|
291
|
+
z.meta({ examples: ['0x59d27987bc7cc1521bba5f688a170c65840cbf43'] }),
|
|
292
|
+
),
|
|
293
|
+
type: z
|
|
294
|
+
.nullable(engineType)
|
|
295
|
+
.check(z.describe('Inferred engine type, or null when it is unknown.')),
|
|
296
|
+
venue: z
|
|
297
|
+
.nullable(
|
|
298
|
+
Schema.Address.check(
|
|
299
|
+
z.describe('Yield venue contract bound to the engine.'),
|
|
300
|
+
z.meta({ examples: ['0x9a044ae05e5e6290dcf56afd69548565e957a626'] }),
|
|
301
|
+
),
|
|
302
|
+
)
|
|
303
|
+
.check(z.describe('Yield venue, or null when the engine does not expose one.')),
|
|
304
|
+
}),
|
|
305
|
+
'Current vault engine.',
|
|
306
|
+
),
|
|
307
|
+
'EarnVaultEngine',
|
|
148
308
|
)
|
|
149
309
|
|
|
150
310
|
const include = z
|
|
@@ -156,6 +316,85 @@ export namespace schema {
|
|
|
156
316
|
'Comma-separated vault fields to include, such as `apy,tvl`.',
|
|
157
317
|
)
|
|
158
318
|
|
|
319
|
+
const aprRatio = z
|
|
320
|
+
.string()
|
|
321
|
+
.check(
|
|
322
|
+
z.regex(/^\d+(\.\d+)?$/),
|
|
323
|
+
z.describe('Annual percentage rate as a non-negative decimal ratio.'),
|
|
324
|
+
z.meta({ examples: ['0.0195'] }),
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
const reward = z.strictObject({
|
|
328
|
+
apr: z
|
|
329
|
+
.nullable(aprRatio)
|
|
330
|
+
.check(z.describe('Current reward APR, or null before its first calculation.')),
|
|
331
|
+
asset: z
|
|
332
|
+
.strictObject({
|
|
333
|
+
address: Schema.Address,
|
|
334
|
+
chainId: Schema.ChainId,
|
|
335
|
+
decimals: z
|
|
336
|
+
.number()
|
|
337
|
+
.check(
|
|
338
|
+
z.int(),
|
|
339
|
+
z.nonnegative(),
|
|
340
|
+
z.describe('Reward asset decimal places.'),
|
|
341
|
+
z.meta({ examples: [18] }),
|
|
342
|
+
),
|
|
343
|
+
})
|
|
344
|
+
.check(z.describe('EarnShare token distributed by the reward campaign.')),
|
|
345
|
+
calculatedThrough: z
|
|
346
|
+
.optional(z.number().check(z.int(), z.nonnegative()))
|
|
347
|
+
.check(
|
|
348
|
+
z.describe('Unix timestamp through which a calculated reward APR applies.'),
|
|
349
|
+
z.meta({ examples: [1788134700] }),
|
|
350
|
+
),
|
|
351
|
+
campaignId: z
|
|
352
|
+
.string()
|
|
353
|
+
.check(
|
|
354
|
+
z.describe('EarnVault address that identifies the reward campaign.'),
|
|
355
|
+
z.meta({ examples: ['0x1000000000000000000000000000000000000001'] }),
|
|
356
|
+
),
|
|
357
|
+
endsAt: z
|
|
358
|
+
.number()
|
|
359
|
+
.check(
|
|
360
|
+
z.int(),
|
|
361
|
+
z.nonnegative(),
|
|
362
|
+
z.describe('Exclusive campaign end as a Unix timestamp.'),
|
|
363
|
+
z.meta({ examples: [1790812800] }),
|
|
364
|
+
),
|
|
365
|
+
startsAt: z
|
|
366
|
+
.number()
|
|
367
|
+
.check(
|
|
368
|
+
z.int(),
|
|
369
|
+
z.nonnegative(),
|
|
370
|
+
z.describe('Inclusive campaign start as a Unix timestamp.'),
|
|
371
|
+
z.meta({ examples: [1788134400] }),
|
|
372
|
+
),
|
|
373
|
+
targetTotalApr: aprRatio.check(
|
|
374
|
+
z.describe('Configured target for combined observed vault yield and Merkle rewards.'),
|
|
375
|
+
z.meta({ examples: ['0.0700'] }),
|
|
376
|
+
),
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
const apy = z.strictObject({
|
|
380
|
+
asOf: EarnRates.schema.Apy.shape.asOf,
|
|
381
|
+
methodology: EarnRates.schema.Apy.shape.methodology,
|
|
382
|
+
net: EarnRates.schema.Apy.shape.net.check(
|
|
383
|
+
z.describe('Higher of observed vault APY and configured reward campaign targets.'),
|
|
384
|
+
),
|
|
385
|
+
rewards: z
|
|
386
|
+
.optional(z.array(reward))
|
|
387
|
+
.check(
|
|
388
|
+
z.describe(
|
|
389
|
+
'Enabled, registered Merkle rewards. Omitted when reward enrichment is unavailable.',
|
|
390
|
+
),
|
|
391
|
+
),
|
|
392
|
+
vault: EarnRates.schema.Apy.shape.net.check(
|
|
393
|
+
z.describe('Observed fee-aware vault APY before reward APR.'),
|
|
394
|
+
),
|
|
395
|
+
window: EarnRates.schema.Apy.shape.window,
|
|
396
|
+
})
|
|
397
|
+
|
|
159
398
|
// `apy` and `tvl` need indexer and FX access, so surfaces lacking either
|
|
160
399
|
// select from this reduced set instead.
|
|
161
400
|
const baseInclude = z
|
|
@@ -167,65 +406,71 @@ export namespace schema {
|
|
|
167
406
|
'Comma-separated vault fields to include, such as `access,zone`.',
|
|
168
407
|
)
|
|
169
408
|
|
|
170
|
-
const zone =
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
inputTokens: z
|
|
177
|
-
.array(Schema.Address)
|
|
178
|
-
.check(
|
|
179
|
-
z.describe('Tokens accepted by private deposits.'),
|
|
180
|
-
z.meta({ examples: [['0x20c0000000000000000000002139993d5f625d59']] }),
|
|
181
|
-
),
|
|
182
|
-
name: z
|
|
183
|
-
.string()
|
|
184
|
-
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-moderato-internal'] })),
|
|
185
|
-
outputTokens: z
|
|
186
|
-
.array(Schema.Address)
|
|
187
|
-
.check(
|
|
188
|
-
z.describe('Tokens supported by private redemptions.'),
|
|
189
|
-
z.meta({ examples: [['0x20c0000000000000000000002139993d5f625d59']] }),
|
|
409
|
+
const zone = OpenApi.component(
|
|
410
|
+
z
|
|
411
|
+
.strictObject({
|
|
412
|
+
chainId: Schema.ChainId.check(
|
|
413
|
+
z.describe('Private Zone chain id.'),
|
|
414
|
+
z.meta({ examples: [421700001] }),
|
|
190
415
|
),
|
|
191
|
-
|
|
192
|
-
|
|
416
|
+
inputTokens: z
|
|
417
|
+
.array(Schema.Address)
|
|
418
|
+
.check(
|
|
419
|
+
z.describe('Tokens accepted by private deposits.'),
|
|
420
|
+
z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] }),
|
|
421
|
+
),
|
|
422
|
+
name: z
|
|
423
|
+
.string()
|
|
424
|
+
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-mainnet-internal'] })),
|
|
425
|
+
outputTokens: z
|
|
426
|
+
.array(Schema.Address)
|
|
427
|
+
.check(
|
|
428
|
+
z.describe('Tokens supported by private redemptions.'),
|
|
429
|
+
z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] }),
|
|
430
|
+
),
|
|
431
|
+
})
|
|
432
|
+
.check(z.describe('Private Zone route configured for a verified vault.')),
|
|
433
|
+
'EarnVaultZone',
|
|
434
|
+
)
|
|
193
435
|
|
|
194
|
-
const zoneRoute =
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
deploymentBlock: z
|
|
201
|
-
.number()
|
|
202
|
-
.check(
|
|
203
|
-
z.int(),
|
|
204
|
-
z.nonnegative(),
|
|
205
|
-
z.describe('Parent-chain block that deployed the Earn router.'),
|
|
206
|
-
z.meta({ examples: [31730087] }),
|
|
207
|
-
),
|
|
208
|
-
earnRouter: Schema.Address.check(
|
|
209
|
-
z.describe('Parent-chain router for this Zone and Earn vault.'),
|
|
210
|
-
z.meta({ examples: ['0xebedc74ffeead186acc6cac05eb82fb9e093a7c7'] }),
|
|
211
|
-
),
|
|
212
|
-
inputTokens: z
|
|
213
|
-
.array(Schema.Address)
|
|
214
|
-
.check(
|
|
215
|
-
z.describe('Tokens accepted by private deposits.'),
|
|
216
|
-
z.meta({ examples: [['0x20c0000000000000000000002139993d5f625d59']] }),
|
|
436
|
+
const zoneRoute = OpenApi.component(
|
|
437
|
+
z
|
|
438
|
+
.strictObject({
|
|
439
|
+
chainId: Schema.ChainId.check(
|
|
440
|
+
z.describe('Private Zone chain id.'),
|
|
441
|
+
z.meta({ examples: [421700001] }),
|
|
217
442
|
),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
443
|
+
deploymentBlock: z
|
|
444
|
+
.number()
|
|
445
|
+
.check(
|
|
446
|
+
z.int(),
|
|
447
|
+
z.nonnegative(),
|
|
448
|
+
z.describe('Parent-chain block that deployed the Earn router.'),
|
|
449
|
+
z.meta({ examples: [35822949] }),
|
|
450
|
+
),
|
|
451
|
+
earnRouter: Schema.Address.check(
|
|
452
|
+
z.describe('Parent-chain router for this Zone and Earn vault.'),
|
|
453
|
+
z.meta({ examples: ['0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6'] }),
|
|
226
454
|
),
|
|
227
|
-
|
|
228
|
-
|
|
455
|
+
inputTokens: z
|
|
456
|
+
.array(Schema.Address)
|
|
457
|
+
.check(
|
|
458
|
+
z.describe('Tokens accepted by private deposits.'),
|
|
459
|
+
z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] }),
|
|
460
|
+
),
|
|
461
|
+
name: z
|
|
462
|
+
.string()
|
|
463
|
+
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-mainnet-internal'] })),
|
|
464
|
+
outputTokens: z
|
|
465
|
+
.array(Schema.Address)
|
|
466
|
+
.check(
|
|
467
|
+
z.describe('Tokens returned by private redemptions.'),
|
|
468
|
+
z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] }),
|
|
469
|
+
),
|
|
470
|
+
})
|
|
471
|
+
.check(z.describe('Verified Earn route through one private Zone.')),
|
|
472
|
+
'EarnVaultZoneRoute',
|
|
473
|
+
)
|
|
229
474
|
|
|
230
475
|
const value = z.strictObject({
|
|
231
476
|
amount: Schema.DecimalString.check(
|
|
@@ -257,13 +502,28 @@ export namespace schema {
|
|
|
257
502
|
.optional(EarnVaults.schema.Discovery.shape.access)
|
|
258
503
|
.check(z.describe('Vault share-token access, when requested.')),
|
|
259
504
|
apy: z
|
|
260
|
-
.optional(z.nullable(
|
|
505
|
+
.optional(z.nullable(apy))
|
|
261
506
|
.check(
|
|
262
507
|
z.describe(
|
|
263
|
-
'Annualized
|
|
508
|
+
'Annualized vault yield over the selected window, plus every available current Merkle reward APR. Null when no component is measurable.',
|
|
264
509
|
),
|
|
265
510
|
),
|
|
266
|
-
assetToken: Tokens.schema.Token.check(
|
|
511
|
+
assetToken: Tokens.schema.Token.check(
|
|
512
|
+
z.describe('Asset accepted by the vault.'),
|
|
513
|
+
z.meta({
|
|
514
|
+
examples: [
|
|
515
|
+
{
|
|
516
|
+
address: '0x20c0000000000000000000000000000000000000',
|
|
517
|
+
currency: 'USD',
|
|
518
|
+
decimals: 6,
|
|
519
|
+
id: '0x20c0000000000000000000000000000000000000',
|
|
520
|
+
name: 'PathUSD',
|
|
521
|
+
symbol: 'pathUSD',
|
|
522
|
+
verified: true,
|
|
523
|
+
},
|
|
524
|
+
],
|
|
525
|
+
}),
|
|
526
|
+
),
|
|
267
527
|
capabilities: z
|
|
268
528
|
.optional(EarnVaults.schema.Discovery.shape.capabilities)
|
|
269
529
|
.check(z.describe('Vault capabilities, when requested.')),
|
|
@@ -271,21 +531,28 @@ export namespace schema {
|
|
|
271
531
|
.nullable(z.string())
|
|
272
532
|
.check(
|
|
273
533
|
z.describe('Curated vault description, or null when the vault is not verified.'),
|
|
274
|
-
z.meta({ examples: ['
|
|
534
|
+
z.meta({ examples: ['deelUSD deposited into the canonical Tempo Earn deployment.'] }),
|
|
275
535
|
),
|
|
276
536
|
engine,
|
|
277
537
|
id: Schema.Address.check(
|
|
278
538
|
z.describe('Stable vault id, equal to the lowercase vault address.'),
|
|
279
|
-
z.meta({ examples: ['
|
|
539
|
+
z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] }),
|
|
280
540
|
),
|
|
281
541
|
instantLiquidity: EarnVaults.schema.Discovery.shape.instantLiquidity.check(
|
|
282
542
|
z.describe(
|
|
283
543
|
'Assets the venue would release right now, capped at the vault backing, in asset base units. Null when the engine interface cannot report a reliable number.',
|
|
284
544
|
),
|
|
285
545
|
),
|
|
546
|
+
instantLiquidityValue: z
|
|
547
|
+
.optional(z.nullable(value))
|
|
548
|
+
.check(
|
|
549
|
+
z.describe(
|
|
550
|
+
'Instant liquidity valued in USD, when requested via `include=tvl`, or null when liquidity is unavailable or the asset has no priced display currency.',
|
|
551
|
+
),
|
|
552
|
+
),
|
|
286
553
|
label: z
|
|
287
554
|
.string()
|
|
288
|
-
.check(z.describe('Vault display label.'), z.meta({ examples: ['
|
|
555
|
+
.check(z.describe('Vault display label.'), z.meta({ examples: ['deelUSD Earn'] })),
|
|
289
556
|
sharePrice: z
|
|
290
557
|
.nullable(value)
|
|
291
558
|
.check(
|
|
@@ -293,12 +560,27 @@ export namespace schema {
|
|
|
293
560
|
'Assets returned for one whole earn share, in the asset display currency, or null when the engine cannot quote an exit.',
|
|
294
561
|
),
|
|
295
562
|
),
|
|
296
|
-
shareToken: Tokens.schema.Token.check(
|
|
563
|
+
shareToken: Tokens.schema.Token.check(
|
|
564
|
+
z.describe('Token representing vault shares.'),
|
|
565
|
+
z.meta({
|
|
566
|
+
examples: [
|
|
567
|
+
{
|
|
568
|
+
address: '0x20c000000000000000000000c3268d803b51d448',
|
|
569
|
+
currency: 'USD',
|
|
570
|
+
decimals: 6,
|
|
571
|
+
id: '0x20c000000000000000000000c3268d803b51d448',
|
|
572
|
+
name: 'Sentora pathUSD (Earn)',
|
|
573
|
+
symbol: 'senpathUSDE',
|
|
574
|
+
verified: false,
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
}),
|
|
578
|
+
),
|
|
297
579
|
slug: z
|
|
298
580
|
.nullable(z.string())
|
|
299
581
|
.check(
|
|
300
582
|
z.describe('Curated URL slug, or null when the vault is not verified.'),
|
|
301
|
-
z.meta({ examples: ['
|
|
583
|
+
z.meta({ examples: ['deelusd-earn'] }),
|
|
302
584
|
),
|
|
303
585
|
state: EarnVaults.schema.Discovery.shape.state,
|
|
304
586
|
tvl: z
|
|
@@ -310,7 +592,7 @@ export namespace schema {
|
|
|
310
592
|
),
|
|
311
593
|
vaultAddress: Schema.Address.check(
|
|
312
594
|
z.describe('Earn vault contract address.'),
|
|
313
|
-
z.meta({ examples: ['
|
|
595
|
+
z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] }),
|
|
314
596
|
),
|
|
315
597
|
verified: z
|
|
316
598
|
.boolean()
|
|
@@ -327,12 +609,12 @@ export namespace schema {
|
|
|
327
609
|
examples: [
|
|
328
610
|
[
|
|
329
611
|
{
|
|
330
|
-
chainId:
|
|
331
|
-
deploymentBlock:
|
|
332
|
-
earnRouter: '
|
|
333
|
-
inputTokens: ['
|
|
334
|
-
name: 'zone-
|
|
335
|
-
outputTokens: ['
|
|
612
|
+
chainId: 421700001,
|
|
613
|
+
deploymentBlock: 35822949,
|
|
614
|
+
earnRouter: '0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6',
|
|
615
|
+
inputTokens: ['0x20c0000000000000000000006fd9a167923ba194'],
|
|
616
|
+
name: 'zone-mainnet-internal',
|
|
617
|
+
outputTokens: ['0x20c0000000000000000000006fd9a167923ba194'],
|
|
336
618
|
},
|
|
337
619
|
],
|
|
338
620
|
],
|
|
@@ -341,26 +623,32 @@ export namespace schema {
|
|
|
341
623
|
})
|
|
342
624
|
|
|
343
625
|
/** One compatible Earn vault resolved from current chain state. */
|
|
344
|
-
export const Vault =
|
|
626
|
+
export const Vault = OpenApi.component(
|
|
627
|
+
Schema.describe(vault, 'A compatible earn vault resolved from chain state.'),
|
|
628
|
+
'EarnVault',
|
|
629
|
+
)
|
|
345
630
|
|
|
346
631
|
/** One registry-curated Earn vault. */
|
|
347
|
-
export const VerifiedVault =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
632
|
+
export const VerifiedVault = OpenApi.component(
|
|
633
|
+
Schema.describe(
|
|
634
|
+
z.extend(vault, {
|
|
635
|
+
engine: z.extend(engine, { type: engineType }),
|
|
636
|
+
slug: z
|
|
637
|
+
.string()
|
|
638
|
+
.check(
|
|
639
|
+
z.describe('Stable curated vault slug.'),
|
|
640
|
+
z.meta({ examples: ['btpathusd-earn-h8k2m4n6'] }),
|
|
641
|
+
),
|
|
642
|
+
verified: z
|
|
643
|
+
.literal(true)
|
|
644
|
+
.check(
|
|
645
|
+
z.describe('This vault is in the curated earn registry.'),
|
|
646
|
+
z.meta({ examples: [true] }),
|
|
647
|
+
),
|
|
648
|
+
}),
|
|
649
|
+
'A registry-curated earn vault resolved from chain state.',
|
|
650
|
+
),
|
|
651
|
+
'VerifiedEarnVault',
|
|
364
652
|
)
|
|
365
653
|
|
|
366
654
|
const position = z.strictObject({
|
|
@@ -369,26 +657,34 @@ export namespace schema {
|
|
|
369
657
|
z.meta({ examples: ['0xbe058e1c4df8a4366a387bf595b284246a93039e'] }),
|
|
370
658
|
),
|
|
371
659
|
assetAllowance: Schema.DecimalString.check(
|
|
372
|
-
z.describe(
|
|
660
|
+
z.describe(
|
|
661
|
+
'Assets the vault may spend from a direct account, in asset base units. Always zero for Zone-routed positions, which use Zone withdrawals instead of approvals.',
|
|
662
|
+
),
|
|
373
663
|
z.meta({ examples: ['0'] }),
|
|
374
664
|
),
|
|
375
665
|
assetBalance: Schema.DecimalString.check(
|
|
376
|
-
z.describe('Assets this account
|
|
666
|
+
z.describe('Assets held by this account at the observation block, in asset base units.'),
|
|
377
667
|
z.meta({ examples: ['250000000'] }),
|
|
378
668
|
),
|
|
379
669
|
assetToken: Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50').check(
|
|
380
|
-
z.describe('TIP-20 asset token accepted by the vault.'),
|
|
670
|
+
z.describe('TIP-20 asset token accepted by the vault or its selected Zone route.'),
|
|
671
|
+
),
|
|
672
|
+
chainId: Schema.ChainId.check(
|
|
673
|
+
z.describe('Chain containing the account position.'),
|
|
674
|
+
z.meta({ examples: [42431] }),
|
|
381
675
|
),
|
|
382
676
|
id: Schema.Address.check(
|
|
383
677
|
z.describe('Stable resource ID for this vault position, equal to the account address.'),
|
|
384
678
|
z.meta({ examples: ['0xbe058e1c4df8a4366a387bf595b284246a93039e'] }),
|
|
385
679
|
),
|
|
386
680
|
shareAllowance: Schema.DecimalString.check(
|
|
387
|
-
z.describe(
|
|
681
|
+
z.describe(
|
|
682
|
+
'Earn shares the vault may spend from a direct account, in share base units. Always zero for Zone-routed positions, which use Zone withdrawals instead of approvals.',
|
|
683
|
+
),
|
|
388
684
|
z.meta({ examples: ['0'] }),
|
|
389
685
|
),
|
|
390
686
|
shareBalance: Schema.DecimalString.check(
|
|
391
|
-
z.describe('Earn shares this account
|
|
687
|
+
z.describe('Earn shares held by this account at the observation block, in share base units.'),
|
|
392
688
|
z.meta({ examples: ['99500000'] }),
|
|
393
689
|
),
|
|
394
690
|
shareToken: Schema.tokenAddress('0x20c000000000000000000000300e14ab91a10769').check(
|
|
@@ -396,44 +692,165 @@ export namespace schema {
|
|
|
396
692
|
),
|
|
397
693
|
value: Schema.DecimalString.check(
|
|
398
694
|
z.describe(
|
|
399
|
-
'
|
|
695
|
+
'Asset value of this account’s earn shares at the observation block, including fees, in `valueToken` base units.',
|
|
400
696
|
),
|
|
401
697
|
z.meta({ examples: ['100000000'] }),
|
|
402
698
|
),
|
|
699
|
+
valueToken: Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50').check(
|
|
700
|
+
z.describe('TIP-20 asset denominating `value` on the vault’s parent chain.'),
|
|
701
|
+
),
|
|
403
702
|
})
|
|
404
703
|
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
z
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
704
|
+
const positionApy = z
|
|
705
|
+
.strictObject({
|
|
706
|
+
breakdown: z
|
|
707
|
+
.array(
|
|
708
|
+
z
|
|
709
|
+
.strictObject({
|
|
710
|
+
assetAmount: z
|
|
711
|
+
.strictObject({
|
|
712
|
+
baseUnits: Schema.DecimalString.check(
|
|
713
|
+
z.describe('Position amount in vault asset base units.'),
|
|
714
|
+
z.meta({ examples: ['25000000000'] }),
|
|
715
|
+
),
|
|
716
|
+
decimals: z
|
|
717
|
+
.number()
|
|
718
|
+
.check(
|
|
719
|
+
z.int(),
|
|
720
|
+
z.nonnegative(),
|
|
721
|
+
z.describe('Vault asset decimal places.'),
|
|
722
|
+
z.meta({ examples: [6] }),
|
|
723
|
+
),
|
|
724
|
+
formatted: z
|
|
725
|
+
.string()
|
|
726
|
+
.check(
|
|
727
|
+
z.regex(/^\d+(\.\d+)?$/),
|
|
728
|
+
z.describe('Position amount rendered in whole vault asset units.'),
|
|
729
|
+
z.meta({ examples: ['25000'] }),
|
|
730
|
+
),
|
|
731
|
+
})
|
|
732
|
+
.check(
|
|
733
|
+
z.describe('Vault asset amount receiving this annual rate.'),
|
|
734
|
+
z.meta({
|
|
735
|
+
examples: [{ baseUnits: '25000000000', decimals: 6, formatted: '25000' }],
|
|
736
|
+
}),
|
|
737
|
+
),
|
|
738
|
+
net: EarnRates.schema.Apy.shape.net.check(
|
|
739
|
+
z.describe('Annual rate applied to this position amount.'),
|
|
740
|
+
z.meta({ examples: ['0.07'] }),
|
|
741
|
+
),
|
|
742
|
+
type: z
|
|
743
|
+
.enum(['base', 'boost'])
|
|
744
|
+
.check(
|
|
745
|
+
z.describe('Base vault yield or qualified depositor boost.'),
|
|
746
|
+
z.meta({ examples: ['boost'] }),
|
|
747
|
+
),
|
|
748
|
+
})
|
|
749
|
+
.check(z.describe('Position component receiving one annual rate.')),
|
|
750
|
+
)
|
|
751
|
+
.check(
|
|
752
|
+
z.describe('Position amounts grouped by the annual rate they receive.'),
|
|
753
|
+
z.meta({
|
|
754
|
+
examples: [
|
|
755
|
+
[
|
|
756
|
+
{
|
|
757
|
+
assetAmount: {
|
|
758
|
+
baseUnits: '25000000000',
|
|
759
|
+
decimals: 6,
|
|
760
|
+
formatted: '25000',
|
|
761
|
+
},
|
|
762
|
+
net: '0.07',
|
|
763
|
+
type: 'boost',
|
|
764
|
+
},
|
|
765
|
+
],
|
|
766
|
+
],
|
|
767
|
+
}),
|
|
424
768
|
),
|
|
769
|
+
net: EarnRates.schema.Apy.shape.net.check(
|
|
770
|
+
z.describe('Balance-weighted annual rate for this wallet position.'),
|
|
771
|
+
z.meta({ examples: ['0.0616666666666667'] }),
|
|
425
772
|
),
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
z.
|
|
429
|
-
|
|
430
|
-
verified: z
|
|
431
|
-
.boolean()
|
|
432
|
-
.check(
|
|
433
|
-
z.describe('Whether the vault is in the curated earn registry.'),
|
|
434
|
-
z.meta({ examples: [true] }),
|
|
773
|
+
})
|
|
774
|
+
.check(
|
|
775
|
+
z.describe(
|
|
776
|
+
'Wallet-specific effective APY combining live position amounts with qualification from the latest delivered reward snapshot.',
|
|
435
777
|
),
|
|
436
|
-
|
|
778
|
+
)
|
|
779
|
+
|
|
780
|
+
const lifetimeCashFlows = z.union([
|
|
781
|
+
z.strictObject({
|
|
782
|
+
status: z
|
|
783
|
+
.literal('complete')
|
|
784
|
+
.check(
|
|
785
|
+
z.describe('Cash flows are complete through the indexed boundary.'),
|
|
786
|
+
z.meta({ examples: ['complete'] }),
|
|
787
|
+
),
|
|
788
|
+
totalDeposited: Schema.DecimalString.check(
|
|
789
|
+
z.describe('Assets deposited with this account as receiver over indexed vault history.'),
|
|
790
|
+
),
|
|
791
|
+
totalWithdrawn: Schema.DecimalString.check(
|
|
792
|
+
z.describe('Assets returned by completed withdrawals over indexed vault history.'),
|
|
793
|
+
),
|
|
794
|
+
}),
|
|
795
|
+
z.strictObject({
|
|
796
|
+
status: z
|
|
797
|
+
.literal('incomplete_history')
|
|
798
|
+
.check(
|
|
799
|
+
z.describe('Cash flows are omitted because asset deposit history is incomplete.'),
|
|
800
|
+
z.meta({ examples: ['incomplete_history'] }),
|
|
801
|
+
),
|
|
802
|
+
}),
|
|
803
|
+
])
|
|
804
|
+
|
|
805
|
+
const addressPosition = OpenApi.component(
|
|
806
|
+
z
|
|
807
|
+
.strictObject({
|
|
808
|
+
assetAmount: value.check(
|
|
809
|
+
z.describe(
|
|
810
|
+
'Current asset value of the held shares, including fees, in `valueToken` units.',
|
|
811
|
+
),
|
|
812
|
+
),
|
|
813
|
+
assetToken: Tokens.schema.Token.check(z.describe('Asset accepted by the vault.')),
|
|
814
|
+
chainId: Schema.ChainId.check(
|
|
815
|
+
z.describe('Chain containing the held shares.'),
|
|
816
|
+
z.meta({ examples: [42431] }),
|
|
817
|
+
),
|
|
818
|
+
id: Schema.Address.check(
|
|
819
|
+
z.describe('Stable resource ID for this position, equal to the vault address.'),
|
|
820
|
+
z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] }),
|
|
821
|
+
),
|
|
822
|
+
lifetimeCashFlows: z
|
|
823
|
+
.optional(lifetimeCashFlows)
|
|
824
|
+
.check(z.describe('Lifetime deposits and completed withdrawals, when requested.')),
|
|
825
|
+
shareAmount: value.check(
|
|
826
|
+
z.describe('Earn share balance this account holds, in `shareToken` units.'),
|
|
827
|
+
),
|
|
828
|
+
shareToken: Tokens.schema.Token.check(z.describe('Token representing vault shares.')),
|
|
829
|
+
valuation: z
|
|
830
|
+
.optional(z.nullable(Valuation.schema.Value))
|
|
831
|
+
.check(
|
|
832
|
+
z.describe(
|
|
833
|
+
'The position’s nominal value when `valuation.currency` is requested, or `null` when ' +
|
|
834
|
+
'the asset token is unverified, its display currency has no rate, or rates were unavailable.',
|
|
835
|
+
),
|
|
836
|
+
),
|
|
837
|
+
valueToken: Tokens.schema.Token.check(
|
|
838
|
+
z.describe('Parent-chain asset denominating `assetAmount`.'),
|
|
839
|
+
),
|
|
840
|
+
vaultAddress: Schema.Address.check(
|
|
841
|
+
z.describe('Earn vault contract address holding this position.'),
|
|
842
|
+
z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] }),
|
|
843
|
+
),
|
|
844
|
+
verified: z
|
|
845
|
+
.boolean()
|
|
846
|
+
.check(
|
|
847
|
+
z.describe('Whether the vault is in the curated earn registry.'),
|
|
848
|
+
z.meta({ examples: [true] }),
|
|
849
|
+
),
|
|
850
|
+
})
|
|
851
|
+
.check(z.describe('An account’s position in one earn vault.')),
|
|
852
|
+
'EarnAddressPosition',
|
|
853
|
+
)
|
|
437
854
|
|
|
438
855
|
const earningsBase = z.strictObject({
|
|
439
856
|
account: Schema.Address.check(
|
|
@@ -476,6 +893,18 @@ export namespace schema {
|
|
|
476
893
|
),
|
|
477
894
|
z.meta({ examples: ['0'] }),
|
|
478
895
|
),
|
|
896
|
+
totalDeposited: Schema.DecimalString.check(
|
|
897
|
+
z.describe(
|
|
898
|
+
'Assets deposited with this account as receiver over complete indexed vault history.',
|
|
899
|
+
),
|
|
900
|
+
z.meta({ examples: ['1000000'] }),
|
|
901
|
+
),
|
|
902
|
+
totalWithdrawn: Schema.DecimalString.check(
|
|
903
|
+
z.describe(
|
|
904
|
+
'Assets returned by completed redemptions and exact withdrawals initiated by this account over complete indexed vault history.',
|
|
905
|
+
),
|
|
906
|
+
z.meta({ examples: ['1000000'] }),
|
|
907
|
+
),
|
|
479
908
|
period: z
|
|
480
909
|
.literal('lifetime')
|
|
481
910
|
.check(
|
|
@@ -548,9 +977,23 @@ export namespace schema {
|
|
|
548
977
|
}),
|
|
549
978
|
z.extend(earningsBase, {
|
|
550
979
|
period: z
|
|
551
|
-
.
|
|
980
|
+
.literal('30d')
|
|
552
981
|
.check(
|
|
553
|
-
z.describe('
|
|
982
|
+
z.describe('Trailing period with an unresolved async redemption.'),
|
|
983
|
+
z.meta({ examples: ['30d'] }),
|
|
984
|
+
),
|
|
985
|
+
status: z
|
|
986
|
+
.literal('pending_redemption')
|
|
987
|
+
.check(
|
|
988
|
+
z.describe('Earnings are unavailable while an async redemption remains open.'),
|
|
989
|
+
z.meta({ examples: ['pending_redemption'] }),
|
|
990
|
+
),
|
|
991
|
+
}),
|
|
992
|
+
z.extend(earningsBase, {
|
|
993
|
+
period: z
|
|
994
|
+
.literal('lifetime')
|
|
995
|
+
.check(
|
|
996
|
+
z.describe('Lifetime period with an unresolved async redemption.'),
|
|
554
997
|
z.meta({ examples: ['lifetime'] }),
|
|
555
998
|
),
|
|
556
999
|
status: z
|
|
@@ -559,6 +1002,12 @@ export namespace schema {
|
|
|
559
1002
|
z.describe('Earnings are unavailable while an async redemption remains open.'),
|
|
560
1003
|
z.meta({ examples: ['pending_redemption'] }),
|
|
561
1004
|
),
|
|
1005
|
+
totalDeposited: Schema.DecimalString.check(
|
|
1006
|
+
z.describe('Assets deposited over complete indexed vault history.'),
|
|
1007
|
+
),
|
|
1008
|
+
totalWithdrawn: Schema.DecimalString.check(
|
|
1009
|
+
z.describe('Assets withdrawn over complete indexed vault history.'),
|
|
1010
|
+
),
|
|
562
1011
|
}),
|
|
563
1012
|
])
|
|
564
1013
|
|
|
@@ -606,15 +1055,18 @@ export namespace schema {
|
|
|
606
1055
|
export const Query = collectionQuery
|
|
607
1056
|
|
|
608
1057
|
/** Paginated list of compatible deployed Earn vaults. */
|
|
609
|
-
export const Response =
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
1058
|
+
export const Response = OpenApi.component(
|
|
1059
|
+
z
|
|
1060
|
+
.strictObject({
|
|
1061
|
+
data: z
|
|
1062
|
+
.array(Vault)
|
|
1063
|
+
.check(z.describe('Compatible deployed earn vaults in deployment order.')),
|
|
1064
|
+
meta: z.optional(meta),
|
|
1065
|
+
nextCursor: Schema.NextCursor,
|
|
1066
|
+
})
|
|
1067
|
+
.check(z.describe('A page of compatible deployed earn vaults.')),
|
|
1068
|
+
'EarnVaultList',
|
|
1069
|
+
)
|
|
618
1070
|
}
|
|
619
1071
|
|
|
620
1072
|
/** Schemas for the getVerifiedEarnVaults operation. */
|
|
@@ -629,15 +1081,18 @@ export namespace schema {
|
|
|
629
1081
|
export const Query = collectionQuery
|
|
630
1082
|
|
|
631
1083
|
/** Paginated list of registry-curated Earn vaults. */
|
|
632
|
-
export const Response =
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
1084
|
+
export const Response = OpenApi.component(
|
|
1085
|
+
z
|
|
1086
|
+
.strictObject({
|
|
1087
|
+
data: z
|
|
1088
|
+
.array(VerifiedVault)
|
|
1089
|
+
.check(z.describe('Registry-curated earn vaults ordered by vault address.')),
|
|
1090
|
+
meta: z.optional(meta),
|
|
1091
|
+
nextCursor: Schema.NextCursor,
|
|
1092
|
+
})
|
|
1093
|
+
.check(z.describe('A page of registry-curated earn vaults.')),
|
|
1094
|
+
'VerifiedEarnVaultList',
|
|
1095
|
+
)
|
|
641
1096
|
}
|
|
642
1097
|
|
|
643
1098
|
/** Schemas for the getEarnAddressPositions operation. */
|
|
@@ -654,6 +1109,10 @@ export namespace schema {
|
|
|
654
1109
|
.strictObject({
|
|
655
1110
|
chainId: Schema.ChainIdQuery,
|
|
656
1111
|
cursor: Schema.Cursor,
|
|
1112
|
+
include: Schema.includeQuery(
|
|
1113
|
+
z.enum(['earnings']),
|
|
1114
|
+
'Comma-separated position fields to include, such as `earnings`. Earnings are unavailable when selecting a private Zone.',
|
|
1115
|
+
),
|
|
657
1116
|
limit: Schema.Limit,
|
|
658
1117
|
'valuation.currency': Schema.Denomination.check(
|
|
659
1118
|
z.describe(
|
|
@@ -687,15 +1146,18 @@ export namespace schema {
|
|
|
687
1146
|
.check(z.describe('Page-level valuation rate provenance.'))
|
|
688
1147
|
|
|
689
1148
|
/** Paginated list of the account's earn vault positions. */
|
|
690
|
-
export const Response =
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
1149
|
+
export const Response = OpenApi.component(
|
|
1150
|
+
z
|
|
1151
|
+
.strictObject({
|
|
1152
|
+
data: z
|
|
1153
|
+
.array(addressPosition)
|
|
1154
|
+
.check(z.describe('Vaults where the account holds earn shares.')),
|
|
1155
|
+
meta: z.optional(Meta),
|
|
1156
|
+
nextCursor: Schema.NextCursor,
|
|
1157
|
+
})
|
|
1158
|
+
.check(z.describe('A page of the account’s earn vault positions.')),
|
|
1159
|
+
'EarnAddressPositionList',
|
|
1160
|
+
)
|
|
699
1161
|
}
|
|
700
1162
|
|
|
701
1163
|
/** Schemas for the getEarnVault operation. */
|
|
@@ -719,19 +1181,115 @@ export namespace schema {
|
|
|
719
1181
|
.check(z.describe('Query parameters selecting one earn vault.'))
|
|
720
1182
|
|
|
721
1183
|
/** One compatible Earn vault resolved directly from current chain state. */
|
|
722
|
-
export const Response =
|
|
723
|
-
|
|
724
|
-
|
|
1184
|
+
export const Response = OpenApi.component(
|
|
1185
|
+
Schema.describe(
|
|
1186
|
+
z.extend(vault, { meta: z.optional(meta) }),
|
|
1187
|
+
'A compatible earn vault resolved from chain state, with rate provenance for its valued fields.',
|
|
1188
|
+
),
|
|
1189
|
+
'EarnVaultDetail',
|
|
1190
|
+
)
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/** Schemas for the getEarnVaultSharePrices operation. */
|
|
1194
|
+
export namespace getEarnVaultSharePrices {
|
|
1195
|
+
const timestamp = z.iso.datetime({ offset: true })
|
|
1196
|
+
|
|
1197
|
+
/** Path parameters identifying one Earn vault. */
|
|
1198
|
+
export const Params = z
|
|
1199
|
+
.strictObject({
|
|
1200
|
+
vaultId: Schema.address('0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a').check(
|
|
1201
|
+
z.describe('Earn vault contract address.'),
|
|
1202
|
+
),
|
|
1203
|
+
})
|
|
1204
|
+
.check(z.describe('Path parameters identifying one Earn vault share-price series.'))
|
|
1205
|
+
|
|
1206
|
+
/** Query parameters selecting a daily historical share-price range. */
|
|
1207
|
+
export const Query = z
|
|
1208
|
+
.strictObject({
|
|
1209
|
+
chainId: Schema.ChainIdQuery,
|
|
1210
|
+
from: timestamp.check(
|
|
1211
|
+
z.describe('First daily share-price observation, as an ISO 8601 timestamp.'),
|
|
1212
|
+
z.meta({ examples: ['2026-07-01T00:00:00.000Z'] }),
|
|
1213
|
+
),
|
|
1214
|
+
interval: z
|
|
1215
|
+
._default(z.literal(EarnSharePrices.interval), EarnSharePrices.interval)
|
|
1216
|
+
.check(
|
|
1217
|
+
z.describe('Time between share-price observations.'),
|
|
1218
|
+
z.meta({ examples: [EarnSharePrices.interval] }),
|
|
1219
|
+
),
|
|
1220
|
+
to: timestamp.check(
|
|
1221
|
+
z.describe('Last possible daily share-price observation, as an ISO 8601 timestamp.'),
|
|
1222
|
+
z.meta({ examples: ['2026-07-31T00:00:00.000Z'] }),
|
|
1223
|
+
),
|
|
1224
|
+
})
|
|
1225
|
+
.check(
|
|
1226
|
+
z.refine((query) => Date.parse(query.from) <= Date.parse(query.to), {
|
|
1227
|
+
error: '`from` must be before or equal to `to`.',
|
|
1228
|
+
path: ['from'],
|
|
1229
|
+
}),
|
|
1230
|
+
z.refine(
|
|
1231
|
+
(query) =>
|
|
1232
|
+
Math.floor((Date.parse(query.to) - Date.parse(query.from)) / Ttl.days(1)) + 1 <=
|
|
1233
|
+
EarnSharePrices.maxPoints,
|
|
1234
|
+
{
|
|
1235
|
+
error: `Share-price series are limited to ${EarnSharePrices.maxPoints} daily observations.`,
|
|
1236
|
+
path: ['to'],
|
|
1237
|
+
},
|
|
1238
|
+
),
|
|
1239
|
+
z.describe('Query parameters selecting an Earn vault share-price series.'),
|
|
1240
|
+
)
|
|
1241
|
+
|
|
1242
|
+
const Point = z
|
|
1243
|
+
.strictObject({
|
|
1244
|
+
sharePrice: value.check(
|
|
1245
|
+
z.describe('Assets returned for one whole Earn share at the observation block.'),
|
|
1246
|
+
),
|
|
1247
|
+
timestamp: z.iso
|
|
1248
|
+
.datetime()
|
|
1249
|
+
.check(
|
|
1250
|
+
z.describe('Requested daily observation timestamp.'),
|
|
1251
|
+
z.meta({ examples: ['2026-07-01T00:00:00.000Z'] }),
|
|
1252
|
+
),
|
|
1253
|
+
})
|
|
1254
|
+
.check(z.describe('One historical Earn vault share price.'))
|
|
1255
|
+
|
|
1256
|
+
/** Daily share prices for one Earn vault. */
|
|
1257
|
+
export const Response = OpenApi.component(
|
|
1258
|
+
z
|
|
1259
|
+
.strictObject({
|
|
1260
|
+
data: z.array(Point).check(
|
|
1261
|
+
z.describe('Daily Earn vault share prices.'),
|
|
1262
|
+
z.meta({
|
|
1263
|
+
examples: [
|
|
1264
|
+
[
|
|
1265
|
+
{
|
|
1266
|
+
sharePrice: {
|
|
1267
|
+
amount: '1000000',
|
|
1268
|
+
currency: 'USD',
|
|
1269
|
+
decimals: 6,
|
|
1270
|
+
formatted: '1',
|
|
1271
|
+
},
|
|
1272
|
+
timestamp: '2026-07-01T00:00:00.000Z',
|
|
1273
|
+
},
|
|
1274
|
+
],
|
|
1275
|
+
],
|
|
1276
|
+
}),
|
|
1277
|
+
),
|
|
1278
|
+
})
|
|
1279
|
+
.check(z.describe('Daily historical share prices for one Earn vault.')),
|
|
1280
|
+
'EarnVaultSharePriceList',
|
|
725
1281
|
)
|
|
726
1282
|
}
|
|
727
1283
|
|
|
728
1284
|
/** Schemas for the getEarnVaultPosition operation. */
|
|
729
1285
|
export namespace getEarnVaultPosition {
|
|
1286
|
+
const asOf = z.iso.datetime({ offset: true })
|
|
1287
|
+
|
|
730
1288
|
/** Path parameters identifying the Earn vault and account. */
|
|
731
1289
|
export const Params = z
|
|
732
1290
|
.strictObject({
|
|
733
1291
|
address: Schema.Address.check(z.describe('Account whose earn position to read.')),
|
|
734
|
-
vaultId: Schema.address('
|
|
1292
|
+
vaultId: Schema.address('0x4f94590b636f5878bce585e82379de81e1ec174f').check(
|
|
735
1293
|
z.describe('Earn vault contract address.'),
|
|
736
1294
|
),
|
|
737
1295
|
})
|
|
@@ -739,13 +1297,116 @@ export namespace schema {
|
|
|
739
1297
|
|
|
740
1298
|
/** Query parameters selecting the chain containing the vault. */
|
|
741
1299
|
export const Query = z
|
|
742
|
-
.strictObject({
|
|
1300
|
+
.strictObject({
|
|
1301
|
+
asOf: z
|
|
1302
|
+
.optional(asOf)
|
|
1303
|
+
.check(
|
|
1304
|
+
z.describe(
|
|
1305
|
+
'ISO 8601 timestamp at which to read the position. Resolves the latest indexed block at or before this time.',
|
|
1306
|
+
),
|
|
1307
|
+
z.meta({ examples: ['2026-07-21T09:00:00.000Z'] }),
|
|
1308
|
+
),
|
|
1309
|
+
chainId: Schema.ChainIdQuery,
|
|
1310
|
+
include: Schema.includeQuery(
|
|
1311
|
+
z.enum(['apy', 'rewards', 'rewards.proof']),
|
|
1312
|
+
'Include wallet-specific APY or current reward state, optionally with the latest recovery proof.',
|
|
1313
|
+
),
|
|
1314
|
+
})
|
|
743
1315
|
.check(z.describe('Query parameters selecting an earn vault position.'))
|
|
744
1316
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
1317
|
+
const Block = z
|
|
1318
|
+
.strictObject({
|
|
1319
|
+
number: z
|
|
1320
|
+
.number()
|
|
1321
|
+
.check(
|
|
1322
|
+
z.int(),
|
|
1323
|
+
z.nonnegative(),
|
|
1324
|
+
z.describe('Indexed observation block.'),
|
|
1325
|
+
z.meta({ examples: [31039238] }),
|
|
1326
|
+
),
|
|
1327
|
+
timestamp: z.iso
|
|
1328
|
+
.datetime()
|
|
1329
|
+
.check(
|
|
1330
|
+
z.describe('Timestamp of the indexed observation block.'),
|
|
1331
|
+
z.meta({ examples: ['2026-07-21T09:00:00.000Z'] }),
|
|
1332
|
+
),
|
|
1333
|
+
})
|
|
1334
|
+
.check(z.describe('Indexed block used for a historical Earn position observation.'))
|
|
1335
|
+
|
|
1336
|
+
/** Current or historical asset and Earn-share state for one account in one vault. */
|
|
1337
|
+
const Rewards = z
|
|
1338
|
+
.strictObject({
|
|
1339
|
+
cumulativeEntitlement: Schema.DecimalString.check(
|
|
1340
|
+
z.describe('Cumulative EarnShare entitlement.'),
|
|
1341
|
+
),
|
|
1342
|
+
cumulativePaid: Schema.DecimalString.check(z.describe('Cumulative EarnShare paid.')),
|
|
1343
|
+
deferral: z
|
|
1344
|
+
.optional(z.string())
|
|
1345
|
+
.check(
|
|
1346
|
+
z.describe('Current payout delivery exception.'),
|
|
1347
|
+
z.meta({ examples: ['transfer_unavailable'] }),
|
|
1348
|
+
),
|
|
1349
|
+
pending: Schema.DecimalString.check(z.describe('EarnShare still owed.')),
|
|
1350
|
+
proof: z
|
|
1351
|
+
.optional(
|
|
1352
|
+
z.strictObject({
|
|
1353
|
+
cumulativeAmount: Schema.DecimalString,
|
|
1354
|
+
distributorAddress: Schema.Address,
|
|
1355
|
+
proof: z.array(Schema.Hash),
|
|
1356
|
+
rootVersion: Schema.DecimalString,
|
|
1357
|
+
statementHash: Schema.Hash,
|
|
1358
|
+
}),
|
|
1359
|
+
)
|
|
1360
|
+
.check(z.describe('Permissionless recovery proof against the confirmed root.')),
|
|
1361
|
+
})
|
|
1362
|
+
.check(z.describe('Current Earn reward state.'))
|
|
1363
|
+
|
|
1364
|
+
export const Response = OpenApi.component(
|
|
1365
|
+
Schema.describe(
|
|
1366
|
+
z.extend(position, {
|
|
1367
|
+
apy: z.optional(z.nullable(positionApy)).check(
|
|
1368
|
+
z.describe(
|
|
1369
|
+
'Wallet-specific effective APY when requested, or null when unavailable. Qualification comes from the latest delivered reward snapshot and may lag recent deposits or transfers.',
|
|
1370
|
+
),
|
|
1371
|
+
z.meta({
|
|
1372
|
+
examples: [
|
|
1373
|
+
{
|
|
1374
|
+
breakdown: [
|
|
1375
|
+
{
|
|
1376
|
+
assetAmount: {
|
|
1377
|
+
baseUnits: '25000000000',
|
|
1378
|
+
decimals: 6,
|
|
1379
|
+
formatted: '25000',
|
|
1380
|
+
},
|
|
1381
|
+
net: '0.07',
|
|
1382
|
+
type: 'boost',
|
|
1383
|
+
},
|
|
1384
|
+
],
|
|
1385
|
+
net: '0.07',
|
|
1386
|
+
},
|
|
1387
|
+
],
|
|
1388
|
+
}),
|
|
1389
|
+
),
|
|
1390
|
+
asOf: z
|
|
1391
|
+
.optional(asOf)
|
|
1392
|
+
.check(
|
|
1393
|
+
z.describe('Requested historical observation time, when supplied.'),
|
|
1394
|
+
z.meta({ examples: ['2026-07-21T09:00:00.000Z'] }),
|
|
1395
|
+
),
|
|
1396
|
+
block: z
|
|
1397
|
+
.optional(Block)
|
|
1398
|
+
.check(
|
|
1399
|
+
z.describe(
|
|
1400
|
+
'Indexed block used for a historical Earn position observation, when requested.',
|
|
1401
|
+
),
|
|
1402
|
+
),
|
|
1403
|
+
rewards: z
|
|
1404
|
+
.optional(Rewards)
|
|
1405
|
+
.check(z.describe('Current reward state when requested through `include`.')),
|
|
1406
|
+
}),
|
|
1407
|
+
'Current or historical asset and earn-share balances, allowances, and asset value for an account in one earn vault.',
|
|
1408
|
+
),
|
|
1409
|
+
'EarnVaultPosition',
|
|
749
1410
|
)
|
|
750
1411
|
}
|
|
751
1412
|
|
|
@@ -770,9 +1431,12 @@ export namespace schema {
|
|
|
770
1431
|
.check(z.describe('Query parameters selecting an earn vault account.'))
|
|
771
1432
|
|
|
772
1433
|
/** Earnings for one account and period in one Earn vault. */
|
|
773
|
-
export const Response =
|
|
774
|
-
|
|
775
|
-
|
|
1434
|
+
export const Response = OpenApi.component(
|
|
1435
|
+
Schema.describe(
|
|
1436
|
+
earnings,
|
|
1437
|
+
'Indexed asset value and cost-basis-aware earnings for an account in one earn vault.',
|
|
1438
|
+
),
|
|
1439
|
+
'EarnVaultEarnings',
|
|
776
1440
|
)
|
|
777
1441
|
}
|
|
778
1442
|
}
|
|
@@ -781,6 +1445,113 @@ export namespace schema {
|
|
|
781
1445
|
export function earn(options: earn.Options = {}) {
|
|
782
1446
|
const oracle = options.fx?.oracle ?? FxOracle.ecb()
|
|
783
1447
|
return new Hono<App.Environment>()
|
|
1448
|
+
.post(
|
|
1449
|
+
'/v1/earn/rewards/eligibility',
|
|
1450
|
+
Auth.policy({ apiKey: { scopes: [Scope.wildcard] } }),
|
|
1451
|
+
OpenApi.validate('json', schema.registerRewardEligibility.Body, {
|
|
1452
|
+
code: 'body_invalid',
|
|
1453
|
+
message: 'Invalid reward eligibility registration',
|
|
1454
|
+
}),
|
|
1455
|
+
OpenApi.describeRoute({
|
|
1456
|
+
description: 'Registers a wallet and Earn vault association for reward eligibility.',
|
|
1457
|
+
hide: true,
|
|
1458
|
+
operationId: 'registerRewardEligibility',
|
|
1459
|
+
responses: OpenApi.responses({
|
|
1460
|
+
errors: {
|
|
1461
|
+
400: { codes: ['body_invalid', 'chain_id_unsupported'] },
|
|
1462
|
+
},
|
|
1463
|
+
success: {
|
|
1464
|
+
description: 'The persisted reward eligibility association.',
|
|
1465
|
+
schema: schema.registerRewardEligibility.Response,
|
|
1466
|
+
},
|
|
1467
|
+
}),
|
|
1468
|
+
summary: 'Register reward eligibility',
|
|
1469
|
+
tags: ['Earn'],
|
|
1470
|
+
}),
|
|
1471
|
+
async (c) => {
|
|
1472
|
+
if (Auth.narrowAccess) return Auth.accessError(c)
|
|
1473
|
+
if (OpenApi.narrowValidation)
|
|
1474
|
+
return OpenApi.validationError(c, {
|
|
1475
|
+
code: 'body_invalid',
|
|
1476
|
+
message: 'Invalid reward eligibility registration',
|
|
1477
|
+
})
|
|
1478
|
+
|
|
1479
|
+
const body = c.req.valid('json')
|
|
1480
|
+
if (!c.get('supportedChainIds').has(body.chainId))
|
|
1481
|
+
return Response.unsupportedChainId(c, body.chainId, c.get('supportedChainIds'))
|
|
1482
|
+
c.set('chainId', body.chainId)
|
|
1483
|
+
c.header('Cache-Control', Cache.policies.noStore)
|
|
1484
|
+
const result = await RewardEligibilityAssociations.upsert(Db.get(c.get('db')), {
|
|
1485
|
+
...body,
|
|
1486
|
+
})
|
|
1487
|
+
return c.json(
|
|
1488
|
+
Response.validated(schema.registerRewardEligibility.Response, {
|
|
1489
|
+
association: toRewardEligibilityAssociation(result.record),
|
|
1490
|
+
created: result.created,
|
|
1491
|
+
}),
|
|
1492
|
+
200,
|
|
1493
|
+
)
|
|
1494
|
+
},
|
|
1495
|
+
)
|
|
1496
|
+
.get(
|
|
1497
|
+
'/v1/earn/rewards/eligibility',
|
|
1498
|
+
Auth.policy({ apiKey: { scopes: ['rewards:read'] } }),
|
|
1499
|
+
OpenApi.validate('query', schema.getRewardEligibility.Query, {
|
|
1500
|
+
code: 'query_invalid',
|
|
1501
|
+
message: 'Invalid reward eligibility selector',
|
|
1502
|
+
}),
|
|
1503
|
+
OpenApi.describeRoute({
|
|
1504
|
+
description:
|
|
1505
|
+
'Lists reward eligibility associations for one Earn vault at a fixed high-water checkpoint.',
|
|
1506
|
+
hide: true,
|
|
1507
|
+
operationId: 'getRewardEligibility',
|
|
1508
|
+
responses: OpenApi.responses({
|
|
1509
|
+
success: {
|
|
1510
|
+
description: 'A checkpointed page of reward eligibility associations.',
|
|
1511
|
+
schema: schema.getRewardEligibility.Response,
|
|
1512
|
+
},
|
|
1513
|
+
}),
|
|
1514
|
+
summary: 'List reward eligibility',
|
|
1515
|
+
tags: ['Earn'],
|
|
1516
|
+
}),
|
|
1517
|
+
async (c) => {
|
|
1518
|
+
if (Auth.narrowAccess) return Auth.accessError(c)
|
|
1519
|
+
if (OpenApi.narrowValidation)
|
|
1520
|
+
return OpenApi.validationError(c, {
|
|
1521
|
+
code: 'query_invalid',
|
|
1522
|
+
message: 'Invalid reward eligibility selector',
|
|
1523
|
+
})
|
|
1524
|
+
|
|
1525
|
+
const query = c.req.valid('query')
|
|
1526
|
+
const zone = c.get('zones').get(query.chainId)
|
|
1527
|
+
const sourceChainId = zone ? zone.sourceId : query.chainId
|
|
1528
|
+
const principal = Auth.getPrincipal(c)
|
|
1529
|
+
if (
|
|
1530
|
+
principal?.type === 'api_key' &&
|
|
1531
|
+
principal.environment === 'sandbox' &&
|
|
1532
|
+
(sourceChainId === undefined || Viem.isMainnet(sourceChainId))
|
|
1533
|
+
)
|
|
1534
|
+
return Response.error(c, {
|
|
1535
|
+
code: 'api_key_forbidden',
|
|
1536
|
+
message: 'Sandbox API keys only support testnet.',
|
|
1537
|
+
status: 403,
|
|
1538
|
+
})
|
|
1539
|
+
|
|
1540
|
+
c.header('Cache-Control', Cache.policies.noStore)
|
|
1541
|
+
const page = await RewardEligibilityAssociations.list(Db.get(c.get('db')), {
|
|
1542
|
+
...query,
|
|
1543
|
+
})
|
|
1544
|
+
return c.json(
|
|
1545
|
+
Response.validated(schema.getRewardEligibility.Response, {
|
|
1546
|
+
chainId: query.chainId,
|
|
1547
|
+
data: page.data.map((association) => association.walletAddress),
|
|
1548
|
+
nextCursor: page.nextCursor,
|
|
1549
|
+
vaultAddress: query.vaultAddress,
|
|
1550
|
+
}),
|
|
1551
|
+
200,
|
|
1552
|
+
)
|
|
1553
|
+
},
|
|
1554
|
+
)
|
|
784
1555
|
.get(
|
|
785
1556
|
'/v1/earn/vaults',
|
|
786
1557
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
@@ -793,7 +1564,12 @@ export function earn(options: earn.Options = {}) {
|
|
|
793
1564
|
'Lists compatible earn vaults discovered from deployment events and resolved from current chain state.',
|
|
794
1565
|
operationId: 'getEarnVaults',
|
|
795
1566
|
responses: OpenApi.responses({
|
|
796
|
-
errors: {
|
|
1567
|
+
errors: {
|
|
1568
|
+
400: {
|
|
1569
|
+
codes: ['chain_id_invalid', 'chain_id_unsupported', 'query_invalid'],
|
|
1570
|
+
},
|
|
1571
|
+
502: 'Could not read earn deployment or vault data.',
|
|
1572
|
+
},
|
|
797
1573
|
success: {
|
|
798
1574
|
description: 'A page of compatible deployed earn vaults.',
|
|
799
1575
|
schema: schema.getEarnVaults.Response,
|
|
@@ -807,10 +1583,22 @@ export function earn(options: earn.Options = {}) {
|
|
|
807
1583
|
Cache.response<App.Environment>({
|
|
808
1584
|
cacheControl: Cache.policies.state,
|
|
809
1585
|
key: (c) => vaultCacheKey(c, schema.getEarnVaults.Query),
|
|
810
|
-
name: 'tempo-api:earn-vaults:
|
|
1586
|
+
name: 'tempo-api:earn-vaults:v5',
|
|
811
1587
|
}),
|
|
812
1588
|
async (c) => {
|
|
813
1589
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
1590
|
+
if (OpenApi.narrowValidation)
|
|
1591
|
+
return Response.error(c, {
|
|
1592
|
+
code: 'chain_id_invalid',
|
|
1593
|
+
message: 'Invalid chain id',
|
|
1594
|
+
status: 400,
|
|
1595
|
+
})
|
|
1596
|
+
if (OpenApi.narrowValidation)
|
|
1597
|
+
return Response.error(c, {
|
|
1598
|
+
code: 'chain_id_unsupported',
|
|
1599
|
+
message: 'Unsupported chain id',
|
|
1600
|
+
status: 400,
|
|
1601
|
+
})
|
|
814
1602
|
if (OpenApi.narrowValidation)
|
|
815
1603
|
return OpenApi.validationError(c, {
|
|
816
1604
|
code: 'query_invalid',
|
|
@@ -839,7 +1627,12 @@ export function earn(options: earn.Options = {}) {
|
|
|
839
1627
|
'Lists registry-curated earn vaults after resolving their current onchain configuration.',
|
|
840
1628
|
operationId: 'getVerifiedEarnVaults',
|
|
841
1629
|
responses: OpenApi.responses({
|
|
842
|
-
errors: {
|
|
1630
|
+
errors: {
|
|
1631
|
+
400: {
|
|
1632
|
+
codes: ['chain_id_invalid', 'chain_id_unsupported', 'query_invalid'],
|
|
1633
|
+
},
|
|
1634
|
+
502: 'Could not read curated earn registry or vault data.',
|
|
1635
|
+
},
|
|
843
1636
|
success: {
|
|
844
1637
|
description: 'A page of registry-curated earn vaults.',
|
|
845
1638
|
schema: schema.getVerifiedEarnVaults.Response,
|
|
@@ -851,67 +1644,166 @@ export function earn(options: earn.Options = {}) {
|
|
|
851
1644
|
Cache.response<App.Environment>({
|
|
852
1645
|
cacheControl: Cache.policies.state,
|
|
853
1646
|
key: (c) => vaultCacheKey(c, schema.getVerifiedEarnVaults.Query),
|
|
854
|
-
name: 'tempo-api:earn-vaults:
|
|
1647
|
+
name: 'tempo-api:earn-vaults:v4',
|
|
1648
|
+
}),
|
|
1649
|
+
async (c) => {
|
|
1650
|
+
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
1651
|
+
if (OpenApi.narrowValidation)
|
|
1652
|
+
return Response.error(c, {
|
|
1653
|
+
code: 'chain_id_invalid',
|
|
1654
|
+
message: 'Invalid chain id',
|
|
1655
|
+
status: 400,
|
|
1656
|
+
})
|
|
1657
|
+
if (OpenApi.narrowValidation)
|
|
1658
|
+
return Response.error(c, {
|
|
1659
|
+
code: 'chain_id_unsupported',
|
|
1660
|
+
message: 'Unsupported chain id',
|
|
1661
|
+
status: 400,
|
|
1662
|
+
})
|
|
1663
|
+
if (OpenApi.narrowValidation)
|
|
1664
|
+
return OpenApi.validationError(c, {
|
|
1665
|
+
code: 'query_invalid',
|
|
1666
|
+
message: 'Invalid query parameters',
|
|
1667
|
+
})
|
|
1668
|
+
|
|
1669
|
+
const query = c.req.valid('query')
|
|
1670
|
+
try {
|
|
1671
|
+
const chainId = query.chainId ?? c.get('chainId')
|
|
1672
|
+
const data = await listVerifiedVaults(c, {
|
|
1673
|
+
...query,
|
|
1674
|
+
chainId,
|
|
1675
|
+
oracle,
|
|
1676
|
+
})
|
|
1677
|
+
return c.json(Response.validated(schema.getVerifiedEarnVaults.Response, data), 200)
|
|
1678
|
+
} catch (cause) {
|
|
1679
|
+
return Response.upstream(c, cause)
|
|
1680
|
+
}
|
|
1681
|
+
},
|
|
1682
|
+
)
|
|
1683
|
+
.get(
|
|
1684
|
+
'/v1/earn/addresses/:address/positions',
|
|
1685
|
+
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
1686
|
+
OpenApi.validate('param', schema.getEarnAddressPositions.Params, {
|
|
1687
|
+
code: 'positions_invalid',
|
|
1688
|
+
message: 'Invalid address positions',
|
|
1689
|
+
}),
|
|
1690
|
+
OpenApi.validate('query', schema.getEarnAddressPositions.Query, {
|
|
1691
|
+
code: 'query_invalid',
|
|
1692
|
+
message: 'Invalid query parameters',
|
|
1693
|
+
}),
|
|
1694
|
+
OpenApi.describeRoute({
|
|
1695
|
+
description:
|
|
1696
|
+
'Lists every earn vault where an account currently holds shares on the selected Tempo chain or private Zone. Lifetime cash flows are available on Tempo chains.',
|
|
1697
|
+
operationId: 'getEarnAddressPositions',
|
|
1698
|
+
responses: OpenApi.responses({
|
|
1699
|
+
errors: {
|
|
1700
|
+
400: {
|
|
1701
|
+
codes: [
|
|
1702
|
+
'chain_id_invalid',
|
|
1703
|
+
'chain_id_unsupported',
|
|
1704
|
+
'positions_invalid',
|
|
1705
|
+
'query_invalid',
|
|
1706
|
+
],
|
|
1707
|
+
},
|
|
1708
|
+
502: 'Could not read earn deployment or position data.',
|
|
1709
|
+
},
|
|
1710
|
+
success: {
|
|
1711
|
+
description: 'A page of the account’s earn vault positions.',
|
|
1712
|
+
schema: schema.getEarnAddressPositions.Response,
|
|
1713
|
+
},
|
|
1714
|
+
}),
|
|
1715
|
+
summary: 'List account positions',
|
|
1716
|
+
tags: ['Earn'],
|
|
1717
|
+
}),
|
|
1718
|
+
// `noStore` matches the address balances listing: account holdings must
|
|
1719
|
+
// read fresh immediately after a deposit or redemption.
|
|
1720
|
+
Cache.response<App.Environment>({
|
|
1721
|
+
cacheControl: Cache.policies.noStore,
|
|
1722
|
+
key: (c) => Cache.urlKey(c, schema.getEarnAddressPositions.Query),
|
|
1723
|
+
name: 'tempo-api:earn-address-positions:v2',
|
|
855
1724
|
}),
|
|
856
1725
|
async (c) => {
|
|
857
1726
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
1727
|
+
if (OpenApi.narrowValidation)
|
|
1728
|
+
return Response.error(c, {
|
|
1729
|
+
code: 'chain_id_invalid',
|
|
1730
|
+
message: 'Invalid chain id',
|
|
1731
|
+
status: 400,
|
|
1732
|
+
})
|
|
1733
|
+
if (OpenApi.narrowValidation)
|
|
1734
|
+
return Response.error(c, {
|
|
1735
|
+
code: 'chain_id_unsupported',
|
|
1736
|
+
message: 'Unsupported chain id',
|
|
1737
|
+
status: 400,
|
|
1738
|
+
})
|
|
1739
|
+
if (OpenApi.narrowValidation)
|
|
1740
|
+
return OpenApi.validationError(c, {
|
|
1741
|
+
code: 'positions_invalid',
|
|
1742
|
+
message: 'Invalid request parameters',
|
|
1743
|
+
})
|
|
858
1744
|
if (OpenApi.narrowValidation)
|
|
859
1745
|
return OpenApi.validationError(c, {
|
|
860
1746
|
code: 'query_invalid',
|
|
861
1747
|
message: 'Invalid query parameters',
|
|
862
1748
|
})
|
|
863
1749
|
|
|
1750
|
+
const { address } = c.req.valid('param')
|
|
864
1751
|
const query = c.req.valid('query')
|
|
1752
|
+
const chainId = query.chainId ?? c.get('chainId')
|
|
865
1753
|
try {
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
return c.json(Response.validated(schema.getVerifiedEarnVaults.Response, data), 200)
|
|
1754
|
+
const data = await listPositions(c, { ...query, address, chainId, oracle })
|
|
1755
|
+
return c.json(Response.validated(schema.getEarnAddressPositions.Response, data), 200)
|
|
869
1756
|
} catch (cause) {
|
|
1757
|
+
if (cause instanceof Valuation.UnsupportedDenominationError)
|
|
1758
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
1759
|
+
if (cause instanceof ZoneEarningsUnsupportedError)
|
|
1760
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
870
1761
|
return Response.upstream(c, cause)
|
|
871
1762
|
}
|
|
872
1763
|
},
|
|
873
1764
|
)
|
|
874
1765
|
.get(
|
|
875
|
-
'/v1/earn/
|
|
1766
|
+
'/v1/earn/vaults/:vaultId/share-prices',
|
|
876
1767
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
877
|
-
OpenApi.validate('param', schema.
|
|
878
|
-
code: '
|
|
879
|
-
message: 'Invalid
|
|
1768
|
+
OpenApi.validate('param', schema.getEarnVaultSharePrices.Params, {
|
|
1769
|
+
code: 'vault_id_invalid',
|
|
1770
|
+
message: 'Invalid vault id',
|
|
880
1771
|
}),
|
|
881
|
-
OpenApi.validate('query', schema.
|
|
1772
|
+
OpenApi.validate('query', schema.getEarnVaultSharePrices.Query, {
|
|
882
1773
|
code: 'query_invalid',
|
|
883
1774
|
message: 'Invalid query parameters',
|
|
884
1775
|
}),
|
|
885
1776
|
OpenApi.describeRoute({
|
|
886
|
-
description:
|
|
887
|
-
|
|
888
|
-
operationId: 'getEarnAddressPositions',
|
|
1777
|
+
description: 'Lists daily historical share prices for one earn vault.',
|
|
1778
|
+
operationId: 'getEarnVaultSharePrices',
|
|
889
1779
|
responses: OpenApi.responses({
|
|
890
1780
|
errors: {
|
|
891
1781
|
400: {
|
|
892
1782
|
codes: [
|
|
893
1783
|
'chain_id_invalid',
|
|
894
1784
|
'chain_id_unsupported',
|
|
895
|
-
'positions_invalid',
|
|
896
1785
|
'query_invalid',
|
|
1786
|
+
'vault_id_invalid',
|
|
897
1787
|
],
|
|
898
1788
|
},
|
|
899
|
-
|
|
1789
|
+
404: {
|
|
1790
|
+
codes: ['earn_vault_not_found'],
|
|
1791
|
+
description: 'No compatible earn vault was found at the supplied vault address.',
|
|
1792
|
+
},
|
|
1793
|
+
502: 'Could not read historical earn vault share prices.',
|
|
900
1794
|
},
|
|
901
1795
|
success: {
|
|
902
|
-
description: '
|
|
903
|
-
schema: schema.
|
|
1796
|
+
description: 'Daily historical share prices for one earn vault.',
|
|
1797
|
+
schema: schema.getEarnVaultSharePrices.Response,
|
|
904
1798
|
},
|
|
905
1799
|
}),
|
|
906
|
-
summary: 'List
|
|
1800
|
+
summary: 'List share prices',
|
|
907
1801
|
tags: ['Earn'],
|
|
908
1802
|
}),
|
|
909
|
-
// `noStore` matches the address balances listing: account holdings must
|
|
910
|
-
// read fresh immediately after a deposit or redemption.
|
|
911
1803
|
Cache.response<App.Environment>({
|
|
912
|
-
cacheControl: Cache.policies.
|
|
913
|
-
key: (c) => Cache.urlKey(c, schema.
|
|
914
|
-
name: 'tempo-api:earn-
|
|
1804
|
+
cacheControl: Cache.policies.state,
|
|
1805
|
+
key: (c) => Cache.urlKey(c, schema.getEarnVaultSharePrices.Query),
|
|
1806
|
+
name: 'tempo-api:earn-vault-share-prices:v1',
|
|
915
1807
|
}),
|
|
916
1808
|
async (c) => {
|
|
917
1809
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -929,8 +1821,8 @@ export function earn(options: earn.Options = {}) {
|
|
|
929
1821
|
})
|
|
930
1822
|
if (OpenApi.narrowValidation)
|
|
931
1823
|
return OpenApi.validationError(c, {
|
|
932
|
-
code: '
|
|
933
|
-
message: 'Invalid
|
|
1824
|
+
code: 'vault_id_invalid',
|
|
1825
|
+
message: 'Invalid vault id',
|
|
934
1826
|
})
|
|
935
1827
|
if (OpenApi.narrowValidation)
|
|
936
1828
|
return OpenApi.validationError(c, {
|
|
@@ -938,15 +1830,35 @@ export function earn(options: earn.Options = {}) {
|
|
|
938
1830
|
message: 'Invalid query parameters',
|
|
939
1831
|
})
|
|
940
1832
|
|
|
941
|
-
const {
|
|
1833
|
+
const { vaultId } = c.req.valid('param')
|
|
942
1834
|
const query = c.req.valid('query')
|
|
943
1835
|
const chainId = query.chainId ?? c.get('chainId')
|
|
944
1836
|
try {
|
|
945
|
-
const
|
|
946
|
-
|
|
1837
|
+
const discovery = await resolveSharePriceVaultDiscovery(c, {
|
|
1838
|
+
chainId,
|
|
1839
|
+
vaultAddress: vaultId,
|
|
1840
|
+
})
|
|
1841
|
+
if (!discovery)
|
|
1842
|
+
return Response.error(c, {
|
|
1843
|
+
code: 'earn_vault_not_found',
|
|
1844
|
+
message: 'Earn vault not found',
|
|
1845
|
+
status: 404,
|
|
1846
|
+
})
|
|
1847
|
+
const data = await getVaultSharePrices(c, {
|
|
1848
|
+
...query,
|
|
1849
|
+
chainId,
|
|
1850
|
+
discovery,
|
|
1851
|
+
vault: vaultId,
|
|
1852
|
+
})
|
|
1853
|
+
return c.json(Response.validated(schema.getEarnVaultSharePrices.Response, { data }), 200)
|
|
947
1854
|
} catch (cause) {
|
|
948
|
-
if (
|
|
1855
|
+
if (
|
|
1856
|
+
cause instanceof EarnSharePrices.IndexedBlockNotFoundError ||
|
|
1857
|
+
cause instanceof EarnSharePrices.IndexedCoverageError
|
|
1858
|
+
)
|
|
949
1859
|
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
1860
|
+
const failure = sharePriceProviderFailure({ cause, chainId })
|
|
1861
|
+
if (failure) c.set('providerFailure', failure)
|
|
950
1862
|
return Response.upstream(c, cause)
|
|
951
1863
|
}
|
|
952
1864
|
},
|
|
@@ -964,7 +1876,7 @@ export function earn(options: earn.Options = {}) {
|
|
|
964
1876
|
}),
|
|
965
1877
|
OpenApi.describeRoute({
|
|
966
1878
|
description:
|
|
967
|
-
'Gets an account’s
|
|
1879
|
+
'Gets an account’s direct or Zone-routed balances and asset value for one earn vault, optionally at an ISO 8601 timestamp.',
|
|
968
1880
|
operationId: 'getEarnVaultPosition',
|
|
969
1881
|
responses: OpenApi.responses({
|
|
970
1882
|
errors: {
|
|
@@ -983,17 +1895,18 @@ export function earn(options: earn.Options = {}) {
|
|
|
983
1895
|
502: 'Could not read the earn vault position.',
|
|
984
1896
|
},
|
|
985
1897
|
success: {
|
|
986
|
-
description: 'Current earn position for one account in one vault.',
|
|
1898
|
+
description: 'Current or historical earn position for one account in one vault.',
|
|
987
1899
|
schema: schema.getEarnVaultPosition.Response,
|
|
988
1900
|
},
|
|
989
1901
|
}),
|
|
990
1902
|
summary: 'Get account position',
|
|
991
1903
|
tags: ['Earn'],
|
|
992
1904
|
}),
|
|
1905
|
+
// Account holdings must read fresh immediately after a deposit or redemption.
|
|
993
1906
|
Cache.response<App.Environment>({
|
|
994
|
-
cacheControl: Cache.policies.
|
|
1907
|
+
cacheControl: Cache.policies.noStore,
|
|
995
1908
|
key: (c) => Cache.urlKey(c, schema.getEarnVaultPosition.Query),
|
|
996
|
-
name: 'tempo-api:earn-vault-positions:
|
|
1909
|
+
name: 'tempo-api:earn-vault-positions:v3',
|
|
997
1910
|
}),
|
|
998
1911
|
async (c) => {
|
|
999
1912
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -1023,25 +1936,123 @@ export function earn(options: earn.Options = {}) {
|
|
|
1023
1936
|
const { address, vaultId } = c.req.valid('param')
|
|
1024
1937
|
const query = c.req.valid('query')
|
|
1025
1938
|
const chainId = query.chainId ?? c.get('chainId')
|
|
1939
|
+
if (query.asOf && query.include.length > 0)
|
|
1940
|
+
return Response.error(c, {
|
|
1941
|
+
code: 'query_invalid',
|
|
1942
|
+
message: 'Historical position enrichments are not available.',
|
|
1943
|
+
status: 400,
|
|
1944
|
+
})
|
|
1945
|
+
if (c.get('zones').has(chainId)) Cache.setPolicy(c, Cache.policies.noStore)
|
|
1026
1946
|
try {
|
|
1027
|
-
const position = await c
|
|
1028
|
-
|
|
1029
|
-
|
|
1947
|
+
const position = await getVaultPosition(c, {
|
|
1948
|
+
account: address,
|
|
1949
|
+
asOf: query.asOf,
|
|
1950
|
+
chainId,
|
|
1951
|
+
vault: vaultId,
|
|
1952
|
+
})
|
|
1953
|
+
const apy = query.include.includes('apy')
|
|
1954
|
+
? await resolvePositionApy(c, {
|
|
1955
|
+
chainId,
|
|
1956
|
+
recipient: address,
|
|
1957
|
+
shareBalance: position.shareBalance,
|
|
1958
|
+
value: position.value,
|
|
1959
|
+
vault: vaultId,
|
|
1960
|
+
})
|
|
1961
|
+
: undefined
|
|
1962
|
+
const rewards = query.include.some((value) => value.startsWith('rewards'))
|
|
1963
|
+
? await RewardRead.recipient({
|
|
1964
|
+
chainId,
|
|
1965
|
+
db: c.get('db'),
|
|
1966
|
+
getClient: c.get('getClient'),
|
|
1967
|
+
recipient: address,
|
|
1968
|
+
vaultAddress: vaultId,
|
|
1969
|
+
})
|
|
1970
|
+
: undefined
|
|
1030
1971
|
return c.json(
|
|
1031
1972
|
Response.validated(schema.getEarnVaultPosition.Response, {
|
|
1032
1973
|
account: address,
|
|
1974
|
+
...(query.include.includes('apy') ? { apy } : {}),
|
|
1033
1975
|
assetAllowance: position.assetAllowance.toString(),
|
|
1034
1976
|
assetBalance: position.assetBalance.toString(),
|
|
1035
1977
|
assetToken: position.assetToken,
|
|
1978
|
+
chainId,
|
|
1979
|
+
asOf: query.asOf,
|
|
1980
|
+
block: position.block,
|
|
1036
1981
|
id: address,
|
|
1982
|
+
...(rewards
|
|
1983
|
+
? {
|
|
1984
|
+
rewards: query.include.includes('rewards.proof')
|
|
1985
|
+
? rewards
|
|
1986
|
+
: { ...rewards, proof: undefined },
|
|
1987
|
+
}
|
|
1988
|
+
: {}),
|
|
1037
1989
|
shareAllowance: position.shareAllowance.toString(),
|
|
1038
1990
|
shareBalance: position.shareBalance.toString(),
|
|
1039
1991
|
shareToken: position.shareToken,
|
|
1040
1992
|
value: position.value.toString(),
|
|
1993
|
+
valueToken: position.valueToken,
|
|
1041
1994
|
}),
|
|
1042
1995
|
200,
|
|
1043
1996
|
)
|
|
1044
1997
|
} catch (cause) {
|
|
1998
|
+
if (cause instanceof IndexedBlockNotFoundError || cause instanceof IndexedCoverageError)
|
|
1999
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
2000
|
+
if (cause instanceof ZoneHistoricalAlignmentError)
|
|
2001
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
|
|
2002
|
+
if (cause instanceof EarnVaults.NotFoundError)
|
|
2003
|
+
return Response.error(c, {
|
|
2004
|
+
code: 'earn_vault_not_found',
|
|
2005
|
+
message: 'Earn vault not found',
|
|
2006
|
+
status: 404,
|
|
2007
|
+
})
|
|
2008
|
+
const zone = c.get('zones').get(chainId)
|
|
2009
|
+
if (query.asOf && !zone) {
|
|
2010
|
+
try {
|
|
2011
|
+
const block = await getIndexedBlockAtOrBefore(c.get('getTidx')(chainId), query.asOf)
|
|
2012
|
+
const client = c.get('getClient')(chainId)
|
|
2013
|
+
// These immutable bindings establish historical vault identity
|
|
2014
|
+
// without repeating fallible token or redemption subreads.
|
|
2015
|
+
const [asset, shareToken] = await Promise.all([
|
|
2016
|
+
client.readContract({
|
|
2017
|
+
abi: Abis.earnVault,
|
|
2018
|
+
address: vaultId,
|
|
2019
|
+
blockNumber: BigInt(block.number),
|
|
2020
|
+
functionName: 'asset',
|
|
2021
|
+
}),
|
|
2022
|
+
client.readContract({
|
|
2023
|
+
abi: Abis.earnVault,
|
|
2024
|
+
address: vaultId,
|
|
2025
|
+
blockNumber: BigInt(block.number),
|
|
2026
|
+
functionName: 'earnShare',
|
|
2027
|
+
}),
|
|
2028
|
+
])
|
|
2029
|
+
if (asset === zeroAddress || shareToken === zeroAddress)
|
|
2030
|
+
return Response.error(c, {
|
|
2031
|
+
code: 'earn_vault_not_found',
|
|
2032
|
+
message: 'Earn vault not found',
|
|
2033
|
+
status: 404,
|
|
2034
|
+
})
|
|
2035
|
+
} catch (identityCause) {
|
|
2036
|
+
if (
|
|
2037
|
+
identityCause instanceof IndexedBlockNotFoundError ||
|
|
2038
|
+
identityCause instanceof IndexedCoverageError
|
|
2039
|
+
)
|
|
2040
|
+
return Response.error(c, {
|
|
2041
|
+
code: 'query_invalid',
|
|
2042
|
+
message: identityCause.message,
|
|
2043
|
+
status: 400,
|
|
2044
|
+
})
|
|
2045
|
+
if (isIncompatible(identityCause))
|
|
2046
|
+
return Response.error(c, {
|
|
2047
|
+
code: 'earn_vault_not_found',
|
|
2048
|
+
message: 'Earn vault not found',
|
|
2049
|
+
status: 404,
|
|
2050
|
+
})
|
|
2051
|
+
return Response.upstream(c, identityCause)
|
|
2052
|
+
}
|
|
2053
|
+
return Response.upstream(c, cause)
|
|
2054
|
+
}
|
|
2055
|
+
if (zone) return Response.upstream(c, cause)
|
|
1045
2056
|
try {
|
|
1046
2057
|
await resolveVaultDiscovery(c, { chainId, include: [], vaultAddress: vaultId })
|
|
1047
2058
|
} catch (vaultCause) {
|
|
@@ -1098,7 +2109,7 @@ export function earn(options: earn.Options = {}) {
|
|
|
1098
2109
|
Cache.response<App.Environment>({
|
|
1099
2110
|
cacheControl: Cache.policies.state,
|
|
1100
2111
|
key: (c) => Cache.urlKey(c, schema.getEarnVaultEarnings.Query),
|
|
1101
|
-
name: 'tempo-api:earn-vault-earnings:
|
|
2112
|
+
name: 'tempo-api:earn-vault-earnings:v4',
|
|
1102
2113
|
}),
|
|
1103
2114
|
async (c) => {
|
|
1104
2115
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -1168,6 +2179,14 @@ export function earn(options: earn.Options = {}) {
|
|
|
1168
2179
|
operationId: 'getEarnVault',
|
|
1169
2180
|
responses: OpenApi.responses({
|
|
1170
2181
|
errors: {
|
|
2182
|
+
400: {
|
|
2183
|
+
codes: [
|
|
2184
|
+
'chain_id_invalid',
|
|
2185
|
+
'chain_id_unsupported',
|
|
2186
|
+
'query_invalid',
|
|
2187
|
+
'vault_id_invalid',
|
|
2188
|
+
],
|
|
2189
|
+
},
|
|
1171
2190
|
404: {
|
|
1172
2191
|
codes: ['earn_vault_not_found'],
|
|
1173
2192
|
description: 'No compatible earn vault was found at this address.',
|
|
@@ -1185,10 +2204,22 @@ export function earn(options: earn.Options = {}) {
|
|
|
1185
2204
|
Cache.response<App.Environment>({
|
|
1186
2205
|
cacheControl: Cache.policies.state,
|
|
1187
2206
|
key: (c) => vaultCacheKey(c, schema.getEarnVault.Query),
|
|
1188
|
-
name: 'tempo-api:earn-vaults:
|
|
2207
|
+
name: 'tempo-api:earn-vaults:v4',
|
|
1189
2208
|
}),
|
|
1190
2209
|
async (c) => {
|
|
1191
2210
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
2211
|
+
if (OpenApi.narrowValidation)
|
|
2212
|
+
return Response.error(c, {
|
|
2213
|
+
code: 'chain_id_invalid',
|
|
2214
|
+
message: 'Invalid chain id',
|
|
2215
|
+
status: 400,
|
|
2216
|
+
})
|
|
2217
|
+
if (OpenApi.narrowValidation)
|
|
2218
|
+
return Response.error(c, {
|
|
2219
|
+
code: 'chain_id_unsupported',
|
|
2220
|
+
message: 'Unsupported chain id',
|
|
2221
|
+
status: 400,
|
|
2222
|
+
})
|
|
1192
2223
|
if (OpenApi.narrowValidation)
|
|
1193
2224
|
return OpenApi.validationError(c, {
|
|
1194
2225
|
code: 'vault_id_invalid',
|
|
@@ -1240,7 +2271,10 @@ export async function getVaultEarnings(
|
|
|
1240
2271
|
) {
|
|
1241
2272
|
const client = c.get('getClient')(options.chainId)
|
|
1242
2273
|
const tidx = c.get('getTidx')(options.chainId)
|
|
1243
|
-
const block = await
|
|
2274
|
+
const [block, rewardTransfer] = await Promise.all([
|
|
2275
|
+
getLatestIndexedBlock(tidx),
|
|
2276
|
+
getRewardTransferPredicate(c, options),
|
|
2277
|
+
])
|
|
1244
2278
|
const blockNumber = block.number
|
|
1245
2279
|
if (options.period === '30d')
|
|
1246
2280
|
return getWindowVaultEarnings(c, {
|
|
@@ -1248,6 +2282,7 @@ export async function getVaultEarnings(
|
|
|
1248
2282
|
blockNumber,
|
|
1249
2283
|
chainId: options.chainId,
|
|
1250
2284
|
period: options.period,
|
|
2285
|
+
rewardTransfer,
|
|
1251
2286
|
timestamp: block.timestamp,
|
|
1252
2287
|
vault: options.vault,
|
|
1253
2288
|
})
|
|
@@ -1268,6 +2303,7 @@ export async function getVaultEarnings(
|
|
|
1268
2303
|
const activeCostBasis = await getActiveCostBasis(tidx, {
|
|
1269
2304
|
account: options.account,
|
|
1270
2305
|
blockNumber,
|
|
2306
|
+
rewardTransfer,
|
|
1271
2307
|
shareBalance: current.shareBalance,
|
|
1272
2308
|
shareToken: current.shareToken,
|
|
1273
2309
|
vault: options.vault,
|
|
@@ -1291,6 +2327,7 @@ export async function getVaultEarnings(
|
|
|
1291
2327
|
const externalShareTransfer = await hasExternalShareTransfer(tidx, {
|
|
1292
2328
|
account: options.account,
|
|
1293
2329
|
blockNumber,
|
|
2330
|
+
rewardTransfer,
|
|
1294
2331
|
shareToken: current.shareToken,
|
|
1295
2332
|
startBlockNumber: beforeFirstBlockNumber,
|
|
1296
2333
|
vault: options.vault,
|
|
@@ -1304,10 +2341,20 @@ export async function getVaultEarnings(
|
|
|
1304
2341
|
}
|
|
1305
2342
|
if (history.incompleteCostBasis || externalShareTransfer)
|
|
1306
2343
|
return { ...base, status: 'incomplete_cost_basis' as const }
|
|
1307
|
-
|
|
1308
|
-
const
|
|
1309
|
-
|
|
1310
|
-
|
|
2344
|
+
const totalWithdrawn = history.redeemed + history.withdrewExact + history.finalized
|
|
2345
|
+
const cashFlows = {
|
|
2346
|
+
totalDeposited: history.deposited.toString(),
|
|
2347
|
+
totalWithdrawn: totalWithdrawn.toString(),
|
|
2348
|
+
}
|
|
2349
|
+
if (history.pendingRedemption)
|
|
2350
|
+
return { ...base, ...cashFlows, status: 'pending_redemption' as const }
|
|
2351
|
+
const lifetimeEarnings = current.value + totalWithdrawn - history.deposited
|
|
2352
|
+
return {
|
|
2353
|
+
...base,
|
|
2354
|
+
...cashFlows,
|
|
2355
|
+
lifetimeEarnings: lifetimeEarnings.toString(),
|
|
2356
|
+
status: 'complete' as const,
|
|
2357
|
+
}
|
|
1311
2358
|
}
|
|
1312
2359
|
|
|
1313
2360
|
/** Reads cash-flow-adjusted earnings over a trailing indexed window. */
|
|
@@ -1329,6 +2376,7 @@ async function getWindowVaultEarnings(
|
|
|
1329
2376
|
hasExternalShareTransfer(tidx, {
|
|
1330
2377
|
account: options.account,
|
|
1331
2378
|
blockNumber: options.blockNumber,
|
|
2379
|
+
rewardTransfer: options.rewardTransfer,
|
|
1332
2380
|
shareToken: current.shareToken,
|
|
1333
2381
|
startBlockNumber,
|
|
1334
2382
|
vault: options.vault,
|
|
@@ -1393,6 +2441,8 @@ declare namespace getWindowVaultEarnings {
|
|
|
1393
2441
|
chainId: z.output<typeof Schema.ChainId>
|
|
1394
2442
|
/** Trailing earnings period. */
|
|
1395
2443
|
period: '30d'
|
|
2444
|
+
/** SQL predicate recognizing paid rewards in the share-transfer history. */
|
|
2445
|
+
rewardTransfer: string
|
|
1396
2446
|
/** Latest indexed block timestamp. */
|
|
1397
2447
|
timestamp: string
|
|
1398
2448
|
/** Earn vault contract address. */
|
|
@@ -1453,6 +2503,62 @@ async function getLatestIndexedBlock(tidx: Tidx.Client) {
|
|
|
1453
2503
|
return { number, timestamp }
|
|
1454
2504
|
}
|
|
1455
2505
|
|
|
2506
|
+
/** Resolves the latest indexed block at or before a historical position timestamp. */
|
|
2507
|
+
async function getIndexedBlockAtOrBefore(tidx: Tidx.Client, asOf: string) {
|
|
2508
|
+
const timestamp = new Date(asOf).toISOString().replace('T', ' ').replace(/Z$/, '')
|
|
2509
|
+
const result = await tidx.fetch({
|
|
2510
|
+
engine: 'clickhouse',
|
|
2511
|
+
// SAFETY: Zod restricts `asOf` to ISO 8601, so the formatted timestamp cannot alter SQL.
|
|
2512
|
+
query: `
|
|
2513
|
+
SELECT 'boundary' AS kind, num, timestamp
|
|
2514
|
+
FROM (
|
|
2515
|
+
SELECT num, timestamp
|
|
2516
|
+
FROM blocks
|
|
2517
|
+
WHERE timestamp <= '${timestamp}'
|
|
2518
|
+
ORDER BY timestamp DESC, num DESC
|
|
2519
|
+
LIMIT 1
|
|
2520
|
+
)
|
|
2521
|
+
UNION ALL
|
|
2522
|
+
SELECT 'head' AS kind, num, timestamp
|
|
2523
|
+
FROM (
|
|
2524
|
+
SELECT num, timestamp
|
|
2525
|
+
FROM blocks
|
|
2526
|
+
ORDER BY num DESC
|
|
2527
|
+
LIMIT 1
|
|
2528
|
+
)
|
|
2529
|
+
` as string,
|
|
2530
|
+
})
|
|
2531
|
+
return parseIndexedBlockAtOrBefore({ asOf, rows: result.rows })
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
/** Decodes the indexed head and historical position boundary from TIDX rows. */
|
|
2535
|
+
export function parseIndexedBlockAtOrBefore(options: parseIndexedBlockAtOrBefore.Options) {
|
|
2536
|
+
const head = options.rows.find((row) => row['kind'] === 'head')
|
|
2537
|
+
if (!head) throw new Error('TIDX returned no indexed head for a historical Earn position.')
|
|
2538
|
+
const headNumber = Value.toNumber(head['num'])
|
|
2539
|
+
const headAt = Value.toIsoDateTime(head['timestamp'])
|
|
2540
|
+
if (headNumber === undefined || headAt === undefined)
|
|
2541
|
+
throw new Error('TIDX returned a malformed indexed head for a historical Earn position.')
|
|
2542
|
+
const boundary = options.rows.find((row) => row['kind'] === 'boundary')
|
|
2543
|
+
if (!boundary) throw new IndexedBlockNotFoundError(options.asOf)
|
|
2544
|
+
const number = Value.toNumber(boundary['num'])
|
|
2545
|
+
const indexedAt = Value.toIsoDateTime(boundary['timestamp'])
|
|
2546
|
+
if (number === undefined || indexedAt === undefined)
|
|
2547
|
+
throw new Error('TIDX returned a malformed historical Earn position boundary.')
|
|
2548
|
+
if (Date.parse(headAt) < Date.parse(options.asOf)) throw new IndexedCoverageError(options.asOf)
|
|
2549
|
+
return { number, timestamp: indexedAt }
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
export declare namespace parseIndexedBlockAtOrBefore {
|
|
2553
|
+
/** Inputs returned by the historical boundary query. */
|
|
2554
|
+
type Options = {
|
|
2555
|
+
/** Requested historical observation timestamp. */
|
|
2556
|
+
asOf: string
|
|
2557
|
+
/** Indexed head and optional boundary rows. */
|
|
2558
|
+
rows: readonly Record<string, unknown>[]
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
|
|
1456
2562
|
/** Resolves the last indexed block at or before a trailing-day boundary. */
|
|
1457
2563
|
async function getWindowStartBlockNumber(
|
|
1458
2564
|
tidx: Tidx.Client,
|
|
@@ -1596,6 +2702,7 @@ async function getVaultEarningsHistory(
|
|
|
1596
2702
|
return {
|
|
1597
2703
|
deposited: BigInt(deposited),
|
|
1598
2704
|
finalized: BigInt(finalized),
|
|
2705
|
+
incompleteCashFlows: venueDeposits > 0,
|
|
1599
2706
|
incompleteCostBasis: transferredCancellations > 0 || venueDeposits > 0,
|
|
1600
2707
|
pendingRedemption: pendingRedemptions > 0,
|
|
1601
2708
|
redeemed: BigInt(redeemed),
|
|
@@ -1717,6 +2824,39 @@ declare namespace getWindowShareState {
|
|
|
1717
2824
|
}
|
|
1718
2825
|
}
|
|
1719
2826
|
|
|
2827
|
+
/** Builds a share-transfer predicate for the vault's verified reward distributors. */
|
|
2828
|
+
async function getRewardTransferPredicate(
|
|
2829
|
+
c: Context<App.Environment>,
|
|
2830
|
+
options: Pick<getVaultEarnings.Options, 'chainId' | 'vault'>,
|
|
2831
|
+
) {
|
|
2832
|
+
const db = Db.get(c.get('db'))
|
|
2833
|
+
const campaign = await RewardCampaigns.get(db, {
|
|
2834
|
+
chainId: options.chainId,
|
|
2835
|
+
vaultAddress: options.vault,
|
|
2836
|
+
})
|
|
2837
|
+
if (!campaign) return '0'
|
|
2838
|
+
const distributors = await RewardCampaignDistributors.list(db, {
|
|
2839
|
+
chainId: options.chainId,
|
|
2840
|
+
vaultAddress: options.vault,
|
|
2841
|
+
})
|
|
2842
|
+
if (distributors.length === 0) return '0'
|
|
2843
|
+
const addresses = distributors
|
|
2844
|
+
.map(({ distributorAddress }) => Schema.Address.parse(distributorAddress))
|
|
2845
|
+
.map((address) => `'${address}'`)
|
|
2846
|
+
.join(', ')
|
|
2847
|
+
const shareToken = Schema.Address.parse(campaign.earnShareAddress)
|
|
2848
|
+
|
|
2849
|
+
// Batch rewards have no per-recipient event; exclude treasury returns instead. Qualify the filter so TIDX does not apply it to other event CTEs.
|
|
2850
|
+
return `
|
|
2851
|
+
token = '${shareToken}'
|
|
2852
|
+
AND "from" IN (${addresses})
|
|
2853
|
+
AND tx_hash NOT IN (
|
|
2854
|
+
SELECT returned.tx_hash FROM UnspentReturned AS returned
|
|
2855
|
+
WHERE returned.address IN (${addresses})
|
|
2856
|
+
)
|
|
2857
|
+
`
|
|
2858
|
+
}
|
|
2859
|
+
|
|
1720
2860
|
/** Returns whether an account sent or received Earn shares outside known vault flows. */
|
|
1721
2861
|
async function hasExternalShareTransfer(
|
|
1722
2862
|
tidx: Tidx.Client,
|
|
@@ -1731,6 +2871,7 @@ async function hasExternalShareTransfer(
|
|
|
1731
2871
|
SELECT count()
|
|
1732
2872
|
FROM token_transfers
|
|
1733
2873
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2874
|
+
AND toUInt256(amount) > 0
|
|
1734
2875
|
AND block_num > ${options.startBlockNumber}
|
|
1735
2876
|
AND block_num <= ${options.blockNumber}
|
|
1736
2877
|
AND (
|
|
@@ -1739,6 +2880,7 @@ async function hasExternalShareTransfer(
|
|
|
1739
2880
|
"to" = '${options.account}'
|
|
1740
2881
|
AND "from" != '${zeroAddress}'
|
|
1741
2882
|
AND "from" != '${options.vault}'
|
|
2883
|
+
AND NOT (${options.rewardTransfer})
|
|
1742
2884
|
)
|
|
1743
2885
|
)
|
|
1744
2886
|
) + (
|
|
@@ -1747,6 +2889,7 @@ async function hasExternalShareTransfer(
|
|
|
1747
2889
|
SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
|
|
1748
2890
|
FROM token_transfers
|
|
1749
2891
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2892
|
+
AND toUInt256(amount) > 0
|
|
1750
2893
|
AND "from" = '${options.account}'
|
|
1751
2894
|
AND "to" = '${options.vault}'
|
|
1752
2895
|
AND block_num > ${options.startBlockNumber}
|
|
@@ -1787,6 +2930,7 @@ async function hasExternalShareTransfer(
|
|
|
1787
2930
|
SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
|
|
1788
2931
|
FROM token_transfers
|
|
1789
2932
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2933
|
+
AND toUInt256(amount) > 0
|
|
1790
2934
|
AND "from" = '${options.vault}'
|
|
1791
2935
|
AND "to" = '${options.account}'
|
|
1792
2936
|
AND block_num > ${options.startBlockNumber}
|
|
@@ -1810,6 +2954,7 @@ async function hasExternalShareTransfer(
|
|
|
1810
2954
|
redeemCancelledSignature,
|
|
1811
2955
|
redeemedSignature,
|
|
1812
2956
|
redeemRequestedSignature,
|
|
2957
|
+
unspentReturnedSignature,
|
|
1813
2958
|
withdrewExactSignature,
|
|
1814
2959
|
],
|
|
1815
2960
|
})
|
|
@@ -1822,6 +2967,7 @@ declare namespace hasExternalShareTransfer {
|
|
|
1822
2967
|
type Options = {
|
|
1823
2968
|
account: z.output<typeof Schema.Address>
|
|
1824
2969
|
blockNumber: number
|
|
2970
|
+
rewardTransfer: string
|
|
1825
2971
|
shareToken: z.output<typeof Schema.Address>
|
|
1826
2972
|
startBlockNumber: number
|
|
1827
2973
|
vault: z.output<typeof Schema.Address>
|
|
@@ -1847,6 +2993,7 @@ export function calculateActiveCostBasis(options: calculateActiveCostBasis.Optio
|
|
|
1847
2993
|
}
|
|
1848
2994
|
|
|
1849
2995
|
for (const action of options.actions) {
|
|
2996
|
+
if (action.shares === 0n) continue
|
|
1850
2997
|
if (action.kind === 'deposit') {
|
|
1851
2998
|
if (costBasis !== undefined) costBasis += action.assets
|
|
1852
2999
|
shares += action.shares
|
|
@@ -2009,7 +3156,7 @@ async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis
|
|
|
2009
3156
|
AND block_num <= ${options.blockNumber}
|
|
2010
3157
|
UNION ALL
|
|
2011
3158
|
SELECT
|
|
2012
|
-
'unknown' AS kind,
|
|
3159
|
+
if(${options.rewardTransfer}, 'deposit', 'unknown') AS kind,
|
|
2013
3160
|
block_num,
|
|
2014
3161
|
log_idx,
|
|
2015
3162
|
'' AS request_id,
|
|
@@ -2017,6 +3164,7 @@ async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis
|
|
|
2017
3164
|
'0' AS assets
|
|
2018
3165
|
FROM token_transfers
|
|
2019
3166
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
3167
|
+
AND toUInt256(amount) > 0
|
|
2020
3168
|
AND "to" = '${options.account}'
|
|
2021
3169
|
AND "from" != '${zeroAddress}'
|
|
2022
3170
|
AND "from" != '${options.vault}'
|
|
@@ -2031,6 +3179,7 @@ async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis
|
|
|
2031
3179
|
'0' AS assets
|
|
2032
3180
|
FROM token_transfers
|
|
2033
3181
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
3182
|
+
AND toUInt256(amount) > 0
|
|
2034
3183
|
AND "from" = '${options.account}'
|
|
2035
3184
|
AND "to" != '${options.vault}'
|
|
2036
3185
|
AND block_num <= ${options.blockNumber}
|
|
@@ -2042,6 +3191,7 @@ async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis
|
|
|
2042
3191
|
redeemCancelledSignature,
|
|
2043
3192
|
redeemRequestedSignature,
|
|
2044
3193
|
redeemedSignature,
|
|
3194
|
+
unspentReturnedSignature,
|
|
2045
3195
|
venueSharesDepositedSignature,
|
|
2046
3196
|
withdrewExactSignature,
|
|
2047
3197
|
],
|
|
@@ -2091,6 +3241,7 @@ declare namespace getActiveCostBasis {
|
|
|
2091
3241
|
type Options = {
|
|
2092
3242
|
account: z.output<typeof Schema.Address>
|
|
2093
3243
|
blockNumber: number
|
|
3244
|
+
rewardTransfer: string
|
|
2094
3245
|
shareBalance: bigint
|
|
2095
3246
|
shareToken: z.output<typeof Schema.Address>
|
|
2096
3247
|
vault: z.output<typeof Schema.Address>
|
|
@@ -2194,7 +3345,7 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
|
|
|
2194
3345
|
apyByVault.has(vaultAddress.toLowerCase()) ? [] : [vaultAddress],
|
|
2195
3346
|
)
|
|
2196
3347
|
: []
|
|
2197
|
-
const [missingApy, rates, tokens] = await Promise.all([
|
|
3348
|
+
const [missingApy, rates, rewards, tokens] = await Promise.all([
|
|
2198
3349
|
missingApyVaults.length > 0
|
|
2199
3350
|
? resolvePageApy(c, {
|
|
2200
3351
|
chainId: options.chainId,
|
|
@@ -2204,12 +3355,27 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
|
|
|
2204
3355
|
})
|
|
2205
3356
|
: undefined,
|
|
2206
3357
|
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
3358
|
+
resolvePageRewards(c, {
|
|
3359
|
+
chainId: options.chainId,
|
|
3360
|
+
include,
|
|
3361
|
+
vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
|
|
3362
|
+
}),
|
|
2207
3363
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
2208
3364
|
])
|
|
2209
3365
|
for (const [vault, apy] of missingApy ?? []) apyByVault.set(vault, apy)
|
|
2210
3366
|
const apy = include.includes('apy') ? apyByVault : undefined
|
|
2211
3367
|
const data = await Promise.all(
|
|
2212
|
-
page.map((match) =>
|
|
3368
|
+
page.map((match) =>
|
|
3369
|
+
resolveVault(c, {
|
|
3370
|
+
...match,
|
|
3371
|
+
apy,
|
|
3372
|
+
include,
|
|
3373
|
+
rates,
|
|
3374
|
+
rewards: rewards?.get(match.discovery.vaultAddress),
|
|
3375
|
+
snapshot,
|
|
3376
|
+
tokens,
|
|
3377
|
+
}),
|
|
3378
|
+
),
|
|
2213
3379
|
)
|
|
2214
3380
|
const last = matches[options.limit - 1]
|
|
2215
3381
|
const nextPosition =
|
|
@@ -2291,60 +3457,429 @@ export async function listVerifiedVaults(
|
|
|
2291
3457
|
}
|
|
2292
3458
|
}
|
|
2293
3459
|
|
|
2294
|
-
const page = matches.slice(0, options.limit)
|
|
2295
|
-
const discoveries = page.map(({ discovery }) => discovery)
|
|
2296
|
-
const [apy, rates, tokens] = await Promise.all([
|
|
2297
|
-
resolvePageApy(c, {
|
|
2298
|
-
chainId: options.chainId,
|
|
2299
|
-
include,
|
|
2300
|
-
vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
|
|
2301
|
-
window: options['apy.window'],
|
|
2302
|
-
}),
|
|
2303
|
-
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
)
|
|
3460
|
+
const page = matches.slice(0, options.limit)
|
|
3461
|
+
const discoveries = page.map(({ discovery }) => discovery)
|
|
3462
|
+
const [apy, rates, rewards, tokens] = await Promise.all([
|
|
3463
|
+
resolvePageApy(c, {
|
|
3464
|
+
chainId: options.chainId,
|
|
3465
|
+
include,
|
|
3466
|
+
vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
|
|
3467
|
+
window: options['apy.window'],
|
|
3468
|
+
}),
|
|
3469
|
+
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
3470
|
+
resolvePageRewards(c, {
|
|
3471
|
+
chainId: options.chainId,
|
|
3472
|
+
include,
|
|
3473
|
+
vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
|
|
3474
|
+
}),
|
|
3475
|
+
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
3476
|
+
])
|
|
3477
|
+
const data = await Promise.all(
|
|
3478
|
+
page.map(async (match) =>
|
|
3479
|
+
Response.validated(
|
|
3480
|
+
schema.VerifiedVault,
|
|
3481
|
+
await resolveVault(c, {
|
|
3482
|
+
...match,
|
|
3483
|
+
apy,
|
|
3484
|
+
include,
|
|
3485
|
+
rates,
|
|
3486
|
+
rewards: rewards?.get(match.discovery.vaultAddress),
|
|
3487
|
+
snapshot,
|
|
3488
|
+
tokens,
|
|
3489
|
+
}),
|
|
3490
|
+
),
|
|
3491
|
+
),
|
|
3492
|
+
)
|
|
3493
|
+
const last = matches[options.limit - 1]
|
|
3494
|
+
return {
|
|
3495
|
+
data,
|
|
3496
|
+
...(rates ? { meta: { valuation: Valuation.pricing(rates, options.oracle) } } : {}),
|
|
3497
|
+
nextCursor:
|
|
3498
|
+
matches.length > options.limit && last ? Cursor.encode([last.record.vaultAddress]) : null,
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
|
|
3502
|
+
export declare namespace listVerifiedVaults {
|
|
3503
|
+
/** One verified vault and its current onchain state. */
|
|
3504
|
+
type Match = {
|
|
3505
|
+
discovery: EarnVaults.Discovery
|
|
3506
|
+
record: RegistryRecord
|
|
3507
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
/** Options for listing verified Earn vaults. */
|
|
3511
|
+
type Options = z.output<typeof schema.getVerifiedEarnVaults.Query> & {
|
|
3512
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
3513
|
+
/** FX rate oracle backing TVL valuation. */
|
|
3514
|
+
oracle: FxOracle.Oracle
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3518
|
+
/** Reads daily historical share prices for one Earn vault. */
|
|
3519
|
+
export async function getVaultSharePrices(
|
|
3520
|
+
c: Context<App.Environment>,
|
|
3521
|
+
options: getVaultSharePrices.Options,
|
|
3522
|
+
) {
|
|
3523
|
+
const prices = await Timing.time(c, 'earn_share_prices', () =>
|
|
3524
|
+
EarnSharePrices.resolve({
|
|
3525
|
+
chainId: options.chainId,
|
|
3526
|
+
from: options.from,
|
|
3527
|
+
// This client is request-local so viem's stateful HTTP batch cannot cross Worker invocations.
|
|
3528
|
+
getClient: (chainId = options.chainId) =>
|
|
3529
|
+
Viem.createBatchClient({
|
|
3530
|
+
chainId,
|
|
3531
|
+
principal: Auth.getPrincipal(c),
|
|
3532
|
+
rpc: c.get('rpc'),
|
|
3533
|
+
zone: c.get('zones').get(chainId),
|
|
3534
|
+
}),
|
|
3535
|
+
getTidx: c.get('getTidx'),
|
|
3536
|
+
shareDecimals: options.discovery.shareToken.decimals,
|
|
3537
|
+
to: options.to,
|
|
3538
|
+
vault: options.vault,
|
|
3539
|
+
}),
|
|
3540
|
+
)
|
|
3541
|
+
return prices.map((price) => ({
|
|
3542
|
+
sharePrice: {
|
|
3543
|
+
amount: price.amount.toString(),
|
|
3544
|
+
currency: options.discovery.assetToken.currency,
|
|
3545
|
+
decimals: options.discovery.assetToken.decimals,
|
|
3546
|
+
formatted: core_Value.format(price.amount, options.discovery.assetToken.decimals),
|
|
3547
|
+
},
|
|
3548
|
+
timestamp: price.timestamp,
|
|
3549
|
+
}))
|
|
3550
|
+
}
|
|
3551
|
+
|
|
3552
|
+
/** Classifies an Earn share-price dependency failure for request metrics. */
|
|
3553
|
+
export function sharePriceProviderFailure(
|
|
3554
|
+
options: sharePriceProviderFailure.Options,
|
|
3555
|
+
): Log.ProviderFailure | undefined {
|
|
3556
|
+
if (options.cause instanceof EarnSharePrices.MalformedResponseError)
|
|
3557
|
+
return {
|
|
3558
|
+
chainId: options.chainId,
|
|
3559
|
+
failure: 'payload',
|
|
3560
|
+
id: 'tidx',
|
|
3561
|
+
operation: 'query',
|
|
3562
|
+
}
|
|
3563
|
+
if (options.cause instanceof EarnSharePrices.TidxRequestError)
|
|
3564
|
+
return { ...Tidx.providerFailure(options.cause.cause), chainId: options.chainId }
|
|
3565
|
+
const failure = Viem.requestFailure(options.cause)
|
|
3566
|
+
if (failure) return { ...failure, chainId: options.chainId, id: 'rpc', operation: 'eth_call' }
|
|
3567
|
+
return undefined
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3570
|
+
export declare namespace sharePriceProviderFailure {
|
|
3571
|
+
/** Failure and chain used to derive bounded dependency metadata. */
|
|
3572
|
+
type Options = {
|
|
3573
|
+
/** Chain whose dependency call failed. */
|
|
3574
|
+
chainId: number
|
|
3575
|
+
/** Error returned by TIDX parsing or the RPC client. */
|
|
3576
|
+
cause: unknown
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
|
|
3580
|
+
export declare namespace getVaultSharePrices {
|
|
3581
|
+
/** Inputs selecting one Earn vault share-price series. */
|
|
3582
|
+
type Options = z.output<typeof schema.getEarnVaultSharePrices.Query> & {
|
|
3583
|
+
/** Chain containing the Earn vault. */
|
|
3584
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
3585
|
+
/** Current compatible vault and token metadata. */
|
|
3586
|
+
discovery: EarnVaults.Discovery
|
|
3587
|
+
/** Earn vault contract address. */
|
|
3588
|
+
vault: z.output<typeof Schema.Address>
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
|
|
3592
|
+
async function resolveSharePriceVaultDiscovery(
|
|
3593
|
+
c: Context<App.Environment>,
|
|
3594
|
+
options: resolveSharePriceVaultDiscovery.Options,
|
|
3595
|
+
): Promise<EarnVaults.Discovery | undefined> {
|
|
3596
|
+
const result = await Store.memoize(
|
|
3597
|
+
async () => {
|
|
3598
|
+
try {
|
|
3599
|
+
return {
|
|
3600
|
+
discovery: await readVaultDiscovery(c, { ...options, include: [] }),
|
|
3601
|
+
status: 'found',
|
|
3602
|
+
} as const
|
|
3603
|
+
} catch (cause) {
|
|
3604
|
+
if (isIncompatible(cause)) return { status: 'not_found' } as const
|
|
3605
|
+
throw cause
|
|
3606
|
+
}
|
|
3607
|
+
},
|
|
3608
|
+
{
|
|
3609
|
+
key: `earn-share-price-vault:v1:${options.chainId}:${options.vaultAddress.toLowerCase()}`,
|
|
3610
|
+
store: c.get('store'),
|
|
3611
|
+
ttl: Ttl.seconds(5),
|
|
3612
|
+
},
|
|
3613
|
+
)
|
|
3614
|
+
return result.status === 'found' ? result.discovery : undefined
|
|
3615
|
+
}
|
|
3616
|
+
|
|
3617
|
+
declare namespace resolveSharePriceVaultDiscovery {
|
|
3618
|
+
type Options = {
|
|
3619
|
+
/** Chain containing the candidate Earn vault. */
|
|
3620
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
3621
|
+
/** Candidate Earn vault contract address. */
|
|
3622
|
+
vaultAddress: z.output<typeof Schema.Address>
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
/** Reads one direct or Zone-routed account position in a parent-chain Earn vault. */
|
|
3627
|
+
export async function getVaultPosition(
|
|
3628
|
+
c: Context<App.Environment>,
|
|
3629
|
+
options: getVaultPosition.Options,
|
|
3630
|
+
): Promise<getVaultPosition.ReturnType> {
|
|
3631
|
+
const zone = c.get('zones').get(options.chainId)
|
|
3632
|
+
if (!zone) {
|
|
3633
|
+
const block =
|
|
3634
|
+
options.asOf === undefined
|
|
3635
|
+
? undefined
|
|
3636
|
+
: await getIndexedBlockAtOrBefore(c.get('getTidx')(options.chainId), options.asOf)
|
|
3637
|
+
const position = await c
|
|
3638
|
+
.get('getClient')(options.chainId)
|
|
3639
|
+
.earn.getPosition({
|
|
3640
|
+
account: options.account,
|
|
3641
|
+
...(block ? { blockNumber: BigInt(block.number) } : {}),
|
|
3642
|
+
vault: options.vault,
|
|
3643
|
+
})
|
|
3644
|
+
return { ...position, block, valueToken: position.assetToken }
|
|
3645
|
+
}
|
|
3646
|
+
|
|
3647
|
+
const route = await resolveZonePositionRoute(c, {
|
|
3648
|
+
chainId: options.chainId,
|
|
3649
|
+
vault: options.vault,
|
|
3650
|
+
})
|
|
3651
|
+
const block =
|
|
3652
|
+
options.asOf === undefined
|
|
3653
|
+
? undefined
|
|
3654
|
+
: await getIndexedBlockAtOrBefore(c.get('getTidx')(options.chainId), options.asOf)
|
|
3655
|
+
const zoneClient = c.get('getClient')(options.chainId)
|
|
3656
|
+
const blockNumber = block ? BigInt(block.number) : await zoneClient.getBlockNumber()
|
|
3657
|
+
const [assetBalance, shareBalance, importedParentBlockNumber] = await Promise.all([
|
|
3658
|
+
readZoneBalance(zoneClient, {
|
|
3659
|
+
account: options.account,
|
|
3660
|
+
blockNumber,
|
|
3661
|
+
token: route.privateAsset,
|
|
3662
|
+
}),
|
|
3663
|
+
readZoneBalance(zoneClient, {
|
|
3664
|
+
account: options.account,
|
|
3665
|
+
blockNumber,
|
|
3666
|
+
token: route.shareToken,
|
|
3667
|
+
}),
|
|
3668
|
+
readZoneSourceBlock(c, {
|
|
3669
|
+
blockNumber,
|
|
3670
|
+
historical: block !== undefined,
|
|
3671
|
+
portal: route.portal,
|
|
3672
|
+
sourceChainId: route.sourceChainId,
|
|
3673
|
+
zoneClient,
|
|
3674
|
+
}),
|
|
3675
|
+
])
|
|
3676
|
+
const sourceBlock = Value.toNumber(importedParentBlockNumber)
|
|
3677
|
+
if (sourceBlock === undefined || sourceBlock < route.deploymentBlock)
|
|
3678
|
+
throw new EarnVaults.NotFoundError()
|
|
3679
|
+
const value = await c
|
|
3680
|
+
.get('getClient')(route.sourceChainId)
|
|
3681
|
+
.earn.getRedeemQuote({
|
|
3682
|
+
blockNumber: BigInt(sourceBlock),
|
|
3683
|
+
shareAmount: shareBalance,
|
|
3684
|
+
vault: options.vault,
|
|
3685
|
+
})
|
|
3686
|
+
return {
|
|
3687
|
+
assetAllowance: 0n,
|
|
3688
|
+
assetBalance,
|
|
3689
|
+
assetToken: route.privateAsset,
|
|
3690
|
+
block,
|
|
3691
|
+
shareAllowance: 0n,
|
|
3692
|
+
shareBalance,
|
|
3693
|
+
shareToken: route.shareToken,
|
|
3694
|
+
value,
|
|
3695
|
+
valueToken: route.vaultAsset,
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3699
|
+
export declare namespace getVaultPosition {
|
|
3700
|
+
/** Inputs selecting one direct or Zone-routed account position. */
|
|
3701
|
+
type Options = {
|
|
3702
|
+
account: z.output<typeof Schema.Address>
|
|
3703
|
+
asOf?: string | undefined
|
|
3704
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
3705
|
+
vault: z.output<typeof Schema.Address>
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
/** Normalized position state across a direct chain or private Zone. */
|
|
3709
|
+
type ReturnType = Actions.earn.getPosition.ReturnValue & {
|
|
3710
|
+
block?: { number: number; timestamp: string } | undefined
|
|
3711
|
+
valueToken: z.output<typeof Schema.Address>
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
|
|
3715
|
+
/** Reads a private Zone token balance with the holder as the authorized RPC caller. */
|
|
3716
|
+
async function readZoneBalance(
|
|
3717
|
+
client: ReturnType<App.Environment['Variables']['getClient']>,
|
|
3718
|
+
options: readZoneBalance.Options,
|
|
3719
|
+
) {
|
|
3720
|
+
return client.readContract({
|
|
3721
|
+
abi: tokenPositionAbi,
|
|
3722
|
+
account: options.account,
|
|
3723
|
+
address: options.token,
|
|
3724
|
+
args: [options.account],
|
|
3725
|
+
...(options.blockNumber === undefined ? {} : { blockNumber: options.blockNumber }),
|
|
3726
|
+
functionName: 'balanceOf',
|
|
3727
|
+
})
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3730
|
+
declare namespace readZoneBalance {
|
|
3731
|
+
/** Private balance selector and optional historical Zone block. */
|
|
3732
|
+
type Options = {
|
|
3733
|
+
account: z.output<typeof Schema.Address>
|
|
3734
|
+
blockNumber?: bigint | undefined
|
|
3735
|
+
token: z.output<typeof Schema.Address>
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
/** Reads the parent Tempo checkpoint imported by one Zone observation. */
|
|
3740
|
+
async function readZoneSourceBlock(
|
|
3741
|
+
c: Context<App.Environment>,
|
|
3742
|
+
options: readZoneSourceBlock.Options,
|
|
3743
|
+
): Promise<bigint> {
|
|
3744
|
+
const verifiedPromise = c.get('getClient')(options.sourceChainId).readContract({
|
|
3745
|
+
abi: zonePortalAbi,
|
|
3746
|
+
address: options.portal,
|
|
3747
|
+
functionName: 'lastSyncedTempoBlockNumber',
|
|
3748
|
+
})
|
|
3749
|
+
// A historical Zone without TempoState rejects before awaiting the portal.
|
|
3750
|
+
void verifiedPromise.catch(() => undefined)
|
|
3751
|
+
const reported = await (async () => {
|
|
3752
|
+
try {
|
|
3753
|
+
return await options.zoneClient.readContract({
|
|
3754
|
+
abi: tempoStateAbi,
|
|
3755
|
+
address: tempoStateAddress,
|
|
3756
|
+
blockNumber: options.blockNumber,
|
|
3757
|
+
functionName: 'tempoBlockNumber',
|
|
3758
|
+
})
|
|
3759
|
+
} catch (cause) {
|
|
3760
|
+
if (
|
|
3761
|
+
!(cause instanceof ContractFunctionExecutionError) ||
|
|
3762
|
+
!(cause.cause instanceof ContractFunctionZeroDataError)
|
|
3763
|
+
)
|
|
3764
|
+
throw cause
|
|
3765
|
+
if (options.historical) throw new ZoneHistoricalAlignmentError()
|
|
3766
|
+
return undefined
|
|
3767
|
+
}
|
|
3768
|
+
})()
|
|
3769
|
+
const verified = await verifiedPromise
|
|
3770
|
+
return alignZoneSourceBlock({ reported, verified })
|
|
3771
|
+
}
|
|
3772
|
+
|
|
3773
|
+
declare namespace readZoneSourceBlock {
|
|
3774
|
+
/** Zone observation and parent Portal used to resolve one synchronization boundary. */
|
|
3775
|
+
type Options = {
|
|
3776
|
+
blockNumber: bigint
|
|
3777
|
+
historical: boolean
|
|
3778
|
+
portal: z.output<typeof Schema.Address>
|
|
3779
|
+
sourceChainId: number
|
|
3780
|
+
zoneClient: ReturnType<App.Environment['Variables']['getClient']>
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3784
|
+
/** Caps a Zone-reported parent checkpoint at the L1 portal's verified watermark. */
|
|
3785
|
+
export function alignZoneSourceBlock(options: alignZoneSourceBlock.Options): bigint {
|
|
3786
|
+
if (options.reported === undefined || options.verified < options.reported) return options.verified
|
|
3787
|
+
return options.reported
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
export declare namespace alignZoneSourceBlock {
|
|
3791
|
+
/** Zone-reported and L1-verified parent checkpoints. */
|
|
3792
|
+
type Options = {
|
|
3793
|
+
/** Parent checkpoint reported by the Zone, when available. */
|
|
3794
|
+
reported?: bigint | undefined
|
|
3795
|
+
/** Latest parent checkpoint verified by the L1 portal. */
|
|
3796
|
+
verified: bigint
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
/** Resolves the verified parent vault and token pair for one Zone route. */
|
|
3801
|
+
async function resolveZonePositionRoute(
|
|
3802
|
+
c: Context<App.Environment>,
|
|
3803
|
+
options: resolveZonePositionRoute.Options,
|
|
3804
|
+
): Promise<resolveZonePositionRoute.ReturnType> {
|
|
3805
|
+
const zone = c.get('zones').get(options.chainId)
|
|
3806
|
+
if (!zone?.sourceId) throw new EarnVaults.NotFoundError()
|
|
3807
|
+
const db = Db.get(c.get('dbCached'))
|
|
3808
|
+
const record = await core_EarnVaults.get(db, {
|
|
3809
|
+
chainId: zone.sourceId,
|
|
3810
|
+
vaultAddress: options.vault,
|
|
3811
|
+
})
|
|
3812
|
+
const configured = record?.zones.find((route) => route.chainId === options.chainId)
|
|
3813
|
+
if (!record || !configured) throw new EarnVaults.NotFoundError()
|
|
3814
|
+
const discovery = await resolveVaultDiscovery(c, {
|
|
3815
|
+
chainId: zone.sourceId,
|
|
3816
|
+
include: [],
|
|
3817
|
+
vaultAddress: options.vault,
|
|
3818
|
+
})
|
|
3819
|
+
const [route] = await EarnVaults.resolveZoneRoutes({
|
|
3820
|
+
discovery,
|
|
3821
|
+
getClient: c.get('getClient'),
|
|
3822
|
+
routes: [configured],
|
|
3823
|
+
zones: [...c.get('zones').values()],
|
|
3824
|
+
})
|
|
3825
|
+
const privateAsset = route?.inputTokens[0]
|
|
3826
|
+
const portalContract = zone.contracts?.['portal']
|
|
3827
|
+
const portal = Schema.Address.safeParse(
|
|
3828
|
+
portalContract && 'address' in portalContract
|
|
3829
|
+
? portalContract.address
|
|
3830
|
+
: portalContract?.[zone.sourceId]?.address,
|
|
2313
3831
|
)
|
|
2314
|
-
|
|
3832
|
+
if (!route || !privateAsset || !portal.success) throw new EarnVaults.NotFoundError()
|
|
2315
3833
|
return {
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
3834
|
+
deploymentBlock: route.deploymentBlock,
|
|
3835
|
+
portal: portal.data,
|
|
3836
|
+
privateAsset,
|
|
3837
|
+
shareToken: discovery.shareToken.address,
|
|
3838
|
+
sourceChainId: zone.sourceId,
|
|
3839
|
+
vaultAsset: discovery.assetToken.address,
|
|
2320
3840
|
}
|
|
2321
3841
|
}
|
|
2322
3842
|
|
|
2323
|
-
|
|
2324
|
-
/**
|
|
2325
|
-
type
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
3843
|
+
declare namespace resolveZonePositionRoute {
|
|
3844
|
+
/** Zone and parent vault selecting one curated route. */
|
|
3845
|
+
type Options = {
|
|
3846
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
3847
|
+
vault: z.output<typeof Schema.Address>
|
|
2329
3848
|
}
|
|
2330
3849
|
|
|
2331
|
-
/**
|
|
2332
|
-
type
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
3850
|
+
/** Verified addresses needed to read and value a Zone position. */
|
|
3851
|
+
type ReturnType = {
|
|
3852
|
+
deploymentBlock: number
|
|
3853
|
+
privateAsset: z.output<typeof Schema.Address>
|
|
3854
|
+
portal: z.output<typeof Schema.Address>
|
|
3855
|
+
shareToken: z.output<typeof Schema.Address>
|
|
3856
|
+
sourceChainId: number
|
|
3857
|
+
vaultAsset: z.output<typeof Schema.Address>
|
|
2336
3858
|
}
|
|
2337
3859
|
}
|
|
2338
3860
|
|
|
2339
3861
|
/** Lists every vault where an account holds earn shares, ordered by vault address. */
|
|
2340
3862
|
export async function listPositions(c: Context<App.Environment>, options: listPositions.Options) {
|
|
2341
3863
|
const denomination = options['valuation.currency']
|
|
3864
|
+
const zone = c.get('zones').get(options.chainId)
|
|
3865
|
+
if (zone && options.include.includes('earnings')) throw new ZoneEarningsUnsupportedError()
|
|
3866
|
+
const sourceChainId = zone ? zone.sourceId : options.chainId
|
|
3867
|
+
if (sourceChainId === undefined) throw new EarnVaults.NotFoundError()
|
|
2342
3868
|
const db = Db.get(c.get('dbCached'))
|
|
2343
|
-
const recordsPromise = core_EarnVaults
|
|
3869
|
+
const recordsPromise = core_EarnVaults
|
|
3870
|
+
.list(db, { chainId: sourceChainId })
|
|
3871
|
+
.then((records) =>
|
|
3872
|
+
zone
|
|
3873
|
+
? records.filter((record) =>
|
|
3874
|
+
record.zones.some((route) => route.chainId === options.chainId),
|
|
3875
|
+
)
|
|
3876
|
+
: records,
|
|
3877
|
+
)
|
|
2344
3878
|
// The verified page needs no index: the registry is the candidate set.
|
|
2345
|
-
const heldPromise =
|
|
2346
|
-
|
|
2347
|
-
|
|
3879
|
+
const heldPromise =
|
|
3880
|
+
options.verified || zone
|
|
3881
|
+
? undefined
|
|
3882
|
+
: queryHeldVaults(c, { address: options.address, chainId: options.chainId })
|
|
2348
3883
|
// Observing these branches prevents unhandled rejections while the
|
|
2349
3884
|
// denomination validates; the later await still propagates them.
|
|
2350
3885
|
void recordsPromise.catch(() => undefined)
|
|
@@ -2383,13 +3918,14 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
|
|
|
2383
3918
|
batch.map(async (vault) => {
|
|
2384
3919
|
const record = registry.get(vault)
|
|
2385
3920
|
try {
|
|
2386
|
-
const position = await
|
|
2387
|
-
|
|
3921
|
+
const position = await getVaultPosition(c, {
|
|
3922
|
+
account: options.address,
|
|
2388
3923
|
chainId: options.chainId,
|
|
2389
|
-
|
|
3924
|
+
vault: Schema.Address.parse(vault),
|
|
2390
3925
|
})
|
|
2391
3926
|
return { position, record, vaultAddress: vault }
|
|
2392
3927
|
} catch (cause) {
|
|
3928
|
+
if (cause instanceof EarnVaults.NotFoundError) return undefined
|
|
2393
3929
|
if (!record && isIncompatible(cause)) return undefined
|
|
2394
3930
|
throw cause
|
|
2395
3931
|
}
|
|
@@ -2403,7 +3939,18 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
|
|
|
2403
3939
|
}
|
|
2404
3940
|
|
|
2405
3941
|
const page = matches.slice(0, options.limit)
|
|
2406
|
-
const
|
|
3942
|
+
const indexedBlock =
|
|
3943
|
+
!zone && page.length > 0 && options.include.includes('earnings')
|
|
3944
|
+
? await getLatestIndexedBlock(c.get('getTidx')(options.chainId))
|
|
3945
|
+
: undefined
|
|
3946
|
+
const [cashFlows, tokens, valueTokens, snapshot] = await Promise.all([
|
|
3947
|
+
indexedBlock
|
|
3948
|
+
? getVaultLifetimeCashFlows(c.get('getTidx')(options.chainId), {
|
|
3949
|
+
account: options.address,
|
|
3950
|
+
blockNumber: indexedBlock.number,
|
|
3951
|
+
vaults: page.map(({ vaultAddress }) => Schema.Address.parse(vaultAddress)),
|
|
3952
|
+
})
|
|
3953
|
+
: undefined,
|
|
2407
3954
|
(async () => {
|
|
2408
3955
|
const addresses = [
|
|
2409
3956
|
...new Set(page.flatMap(({ position }) => [position.assetToken, position.shareToken])),
|
|
@@ -2419,13 +3966,20 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
|
|
|
2419
3966
|
)
|
|
2420
3967
|
return new Map(groups.flatMap((group) => [...group]))
|
|
2421
3968
|
})(),
|
|
2422
|
-
|
|
3969
|
+
zone
|
|
3970
|
+
? Tokens.resolveTokens(c, {
|
|
3971
|
+
addresses: [...new Set(page.map(({ position }) => position.valueToken))],
|
|
3972
|
+
chainId: sourceChainId,
|
|
3973
|
+
include: ['token.verified'],
|
|
3974
|
+
})
|
|
3975
|
+
: undefined,
|
|
3976
|
+
denomination ? VerifiedTokens.snapshot(c, sourceChainId) : undefined,
|
|
2423
3977
|
])
|
|
2424
3978
|
const rates =
|
|
2425
3979
|
denomination && snapshot
|
|
2426
3980
|
? await Valuation.ratesFor(c, {
|
|
2427
3981
|
currencies: page.flatMap(({ position }) => {
|
|
2428
|
-
const currency = snapshot.byAddress.get(position.
|
|
3982
|
+
const currency = snapshot.byAddress.get(position.valueToken.toLowerCase())?.currency
|
|
2429
3983
|
return currency === undefined ? [] : [currency]
|
|
2430
3984
|
}),
|
|
2431
3985
|
denomination,
|
|
@@ -2444,11 +3998,14 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
|
|
|
2444
3998
|
return {
|
|
2445
3999
|
data: page.map((match) =>
|
|
2446
4000
|
serializePosition({
|
|
4001
|
+
cashFlows: cashFlows?.get(match.vaultAddress),
|
|
4002
|
+
chainId: options.chainId,
|
|
2447
4003
|
denomination,
|
|
2448
4004
|
position: match.position,
|
|
2449
4005
|
rates,
|
|
2450
4006
|
snapshot,
|
|
2451
4007
|
tokens,
|
|
4008
|
+
valueTokens,
|
|
2452
4009
|
vaultAddress: match.vaultAddress,
|
|
2453
4010
|
verified: match.record !== undefined,
|
|
2454
4011
|
}),
|
|
@@ -2461,7 +4018,7 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
|
|
|
2461
4018
|
export declare namespace listPositions {
|
|
2462
4019
|
/** One candidate vault holding a non-zero position. */
|
|
2463
4020
|
type Match = {
|
|
2464
|
-
position:
|
|
4021
|
+
position: getVaultPosition.ReturnType
|
|
2465
4022
|
record?: RegistryRecord | undefined
|
|
2466
4023
|
vaultAddress: string
|
|
2467
4024
|
}
|
|
@@ -2481,12 +4038,11 @@ async function queryHeldVaults(
|
|
|
2481
4038
|
c: Context<App.Environment>,
|
|
2482
4039
|
options: queryHeldVaults.Options,
|
|
2483
4040
|
): Promise<readonly string[]> {
|
|
4041
|
+
const factories = deploymentFactories[options.chainId] ?? []
|
|
4042
|
+
if (factories.length === 0) return []
|
|
2484
4043
|
const tidx = c.get('getTidx')(options.chainId)
|
|
2485
|
-
//
|
|
2486
|
-
//
|
|
2487
|
-
// candidates in one round trip, with no literal list to overflow the request.
|
|
2488
|
-
// Earn shares are factory-minted TIP-20s, so the `0x20c0` prefix bounds the
|
|
2489
|
-
// subquery. Stale delta rows are fine: the live read drops them.
|
|
4044
|
+
// Filter emitters before ranking so forged events cannot replace share bindings.
|
|
4045
|
+
// TIP-20 prefixes bound holder scans; live reads discard exited positions.
|
|
2490
4046
|
const result = await Timing.time(c, 'earn_positions_discovery', () =>
|
|
2491
4047
|
tidx.fetch({
|
|
2492
4048
|
chainId: options.chainId,
|
|
@@ -2502,6 +4058,7 @@ async function queryHeldVaults(
|
|
|
2502
4058
|
ORDER BY block_num DESC, log_idx DESC
|
|
2503
4059
|
) AS deployment_rank
|
|
2504
4060
|
FROM EarnStackDeployed
|
|
4061
|
+
WHERE address IN (${factories.map((address) => `'${address}'`).join(', ')})
|
|
2505
4062
|
)
|
|
2506
4063
|
WHERE deployment_rank = 1 AND lower("earnShare") IN (
|
|
2507
4064
|
SELECT DISTINCT lower(token)
|
|
@@ -2528,35 +4085,19 @@ declare namespace queryHeldVaults {
|
|
|
2528
4085
|
}
|
|
2529
4086
|
}
|
|
2530
4087
|
|
|
2531
|
-
/** Reads one account's live position in one vault. */
|
|
2532
|
-
function readPosition(
|
|
2533
|
-
c: Context<App.Environment>,
|
|
2534
|
-
options: readPosition.Options,
|
|
2535
|
-
): Promise<Actions.earn.getPosition.ReturnValue> {
|
|
2536
|
-
return c
|
|
2537
|
-
.get('getClient')(options.chainId)
|
|
2538
|
-
.earn.getPosition({ account: options.address, vault: options.vaultAddress })
|
|
2539
|
-
}
|
|
2540
|
-
|
|
2541
|
-
declare namespace readPosition {
|
|
2542
|
-
/** Inputs selecting one vault position. */
|
|
2543
|
-
type Options = {
|
|
2544
|
-
address: z.output<typeof Schema.Address>
|
|
2545
|
-
chainId: z.output<typeof Schema.ChainId>
|
|
2546
|
-
vaultAddress: z.output<typeof Schema.Address>
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
|
|
2550
4088
|
/** Serializes one live position into the address-scoped row contract. */
|
|
2551
4089
|
function serializePosition(options: serializePosition.Options) {
|
|
2552
4090
|
const { position, tokens } = options
|
|
2553
4091
|
const assetToken = getToken(tokens, position.assetToken)
|
|
2554
4092
|
const shareToken = getToken(tokens, position.shareToken)
|
|
4093
|
+
const valueToken = getToken(options.valueTokens ?? tokens, position.valueToken)
|
|
2555
4094
|
const vaultAddress = Schema.Address.parse(options.vaultAddress.toLowerCase())
|
|
2556
4095
|
return {
|
|
2557
|
-
assetAmount: valueFor(position.value,
|
|
4096
|
+
assetAmount: valueFor(position.value, valueToken),
|
|
2558
4097
|
assetToken,
|
|
4098
|
+
chainId: options.chainId,
|
|
2559
4099
|
id: vaultAddress,
|
|
4100
|
+
...(options.cashFlows ? { lifetimeCashFlows: options.cashFlows } : {}),
|
|
2560
4101
|
shareAmount: valueFor(position.shareBalance, shareToken),
|
|
2561
4102
|
shareToken,
|
|
2562
4103
|
...(options.denomination
|
|
@@ -2565,10 +4106,11 @@ function serializePosition(options: serializePosition.Options) {
|
|
|
2565
4106
|
amount: position.value,
|
|
2566
4107
|
denomination: options.denomination,
|
|
2567
4108
|
rates: options.rates,
|
|
2568
|
-
token: options.snapshot?.byAddress.get(
|
|
4109
|
+
token: options.snapshot?.byAddress.get(valueToken.address),
|
|
2569
4110
|
}),
|
|
2570
4111
|
}
|
|
2571
4112
|
: {}),
|
|
4113
|
+
valueToken,
|
|
2572
4114
|
vaultAddress,
|
|
2573
4115
|
verified: options.verified,
|
|
2574
4116
|
}
|
|
@@ -2577,19 +4119,174 @@ function serializePosition(options: serializePosition.Options) {
|
|
|
2577
4119
|
declare namespace serializePosition {
|
|
2578
4120
|
/** Values used to serialize one account position row. */
|
|
2579
4121
|
type Options = {
|
|
4122
|
+
/** Indexed lifetime cash flows, when requested. */
|
|
4123
|
+
cashFlows?: z.output<
|
|
4124
|
+
typeof schema.getEarnAddressPositions.Response
|
|
4125
|
+
>['data'][number]['lifetimeCashFlows']
|
|
4126
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
2580
4127
|
/** Currency the row valuation is denominated in (uppercase). */
|
|
2581
4128
|
denomination?: string | undefined
|
|
2582
|
-
position:
|
|
4129
|
+
position: getVaultPosition.ReturnType
|
|
2583
4130
|
/** Consulted FX rate set, or undefined when unavailable or unnecessary. */
|
|
2584
4131
|
rates: Awaited<ReturnType<typeof Valuation.ratesFor>>
|
|
2585
4132
|
/** Curated token snapshot backing valuation, present when requested. */
|
|
2586
4133
|
snapshot?: VerifiedTokens.Snapshot | undefined
|
|
2587
4134
|
tokens: Tokens.resolveTokens.ReturnType
|
|
4135
|
+
valueTokens?: Tokens.resolveTokens.ReturnType | undefined
|
|
2588
4136
|
vaultAddress: string
|
|
2589
4137
|
verified: boolean
|
|
2590
4138
|
}
|
|
2591
4139
|
}
|
|
2592
4140
|
|
|
4141
|
+
/** Reads complete protocol cash flows for one account and a set of vaults. */
|
|
4142
|
+
export async function getVaultLifetimeCashFlows(
|
|
4143
|
+
tidx: Tidx.Client,
|
|
4144
|
+
options: getVaultLifetimeCashFlows.Options,
|
|
4145
|
+
) {
|
|
4146
|
+
const vaults = [...new Set(options.vaults.map((vault) => vault.toLowerCase()))]
|
|
4147
|
+
const cashFlows = new Map<string, getVaultLifetimeCashFlows.CashFlows>()
|
|
4148
|
+
if (vaults.length === 0) return cashFlows
|
|
4149
|
+
const addresses = vaults.map((vault) => `'${vault}'`).join(', ')
|
|
4150
|
+
const seeds = vaults
|
|
4151
|
+
.map(
|
|
4152
|
+
(vault) => `
|
|
4153
|
+
SELECT '${vault}' AS vault,
|
|
4154
|
+
toUInt256(0) AS deposited_assets,
|
|
4155
|
+
toUInt256(0) AS finalized_assets,
|
|
4156
|
+
toUInt256(0) AS redeemed_assets,
|
|
4157
|
+
toUInt64(0) AS venue_deposits,
|
|
4158
|
+
toUInt256(0) AS withdrew_exact`,
|
|
4159
|
+
)
|
|
4160
|
+
.join('\n UNION ALL')
|
|
4161
|
+
const result = await tidx.fetch({
|
|
4162
|
+
engine: 'clickhouse',
|
|
4163
|
+
query: `
|
|
4164
|
+
SELECT vault,
|
|
4165
|
+
toString(sum(deposited_assets)) AS deposited_assets,
|
|
4166
|
+
toString(sum(finalized_assets)) AS finalized_assets,
|
|
4167
|
+
toString(sum(redeemed_assets)) AS redeemed_assets,
|
|
4168
|
+
sum(venue_deposits) AS venue_deposits,
|
|
4169
|
+
toString(sum(withdrew_exact)) AS withdrew_exact
|
|
4170
|
+
FROM (
|
|
4171
|
+
${seeds}
|
|
4172
|
+
UNION ALL
|
|
4173
|
+
SELECT address AS vault, sum(toUInt256(assets)) AS deposited_assets,
|
|
4174
|
+
toUInt256(0) AS finalized_assets, toUInt256(0) AS redeemed_assets,
|
|
4175
|
+
toUInt64(0) AS venue_deposits, toUInt256(0) AS withdrew_exact
|
|
4176
|
+
FROM Deposited
|
|
4177
|
+
WHERE address IN (${addresses})
|
|
4178
|
+
AND receiver = '${options.account}'
|
|
4179
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
4180
|
+
AND block_num <= ${options.blockNumber}
|
|
4181
|
+
GROUP BY address
|
|
4182
|
+
UNION ALL
|
|
4183
|
+
SELECT finalized.address AS vault, toUInt256(0) AS deposited_assets,
|
|
4184
|
+
sum(toUInt256(finalized.assets)) AS finalized_assets,
|
|
4185
|
+
toUInt256(0) AS redeemed_assets, toUInt64(0) AS venue_deposits,
|
|
4186
|
+
toUInt256(0) AS withdrew_exact
|
|
4187
|
+
FROM RedeemFinalized AS finalized
|
|
4188
|
+
INNER JOIN RedeemRequested AS requested
|
|
4189
|
+
ON requested.address = finalized.address
|
|
4190
|
+
AND requested."requestId" = finalized."requestId"
|
|
4191
|
+
WHERE finalized.address IN (${addresses})
|
|
4192
|
+
AND requested.requester = '${options.account}'
|
|
4193
|
+
AND finalized.block_num > ${beforeFirstBlockNumber}
|
|
4194
|
+
AND finalized.block_num <= ${options.blockNumber}
|
|
4195
|
+
AND requested.block_num <= ${options.blockNumber}
|
|
4196
|
+
GROUP BY finalized.address
|
|
4197
|
+
UNION ALL
|
|
4198
|
+
SELECT address AS vault, toUInt256(0) AS deposited_assets,
|
|
4199
|
+
toUInt256(0) AS finalized_assets, sum(toUInt256(assets)) AS redeemed_assets,
|
|
4200
|
+
toUInt64(0) AS venue_deposits,
|
|
4201
|
+
toUInt256(0) AS withdrew_exact
|
|
4202
|
+
FROM Redeemed
|
|
4203
|
+
WHERE address IN (${addresses})
|
|
4204
|
+
AND caller = '${options.account}'
|
|
4205
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
4206
|
+
AND block_num <= ${options.blockNumber}
|
|
4207
|
+
GROUP BY address
|
|
4208
|
+
UNION ALL
|
|
4209
|
+
SELECT address AS vault, toUInt256(0) AS deposited_assets,
|
|
4210
|
+
toUInt256(0) AS finalized_assets, toUInt256(0) AS redeemed_assets,
|
|
4211
|
+
count() AS venue_deposits, toUInt256(0) AS withdrew_exact
|
|
4212
|
+
FROM VenueSharesDeposited
|
|
4213
|
+
WHERE address IN (${addresses})
|
|
4214
|
+
AND receiver = '${options.account}'
|
|
4215
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
4216
|
+
AND block_num <= ${options.blockNumber}
|
|
4217
|
+
GROUP BY address
|
|
4218
|
+
UNION ALL
|
|
4219
|
+
SELECT address AS vault, toUInt256(0) AS deposited_assets,
|
|
4220
|
+
toUInt256(0) AS finalized_assets, toUInt256(0) AS redeemed_assets,
|
|
4221
|
+
toUInt64(0) AS venue_deposits, sum(toUInt256(assets)) AS withdrew_exact
|
|
4222
|
+
FROM WithdrewExact
|
|
4223
|
+
WHERE address IN (${addresses})
|
|
4224
|
+
AND caller = '${options.account}'
|
|
4225
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
4226
|
+
AND block_num <= ${options.blockNumber}
|
|
4227
|
+
GROUP BY address
|
|
4228
|
+
) AS histories
|
|
4229
|
+
GROUP BY vault
|
|
4230
|
+
` as string,
|
|
4231
|
+
signatures: [
|
|
4232
|
+
depositedSignature,
|
|
4233
|
+
redeemFinalizedSignature,
|
|
4234
|
+
redeemRequestedSignature,
|
|
4235
|
+
redeemedSignature,
|
|
4236
|
+
venueSharesDepositedSignature,
|
|
4237
|
+
withdrewExactSignature,
|
|
4238
|
+
],
|
|
4239
|
+
})
|
|
4240
|
+
for (const row of result.rows) {
|
|
4241
|
+
const vault = Schema.Address.safeParse(Value.toText(row['vault']))
|
|
4242
|
+
const deposited = Value.toIntegerString(row['deposited_assets'])
|
|
4243
|
+
const finalized = Value.toIntegerString(row['finalized_assets'])
|
|
4244
|
+
const redeemed = Value.toIntegerString(row['redeemed_assets'])
|
|
4245
|
+
const venueDeposits = Value.toNumber(row['venue_deposits'])
|
|
4246
|
+
const withdrewExact = Value.toIntegerString(row['withdrew_exact'])
|
|
4247
|
+
if (
|
|
4248
|
+
!vault.success ||
|
|
4249
|
+
deposited === undefined ||
|
|
4250
|
+
finalized === undefined ||
|
|
4251
|
+
redeemed === undefined ||
|
|
4252
|
+
venueDeposits === undefined ||
|
|
4253
|
+
withdrewExact === undefined
|
|
4254
|
+
)
|
|
4255
|
+
throw new Error('TIDX returned invalid Earn lifetime cash flows.')
|
|
4256
|
+
cashFlows.set(
|
|
4257
|
+
vault.data.toLowerCase(),
|
|
4258
|
+
venueDeposits > 0
|
|
4259
|
+
? { status: 'incomplete_history' }
|
|
4260
|
+
: {
|
|
4261
|
+
status: 'complete',
|
|
4262
|
+
totalDeposited: deposited,
|
|
4263
|
+
totalWithdrawn: (
|
|
4264
|
+
BigInt(finalized) +
|
|
4265
|
+
BigInt(redeemed) +
|
|
4266
|
+
BigInt(withdrewExact)
|
|
4267
|
+
).toString(),
|
|
4268
|
+
},
|
|
4269
|
+
)
|
|
4270
|
+
}
|
|
4271
|
+
if (cashFlows.size !== vaults.length)
|
|
4272
|
+
throw new Error('TIDX returned incomplete Earn lifetime cash flows.')
|
|
4273
|
+
return cashFlows
|
|
4274
|
+
}
|
|
4275
|
+
|
|
4276
|
+
export declare namespace getVaultLifetimeCashFlows {
|
|
4277
|
+
/** Lifetime cash-flow state for one vault. */
|
|
4278
|
+
type CashFlows = NonNullable<
|
|
4279
|
+
z.output<typeof schema.getEarnAddressPositions.Response>['data'][number]['lifetimeCashFlows']
|
|
4280
|
+
>
|
|
4281
|
+
|
|
4282
|
+
/** Indexed boundary and account whose protocol cash flows are read. */
|
|
4283
|
+
type Options = {
|
|
4284
|
+
account: z.output<typeof Schema.Address>
|
|
4285
|
+
blockNumber: number
|
|
4286
|
+
vaults: readonly z.output<typeof Schema.Address>[]
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
|
|
2593
4290
|
/** Renders a base-unit amount in the token's display currency and precision. */
|
|
2594
4291
|
function valueFor(amount: bigint, token: z.output<typeof Tokens.schema.Token>) {
|
|
2595
4292
|
return {
|
|
@@ -2624,7 +4321,7 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
|
|
|
2624
4321
|
record,
|
|
2625
4322
|
})
|
|
2626
4323
|
const discoveries = [discovery]
|
|
2627
|
-
const [apy, rates, tokens] = await Promise.all([
|
|
4324
|
+
const [apy, rates, rewards, tokens] = await Promise.all([
|
|
2628
4325
|
resolvePageApy(c, {
|
|
2629
4326
|
chainId: options.chainId,
|
|
2630
4327
|
include,
|
|
@@ -2632,6 +4329,11 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
|
|
|
2632
4329
|
window: options['apy.window'],
|
|
2633
4330
|
}),
|
|
2634
4331
|
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
4332
|
+
resolveVaultRewards(c, {
|
|
4333
|
+
chainId: options.chainId,
|
|
4334
|
+
include,
|
|
4335
|
+
vault: discovery.vaultAddress,
|
|
4336
|
+
}),
|
|
2635
4337
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
2636
4338
|
])
|
|
2637
4339
|
return {
|
|
@@ -2641,6 +4343,7 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
|
|
|
2641
4343
|
include,
|
|
2642
4344
|
rates,
|
|
2643
4345
|
record,
|
|
4346
|
+
rewards,
|
|
2644
4347
|
snapshot,
|
|
2645
4348
|
tokens,
|
|
2646
4349
|
zoneRoutes,
|
|
@@ -2718,29 +4421,36 @@ async function resolveVaultDiscovery(
|
|
|
2718
4421
|
c: Context<App.Environment>,
|
|
2719
4422
|
options: resolveVaultDiscovery.Options,
|
|
2720
4423
|
) {
|
|
2721
|
-
return Store.memoize(
|
|
2722
|
-
()
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
4424
|
+
return Store.memoize(() => readVaultDiscovery(c, options), {
|
|
4425
|
+
key: `earn-vault:v3:${options.chainId}:${options.vaultAddress.toLowerCase()}:include:${options.include.join(',') || 'base'}`,
|
|
4426
|
+
store: c.get('store'),
|
|
4427
|
+
// Matches the routes' `state` policy `max-age` so the two cache layers do
|
|
4428
|
+
// not compound staleness on live vault state.
|
|
4429
|
+
ttl: Ttl.seconds(30),
|
|
4430
|
+
})
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4433
|
+
async function readVaultDiscovery(
|
|
4434
|
+
c: Context<App.Environment>,
|
|
4435
|
+
options: readVaultDiscovery.Options,
|
|
4436
|
+
) {
|
|
4437
|
+
return Timing.time(c, 'earn_vault_discovery', () =>
|
|
4438
|
+
EarnVaults.resolve({
|
|
4439
|
+
getClient: c.get('getClient'),
|
|
4440
|
+
include: options.include,
|
|
4441
|
+
input: {
|
|
4442
|
+
chainId: options.chainId,
|
|
4443
|
+
vaultAddress: options.vaultAddress,
|
|
4444
|
+
},
|
|
4445
|
+
zones: [...c.get('zones').values()],
|
|
4446
|
+
}),
|
|
2741
4447
|
)
|
|
2742
4448
|
}
|
|
2743
4449
|
|
|
4450
|
+
declare namespace readVaultDiscovery {
|
|
4451
|
+
type Options = resolveVaultDiscovery.Options
|
|
4452
|
+
}
|
|
4453
|
+
|
|
2744
4454
|
declare namespace resolveVaultDiscovery {
|
|
2745
4455
|
type Options = {
|
|
2746
4456
|
chainId: z.output<typeof Schema.ChainId>
|
|
@@ -2803,6 +4513,129 @@ declare namespace resolveVaultRoutes {
|
|
|
2803
4513
|
}
|
|
2804
4514
|
}
|
|
2805
4515
|
|
|
4516
|
+
async function resolvePositionApy(
|
|
4517
|
+
c: Context<App.Environment>,
|
|
4518
|
+
options: resolvePositionApy.Options,
|
|
4519
|
+
): Promise<RewardRead.PositionApy | null> {
|
|
4520
|
+
const sourceChainId = c.get('zones').get(options.chainId)?.sourceId ?? options.chainId
|
|
4521
|
+
const recordFailure = (failure: Log.ProviderFailure) => {
|
|
4522
|
+
Cache.setPolicy(c, Cache.policies.noStore)
|
|
4523
|
+
c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure])
|
|
4524
|
+
}
|
|
4525
|
+
const rateFailures: Log.ProviderFailure[] = []
|
|
4526
|
+
const [rates, discovery] = await Promise.all([
|
|
4527
|
+
Timing.time(c, 'earn_apy', () =>
|
|
4528
|
+
EarnRates.resolve({
|
|
4529
|
+
chainId: sourceChainId,
|
|
4530
|
+
getClient: c.get('getClient'),
|
|
4531
|
+
getTidx: c.get('getTidx'),
|
|
4532
|
+
onFailure: (failure) => {
|
|
4533
|
+
rateFailures.push({ ...failure, chainId: sourceChainId })
|
|
4534
|
+
},
|
|
4535
|
+
store: c.get('store'),
|
|
4536
|
+
vaults: [options.vault],
|
|
4537
|
+
}),
|
|
4538
|
+
).catch(() => {
|
|
4539
|
+
rateFailures.push({
|
|
4540
|
+
chainId: sourceChainId,
|
|
4541
|
+
failure: 'unknown',
|
|
4542
|
+
id: 'earn-apy',
|
|
4543
|
+
operation: 'resolve',
|
|
4544
|
+
})
|
|
4545
|
+
return undefined
|
|
4546
|
+
}),
|
|
4547
|
+
resolveVaultDiscovery(c, {
|
|
4548
|
+
chainId: sourceChainId,
|
|
4549
|
+
include: [],
|
|
4550
|
+
vaultAddress: options.vault,
|
|
4551
|
+
}).catch((cause) => {
|
|
4552
|
+
const failure = Viem.requestFailure(cause)
|
|
4553
|
+
recordFailure(
|
|
4554
|
+
failure
|
|
4555
|
+
? { ...failure, chainId: sourceChainId, id: 'rpc', operation: 'eth_call' }
|
|
4556
|
+
: {
|
|
4557
|
+
chainId: sourceChainId,
|
|
4558
|
+
failure: 'unknown',
|
|
4559
|
+
id: 'earn-vaults',
|
|
4560
|
+
operation: 'getVault',
|
|
4561
|
+
},
|
|
4562
|
+
)
|
|
4563
|
+
return undefined
|
|
4564
|
+
}),
|
|
4565
|
+
])
|
|
4566
|
+
const base = rates?.get(options.vault.toLowerCase())
|
|
4567
|
+
const rateFailure = rateFailures[0]
|
|
4568
|
+
if (rateFailure) recordFailure(rateFailure)
|
|
4569
|
+
if (!base || !discovery) return null
|
|
4570
|
+
return await Timing.time(c, 'earn_rewards_apy', async () => {
|
|
4571
|
+
const [earnFees, record] = await Promise.all([
|
|
4572
|
+
c.get('getClient')(sourceChainId).readContract({
|
|
4573
|
+
abi: Abis.earnVault,
|
|
4574
|
+
address: options.vault,
|
|
4575
|
+
functionName: 'earnFees',
|
|
4576
|
+
}),
|
|
4577
|
+
core_EarnVaults.get(Db.get(c.get('db')), {
|
|
4578
|
+
chainId: options.chainId,
|
|
4579
|
+
vaultAddress: options.vault,
|
|
4580
|
+
}),
|
|
4581
|
+
])
|
|
4582
|
+
// Accounting retains qualified shares for excluded infrastructure, so apply its current exclusions here too.
|
|
4583
|
+
const zoneContracts = [...c.get('zones').values()]
|
|
4584
|
+
.filter((zone) => zone.sourceId === options.chainId)
|
|
4585
|
+
.flatMap((zone) => positionApyContractAddresses(zone.contracts))
|
|
4586
|
+
return RewardRead.positionApy({
|
|
4587
|
+
assetDecimals: discovery.assetToken.decimals,
|
|
4588
|
+
baseNet: base.net,
|
|
4589
|
+
chainId: options.chainId,
|
|
4590
|
+
db: c.get('db'),
|
|
4591
|
+
excludedAddresses: [
|
|
4592
|
+
discovery.engine.address,
|
|
4593
|
+
earnFees,
|
|
4594
|
+
...(record?.zones.map((zone) => zone.earnRouter) ?? []),
|
|
4595
|
+
...zoneContracts,
|
|
4596
|
+
],
|
|
4597
|
+
recipient: options.recipient,
|
|
4598
|
+
shareBalance: options.shareBalance.toString(),
|
|
4599
|
+
value: options.value.toString(),
|
|
4600
|
+
vaultAddress: options.vault,
|
|
4601
|
+
})
|
|
4602
|
+
}).catch((cause) => {
|
|
4603
|
+
recordFailure(
|
|
4604
|
+
sharePriceProviderFailure({ cause, chainId: sourceChainId }) ?? {
|
|
4605
|
+
chainId: options.chainId,
|
|
4606
|
+
failure: 'unknown',
|
|
4607
|
+
id: 'earn-rewards',
|
|
4608
|
+
operation: 'getPositionApy',
|
|
4609
|
+
},
|
|
4610
|
+
)
|
|
4611
|
+
return null
|
|
4612
|
+
})
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4615
|
+
declare namespace resolvePositionApy {
|
|
4616
|
+
/** Current wallet position used to resolve its effective APY. */
|
|
4617
|
+
type Options = {
|
|
4618
|
+
/** Chain containing the vault position. */
|
|
4619
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
4620
|
+
/** Wallet receiving the position yield. */
|
|
4621
|
+
recipient: z.output<typeof Schema.Address>
|
|
4622
|
+
/** Current EarnShare balance. */
|
|
4623
|
+
shareBalance: bigint
|
|
4624
|
+
/** Current asset value of the position. */
|
|
4625
|
+
value: bigint
|
|
4626
|
+
/** EarnVault containing the position. */
|
|
4627
|
+
vault: z.output<typeof Schema.Address>
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
|
|
4631
|
+
function positionApyContractAddresses(contract: unknown): string[] {
|
|
4632
|
+
if (!contract || typeof contract !== 'object') return []
|
|
4633
|
+
const value = contract as Record<string, unknown>
|
|
4634
|
+
const address = value['address']
|
|
4635
|
+
if (typeof address === 'string' && isAddress(address)) return [address]
|
|
4636
|
+
return Object.values(value).flatMap(positionApyContractAddresses)
|
|
4637
|
+
}
|
|
4638
|
+
|
|
2806
4639
|
// Measuring a rate costs indexer boundary queries plus historical quotes against
|
|
2807
4640
|
// an archive node, so an unrequested rate reaches neither.
|
|
2808
4641
|
function resolvePageApy(c: Context<App.Environment>, options: resolvePageApy.Options) {
|
|
@@ -2819,6 +4652,64 @@ function resolvePageApy(c: Context<App.Environment>, options: resolvePageApy.Opt
|
|
|
2819
4652
|
)
|
|
2820
4653
|
}
|
|
2821
4654
|
|
|
4655
|
+
function resolvePageRewards(c: Context<App.Environment>, options: resolvePageRewards.Options) {
|
|
4656
|
+
if (!options.include.includes('apy')) return undefined
|
|
4657
|
+
return Timing.time(c, 'earn_rewards_apy', () =>
|
|
4658
|
+
RewardRead.resolveCollection({
|
|
4659
|
+
chainId: options.chainId,
|
|
4660
|
+
db: c.get('dbCached'),
|
|
4661
|
+
vaults: options.vaults,
|
|
4662
|
+
}).catch(() => {
|
|
4663
|
+
Cache.setPolicy(c, Cache.policies.noStore)
|
|
4664
|
+
const failure = {
|
|
4665
|
+
chainId: options.chainId,
|
|
4666
|
+
failure: 'unknown',
|
|
4667
|
+
id: 'earn-rewards',
|
|
4668
|
+
operation: 'listVaultRewards',
|
|
4669
|
+
} satisfies Log.ProviderFailure
|
|
4670
|
+
c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure])
|
|
4671
|
+
return new Map<string, readonly RewardRead.Reward[]>()
|
|
4672
|
+
}),
|
|
4673
|
+
)
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4676
|
+
function resolveVaultRewards(c: Context<App.Environment>, options: resolveVaultRewards.Options) {
|
|
4677
|
+
if (!options.include.includes('apy')) return undefined
|
|
4678
|
+
return Timing.time(c, 'earn_rewards_apy', () =>
|
|
4679
|
+
RewardRead.get({
|
|
4680
|
+
chainId: options.chainId,
|
|
4681
|
+
db: c.get('dbCached'),
|
|
4682
|
+
vaultAddress: options.vault,
|
|
4683
|
+
}).catch(() => {
|
|
4684
|
+
Cache.setPolicy(c, Cache.policies.noStore)
|
|
4685
|
+
const failure = {
|
|
4686
|
+
chainId: options.chainId,
|
|
4687
|
+
failure: 'unknown',
|
|
4688
|
+
id: 'earn-rewards',
|
|
4689
|
+
operation: 'getVaultRewards',
|
|
4690
|
+
} satisfies Log.ProviderFailure
|
|
4691
|
+
c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure])
|
|
4692
|
+
return undefined
|
|
4693
|
+
}),
|
|
4694
|
+
)
|
|
4695
|
+
}
|
|
4696
|
+
|
|
4697
|
+
declare namespace resolveVaultRewards {
|
|
4698
|
+
type Options = {
|
|
4699
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
4700
|
+
include: z.output<typeof schema.getEarnVault.Query>['include']
|
|
4701
|
+
vault: z.output<typeof Schema.Address>
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
|
|
4705
|
+
declare namespace resolvePageRewards {
|
|
4706
|
+
type Options = {
|
|
4707
|
+
chainId: z.output<typeof Schema.ChainId>
|
|
4708
|
+
include: z.output<typeof schema.getEarnVault.Query>['include']
|
|
4709
|
+
vaults: readonly z.output<typeof Schema.Address>[]
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
|
|
2822
4713
|
declare namespace resolvePageApy {
|
|
2823
4714
|
type Options = {
|
|
2824
4715
|
chainId: z.output<typeof Schema.ChainId>
|
|
@@ -2898,12 +4789,30 @@ async function resolveVault(c: Context<App.Environment>, options: resolveVault.O
|
|
|
2898
4789
|
token: options.snapshot.byAddress.get(discovery.assetToken.address),
|
|
2899
4790
|
})
|
|
2900
4791
|
: undefined
|
|
4792
|
+
const liquidityValue =
|
|
4793
|
+
options.include.includes('tvl') && discovery.instantLiquidity !== null
|
|
4794
|
+
? Valuation.valuationFor({
|
|
4795
|
+
amount: BigInt(discovery.instantLiquidity),
|
|
4796
|
+
denomination: tvlDenomination,
|
|
4797
|
+
rates: options.rates,
|
|
4798
|
+
token: options.snapshot.byAddress.get(discovery.assetToken.address),
|
|
4799
|
+
})
|
|
4800
|
+
: undefined
|
|
2901
4801
|
return serializeVault({
|
|
2902
4802
|
apy: options.apy?.get(discovery.vaultAddress) ?? null,
|
|
2903
4803
|
assetToken: getToken(options.tokens, discovery.assetToken.address),
|
|
2904
4804
|
discovery,
|
|
2905
4805
|
include: options.include,
|
|
4806
|
+
instantLiquidityValue: liquidityValue
|
|
4807
|
+
? {
|
|
4808
|
+
amount: core_Value.from(liquidityValue.amount, tvlDecimals).toString(),
|
|
4809
|
+
currency: liquidityValue.currency,
|
|
4810
|
+
decimals: tvlDecimals,
|
|
4811
|
+
formatted: liquidityValue.amount,
|
|
4812
|
+
}
|
|
4813
|
+
: null,
|
|
2906
4814
|
record,
|
|
4815
|
+
rewards: options.rewards,
|
|
2907
4816
|
shareToken: getToken(options.tokens, discovery.shareToken.address),
|
|
2908
4817
|
tvl: valued
|
|
2909
4818
|
? {
|
|
@@ -2925,6 +4834,7 @@ declare namespace resolveVault {
|
|
|
2925
4834
|
include: z.output<typeof schema.getEarnVault.Query>['include']
|
|
2926
4835
|
rates: Awaited<ReturnType<typeof Valuation.ratesFor>>
|
|
2927
4836
|
record?: RegistryRecord | undefined
|
|
4837
|
+
rewards?: readonly RewardRead.Reward[] | undefined
|
|
2928
4838
|
snapshot: VerifiedTokens.Snapshot
|
|
2929
4839
|
tokens: Tokens.resolveTokens.ReturnType
|
|
2930
4840
|
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
@@ -2939,9 +4849,41 @@ export function serializeVault(options: serializeVault.Options): z.output<typeof
|
|
|
2939
4849
|
if (options.include.includes('capabilities') && !discovery.capabilities)
|
|
2940
4850
|
throw new Error('Earn vault capabilities were not resolved.')
|
|
2941
4851
|
const vaultAddress = Schema.Address.parse(discovery.vaultAddress.toLowerCase())
|
|
4852
|
+
const rewards = options.rewards?.map((reward) => ({
|
|
4853
|
+
apr:
|
|
4854
|
+
reward.currentRewardsAprBps === null ? null : RewardRead.ratio(reward.currentRewardsAprBps),
|
|
4855
|
+
asset: reward.asset,
|
|
4856
|
+
...(reward.calculatedThrough !== undefined
|
|
4857
|
+
? { calculatedThrough: reward.calculatedThrough }
|
|
4858
|
+
: {}),
|
|
4859
|
+
campaignId: reward.campaignId,
|
|
4860
|
+
endsAt: reward.endsAt,
|
|
4861
|
+
startsAt: reward.startsAt,
|
|
4862
|
+
targetTotalApr: RewardRead.ratio(reward.targetTotalAprBps),
|
|
4863
|
+
}))
|
|
4864
|
+
const startedRewards = options.rewards?.filter(
|
|
4865
|
+
(reward) => reward.startsAt <= Math.floor(Date.now() / 1_000),
|
|
4866
|
+
)
|
|
4867
|
+
const targetTotalAprBps = startedRewards?.reduce(
|
|
4868
|
+
(target, reward) => Math.max(target, reward.targetTotalAprBps),
|
|
4869
|
+
0,
|
|
4870
|
+
)
|
|
4871
|
+
const apy = options.apy
|
|
4872
|
+
? {
|
|
4873
|
+
...options.apy,
|
|
4874
|
+
net: (() => {
|
|
4875
|
+
if (!startedRewards || startedRewards.length === 0) return options.apy.net
|
|
4876
|
+
const target = targetTotalAprBps ?? 0
|
|
4877
|
+
if (parseUnits(options.apy.net, 6) >= BigInt(target) * 100n) return options.apy.net
|
|
4878
|
+
return RewardRead.ratio(target)
|
|
4879
|
+
})(),
|
|
4880
|
+
...(rewards ? { rewards } : {}),
|
|
4881
|
+
vault: options.apy.net,
|
|
4882
|
+
}
|
|
4883
|
+
: null
|
|
2942
4884
|
return Response.validated(schema.Vault, {
|
|
2943
4885
|
...(options.include.includes('access') ? { access: discovery.access } : {}),
|
|
2944
|
-
...(options.include.includes('apy') ? { apy
|
|
4886
|
+
...(options.include.includes('apy') ? { apy } : {}),
|
|
2945
4887
|
assetToken: options.assetToken,
|
|
2946
4888
|
...(options.include.includes('capabilities') ? { capabilities: discovery.capabilities } : {}),
|
|
2947
4889
|
description: record?.description ?? null,
|
|
@@ -2952,6 +4894,9 @@ export function serializeVault(options: serializeVault.Options): z.output<typeof
|
|
|
2952
4894
|
},
|
|
2953
4895
|
id: vaultAddress,
|
|
2954
4896
|
instantLiquidity: discovery.instantLiquidity,
|
|
4897
|
+
...(options.include.includes('tvl')
|
|
4898
|
+
? { instantLiquidityValue: options.instantLiquidityValue }
|
|
4899
|
+
: {}),
|
|
2955
4900
|
label: record?.label ?? options.shareToken.name,
|
|
2956
4901
|
sharePrice:
|
|
2957
4902
|
discovery.sharePrice === null
|
|
@@ -2995,8 +4940,12 @@ export declare namespace serializeVault {
|
|
|
2995
4940
|
discovery: EarnVaults.Discovery
|
|
2996
4941
|
/** Optional vault fields selected by the request. */
|
|
2997
4942
|
include: z.output<typeof schema.getEarnVault.Query>['include']
|
|
4943
|
+
/** USD value of instant liquidity, or null when unavailable; omitted unless `include` carries `tvl`. */
|
|
4944
|
+
instantLiquidityValue: z.output<typeof schema.Vault>['instantLiquidityValue']
|
|
2998
4945
|
/** Curated registry row, when verified. */
|
|
2999
4946
|
record?: core_EarnVaults.Record | undefined
|
|
4947
|
+
/** Enabled, registered Merkle rewards, or undefined when enrichment is unavailable. */
|
|
4948
|
+
rewards?: readonly RewardRead.Reward[] | undefined
|
|
3000
4949
|
/** Resolved share token. */
|
|
3001
4950
|
shareToken: z.output<typeof Tokens.schema.Token>
|
|
3002
4951
|
/** USD value of the assets, or null when unpriced; omitted unless `include` carries `tvl`. */
|
|
@@ -3065,6 +5014,8 @@ async function queryDeployments(
|
|
|
3065
5014
|
c: Context<App.Environment>,
|
|
3066
5015
|
options: queryDeployments.Options,
|
|
3067
5016
|
): Promise<queryDeployments.Result> {
|
|
5017
|
+
const factories = deploymentFactories[options.chainId] ?? []
|
|
5018
|
+
if (factories.length === 0) return { hasMore: false, items: [] }
|
|
3068
5019
|
const filters: string[] = []
|
|
3069
5020
|
if (options.asset) filters.push(`lower(asset) = '${options.asset.toLowerCase()}'`)
|
|
3070
5021
|
if (options.cursor)
|
|
@@ -3083,7 +5034,8 @@ async function queryDeployments(
|
|
|
3083
5034
|
]),
|
|
3084
5035
|
)
|
|
3085
5036
|
|
|
3086
|
-
//
|
|
5037
|
+
// Authenticate emitters before deduplication so a forged newer event cannot
|
|
5038
|
+
// replace a factory deployment or suppress it through outer filters.
|
|
3087
5039
|
const result = await c
|
|
3088
5040
|
.get('getTidx')(options.chainId)
|
|
3089
5041
|
.fetch({
|
|
@@ -3098,6 +5050,7 @@ async function queryDeployments(
|
|
|
3098
5050
|
block_num,
|
|
3099
5051
|
log_idx
|
|
3100
5052
|
FROM EarnStackDeployed
|
|
5053
|
+
WHERE address IN (${factories.map((address) => `'${address}'`).join(', ')})
|
|
3101
5054
|
ORDER BY block_num DESC, log_idx DESC
|
|
3102
5055
|
LIMIT 1 BY lower("earnVault")
|
|
3103
5056
|
)
|
|
@@ -3195,3 +5148,36 @@ type RegistryRecord = Awaited<ReturnType<typeof core_EarnVaults.list>>[number]
|
|
|
3195
5148
|
export class NotFoundError extends Error {
|
|
3196
5149
|
override name = 'Earn.NotFoundError'
|
|
3197
5150
|
}
|
|
5151
|
+
|
|
5152
|
+
/** Thrown when a historical position boundary is not indexed. */
|
|
5153
|
+
class IndexedBlockNotFoundError extends Error {
|
|
5154
|
+
override name = 'Earn.IndexedBlockNotFoundError'
|
|
5155
|
+
|
|
5156
|
+
constructor(asOf: string) {
|
|
5157
|
+
super(`No indexed block exists at or before ${asOf}.`)
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
|
|
5161
|
+
class IndexedCoverageError extends Error {
|
|
5162
|
+
override name = 'Earn.IndexedCoverageError'
|
|
5163
|
+
|
|
5164
|
+
constructor(asOf: string) {
|
|
5165
|
+
super(`Indexed history does not yet cover ${asOf}.`)
|
|
5166
|
+
}
|
|
5167
|
+
}
|
|
5168
|
+
|
|
5169
|
+
class ZoneHistoricalAlignmentError extends Error {
|
|
5170
|
+
override name = 'Earn.ZoneHistoricalAlignmentError'
|
|
5171
|
+
|
|
5172
|
+
constructor() {
|
|
5173
|
+
super('This Zone does not expose historical parent-chain synchronization checkpoints.')
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
|
|
5177
|
+
class ZoneEarningsUnsupportedError extends Error {
|
|
5178
|
+
override name = 'Earn.ZoneEarningsUnsupportedError'
|
|
5179
|
+
|
|
5180
|
+
constructor() {
|
|
5181
|
+
super('Zone positions do not support the earnings include.')
|
|
5182
|
+
}
|
|
5183
|
+
}
|