tapimo 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts +11333 -9563
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +39 -3
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +2 -0
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +17 -0
- 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 +1064 -924
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +80 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +54 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +63 -15
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +2 -1
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +92 -3
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +69 -7
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +7 -7
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +151 -151
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/Zones.d.ts +28 -28
- package/dist/apps/Zones.js +7 -7
- package/dist/apps/data/App.d.ts +2909 -2523
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +26 -21
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +8 -8
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
- package/dist/apps/data/ZoneSelection.js +1 -1
- package/dist/apps/data/ZoneSelection.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +588 -584
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +1561 -1239
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts +26 -26
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +43 -16
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +44 -44
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +21 -11
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +3 -3
- package/dist/apps/data/routes/earn.d.ts +201 -25
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +434 -75
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +160 -145
- 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 +2 -2
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +18 -19
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +155 -55
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +28 -10
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +13 -13
- package/dist/apps/data/routes/tokens.d.ts +5 -5
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +51 -20
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +7 -2
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +37 -17
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +13 -13
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +18 -12
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +31 -31
- package/dist/apps/data/routes/valuation.d.ts.map +1 -1
- package/dist/apps/data/routes/valuation.js +12 -7
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +8 -8
- package/dist/apps/data/routes/webhooks.d.ts +816 -113
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +47 -5
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +14 -14
- package/dist/apps/data/routes/zones.js +1 -1
- package/dist/apps/funding/App.d.ts +466 -44
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/App.js +1 -1
- package/dist/apps/funding/App.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +17 -17
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +17 -12
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +650 -57
- package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
- package/dist/apps/funding/routes/transfers.js +238 -24
- package/dist/apps/funding/routes/transfers.js.map +1 -1
- package/dist/apps/management/App.d.ts +5120 -4152
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +17 -1
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +632 -81
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +236 -4
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +76 -76
- package/dist/apps/management/routes/faucet.d.ts +6 -6
- package/dist/apps/management/routes/invitations.d.ts +24 -24
- package/dist/apps/management/routes/invite-links.d.ts +4 -4
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +20 -20
- package/dist/apps/management/routes/projects.d.ts +4 -4
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +17 -17
- package/dist/apps/management/routes/webhooks.d.ts +675 -25
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +21 -21
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +115 -23
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +27 -1
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +34 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +11 -5
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +21 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/fundingCatalog.d.ts +4 -2
- package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
- package/dist/db/tables/fundingCatalog.js +5 -1
- package/dist/db/tables/fundingCatalog.js.map +1 -1
- package/dist/db/tables/fundingTransferTransactions.d.ts +38 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -1
- package/dist/db/tables/fundingTransferTransactions.js +44 -3
- package/dist/db/tables/fundingTransferTransactions.js.map +1 -1
- package/dist/db/tables/fundingTransfers.d.ts +17 -0
- package/dist/db/tables/fundingTransfers.d.ts.map +1 -1
- package/dist/db/tables/fundingTransfers.js +21 -0
- package/dist/db/tables/fundingTransfers.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +24 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +27 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +25 -1
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +26 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +44 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +146 -13
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +10 -6
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +9 -6
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +9 -0
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/internal/Auth.d.ts +3 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +6 -3
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +3 -3
- package/dist/internal/EarnVaults.js +5 -5
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/Fetch.d.ts +23 -0
- package/dist/internal/Fetch.d.ts.map +1 -0
- package/dist/internal/Fetch.js +26 -0
- package/dist/internal/Fetch.js.map +1 -0
- package/dist/internal/Log.d.ts +4 -2
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +16 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +5 -3
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +13 -3
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Schema.d.ts +6 -3
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +8 -2
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +16 -3
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +82 -16
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +7 -2
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Timeout.d.ts +36 -0
- package/dist/internal/Timeout.d.ts.map +1 -0
- package/dist/internal/Timeout.js +37 -0
- package/dist/internal/Timeout.js.map +1 -0
- package/dist/internal/Timing.d.ts +9 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +7 -0
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/Viem.d.ts +16 -1
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +12 -2
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/WebhookDestination.d.ts.map +1 -1
- package/dist/internal/WebhookDestination.js +3 -0
- package/dist/internal/WebhookDestination.js.map +1 -1
- package/dist/internal/funding/Action.d.ts +9 -0
- package/dist/internal/funding/Action.d.ts.map +1 -1
- package/dist/internal/funding/Action.js +16 -8
- package/dist/internal/funding/Action.js.map +1 -1
- package/dist/internal/funding/Catalog.d.ts +9 -2
- package/dist/internal/funding/Catalog.d.ts.map +1 -1
- package/dist/internal/funding/Catalog.js +19 -8
- package/dist/internal/funding/Catalog.js.map +1 -1
- package/dist/internal/funding/DepositWebhook.d.ts.map +1 -1
- package/dist/internal/funding/DepositWebhook.js +2 -1
- package/dist/internal/funding/DepositWebhook.js.map +1 -1
- package/dist/internal/funding/Evidence.d.ts.map +1 -1
- package/dist/internal/funding/Evidence.js +2 -10
- package/dist/internal/funding/Evidence.js.map +1 -1
- package/dist/internal/funding/Provider.d.ts +108 -13
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +34 -8
- package/dist/internal/funding/Provider.js.map +1 -1
- package/dist/internal/funding/SourceObservation.d.ts.map +1 -1
- package/dist/internal/funding/SourceObservation.js +5 -7
- package/dist/internal/funding/SourceObservation.js.map +1 -1
- package/dist/internal/funding/Transfer.d.ts +114 -18
- package/dist/internal/funding/Transfer.d.ts.map +1 -1
- package/dist/internal/funding/Transfer.js +185 -55
- package/dist/internal/funding/Transfer.js.map +1 -1
- package/dist/internal/funding/TransferReconciliation.d.ts +52 -0
- package/dist/internal/funding/TransferReconciliation.d.ts.map +1 -0
- package/dist/internal/funding/TransferReconciliation.js +192 -0
- package/dist/internal/funding/TransferReconciliation.js.map +1 -0
- package/dist/internal/funding/TransferWebhook.d.ts +21 -0
- package/dist/internal/funding/TransferWebhook.d.ts.map +1 -0
- package/dist/internal/funding/TransferWebhook.js +43 -0
- package/dist/internal/funding/TransferWebhook.js.map +1 -0
- package/dist/internal/funding/index.d.ts +1 -0
- package/dist/internal/funding/index.d.ts.map +1 -1
- package/dist/internal/funding/index.js +1 -0
- package/dist/internal/funding/index.js.map +1 -1
- package/dist/internal/funding/providers/relay.d.ts.map +1 -1
- package/dist/internal/funding/providers/relay.js +3 -12
- package/dist/internal/funding/providers/relay.js.map +1 -1
- package/dist/internal/funding/providers/stargate.d.ts +127 -9
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -1
- package/dist/internal/funding/providers/stargate.js +548 -112
- package/dist/internal/funding/providers/stargate.js.map +1 -1
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1 -0
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
- package/dist/internal/webhookDestinations/slack.js +16 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/package.json +2 -2
- package/src/App.test.ts +100 -0
- package/src/App.ts +43 -3
- package/src/Client.test-d.ts +129 -2
- package/src/Scope.test.ts +20 -0
- package/src/Scope.ts +16 -0
- package/src/Webhooks.ts +2 -2
- package/src/admin/apps/api-keys.test.ts +75 -0
- package/src/admin/apps/api-keys.ts +64 -0
- package/src/admin/apps/earn-vaults.test.ts +1 -1
- package/src/admin/apps/earn-vaults.ts +2 -1
- package/src/admin/apps/organizations.test.ts +53 -1
- package/src/admin/apps/organizations.ts +90 -5
- package/src/admin/ui/src/lib/api-keys.ts +19 -0
- package/src/admin/ui/src/lib/organizations.test.ts +112 -1
- package/src/admin/ui/src/lib/organizations.ts +55 -0
- package/src/admin/ui/src/routes/api-keys.tsx +89 -2
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +116 -0
- package/src/admin/ui.generated.ts +189 -151
- package/src/apps/Zones.test.ts +7 -7
- package/src/apps/Zones.ts +7 -7
- package/src/apps/composition.test.ts +2 -1
- package/src/apps/data/App.test.ts +41 -0
- package/src/apps/data/App.ts +30 -21
- package/src/apps/data/ZoneSelection.test.ts +2 -2
- package/src/apps/data/ZoneSelection.ts +8 -8
- package/src/apps/data/routes/activities.test.ts +1526 -12
- package/src/apps/data/routes/activities.ts +1774 -1356
- package/src/apps/data/routes/balances.ts +133 -97
- package/src/apps/data/routes/blocks.test.ts +533 -0
- package/src/apps/data/routes/blocks.ts +35 -16
- package/src/apps/data/routes/earn.test.ts +373 -16
- package/src/apps/data/routes/earn.ts +548 -79
- package/src/apps/data/routes/earn.zone-access.test.ts +6 -6
- package/src/apps/data/routes/exchanges.test.ts +740 -15
- package/src/apps/data/routes/exchanges.ts +954 -753
- package/src/apps/data/routes/fee-amm.ts +17 -18
- package/src/apps/data/routes/receipts.ts +47 -16
- package/src/apps/data/routes/tokens.test.ts +578 -0
- package/src/apps/data/routes/tokens.ts +283 -225
- package/src/apps/data/routes/transactions.ts +68 -29
- package/src/apps/data/routes/transfers.test.ts +421 -0
- package/src/apps/data/routes/transfers.ts +45 -27
- package/src/apps/data/routes/valuation.ts +94 -78
- package/src/apps/data/routes/webhooks.test.ts +21 -5
- package/src/apps/data/routes/webhooks.ts +63 -8
- package/src/apps/data/routes/zones.test.ts +2 -2
- package/src/apps/data/routes/zones.ts +1 -1
- package/src/apps/funding/App.ts +12 -2
- package/src/apps/funding/routes/deposit-addresses.test.ts +29 -7
- package/src/apps/funding/routes/deposit-addresses.ts +19 -14
- package/src/apps/funding/routes/quotes.test.ts +5 -9
- package/src/apps/funding/routes/transfers.test.ts +901 -23
- package/src/apps/funding/routes/transfers.ts +347 -64
- package/src/apps/management/Billing.ts +18 -5
- package/src/apps/management/routes/api-keys.test.ts +220 -0
- package/src/apps/management/routes/api-keys.ts +280 -3
- package/src/apps/management/routes/webhooks.test.ts +3 -3
- package/src/apps/management/routes/webhooks.ts +24 -25
- package/src/apps/relay/App.test.ts +212 -1
- package/src/apps/relay/App.ts +158 -29
- package/src/apps/relay/Sponsorships.ts +24 -1
- package/src/db/Db.ts +48 -1
- package/src/db/Schema.ts +22 -4
- package/src/db/tables/earnVaults.test.ts +9 -9
- package/src/db/tables/fundingCatalog.test.ts +16 -2
- package/src/db/tables/fundingCatalog.ts +9 -3
- package/src/db/tables/fundingTransferTransactions.test.ts +43 -0
- package/src/db/tables/fundingTransferTransactions.ts +79 -3
- package/src/db/tables/fundingTransfers.test.ts +26 -0
- package/src/db/tables/fundingTransfers.ts +36 -0
- package/src/db/tables/organizations.test.ts +41 -0
- package/src/db/tables/organizations.ts +49 -0
- package/src/db/tables/projects.test.ts +55 -0
- package/src/db/tables/projects.ts +46 -1
- package/src/db/tables/sponsoredTransactions.test.ts +338 -0
- package/src/db/tables/sponsoredTransactions.ts +197 -13
- package/src/db/tables/webhookSubscriptions.ts +18 -11
- package/src/handlers/internal/utils.test.ts +53 -0
- package/src/handlers/internal/utils.ts +15 -0
- package/src/internal/Auth.ts +12 -4
- package/src/internal/EarnVaults.capabilities.test.ts +2 -2
- package/src/internal/EarnVaults.test.ts +1 -1
- package/src/internal/EarnVaults.ts +5 -5
- package/src/internal/Fetch.test.ts +46 -0
- package/src/internal/Fetch.ts +56 -0
- package/src/internal/Log.test-d.ts +2 -0
- package/src/internal/Log.test.ts +21 -0
- package/src/internal/Log.ts +22 -5
- package/src/internal/OpenApi.ts +14 -4
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.test.ts +2 -0
- package/src/internal/Schema.ts +12 -2
- package/src/internal/Store.test.ts +178 -0
- package/src/internal/Store.ts +104 -18
- package/src/internal/Tidx.test.ts +2 -1
- package/src/internal/Tidx.ts +7 -2
- package/src/internal/Timeout.test.ts +35 -0
- package/src/internal/Timeout.ts +73 -0
- package/src/internal/Timing.ts +16 -0
- package/src/internal/Viem.ts +39 -3
- package/src/internal/WebhookDestination.ts +3 -0
- package/src/internal/Webhooks.test.ts +45 -0
- package/src/internal/funding/Action.test.ts +41 -1
- package/src/internal/funding/Action.ts +69 -41
- package/src/internal/funding/Catalog.test.ts +34 -0
- package/src/internal/funding/Catalog.ts +28 -11
- package/src/internal/funding/DepositWebhook.ts +2 -1
- package/src/internal/funding/Evidence.ts +2 -13
- package/src/internal/funding/Provider.test.ts +73 -0
- package/src/internal/funding/Provider.ts +125 -28
- package/src/internal/funding/SourceObservation.ts +5 -9
- package/src/internal/funding/Transfer.test.ts +155 -0
- package/src/internal/funding/Transfer.ts +387 -147
- package/src/internal/funding/TransferReconciliation.test.ts +147 -0
- package/src/internal/funding/TransferReconciliation.ts +264 -0
- package/src/internal/funding/TransferWebhook.test.ts +128 -0
- package/src/internal/funding/TransferWebhook.ts +67 -0
- package/src/internal/funding/index.test.ts +1 -0
- package/src/internal/funding/index.ts +1 -0
- package/src/internal/funding/providers/index.test.ts +4 -167
- package/src/internal/funding/providers/relay.test.ts +2 -2
- package/src/internal/funding/providers/relay.ts +3 -15
- package/src/internal/funding/providers/stargate.test.ts +328 -0
- package/src/internal/funding/providers/stargate.ts +807 -135
- package/src/internal/index.test.ts +1 -0
- package/src/internal/index.ts +1 -0
- package/src/internal/webhookDestinations/slack.ts +15 -0
|
@@ -7,6 +7,8 @@ import * as TestEarn from '../../../../test/Earn.js'
|
|
|
7
7
|
import * as Runtime from '../../../../test/runtime.js'
|
|
8
8
|
import * as Cursor from '../../../internal/Cursor.js'
|
|
9
9
|
import * as Store from '../../../internal/Store.js'
|
|
10
|
+
import * as Tidx from '../../../internal/Tidx.js'
|
|
11
|
+
import * as Value from '../../../internal/Value.js'
|
|
10
12
|
import * as Earn from './earn.js'
|
|
11
13
|
|
|
12
14
|
/**
|
|
@@ -32,7 +34,10 @@ type OpenApiOperation = {
|
|
|
32
34
|
name?: string
|
|
33
35
|
schema?: { enum?: readonly unknown[]; examples?: readonly unknown[]; pattern?: string }
|
|
34
36
|
}[]
|
|
35
|
-
responses?: Record<
|
|
37
|
+
responses?: Record<
|
|
38
|
+
string,
|
|
39
|
+
{ content?: { 'application/json'?: { schema?: OpenApiSchema } }; description?: string }
|
|
40
|
+
>
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
type OpenApiDocument = {
|
|
@@ -106,6 +111,40 @@ describe('schema.getEarnVaults.Query', () => {
|
|
|
106
111
|
})
|
|
107
112
|
})
|
|
108
113
|
|
|
114
|
+
describe('parseIndexedBlockAtOrBefore', () => {
|
|
115
|
+
test('rejects an empty upstream result before classifying the boundary', () => {
|
|
116
|
+
expect(() =>
|
|
117
|
+
Earn.parseIndexedBlockAtOrBefore({
|
|
118
|
+
asOf: '2026-07-21T09:00:00.000Z',
|
|
119
|
+
rows: [],
|
|
120
|
+
}),
|
|
121
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
122
|
+
`[Error: TIDX returned no indexed head for a historical Earn position.]`,
|
|
123
|
+
)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('classifies a missing boundary only after validating the indexed head', () => {
|
|
127
|
+
expect(() =>
|
|
128
|
+
Earn.parseIndexedBlockAtOrBefore({
|
|
129
|
+
asOf: '2026-07-21T09:00:00.000Z',
|
|
130
|
+
rows: [{ kind: 'head', num: 10, timestamp: '2026-07-21T10:00:00.000Z' }],
|
|
131
|
+
}),
|
|
132
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
133
|
+
`[Earn.IndexedBlockNotFoundError: No indexed block exists at or before 2026-07-21T09:00:00.000Z.]`,
|
|
134
|
+
)
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('schema.getEarnVaultPosition.Query', () => {
|
|
139
|
+
test('accepts offset-bearing ISO 8601 timestamps', () => {
|
|
140
|
+
expect(
|
|
141
|
+
Earn.schema.getEarnVaultPosition.Query.parse({
|
|
142
|
+
asOf: '2026-07-21T10:00:00+01:00',
|
|
143
|
+
}).asOf,
|
|
144
|
+
).toBe('2026-07-21T10:00:00+01:00')
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
|
|
109
148
|
describe('schema.getEarnAddressPositions.Query', () => {
|
|
110
149
|
test('parses collection filters', () => {
|
|
111
150
|
const query = Earn.schema.getEarnAddressPositions.Query.parse({
|
|
@@ -181,6 +220,8 @@ describe('schema.getEarnVaultEarnings.Response', () => {
|
|
|
181
220
|
lifetimeEarnings: '0',
|
|
182
221
|
period: 'lifetime',
|
|
183
222
|
status: 'complete',
|
|
223
|
+
totalDeposited: '1000000',
|
|
224
|
+
totalWithdrawn: '500000',
|
|
184
225
|
}).success,
|
|
185
226
|
pending: Earn.schema.getEarnVaultEarnings.Response.safeParse({
|
|
186
227
|
...response,
|
|
@@ -199,9 +240,10 @@ describe('schema.getEarnVaultEarnings.Response', () => {
|
|
|
199
240
|
}).success,
|
|
200
241
|
pendingWithEarnings: Earn.schema.getEarnVaultEarnings.Response.safeParse({
|
|
201
242
|
...response,
|
|
202
|
-
lifetimeEarnings: '0',
|
|
203
243
|
period: 'lifetime',
|
|
204
244
|
status: 'pending_redemption',
|
|
245
|
+
totalDeposited: '1000000',
|
|
246
|
+
totalWithdrawn: '500000',
|
|
205
247
|
}).success,
|
|
206
248
|
window: Earn.schema.getEarnVaultEarnings.Response.safeParse({
|
|
207
249
|
...response,
|
|
@@ -229,10 +271,10 @@ describe('schema.getEarnVaultEarnings.Response', () => {
|
|
|
229
271
|
"incompleteWindow": true,
|
|
230
272
|
"incompleteWithEarnings": false,
|
|
231
273
|
"lifetime": true,
|
|
232
|
-
"pending":
|
|
274
|
+
"pending": false,
|
|
233
275
|
"pendingActive": false,
|
|
234
276
|
"pendingWindow": true,
|
|
235
|
-
"pendingWithEarnings":
|
|
277
|
+
"pendingWithEarnings": true,
|
|
236
278
|
"window": true,
|
|
237
279
|
"windowWithActiveEarnings": false,
|
|
238
280
|
"windowWithoutEarnings": false,
|
|
@@ -241,6 +283,75 @@ describe('schema.getEarnVaultEarnings.Response', () => {
|
|
|
241
283
|
})
|
|
242
284
|
})
|
|
243
285
|
|
|
286
|
+
describe('serializeVault', () => {
|
|
287
|
+
test('includes a non-null instant-liquidity valuation with TVL', () => {
|
|
288
|
+
const assetToken = {
|
|
289
|
+
address: TestEarn.assetTokenAddress,
|
|
290
|
+
currency: 'USD',
|
|
291
|
+
decimals: 6,
|
|
292
|
+
id: TestEarn.assetTokenAddress,
|
|
293
|
+
name: 'Bridge Test PATHUSD',
|
|
294
|
+
symbol: 'btPATHUSD',
|
|
295
|
+
verified: true,
|
|
296
|
+
} as const
|
|
297
|
+
const shareTokenAddress = `0x20c0${'11'.repeat(18)}` as const
|
|
298
|
+
const vault = Earn.serializeVault({
|
|
299
|
+
apy: null,
|
|
300
|
+
assetToken,
|
|
301
|
+
discovery: {
|
|
302
|
+
assetToken,
|
|
303
|
+
chainId: TestEarn.chain.id,
|
|
304
|
+
engine: { address: TestEarn.vaultAddress, type: 'erc4626', venue: null },
|
|
305
|
+
instantLiquidity: '500000000',
|
|
306
|
+
sharePrice: '1000000',
|
|
307
|
+
shareToken: {
|
|
308
|
+
address: shareTokenAddress,
|
|
309
|
+
currency: 'USD',
|
|
310
|
+
decimals: 6,
|
|
311
|
+
name: 'Bridge Test PATHUSD Earn',
|
|
312
|
+
symbol: 'btPATHUSDE',
|
|
313
|
+
},
|
|
314
|
+
state: {
|
|
315
|
+
depositsPaused: false,
|
|
316
|
+
engineShares: '1000000000',
|
|
317
|
+
feesActive: true,
|
|
318
|
+
isAccountingAligned: true,
|
|
319
|
+
openRedeemRequestCount: 0,
|
|
320
|
+
totalAssets: '1000000000',
|
|
321
|
+
totalEarnShares: '1000000000',
|
|
322
|
+
},
|
|
323
|
+
vaultAddress: TestEarn.vaultAddress,
|
|
324
|
+
},
|
|
325
|
+
include: ['tvl'],
|
|
326
|
+
instantLiquidityValue: {
|
|
327
|
+
amount: '500000000',
|
|
328
|
+
currency: 'USD',
|
|
329
|
+
decimals: 6,
|
|
330
|
+
formatted: '500',
|
|
331
|
+
},
|
|
332
|
+
shareToken: {
|
|
333
|
+
address: shareTokenAddress,
|
|
334
|
+
currency: 'USD',
|
|
335
|
+
decimals: 6,
|
|
336
|
+
id: shareTokenAddress,
|
|
337
|
+
name: 'Bridge Test PATHUSD Earn',
|
|
338
|
+
symbol: 'btPATHUSDE',
|
|
339
|
+
verified: false,
|
|
340
|
+
},
|
|
341
|
+
tvl: { amount: '1000000000', currency: 'USD', decimals: 6, formatted: '1000' },
|
|
342
|
+
zoneRoutes: [],
|
|
343
|
+
zones: [],
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
expect(vault.instantLiquidityValue).toStrictEqual({
|
|
347
|
+
amount: '500000000',
|
|
348
|
+
currency: 'USD',
|
|
349
|
+
decimals: 6,
|
|
350
|
+
formatted: '500',
|
|
351
|
+
})
|
|
352
|
+
})
|
|
353
|
+
})
|
|
354
|
+
|
|
244
355
|
describe('schema.getEarnVaultEarnings.Query', () => {
|
|
245
356
|
test('defaults to lifetime and accepts active and trailing earnings', () => {
|
|
246
357
|
expect([
|
|
@@ -721,6 +832,45 @@ describe('GET /v1/earn/vaults/verified', () => {
|
|
|
721
832
|
})
|
|
722
833
|
|
|
723
834
|
describe('GET /v1/earn/addresses/:address/positions', () => {
|
|
835
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
836
|
+
'batches lifetime cash flows for multiple positions into one query',
|
|
837
|
+
async () => {
|
|
838
|
+
const tidx = Tidx.getClient({
|
|
839
|
+
chainId: TestEarn.chain.id,
|
|
840
|
+
tidx: { auth: process.env.TIDX_AUTH, baseUrl: Runtime.get().tidxUrl },
|
|
841
|
+
})
|
|
842
|
+
let queryCount = 0
|
|
843
|
+
const client = new Proxy(tidx, {
|
|
844
|
+
get(target, property, receiver) {
|
|
845
|
+
if (property !== 'fetch') return Reflect.get(target, property, receiver)
|
|
846
|
+
return (...options: Parameters<Tidx.Client['fetch']>) => {
|
|
847
|
+
queryCount += 1
|
|
848
|
+
return target.fetch(...options)
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
})
|
|
852
|
+
const emptyVault = Schema.Address.parse(`0x${'11'.repeat(20)}`)
|
|
853
|
+
const cashFlows = await Earn.getVaultLifetimeCashFlows(client, {
|
|
854
|
+
account: TestEarn.earningsAddress,
|
|
855
|
+
blockNumber: 1_000_000_000,
|
|
856
|
+
vaults: [TestEarn.vaultAddress, emptyVault],
|
|
857
|
+
})
|
|
858
|
+
|
|
859
|
+
expect(queryCount).toBe(1)
|
|
860
|
+
expect(cashFlows.get(TestEarn.vaultAddress)).toMatchObject({
|
|
861
|
+
status: 'complete',
|
|
862
|
+
totalDeposited: expect.stringMatching(/^[1-9]\d*$/),
|
|
863
|
+
totalWithdrawn: expect.stringMatching(/^\d+$/),
|
|
864
|
+
})
|
|
865
|
+
expect(cashFlows.get(emptyVault)).toStrictEqual({
|
|
866
|
+
status: 'complete',
|
|
867
|
+
totalDeposited: '0',
|
|
868
|
+
totalWithdrawn: '0',
|
|
869
|
+
})
|
|
870
|
+
},
|
|
871
|
+
60_000,
|
|
872
|
+
)
|
|
873
|
+
|
|
724
874
|
test('returns chain selection errors', async () => {
|
|
725
875
|
const app = TestApp.create({ auth: false, cache })
|
|
726
876
|
const invalid = await app.request(
|
|
@@ -750,7 +900,7 @@ describe('GET /v1/earn/addresses/:address/positions', () => {
|
|
|
750
900
|
test('returns an empty verified page without curated vaults', async () => {
|
|
751
901
|
const app = TestApp.create({ auth: false, cache })
|
|
752
902
|
const response = await app.request(
|
|
753
|
-
`/v1/earn/addresses/${TestEarn.positionAddress}/positions?verified=true`,
|
|
903
|
+
`/v1/earn/addresses/${TestEarn.positionAddress}/positions?include=earnings&verified=true`,
|
|
754
904
|
)
|
|
755
905
|
|
|
756
906
|
expect(response.status).toBe(200)
|
|
@@ -774,7 +924,7 @@ describe('GET /v1/earn/addresses/:address/positions', () => {
|
|
|
774
924
|
})
|
|
775
925
|
const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
|
|
776
926
|
const response = await app.request(
|
|
777
|
-
`/v1/earn/addresses/${TestEarn.activeEarningsAddress}/positions?chainId=${TestEarn.chain.id}&verified=true&valuation.currency=USD`,
|
|
927
|
+
`/v1/earn/addresses/${TestEarn.activeEarningsAddress}/positions?chainId=${TestEarn.chain.id}&include=earnings&verified=true&valuation.currency=USD`,
|
|
778
928
|
)
|
|
779
929
|
|
|
780
930
|
expect(response.status).toBe(200)
|
|
@@ -790,6 +940,7 @@ describe('GET /v1/earn/addresses/:address/positions', () => {
|
|
|
790
940
|
expect(row.shareAmount.decimals).toBe(row.shareToken.decimals)
|
|
791
941
|
expect(row.assetAmount.currency).toBe(row.assetToken.currency)
|
|
792
942
|
expect(row.assetAmount.decimals).toBe(row.assetToken.decimals)
|
|
943
|
+
expect(row.lifetimeCashFlows?.status).toMatch(/^(complete|incomplete_history)$/)
|
|
793
944
|
// A USD-denominated asset values identically without consulting rates.
|
|
794
945
|
expect(row.valuation).toStrictEqual({ amount: row.assetAmount.formatted, currency: 'USD' })
|
|
795
946
|
expect(body.meta).toBeUndefined()
|
|
@@ -1008,6 +1159,7 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
|
|
|
1008
1159
|
// The pinned venue exposes no withdrawal-limit view, so liquidity is
|
|
1009
1160
|
// absent rather than a restatement of the backing.
|
|
1010
1161
|
instantLiquidity: vault.instantLiquidity,
|
|
1162
|
+
instantLiquidityValue: vault.instantLiquidityValue,
|
|
1011
1163
|
isAccountingAligned: vault.state.isAccountingAligned,
|
|
1012
1164
|
openRedeemRequestCount: vault.state.openRedeemRequestCount,
|
|
1013
1165
|
pricedPerShare: vault.sharePrice !== null && BigInt(vault.sharePrice.amount) > 0n,
|
|
@@ -1019,6 +1171,7 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
|
|
|
1019
1171
|
"engineType": "erc4626",
|
|
1020
1172
|
"feesActive": true,
|
|
1021
1173
|
"instantLiquidity": null,
|
|
1174
|
+
"instantLiquidityValue": null,
|
|
1022
1175
|
"isAccountingAligned": true,
|
|
1023
1176
|
"openRedeemRequestCount": 0,
|
|
1024
1177
|
"pricedPerShare": true,
|
|
@@ -1089,16 +1242,22 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
|
|
|
1089
1242
|
)
|
|
1090
1243
|
|
|
1091
1244
|
test.runIf(Runtime.get().mode === 'testnet')(
|
|
1092
|
-
'leaves the rate unmeasured
|
|
1245
|
+
'leaves the rate unmeasured when the window starts before deployment',
|
|
1093
1246
|
async () => {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1247
|
+
// This vault was deployed on 2026-07-23, so the pinned window begins before deployment.
|
|
1248
|
+
vi.useFakeTimers({ now: new Date('2026-07-24T10:00:00Z'), toFake: ['Date'] })
|
|
1249
|
+
try {
|
|
1250
|
+
const app = TestApp.create({ auth: false, cache, zones: [TestEarn.zone] })
|
|
1251
|
+
const response = await app.request(
|
|
1252
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}?chainId=${TestEarn.chain.id}&apy.window=30d`,
|
|
1253
|
+
)
|
|
1098
1254
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1255
|
+
expect(response.status).toBe(200)
|
|
1256
|
+
const vault = await TestApp.json(response, Earn.schema.getEarnVault.Response)
|
|
1257
|
+
expect(vault.apy).toBeNull()
|
|
1258
|
+
} finally {
|
|
1259
|
+
vi.useRealTimers()
|
|
1260
|
+
}
|
|
1102
1261
|
},
|
|
1103
1262
|
60_000,
|
|
1104
1263
|
)
|
|
@@ -1300,6 +1459,25 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
|
|
|
1300
1459
|
})
|
|
1301
1460
|
|
|
1302
1461
|
describe('GET /v1/earn/vaults/:vaultId/positions/:address', () => {
|
|
1462
|
+
test('rejects invalid as-of timestamps', async () => {
|
|
1463
|
+
const app = TestApp.create({ auth: false, cache })
|
|
1464
|
+
const [malformed, unix] = await Promise.all([
|
|
1465
|
+
app.request(
|
|
1466
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?asOf=not-a-time`,
|
|
1467
|
+
),
|
|
1468
|
+
app.request(
|
|
1469
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?asOf=1787312400`,
|
|
1470
|
+
),
|
|
1471
|
+
])
|
|
1472
|
+
|
|
1473
|
+
for (const response of [malformed, unix]) {
|
|
1474
|
+
expect(response.status).toBe(400)
|
|
1475
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1476
|
+
error: { code: 'query_invalid' },
|
|
1477
|
+
})
|
|
1478
|
+
}
|
|
1479
|
+
})
|
|
1480
|
+
|
|
1303
1481
|
test('returns chain selection errors', async () => {
|
|
1304
1482
|
const app = TestApp.create({ auth: false, cache })
|
|
1305
1483
|
const invalid = await app.request(
|
|
@@ -1329,6 +1507,59 @@ describe('GET /v1/earn/vaults/:vaultId/positions/:address', () => {
|
|
|
1329
1507
|
})
|
|
1330
1508
|
})
|
|
1331
1509
|
|
|
1510
|
+
test('requires TIDX for historical reads on an RPC-only chain', async () => {
|
|
1511
|
+
const response = await TestApp.create({
|
|
1512
|
+
auth: false,
|
|
1513
|
+
cache,
|
|
1514
|
+
rpc: { url: { 31_337: 'http://127.0.0.1:1' } },
|
|
1515
|
+
tidx: {},
|
|
1516
|
+
}).request(
|
|
1517
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?chainId=31337&asOf=2026-07-21T09%3A00Z`,
|
|
1518
|
+
)
|
|
1519
|
+
|
|
1520
|
+
expect(response.status).toBe(400)
|
|
1521
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1522
|
+
error: { code: 'chain_id_unsupported' },
|
|
1523
|
+
})
|
|
1524
|
+
})
|
|
1525
|
+
|
|
1526
|
+
test('validates malformed historical timestamps on an RPC-only chain', async () => {
|
|
1527
|
+
const response = await TestApp.create({
|
|
1528
|
+
auth: false,
|
|
1529
|
+
cache,
|
|
1530
|
+
rpc: { url: { 31_337: 'http://127.0.0.1:1' } },
|
|
1531
|
+
tidx: {},
|
|
1532
|
+
}).request(
|
|
1533
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?chainId=31337&asOf=not-a-time`,
|
|
1534
|
+
)
|
|
1535
|
+
|
|
1536
|
+
expect(response.status).toBe(400)
|
|
1537
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1538
|
+
error: { code: 'query_invalid' },
|
|
1539
|
+
})
|
|
1540
|
+
})
|
|
1541
|
+
|
|
1542
|
+
test('validates the complete historical query on an RPC-only chain', async () => {
|
|
1543
|
+
const app = TestApp.create({
|
|
1544
|
+
auth: false,
|
|
1545
|
+
cache,
|
|
1546
|
+
rpc: { url: { 31_337: 'http://127.0.0.1:1' } },
|
|
1547
|
+
tidx: {},
|
|
1548
|
+
})
|
|
1549
|
+
const path = `/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?chainId=31337&asOf=2026-07-21T09%3A00Z`
|
|
1550
|
+
const [duplicate, unknown] = await Promise.all([
|
|
1551
|
+
app.request(`${path}&asOf=2026-07-21T10%3A00Z`),
|
|
1552
|
+
app.request(`${path}&unknown=1`),
|
|
1553
|
+
])
|
|
1554
|
+
|
|
1555
|
+
for (const response of [duplicate, unknown]) {
|
|
1556
|
+
expect(response.status).toBe(400)
|
|
1557
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1558
|
+
error: { code: 'query_invalid' },
|
|
1559
|
+
})
|
|
1560
|
+
}
|
|
1561
|
+
})
|
|
1562
|
+
|
|
1332
1563
|
test('rejects malformed vault position parameters', async () => {
|
|
1333
1564
|
const response = await TestApp.create({ auth: false, cache }).request(
|
|
1334
1565
|
'/v1/earn/vaults/not-an-address/positions/not-an-address',
|
|
@@ -1349,6 +1580,7 @@ describe('GET /v1/earn/vaults/:vaultId/positions/:address', () => {
|
|
|
1349
1580
|
)
|
|
1350
1581
|
|
|
1351
1582
|
expect(response.status).toBe(200)
|
|
1583
|
+
expect(response.headers.get('cache-control')).toBe('no-store')
|
|
1352
1584
|
const position = await TestApp.json(response, Earn.schema.getEarnVaultPosition.Response)
|
|
1353
1585
|
expect({
|
|
1354
1586
|
account: position.account,
|
|
@@ -1389,6 +1621,107 @@ describe('GET /v1/earn/vaults/:vaultId/positions/:address', () => {
|
|
|
1389
1621
|
},
|
|
1390
1622
|
60_000,
|
|
1391
1623
|
)
|
|
1624
|
+
|
|
1625
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
1626
|
+
'returns a position as of an indexed ISO 8601 timestamp',
|
|
1627
|
+
async () => {
|
|
1628
|
+
const runtime = Runtime.get()
|
|
1629
|
+
const tidx = Tidx.getClient({
|
|
1630
|
+
chainId: runtime.chainId,
|
|
1631
|
+
tidx: { auth: process.env.TIDX_AUTH, baseUrl: runtime.tidxUrl },
|
|
1632
|
+
})
|
|
1633
|
+
const indexed = await tidx.fetch({
|
|
1634
|
+
engine: 'clickhouse',
|
|
1635
|
+
query: 'SELECT num, timestamp FROM blocks ORDER BY num DESC LIMIT 1 OFFSET 100',
|
|
1636
|
+
})
|
|
1637
|
+
const blockNumber = Value.toNumber(indexed.rows[0]?.['num'])
|
|
1638
|
+
const asOf = Value.toIsoDateTime(indexed.rows[0]?.['timestamp'])
|
|
1639
|
+
if (blockNumber === undefined || asOf === undefined)
|
|
1640
|
+
throw new Error('expected an indexed block')
|
|
1641
|
+
const response = await TestApp.create({ auth: false, cache }).request(
|
|
1642
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?chainId=${TestEarn.chain.id}&asOf=${encodeURIComponent(asOf)}`,
|
|
1643
|
+
)
|
|
1644
|
+
|
|
1645
|
+
expect(response.status).toBe(200)
|
|
1646
|
+
const position = await TestApp.json(response, Earn.schema.getEarnVaultPosition.Response)
|
|
1647
|
+
expect(position.asOf).toBe(asOf)
|
|
1648
|
+
expect(position.block?.number).toBeGreaterThanOrEqual(blockNumber)
|
|
1649
|
+
expect(position.block?.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/)
|
|
1650
|
+
expect(Date.parse(position.block?.timestamp ?? '')).toBeLessThanOrEqual(Date.parse(asOf))
|
|
1651
|
+
},
|
|
1652
|
+
60_000,
|
|
1653
|
+
)
|
|
1654
|
+
|
|
1655
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
1656
|
+
'returns not found before the vault was deployed',
|
|
1657
|
+
async () => {
|
|
1658
|
+
const runtime = Runtime.get()
|
|
1659
|
+
const tidx = Tidx.getClient({
|
|
1660
|
+
chainId: runtime.chainId,
|
|
1661
|
+
tidx: { auth: process.env.TIDX_AUTH, baseUrl: runtime.tidxUrl },
|
|
1662
|
+
})
|
|
1663
|
+
const indexed = await tidx.fetch({
|
|
1664
|
+
engine: 'clickhouse',
|
|
1665
|
+
query: 'SELECT timestamp FROM blocks ORDER BY num ASC LIMIT 1',
|
|
1666
|
+
})
|
|
1667
|
+
const asOf = Value.toIsoDateTime(indexed.rows[0]?.['timestamp'])
|
|
1668
|
+
if (asOf === undefined) throw new Error('expected the pre-deployment block to be indexed')
|
|
1669
|
+
const response = await TestApp.create({ auth: false, cache }).request(
|
|
1670
|
+
`/v1/earn/vaults/${TestEarn.indexedDeployment.vaultAddress}/positions/${TestEarn.positionAddress}?chainId=${TestEarn.chain.id}&asOf=${encodeURIComponent(asOf)}`,
|
|
1671
|
+
)
|
|
1672
|
+
|
|
1673
|
+
expect(response.status).toBe(404)
|
|
1674
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1675
|
+
error: { code: 'earn_vault_not_found' },
|
|
1676
|
+
})
|
|
1677
|
+
},
|
|
1678
|
+
60_000,
|
|
1679
|
+
)
|
|
1680
|
+
|
|
1681
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
1682
|
+
'returns not found for a deployed incompatible contract at a historical block',
|
|
1683
|
+
async () => {
|
|
1684
|
+
const runtime = Runtime.get()
|
|
1685
|
+
const tidx = Tidx.getClient({
|
|
1686
|
+
chainId: runtime.chainId,
|
|
1687
|
+
tidx: { auth: process.env.TIDX_AUTH, baseUrl: runtime.tidxUrl },
|
|
1688
|
+
})
|
|
1689
|
+
const indexed = await tidx.fetch({
|
|
1690
|
+
engine: 'clickhouse',
|
|
1691
|
+
query: 'SELECT timestamp FROM blocks ORDER BY num DESC LIMIT 1',
|
|
1692
|
+
})
|
|
1693
|
+
const asOf = Value.toIsoDateTime(indexed.rows[0]?.['timestamp'])
|
|
1694
|
+
if (asOf === undefined) throw new Error('expected an indexed block')
|
|
1695
|
+
const response = await TestApp.create({ auth: false, cache }).request(
|
|
1696
|
+
`/v1/earn/vaults/${TestEarn.assetTokenAddress}/positions/${TestEarn.positionAddress}?chainId=${TestEarn.chain.id}&asOf=${encodeURIComponent(asOf)}`,
|
|
1697
|
+
)
|
|
1698
|
+
|
|
1699
|
+
expect(response.status).toBe(404)
|
|
1700
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1701
|
+
error: { code: 'earn_vault_not_found' },
|
|
1702
|
+
})
|
|
1703
|
+
},
|
|
1704
|
+
60_000,
|
|
1705
|
+
)
|
|
1706
|
+
|
|
1707
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
1708
|
+
'rejects timestamps beyond indexed coverage',
|
|
1709
|
+
async () => {
|
|
1710
|
+
const asOf = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString()
|
|
1711
|
+
const response = await TestApp.create({ auth: false, cache }).request(
|
|
1712
|
+
`/v1/earn/vaults/${TestEarn.vaultAddress}/positions/${TestEarn.positionAddress}?chainId=${TestEarn.chain.id}&asOf=${encodeURIComponent(asOf)}`,
|
|
1713
|
+
)
|
|
1714
|
+
|
|
1715
|
+
expect(response.status).toBe(400)
|
|
1716
|
+
expect(await TestApp.json(response, Schema.ErrorResponse)).toMatchObject({
|
|
1717
|
+
error: {
|
|
1718
|
+
code: 'query_invalid',
|
|
1719
|
+
message: `Indexed history does not yet cover ${asOf}.`,
|
|
1720
|
+
},
|
|
1721
|
+
})
|
|
1722
|
+
},
|
|
1723
|
+
60_000,
|
|
1724
|
+
)
|
|
1392
1725
|
})
|
|
1393
1726
|
|
|
1394
1727
|
describe('GET /v1/earn/vaults/:vaultId/earnings/:address', () => {
|
|
@@ -1437,6 +1770,8 @@ describe('GET /v1/earn/vaults/:vaultId/earnings/:address', () => {
|
|
|
1437
1770
|
lifetimeEarnings: expect.stringMatching(/^-?\d+$/),
|
|
1438
1771
|
period: 'lifetime',
|
|
1439
1772
|
status: 'complete',
|
|
1773
|
+
totalDeposited: expect.stringMatching(/^\d+$/),
|
|
1774
|
+
totalWithdrawn: expect.stringMatching(/^\d+$/),
|
|
1440
1775
|
})
|
|
1441
1776
|
},
|
|
1442
1777
|
60_000,
|
|
@@ -1747,6 +2082,9 @@ describe('OpenAPI', () => {
|
|
|
1747
2082
|
expect(JSON.stringify(include?.schema)).toContain('"apy"')
|
|
1748
2083
|
expect(JSON.stringify(include?.schema)).toContain('"tvl"')
|
|
1749
2084
|
expect(JSON.stringify(include?.schema)).toContain('"zones"')
|
|
2085
|
+
expect(JSON.stringify(spec.paths['/v1/earn/vaults/{vaultId}']?.get?.responses)).toContain(
|
|
2086
|
+
'Instant liquidity valued in USD',
|
|
2087
|
+
)
|
|
1750
2088
|
})
|
|
1751
2089
|
|
|
1752
2090
|
test('documents vault-position inputs and responses', async () => {
|
|
@@ -1754,6 +2092,7 @@ describe('OpenAPI', () => {
|
|
|
1754
2092
|
const spec = (await (await app.request('/openapi.json')).json()) as OpenApiDocument
|
|
1755
2093
|
const operation = spec.paths['/v1/earn/vaults/{vaultId}/positions/{address}']?.get
|
|
1756
2094
|
const address = operation?.parameters?.find((parameter) => parameter.name === 'address')
|
|
2095
|
+
const asOf = operation?.parameters?.find((parameter) => parameter.name === 'asOf')
|
|
1757
2096
|
const errors = errorSchemas(spec, operation)
|
|
1758
2097
|
const response = JSON.stringify(operation?.responses)
|
|
1759
2098
|
const vaultId = operation?.parameters?.find((parameter) => parameter.name === 'vaultId')
|
|
@@ -1767,6 +2106,17 @@ describe('OpenAPI', () => {
|
|
|
1767
2106
|
expect(response).toContain('0x20c000000000000000000000b9537d11c60e8b50')
|
|
1768
2107
|
expect(response).toContain('0x20c000000000000000000000300e14ab91a10769')
|
|
1769
2108
|
expect(address?.schema?.examples).toStrictEqual([TestEarn.positionAddress])
|
|
2109
|
+
expect(asOf?.description).toContain('latest indexed block at or before')
|
|
2110
|
+
expect(asOf?.schema?.examples).toStrictEqual(['2026-07-21T09:00:00.000Z'])
|
|
2111
|
+
expect(response).toContain('Indexed block used for a historical Earn position observation')
|
|
2112
|
+
expect(response).toContain('Assets held by this account at the observation block')
|
|
2113
|
+
expect(response).toContain('Earn shares held by this account at the observation block')
|
|
2114
|
+
expect(response).toContain('Asset value of this account’s earn shares at the observation block')
|
|
2115
|
+
expect(response).not.toContain('Assets this account currently holds')
|
|
2116
|
+
expect(response).not.toContain('Earn shares this account currently holds')
|
|
2117
|
+
expect(operation?.responses?.['200']?.description).toBe(
|
|
2118
|
+
'Current or historical earn position for one account in one vault.',
|
|
2119
|
+
)
|
|
1770
2120
|
expect(vaultId?.schema?.examples).toStrictEqual([TestEarn.mainnetVaultAddress])
|
|
1771
2121
|
})
|
|
1772
2122
|
|
|
@@ -1778,13 +2128,16 @@ describe('OpenAPI', () => {
|
|
|
1778
2128
|
const denomination = operation?.parameters?.find(
|
|
1779
2129
|
(parameter) => parameter.name === 'valuation.currency',
|
|
1780
2130
|
)
|
|
2131
|
+
const include = operation?.parameters?.find((parameter) => parameter.name === 'include')
|
|
1781
2132
|
const verified = operation?.parameters?.find((parameter) => parameter.name === 'verified')
|
|
1782
2133
|
const errors = errorSchemas(spec, operation)
|
|
1783
2134
|
const response = JSON.stringify(operation?.responses)
|
|
2135
|
+
const tokenReference = JSON.stringify(spec.components?.schemas?.['TokenReference'])
|
|
1784
2136
|
|
|
1785
2137
|
expect(operation?.description).toContain('currently holds shares')
|
|
1786
2138
|
expect(address?.schema?.examples).toStrictEqual([TestEarn.positionAddress])
|
|
1787
2139
|
expect(denomination?.description).toContain('nominal value')
|
|
2140
|
+
expect(include?.description).toContain('`earnings`')
|
|
1788
2141
|
expect(verified?.description).toContain('registry-curated')
|
|
1789
2142
|
expect(verified?.schema?.examples).toStrictEqual([true])
|
|
1790
2143
|
expect(errors).toContain('"chain_id_invalid"')
|
|
@@ -1795,11 +2148,13 @@ describe('OpenAPI', () => {
|
|
|
1795
2148
|
expect(response).toContain('Current asset value of the held shares')
|
|
1796
2149
|
expect(response).toContain('"assetAmount"')
|
|
1797
2150
|
expect(response).toContain('"shareAmount"')
|
|
2151
|
+
expect(response).toContain('"lifetimeCashFlows"')
|
|
1798
2152
|
expect(response).toContain('"valuation"')
|
|
1799
2153
|
expect(response).toContain('"vaultAddress"')
|
|
1800
2154
|
expect(response).toContain('"nextCursor"')
|
|
1801
|
-
|
|
1802
|
-
|
|
2155
|
+
expect(response).toContain('#/components/schemas/TokenReference')
|
|
2156
|
+
// Token references retain display metadata through the shared component.
|
|
2157
|
+
expect(tokenReference).toContain('"symbol"')
|
|
1803
2158
|
})
|
|
1804
2159
|
|
|
1805
2160
|
test('documents vault-earnings variants', async () => {
|
|
@@ -1817,6 +2172,8 @@ describe('OpenAPI', () => {
|
|
|
1817
2172
|
expect(errors).toContain('"earn_vault_not_found"')
|
|
1818
2173
|
expect(response).toContain('Stable resource ID for these vault earnings')
|
|
1819
2174
|
expect(response).toContain('Current share value plus completed redemptions')
|
|
2175
|
+
expect(response).toContain('Assets deposited with this account as receiver')
|
|
2176
|
+
expect(response).toContain('Assets returned by completed redemptions')
|
|
1820
2177
|
expect(response).toContain('weighted-average asset cost basis')
|
|
1821
2178
|
expect(response).toContain('Ending share value plus realized assets')
|
|
1822
2179
|
expect(response).toContain('cannot reconstruct the asset cost basis for the requested period')
|