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,16 +1,22 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { Value as core_Value } from 'ox';
|
|
3
|
-
import {
|
|
3
|
+
import { Abis } from 'viem/tempo';
|
|
4
|
+
import { ContractFunctionExecutionError, ContractFunctionRevertedError, ContractFunctionZeroDataError, isAddress, parseAbi, parseUnits, zeroAddress, } from 'viem';
|
|
4
5
|
import * as z from 'zod/mini';
|
|
5
6
|
import * as Scope from '../../../Scope.js';
|
|
6
7
|
import * as Db from '../../../db/Db.js';
|
|
7
8
|
import * as core_EarnVaults from '../../../db/tables/earnVaults.js';
|
|
9
|
+
import * as RewardCampaignDistributors from '../../../db/tables/rewardCampaignDistributors.js';
|
|
10
|
+
import * as RewardCampaigns from '../../../db/tables/rewardCampaigns.js';
|
|
11
|
+
import * as RewardEligibilityAssociations from '../../../db/tables/rewardEligibilityAssociations.js';
|
|
8
12
|
import * as Auth from '../../../internal/Auth.js';
|
|
9
13
|
import * as Cache from '../../../internal/Cache.js';
|
|
10
14
|
import * as Cursor from '../../../internal/Cursor.js';
|
|
11
15
|
import * as EarnRates from '../../../internal/EarnRates.js';
|
|
16
|
+
import * as EarnSharePrices from '../../../internal/EarnSharePrices.js';
|
|
12
17
|
import * as EarnVaults from '../../../internal/EarnVaults.js';
|
|
13
18
|
import * as OpenApi from '../../../internal/OpenApi.js';
|
|
19
|
+
import * as RewardRead from '../../../internal/rewards/Read.js';
|
|
14
20
|
import * as Response from '../../../internal/Response.js';
|
|
15
21
|
import * as Schema from '../../../internal/Schema.js';
|
|
16
22
|
import * as Store from '../../../internal/Store.js';
|
|
@@ -19,10 +25,31 @@ import * as Timing from '../../../internal/Timing.js';
|
|
|
19
25
|
import * as Ttl from '../../../internal/Ttl.js';
|
|
20
26
|
import * as Value from '../../../internal/Value.js';
|
|
21
27
|
import * as VerifiedTokens from '../../../internal/VerifiedTokens.js';
|
|
28
|
+
import * as Viem from '../../../internal/Viem.js';
|
|
22
29
|
import * as FxOracle from '../FxOracle.js';
|
|
23
30
|
import * as Tokens from './tokens.js';
|
|
24
31
|
import * as Valuation from './valuation.js';
|
|
25
32
|
const deployedSignature = '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)';
|
|
33
|
+
// Historical factories for this signature, verified against upstream deployments
|
|
34
|
+
// and compiled EarnFactory releases. See docs/earn-discovery.md before updating.
|
|
35
|
+
const deploymentFactories = {
|
|
36
|
+
4217: [
|
|
37
|
+
'0x5b972d2490d06e436982fab77612fd9987f097d0',
|
|
38
|
+
'0x75b20eafdbd3dd974d00b573fd72852ab0237afd',
|
|
39
|
+
],
|
|
40
|
+
42431: [
|
|
41
|
+
'0x0f9ccbc97563a179f5f0886f89ee51c9185f6ec4',
|
|
42
|
+
'0x2aa26b7e24e6f1fb2d539d527b8f1bb5cacfa288',
|
|
43
|
+
'0x4990c74ae874f2b0fd4938662e2cdb8ca4c27887',
|
|
44
|
+
'0x518d4fbd5334bb7ff67c6ebcb67a7d60e1ef8d5d',
|
|
45
|
+
'0x6742345070be5a20ce05f53b6d08d071162c0ef8',
|
|
46
|
+
'0x846b8479d64691ff61c05137dc580a1ecdc188c5',
|
|
47
|
+
'0xb4944264260a6412351d64653f65d2c27d9cb038',
|
|
48
|
+
'0xb4ecb65a57e3585c3699c1617c2abb5de35a697d',
|
|
49
|
+
'0xb5e53c6b17c6f3a380ad94f5417c5e541dfeefac',
|
|
50
|
+
'0xe8fd5b183021ba3f6d3197c5b4238c93561b1b7a',
|
|
51
|
+
],
|
|
52
|
+
};
|
|
26
53
|
const depositedSignature = 'event Deposited(address indexed caller,address indexed receiver,uint256 assets,uint256 earnShares)';
|
|
27
54
|
const redeemedSignature = 'event Redeemed(address indexed caller,address indexed receiver,uint256 earnShares,uint256 assets)';
|
|
28
55
|
const withdrewExactSignature = 'event WithdrewExact(address indexed caller,address indexed receiver,uint256 assets,uint256 earnSharesBurned)';
|
|
@@ -30,17 +57,28 @@ const redeemFinalizedSignature = 'event RedeemFinalized(bytes32 indexed requestI
|
|
|
30
57
|
const redeemCancelledSignature = 'event RedeemCancelled(bytes32 indexed requestId,address indexed receiver,uint256 earnShares)';
|
|
31
58
|
const redeemRequestedSignature = 'event RedeemRequested(bytes32 indexed requestId,address indexed requester,address indexed receiver,uint256 earnShares)';
|
|
32
59
|
const venueSharesDepositedSignature = 'event VenueSharesDeposited(address indexed caller,address indexed receiver,uint256 requestedVenueShares,uint256 receivedVenueShares,uint256 earnShares)';
|
|
60
|
+
const unspentReturnedSignature = 'event UnspentReturned(address indexed treasury,uint256 earnShares)';
|
|
33
61
|
const maxScannedDeployments = 250;
|
|
34
62
|
const scanLimit = 50;
|
|
35
63
|
// Concurrent metadata reads in one macrotask collapse into one deployless
|
|
36
64
|
// multicall; an await between small chunks keeps each call under the RPC limit.
|
|
37
65
|
const tokenReadChunkSize = 20;
|
|
66
|
+
const tempoStateAddress = '0x1c00000000000000000000000000000000000000';
|
|
67
|
+
const tempoStateAbi = parseAbi(['function tempoBlockNumber() view returns (uint64)']);
|
|
68
|
+
const zonePortalAbi = parseAbi(['function lastSyncedTempoBlockNumber() view returns (uint64)']);
|
|
69
|
+
const tokenPositionAbi = parseAbi(['function balanceOf(address account) view returns (uint256)']);
|
|
38
70
|
/** Block boundary that includes all indexed history. */
|
|
39
71
|
const beforeFirstBlockNumber = -1;
|
|
40
72
|
/** Vault TVL is reported in USD only; the API exposes no denomination parameter. */
|
|
41
73
|
const tvlDenomination = 'USD';
|
|
42
74
|
/** `Valuation.valuationFor` floors to 6 dp, so 6 is the precision a valued amount carries. */
|
|
43
75
|
const tvlDecimals = 6;
|
|
76
|
+
function toRewardEligibilityAssociation(record) {
|
|
77
|
+
return {
|
|
78
|
+
...record,
|
|
79
|
+
id: `${record.vaultAddress}-${record.walletAddress}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
44
82
|
/** Returns the smallest useful live-discovery batch. */
|
|
45
83
|
export function discoveryBatchLimit(options) {
|
|
46
84
|
const needed = options.limit + 1 - options.matches;
|
|
@@ -54,6 +92,78 @@ export function hasZoneAccess(options) {
|
|
|
54
92
|
/** Zod schemas owned by the public Earn-vault resource. */
|
|
55
93
|
export var schema;
|
|
56
94
|
(function (schema) {
|
|
95
|
+
/** Schemas for the registerRewardEligibility operation. */
|
|
96
|
+
let registerRewardEligibility;
|
|
97
|
+
(function (registerRewardEligibility) {
|
|
98
|
+
/** Wallet and vault association to register for reward eligibility. */
|
|
99
|
+
registerRewardEligibility.Body = z
|
|
100
|
+
.strictObject({
|
|
101
|
+
chainId: Schema.ChainId.check(z.describe('Chain containing the Earn vault.'), z.meta({ examples: [4217] })),
|
|
102
|
+
transactionHash: z.optional(Schema.hash(`0x${'33'.repeat(32)}`)),
|
|
103
|
+
vaultAddress: Schema.Address.check(z.describe('Earn vault contract address.'), z.meta({ examples: ['0x59d27987bc7cc1521bba5f688a170c65840cbf43'] })),
|
|
104
|
+
walletAddress: Schema.Address.check(z.describe('Wallet to register for rewards.'), z.meta({ examples: ['0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6'] })),
|
|
105
|
+
})
|
|
106
|
+
.check(z.describe('Reward eligibility registration.'));
|
|
107
|
+
/** Persisted reward eligibility association. */
|
|
108
|
+
registerRewardEligibility.Association = z
|
|
109
|
+
.strictObject({
|
|
110
|
+
chainId: Schema.ChainId,
|
|
111
|
+
firstRegisteredAt: z.iso
|
|
112
|
+
.datetime()
|
|
113
|
+
.check(z.describe('When the association was first registered.'), z.meta({ examples: ['2026-08-25T20:00:00.000Z'] })),
|
|
114
|
+
id: z.string().check(z.describe('Stable reward eligibility association identifier.'), z.meta({
|
|
115
|
+
examples: [
|
|
116
|
+
'0x59d27987bc7cc1521bba5f688a170c65840cbf43-0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6',
|
|
117
|
+
],
|
|
118
|
+
})),
|
|
119
|
+
latestRegisteredAt: z.iso
|
|
120
|
+
.datetime()
|
|
121
|
+
.check(z.describe('When the association was most recently registered.'), z.meta({ examples: ['2026-08-25T20:00:00.000Z'] })),
|
|
122
|
+
registrationOrder: z
|
|
123
|
+
.string()
|
|
124
|
+
.check(z.regex(/^\d+$/), z.describe('Monotonic registration order.'), z.meta({ examples: ['42'] })),
|
|
125
|
+
transactionHash: z.optional(Schema.hash(`0x${'33'.repeat(32)}`)),
|
|
126
|
+
vaultAddress: Schema.Address,
|
|
127
|
+
walletAddress: Schema.Address,
|
|
128
|
+
})
|
|
129
|
+
.check(z.describe('Persisted reward eligibility association.'));
|
|
130
|
+
/** Persisted reward eligibility registration result. */
|
|
131
|
+
registerRewardEligibility.Response = z
|
|
132
|
+
.strictObject({
|
|
133
|
+
association: registerRewardEligibility.Association,
|
|
134
|
+
created: z
|
|
135
|
+
.boolean()
|
|
136
|
+
.check(z.describe('Whether this request created the association.'), z.meta({ examples: [true] })),
|
|
137
|
+
})
|
|
138
|
+
.check(z.describe('Persisted reward eligibility registration result.'));
|
|
139
|
+
})(registerRewardEligibility = schema.registerRewardEligibility || (schema.registerRewardEligibility = {}));
|
|
140
|
+
/** Schemas for the getRewardEligibility operation. */
|
|
141
|
+
let getRewardEligibility;
|
|
142
|
+
(function (getRewardEligibility) {
|
|
143
|
+
const Limit = z
|
|
144
|
+
._default(z.pipe(z.coerce.number().check(z.int(), z.gte(Schema.minLimit)), z.transform((value) => Math.min(value, 100))), 10)
|
|
145
|
+
.check(z.describe('How many items to return per page (5 to 100, default 10). Use `nextCursor` to fetch more.'), z.meta({ examples: [10] }));
|
|
146
|
+
/** Selects one chain and vault eligibility snapshot page. */
|
|
147
|
+
getRewardEligibility.Query = z
|
|
148
|
+
.strictObject({
|
|
149
|
+
chainId: Schema.ChainId.check(z.describe('Chain containing the Earn vault.')),
|
|
150
|
+
cursor: Schema.Cursor,
|
|
151
|
+
limit: Limit,
|
|
152
|
+
vaultAddress: Schema.Address.check(z.describe('Earn vault contract address.')),
|
|
153
|
+
})
|
|
154
|
+
.check(z.describe('Reward eligibility page selector.'));
|
|
155
|
+
/** One page of eligible wallets at the cursor's fixed checkpoint. */
|
|
156
|
+
getRewardEligibility.Response = z
|
|
157
|
+
.strictObject({
|
|
158
|
+
chainId: Schema.ChainId,
|
|
159
|
+
data: z
|
|
160
|
+
.array(Schema.Address)
|
|
161
|
+
.check(z.describe('Eligible wallet addresses in registration order.')),
|
|
162
|
+
nextCursor: Schema.NextCursor,
|
|
163
|
+
vaultAddress: Schema.Address,
|
|
164
|
+
})
|
|
165
|
+
.check(z.describe('A fixed-snapshot page of eligible wallet addresses.'));
|
|
166
|
+
})(getRewardEligibility = schema.getRewardEligibility || (schema.getRewardEligibility = {}));
|
|
57
167
|
const capability = z
|
|
58
168
|
.enum([
|
|
59
169
|
'asyncRedeem',
|
|
@@ -69,57 +179,97 @@ export var schema;
|
|
|
69
179
|
const engineType = z
|
|
70
180
|
.enum(['erc4626', 'veda'])
|
|
71
181
|
.check(z.describe('Inferred vault engine type.'), z.meta({ examples: ['erc4626'] }));
|
|
72
|
-
const engine = Schema.describe(z.strictObject({
|
|
73
|
-
address: Schema.Address.check(z.describe('Current vault engine contract address.'), z.meta({ examples: ['
|
|
182
|
+
const engine = OpenApi.component(Schema.describe(z.strictObject({
|
|
183
|
+
address: Schema.Address.check(z.describe('Current vault engine contract address.'), z.meta({ examples: ['0x59d27987bc7cc1521bba5f688a170c65840cbf43'] })),
|
|
74
184
|
type: z
|
|
75
185
|
.nullable(engineType)
|
|
76
186
|
.check(z.describe('Inferred engine type, or null when it is unknown.')),
|
|
77
187
|
venue: z
|
|
78
|
-
.nullable(Schema.Address.check(z.describe('Yield venue contract bound to the engine.'), z.meta({ examples: ['
|
|
188
|
+
.nullable(Schema.Address.check(z.describe('Yield venue contract bound to the engine.'), z.meta({ examples: ['0x9a044ae05e5e6290dcf56afd69548565e957a626'] })))
|
|
79
189
|
.check(z.describe('Yield venue, or null when the engine does not expose one.')),
|
|
80
|
-
}), 'Current vault engine.');
|
|
190
|
+
}), 'Current vault engine.'), 'EarnVaultEngine');
|
|
81
191
|
const include = z
|
|
82
192
|
.enum(['access', 'apy', 'capabilities', 'token.logoUri', 'tvl', 'zone', 'zones'])
|
|
83
193
|
.check(z.describe('Optional vault fields to embed via `include`.'));
|
|
84
194
|
const includeQuery = Schema.includeQuery(include, 'Comma-separated vault fields to include, such as `apy,tvl`.');
|
|
195
|
+
const aprRatio = z
|
|
196
|
+
.string()
|
|
197
|
+
.check(z.regex(/^\d+(\.\d+)?$/), z.describe('Annual percentage rate as a non-negative decimal ratio.'), z.meta({ examples: ['0.0195'] }));
|
|
198
|
+
const reward = z.strictObject({
|
|
199
|
+
apr: z
|
|
200
|
+
.nullable(aprRatio)
|
|
201
|
+
.check(z.describe('Current reward APR, or null before its first calculation.')),
|
|
202
|
+
asset: z
|
|
203
|
+
.strictObject({
|
|
204
|
+
address: Schema.Address,
|
|
205
|
+
chainId: Schema.ChainId,
|
|
206
|
+
decimals: z
|
|
207
|
+
.number()
|
|
208
|
+
.check(z.int(), z.nonnegative(), z.describe('Reward asset decimal places.'), z.meta({ examples: [18] })),
|
|
209
|
+
})
|
|
210
|
+
.check(z.describe('EarnShare token distributed by the reward campaign.')),
|
|
211
|
+
calculatedThrough: z
|
|
212
|
+
.optional(z.number().check(z.int(), z.nonnegative()))
|
|
213
|
+
.check(z.describe('Unix timestamp through which a calculated reward APR applies.'), z.meta({ examples: [1788134700] })),
|
|
214
|
+
campaignId: z
|
|
215
|
+
.string()
|
|
216
|
+
.check(z.describe('EarnVault address that identifies the reward campaign.'), z.meta({ examples: ['0x1000000000000000000000000000000000000001'] })),
|
|
217
|
+
endsAt: z
|
|
218
|
+
.number()
|
|
219
|
+
.check(z.int(), z.nonnegative(), z.describe('Exclusive campaign end as a Unix timestamp.'), z.meta({ examples: [1790812800] })),
|
|
220
|
+
startsAt: z
|
|
221
|
+
.number()
|
|
222
|
+
.check(z.int(), z.nonnegative(), z.describe('Inclusive campaign start as a Unix timestamp.'), z.meta({ examples: [1788134400] })),
|
|
223
|
+
targetTotalApr: aprRatio.check(z.describe('Configured target for combined observed vault yield and Merkle rewards.'), z.meta({ examples: ['0.0700'] })),
|
|
224
|
+
});
|
|
225
|
+
const apy = z.strictObject({
|
|
226
|
+
asOf: EarnRates.schema.Apy.shape.asOf,
|
|
227
|
+
methodology: EarnRates.schema.Apy.shape.methodology,
|
|
228
|
+
net: EarnRates.schema.Apy.shape.net.check(z.describe('Higher of observed vault APY and configured reward campaign targets.')),
|
|
229
|
+
rewards: z
|
|
230
|
+
.optional(z.array(reward))
|
|
231
|
+
.check(z.describe('Enabled, registered Merkle rewards. Omitted when reward enrichment is unavailable.')),
|
|
232
|
+
vault: EarnRates.schema.Apy.shape.net.check(z.describe('Observed fee-aware vault APY before reward APR.')),
|
|
233
|
+
window: EarnRates.schema.Apy.shape.window,
|
|
234
|
+
});
|
|
85
235
|
// `apy` and `tvl` need indexer and FX access, so surfaces lacking either
|
|
86
236
|
// select from this reduced set instead.
|
|
87
237
|
const baseInclude = z
|
|
88
238
|
.enum(['access', 'capabilities', 'token.logoUri', 'zone', 'zones'])
|
|
89
239
|
.check(z.describe('Optional vault fields to embed via `include`.'));
|
|
90
240
|
const baseIncludeQuery = Schema.includeQuery(baseInclude, 'Comma-separated vault fields to include, such as `access,zone`.');
|
|
91
|
-
const zone = z
|
|
241
|
+
const zone = OpenApi.component(z
|
|
92
242
|
.strictObject({
|
|
93
|
-
chainId: Schema.ChainId.check(z.describe('Private Zone chain id.'), z.meta({ examples: [
|
|
243
|
+
chainId: Schema.ChainId.check(z.describe('Private Zone chain id.'), z.meta({ examples: [421700001] })),
|
|
94
244
|
inputTokens: z
|
|
95
245
|
.array(Schema.Address)
|
|
96
|
-
.check(z.describe('Tokens accepted by private deposits.'), z.meta({ examples: [['
|
|
246
|
+
.check(z.describe('Tokens accepted by private deposits.'), z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] })),
|
|
97
247
|
name: z
|
|
98
248
|
.string()
|
|
99
|
-
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-
|
|
249
|
+
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-mainnet-internal'] })),
|
|
100
250
|
outputTokens: z
|
|
101
251
|
.array(Schema.Address)
|
|
102
|
-
.check(z.describe('Tokens supported by private redemptions.'), z.meta({ examples: [['
|
|
252
|
+
.check(z.describe('Tokens supported by private redemptions.'), z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] })),
|
|
103
253
|
})
|
|
104
|
-
.check(z.describe('Private Zone route configured for a verified vault.'));
|
|
105
|
-
const zoneRoute = z
|
|
254
|
+
.check(z.describe('Private Zone route configured for a verified vault.')), 'EarnVaultZone');
|
|
255
|
+
const zoneRoute = OpenApi.component(z
|
|
106
256
|
.strictObject({
|
|
107
|
-
chainId: Schema.ChainId.check(z.describe('Private Zone chain id.'), z.meta({ examples: [
|
|
257
|
+
chainId: Schema.ChainId.check(z.describe('Private Zone chain id.'), z.meta({ examples: [421700001] })),
|
|
108
258
|
deploymentBlock: z
|
|
109
259
|
.number()
|
|
110
|
-
.check(z.int(), z.nonnegative(), z.describe('Parent-chain block that deployed the Earn router.'), z.meta({ examples: [
|
|
111
|
-
earnRouter: Schema.Address.check(z.describe('Parent-chain router for this Zone and Earn vault.'), z.meta({ examples: ['
|
|
260
|
+
.check(z.int(), z.nonnegative(), z.describe('Parent-chain block that deployed the Earn router.'), z.meta({ examples: [35822949] })),
|
|
261
|
+
earnRouter: Schema.Address.check(z.describe('Parent-chain router for this Zone and Earn vault.'), z.meta({ examples: ['0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6'] })),
|
|
112
262
|
inputTokens: z
|
|
113
263
|
.array(Schema.Address)
|
|
114
|
-
.check(z.describe('Tokens accepted by private deposits.'), z.meta({ examples: [['
|
|
264
|
+
.check(z.describe('Tokens accepted by private deposits.'), z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] })),
|
|
115
265
|
name: z
|
|
116
266
|
.string()
|
|
117
|
-
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-
|
|
267
|
+
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-mainnet-internal'] })),
|
|
118
268
|
outputTokens: z
|
|
119
269
|
.array(Schema.Address)
|
|
120
|
-
.check(z.describe('Tokens returned by private redemptions.'), z.meta({ examples: [['
|
|
270
|
+
.check(z.describe('Tokens returned by private redemptions.'), z.meta({ examples: [['0x20c0000000000000000000006fd9a167923ba194']] })),
|
|
121
271
|
})
|
|
122
|
-
.check(z.describe('Verified Earn route through one private Zone.'));
|
|
272
|
+
.check(z.describe('Verified Earn route through one private Zone.')), 'EarnVaultZoneRoute');
|
|
123
273
|
const value = z.strictObject({
|
|
124
274
|
amount: Schema.DecimalString.check(z.describe('Value in base units at `decimals` precision.'), z.meta({ examples: ['125288750000'] })),
|
|
125
275
|
currency: z
|
|
@@ -137,33 +287,60 @@ export var schema;
|
|
|
137
287
|
.optional(EarnVaults.schema.Discovery.shape.access)
|
|
138
288
|
.check(z.describe('Vault share-token access, when requested.')),
|
|
139
289
|
apy: z
|
|
140
|
-
.optional(z.nullable(
|
|
141
|
-
.check(z.describe('Annualized
|
|
142
|
-
assetToken: Tokens.schema.Token.check(z.describe('Asset accepted by the vault.')
|
|
290
|
+
.optional(z.nullable(apy))
|
|
291
|
+
.check(z.describe('Annualized vault yield over the selected window, plus every available current Merkle reward APR. Null when no component is measurable.')),
|
|
292
|
+
assetToken: Tokens.schema.Token.check(z.describe('Asset accepted by the vault.'), z.meta({
|
|
293
|
+
examples: [
|
|
294
|
+
{
|
|
295
|
+
address: '0x20c0000000000000000000000000000000000000',
|
|
296
|
+
currency: 'USD',
|
|
297
|
+
decimals: 6,
|
|
298
|
+
id: '0x20c0000000000000000000000000000000000000',
|
|
299
|
+
name: 'PathUSD',
|
|
300
|
+
symbol: 'pathUSD',
|
|
301
|
+
verified: true,
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
})),
|
|
143
305
|
capabilities: z
|
|
144
306
|
.optional(EarnVaults.schema.Discovery.shape.capabilities)
|
|
145
307
|
.check(z.describe('Vault capabilities, when requested.')),
|
|
146
308
|
description: z
|
|
147
309
|
.nullable(z.string())
|
|
148
|
-
.check(z.describe('Curated vault description, or null when the vault is not verified.'), z.meta({ examples: ['
|
|
310
|
+
.check(z.describe('Curated vault description, or null when the vault is not verified.'), z.meta({ examples: ['deelUSD deposited into the canonical Tempo Earn deployment.'] })),
|
|
149
311
|
engine,
|
|
150
|
-
id: Schema.Address.check(z.describe('Stable vault id, equal to the lowercase vault address.'), z.meta({ examples: ['
|
|
312
|
+
id: Schema.Address.check(z.describe('Stable vault id, equal to the lowercase vault address.'), z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] })),
|
|
151
313
|
instantLiquidity: EarnVaults.schema.Discovery.shape.instantLiquidity.check(z.describe('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.')),
|
|
314
|
+
instantLiquidityValue: z
|
|
315
|
+
.optional(z.nullable(value))
|
|
316
|
+
.check(z.describe('Instant liquidity valued in USD, when requested via `include=tvl`, or null when liquidity is unavailable or the asset has no priced display currency.')),
|
|
152
317
|
label: z
|
|
153
318
|
.string()
|
|
154
|
-
.check(z.describe('Vault display label.'), z.meta({ examples: ['
|
|
319
|
+
.check(z.describe('Vault display label.'), z.meta({ examples: ['deelUSD Earn'] })),
|
|
155
320
|
sharePrice: z
|
|
156
321
|
.nullable(value)
|
|
157
322
|
.check(z.describe('Assets returned for one whole earn share, in the asset display currency, or null when the engine cannot quote an exit.')),
|
|
158
|
-
shareToken: Tokens.schema.Token.check(z.describe('Token representing vault shares.')
|
|
323
|
+
shareToken: Tokens.schema.Token.check(z.describe('Token representing vault shares.'), z.meta({
|
|
324
|
+
examples: [
|
|
325
|
+
{
|
|
326
|
+
address: '0x20c000000000000000000000c3268d803b51d448',
|
|
327
|
+
currency: 'USD',
|
|
328
|
+
decimals: 6,
|
|
329
|
+
id: '0x20c000000000000000000000c3268d803b51d448',
|
|
330
|
+
name: 'Sentora pathUSD (Earn)',
|
|
331
|
+
symbol: 'senpathUSDE',
|
|
332
|
+
verified: false,
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
})),
|
|
159
336
|
slug: z
|
|
160
337
|
.nullable(z.string())
|
|
161
|
-
.check(z.describe('Curated URL slug, or null when the vault is not verified.'), z.meta({ examples: ['
|
|
338
|
+
.check(z.describe('Curated URL slug, or null when the vault is not verified.'), z.meta({ examples: ['deelusd-earn'] })),
|
|
162
339
|
state: EarnVaults.schema.Discovery.shape.state,
|
|
163
340
|
tvl: z
|
|
164
341
|
.optional(z.nullable(value))
|
|
165
342
|
.check(z.describe('Total assets valued in USD, when requested via `include=tvl`, or null when the asset has no priced display currency.')),
|
|
166
|
-
vaultAddress: Schema.Address.check(z.describe('Earn vault contract address.'), z.meta({ examples: ['
|
|
343
|
+
vaultAddress: Schema.Address.check(z.describe('Earn vault contract address.'), z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] })),
|
|
167
344
|
verified: z
|
|
168
345
|
.boolean()
|
|
169
346
|
.check(z.describe('Whether this vault is in the curated earn registry.'), z.meta({ examples: [true] })),
|
|
@@ -174,21 +351,21 @@ export var schema;
|
|
|
174
351
|
examples: [
|
|
175
352
|
[
|
|
176
353
|
{
|
|
177
|
-
chainId:
|
|
178
|
-
deploymentBlock:
|
|
179
|
-
earnRouter: '
|
|
180
|
-
inputTokens: ['
|
|
181
|
-
name: 'zone-
|
|
182
|
-
outputTokens: ['
|
|
354
|
+
chainId: 421700001,
|
|
355
|
+
deploymentBlock: 35822949,
|
|
356
|
+
earnRouter: '0x8117e0ba6239b9695f780deb010f72a2fa4bdfb6',
|
|
357
|
+
inputTokens: ['0x20c0000000000000000000006fd9a167923ba194'],
|
|
358
|
+
name: 'zone-mainnet-internal',
|
|
359
|
+
outputTokens: ['0x20c0000000000000000000006fd9a167923ba194'],
|
|
183
360
|
},
|
|
184
361
|
],
|
|
185
362
|
],
|
|
186
363
|
})),
|
|
187
364
|
});
|
|
188
365
|
/** One compatible Earn vault resolved from current chain state. */
|
|
189
|
-
schema.Vault = Schema.describe(vault, 'A compatible earn vault resolved from chain state.');
|
|
366
|
+
schema.Vault = OpenApi.component(Schema.describe(vault, 'A compatible earn vault resolved from chain state.'), 'EarnVault');
|
|
190
367
|
/** One registry-curated Earn vault. */
|
|
191
|
-
schema.VerifiedVault = Schema.describe(z.extend(vault, {
|
|
368
|
+
schema.VerifiedVault = OpenApi.component(Schema.describe(z.extend(vault, {
|
|
192
369
|
engine: z.extend(engine, { type: engineType }),
|
|
193
370
|
slug: z
|
|
194
371
|
.string()
|
|
@@ -196,33 +373,98 @@ export var schema;
|
|
|
196
373
|
verified: z
|
|
197
374
|
.literal(true)
|
|
198
375
|
.check(z.describe('This vault is in the curated earn registry.'), z.meta({ examples: [true] })),
|
|
199
|
-
}), 'A registry-curated earn vault resolved from chain state.');
|
|
376
|
+
}), 'A registry-curated earn vault resolved from chain state.'), 'VerifiedEarnVault');
|
|
200
377
|
const position = z.strictObject({
|
|
201
378
|
account: Schema.Address.check(z.describe('Account whose earn position was read.'), z.meta({ examples: ['0xbe058e1c4df8a4366a387bf595b284246a93039e'] })),
|
|
202
|
-
assetAllowance: Schema.DecimalString.check(z.describe('Assets the vault may spend from
|
|
203
|
-
assetBalance: Schema.DecimalString.check(z.describe('Assets this account
|
|
204
|
-
assetToken: Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50').check(z.describe('TIP-20 asset token accepted by the vault.')),
|
|
379
|
+
assetAllowance: Schema.DecimalString.check(z.describe('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.'), z.meta({ examples: ['0'] })),
|
|
380
|
+
assetBalance: Schema.DecimalString.check(z.describe('Assets held by this account at the observation block, in asset base units.'), z.meta({ examples: ['250000000'] })),
|
|
381
|
+
assetToken: Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50').check(z.describe('TIP-20 asset token accepted by the vault or its selected Zone route.')),
|
|
382
|
+
chainId: Schema.ChainId.check(z.describe('Chain containing the account position.'), z.meta({ examples: [42431] })),
|
|
205
383
|
id: Schema.Address.check(z.describe('Stable resource ID for this vault position, equal to the account address.'), z.meta({ examples: ['0xbe058e1c4df8a4366a387bf595b284246a93039e'] })),
|
|
206
|
-
shareAllowance: Schema.DecimalString.check(z.describe('Earn shares the vault may spend from
|
|
207
|
-
shareBalance: Schema.DecimalString.check(z.describe('Earn shares this account
|
|
384
|
+
shareAllowance: Schema.DecimalString.check(z.describe('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.'), z.meta({ examples: ['0'] })),
|
|
385
|
+
shareBalance: Schema.DecimalString.check(z.describe('Earn shares held by this account at the observation block, in share base units.'), z.meta({ examples: ['99500000'] })),
|
|
208
386
|
shareToken: Schema.tokenAddress('0x20c000000000000000000000300e14ab91a10769').check(z.describe('TIP-20 token representing earn shares.')),
|
|
209
|
-
value: Schema.DecimalString.check(z.describe('
|
|
387
|
+
value: Schema.DecimalString.check(z.describe('Asset value of this account’s earn shares at the observation block, including fees, in `valueToken` base units.'), z.meta({ examples: ['100000000'] })),
|
|
388
|
+
valueToken: Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50').check(z.describe('TIP-20 asset denominating `value` on the vault’s parent chain.')),
|
|
210
389
|
});
|
|
211
|
-
const
|
|
212
|
-
|
|
390
|
+
const positionApy = z
|
|
391
|
+
.strictObject({
|
|
392
|
+
breakdown: z
|
|
393
|
+
.array(z
|
|
394
|
+
.strictObject({
|
|
395
|
+
assetAmount: z
|
|
396
|
+
.strictObject({
|
|
397
|
+
baseUnits: Schema.DecimalString.check(z.describe('Position amount in vault asset base units.'), z.meta({ examples: ['25000000000'] })),
|
|
398
|
+
decimals: z
|
|
399
|
+
.number()
|
|
400
|
+
.check(z.int(), z.nonnegative(), z.describe('Vault asset decimal places.'), z.meta({ examples: [6] })),
|
|
401
|
+
formatted: z
|
|
402
|
+
.string()
|
|
403
|
+
.check(z.regex(/^\d+(\.\d+)?$/), z.describe('Position amount rendered in whole vault asset units.'), z.meta({ examples: ['25000'] })),
|
|
404
|
+
})
|
|
405
|
+
.check(z.describe('Vault asset amount receiving this annual rate.'), z.meta({
|
|
406
|
+
examples: [{ baseUnits: '25000000000', decimals: 6, formatted: '25000' }],
|
|
407
|
+
})),
|
|
408
|
+
net: EarnRates.schema.Apy.shape.net.check(z.describe('Annual rate applied to this position amount.'), z.meta({ examples: ['0.07'] })),
|
|
409
|
+
type: z
|
|
410
|
+
.enum(['base', 'boost'])
|
|
411
|
+
.check(z.describe('Base vault yield or qualified depositor boost.'), z.meta({ examples: ['boost'] })),
|
|
412
|
+
})
|
|
413
|
+
.check(z.describe('Position component receiving one annual rate.')))
|
|
414
|
+
.check(z.describe('Position amounts grouped by the annual rate they receive.'), z.meta({
|
|
415
|
+
examples: [
|
|
416
|
+
[
|
|
417
|
+
{
|
|
418
|
+
assetAmount: {
|
|
419
|
+
baseUnits: '25000000000',
|
|
420
|
+
decimals: 6,
|
|
421
|
+
formatted: '25000',
|
|
422
|
+
},
|
|
423
|
+
net: '0.07',
|
|
424
|
+
type: 'boost',
|
|
425
|
+
},
|
|
426
|
+
],
|
|
427
|
+
],
|
|
428
|
+
})),
|
|
429
|
+
net: EarnRates.schema.Apy.shape.net.check(z.describe('Balance-weighted annual rate for this wallet position.'), z.meta({ examples: ['0.0616666666666667'] })),
|
|
430
|
+
})
|
|
431
|
+
.check(z.describe('Wallet-specific effective APY combining live position amounts with qualification from the latest delivered reward snapshot.'));
|
|
432
|
+
const lifetimeCashFlows = z.union([
|
|
433
|
+
z.strictObject({
|
|
434
|
+
status: z
|
|
435
|
+
.literal('complete')
|
|
436
|
+
.check(z.describe('Cash flows are complete through the indexed boundary.'), z.meta({ examples: ['complete'] })),
|
|
437
|
+
totalDeposited: Schema.DecimalString.check(z.describe('Assets deposited with this account as receiver over indexed vault history.')),
|
|
438
|
+
totalWithdrawn: Schema.DecimalString.check(z.describe('Assets returned by completed withdrawals over indexed vault history.')),
|
|
439
|
+
}),
|
|
440
|
+
z.strictObject({
|
|
441
|
+
status: z
|
|
442
|
+
.literal('incomplete_history')
|
|
443
|
+
.check(z.describe('Cash flows are omitted because asset deposit history is incomplete.'), z.meta({ examples: ['incomplete_history'] })),
|
|
444
|
+
}),
|
|
445
|
+
]);
|
|
446
|
+
const addressPosition = OpenApi.component(z
|
|
447
|
+
.strictObject({
|
|
448
|
+
assetAmount: value.check(z.describe('Current asset value of the held shares, including fees, in `valueToken` units.')),
|
|
213
449
|
assetToken: Tokens.schema.Token.check(z.describe('Asset accepted by the vault.')),
|
|
214
|
-
|
|
450
|
+
chainId: Schema.ChainId.check(z.describe('Chain containing the held shares.'), z.meta({ examples: [42431] })),
|
|
451
|
+
id: Schema.Address.check(z.describe('Stable resource ID for this position, equal to the vault address.'), z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] })),
|
|
452
|
+
lifetimeCashFlows: z
|
|
453
|
+
.optional(lifetimeCashFlows)
|
|
454
|
+
.check(z.describe('Lifetime deposits and completed withdrawals, when requested.')),
|
|
215
455
|
shareAmount: value.check(z.describe('Earn share balance this account holds, in `shareToken` units.')),
|
|
216
456
|
shareToken: Tokens.schema.Token.check(z.describe('Token representing vault shares.')),
|
|
217
457
|
valuation: z
|
|
218
458
|
.optional(z.nullable(Valuation.schema.Value))
|
|
219
459
|
.check(z.describe('The position’s nominal value when `valuation.currency` is requested, or `null` when ' +
|
|
220
460
|
'the asset token is unverified, its display currency has no rate, or rates were unavailable.')),
|
|
221
|
-
|
|
461
|
+
valueToken: Tokens.schema.Token.check(z.describe('Parent-chain asset denominating `assetAmount`.')),
|
|
462
|
+
vaultAddress: Schema.Address.check(z.describe('Earn vault contract address holding this position.'), z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] })),
|
|
222
463
|
verified: z
|
|
223
464
|
.boolean()
|
|
224
465
|
.check(z.describe('Whether the vault is in the curated earn registry.'), z.meta({ examples: [true] })),
|
|
225
|
-
})
|
|
466
|
+
})
|
|
467
|
+
.check(z.describe('An account’s position in one earn vault.')), 'EarnAddressPosition');
|
|
226
468
|
const earningsBase = z.strictObject({
|
|
227
469
|
account: Schema.Address.check(z.describe('Account whose vault earnings were calculated.'), z.meta({ examples: ['0x68f94cfca22e5969c0553bbeab00a2acde88939b'] })),
|
|
228
470
|
assetToken: Schema.TokenAddress.check(z.describe('TIP-20 asset token accepted by the vault.'), z.meta({ examples: ['0x20c000000000000000000000ff04042ee92fd449'] })),
|
|
@@ -237,6 +479,8 @@ export var schema;
|
|
|
237
479
|
lifetimeEarnings: z
|
|
238
480
|
.string()
|
|
239
481
|
.check(z.regex(/^-?\d+$/), z.describe('Current share value plus completed redemptions, exact withdrawals, and finalized async assets, minus asset deposits, at the latest indexed block.'), z.meta({ examples: ['0'] })),
|
|
482
|
+
totalDeposited: Schema.DecimalString.check(z.describe('Assets deposited with this account as receiver over complete indexed vault history.'), z.meta({ examples: ['1000000'] })),
|
|
483
|
+
totalWithdrawn: Schema.DecimalString.check(z.describe('Assets returned by completed redemptions and exact withdrawals initiated by this account over complete indexed vault history.'), z.meta({ examples: ['1000000'] })),
|
|
240
484
|
period: z
|
|
241
485
|
.literal('lifetime')
|
|
242
486
|
.check(z.describe('Returns lifetime net asset earnings.'), z.meta({ examples: ['lifetime'] })),
|
|
@@ -274,12 +518,22 @@ export var schema;
|
|
|
274
518
|
}),
|
|
275
519
|
z.extend(earningsBase, {
|
|
276
520
|
period: z
|
|
277
|
-
.
|
|
278
|
-
.check(z.describe('
|
|
521
|
+
.literal('30d')
|
|
522
|
+
.check(z.describe('Trailing period with an unresolved async redemption.'), z.meta({ examples: ['30d'] })),
|
|
279
523
|
status: z
|
|
280
524
|
.literal('pending_redemption')
|
|
281
525
|
.check(z.describe('Earnings are unavailable while an async redemption remains open.'), z.meta({ examples: ['pending_redemption'] })),
|
|
282
526
|
}),
|
|
527
|
+
z.extend(earningsBase, {
|
|
528
|
+
period: z
|
|
529
|
+
.literal('lifetime')
|
|
530
|
+
.check(z.describe('Lifetime period with an unresolved async redemption.'), z.meta({ examples: ['lifetime'] })),
|
|
531
|
+
status: z
|
|
532
|
+
.literal('pending_redemption')
|
|
533
|
+
.check(z.describe('Earnings are unavailable while an async redemption remains open.'), z.meta({ examples: ['pending_redemption'] })),
|
|
534
|
+
totalDeposited: Schema.DecimalString.check(z.describe('Assets deposited over complete indexed vault history.')),
|
|
535
|
+
totalWithdrawn: Schema.DecimalString.check(z.describe('Assets withdrawn over complete indexed vault history.')),
|
|
536
|
+
}),
|
|
283
537
|
]);
|
|
284
538
|
const meta = z
|
|
285
539
|
.object({
|
|
@@ -314,7 +568,7 @@ export var schema;
|
|
|
314
568
|
/** Query parameters for all compatible deployed Earn vaults. */
|
|
315
569
|
getEarnVaults.Query = collectionQuery;
|
|
316
570
|
/** Paginated list of compatible deployed Earn vaults. */
|
|
317
|
-
getEarnVaults.Response = z
|
|
571
|
+
getEarnVaults.Response = OpenApi.component(z
|
|
318
572
|
.strictObject({
|
|
319
573
|
data: z
|
|
320
574
|
.array(schema.Vault)
|
|
@@ -322,7 +576,7 @@ export var schema;
|
|
|
322
576
|
meta: z.optional(meta),
|
|
323
577
|
nextCursor: Schema.NextCursor,
|
|
324
578
|
})
|
|
325
|
-
.check(z.describe('A page of compatible deployed earn vaults.'));
|
|
579
|
+
.check(z.describe('A page of compatible deployed earn vaults.')), 'EarnVaultList');
|
|
326
580
|
})(getEarnVaults = schema.getEarnVaults || (schema.getEarnVaults = {}));
|
|
327
581
|
/** Schemas for the getVerifiedEarnVaults operation. */
|
|
328
582
|
let getVerifiedEarnVaults;
|
|
@@ -332,7 +586,7 @@ export var schema;
|
|
|
332
586
|
/** Query parameters for registry-curated Earn vaults. */
|
|
333
587
|
getVerifiedEarnVaults.Query = collectionQuery;
|
|
334
588
|
/** Paginated list of registry-curated Earn vaults. */
|
|
335
|
-
getVerifiedEarnVaults.Response = z
|
|
589
|
+
getVerifiedEarnVaults.Response = OpenApi.component(z
|
|
336
590
|
.strictObject({
|
|
337
591
|
data: z
|
|
338
592
|
.array(schema.VerifiedVault)
|
|
@@ -340,7 +594,7 @@ export var schema;
|
|
|
340
594
|
meta: z.optional(meta),
|
|
341
595
|
nextCursor: Schema.NextCursor,
|
|
342
596
|
})
|
|
343
|
-
.check(z.describe('A page of registry-curated earn vaults.'));
|
|
597
|
+
.check(z.describe('A page of registry-curated earn vaults.')), 'VerifiedEarnVaultList');
|
|
344
598
|
})(getVerifiedEarnVaults = schema.getVerifiedEarnVaults || (schema.getVerifiedEarnVaults = {}));
|
|
345
599
|
/** Schemas for the getEarnAddressPositions operation. */
|
|
346
600
|
let getEarnAddressPositions;
|
|
@@ -356,6 +610,7 @@ export var schema;
|
|
|
356
610
|
.strictObject({
|
|
357
611
|
chainId: Schema.ChainIdQuery,
|
|
358
612
|
cursor: Schema.Cursor,
|
|
613
|
+
include: Schema.includeQuery(z.enum(['earnings']), 'Comma-separated position fields to include, such as `earnings`. Earnings are unavailable when selecting a private Zone.'),
|
|
359
614
|
limit: Schema.Limit,
|
|
360
615
|
'valuation.currency': Schema.Denomination.check(z.describe('When present, include each position’s nominal value in this denomination. ' +
|
|
361
616
|
'Case-insensitive and must be priced by the configured FX oracle.')),
|
|
@@ -374,7 +629,7 @@ export var schema;
|
|
|
374
629
|
})
|
|
375
630
|
.check(z.describe('Page-level valuation rate provenance.'));
|
|
376
631
|
/** Paginated list of the account's earn vault positions. */
|
|
377
|
-
getEarnAddressPositions.Response = z
|
|
632
|
+
getEarnAddressPositions.Response = OpenApi.component(z
|
|
378
633
|
.strictObject({
|
|
379
634
|
data: z
|
|
380
635
|
.array(addressPosition)
|
|
@@ -382,7 +637,7 @@ export var schema;
|
|
|
382
637
|
meta: z.optional(getEarnAddressPositions.Meta),
|
|
383
638
|
nextCursor: Schema.NextCursor,
|
|
384
639
|
})
|
|
385
|
-
.check(z.describe('A page of the account’s earn vault positions.'));
|
|
640
|
+
.check(z.describe('A page of the account’s earn vault positions.')), 'EarnAddressPositionList');
|
|
386
641
|
})(getEarnAddressPositions = schema.getEarnAddressPositions || (schema.getEarnAddressPositions = {}));
|
|
387
642
|
/** Schemas for the getEarnVault operation. */
|
|
388
643
|
let getEarnVault;
|
|
@@ -400,24 +655,145 @@ export var schema;
|
|
|
400
655
|
.extend(vaultSelector, { 'apy.window': EarnRates.schema.Window })
|
|
401
656
|
.check(z.describe('Query parameters selecting one earn vault.'));
|
|
402
657
|
/** One compatible Earn vault resolved directly from current chain state. */
|
|
403
|
-
getEarnVault.Response = Schema.describe(z.extend(vault, { meta: z.optional(meta) }), 'A compatible earn vault resolved from chain state, with rate provenance for its valued fields.');
|
|
658
|
+
getEarnVault.Response = OpenApi.component(Schema.describe(z.extend(vault, { meta: z.optional(meta) }), 'A compatible earn vault resolved from chain state, with rate provenance for its valued fields.'), 'EarnVaultDetail');
|
|
404
659
|
})(getEarnVault = schema.getEarnVault || (schema.getEarnVault = {}));
|
|
660
|
+
/** Schemas for the getEarnVaultSharePrices operation. */
|
|
661
|
+
let getEarnVaultSharePrices;
|
|
662
|
+
(function (getEarnVaultSharePrices) {
|
|
663
|
+
const timestamp = z.iso.datetime({ offset: true });
|
|
664
|
+
/** Path parameters identifying one Earn vault. */
|
|
665
|
+
getEarnVaultSharePrices.Params = z
|
|
666
|
+
.strictObject({
|
|
667
|
+
vaultId: Schema.address('0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a').check(z.describe('Earn vault contract address.')),
|
|
668
|
+
})
|
|
669
|
+
.check(z.describe('Path parameters identifying one Earn vault share-price series.'));
|
|
670
|
+
/** Query parameters selecting a daily historical share-price range. */
|
|
671
|
+
getEarnVaultSharePrices.Query = z
|
|
672
|
+
.strictObject({
|
|
673
|
+
chainId: Schema.ChainIdQuery,
|
|
674
|
+
from: timestamp.check(z.describe('First daily share-price observation, as an ISO 8601 timestamp.'), z.meta({ examples: ['2026-07-01T00:00:00.000Z'] })),
|
|
675
|
+
interval: z
|
|
676
|
+
._default(z.literal(EarnSharePrices.interval), EarnSharePrices.interval)
|
|
677
|
+
.check(z.describe('Time between share-price observations.'), z.meta({ examples: [EarnSharePrices.interval] })),
|
|
678
|
+
to: timestamp.check(z.describe('Last possible daily share-price observation, as an ISO 8601 timestamp.'), z.meta({ examples: ['2026-07-31T00:00:00.000Z'] })),
|
|
679
|
+
})
|
|
680
|
+
.check(z.refine((query) => Date.parse(query.from) <= Date.parse(query.to), {
|
|
681
|
+
error: '`from` must be before or equal to `to`.',
|
|
682
|
+
path: ['from'],
|
|
683
|
+
}), z.refine((query) => Math.floor((Date.parse(query.to) - Date.parse(query.from)) / Ttl.days(1)) + 1 <=
|
|
684
|
+
EarnSharePrices.maxPoints, {
|
|
685
|
+
error: `Share-price series are limited to ${EarnSharePrices.maxPoints} daily observations.`,
|
|
686
|
+
path: ['to'],
|
|
687
|
+
}), z.describe('Query parameters selecting an Earn vault share-price series.'));
|
|
688
|
+
const Point = z
|
|
689
|
+
.strictObject({
|
|
690
|
+
sharePrice: value.check(z.describe('Assets returned for one whole Earn share at the observation block.')),
|
|
691
|
+
timestamp: z.iso
|
|
692
|
+
.datetime()
|
|
693
|
+
.check(z.describe('Requested daily observation timestamp.'), z.meta({ examples: ['2026-07-01T00:00:00.000Z'] })),
|
|
694
|
+
})
|
|
695
|
+
.check(z.describe('One historical Earn vault share price.'));
|
|
696
|
+
/** Daily share prices for one Earn vault. */
|
|
697
|
+
getEarnVaultSharePrices.Response = OpenApi.component(z
|
|
698
|
+
.strictObject({
|
|
699
|
+
data: z.array(Point).check(z.describe('Daily Earn vault share prices.'), z.meta({
|
|
700
|
+
examples: [
|
|
701
|
+
[
|
|
702
|
+
{
|
|
703
|
+
sharePrice: {
|
|
704
|
+
amount: '1000000',
|
|
705
|
+
currency: 'USD',
|
|
706
|
+
decimals: 6,
|
|
707
|
+
formatted: '1',
|
|
708
|
+
},
|
|
709
|
+
timestamp: '2026-07-01T00:00:00.000Z',
|
|
710
|
+
},
|
|
711
|
+
],
|
|
712
|
+
],
|
|
713
|
+
})),
|
|
714
|
+
})
|
|
715
|
+
.check(z.describe('Daily historical share prices for one Earn vault.')), 'EarnVaultSharePriceList');
|
|
716
|
+
})(getEarnVaultSharePrices = schema.getEarnVaultSharePrices || (schema.getEarnVaultSharePrices = {}));
|
|
405
717
|
/** Schemas for the getEarnVaultPosition operation. */
|
|
406
718
|
let getEarnVaultPosition;
|
|
407
719
|
(function (getEarnVaultPosition) {
|
|
720
|
+
const asOf = z.iso.datetime({ offset: true });
|
|
408
721
|
/** Path parameters identifying the Earn vault and account. */
|
|
409
722
|
getEarnVaultPosition.Params = z
|
|
410
723
|
.strictObject({
|
|
411
724
|
address: Schema.Address.check(z.describe('Account whose earn position to read.')),
|
|
412
|
-
vaultId: Schema.address('
|
|
725
|
+
vaultId: Schema.address('0x4f94590b636f5878bce585e82379de81e1ec174f').check(z.describe('Earn vault contract address.')),
|
|
413
726
|
})
|
|
414
727
|
.check(z.describe('Path parameters identifying an earn vault position.'));
|
|
415
728
|
/** Query parameters selecting the chain containing the vault. */
|
|
416
729
|
getEarnVaultPosition.Query = z
|
|
417
|
-
.strictObject({
|
|
730
|
+
.strictObject({
|
|
731
|
+
asOf: z
|
|
732
|
+
.optional(asOf)
|
|
733
|
+
.check(z.describe('ISO 8601 timestamp at which to read the position. Resolves the latest indexed block at or before this time.'), z.meta({ examples: ['2026-07-21T09:00:00.000Z'] })),
|
|
734
|
+
chainId: Schema.ChainIdQuery,
|
|
735
|
+
include: Schema.includeQuery(z.enum(['apy', 'rewards', 'rewards.proof']), 'Include wallet-specific APY or current reward state, optionally with the latest recovery proof.'),
|
|
736
|
+
})
|
|
418
737
|
.check(z.describe('Query parameters selecting an earn vault position.'));
|
|
419
|
-
|
|
420
|
-
|
|
738
|
+
const Block = z
|
|
739
|
+
.strictObject({
|
|
740
|
+
number: z
|
|
741
|
+
.number()
|
|
742
|
+
.check(z.int(), z.nonnegative(), z.describe('Indexed observation block.'), z.meta({ examples: [31039238] })),
|
|
743
|
+
timestamp: z.iso
|
|
744
|
+
.datetime()
|
|
745
|
+
.check(z.describe('Timestamp of the indexed observation block.'), z.meta({ examples: ['2026-07-21T09:00:00.000Z'] })),
|
|
746
|
+
})
|
|
747
|
+
.check(z.describe('Indexed block used for a historical Earn position observation.'));
|
|
748
|
+
/** Current or historical asset and Earn-share state for one account in one vault. */
|
|
749
|
+
const Rewards = z
|
|
750
|
+
.strictObject({
|
|
751
|
+
cumulativeEntitlement: Schema.DecimalString.check(z.describe('Cumulative EarnShare entitlement.')),
|
|
752
|
+
cumulativePaid: Schema.DecimalString.check(z.describe('Cumulative EarnShare paid.')),
|
|
753
|
+
deferral: z
|
|
754
|
+
.optional(z.string())
|
|
755
|
+
.check(z.describe('Current payout delivery exception.'), z.meta({ examples: ['transfer_unavailable'] })),
|
|
756
|
+
pending: Schema.DecimalString.check(z.describe('EarnShare still owed.')),
|
|
757
|
+
proof: z
|
|
758
|
+
.optional(z.strictObject({
|
|
759
|
+
cumulativeAmount: Schema.DecimalString,
|
|
760
|
+
distributorAddress: Schema.Address,
|
|
761
|
+
proof: z.array(Schema.Hash),
|
|
762
|
+
rootVersion: Schema.DecimalString,
|
|
763
|
+
statementHash: Schema.Hash,
|
|
764
|
+
}))
|
|
765
|
+
.check(z.describe('Permissionless recovery proof against the confirmed root.')),
|
|
766
|
+
})
|
|
767
|
+
.check(z.describe('Current Earn reward state.'));
|
|
768
|
+
getEarnVaultPosition.Response = OpenApi.component(Schema.describe(z.extend(position, {
|
|
769
|
+
apy: z.optional(z.nullable(positionApy)).check(z.describe('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.'), z.meta({
|
|
770
|
+
examples: [
|
|
771
|
+
{
|
|
772
|
+
breakdown: [
|
|
773
|
+
{
|
|
774
|
+
assetAmount: {
|
|
775
|
+
baseUnits: '25000000000',
|
|
776
|
+
decimals: 6,
|
|
777
|
+
formatted: '25000',
|
|
778
|
+
},
|
|
779
|
+
net: '0.07',
|
|
780
|
+
type: 'boost',
|
|
781
|
+
},
|
|
782
|
+
],
|
|
783
|
+
net: '0.07',
|
|
784
|
+
},
|
|
785
|
+
],
|
|
786
|
+
})),
|
|
787
|
+
asOf: z
|
|
788
|
+
.optional(asOf)
|
|
789
|
+
.check(z.describe('Requested historical observation time, when supplied.'), z.meta({ examples: ['2026-07-21T09:00:00.000Z'] })),
|
|
790
|
+
block: z
|
|
791
|
+
.optional(Block)
|
|
792
|
+
.check(z.describe('Indexed block used for a historical Earn position observation, when requested.')),
|
|
793
|
+
rewards: z
|
|
794
|
+
.optional(Rewards)
|
|
795
|
+
.check(z.describe('Current reward state when requested through `include`.')),
|
|
796
|
+
}), 'Current or historical asset and earn-share balances, allowances, and asset value for an account in one earn vault.'), 'EarnVaultPosition');
|
|
421
797
|
})(getEarnVaultPosition = schema.getEarnVaultPosition || (schema.getEarnVaultPosition = {}));
|
|
422
798
|
/** Schemas for the getEarnVaultEarnings operation. */
|
|
423
799
|
let getEarnVaultEarnings;
|
|
@@ -437,13 +813,98 @@ export var schema;
|
|
|
437
813
|
})
|
|
438
814
|
.check(z.describe('Query parameters selecting an earn vault account.'));
|
|
439
815
|
/** Earnings for one account and period in one Earn vault. */
|
|
440
|
-
getEarnVaultEarnings.Response = Schema.describe(earnings, 'Indexed asset value and cost-basis-aware earnings for an account in one earn vault.');
|
|
816
|
+
getEarnVaultEarnings.Response = OpenApi.component(Schema.describe(earnings, 'Indexed asset value and cost-basis-aware earnings for an account in one earn vault.'), 'EarnVaultEarnings');
|
|
441
817
|
})(getEarnVaultEarnings = schema.getEarnVaultEarnings || (schema.getEarnVaultEarnings = {}));
|
|
442
818
|
})(schema || (schema = {}));
|
|
443
819
|
/** Creates the public Earn-vault handlers. */
|
|
444
820
|
export function earn(options = {}) {
|
|
445
821
|
const oracle = options.fx?.oracle ?? FxOracle.ecb();
|
|
446
822
|
return new Hono()
|
|
823
|
+
.post('/v1/earn/rewards/eligibility', Auth.policy({ apiKey: { scopes: [Scope.wildcard] } }), OpenApi.validate('json', schema.registerRewardEligibility.Body, {
|
|
824
|
+
code: 'body_invalid',
|
|
825
|
+
message: 'Invalid reward eligibility registration',
|
|
826
|
+
}), OpenApi.describeRoute({
|
|
827
|
+
description: 'Registers a wallet and Earn vault association for reward eligibility.',
|
|
828
|
+
hide: true,
|
|
829
|
+
operationId: 'registerRewardEligibility',
|
|
830
|
+
responses: OpenApi.responses({
|
|
831
|
+
errors: {
|
|
832
|
+
400: { codes: ['body_invalid', 'chain_id_unsupported'] },
|
|
833
|
+
},
|
|
834
|
+
success: {
|
|
835
|
+
description: 'The persisted reward eligibility association.',
|
|
836
|
+
schema: schema.registerRewardEligibility.Response,
|
|
837
|
+
},
|
|
838
|
+
}),
|
|
839
|
+
summary: 'Register reward eligibility',
|
|
840
|
+
tags: ['Earn'],
|
|
841
|
+
}), async (c) => {
|
|
842
|
+
if (Auth.narrowAccess)
|
|
843
|
+
return Auth.accessError(c);
|
|
844
|
+
if (OpenApi.narrowValidation)
|
|
845
|
+
return OpenApi.validationError(c, {
|
|
846
|
+
code: 'body_invalid',
|
|
847
|
+
message: 'Invalid reward eligibility registration',
|
|
848
|
+
});
|
|
849
|
+
const body = c.req.valid('json');
|
|
850
|
+
if (!c.get('supportedChainIds').has(body.chainId))
|
|
851
|
+
return Response.unsupportedChainId(c, body.chainId, c.get('supportedChainIds'));
|
|
852
|
+
c.set('chainId', body.chainId);
|
|
853
|
+
c.header('Cache-Control', Cache.policies.noStore);
|
|
854
|
+
const result = await RewardEligibilityAssociations.upsert(Db.get(c.get('db')), {
|
|
855
|
+
...body,
|
|
856
|
+
});
|
|
857
|
+
return c.json(Response.validated(schema.registerRewardEligibility.Response, {
|
|
858
|
+
association: toRewardEligibilityAssociation(result.record),
|
|
859
|
+
created: result.created,
|
|
860
|
+
}), 200);
|
|
861
|
+
})
|
|
862
|
+
.get('/v1/earn/rewards/eligibility', Auth.policy({ apiKey: { scopes: ['rewards:read'] } }), OpenApi.validate('query', schema.getRewardEligibility.Query, {
|
|
863
|
+
code: 'query_invalid',
|
|
864
|
+
message: 'Invalid reward eligibility selector',
|
|
865
|
+
}), OpenApi.describeRoute({
|
|
866
|
+
description: 'Lists reward eligibility associations for one Earn vault at a fixed high-water checkpoint.',
|
|
867
|
+
hide: true,
|
|
868
|
+
operationId: 'getRewardEligibility',
|
|
869
|
+
responses: OpenApi.responses({
|
|
870
|
+
success: {
|
|
871
|
+
description: 'A checkpointed page of reward eligibility associations.',
|
|
872
|
+
schema: schema.getRewardEligibility.Response,
|
|
873
|
+
},
|
|
874
|
+
}),
|
|
875
|
+
summary: 'List reward eligibility',
|
|
876
|
+
tags: ['Earn'],
|
|
877
|
+
}), async (c) => {
|
|
878
|
+
if (Auth.narrowAccess)
|
|
879
|
+
return Auth.accessError(c);
|
|
880
|
+
if (OpenApi.narrowValidation)
|
|
881
|
+
return OpenApi.validationError(c, {
|
|
882
|
+
code: 'query_invalid',
|
|
883
|
+
message: 'Invalid reward eligibility selector',
|
|
884
|
+
});
|
|
885
|
+
const query = c.req.valid('query');
|
|
886
|
+
const zone = c.get('zones').get(query.chainId);
|
|
887
|
+
const sourceChainId = zone ? zone.sourceId : query.chainId;
|
|
888
|
+
const principal = Auth.getPrincipal(c);
|
|
889
|
+
if (principal?.type === 'api_key' &&
|
|
890
|
+
principal.environment === 'sandbox' &&
|
|
891
|
+
(sourceChainId === undefined || Viem.isMainnet(sourceChainId)))
|
|
892
|
+
return Response.error(c, {
|
|
893
|
+
code: 'api_key_forbidden',
|
|
894
|
+
message: 'Sandbox API keys only support testnet.',
|
|
895
|
+
status: 403,
|
|
896
|
+
});
|
|
897
|
+
c.header('Cache-Control', Cache.policies.noStore);
|
|
898
|
+
const page = await RewardEligibilityAssociations.list(Db.get(c.get('db')), {
|
|
899
|
+
...query,
|
|
900
|
+
});
|
|
901
|
+
return c.json(Response.validated(schema.getRewardEligibility.Response, {
|
|
902
|
+
chainId: query.chainId,
|
|
903
|
+
data: page.data.map((association) => association.walletAddress),
|
|
904
|
+
nextCursor: page.nextCursor,
|
|
905
|
+
vaultAddress: query.vaultAddress,
|
|
906
|
+
}), 200);
|
|
907
|
+
})
|
|
447
908
|
.get('/v1/earn/vaults', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.validate('query', schema.getEarnVaults.Query, {
|
|
448
909
|
code: 'query_invalid',
|
|
449
910
|
message: 'Invalid query parameters',
|
|
@@ -451,7 +912,12 @@ export function earn(options = {}) {
|
|
|
451
912
|
description: 'Lists compatible earn vaults discovered from deployment events and resolved from current chain state.',
|
|
452
913
|
operationId: 'getEarnVaults',
|
|
453
914
|
responses: OpenApi.responses({
|
|
454
|
-
errors: {
|
|
915
|
+
errors: {
|
|
916
|
+
400: {
|
|
917
|
+
codes: ['chain_id_invalid', 'chain_id_unsupported', 'query_invalid'],
|
|
918
|
+
},
|
|
919
|
+
502: 'Could not read earn deployment or vault data.',
|
|
920
|
+
},
|
|
455
921
|
success: {
|
|
456
922
|
description: 'A page of compatible deployed earn vaults.',
|
|
457
923
|
schema: schema.getEarnVaults.Response,
|
|
@@ -465,10 +931,22 @@ export function earn(options = {}) {
|
|
|
465
931
|
Cache.response({
|
|
466
932
|
cacheControl: Cache.policies.state,
|
|
467
933
|
key: (c) => vaultCacheKey(c, schema.getEarnVaults.Query),
|
|
468
|
-
name: 'tempo-api:earn-vaults:
|
|
934
|
+
name: 'tempo-api:earn-vaults:v5',
|
|
469
935
|
}), async (c) => {
|
|
470
936
|
if (Auth.narrowAccess)
|
|
471
937
|
return Auth.paidAccessError(c);
|
|
938
|
+
if (OpenApi.narrowValidation)
|
|
939
|
+
return Response.error(c, {
|
|
940
|
+
code: 'chain_id_invalid',
|
|
941
|
+
message: 'Invalid chain id',
|
|
942
|
+
status: 400,
|
|
943
|
+
});
|
|
944
|
+
if (OpenApi.narrowValidation)
|
|
945
|
+
return Response.error(c, {
|
|
946
|
+
code: 'chain_id_unsupported',
|
|
947
|
+
message: 'Unsupported chain id',
|
|
948
|
+
status: 400,
|
|
949
|
+
});
|
|
472
950
|
if (OpenApi.narrowValidation)
|
|
473
951
|
return OpenApi.validationError(c, {
|
|
474
952
|
code: 'query_invalid',
|
|
@@ -491,7 +969,12 @@ export function earn(options = {}) {
|
|
|
491
969
|
description: 'Lists registry-curated earn vaults after resolving their current onchain configuration.',
|
|
492
970
|
operationId: 'getVerifiedEarnVaults',
|
|
493
971
|
responses: OpenApi.responses({
|
|
494
|
-
errors: {
|
|
972
|
+
errors: {
|
|
973
|
+
400: {
|
|
974
|
+
codes: ['chain_id_invalid', 'chain_id_unsupported', 'query_invalid'],
|
|
975
|
+
},
|
|
976
|
+
502: 'Could not read curated earn registry or vault data.',
|
|
977
|
+
},
|
|
495
978
|
success: {
|
|
496
979
|
description: 'A page of registry-curated earn vaults.',
|
|
497
980
|
schema: schema.getVerifiedEarnVaults.Response,
|
|
@@ -502,10 +985,22 @@ export function earn(options = {}) {
|
|
|
502
985
|
}), Cache.response({
|
|
503
986
|
cacheControl: Cache.policies.state,
|
|
504
987
|
key: (c) => vaultCacheKey(c, schema.getVerifiedEarnVaults.Query),
|
|
505
|
-
name: 'tempo-api:earn-vaults:
|
|
988
|
+
name: 'tempo-api:earn-vaults:v4',
|
|
506
989
|
}), async (c) => {
|
|
507
990
|
if (Auth.narrowAccess)
|
|
508
991
|
return Auth.paidAccessError(c);
|
|
992
|
+
if (OpenApi.narrowValidation)
|
|
993
|
+
return Response.error(c, {
|
|
994
|
+
code: 'chain_id_invalid',
|
|
995
|
+
message: 'Invalid chain id',
|
|
996
|
+
status: 400,
|
|
997
|
+
});
|
|
998
|
+
if (OpenApi.narrowValidation)
|
|
999
|
+
return Response.error(c, {
|
|
1000
|
+
code: 'chain_id_unsupported',
|
|
1001
|
+
message: 'Unsupported chain id',
|
|
1002
|
+
status: 400,
|
|
1003
|
+
});
|
|
509
1004
|
if (OpenApi.narrowValidation)
|
|
510
1005
|
return OpenApi.validationError(c, {
|
|
511
1006
|
code: 'query_invalid',
|
|
@@ -514,7 +1009,11 @@ export function earn(options = {}) {
|
|
|
514
1009
|
const query = c.req.valid('query');
|
|
515
1010
|
try {
|
|
516
1011
|
const chainId = query.chainId ?? c.get('chainId');
|
|
517
|
-
const data = await listVerifiedVaults(c, {
|
|
1012
|
+
const data = await listVerifiedVaults(c, {
|
|
1013
|
+
...query,
|
|
1014
|
+
chainId,
|
|
1015
|
+
oracle,
|
|
1016
|
+
});
|
|
518
1017
|
return c.json(Response.validated(schema.getVerifiedEarnVaults.Response, data), 200);
|
|
519
1018
|
}
|
|
520
1019
|
catch (cause) {
|
|
@@ -528,7 +1027,7 @@ export function earn(options = {}) {
|
|
|
528
1027
|
code: 'query_invalid',
|
|
529
1028
|
message: 'Invalid query parameters',
|
|
530
1029
|
}), OpenApi.describeRoute({
|
|
531
|
-
description: 'Lists every earn vault where an account currently holds shares
|
|
1030
|
+
description: '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.',
|
|
532
1031
|
operationId: 'getEarnAddressPositions',
|
|
533
1032
|
responses: OpenApi.responses({
|
|
534
1033
|
errors: {
|
|
@@ -555,7 +1054,7 @@ export function earn(options = {}) {
|
|
|
555
1054
|
Cache.response({
|
|
556
1055
|
cacheControl: Cache.policies.noStore,
|
|
557
1056
|
key: (c) => Cache.urlKey(c, schema.getEarnAddressPositions.Query),
|
|
558
|
-
name: 'tempo-api:earn-address-positions:
|
|
1057
|
+
name: 'tempo-api:earn-address-positions:v2',
|
|
559
1058
|
}), async (c) => {
|
|
560
1059
|
if (Auth.narrowAccess)
|
|
561
1060
|
return Auth.paidAccessError(c);
|
|
@@ -591,6 +1090,101 @@ export function earn(options = {}) {
|
|
|
591
1090
|
catch (cause) {
|
|
592
1091
|
if (cause instanceof Valuation.UnsupportedDenominationError)
|
|
593
1092
|
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 });
|
|
1093
|
+
if (cause instanceof ZoneEarningsUnsupportedError)
|
|
1094
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 });
|
|
1095
|
+
return Response.upstream(c, cause);
|
|
1096
|
+
}
|
|
1097
|
+
})
|
|
1098
|
+
.get('/v1/earn/vaults/:vaultId/share-prices', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.validate('param', schema.getEarnVaultSharePrices.Params, {
|
|
1099
|
+
code: 'vault_id_invalid',
|
|
1100
|
+
message: 'Invalid vault id',
|
|
1101
|
+
}), OpenApi.validate('query', schema.getEarnVaultSharePrices.Query, {
|
|
1102
|
+
code: 'query_invalid',
|
|
1103
|
+
message: 'Invalid query parameters',
|
|
1104
|
+
}), OpenApi.describeRoute({
|
|
1105
|
+
description: 'Lists daily historical share prices for one earn vault.',
|
|
1106
|
+
operationId: 'getEarnVaultSharePrices',
|
|
1107
|
+
responses: OpenApi.responses({
|
|
1108
|
+
errors: {
|
|
1109
|
+
400: {
|
|
1110
|
+
codes: [
|
|
1111
|
+
'chain_id_invalid',
|
|
1112
|
+
'chain_id_unsupported',
|
|
1113
|
+
'query_invalid',
|
|
1114
|
+
'vault_id_invalid',
|
|
1115
|
+
],
|
|
1116
|
+
},
|
|
1117
|
+
404: {
|
|
1118
|
+
codes: ['earn_vault_not_found'],
|
|
1119
|
+
description: 'No compatible earn vault was found at the supplied vault address.',
|
|
1120
|
+
},
|
|
1121
|
+
502: 'Could not read historical earn vault share prices.',
|
|
1122
|
+
},
|
|
1123
|
+
success: {
|
|
1124
|
+
description: 'Daily historical share prices for one earn vault.',
|
|
1125
|
+
schema: schema.getEarnVaultSharePrices.Response,
|
|
1126
|
+
},
|
|
1127
|
+
}),
|
|
1128
|
+
summary: 'List share prices',
|
|
1129
|
+
tags: ['Earn'],
|
|
1130
|
+
}), Cache.response({
|
|
1131
|
+
cacheControl: Cache.policies.state,
|
|
1132
|
+
key: (c) => Cache.urlKey(c, schema.getEarnVaultSharePrices.Query),
|
|
1133
|
+
name: 'tempo-api:earn-vault-share-prices:v1',
|
|
1134
|
+
}), async (c) => {
|
|
1135
|
+
if (Auth.narrowAccess)
|
|
1136
|
+
return Auth.paidAccessError(c);
|
|
1137
|
+
if (OpenApi.narrowValidation)
|
|
1138
|
+
return Response.error(c, {
|
|
1139
|
+
code: 'chain_id_invalid',
|
|
1140
|
+
message: 'Invalid chain id',
|
|
1141
|
+
status: 400,
|
|
1142
|
+
});
|
|
1143
|
+
if (OpenApi.narrowValidation)
|
|
1144
|
+
return Response.error(c, {
|
|
1145
|
+
code: 'chain_id_unsupported',
|
|
1146
|
+
message: 'Unsupported chain id',
|
|
1147
|
+
status: 400,
|
|
1148
|
+
});
|
|
1149
|
+
if (OpenApi.narrowValidation)
|
|
1150
|
+
return OpenApi.validationError(c, {
|
|
1151
|
+
code: 'vault_id_invalid',
|
|
1152
|
+
message: 'Invalid vault id',
|
|
1153
|
+
});
|
|
1154
|
+
if (OpenApi.narrowValidation)
|
|
1155
|
+
return OpenApi.validationError(c, {
|
|
1156
|
+
code: 'query_invalid',
|
|
1157
|
+
message: 'Invalid query parameters',
|
|
1158
|
+
});
|
|
1159
|
+
const { vaultId } = c.req.valid('param');
|
|
1160
|
+
const query = c.req.valid('query');
|
|
1161
|
+
const chainId = query.chainId ?? c.get('chainId');
|
|
1162
|
+
try {
|
|
1163
|
+
const discovery = await resolveSharePriceVaultDiscovery(c, {
|
|
1164
|
+
chainId,
|
|
1165
|
+
vaultAddress: vaultId,
|
|
1166
|
+
});
|
|
1167
|
+
if (!discovery)
|
|
1168
|
+
return Response.error(c, {
|
|
1169
|
+
code: 'earn_vault_not_found',
|
|
1170
|
+
message: 'Earn vault not found',
|
|
1171
|
+
status: 404,
|
|
1172
|
+
});
|
|
1173
|
+
const data = await getVaultSharePrices(c, {
|
|
1174
|
+
...query,
|
|
1175
|
+
chainId,
|
|
1176
|
+
discovery,
|
|
1177
|
+
vault: vaultId,
|
|
1178
|
+
});
|
|
1179
|
+
return c.json(Response.validated(schema.getEarnVaultSharePrices.Response, { data }), 200);
|
|
1180
|
+
}
|
|
1181
|
+
catch (cause) {
|
|
1182
|
+
if (cause instanceof EarnSharePrices.IndexedBlockNotFoundError ||
|
|
1183
|
+
cause instanceof EarnSharePrices.IndexedCoverageError)
|
|
1184
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 });
|
|
1185
|
+
const failure = sharePriceProviderFailure({ cause, chainId });
|
|
1186
|
+
if (failure)
|
|
1187
|
+
c.set('providerFailure', failure);
|
|
594
1188
|
return Response.upstream(c, cause);
|
|
595
1189
|
}
|
|
596
1190
|
})
|
|
@@ -601,7 +1195,7 @@ export function earn(options = {}) {
|
|
|
601
1195
|
code: 'query_invalid',
|
|
602
1196
|
message: 'Invalid query parameters',
|
|
603
1197
|
}), OpenApi.describeRoute({
|
|
604
|
-
description: 'Gets an account’s
|
|
1198
|
+
description: 'Gets an account’s direct or Zone-routed balances and asset value for one earn vault, optionally at an ISO 8601 timestamp.',
|
|
605
1199
|
operationId: 'getEarnVaultPosition',
|
|
606
1200
|
responses: OpenApi.responses({
|
|
607
1201
|
errors: {
|
|
@@ -620,16 +1214,18 @@ export function earn(options = {}) {
|
|
|
620
1214
|
502: 'Could not read the earn vault position.',
|
|
621
1215
|
},
|
|
622
1216
|
success: {
|
|
623
|
-
description: 'Current earn position for one account in one vault.',
|
|
1217
|
+
description: 'Current or historical earn position for one account in one vault.',
|
|
624
1218
|
schema: schema.getEarnVaultPosition.Response,
|
|
625
1219
|
},
|
|
626
1220
|
}),
|
|
627
1221
|
summary: 'Get account position',
|
|
628
1222
|
tags: ['Earn'],
|
|
629
|
-
}),
|
|
630
|
-
|
|
1223
|
+
}),
|
|
1224
|
+
// Account holdings must read fresh immediately after a deposit or redemption.
|
|
1225
|
+
Cache.response({
|
|
1226
|
+
cacheControl: Cache.policies.noStore,
|
|
631
1227
|
key: (c) => Cache.urlKey(c, schema.getEarnVaultPosition.Query),
|
|
632
|
-
name: 'tempo-api:earn-vault-positions:
|
|
1228
|
+
name: 'tempo-api:earn-vault-positions:v3',
|
|
633
1229
|
}), async (c) => {
|
|
634
1230
|
if (Auth.narrowAccess)
|
|
635
1231
|
return Auth.paidAccessError(c);
|
|
@@ -658,23 +1254,122 @@ export function earn(options = {}) {
|
|
|
658
1254
|
const { address, vaultId } = c.req.valid('param');
|
|
659
1255
|
const query = c.req.valid('query');
|
|
660
1256
|
const chainId = query.chainId ?? c.get('chainId');
|
|
1257
|
+
if (query.asOf && query.include.length > 0)
|
|
1258
|
+
return Response.error(c, {
|
|
1259
|
+
code: 'query_invalid',
|
|
1260
|
+
message: 'Historical position enrichments are not available.',
|
|
1261
|
+
status: 400,
|
|
1262
|
+
});
|
|
1263
|
+
if (c.get('zones').has(chainId))
|
|
1264
|
+
Cache.setPolicy(c, Cache.policies.noStore);
|
|
661
1265
|
try {
|
|
662
|
-
const position = await c
|
|
663
|
-
|
|
664
|
-
|
|
1266
|
+
const position = await getVaultPosition(c, {
|
|
1267
|
+
account: address,
|
|
1268
|
+
asOf: query.asOf,
|
|
1269
|
+
chainId,
|
|
1270
|
+
vault: vaultId,
|
|
1271
|
+
});
|
|
1272
|
+
const apy = query.include.includes('apy')
|
|
1273
|
+
? await resolvePositionApy(c, {
|
|
1274
|
+
chainId,
|
|
1275
|
+
recipient: address,
|
|
1276
|
+
shareBalance: position.shareBalance,
|
|
1277
|
+
value: position.value,
|
|
1278
|
+
vault: vaultId,
|
|
1279
|
+
})
|
|
1280
|
+
: undefined;
|
|
1281
|
+
const rewards = query.include.some((value) => value.startsWith('rewards'))
|
|
1282
|
+
? await RewardRead.recipient({
|
|
1283
|
+
chainId,
|
|
1284
|
+
db: c.get('db'),
|
|
1285
|
+
getClient: c.get('getClient'),
|
|
1286
|
+
recipient: address,
|
|
1287
|
+
vaultAddress: vaultId,
|
|
1288
|
+
})
|
|
1289
|
+
: undefined;
|
|
665
1290
|
return c.json(Response.validated(schema.getEarnVaultPosition.Response, {
|
|
666
1291
|
account: address,
|
|
1292
|
+
...(query.include.includes('apy') ? { apy } : {}),
|
|
667
1293
|
assetAllowance: position.assetAllowance.toString(),
|
|
668
1294
|
assetBalance: position.assetBalance.toString(),
|
|
669
1295
|
assetToken: position.assetToken,
|
|
1296
|
+
chainId,
|
|
1297
|
+
asOf: query.asOf,
|
|
1298
|
+
block: position.block,
|
|
670
1299
|
id: address,
|
|
1300
|
+
...(rewards
|
|
1301
|
+
? {
|
|
1302
|
+
rewards: query.include.includes('rewards.proof')
|
|
1303
|
+
? rewards
|
|
1304
|
+
: { ...rewards, proof: undefined },
|
|
1305
|
+
}
|
|
1306
|
+
: {}),
|
|
671
1307
|
shareAllowance: position.shareAllowance.toString(),
|
|
672
1308
|
shareBalance: position.shareBalance.toString(),
|
|
673
1309
|
shareToken: position.shareToken,
|
|
674
1310
|
value: position.value.toString(),
|
|
1311
|
+
valueToken: position.valueToken,
|
|
675
1312
|
}), 200);
|
|
676
1313
|
}
|
|
677
1314
|
catch (cause) {
|
|
1315
|
+
if (cause instanceof IndexedBlockNotFoundError || cause instanceof IndexedCoverageError)
|
|
1316
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 });
|
|
1317
|
+
if (cause instanceof ZoneHistoricalAlignmentError)
|
|
1318
|
+
return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 });
|
|
1319
|
+
if (cause instanceof EarnVaults.NotFoundError)
|
|
1320
|
+
return Response.error(c, {
|
|
1321
|
+
code: 'earn_vault_not_found',
|
|
1322
|
+
message: 'Earn vault not found',
|
|
1323
|
+
status: 404,
|
|
1324
|
+
});
|
|
1325
|
+
const zone = c.get('zones').get(chainId);
|
|
1326
|
+
if (query.asOf && !zone) {
|
|
1327
|
+
try {
|
|
1328
|
+
const block = await getIndexedBlockAtOrBefore(c.get('getTidx')(chainId), query.asOf);
|
|
1329
|
+
const client = c.get('getClient')(chainId);
|
|
1330
|
+
// These immutable bindings establish historical vault identity
|
|
1331
|
+
// without repeating fallible token or redemption subreads.
|
|
1332
|
+
const [asset, shareToken] = await Promise.all([
|
|
1333
|
+
client.readContract({
|
|
1334
|
+
abi: Abis.earnVault,
|
|
1335
|
+
address: vaultId,
|
|
1336
|
+
blockNumber: BigInt(block.number),
|
|
1337
|
+
functionName: 'asset',
|
|
1338
|
+
}),
|
|
1339
|
+
client.readContract({
|
|
1340
|
+
abi: Abis.earnVault,
|
|
1341
|
+
address: vaultId,
|
|
1342
|
+
blockNumber: BigInt(block.number),
|
|
1343
|
+
functionName: 'earnShare',
|
|
1344
|
+
}),
|
|
1345
|
+
]);
|
|
1346
|
+
if (asset === zeroAddress || shareToken === zeroAddress)
|
|
1347
|
+
return Response.error(c, {
|
|
1348
|
+
code: 'earn_vault_not_found',
|
|
1349
|
+
message: 'Earn vault not found',
|
|
1350
|
+
status: 404,
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
catch (identityCause) {
|
|
1354
|
+
if (identityCause instanceof IndexedBlockNotFoundError ||
|
|
1355
|
+
identityCause instanceof IndexedCoverageError)
|
|
1356
|
+
return Response.error(c, {
|
|
1357
|
+
code: 'query_invalid',
|
|
1358
|
+
message: identityCause.message,
|
|
1359
|
+
status: 400,
|
|
1360
|
+
});
|
|
1361
|
+
if (isIncompatible(identityCause))
|
|
1362
|
+
return Response.error(c, {
|
|
1363
|
+
code: 'earn_vault_not_found',
|
|
1364
|
+
message: 'Earn vault not found',
|
|
1365
|
+
status: 404,
|
|
1366
|
+
});
|
|
1367
|
+
return Response.upstream(c, identityCause);
|
|
1368
|
+
}
|
|
1369
|
+
return Response.upstream(c, cause);
|
|
1370
|
+
}
|
|
1371
|
+
if (zone)
|
|
1372
|
+
return Response.upstream(c, cause);
|
|
678
1373
|
try {
|
|
679
1374
|
await resolveVaultDiscovery(c, { chainId, include: [], vaultAddress: vaultId });
|
|
680
1375
|
}
|
|
@@ -724,7 +1419,7 @@ export function earn(options = {}) {
|
|
|
724
1419
|
}), Cache.response({
|
|
725
1420
|
cacheControl: Cache.policies.state,
|
|
726
1421
|
key: (c) => Cache.urlKey(c, schema.getEarnVaultEarnings.Query),
|
|
727
|
-
name: 'tempo-api:earn-vault-earnings:
|
|
1422
|
+
name: 'tempo-api:earn-vault-earnings:v4',
|
|
728
1423
|
}), async (c) => {
|
|
729
1424
|
if (Auth.narrowAccess)
|
|
730
1425
|
return Auth.paidAccessError(c);
|
|
@@ -788,6 +1483,14 @@ export function earn(options = {}) {
|
|
|
788
1483
|
operationId: 'getEarnVault',
|
|
789
1484
|
responses: OpenApi.responses({
|
|
790
1485
|
errors: {
|
|
1486
|
+
400: {
|
|
1487
|
+
codes: [
|
|
1488
|
+
'chain_id_invalid',
|
|
1489
|
+
'chain_id_unsupported',
|
|
1490
|
+
'query_invalid',
|
|
1491
|
+
'vault_id_invalid',
|
|
1492
|
+
],
|
|
1493
|
+
},
|
|
791
1494
|
404: {
|
|
792
1495
|
codes: ['earn_vault_not_found'],
|
|
793
1496
|
description: 'No compatible earn vault was found at this address.',
|
|
@@ -804,10 +1507,22 @@ export function earn(options = {}) {
|
|
|
804
1507
|
}), Cache.response({
|
|
805
1508
|
cacheControl: Cache.policies.state,
|
|
806
1509
|
key: (c) => vaultCacheKey(c, schema.getEarnVault.Query),
|
|
807
|
-
name: 'tempo-api:earn-vaults:
|
|
1510
|
+
name: 'tempo-api:earn-vaults:v4',
|
|
808
1511
|
}), async (c) => {
|
|
809
1512
|
if (Auth.narrowAccess)
|
|
810
1513
|
return Auth.paidAccessError(c);
|
|
1514
|
+
if (OpenApi.narrowValidation)
|
|
1515
|
+
return Response.error(c, {
|
|
1516
|
+
code: 'chain_id_invalid',
|
|
1517
|
+
message: 'Invalid chain id',
|
|
1518
|
+
status: 400,
|
|
1519
|
+
});
|
|
1520
|
+
if (OpenApi.narrowValidation)
|
|
1521
|
+
return Response.error(c, {
|
|
1522
|
+
code: 'chain_id_unsupported',
|
|
1523
|
+
message: 'Unsupported chain id',
|
|
1524
|
+
status: 400,
|
|
1525
|
+
});
|
|
811
1526
|
if (OpenApi.narrowValidation)
|
|
812
1527
|
return OpenApi.validationError(c, {
|
|
813
1528
|
code: 'vault_id_invalid',
|
|
@@ -846,7 +1561,10 @@ export function earn(options = {}) {
|
|
|
846
1561
|
export async function getVaultEarnings(c, options) {
|
|
847
1562
|
const client = c.get('getClient')(options.chainId);
|
|
848
1563
|
const tidx = c.get('getTidx')(options.chainId);
|
|
849
|
-
const block = await
|
|
1564
|
+
const [block, rewardTransfer] = await Promise.all([
|
|
1565
|
+
getLatestIndexedBlock(tidx),
|
|
1566
|
+
getRewardTransferPredicate(c, options),
|
|
1567
|
+
]);
|
|
850
1568
|
const blockNumber = block.number;
|
|
851
1569
|
if (options.period === '30d')
|
|
852
1570
|
return getWindowVaultEarnings(c, {
|
|
@@ -854,6 +1572,7 @@ export async function getVaultEarnings(c, options) {
|
|
|
854
1572
|
blockNumber,
|
|
855
1573
|
chainId: options.chainId,
|
|
856
1574
|
period: options.period,
|
|
1575
|
+
rewardTransfer,
|
|
857
1576
|
timestamp: block.timestamp,
|
|
858
1577
|
vault: options.vault,
|
|
859
1578
|
});
|
|
@@ -874,6 +1593,7 @@ export async function getVaultEarnings(c, options) {
|
|
|
874
1593
|
const activeCostBasis = await getActiveCostBasis(tidx, {
|
|
875
1594
|
account: options.account,
|
|
876
1595
|
blockNumber,
|
|
1596
|
+
rewardTransfer,
|
|
877
1597
|
shareBalance: current.shareBalance,
|
|
878
1598
|
shareToken: current.shareToken,
|
|
879
1599
|
vault: options.vault,
|
|
@@ -898,6 +1618,7 @@ export async function getVaultEarnings(c, options) {
|
|
|
898
1618
|
const externalShareTransfer = await hasExternalShareTransfer(tidx, {
|
|
899
1619
|
account: options.account,
|
|
900
1620
|
blockNumber,
|
|
1621
|
+
rewardTransfer,
|
|
901
1622
|
shareToken: current.shareToken,
|
|
902
1623
|
startBlockNumber: beforeFirstBlockNumber,
|
|
903
1624
|
vault: options.vault,
|
|
@@ -911,10 +1632,20 @@ export async function getVaultEarnings(c, options) {
|
|
|
911
1632
|
};
|
|
912
1633
|
if (history.incompleteCostBasis || externalShareTransfer)
|
|
913
1634
|
return { ...base, status: 'incomplete_cost_basis' };
|
|
1635
|
+
const totalWithdrawn = history.redeemed + history.withdrewExact + history.finalized;
|
|
1636
|
+
const cashFlows = {
|
|
1637
|
+
totalDeposited: history.deposited.toString(),
|
|
1638
|
+
totalWithdrawn: totalWithdrawn.toString(),
|
|
1639
|
+
};
|
|
914
1640
|
if (history.pendingRedemption)
|
|
915
|
-
return { ...base, status: 'pending_redemption' };
|
|
916
|
-
const lifetimeEarnings = current.value +
|
|
917
|
-
return {
|
|
1641
|
+
return { ...base, ...cashFlows, status: 'pending_redemption' };
|
|
1642
|
+
const lifetimeEarnings = current.value + totalWithdrawn - history.deposited;
|
|
1643
|
+
return {
|
|
1644
|
+
...base,
|
|
1645
|
+
...cashFlows,
|
|
1646
|
+
lifetimeEarnings: lifetimeEarnings.toString(),
|
|
1647
|
+
status: 'complete',
|
|
1648
|
+
};
|
|
918
1649
|
}
|
|
919
1650
|
/** Reads cash-flow-adjusted earnings over a trailing indexed window. */
|
|
920
1651
|
async function getWindowVaultEarnings(c, options) {
|
|
@@ -932,6 +1663,7 @@ async function getWindowVaultEarnings(c, options) {
|
|
|
932
1663
|
hasExternalShareTransfer(tidx, {
|
|
933
1664
|
account: options.account,
|
|
934
1665
|
blockNumber: options.blockNumber,
|
|
1666
|
+
rewardTransfer: options.rewardTransfer,
|
|
935
1667
|
shareToken: current.shareToken,
|
|
936
1668
|
startBlockNumber,
|
|
937
1669
|
vault: options.vault,
|
|
@@ -1003,6 +1735,53 @@ async function getLatestIndexedBlock(tidx) {
|
|
|
1003
1735
|
throw new Error('TIDX returned no indexed block.');
|
|
1004
1736
|
return { number, timestamp };
|
|
1005
1737
|
}
|
|
1738
|
+
/** Resolves the latest indexed block at or before a historical position timestamp. */
|
|
1739
|
+
async function getIndexedBlockAtOrBefore(tidx, asOf) {
|
|
1740
|
+
const timestamp = new Date(asOf).toISOString().replace('T', ' ').replace(/Z$/, '');
|
|
1741
|
+
const result = await tidx.fetch({
|
|
1742
|
+
engine: 'clickhouse',
|
|
1743
|
+
// SAFETY: Zod restricts `asOf` to ISO 8601, so the formatted timestamp cannot alter SQL.
|
|
1744
|
+
query: `
|
|
1745
|
+
SELECT 'boundary' AS kind, num, timestamp
|
|
1746
|
+
FROM (
|
|
1747
|
+
SELECT num, timestamp
|
|
1748
|
+
FROM blocks
|
|
1749
|
+
WHERE timestamp <= '${timestamp}'
|
|
1750
|
+
ORDER BY timestamp DESC, num DESC
|
|
1751
|
+
LIMIT 1
|
|
1752
|
+
)
|
|
1753
|
+
UNION ALL
|
|
1754
|
+
SELECT 'head' AS kind, num, timestamp
|
|
1755
|
+
FROM (
|
|
1756
|
+
SELECT num, timestamp
|
|
1757
|
+
FROM blocks
|
|
1758
|
+
ORDER BY num DESC
|
|
1759
|
+
LIMIT 1
|
|
1760
|
+
)
|
|
1761
|
+
`,
|
|
1762
|
+
});
|
|
1763
|
+
return parseIndexedBlockAtOrBefore({ asOf, rows: result.rows });
|
|
1764
|
+
}
|
|
1765
|
+
/** Decodes the indexed head and historical position boundary from TIDX rows. */
|
|
1766
|
+
export function parseIndexedBlockAtOrBefore(options) {
|
|
1767
|
+
const head = options.rows.find((row) => row['kind'] === 'head');
|
|
1768
|
+
if (!head)
|
|
1769
|
+
throw new Error('TIDX returned no indexed head for a historical Earn position.');
|
|
1770
|
+
const headNumber = Value.toNumber(head['num']);
|
|
1771
|
+
const headAt = Value.toIsoDateTime(head['timestamp']);
|
|
1772
|
+
if (headNumber === undefined || headAt === undefined)
|
|
1773
|
+
throw new Error('TIDX returned a malformed indexed head for a historical Earn position.');
|
|
1774
|
+
const boundary = options.rows.find((row) => row['kind'] === 'boundary');
|
|
1775
|
+
if (!boundary)
|
|
1776
|
+
throw new IndexedBlockNotFoundError(options.asOf);
|
|
1777
|
+
const number = Value.toNumber(boundary['num']);
|
|
1778
|
+
const indexedAt = Value.toIsoDateTime(boundary['timestamp']);
|
|
1779
|
+
if (number === undefined || indexedAt === undefined)
|
|
1780
|
+
throw new Error('TIDX returned a malformed historical Earn position boundary.');
|
|
1781
|
+
if (Date.parse(headAt) < Date.parse(options.asOf))
|
|
1782
|
+
throw new IndexedCoverageError(options.asOf);
|
|
1783
|
+
return { number, timestamp: indexedAt };
|
|
1784
|
+
}
|
|
1006
1785
|
/** Resolves the last indexed block at or before a trailing-day boundary. */
|
|
1007
1786
|
async function getWindowStartBlockNumber(tidx, options) {
|
|
1008
1787
|
const cutoff = new Date(Date.parse(options.timestamp) - Ttl.days(options.days)).toISOString();
|
|
@@ -1128,6 +1907,7 @@ async function getVaultEarningsHistory(tidx, options) {
|
|
|
1128
1907
|
return {
|
|
1129
1908
|
deposited: BigInt(deposited),
|
|
1130
1909
|
finalized: BigInt(finalized),
|
|
1910
|
+
incompleteCashFlows: venueDeposits > 0,
|
|
1131
1911
|
incompleteCostBasis: transferredCancellations > 0 || venueDeposits > 0,
|
|
1132
1912
|
pendingRedemption: pendingRedemptions > 0,
|
|
1133
1913
|
redeemed: BigInt(redeemed),
|
|
@@ -1221,6 +2001,36 @@ async function getWindowShareState(tidx, options) {
|
|
|
1221
2001
|
startShares: receivedStartValue - sentStartValue,
|
|
1222
2002
|
};
|
|
1223
2003
|
}
|
|
2004
|
+
/** Builds a share-transfer predicate for the vault's verified reward distributors. */
|
|
2005
|
+
async function getRewardTransferPredicate(c, options) {
|
|
2006
|
+
const db = Db.get(c.get('db'));
|
|
2007
|
+
const campaign = await RewardCampaigns.get(db, {
|
|
2008
|
+
chainId: options.chainId,
|
|
2009
|
+
vaultAddress: options.vault,
|
|
2010
|
+
});
|
|
2011
|
+
if (!campaign)
|
|
2012
|
+
return '0';
|
|
2013
|
+
const distributors = await RewardCampaignDistributors.list(db, {
|
|
2014
|
+
chainId: options.chainId,
|
|
2015
|
+
vaultAddress: options.vault,
|
|
2016
|
+
});
|
|
2017
|
+
if (distributors.length === 0)
|
|
2018
|
+
return '0';
|
|
2019
|
+
const addresses = distributors
|
|
2020
|
+
.map(({ distributorAddress }) => Schema.Address.parse(distributorAddress))
|
|
2021
|
+
.map((address) => `'${address}'`)
|
|
2022
|
+
.join(', ');
|
|
2023
|
+
const shareToken = Schema.Address.parse(campaign.earnShareAddress);
|
|
2024
|
+
// Batch rewards have no per-recipient event; exclude treasury returns instead. Qualify the filter so TIDX does not apply it to other event CTEs.
|
|
2025
|
+
return `
|
|
2026
|
+
token = '${shareToken}'
|
|
2027
|
+
AND "from" IN (${addresses})
|
|
2028
|
+
AND tx_hash NOT IN (
|
|
2029
|
+
SELECT returned.tx_hash FROM UnspentReturned AS returned
|
|
2030
|
+
WHERE returned.address IN (${addresses})
|
|
2031
|
+
)
|
|
2032
|
+
`;
|
|
2033
|
+
}
|
|
1224
2034
|
/** Returns whether an account sent or received Earn shares outside known vault flows. */
|
|
1225
2035
|
async function hasExternalShareTransfer(tidx, options) {
|
|
1226
2036
|
// Vault exits pull shares into the vault before burning. Reconcile counts by transaction and amount so unmatched direct sends remain external.
|
|
@@ -1232,6 +2042,7 @@ async function hasExternalShareTransfer(tidx, options) {
|
|
|
1232
2042
|
SELECT count()
|
|
1233
2043
|
FROM token_transfers
|
|
1234
2044
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2045
|
+
AND toUInt256(amount) > 0
|
|
1235
2046
|
AND block_num > ${options.startBlockNumber}
|
|
1236
2047
|
AND block_num <= ${options.blockNumber}
|
|
1237
2048
|
AND (
|
|
@@ -1240,6 +2051,7 @@ async function hasExternalShareTransfer(tidx, options) {
|
|
|
1240
2051
|
"to" = '${options.account}'
|
|
1241
2052
|
AND "from" != '${zeroAddress}'
|
|
1242
2053
|
AND "from" != '${options.vault}'
|
|
2054
|
+
AND NOT (${options.rewardTransfer})
|
|
1243
2055
|
)
|
|
1244
2056
|
)
|
|
1245
2057
|
) + (
|
|
@@ -1248,6 +2060,7 @@ async function hasExternalShareTransfer(tidx, options) {
|
|
|
1248
2060
|
SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
|
|
1249
2061
|
FROM token_transfers
|
|
1250
2062
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2063
|
+
AND toUInt256(amount) > 0
|
|
1251
2064
|
AND "from" = '${options.account}'
|
|
1252
2065
|
AND "to" = '${options.vault}'
|
|
1253
2066
|
AND block_num > ${options.startBlockNumber}
|
|
@@ -1288,6 +2101,7 @@ async function hasExternalShareTransfer(tidx, options) {
|
|
|
1288
2101
|
SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
|
|
1289
2102
|
FROM token_transfers
|
|
1290
2103
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2104
|
+
AND toUInt256(amount) > 0
|
|
1291
2105
|
AND "from" = '${options.vault}'
|
|
1292
2106
|
AND "to" = '${options.account}'
|
|
1293
2107
|
AND block_num > ${options.startBlockNumber}
|
|
@@ -1311,6 +2125,7 @@ async function hasExternalShareTransfer(tidx, options) {
|
|
|
1311
2125
|
redeemCancelledSignature,
|
|
1312
2126
|
redeemedSignature,
|
|
1313
2127
|
redeemRequestedSignature,
|
|
2128
|
+
unspentReturnedSignature,
|
|
1314
2129
|
withdrewExactSignature,
|
|
1315
2130
|
],
|
|
1316
2131
|
});
|
|
@@ -1340,6 +2155,8 @@ export function calculateActiveCostBasis(options) {
|
|
|
1340
2155
|
return { costBasis: removed };
|
|
1341
2156
|
};
|
|
1342
2157
|
for (const action of options.actions) {
|
|
2158
|
+
if (action.shares === 0n)
|
|
2159
|
+
continue;
|
|
1343
2160
|
if (action.kind === 'deposit') {
|
|
1344
2161
|
if (costBasis !== undefined)
|
|
1345
2162
|
costBasis += action.assets;
|
|
@@ -1456,7 +2273,7 @@ async function getActiveCostBasis(tidx, options) {
|
|
|
1456
2273
|
AND block_num <= ${options.blockNumber}
|
|
1457
2274
|
UNION ALL
|
|
1458
2275
|
SELECT
|
|
1459
|
-
'unknown' AS kind,
|
|
2276
|
+
if(${options.rewardTransfer}, 'deposit', 'unknown') AS kind,
|
|
1460
2277
|
block_num,
|
|
1461
2278
|
log_idx,
|
|
1462
2279
|
'' AS request_id,
|
|
@@ -1464,6 +2281,7 @@ async function getActiveCostBasis(tidx, options) {
|
|
|
1464
2281
|
'0' AS assets
|
|
1465
2282
|
FROM token_transfers
|
|
1466
2283
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2284
|
+
AND toUInt256(amount) > 0
|
|
1467
2285
|
AND "to" = '${options.account}'
|
|
1468
2286
|
AND "from" != '${zeroAddress}'
|
|
1469
2287
|
AND "from" != '${options.vault}'
|
|
@@ -1478,6 +2296,7 @@ async function getActiveCostBasis(tidx, options) {
|
|
|
1478
2296
|
'0' AS assets
|
|
1479
2297
|
FROM token_transfers
|
|
1480
2298
|
WHERE token = '${options.shareToken.toLowerCase()}'
|
|
2299
|
+
AND toUInt256(amount) > 0
|
|
1481
2300
|
AND "from" = '${options.account}'
|
|
1482
2301
|
AND "to" != '${options.vault}'
|
|
1483
2302
|
AND block_num <= ${options.blockNumber}
|
|
@@ -1489,6 +2308,7 @@ async function getActiveCostBasis(tidx, options) {
|
|
|
1489
2308
|
redeemCancelledSignature,
|
|
1490
2309
|
redeemRequestedSignature,
|
|
1491
2310
|
redeemedSignature,
|
|
2311
|
+
unspentReturnedSignature,
|
|
1492
2312
|
venueSharesDepositedSignature,
|
|
1493
2313
|
withdrewExactSignature,
|
|
1494
2314
|
],
|
|
@@ -1631,7 +2451,7 @@ export async function listVaults(c, options) {
|
|
|
1631
2451
|
const missingApyVaults = include.includes('apy')
|
|
1632
2452
|
? discoveries.flatMap(({ vaultAddress }) => apyByVault.has(vaultAddress.toLowerCase()) ? [] : [vaultAddress])
|
|
1633
2453
|
: [];
|
|
1634
|
-
const [missingApy, rates, tokens] = await Promise.all([
|
|
2454
|
+
const [missingApy, rates, rewards, tokens] = await Promise.all([
|
|
1635
2455
|
missingApyVaults.length > 0
|
|
1636
2456
|
? resolvePageApy(c, {
|
|
1637
2457
|
chainId: options.chainId,
|
|
@@ -1641,12 +2461,25 @@ export async function listVaults(c, options) {
|
|
|
1641
2461
|
})
|
|
1642
2462
|
: undefined,
|
|
1643
2463
|
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
2464
|
+
resolvePageRewards(c, {
|
|
2465
|
+
chainId: options.chainId,
|
|
2466
|
+
include,
|
|
2467
|
+
vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
|
|
2468
|
+
}),
|
|
1644
2469
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
1645
2470
|
]);
|
|
1646
2471
|
for (const [vault, apy] of missingApy ?? [])
|
|
1647
2472
|
apyByVault.set(vault, apy);
|
|
1648
2473
|
const apy = include.includes('apy') ? apyByVault : undefined;
|
|
1649
|
-
const data = await Promise.all(page.map((match) => resolveVault(c, {
|
|
2474
|
+
const data = await Promise.all(page.map((match) => resolveVault(c, {
|
|
2475
|
+
...match,
|
|
2476
|
+
apy,
|
|
2477
|
+
include,
|
|
2478
|
+
rates,
|
|
2479
|
+
rewards: rewards?.get(match.discovery.vaultAddress),
|
|
2480
|
+
snapshot,
|
|
2481
|
+
tokens,
|
|
2482
|
+
})));
|
|
1650
2483
|
const last = matches[options.limit - 1];
|
|
1651
2484
|
const nextPosition = matches.length > options.limit ? last?.position : hasMore ? position : undefined;
|
|
1652
2485
|
return {
|
|
@@ -1699,7 +2532,7 @@ export async function listVerifiedVaults(c, options) {
|
|
|
1699
2532
|
}
|
|
1700
2533
|
const page = matches.slice(0, options.limit);
|
|
1701
2534
|
const discoveries = page.map(({ discovery }) => discovery);
|
|
1702
|
-
const [apy, rates, tokens] = await Promise.all([
|
|
2535
|
+
const [apy, rates, rewards, tokens] = await Promise.all([
|
|
1703
2536
|
resolvePageApy(c, {
|
|
1704
2537
|
chainId: options.chainId,
|
|
1705
2538
|
include,
|
|
@@ -1707,9 +2540,22 @@ export async function listVerifiedVaults(c, options) {
|
|
|
1707
2540
|
window: options['apy.window'],
|
|
1708
2541
|
}),
|
|
1709
2542
|
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
2543
|
+
resolvePageRewards(c, {
|
|
2544
|
+
chainId: options.chainId,
|
|
2545
|
+
include,
|
|
2546
|
+
vaults: discoveries.map(({ vaultAddress }) => vaultAddress),
|
|
2547
|
+
}),
|
|
1710
2548
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
1711
2549
|
]);
|
|
1712
|
-
const data = await Promise.all(page.map(async (match) => Response.validated(schema.VerifiedVault, await resolveVault(c, {
|
|
2550
|
+
const data = await Promise.all(page.map(async (match) => Response.validated(schema.VerifiedVault, await resolveVault(c, {
|
|
2551
|
+
...match,
|
|
2552
|
+
apy,
|
|
2553
|
+
include,
|
|
2554
|
+
rates,
|
|
2555
|
+
rewards: rewards?.get(match.discovery.vaultAddress),
|
|
2556
|
+
snapshot,
|
|
2557
|
+
tokens,
|
|
2558
|
+
}))));
|
|
1713
2559
|
const last = matches[options.limit - 1];
|
|
1714
2560
|
return {
|
|
1715
2561
|
data,
|
|
@@ -1717,13 +2563,239 @@ export async function listVerifiedVaults(c, options) {
|
|
|
1717
2563
|
nextCursor: matches.length > options.limit && last ? Cursor.encode([last.record.vaultAddress]) : null,
|
|
1718
2564
|
};
|
|
1719
2565
|
}
|
|
2566
|
+
/** Reads daily historical share prices for one Earn vault. */
|
|
2567
|
+
export async function getVaultSharePrices(c, options) {
|
|
2568
|
+
const prices = await Timing.time(c, 'earn_share_prices', () => EarnSharePrices.resolve({
|
|
2569
|
+
chainId: options.chainId,
|
|
2570
|
+
from: options.from,
|
|
2571
|
+
// This client is request-local so viem's stateful HTTP batch cannot cross Worker invocations.
|
|
2572
|
+
getClient: (chainId = options.chainId) => Viem.createBatchClient({
|
|
2573
|
+
chainId,
|
|
2574
|
+
principal: Auth.getPrincipal(c),
|
|
2575
|
+
rpc: c.get('rpc'),
|
|
2576
|
+
zone: c.get('zones').get(chainId),
|
|
2577
|
+
}),
|
|
2578
|
+
getTidx: c.get('getTidx'),
|
|
2579
|
+
shareDecimals: options.discovery.shareToken.decimals,
|
|
2580
|
+
to: options.to,
|
|
2581
|
+
vault: options.vault,
|
|
2582
|
+
}));
|
|
2583
|
+
return prices.map((price) => ({
|
|
2584
|
+
sharePrice: {
|
|
2585
|
+
amount: price.amount.toString(),
|
|
2586
|
+
currency: options.discovery.assetToken.currency,
|
|
2587
|
+
decimals: options.discovery.assetToken.decimals,
|
|
2588
|
+
formatted: core_Value.format(price.amount, options.discovery.assetToken.decimals),
|
|
2589
|
+
},
|
|
2590
|
+
timestamp: price.timestamp,
|
|
2591
|
+
}));
|
|
2592
|
+
}
|
|
2593
|
+
/** Classifies an Earn share-price dependency failure for request metrics. */
|
|
2594
|
+
export function sharePriceProviderFailure(options) {
|
|
2595
|
+
if (options.cause instanceof EarnSharePrices.MalformedResponseError)
|
|
2596
|
+
return {
|
|
2597
|
+
chainId: options.chainId,
|
|
2598
|
+
failure: 'payload',
|
|
2599
|
+
id: 'tidx',
|
|
2600
|
+
operation: 'query',
|
|
2601
|
+
};
|
|
2602
|
+
if (options.cause instanceof EarnSharePrices.TidxRequestError)
|
|
2603
|
+
return { ...Tidx.providerFailure(options.cause.cause), chainId: options.chainId };
|
|
2604
|
+
const failure = Viem.requestFailure(options.cause);
|
|
2605
|
+
if (failure)
|
|
2606
|
+
return { ...failure, chainId: options.chainId, id: 'rpc', operation: 'eth_call' };
|
|
2607
|
+
return undefined;
|
|
2608
|
+
}
|
|
2609
|
+
async function resolveSharePriceVaultDiscovery(c, options) {
|
|
2610
|
+
const result = await Store.memoize(async () => {
|
|
2611
|
+
try {
|
|
2612
|
+
return {
|
|
2613
|
+
discovery: await readVaultDiscovery(c, { ...options, include: [] }),
|
|
2614
|
+
status: 'found',
|
|
2615
|
+
};
|
|
2616
|
+
}
|
|
2617
|
+
catch (cause) {
|
|
2618
|
+
if (isIncompatible(cause))
|
|
2619
|
+
return { status: 'not_found' };
|
|
2620
|
+
throw cause;
|
|
2621
|
+
}
|
|
2622
|
+
}, {
|
|
2623
|
+
key: `earn-share-price-vault:v1:${options.chainId}:${options.vaultAddress.toLowerCase()}`,
|
|
2624
|
+
store: c.get('store'),
|
|
2625
|
+
ttl: Ttl.seconds(5),
|
|
2626
|
+
});
|
|
2627
|
+
return result.status === 'found' ? result.discovery : undefined;
|
|
2628
|
+
}
|
|
2629
|
+
/** Reads one direct or Zone-routed account position in a parent-chain Earn vault. */
|
|
2630
|
+
export async function getVaultPosition(c, options) {
|
|
2631
|
+
const zone = c.get('zones').get(options.chainId);
|
|
2632
|
+
if (!zone) {
|
|
2633
|
+
const block = options.asOf === undefined
|
|
2634
|
+
? undefined
|
|
2635
|
+
: await getIndexedBlockAtOrBefore(c.get('getTidx')(options.chainId), options.asOf);
|
|
2636
|
+
const position = await c
|
|
2637
|
+
.get('getClient')(options.chainId)
|
|
2638
|
+
.earn.getPosition({
|
|
2639
|
+
account: options.account,
|
|
2640
|
+
...(block ? { blockNumber: BigInt(block.number) } : {}),
|
|
2641
|
+
vault: options.vault,
|
|
2642
|
+
});
|
|
2643
|
+
return { ...position, block, valueToken: position.assetToken };
|
|
2644
|
+
}
|
|
2645
|
+
const route = await resolveZonePositionRoute(c, {
|
|
2646
|
+
chainId: options.chainId,
|
|
2647
|
+
vault: options.vault,
|
|
2648
|
+
});
|
|
2649
|
+
const block = options.asOf === undefined
|
|
2650
|
+
? undefined
|
|
2651
|
+
: await getIndexedBlockAtOrBefore(c.get('getTidx')(options.chainId), options.asOf);
|
|
2652
|
+
const zoneClient = c.get('getClient')(options.chainId);
|
|
2653
|
+
const blockNumber = block ? BigInt(block.number) : await zoneClient.getBlockNumber();
|
|
2654
|
+
const [assetBalance, shareBalance, importedParentBlockNumber] = await Promise.all([
|
|
2655
|
+
readZoneBalance(zoneClient, {
|
|
2656
|
+
account: options.account,
|
|
2657
|
+
blockNumber,
|
|
2658
|
+
token: route.privateAsset,
|
|
2659
|
+
}),
|
|
2660
|
+
readZoneBalance(zoneClient, {
|
|
2661
|
+
account: options.account,
|
|
2662
|
+
blockNumber,
|
|
2663
|
+
token: route.shareToken,
|
|
2664
|
+
}),
|
|
2665
|
+
readZoneSourceBlock(c, {
|
|
2666
|
+
blockNumber,
|
|
2667
|
+
historical: block !== undefined,
|
|
2668
|
+
portal: route.portal,
|
|
2669
|
+
sourceChainId: route.sourceChainId,
|
|
2670
|
+
zoneClient,
|
|
2671
|
+
}),
|
|
2672
|
+
]);
|
|
2673
|
+
const sourceBlock = Value.toNumber(importedParentBlockNumber);
|
|
2674
|
+
if (sourceBlock === undefined || sourceBlock < route.deploymentBlock)
|
|
2675
|
+
throw new EarnVaults.NotFoundError();
|
|
2676
|
+
const value = await c
|
|
2677
|
+
.get('getClient')(route.sourceChainId)
|
|
2678
|
+
.earn.getRedeemQuote({
|
|
2679
|
+
blockNumber: BigInt(sourceBlock),
|
|
2680
|
+
shareAmount: shareBalance,
|
|
2681
|
+
vault: options.vault,
|
|
2682
|
+
});
|
|
2683
|
+
return {
|
|
2684
|
+
assetAllowance: 0n,
|
|
2685
|
+
assetBalance,
|
|
2686
|
+
assetToken: route.privateAsset,
|
|
2687
|
+
block,
|
|
2688
|
+
shareAllowance: 0n,
|
|
2689
|
+
shareBalance,
|
|
2690
|
+
shareToken: route.shareToken,
|
|
2691
|
+
value,
|
|
2692
|
+
valueToken: route.vaultAsset,
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
/** Reads a private Zone token balance with the holder as the authorized RPC caller. */
|
|
2696
|
+
async function readZoneBalance(client, options) {
|
|
2697
|
+
return client.readContract({
|
|
2698
|
+
abi: tokenPositionAbi,
|
|
2699
|
+
account: options.account,
|
|
2700
|
+
address: options.token,
|
|
2701
|
+
args: [options.account],
|
|
2702
|
+
...(options.blockNumber === undefined ? {} : { blockNumber: options.blockNumber }),
|
|
2703
|
+
functionName: 'balanceOf',
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
/** Reads the parent Tempo checkpoint imported by one Zone observation. */
|
|
2707
|
+
async function readZoneSourceBlock(c, options) {
|
|
2708
|
+
const verifiedPromise = c.get('getClient')(options.sourceChainId).readContract({
|
|
2709
|
+
abi: zonePortalAbi,
|
|
2710
|
+
address: options.portal,
|
|
2711
|
+
functionName: 'lastSyncedTempoBlockNumber',
|
|
2712
|
+
});
|
|
2713
|
+
// A historical Zone without TempoState rejects before awaiting the portal.
|
|
2714
|
+
void verifiedPromise.catch(() => undefined);
|
|
2715
|
+
const reported = await (async () => {
|
|
2716
|
+
try {
|
|
2717
|
+
return await options.zoneClient.readContract({
|
|
2718
|
+
abi: tempoStateAbi,
|
|
2719
|
+
address: tempoStateAddress,
|
|
2720
|
+
blockNumber: options.blockNumber,
|
|
2721
|
+
functionName: 'tempoBlockNumber',
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2724
|
+
catch (cause) {
|
|
2725
|
+
if (!(cause instanceof ContractFunctionExecutionError) ||
|
|
2726
|
+
!(cause.cause instanceof ContractFunctionZeroDataError))
|
|
2727
|
+
throw cause;
|
|
2728
|
+
if (options.historical)
|
|
2729
|
+
throw new ZoneHistoricalAlignmentError();
|
|
2730
|
+
return undefined;
|
|
2731
|
+
}
|
|
2732
|
+
})();
|
|
2733
|
+
const verified = await verifiedPromise;
|
|
2734
|
+
return alignZoneSourceBlock({ reported, verified });
|
|
2735
|
+
}
|
|
2736
|
+
/** Caps a Zone-reported parent checkpoint at the L1 portal's verified watermark. */
|
|
2737
|
+
export function alignZoneSourceBlock(options) {
|
|
2738
|
+
if (options.reported === undefined || options.verified < options.reported)
|
|
2739
|
+
return options.verified;
|
|
2740
|
+
return options.reported;
|
|
2741
|
+
}
|
|
2742
|
+
/** Resolves the verified parent vault and token pair for one Zone route. */
|
|
2743
|
+
async function resolveZonePositionRoute(c, options) {
|
|
2744
|
+
const zone = c.get('zones').get(options.chainId);
|
|
2745
|
+
if (!zone?.sourceId)
|
|
2746
|
+
throw new EarnVaults.NotFoundError();
|
|
2747
|
+
const db = Db.get(c.get('dbCached'));
|
|
2748
|
+
const record = await core_EarnVaults.get(db, {
|
|
2749
|
+
chainId: zone.sourceId,
|
|
2750
|
+
vaultAddress: options.vault,
|
|
2751
|
+
});
|
|
2752
|
+
const configured = record?.zones.find((route) => route.chainId === options.chainId);
|
|
2753
|
+
if (!record || !configured)
|
|
2754
|
+
throw new EarnVaults.NotFoundError();
|
|
2755
|
+
const discovery = await resolveVaultDiscovery(c, {
|
|
2756
|
+
chainId: zone.sourceId,
|
|
2757
|
+
include: [],
|
|
2758
|
+
vaultAddress: options.vault,
|
|
2759
|
+
});
|
|
2760
|
+
const [route] = await EarnVaults.resolveZoneRoutes({
|
|
2761
|
+
discovery,
|
|
2762
|
+
getClient: c.get('getClient'),
|
|
2763
|
+
routes: [configured],
|
|
2764
|
+
zones: [...c.get('zones').values()],
|
|
2765
|
+
});
|
|
2766
|
+
const privateAsset = route?.inputTokens[0];
|
|
2767
|
+
const portalContract = zone.contracts?.['portal'];
|
|
2768
|
+
const portal = Schema.Address.safeParse(portalContract && 'address' in portalContract
|
|
2769
|
+
? portalContract.address
|
|
2770
|
+
: portalContract?.[zone.sourceId]?.address);
|
|
2771
|
+
if (!route || !privateAsset || !portal.success)
|
|
2772
|
+
throw new EarnVaults.NotFoundError();
|
|
2773
|
+
return {
|
|
2774
|
+
deploymentBlock: route.deploymentBlock,
|
|
2775
|
+
portal: portal.data,
|
|
2776
|
+
privateAsset,
|
|
2777
|
+
shareToken: discovery.shareToken.address,
|
|
2778
|
+
sourceChainId: zone.sourceId,
|
|
2779
|
+
vaultAsset: discovery.assetToken.address,
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
1720
2782
|
/** Lists every vault where an account holds earn shares, ordered by vault address. */
|
|
1721
2783
|
export async function listPositions(c, options) {
|
|
1722
2784
|
const denomination = options['valuation.currency'];
|
|
2785
|
+
const zone = c.get('zones').get(options.chainId);
|
|
2786
|
+
if (zone && options.include.includes('earnings'))
|
|
2787
|
+
throw new ZoneEarningsUnsupportedError();
|
|
2788
|
+
const sourceChainId = zone ? zone.sourceId : options.chainId;
|
|
2789
|
+
if (sourceChainId === undefined)
|
|
2790
|
+
throw new EarnVaults.NotFoundError();
|
|
1723
2791
|
const db = Db.get(c.get('dbCached'));
|
|
1724
|
-
const recordsPromise = core_EarnVaults
|
|
2792
|
+
const recordsPromise = core_EarnVaults
|
|
2793
|
+
.list(db, { chainId: sourceChainId })
|
|
2794
|
+
.then((records) => zone
|
|
2795
|
+
? records.filter((record) => record.zones.some((route) => route.chainId === options.chainId))
|
|
2796
|
+
: records);
|
|
1725
2797
|
// The verified page needs no index: the registry is the candidate set.
|
|
1726
|
-
const heldPromise = options.verified
|
|
2798
|
+
const heldPromise = options.verified || zone
|
|
1727
2799
|
? undefined
|
|
1728
2800
|
: queryHeldVaults(c, { address: options.address, chainId: options.chainId });
|
|
1729
2801
|
// Observing these branches prevents unhandled rejections while the
|
|
@@ -1759,14 +2831,16 @@ export async function listPositions(c, options) {
|
|
|
1759
2831
|
const read = await Timing.time(c, 'earn_positions', () => Promise.all(batch.map(async (vault) => {
|
|
1760
2832
|
const record = registry.get(vault);
|
|
1761
2833
|
try {
|
|
1762
|
-
const position = await
|
|
1763
|
-
|
|
2834
|
+
const position = await getVaultPosition(c, {
|
|
2835
|
+
account: options.address,
|
|
1764
2836
|
chainId: options.chainId,
|
|
1765
|
-
|
|
2837
|
+
vault: Schema.Address.parse(vault),
|
|
1766
2838
|
});
|
|
1767
2839
|
return { position, record, vaultAddress: vault };
|
|
1768
2840
|
}
|
|
1769
2841
|
catch (cause) {
|
|
2842
|
+
if (cause instanceof EarnVaults.NotFoundError)
|
|
2843
|
+
return undefined;
|
|
1770
2844
|
if (!record && isIncompatible(cause))
|
|
1771
2845
|
return undefined;
|
|
1772
2846
|
throw cause;
|
|
@@ -1779,7 +2853,17 @@ export async function listPositions(c, options) {
|
|
|
1779
2853
|
}
|
|
1780
2854
|
}
|
|
1781
2855
|
const page = matches.slice(0, options.limit);
|
|
1782
|
-
const
|
|
2856
|
+
const indexedBlock = !zone && page.length > 0 && options.include.includes('earnings')
|
|
2857
|
+
? await getLatestIndexedBlock(c.get('getTidx')(options.chainId))
|
|
2858
|
+
: undefined;
|
|
2859
|
+
const [cashFlows, tokens, valueTokens, snapshot] = await Promise.all([
|
|
2860
|
+
indexedBlock
|
|
2861
|
+
? getVaultLifetimeCashFlows(c.get('getTidx')(options.chainId), {
|
|
2862
|
+
account: options.address,
|
|
2863
|
+
blockNumber: indexedBlock.number,
|
|
2864
|
+
vaults: page.map(({ vaultAddress }) => Schema.Address.parse(vaultAddress)),
|
|
2865
|
+
})
|
|
2866
|
+
: undefined,
|
|
1783
2867
|
(async () => {
|
|
1784
2868
|
const addresses = [
|
|
1785
2869
|
...new Set(page.flatMap(({ position }) => [position.assetToken, position.shareToken])),
|
|
@@ -1793,12 +2877,19 @@ export async function listPositions(c, options) {
|
|
|
1793
2877
|
}));
|
|
1794
2878
|
return new Map(groups.flatMap((group) => [...group]));
|
|
1795
2879
|
})(),
|
|
1796
|
-
|
|
2880
|
+
zone
|
|
2881
|
+
? Tokens.resolveTokens(c, {
|
|
2882
|
+
addresses: [...new Set(page.map(({ position }) => position.valueToken))],
|
|
2883
|
+
chainId: sourceChainId,
|
|
2884
|
+
include: ['token.verified'],
|
|
2885
|
+
})
|
|
2886
|
+
: undefined,
|
|
2887
|
+
denomination ? VerifiedTokens.snapshot(c, sourceChainId) : undefined,
|
|
1797
2888
|
]);
|
|
1798
2889
|
const rates = denomination && snapshot
|
|
1799
2890
|
? await Valuation.ratesFor(c, {
|
|
1800
2891
|
currencies: page.flatMap(({ position }) => {
|
|
1801
|
-
const currency = snapshot.byAddress.get(position.
|
|
2892
|
+
const currency = snapshot.byAddress.get(position.valueToken.toLowerCase())?.currency;
|
|
1802
2893
|
return currency === undefined ? [] : [currency];
|
|
1803
2894
|
}),
|
|
1804
2895
|
denomination,
|
|
@@ -1815,11 +2906,14 @@ export async function listPositions(c, options) {
|
|
|
1815
2906
|
: undefined;
|
|
1816
2907
|
return {
|
|
1817
2908
|
data: page.map((match) => serializePosition({
|
|
2909
|
+
cashFlows: cashFlows?.get(match.vaultAddress),
|
|
2910
|
+
chainId: options.chainId,
|
|
1818
2911
|
denomination,
|
|
1819
2912
|
position: match.position,
|
|
1820
2913
|
rates,
|
|
1821
2914
|
snapshot,
|
|
1822
2915
|
tokens,
|
|
2916
|
+
valueTokens,
|
|
1823
2917
|
vaultAddress: match.vaultAddress,
|
|
1824
2918
|
verified: match.record !== undefined,
|
|
1825
2919
|
})),
|
|
@@ -1829,12 +2923,12 @@ export async function listPositions(c, options) {
|
|
|
1829
2923
|
}
|
|
1830
2924
|
/** Finds vaults whose earn share token the account has ever held, by vault address. */
|
|
1831
2925
|
async function queryHeldVaults(c, options) {
|
|
2926
|
+
const factories = deploymentFactories[options.chainId] ?? [];
|
|
2927
|
+
if (factories.length === 0)
|
|
2928
|
+
return [];
|
|
1832
2929
|
const tidx = c.get('getTidx')(options.chainId);
|
|
1833
|
-
//
|
|
1834
|
-
//
|
|
1835
|
-
// candidates in one round trip, with no literal list to overflow the request.
|
|
1836
|
-
// Earn shares are factory-minted TIP-20s, so the `0x20c0` prefix bounds the
|
|
1837
|
-
// subquery. Stale delta rows are fine: the live read drops them.
|
|
2930
|
+
// Filter emitters before ranking so forged events cannot replace share bindings.
|
|
2931
|
+
// TIP-20 prefixes bound holder scans; live reads discard exited positions.
|
|
1838
2932
|
const result = await Timing.time(c, 'earn_positions_discovery', () => tidx.fetch({
|
|
1839
2933
|
chainId: options.chainId,
|
|
1840
2934
|
engine: 'clickhouse',
|
|
@@ -1849,6 +2943,7 @@ async function queryHeldVaults(c, options) {
|
|
|
1849
2943
|
ORDER BY block_num DESC, log_idx DESC
|
|
1850
2944
|
) AS deployment_rank
|
|
1851
2945
|
FROM EarnStackDeployed
|
|
2946
|
+
WHERE address IN (${factories.map((address) => `'${address}'`).join(', ')})
|
|
1852
2947
|
)
|
|
1853
2948
|
WHERE deployment_rank = 1 AND lower("earnShare") IN (
|
|
1854
2949
|
SELECT DISTINCT lower(token)
|
|
@@ -1865,22 +2960,19 @@ async function queryHeldVaults(c, options) {
|
|
|
1865
2960
|
return vault.success ? [vault.data.toLowerCase()] : [];
|
|
1866
2961
|
});
|
|
1867
2962
|
}
|
|
1868
|
-
/** Reads one account's live position in one vault. */
|
|
1869
|
-
function readPosition(c, options) {
|
|
1870
|
-
return c
|
|
1871
|
-
.get('getClient')(options.chainId)
|
|
1872
|
-
.earn.getPosition({ account: options.address, vault: options.vaultAddress });
|
|
1873
|
-
}
|
|
1874
2963
|
/** Serializes one live position into the address-scoped row contract. */
|
|
1875
2964
|
function serializePosition(options) {
|
|
1876
2965
|
const { position, tokens } = options;
|
|
1877
2966
|
const assetToken = getToken(tokens, position.assetToken);
|
|
1878
2967
|
const shareToken = getToken(tokens, position.shareToken);
|
|
2968
|
+
const valueToken = getToken(options.valueTokens ?? tokens, position.valueToken);
|
|
1879
2969
|
const vaultAddress = Schema.Address.parse(options.vaultAddress.toLowerCase());
|
|
1880
2970
|
return {
|
|
1881
|
-
assetAmount: valueFor(position.value,
|
|
2971
|
+
assetAmount: valueFor(position.value, valueToken),
|
|
1882
2972
|
assetToken,
|
|
2973
|
+
chainId: options.chainId,
|
|
1883
2974
|
id: vaultAddress,
|
|
2975
|
+
...(options.cashFlows ? { lifetimeCashFlows: options.cashFlows } : {}),
|
|
1884
2976
|
shareAmount: valueFor(position.shareBalance, shareToken),
|
|
1885
2977
|
shareToken,
|
|
1886
2978
|
...(options.denomination
|
|
@@ -1889,14 +2981,138 @@ function serializePosition(options) {
|
|
|
1889
2981
|
amount: position.value,
|
|
1890
2982
|
denomination: options.denomination,
|
|
1891
2983
|
rates: options.rates,
|
|
1892
|
-
token: options.snapshot?.byAddress.get(
|
|
2984
|
+
token: options.snapshot?.byAddress.get(valueToken.address),
|
|
1893
2985
|
}),
|
|
1894
2986
|
}
|
|
1895
2987
|
: {}),
|
|
2988
|
+
valueToken,
|
|
1896
2989
|
vaultAddress,
|
|
1897
2990
|
verified: options.verified,
|
|
1898
2991
|
};
|
|
1899
2992
|
}
|
|
2993
|
+
/** Reads complete protocol cash flows for one account and a set of vaults. */
|
|
2994
|
+
export async function getVaultLifetimeCashFlows(tidx, options) {
|
|
2995
|
+
const vaults = [...new Set(options.vaults.map((vault) => vault.toLowerCase()))];
|
|
2996
|
+
const cashFlows = new Map();
|
|
2997
|
+
if (vaults.length === 0)
|
|
2998
|
+
return cashFlows;
|
|
2999
|
+
const addresses = vaults.map((vault) => `'${vault}'`).join(', ');
|
|
3000
|
+
const seeds = vaults
|
|
3001
|
+
.map((vault) => `
|
|
3002
|
+
SELECT '${vault}' AS vault,
|
|
3003
|
+
toUInt256(0) AS deposited_assets,
|
|
3004
|
+
toUInt256(0) AS finalized_assets,
|
|
3005
|
+
toUInt256(0) AS redeemed_assets,
|
|
3006
|
+
toUInt64(0) AS venue_deposits,
|
|
3007
|
+
toUInt256(0) AS withdrew_exact`)
|
|
3008
|
+
.join('\n UNION ALL');
|
|
3009
|
+
const result = await tidx.fetch({
|
|
3010
|
+
engine: 'clickhouse',
|
|
3011
|
+
query: `
|
|
3012
|
+
SELECT vault,
|
|
3013
|
+
toString(sum(deposited_assets)) AS deposited_assets,
|
|
3014
|
+
toString(sum(finalized_assets)) AS finalized_assets,
|
|
3015
|
+
toString(sum(redeemed_assets)) AS redeemed_assets,
|
|
3016
|
+
sum(venue_deposits) AS venue_deposits,
|
|
3017
|
+
toString(sum(withdrew_exact)) AS withdrew_exact
|
|
3018
|
+
FROM (
|
|
3019
|
+
${seeds}
|
|
3020
|
+
UNION ALL
|
|
3021
|
+
SELECT address AS vault, sum(toUInt256(assets)) AS deposited_assets,
|
|
3022
|
+
toUInt256(0) AS finalized_assets, toUInt256(0) AS redeemed_assets,
|
|
3023
|
+
toUInt64(0) AS venue_deposits, toUInt256(0) AS withdrew_exact
|
|
3024
|
+
FROM Deposited
|
|
3025
|
+
WHERE address IN (${addresses})
|
|
3026
|
+
AND receiver = '${options.account}'
|
|
3027
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
3028
|
+
AND block_num <= ${options.blockNumber}
|
|
3029
|
+
GROUP BY address
|
|
3030
|
+
UNION ALL
|
|
3031
|
+
SELECT finalized.address AS vault, toUInt256(0) AS deposited_assets,
|
|
3032
|
+
sum(toUInt256(finalized.assets)) AS finalized_assets,
|
|
3033
|
+
toUInt256(0) AS redeemed_assets, toUInt64(0) AS venue_deposits,
|
|
3034
|
+
toUInt256(0) AS withdrew_exact
|
|
3035
|
+
FROM RedeemFinalized AS finalized
|
|
3036
|
+
INNER JOIN RedeemRequested AS requested
|
|
3037
|
+
ON requested.address = finalized.address
|
|
3038
|
+
AND requested."requestId" = finalized."requestId"
|
|
3039
|
+
WHERE finalized.address IN (${addresses})
|
|
3040
|
+
AND requested.requester = '${options.account}'
|
|
3041
|
+
AND finalized.block_num > ${beforeFirstBlockNumber}
|
|
3042
|
+
AND finalized.block_num <= ${options.blockNumber}
|
|
3043
|
+
AND requested.block_num <= ${options.blockNumber}
|
|
3044
|
+
GROUP BY finalized.address
|
|
3045
|
+
UNION ALL
|
|
3046
|
+
SELECT address AS vault, toUInt256(0) AS deposited_assets,
|
|
3047
|
+
toUInt256(0) AS finalized_assets, sum(toUInt256(assets)) AS redeemed_assets,
|
|
3048
|
+
toUInt64(0) AS venue_deposits,
|
|
3049
|
+
toUInt256(0) AS withdrew_exact
|
|
3050
|
+
FROM Redeemed
|
|
3051
|
+
WHERE address IN (${addresses})
|
|
3052
|
+
AND caller = '${options.account}'
|
|
3053
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
3054
|
+
AND block_num <= ${options.blockNumber}
|
|
3055
|
+
GROUP BY address
|
|
3056
|
+
UNION ALL
|
|
3057
|
+
SELECT address AS vault, toUInt256(0) AS deposited_assets,
|
|
3058
|
+
toUInt256(0) AS finalized_assets, toUInt256(0) AS redeemed_assets,
|
|
3059
|
+
count() AS venue_deposits, toUInt256(0) AS withdrew_exact
|
|
3060
|
+
FROM VenueSharesDeposited
|
|
3061
|
+
WHERE address IN (${addresses})
|
|
3062
|
+
AND receiver = '${options.account}'
|
|
3063
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
3064
|
+
AND block_num <= ${options.blockNumber}
|
|
3065
|
+
GROUP BY address
|
|
3066
|
+
UNION ALL
|
|
3067
|
+
SELECT address AS vault, toUInt256(0) AS deposited_assets,
|
|
3068
|
+
toUInt256(0) AS finalized_assets, toUInt256(0) AS redeemed_assets,
|
|
3069
|
+
toUInt64(0) AS venue_deposits, sum(toUInt256(assets)) AS withdrew_exact
|
|
3070
|
+
FROM WithdrewExact
|
|
3071
|
+
WHERE address IN (${addresses})
|
|
3072
|
+
AND caller = '${options.account}'
|
|
3073
|
+
AND block_num > ${beforeFirstBlockNumber}
|
|
3074
|
+
AND block_num <= ${options.blockNumber}
|
|
3075
|
+
GROUP BY address
|
|
3076
|
+
) AS histories
|
|
3077
|
+
GROUP BY vault
|
|
3078
|
+
`,
|
|
3079
|
+
signatures: [
|
|
3080
|
+
depositedSignature,
|
|
3081
|
+
redeemFinalizedSignature,
|
|
3082
|
+
redeemRequestedSignature,
|
|
3083
|
+
redeemedSignature,
|
|
3084
|
+
venueSharesDepositedSignature,
|
|
3085
|
+
withdrewExactSignature,
|
|
3086
|
+
],
|
|
3087
|
+
});
|
|
3088
|
+
for (const row of result.rows) {
|
|
3089
|
+
const vault = Schema.Address.safeParse(Value.toText(row['vault']));
|
|
3090
|
+
const deposited = Value.toIntegerString(row['deposited_assets']);
|
|
3091
|
+
const finalized = Value.toIntegerString(row['finalized_assets']);
|
|
3092
|
+
const redeemed = Value.toIntegerString(row['redeemed_assets']);
|
|
3093
|
+
const venueDeposits = Value.toNumber(row['venue_deposits']);
|
|
3094
|
+
const withdrewExact = Value.toIntegerString(row['withdrew_exact']);
|
|
3095
|
+
if (!vault.success ||
|
|
3096
|
+
deposited === undefined ||
|
|
3097
|
+
finalized === undefined ||
|
|
3098
|
+
redeemed === undefined ||
|
|
3099
|
+
venueDeposits === undefined ||
|
|
3100
|
+
withdrewExact === undefined)
|
|
3101
|
+
throw new Error('TIDX returned invalid Earn lifetime cash flows.');
|
|
3102
|
+
cashFlows.set(vault.data.toLowerCase(), venueDeposits > 0
|
|
3103
|
+
? { status: 'incomplete_history' }
|
|
3104
|
+
: {
|
|
3105
|
+
status: 'complete',
|
|
3106
|
+
totalDeposited: deposited,
|
|
3107
|
+
totalWithdrawn: (BigInt(finalized) +
|
|
3108
|
+
BigInt(redeemed) +
|
|
3109
|
+
BigInt(withdrewExact)).toString(),
|
|
3110
|
+
});
|
|
3111
|
+
}
|
|
3112
|
+
if (cashFlows.size !== vaults.length)
|
|
3113
|
+
throw new Error('TIDX returned incomplete Earn lifetime cash flows.');
|
|
3114
|
+
return cashFlows;
|
|
3115
|
+
}
|
|
1900
3116
|
/** Renders a base-unit amount in the token's display currency and precision. */
|
|
1901
3117
|
function valueFor(amount, token) {
|
|
1902
3118
|
return {
|
|
@@ -1930,7 +3146,7 @@ export async function getVault(c, options) {
|
|
|
1930
3146
|
record,
|
|
1931
3147
|
});
|
|
1932
3148
|
const discoveries = [discovery];
|
|
1933
|
-
const [apy, rates, tokens] = await Promise.all([
|
|
3149
|
+
const [apy, rates, rewards, tokens] = await Promise.all([
|
|
1934
3150
|
resolvePageApy(c, {
|
|
1935
3151
|
chainId: options.chainId,
|
|
1936
3152
|
include,
|
|
@@ -1938,6 +3154,11 @@ export async function getVault(c, options) {
|
|
|
1938
3154
|
window: options['apy.window'],
|
|
1939
3155
|
}),
|
|
1940
3156
|
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
3157
|
+
resolveVaultRewards(c, {
|
|
3158
|
+
chainId: options.chainId,
|
|
3159
|
+
include,
|
|
3160
|
+
vault: discovery.vaultAddress,
|
|
3161
|
+
}),
|
|
1941
3162
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
1942
3163
|
]);
|
|
1943
3164
|
return {
|
|
@@ -1947,6 +3168,7 @@ export async function getVault(c, options) {
|
|
|
1947
3168
|
include,
|
|
1948
3169
|
rates,
|
|
1949
3170
|
record,
|
|
3171
|
+
rewards,
|
|
1950
3172
|
snapshot,
|
|
1951
3173
|
tokens,
|
|
1952
3174
|
zoneRoutes,
|
|
@@ -1993,7 +3215,16 @@ function discoveryInclude(options) {
|
|
|
1993
3215
|
];
|
|
1994
3216
|
}
|
|
1995
3217
|
async function resolveVaultDiscovery(c, options) {
|
|
1996
|
-
return Store.memoize(() =>
|
|
3218
|
+
return Store.memoize(() => readVaultDiscovery(c, options), {
|
|
3219
|
+
key: `earn-vault:v3:${options.chainId}:${options.vaultAddress.toLowerCase()}:include:${options.include.join(',') || 'base'}`,
|
|
3220
|
+
store: c.get('store'),
|
|
3221
|
+
// Matches the routes' `state` policy `max-age` so the two cache layers do
|
|
3222
|
+
// not compound staleness on live vault state.
|
|
3223
|
+
ttl: Ttl.seconds(30),
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3226
|
+
async function readVaultDiscovery(c, options) {
|
|
3227
|
+
return Timing.time(c, 'earn_vault_discovery', () => EarnVaults.resolve({
|
|
1997
3228
|
getClient: c.get('getClient'),
|
|
1998
3229
|
include: options.include,
|
|
1999
3230
|
input: {
|
|
@@ -2001,13 +3232,7 @@ async function resolveVaultDiscovery(c, options) {
|
|
|
2001
3232
|
vaultAddress: options.vaultAddress,
|
|
2002
3233
|
},
|
|
2003
3234
|
zones: [...c.get('zones').values()],
|
|
2004
|
-
}))
|
|
2005
|
-
key: `earn-vault:v3:${options.chainId}:${options.vaultAddress.toLowerCase()}:include:${options.include.join(',') || 'base'}`,
|
|
2006
|
-
store: c.get('store'),
|
|
2007
|
-
// Matches the routes' `state` policy `max-age` so the two cache layers do
|
|
2008
|
-
// not compound staleness on live vault state.
|
|
2009
|
-
ttl: Ttl.seconds(30),
|
|
2010
|
-
});
|
|
3235
|
+
}));
|
|
2011
3236
|
}
|
|
2012
3237
|
async function resolveVaultRoutes(c, options) {
|
|
2013
3238
|
const { discovery, record } = options;
|
|
@@ -2042,6 +3267,106 @@ async function resolveVaultRoutes(c, options) {
|
|
|
2042
3267
|
: [],
|
|
2043
3268
|
};
|
|
2044
3269
|
}
|
|
3270
|
+
async function resolvePositionApy(c, options) {
|
|
3271
|
+
const sourceChainId = c.get('zones').get(options.chainId)?.sourceId ?? options.chainId;
|
|
3272
|
+
const recordFailure = (failure) => {
|
|
3273
|
+
Cache.setPolicy(c, Cache.policies.noStore);
|
|
3274
|
+
c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure]);
|
|
3275
|
+
};
|
|
3276
|
+
const rateFailures = [];
|
|
3277
|
+
const [rates, discovery] = await Promise.all([
|
|
3278
|
+
Timing.time(c, 'earn_apy', () => EarnRates.resolve({
|
|
3279
|
+
chainId: sourceChainId,
|
|
3280
|
+
getClient: c.get('getClient'),
|
|
3281
|
+
getTidx: c.get('getTidx'),
|
|
3282
|
+
onFailure: (failure) => {
|
|
3283
|
+
rateFailures.push({ ...failure, chainId: sourceChainId });
|
|
3284
|
+
},
|
|
3285
|
+
store: c.get('store'),
|
|
3286
|
+
vaults: [options.vault],
|
|
3287
|
+
})).catch(() => {
|
|
3288
|
+
rateFailures.push({
|
|
3289
|
+
chainId: sourceChainId,
|
|
3290
|
+
failure: 'unknown',
|
|
3291
|
+
id: 'earn-apy',
|
|
3292
|
+
operation: 'resolve',
|
|
3293
|
+
});
|
|
3294
|
+
return undefined;
|
|
3295
|
+
}),
|
|
3296
|
+
resolveVaultDiscovery(c, {
|
|
3297
|
+
chainId: sourceChainId,
|
|
3298
|
+
include: [],
|
|
3299
|
+
vaultAddress: options.vault,
|
|
3300
|
+
}).catch((cause) => {
|
|
3301
|
+
const failure = Viem.requestFailure(cause);
|
|
3302
|
+
recordFailure(failure
|
|
3303
|
+
? { ...failure, chainId: sourceChainId, id: 'rpc', operation: 'eth_call' }
|
|
3304
|
+
: {
|
|
3305
|
+
chainId: sourceChainId,
|
|
3306
|
+
failure: 'unknown',
|
|
3307
|
+
id: 'earn-vaults',
|
|
3308
|
+
operation: 'getVault',
|
|
3309
|
+
});
|
|
3310
|
+
return undefined;
|
|
3311
|
+
}),
|
|
3312
|
+
]);
|
|
3313
|
+
const base = rates?.get(options.vault.toLowerCase());
|
|
3314
|
+
const rateFailure = rateFailures[0];
|
|
3315
|
+
if (rateFailure)
|
|
3316
|
+
recordFailure(rateFailure);
|
|
3317
|
+
if (!base || !discovery)
|
|
3318
|
+
return null;
|
|
3319
|
+
return await Timing.time(c, 'earn_rewards_apy', async () => {
|
|
3320
|
+
const [earnFees, record] = await Promise.all([
|
|
3321
|
+
c.get('getClient')(sourceChainId).readContract({
|
|
3322
|
+
abi: Abis.earnVault,
|
|
3323
|
+
address: options.vault,
|
|
3324
|
+
functionName: 'earnFees',
|
|
3325
|
+
}),
|
|
3326
|
+
core_EarnVaults.get(Db.get(c.get('db')), {
|
|
3327
|
+
chainId: options.chainId,
|
|
3328
|
+
vaultAddress: options.vault,
|
|
3329
|
+
}),
|
|
3330
|
+
]);
|
|
3331
|
+
// Accounting retains qualified shares for excluded infrastructure, so apply its current exclusions here too.
|
|
3332
|
+
const zoneContracts = [...c.get('zones').values()]
|
|
3333
|
+
.filter((zone) => zone.sourceId === options.chainId)
|
|
3334
|
+
.flatMap((zone) => positionApyContractAddresses(zone.contracts));
|
|
3335
|
+
return RewardRead.positionApy({
|
|
3336
|
+
assetDecimals: discovery.assetToken.decimals,
|
|
3337
|
+
baseNet: base.net,
|
|
3338
|
+
chainId: options.chainId,
|
|
3339
|
+
db: c.get('db'),
|
|
3340
|
+
excludedAddresses: [
|
|
3341
|
+
discovery.engine.address,
|
|
3342
|
+
earnFees,
|
|
3343
|
+
...(record?.zones.map((zone) => zone.earnRouter) ?? []),
|
|
3344
|
+
...zoneContracts,
|
|
3345
|
+
],
|
|
3346
|
+
recipient: options.recipient,
|
|
3347
|
+
shareBalance: options.shareBalance.toString(),
|
|
3348
|
+
value: options.value.toString(),
|
|
3349
|
+
vaultAddress: options.vault,
|
|
3350
|
+
});
|
|
3351
|
+
}).catch((cause) => {
|
|
3352
|
+
recordFailure(sharePriceProviderFailure({ cause, chainId: sourceChainId }) ?? {
|
|
3353
|
+
chainId: options.chainId,
|
|
3354
|
+
failure: 'unknown',
|
|
3355
|
+
id: 'earn-rewards',
|
|
3356
|
+
operation: 'getPositionApy',
|
|
3357
|
+
});
|
|
3358
|
+
return null;
|
|
3359
|
+
});
|
|
3360
|
+
}
|
|
3361
|
+
function positionApyContractAddresses(contract) {
|
|
3362
|
+
if (!contract || typeof contract !== 'object')
|
|
3363
|
+
return [];
|
|
3364
|
+
const value = contract;
|
|
3365
|
+
const address = value['address'];
|
|
3366
|
+
if (typeof address === 'string' && isAddress(address))
|
|
3367
|
+
return [address];
|
|
3368
|
+
return Object.values(value).flatMap(positionApyContractAddresses);
|
|
3369
|
+
}
|
|
2045
3370
|
// Measuring a rate costs indexer boundary queries plus historical quotes against
|
|
2046
3371
|
// an archive node, so an unrequested rate reaches neither.
|
|
2047
3372
|
function resolvePageApy(c, options) {
|
|
@@ -2056,6 +3381,44 @@ function resolvePageApy(c, options) {
|
|
|
2056
3381
|
window: options.window,
|
|
2057
3382
|
}));
|
|
2058
3383
|
}
|
|
3384
|
+
function resolvePageRewards(c, options) {
|
|
3385
|
+
if (!options.include.includes('apy'))
|
|
3386
|
+
return undefined;
|
|
3387
|
+
return Timing.time(c, 'earn_rewards_apy', () => RewardRead.resolveCollection({
|
|
3388
|
+
chainId: options.chainId,
|
|
3389
|
+
db: c.get('dbCached'),
|
|
3390
|
+
vaults: options.vaults,
|
|
3391
|
+
}).catch(() => {
|
|
3392
|
+
Cache.setPolicy(c, Cache.policies.noStore);
|
|
3393
|
+
const failure = {
|
|
3394
|
+
chainId: options.chainId,
|
|
3395
|
+
failure: 'unknown',
|
|
3396
|
+
id: 'earn-rewards',
|
|
3397
|
+
operation: 'listVaultRewards',
|
|
3398
|
+
};
|
|
3399
|
+
c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure]);
|
|
3400
|
+
return new Map();
|
|
3401
|
+
}));
|
|
3402
|
+
}
|
|
3403
|
+
function resolveVaultRewards(c, options) {
|
|
3404
|
+
if (!options.include.includes('apy'))
|
|
3405
|
+
return undefined;
|
|
3406
|
+
return Timing.time(c, 'earn_rewards_apy', () => RewardRead.get({
|
|
3407
|
+
chainId: options.chainId,
|
|
3408
|
+
db: c.get('dbCached'),
|
|
3409
|
+
vaultAddress: options.vault,
|
|
3410
|
+
}).catch(() => {
|
|
3411
|
+
Cache.setPolicy(c, Cache.policies.noStore);
|
|
3412
|
+
const failure = {
|
|
3413
|
+
chainId: options.chainId,
|
|
3414
|
+
failure: 'unknown',
|
|
3415
|
+
id: 'earn-rewards',
|
|
3416
|
+
operation: 'getVaultRewards',
|
|
3417
|
+
};
|
|
3418
|
+
c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure]);
|
|
3419
|
+
return undefined;
|
|
3420
|
+
}));
|
|
3421
|
+
}
|
|
2059
3422
|
// The TVL denomination is a fixed constant, not caller input, so a rate set
|
|
2060
3423
|
// lacking it leaves `tvl` unpriced instead of failing the whole vault read.
|
|
2061
3424
|
function resolvePageRates(c, options) {
|
|
@@ -2104,12 +3467,29 @@ async function resolveVault(c, options) {
|
|
|
2104
3467
|
token: options.snapshot.byAddress.get(discovery.assetToken.address),
|
|
2105
3468
|
})
|
|
2106
3469
|
: undefined;
|
|
3470
|
+
const liquidityValue = options.include.includes('tvl') && discovery.instantLiquidity !== null
|
|
3471
|
+
? Valuation.valuationFor({
|
|
3472
|
+
amount: BigInt(discovery.instantLiquidity),
|
|
3473
|
+
denomination: tvlDenomination,
|
|
3474
|
+
rates: options.rates,
|
|
3475
|
+
token: options.snapshot.byAddress.get(discovery.assetToken.address),
|
|
3476
|
+
})
|
|
3477
|
+
: undefined;
|
|
2107
3478
|
return serializeVault({
|
|
2108
3479
|
apy: options.apy?.get(discovery.vaultAddress) ?? null,
|
|
2109
3480
|
assetToken: getToken(options.tokens, discovery.assetToken.address),
|
|
2110
3481
|
discovery,
|
|
2111
3482
|
include: options.include,
|
|
3483
|
+
instantLiquidityValue: liquidityValue
|
|
3484
|
+
? {
|
|
3485
|
+
amount: core_Value.from(liquidityValue.amount, tvlDecimals).toString(),
|
|
3486
|
+
currency: liquidityValue.currency,
|
|
3487
|
+
decimals: tvlDecimals,
|
|
3488
|
+
formatted: liquidityValue.amount,
|
|
3489
|
+
}
|
|
3490
|
+
: null,
|
|
2112
3491
|
record,
|
|
3492
|
+
rewards: options.rewards,
|
|
2113
3493
|
shareToken: getToken(options.tokens, discovery.shareToken.address),
|
|
2114
3494
|
tvl: valued
|
|
2115
3495
|
? {
|
|
@@ -2131,9 +3511,37 @@ export function serializeVault(options) {
|
|
|
2131
3511
|
if (options.include.includes('capabilities') && !discovery.capabilities)
|
|
2132
3512
|
throw new Error('Earn vault capabilities were not resolved.');
|
|
2133
3513
|
const vaultAddress = Schema.Address.parse(discovery.vaultAddress.toLowerCase());
|
|
3514
|
+
const rewards = options.rewards?.map((reward) => ({
|
|
3515
|
+
apr: reward.currentRewardsAprBps === null ? null : RewardRead.ratio(reward.currentRewardsAprBps),
|
|
3516
|
+
asset: reward.asset,
|
|
3517
|
+
...(reward.calculatedThrough !== undefined
|
|
3518
|
+
? { calculatedThrough: reward.calculatedThrough }
|
|
3519
|
+
: {}),
|
|
3520
|
+
campaignId: reward.campaignId,
|
|
3521
|
+
endsAt: reward.endsAt,
|
|
3522
|
+
startsAt: reward.startsAt,
|
|
3523
|
+
targetTotalApr: RewardRead.ratio(reward.targetTotalAprBps),
|
|
3524
|
+
}));
|
|
3525
|
+
const startedRewards = options.rewards?.filter((reward) => reward.startsAt <= Math.floor(Date.now() / 1_000));
|
|
3526
|
+
const targetTotalAprBps = startedRewards?.reduce((target, reward) => Math.max(target, reward.targetTotalAprBps), 0);
|
|
3527
|
+
const apy = options.apy
|
|
3528
|
+
? {
|
|
3529
|
+
...options.apy,
|
|
3530
|
+
net: (() => {
|
|
3531
|
+
if (!startedRewards || startedRewards.length === 0)
|
|
3532
|
+
return options.apy.net;
|
|
3533
|
+
const target = targetTotalAprBps ?? 0;
|
|
3534
|
+
if (parseUnits(options.apy.net, 6) >= BigInt(target) * 100n)
|
|
3535
|
+
return options.apy.net;
|
|
3536
|
+
return RewardRead.ratio(target);
|
|
3537
|
+
})(),
|
|
3538
|
+
...(rewards ? { rewards } : {}),
|
|
3539
|
+
vault: options.apy.net,
|
|
3540
|
+
}
|
|
3541
|
+
: null;
|
|
2134
3542
|
return Response.validated(schema.Vault, {
|
|
2135
3543
|
...(options.include.includes('access') ? { access: discovery.access } : {}),
|
|
2136
|
-
...(options.include.includes('apy') ? { apy
|
|
3544
|
+
...(options.include.includes('apy') ? { apy } : {}),
|
|
2137
3545
|
assetToken: options.assetToken,
|
|
2138
3546
|
...(options.include.includes('capabilities') ? { capabilities: discovery.capabilities } : {}),
|
|
2139
3547
|
description: record?.description ?? null,
|
|
@@ -2144,6 +3552,9 @@ export function serializeVault(options) {
|
|
|
2144
3552
|
},
|
|
2145
3553
|
id: vaultAddress,
|
|
2146
3554
|
instantLiquidity: discovery.instantLiquidity,
|
|
3555
|
+
...(options.include.includes('tvl')
|
|
3556
|
+
? { instantLiquidityValue: options.instantLiquidityValue }
|
|
3557
|
+
: {}),
|
|
2147
3558
|
label: record?.label ?? options.shareToken.name,
|
|
2148
3559
|
sharePrice: discovery.sharePrice === null
|
|
2149
3560
|
? null
|
|
@@ -2214,6 +3625,9 @@ function getToken(tokens, address) {
|
|
|
2214
3625
|
return Response.validated(Tokens.schema.Token, token);
|
|
2215
3626
|
}
|
|
2216
3627
|
async function queryDeployments(c, options) {
|
|
3628
|
+
const factories = deploymentFactories[options.chainId] ?? [];
|
|
3629
|
+
if (factories.length === 0)
|
|
3630
|
+
return { hasMore: false, items: [] };
|
|
2217
3631
|
const filters = [];
|
|
2218
3632
|
if (options.asset)
|
|
2219
3633
|
filters.push(`lower(asset) = '${options.asset.toLowerCase()}'`);
|
|
@@ -2230,7 +3644,8 @@ async function queryDeployments(c, options) {
|
|
|
2230
3644
|
order: 'desc',
|
|
2231
3645
|
},
|
|
2232
3646
|
]));
|
|
2233
|
-
//
|
|
3647
|
+
// Authenticate emitters before deduplication so a forged newer event cannot
|
|
3648
|
+
// replace a factory deployment or suppress it through outer filters.
|
|
2234
3649
|
const result = await c
|
|
2235
3650
|
.get('getTidx')(options.chainId)
|
|
2236
3651
|
.fetch({
|
|
@@ -2245,6 +3660,7 @@ async function queryDeployments(c, options) {
|
|
|
2245
3660
|
block_num,
|
|
2246
3661
|
log_idx
|
|
2247
3662
|
FROM EarnStackDeployed
|
|
3663
|
+
WHERE address IN (${factories.map((address) => `'${address}'`).join(', ')})
|
|
2248
3664
|
ORDER BY block_num DESC, log_idx DESC
|
|
2249
3665
|
LIMIT 1 BY lower("earnVault")
|
|
2250
3666
|
)
|
|
@@ -2301,4 +3717,29 @@ export function isIncompatible(cause) {
|
|
|
2301
3717
|
export class NotFoundError extends Error {
|
|
2302
3718
|
name = 'Earn.NotFoundError';
|
|
2303
3719
|
}
|
|
3720
|
+
/** Thrown when a historical position boundary is not indexed. */
|
|
3721
|
+
class IndexedBlockNotFoundError extends Error {
|
|
3722
|
+
name = 'Earn.IndexedBlockNotFoundError';
|
|
3723
|
+
constructor(asOf) {
|
|
3724
|
+
super(`No indexed block exists at or before ${asOf}.`);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
class IndexedCoverageError extends Error {
|
|
3728
|
+
name = 'Earn.IndexedCoverageError';
|
|
3729
|
+
constructor(asOf) {
|
|
3730
|
+
super(`Indexed history does not yet cover ${asOf}.`);
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
class ZoneHistoricalAlignmentError extends Error {
|
|
3734
|
+
name = 'Earn.ZoneHistoricalAlignmentError';
|
|
3735
|
+
constructor() {
|
|
3736
|
+
super('This Zone does not expose historical parent-chain synchronization checkpoints.');
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
class ZoneEarningsUnsupportedError extends Error {
|
|
3740
|
+
name = 'Earn.ZoneEarningsUnsupportedError';
|
|
3741
|
+
constructor() {
|
|
3742
|
+
super('Zone positions do not support the earnings include.');
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
2304
3745
|
//# sourceMappingURL=earn.js.map
|