tapimo 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApiKeys.d.ts +24 -7
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +17 -5
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +12104 -7861
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +191 -128
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +10 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +17 -4
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts +19 -8
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +25 -9
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -1
- package/dist/admin/App.d.ts +601 -20
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +12 -2
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +94 -11
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +141 -32
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +1069 -0
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -0
- package/dist/admin/apps/earn-vaults.js +409 -0
- package/dist/admin/apps/earn-vaults.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +166 -166
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +99 -43
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +2 -0
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +18 -2
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +22 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +59 -39
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/Zones.d.ts +8335 -0
- package/dist/apps/Zones.d.ts.map +1 -0
- package/dist/apps/Zones.js +38 -0
- package/dist/apps/Zones.js.map +1 -0
- package/dist/apps/data/App.d.ts +12125 -7913
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +91 -19
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +1 -1
- package/dist/apps/data/FxOracle.d.ts.map +1 -1
- package/dist/apps/data/index.d.ts +0 -1
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +0 -1
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +32 -32
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +130 -65
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +312 -312
- package/dist/apps/data/routes/balances.d.ts +18 -18
- package/dist/apps/data/routes/balances.js +5 -5
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
- package/dist/apps/data/routes/coingecko.js +62 -35
- package/dist/apps/data/routes/coingecko.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +2144 -0
- package/dist/apps/data/routes/earn.d.ts.map +1 -0
- package/dist/apps/data/routes/earn.js +947 -0
- package/dist/apps/data/routes/earn.js.map +1 -0
- package/dist/apps/data/routes/exchanges.d.ts +1625 -718
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +656 -193
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +108 -108
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +59 -8
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/funding.d.ts +4092 -387
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +1403 -256
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +30 -30
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +19 -2
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +263 -263
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +11 -11
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +5 -5
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +211 -22
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +39 -8
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +114 -86
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +194 -91
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +53 -53
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +78 -39
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +76 -27
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +165 -67
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +42 -42
- package/dist/apps/data/routes/valuation.js +2 -2
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +369 -367
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +161 -59
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +281 -0
- package/dist/apps/data/routes/zones.d.ts.map +1 -0
- package/dist/apps/data/routes/zones.js +252 -0
- package/dist/apps/data/routes/zones.js.map +1 -0
- package/dist/apps/docs/reference.js +6 -5
- package/dist/apps/docs/reference.js.map +1 -1
- package/dist/apps/index.d.ts +2 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +2 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +670 -670
- package/dist/apps/management/Billing.d.ts +8 -0
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +12 -0
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/Error.d.ts +12 -0
- package/dist/apps/management/Error.d.ts.map +1 -0
- package/dist/apps/management/Error.js +10 -0
- package/dist/apps/management/Error.js.map +1 -0
- package/dist/apps/management/routes/api-keys.d.ts +5 -5
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +2 -8
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +119 -119
- package/dist/apps/management/routes/faucet.d.ts +2 -2
- package/dist/apps/management/routes/invitations.d.ts +62 -62
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +4 -10
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +30 -30
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +2 -2
- package/dist/apps/management/routes/orgs.d.ts +48 -48
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +2 -8
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +9 -9
- package/dist/apps/management/routes/scopes.js +2 -2
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +36 -36
- package/dist/apps/management/routes/webhooks.d.ts +50 -50
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +15 -3
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/App.d.ts +55 -56
- package/dist/apps/mpp/App.d.ts.map +1 -1
- package/dist/apps/mpp/App.js +192 -27
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/Mpp.d.ts +0 -20
- package/dist/apps/mpp/Mpp.d.ts.map +1 -1
- package/dist/apps/mpp/Mpp.js +0 -24
- package/dist/apps/mpp/Mpp.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +40 -0
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Adapter.js +66 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -0
- package/dist/apps/mpp/internal/Error.d.ts +4 -0
- package/dist/apps/mpp/internal/Error.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Error.js +41 -0
- package/dist/apps/mpp/internal/Error.js.map +1 -0
- package/dist/apps/mpp/internal/Idempotency.d.ts +33 -0
- package/dist/apps/mpp/internal/Idempotency.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Idempotency.js +28 -0
- package/dist/apps/mpp/internal/Idempotency.js.map +1 -0
- package/dist/apps/mpp/internal/Policy.d.ts +46 -0
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Policy.js +57 -0
- package/dist/apps/mpp/internal/Policy.js.map +1 -0
- package/dist/apps/mpp/internal/ScreenManager.d.ts +27 -0
- package/dist/apps/mpp/internal/ScreenManager.d.ts.map +1 -0
- package/dist/apps/mpp/internal/ScreenManager.js +18 -0
- package/dist/apps/mpp/internal/ScreenManager.js.map +1 -0
- package/dist/apps/mpp/internal/Screening.d.ts +35 -0
- package/dist/apps/mpp/internal/Screening.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Screening.js +20 -0
- package/dist/apps/mpp/internal/Screening.js.map +1 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts +36 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Sponsorship.js +103 -0
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -0
- package/dist/apps/mpp/internal/Utils.d.ts +7 -0
- package/dist/apps/mpp/internal/Utils.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Utils.js +24 -0
- package/dist/apps/mpp/internal/Utils.js.map +1 -0
- package/dist/apps/relay/App.js +183 -23
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +15 -6
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/db/Db.d.ts +20 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +342 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +921 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +269 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +68 -0
- package/dist/db/tables/earnVaults.d.ts.map +1 -0
- package/dist/db/tables/earnVaults.js +72 -0
- package/dist/db/tables/earnVaults.js.map +1 -0
- package/dist/db/tables/fundingCatalog.d.ts +56 -0
- package/dist/db/tables/fundingCatalog.d.ts.map +1 -0
- package/dist/db/tables/fundingCatalog.js +85 -0
- package/dist/db/tables/fundingCatalog.js.map +1 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts +159 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -0
- package/dist/db/tables/fundingDepositAddresses.js +206 -0
- package/dist/db/tables/fundingDepositAddresses.js.map +1 -0
- package/dist/db/tables/fundingDeposits.d.ts +115 -0
- package/dist/db/tables/fundingDeposits.d.ts.map +1 -0
- package/dist/db/tables/fundingDeposits.js +100 -0
- package/dist/db/tables/fundingDeposits.js.map +1 -0
- package/dist/db/tables/fundingIdempotency.d.ts +91 -0
- package/dist/db/tables/fundingIdempotency.d.ts.map +1 -0
- package/dist/db/tables/fundingIdempotency.js +103 -0
- package/dist/db/tables/fundingIdempotency.js.map +1 -0
- package/dist/db/tables/fundingTransferEvents.d.ts +12 -0
- package/dist/db/tables/fundingTransferEvents.d.ts.map +1 -0
- package/dist/db/tables/fundingTransferEvents.js +18 -0
- package/dist/db/tables/fundingTransferEvents.js.map +1 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts +15 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -0
- package/dist/db/tables/fundingTransferTransactions.js +27 -0
- package/dist/db/tables/fundingTransferTransactions.js.map +1 -0
- package/dist/db/tables/fundingTransfers.d.ts +82 -0
- package/dist/db/tables/fundingTransfers.d.ts.map +1 -0
- package/dist/db/tables/fundingTransfers.js +89 -0
- package/dist/db/tables/fundingTransfers.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +8 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +16 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +8 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +16 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +13 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +16 -0
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +2 -2
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +1 -1
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +8 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +16 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokens.d.ts +14 -7
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokens.js +9 -7
- package/dist/db/tables/verifiedTokens.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +31 -1
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +24 -3
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/relay.js +108 -108
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +26 -0
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +35 -2
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +16 -10
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/Cursor.js +1 -1
- package/dist/internal/Cursor.js.map +1 -1
- package/dist/internal/EarnRates.d.ts +89 -0
- package/dist/internal/EarnRates.d.ts.map +1 -0
- package/dist/internal/EarnRates.js +266 -0
- package/dist/internal/EarnRates.js.map +1 -0
- package/dist/internal/EarnVaults.d.ts +171 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -0
- package/dist/internal/EarnVaults.js +547 -0
- package/dist/internal/EarnVaults.js.map +1 -0
- package/dist/internal/EdgeCache.d.ts +8 -1
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +33 -7
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Id.d.ts +11 -0
- package/dist/internal/Id.d.ts.map +1 -1
- package/dist/internal/Id.js +13 -0
- package/dist/internal/Id.js.map +1 -1
- package/dist/internal/Idempotency.d.ts +83 -0
- package/dist/internal/Idempotency.d.ts.map +1 -0
- package/dist/internal/Idempotency.js +113 -0
- package/dist/internal/Idempotency.js.map +1 -0
- package/dist/internal/Log.d.ts +64 -9
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +29 -7
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +47 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +1 -1
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +3 -0
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Provider.d.ts +14 -0
- package/dist/internal/Provider.d.ts.map +1 -0
- package/dist/internal/Provider.js +5 -0
- package/dist/internal/Provider.js.map +1 -0
- package/dist/internal/Schema.d.ts +6 -1
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +20 -11
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +35 -0
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +43 -24
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +79 -11
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Viem.d.ts +82 -65
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +83 -12
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/WebhookDestination.d.ts.map +1 -1
- package/dist/internal/WebhookDestination.js +34 -28
- package/dist/internal/WebhookDestination.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +9 -0
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +15 -10
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/exchange/Provider.d.ts +219 -0
- package/dist/internal/exchange/Provider.d.ts.map +1 -0
- package/dist/internal/exchange/Provider.js +117 -0
- package/dist/internal/exchange/Provider.js.map +1 -0
- package/dist/internal/exchange/index.d.ts +2 -0
- package/dist/internal/exchange/index.d.ts.map +1 -0
- package/dist/internal/exchange/index.js +2 -0
- package/dist/internal/exchange/index.js.map +1 -0
- package/dist/internal/exchange/providers/uniswap.d.ts +57 -0
- package/dist/internal/exchange/providers/uniswap.d.ts.map +1 -0
- package/dist/internal/exchange/providers/uniswap.js +553 -0
- package/dist/internal/exchange/providers/uniswap.js.map +1 -0
- package/dist/internal/funding/Action.d.ts +55 -0
- package/dist/internal/funding/Action.d.ts.map +1 -0
- package/dist/internal/funding/Action.js +74 -0
- package/dist/internal/funding/Action.js.map +1 -0
- package/dist/internal/funding/Catalog.d.ts +107 -0
- package/dist/internal/funding/Catalog.d.ts.map +1 -0
- package/dist/internal/funding/Catalog.js +270 -0
- package/dist/internal/funding/Catalog.js.map +1 -0
- package/dist/internal/funding/Chain.d.ts +76 -0
- package/dist/internal/funding/Chain.d.ts.map +1 -0
- package/dist/internal/funding/Chain.js +38 -0
- package/dist/internal/funding/Chain.js.map +1 -0
- package/dist/internal/funding/Deposit.d.ts +366 -0
- package/dist/internal/funding/Deposit.d.ts.map +1 -0
- package/dist/internal/funding/Deposit.js +286 -0
- package/dist/internal/funding/Deposit.js.map +1 -0
- package/dist/internal/funding/DepositAddress.d.ts +345 -0
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -0
- package/dist/internal/funding/DepositAddress.js +189 -0
- package/dist/internal/funding/DepositAddress.js.map +1 -0
- package/dist/internal/funding/Evidence.d.ts +52 -0
- package/dist/internal/funding/Evidence.d.ts.map +1 -0
- package/dist/internal/funding/Evidence.js +314 -0
- package/dist/internal/funding/Evidence.js.map +1 -0
- package/dist/internal/funding/Provider.d.ts +1186 -0
- package/dist/internal/funding/Provider.d.ts.map +1 -0
- package/dist/internal/funding/Provider.js +1081 -0
- package/dist/internal/funding/Provider.js.map +1 -0
- package/dist/internal/funding/Reconciliation.d.ts +113 -0
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -0
- package/dist/internal/funding/Reconciliation.js +676 -0
- package/dist/internal/funding/Reconciliation.js.map +1 -0
- package/dist/internal/funding/Route.d.ts +21 -0
- package/dist/internal/funding/Route.d.ts.map +1 -0
- package/dist/internal/funding/Route.js +5 -0
- package/dist/internal/funding/Route.js.map +1 -0
- package/dist/internal/funding/Subsidy.d.ts +113 -0
- package/dist/internal/funding/Subsidy.d.ts.map +1 -0
- package/dist/internal/funding/Subsidy.js +138 -0
- package/dist/internal/funding/Subsidy.js.map +1 -0
- package/dist/internal/funding/Token.d.ts +41 -0
- package/dist/internal/funding/Token.d.ts.map +1 -0
- package/dist/internal/funding/Token.js +22 -0
- package/dist/internal/funding/Token.js.map +1 -0
- package/dist/internal/funding/Transfer.d.ts +643 -0
- package/dist/internal/funding/Transfer.d.ts.map +1 -0
- package/dist/internal/funding/Transfer.js +332 -0
- package/dist/internal/funding/Transfer.js.map +1 -0
- package/dist/internal/funding/index.d.ts +13 -0
- package/dist/internal/funding/index.d.ts.map +1 -0
- package/dist/internal/funding/index.js +13 -0
- package/dist/internal/funding/index.js.map +1 -0
- package/dist/internal/funding/providers/across.d.ts +21 -0
- package/dist/internal/funding/providers/across.d.ts.map +1 -0
- package/dist/internal/funding/providers/across.js +117 -0
- package/dist/internal/funding/providers/across.js.map +1 -0
- package/dist/internal/funding/providers/relay.d.ts +46 -0
- package/dist/internal/funding/providers/relay.d.ts.map +1 -0
- package/dist/internal/funding/providers/relay.js +464 -0
- package/dist/internal/funding/providers/relay.js.map +1 -0
- package/dist/internal/funding/providers/rhino.d.ts +15 -0
- package/dist/internal/funding/providers/rhino.d.ts.map +1 -0
- package/dist/internal/funding/providers/rhino.js +116 -0
- package/dist/internal/funding/providers/rhino.js.map +1 -0
- package/dist/internal/funding/providers/squid.d.ts +19 -0
- package/dist/internal/funding/providers/squid.d.ts.map +1 -0
- package/dist/internal/funding/providers/squid.js +120 -0
- package/dist/internal/funding/providers/squid.js.map +1 -0
- package/dist/internal/funding/providers/symbiosis.d.ts +20 -0
- package/dist/internal/funding/providers/symbiosis.d.ts.map +1 -0
- package/dist/internal/funding/providers/symbiosis.js +176 -0
- package/dist/internal/funding/providers/symbiosis.js.map +1 -0
- package/dist/internal/index.d.ts +5 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +5 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/webhookDestinations/url.js +61 -57
- package/dist/internal/webhookDestinations/url.js.map +1 -1
- package/dist/providers/index.d.ts +43 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +19 -0
- package/dist/providers/index.js.map +1 -0
- package/package.json +9 -4
- package/src/ApiKeys.test.ts +11 -7
- package/src/ApiKeys.ts +37 -9
- package/src/App.test.ts +85 -10
- package/src/App.ts +224 -137
- package/src/Assets.ts +29 -4
- package/src/Client.test-d.ts +650 -30
- package/src/Scope.test.ts +19 -0
- package/src/Scope.ts +28 -11
- package/src/Webhooks.test.ts +25 -0
- package/src/Webhooks.ts +1 -1
- package/src/admin/App.test.ts +9 -2
- package/src/admin/App.ts +32 -9
- package/src/admin/apps/api-keys.test.ts +167 -23
- package/src/admin/apps/api-keys.ts +166 -28
- package/src/admin/apps/earn-vaults.test.ts +338 -0
- package/src/admin/apps/earn-vaults.ts +572 -0
- package/src/admin/apps/scopes.test.ts +16 -1
- package/src/admin/ui/plugin.ts +2 -2
- package/src/admin/ui/src/components/EarnVaultForm.tsx +137 -0
- package/src/admin/ui/src/components/MobileProfile.tsx +2 -2
- package/src/admin/ui/src/components/Page.tsx +1 -1
- package/src/admin/ui/src/components/ThemeToggle.tsx +1 -1
- package/src/admin/ui/src/lib/api-keys.ts +37 -7
- package/src/admin/ui/src/lib/client.ts +1 -1
- package/src/admin/ui/src/lib/config.ts +1 -1
- package/src/admin/ui/src/lib/early-access.ts +8 -9
- package/src/admin/ui/src/lib/earn-vaults.ts +207 -0
- package/src/admin/ui/src/lib/format.ts +13 -0
- package/src/admin/ui/src/lib/organizations.test.ts +14 -4
- package/src/admin/ui/src/lib/organizations.ts +7 -1
- package/src/admin/ui/src/lib/response.ts +22 -0
- package/src/admin/ui/src/lib/scopes.test.ts +19 -11
- package/src/admin/ui/src/lib/scopes.ts +28 -7
- package/src/admin/ui/src/lib/verified-tokens.ts +10 -9
- package/src/admin/ui/src/routeTree.gen.ts +70 -7
- package/src/admin/ui/src/router.tsx +2 -2
- package/src/admin/ui/src/routes/__root.tsx +9 -8
- package/src/admin/ui/src/routes/api-keys.tsx +475 -64
- package/src/admin/ui/src/routes/early-access.tsx +5 -12
- package/src/admin/ui/src/routes/earn.vaults.tsx +348 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +154 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +190 -0
- package/src/admin/ui/src/routes/organizations.tsx +4 -7
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +56 -54
- package/src/admin/ui/src/routes/verified-tokens.tsx +4 -4
- package/src/admin/ui/vite.config.ts +4 -1
- package/src/admin/ui.generated.ts +113 -43
- package/src/analytics/Analytics.test.ts +69 -10
- package/src/analytics/Analytics.ts +20 -1
- package/src/analytics/tables/requestEvents.ts +79 -37
- package/src/apps/Zones.test.ts +33 -0
- package/src/apps/Zones.ts +40 -0
- package/src/apps/composition.test.ts +84 -1
- package/src/apps/data/App.test.ts +28 -11
- package/src/apps/data/App.ts +96 -33
- package/src/apps/data/FxOracle.ts +1 -1
- package/src/apps/data/index.ts +0 -1
- package/src/apps/data/routes/activities.test.ts +82 -6
- package/src/apps/data/routes/activities.ts +131 -71
- package/src/apps/data/routes/balances.test.ts +50 -37
- package/src/apps/data/routes/balances.ts +5 -5
- package/src/apps/data/routes/blocks.test.ts +2 -0
- package/src/apps/data/routes/coingecko.test.ts +22 -0
- package/src/apps/data/routes/coingecko.ts +84 -48
- package/src/apps/data/routes/earn.test.ts +1108 -0
- package/src/apps/data/routes/earn.ts +1391 -0
- package/src/apps/data/routes/exchanges.test.ts +82 -33
- package/src/apps/data/routes/exchanges.ts +842 -227
- package/src/apps/data/routes/fee-amm.test.ts +4 -6
- package/src/apps/data/routes/fee-amm.ts +69 -12
- package/src/apps/data/routes/funding.test.ts +2712 -221
- package/src/apps/data/routes/funding.ts +1604 -387
- package/src/apps/data/routes/indexer.test.ts +43 -34
- package/src/apps/data/routes/indexer.ts +19 -2
- package/src/apps/data/routes/receipts.test.ts +5 -3
- package/src/apps/data/routes/receipts.ts +13 -11
- package/src/apps/data/routes/rpc.test.ts +446 -28
- package/src/apps/data/routes/rpc.ts +243 -25
- package/src/apps/data/routes/tokenlist.ts +72 -19
- package/src/apps/data/routes/tokens.ts +258 -86
- package/src/apps/data/routes/transactions.test.ts +2 -0
- package/src/apps/data/routes/transactions.ts +77 -42
- package/src/apps/data/routes/transfers.test.ts +166 -4
- package/src/apps/data/routes/transfers.ts +216 -78
- package/src/apps/data/routes/valuation.test.ts +62 -9
- package/src/apps/data/routes/valuation.ts +2 -2
- package/src/apps/data/routes/webhooks.test.ts +386 -43
- package/src/apps/data/routes/webhooks.ts +172 -71
- package/src/apps/data/routes/zones.test.ts +473 -0
- package/src/apps/data/routes/zones.ts +338 -0
- package/src/apps/docs/reference.ts +8 -6
- package/src/apps/index.ts +2 -1
- package/src/apps/management/Billing.test.ts +29 -0
- package/src/apps/management/Billing.ts +23 -0
- package/src/apps/management/Error.ts +12 -0
- package/src/apps/management/routes/api-keys.test.ts +5 -3
- package/src/apps/management/routes/api-keys.ts +2 -9
- package/src/apps/management/routes/invitations.ts +4 -11
- package/src/apps/management/routes/orgs.ts +2 -9
- package/src/apps/management/routes/scopes.test.ts +7 -2
- package/src/apps/management/routes/scopes.ts +2 -2
- package/src/apps/management/routes/webhooks.test.ts +6 -1
- package/src/apps/management/routes/webhooks.ts +15 -3
- package/src/apps/mpp/App.ts +276 -29
- package/src/apps/mpp/Mpp.test.ts +631 -26
- package/src/apps/mpp/Mpp.ts +0 -42
- package/src/apps/mpp/internal/Adapter.ts +108 -3
- package/src/apps/mpp/internal/Error.test.ts +33 -0
- package/src/apps/mpp/internal/Error.ts +44 -6
- package/src/apps/mpp/internal/Idempotency.test.ts +213 -0
- package/src/apps/mpp/internal/Idempotency.ts +59 -5
- package/src/apps/mpp/internal/Policy.test.ts +122 -0
- package/src/apps/mpp/internal/Policy.ts +98 -0
- package/src/apps/mpp/internal/ScreenManager.test.ts +68 -0
- package/src/apps/mpp/internal/ScreenManager.ts +41 -0
- package/src/apps/mpp/internal/Screening.ts +40 -3
- package/src/apps/mpp/internal/Sponsorship.ts +144 -0
- package/src/apps/mpp/internal/Utils.ts +30 -0
- package/src/apps/relay/App.test.ts +493 -62
- package/src/apps/relay/App.ts +233 -23
- package/src/apps/relay/Sponsorships.test.ts +49 -0
- package/src/apps/relay/Sponsorships.ts +18 -6
- package/src/db/Db.ts +439 -0
- package/src/db/Schema.ts +325 -2
- package/src/db/tables/earnVaults.test.ts +185 -0
- package/src/db/tables/earnVaults.ts +151 -0
- package/src/db/tables/fundingCatalog.test.ts +108 -0
- package/src/db/tables/fundingCatalog.ts +157 -0
- package/src/db/tables/fundingDepositAddresses.test.ts +580 -0
- package/src/db/tables/fundingDepositAddresses.ts +376 -0
- package/src/db/tables/fundingDeposits.test.ts +261 -0
- package/src/db/tables/fundingDeposits.ts +229 -0
- package/src/db/tables/fundingIdempotency.test.ts +182 -0
- package/src/db/tables/fundingIdempotency.ts +180 -0
- package/src/db/tables/fundingTransferEvents.ts +28 -0
- package/src/db/tables/fundingTransferTransactions.test.ts +69 -0
- package/src/db/tables/fundingTransferTransactions.ts +37 -0
- package/src/db/tables/fundingTransfers.test.ts +89 -0
- package/src/db/tables/fundingTransfers.ts +153 -0
- package/src/db/tables/organizations.ts +16 -0
- package/src/db/tables/projects.ts +16 -0
- package/src/db/tables/requestUsage.ts +23 -0
- package/src/db/tables/sponsoredTransactions.test.ts +11 -0
- package/src/db/tables/sponsoredTransactions.ts +3 -3
- package/src/db/tables/users.ts +16 -0
- package/src/db/tables/verifiedTokens.ts +19 -14
- package/src/db/tables/webhookSubscriptions.ts +58 -3
- package/src/handlers/relay.test.ts +2 -0
- package/src/handlers/relay.ts +95 -99
- package/src/internal/Auth.test.ts +48 -0
- package/src/internal/Auth.ts +61 -2
- package/src/internal/Cache.ts +13 -9
- package/src/internal/Cursor.test.ts +2 -2
- package/src/internal/Cursor.ts +1 -1
- package/src/internal/EarnRates.test.ts +125 -0
- package/src/internal/EarnRates.ts +409 -0
- package/src/internal/EarnVaults.test.ts +195 -0
- package/src/internal/EarnVaults.ts +876 -0
- package/src/internal/EdgeCache.test.ts +19 -0
- package/src/internal/EdgeCache.ts +35 -5
- package/src/internal/Id.ts +14 -0
- package/src/internal/Idempotency.test.ts +109 -0
- package/src/internal/Idempotency.ts +237 -0
- package/src/internal/Log.test-d.ts +41 -8
- package/src/internal/Log.test.ts +189 -8
- package/src/internal/Log.ts +124 -17
- package/src/internal/MetricSink.test.ts +244 -4
- package/src/internal/MetricSink.ts +51 -1
- package/src/internal/OpenApi.ts +3 -0
- package/src/internal/Provider.test.ts +17 -0
- package/src/internal/Provider.ts +17 -0
- package/src/internal/Schema.ts +27 -17
- package/src/internal/Store.test.ts +25 -0
- package/src/internal/Store.ts +46 -0
- package/src/internal/Tidx.local.test.ts +78 -3
- package/src/internal/Tidx.test.ts +212 -18
- package/src/internal/Tidx.ts +112 -32
- package/src/internal/VerifiedTokens.test.ts +15 -0
- package/src/internal/Viem.test.ts +170 -17
- package/src/internal/Viem.ts +111 -28
- package/src/internal/WebhookDestination.ts +25 -23
- package/src/internal/Webhooks.test.ts +59 -0
- package/src/internal/Webhooks.ts +34 -10
- package/src/internal/exchange/Provider.test.ts +216 -0
- package/src/internal/exchange/Provider.ts +326 -0
- package/src/internal/exchange/index.test.ts +6 -0
- package/src/internal/exchange/index.ts +1 -0
- package/src/internal/exchange/providers/uniswap.test.ts +122 -0
- package/src/internal/exchange/providers/uniswap.ts +682 -0
- package/src/internal/funding/Action.test.ts +138 -0
- package/src/internal/funding/Action.ts +117 -0
- package/src/internal/funding/Catalog.test.ts +311 -0
- package/src/internal/funding/Catalog.ts +347 -0
- package/src/internal/funding/Chain.test.ts +79 -0
- package/src/internal/funding/Chain.ts +120 -0
- package/src/internal/funding/Deposit.test.ts +26 -0
- package/src/internal/funding/Deposit.ts +453 -0
- package/src/internal/funding/DepositAddress.test.ts +18 -0
- package/src/internal/funding/DepositAddress.ts +312 -0
- package/src/internal/funding/Evidence.test.ts +297 -0
- package/src/internal/funding/Evidence.ts +430 -0
- package/src/internal/funding/Provider.test.ts +1328 -0
- package/src/internal/funding/Provider.ts +1796 -0
- package/src/internal/funding/Reconciliation.local.test.ts +504 -0
- package/src/internal/funding/Reconciliation.test.ts +2020 -0
- package/src/internal/funding/Reconciliation.ts +930 -0
- package/src/internal/funding/Route.test.ts +66 -0
- package/src/internal/funding/Route.ts +29 -0
- package/src/internal/funding/Subsidy.local.test.ts +152 -0
- package/src/internal/funding/Subsidy.test.ts +75 -0
- package/src/internal/funding/Subsidy.ts +260 -0
- package/src/internal/funding/Token.test.ts +47 -0
- package/src/internal/funding/Token.ts +59 -0
- package/src/internal/funding/Transfer.test.ts +369 -0
- package/src/internal/funding/Transfer.ts +522 -0
- package/src/internal/funding/index.test.ts +20 -0
- package/src/internal/funding/index.ts +12 -0
- package/src/internal/funding/providers/across.ts +149 -0
- package/src/{apps/data/FundingQuoteProviders.test.ts → internal/funding/providers/index.test.ts} +178 -157
- package/src/internal/funding/providers/relay.test.ts +474 -0
- package/src/internal/funding/providers/relay.ts +559 -0
- package/src/internal/funding/providers/rhino.ts +139 -0
- package/src/internal/funding/providers/squid.ts +151 -0
- package/src/internal/funding/providers/symbiosis.ts +221 -0
- package/src/internal/index.test.ts +5 -1
- package/src/internal/index.ts +5 -1
- package/src/internal/webhookDestinations/url.ts +49 -45
- package/src/providers/index.test.ts +14 -0
- package/src/providers/index.ts +54 -0
- package/dist/apps/data/FundingQuoteProviders.d.ts +0 -174
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +0 -1
- package/dist/apps/data/FundingQuoteProviders.js +0 -775
- package/dist/apps/data/FundingQuoteProviders.js.map +0 -1
- package/dist/internal/FundingQuotes.d.ts +0 -864
- package/dist/internal/FundingQuotes.d.ts.map +0 -1
- package/dist/internal/FundingQuotes.js +0 -672
- package/dist/internal/FundingQuotes.js.map +0 -1
- package/src/apps/data/FundingQuoteProviders.ts +0 -1043
- package/src/internal/FundingQuotes.test.ts +0 -456
- package/src/internal/FundingQuotes.ts +0 -944
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import type { JSONColumnType, Selectable } from 'kysely'
|
|
2
|
+
|
|
3
|
+
import type * as Db from '../Db.js'
|
|
4
|
+
import type * as db_Schema from '../Schema.js'
|
|
5
|
+
|
|
6
|
+
/** Columns of the `funding_deposits` table. */
|
|
7
|
+
export type Table = Omit<
|
|
8
|
+
db_Schema.FundingDeposit,
|
|
9
|
+
'providerRequestIds' | 'providerTransactionHashes'
|
|
10
|
+
> & {
|
|
11
|
+
/** Private provider request identifiers stored as JSON. */
|
|
12
|
+
providerRequestIds: JSONColumnType<readonly string[], string, string>
|
|
13
|
+
/** Private provider transaction references stored as JSON. */
|
|
14
|
+
providerTransactionHashes: JSONColumnType<readonly string[], string, string>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** A stored funding deposit. */
|
|
18
|
+
export type Record = Selectable<Table>
|
|
19
|
+
|
|
20
|
+
/** Ownership filter inherited from the deposit address. */
|
|
21
|
+
export type Owner = {
|
|
22
|
+
/** Key environment. */
|
|
23
|
+
environment: Record['environment']
|
|
24
|
+
/** Owning organization id (`org_…`). */
|
|
25
|
+
orgId: string
|
|
26
|
+
/** Attributed project id for project-scoped API keys. */
|
|
27
|
+
projectId?: string | undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Inserts one provider-observed source transfer as a funding deposit. */
|
|
31
|
+
export function insert(db: Db.Db, record: Record): Promise<Record> {
|
|
32
|
+
return db.kysely
|
|
33
|
+
.insertInto('funding_deposits')
|
|
34
|
+
.values({
|
|
35
|
+
...record,
|
|
36
|
+
providerRequestIds: JSON.stringify(record.providerRequestIds),
|
|
37
|
+
providerTransactionHashes: JSON.stringify(record.providerTransactionHashes),
|
|
38
|
+
})
|
|
39
|
+
.returningAll()
|
|
40
|
+
.executeTakeFirstOrThrow()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Gets deposits created from one provider-observed source transaction. */
|
|
44
|
+
export function listByProviderObservation(
|
|
45
|
+
db: Db.Db,
|
|
46
|
+
options: listByProviderObservation.Options,
|
|
47
|
+
): Promise<Record[]> {
|
|
48
|
+
return db.kysely
|
|
49
|
+
.selectFrom('funding_deposits')
|
|
50
|
+
.selectAll()
|
|
51
|
+
.where('depositAddressId', '=', options.depositAddressId)
|
|
52
|
+
.where('providerRequestId', '=', options.providerRequestId)
|
|
53
|
+
.where('sourceTransactionHash', '=', options.sourceTransactionHash)
|
|
54
|
+
.orderBy('providerTransferIndex', 'asc')
|
|
55
|
+
.execute()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export declare namespace listByProviderObservation {
|
|
59
|
+
/** Provider observation fields that identify one source transaction. */
|
|
60
|
+
type Options = {
|
|
61
|
+
/** Funding deposit address that received the transfer. */
|
|
62
|
+
depositAddressId: string
|
|
63
|
+
/** Provider request that reported the transfer. */
|
|
64
|
+
providerRequestId: string
|
|
65
|
+
/** Provider-observed source transaction reference. */
|
|
66
|
+
sourceTransactionHash: string
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Gets deposits associated with one address and source transaction. */
|
|
71
|
+
export function listBySourceTransaction(
|
|
72
|
+
db: Db.Db,
|
|
73
|
+
options: listBySourceTransaction.Options,
|
|
74
|
+
): Promise<Record[]> {
|
|
75
|
+
return db.kysely
|
|
76
|
+
.selectFrom('funding_deposits')
|
|
77
|
+
.selectAll()
|
|
78
|
+
.where('depositAddressId', '=', options.depositAddressId)
|
|
79
|
+
.where('sourceTransactionHash', '=', options.sourceTransactionHash)
|
|
80
|
+
.orderBy('sourceTransferIndex', 'asc')
|
|
81
|
+
.execute()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export declare namespace listBySourceTransaction {
|
|
85
|
+
/** Source transaction fields scoped to one deposit address. */
|
|
86
|
+
type Options = {
|
|
87
|
+
/** Funding deposit address that received the transfer. */
|
|
88
|
+
depositAddressId: string
|
|
89
|
+
/** Provider-observed source transaction reference. */
|
|
90
|
+
sourceTransactionHash: string
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Gets a funding deposit without ownership scoping. */
|
|
95
|
+
export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
96
|
+
return db.kysely
|
|
97
|
+
.selectFrom('funding_deposits')
|
|
98
|
+
.selectAll()
|
|
99
|
+
.where('id', '=', id)
|
|
100
|
+
.executeTakeFirst()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Gets an owner-visible funding deposit. */
|
|
104
|
+
export function getOwned(db: Db.Db, owner: Owner, id: string): Promise<Record | undefined> {
|
|
105
|
+
let query = db.kysely
|
|
106
|
+
.selectFrom('funding_deposits')
|
|
107
|
+
.selectAll()
|
|
108
|
+
.where('environment', '=', owner.environment)
|
|
109
|
+
.where('id', '=', id)
|
|
110
|
+
.where('orgId', '=', owner.orgId)
|
|
111
|
+
if (owner.projectId !== undefined) query = query.where('projectId', '=', owner.projectId)
|
|
112
|
+
return query.executeTakeFirst()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Lists one owner-visible address's deposits newest-first. */
|
|
116
|
+
export function listByAddress(
|
|
117
|
+
db: Db.Db,
|
|
118
|
+
owner: Owner,
|
|
119
|
+
addressId: string,
|
|
120
|
+
options: listByAddress.Options,
|
|
121
|
+
): Promise<Record[]> {
|
|
122
|
+
const { cursor, limit } = options
|
|
123
|
+
let query = db.kysely
|
|
124
|
+
.selectFrom('funding_deposits')
|
|
125
|
+
.selectAll()
|
|
126
|
+
.where('depositAddressId', '=', addressId)
|
|
127
|
+
.where('environment', '=', owner.environment)
|
|
128
|
+
.where('orgId', '=', owner.orgId)
|
|
129
|
+
if (owner.projectId !== undefined) query = query.where('projectId', '=', owner.projectId)
|
|
130
|
+
if (cursor)
|
|
131
|
+
query = query.where((eb) =>
|
|
132
|
+
eb.or([
|
|
133
|
+
eb('createdAt', '<', cursor.createdAt),
|
|
134
|
+
eb.and([eb('createdAt', '=', cursor.createdAt), eb('id', '<', cursor.id)]),
|
|
135
|
+
]),
|
|
136
|
+
)
|
|
137
|
+
return query.orderBy('createdAt', 'desc').orderBy('id', 'desc').limit(limit).execute()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export declare namespace listByAddress {
|
|
141
|
+
/** Cursor fields for the last deposit returned by the previous page. */
|
|
142
|
+
type Cursor = {
|
|
143
|
+
/** Deposit creation time. */
|
|
144
|
+
createdAt: string
|
|
145
|
+
/** Deposit id, used as a deterministic tie-breaker. */
|
|
146
|
+
id: string
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Paging options for one address's deposits. */
|
|
150
|
+
type Options = {
|
|
151
|
+
/** Exclusive lower bound from the previous page. */
|
|
152
|
+
cursor?: Cursor | undefined
|
|
153
|
+
/** Maximum rows to return. */
|
|
154
|
+
limit: number
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Applies a version-guarded deposit update. */
|
|
159
|
+
export function update(db: Db.Db, options: update.Options): Promise<Record | undefined> {
|
|
160
|
+
return db.kysely
|
|
161
|
+
.updateTable('funding_deposits')
|
|
162
|
+
.set({
|
|
163
|
+
providerOutputAmount: options.providerOutputAmount,
|
|
164
|
+
providerRequestId: options.providerRequestId,
|
|
165
|
+
providerRequestIds: JSON.stringify(options.providerRequestIds),
|
|
166
|
+
providerState: options.providerState,
|
|
167
|
+
providerTransactionHashes: JSON.stringify(options.providerTransactionHashes),
|
|
168
|
+
providerTransferIndex: options.providerTransferIndex,
|
|
169
|
+
retryState: options.retryState,
|
|
170
|
+
settlementTransaction: options.settlementTransaction,
|
|
171
|
+
settlementTransactionHash: options.settlementTransactionHash,
|
|
172
|
+
snapshot: options.snapshot,
|
|
173
|
+
sourceTransferIndex: options.sourceTransferIndex,
|
|
174
|
+
status: options.status,
|
|
175
|
+
statusReason: options.statusReason,
|
|
176
|
+
subsidyAmount: options.subsidyAmount,
|
|
177
|
+
tempoGasPaid: options.tempoGasPaid,
|
|
178
|
+
updatedAt: options.updatedAt,
|
|
179
|
+
version: options.version,
|
|
180
|
+
})
|
|
181
|
+
.where('id', '=', options.id)
|
|
182
|
+
.where('version', '=', options.expectedVersion)
|
|
183
|
+
.returningAll()
|
|
184
|
+
.executeTakeFirst()
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export declare namespace update {
|
|
188
|
+
/** Guarded deposit update fields. */
|
|
189
|
+
type Options = {
|
|
190
|
+
/** Stored version required for the update. */
|
|
191
|
+
expectedVersion: number
|
|
192
|
+
/** Funding deposit id (`fdp_…`). */
|
|
193
|
+
id: string
|
|
194
|
+
/** Provider output amount confirmed on Tempo. */
|
|
195
|
+
providerOutputAmount: Record['providerOutputAmount']
|
|
196
|
+
/** Provider request that first reported the deposit. */
|
|
197
|
+
providerRequestId: Record['providerRequestId']
|
|
198
|
+
/** Private provider request identifiers. */
|
|
199
|
+
providerRequestIds: Record['providerRequestIds']
|
|
200
|
+
/** Bounded private provider state. */
|
|
201
|
+
providerState: Record['providerState']
|
|
202
|
+
/** Provider-leg transaction references. */
|
|
203
|
+
providerTransactionHashes: Record['providerTransactionHashes']
|
|
204
|
+
/** Deposit position within the provider request. */
|
|
205
|
+
providerTransferIndex: Record['providerTransferIndex']
|
|
206
|
+
/** Bounded private retry state. */
|
|
207
|
+
retryState: Record['retryState']
|
|
208
|
+
/** Persisted settlement transaction bytes for exactly-once rebroadcast. */
|
|
209
|
+
settlementTransaction: Record['settlementTransaction']
|
|
210
|
+
/** Persisted settlement transaction hash. */
|
|
211
|
+
settlementTransactionHash: Record['settlementTransactionHash']
|
|
212
|
+
/** Replacement public snapshot. */
|
|
213
|
+
snapshot: Record['snapshot']
|
|
214
|
+
/** Verified transfer position in the source transaction, or null. */
|
|
215
|
+
sourceTransferIndex: Record['sourceTransferIndex']
|
|
216
|
+
/** Replacement lifecycle status. */
|
|
217
|
+
status: Record['status']
|
|
218
|
+
/** Replacement customer-safe reason. */
|
|
219
|
+
statusReason: Record['statusReason']
|
|
220
|
+
/** Destination token amount supplied by Tempo. */
|
|
221
|
+
subsidyAmount: Record['subsidyAmount']
|
|
222
|
+
/** Tempo gas paid for settlement, in base units. */
|
|
223
|
+
tempoGasPaid: Record['tempoGasPaid']
|
|
224
|
+
/** New material update time. */
|
|
225
|
+
updatedAt: string
|
|
226
|
+
/** New material version. */
|
|
227
|
+
version: number
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as TestApp from '../../../test/App.js'
|
|
2
|
+
import * as FundingIdempotency from './fundingIdempotency.js'
|
|
3
|
+
|
|
4
|
+
const db = TestApp.database()
|
|
5
|
+
|
|
6
|
+
const now = new Date('2026-01-01T00:00:00.000Z')
|
|
7
|
+
const replayTtlMs = 86_400_000
|
|
8
|
+
const ttlMs = 60_000
|
|
9
|
+
|
|
10
|
+
beforeEach(() => vi.useFakeTimers({ now, toFake: ['Date'] }))
|
|
11
|
+
afterEach(() => vi.useRealTimers())
|
|
12
|
+
|
|
13
|
+
function input(overrides: Partial<FundingIdempotency.claim.Input> = {}) {
|
|
14
|
+
return {
|
|
15
|
+
apiKeyId: 'key_test',
|
|
16
|
+
keyHash: `hash_${Math.random().toString(36).slice(2)}`,
|
|
17
|
+
requestHash: 'req_aaaa',
|
|
18
|
+
ttlMs,
|
|
19
|
+
...overrides,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('claim', () => {
|
|
24
|
+
test('claims, blocks equivalent concurrent requests, and flags mismatches', async () => {
|
|
25
|
+
const first = input()
|
|
26
|
+
expect(await FundingIdempotency.claim(db, first)).toEqual({
|
|
27
|
+
createdAt: now.toISOString(),
|
|
28
|
+
type: 'claimed',
|
|
29
|
+
})
|
|
30
|
+
expect(await FundingIdempotency.claim(db, first)).toEqual({ type: 'pending' })
|
|
31
|
+
expect(await FundingIdempotency.claim(db, { ...first, requestHash: 'req_bbbb' })).toEqual({
|
|
32
|
+
type: 'mismatch',
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('replays the stored response after completion', async () => {
|
|
37
|
+
const claimed = input()
|
|
38
|
+
const result = await FundingIdempotency.claim(db, claimed)
|
|
39
|
+
expect(result.type).toBe('claimed')
|
|
40
|
+
if (result.type !== 'claimed') return
|
|
41
|
+
const completedAt = new Date('2026-01-01T00:00:30.000Z')
|
|
42
|
+
vi.setSystemTime(completedAt)
|
|
43
|
+
await FundingIdempotency.complete(db, {
|
|
44
|
+
apiKeyId: claimed.apiKeyId,
|
|
45
|
+
createdAt: result.createdAt,
|
|
46
|
+
keyHash: claimed.keyHash,
|
|
47
|
+
replayTtlMs,
|
|
48
|
+
response: '{"id":"ftr_test"}',
|
|
49
|
+
transferId: 'ftr_test',
|
|
50
|
+
})
|
|
51
|
+
await expect(
|
|
52
|
+
db.kysely
|
|
53
|
+
.selectFrom('funding_idempotency_requests')
|
|
54
|
+
.select('expiresAt')
|
|
55
|
+
.where('apiKeyId', '=', claimed.apiKeyId)
|
|
56
|
+
.where('keyHash', '=', claimed.keyHash)
|
|
57
|
+
.executeTakeFirstOrThrow(),
|
|
58
|
+
).resolves.toEqual({ expiresAt: '2026-01-02T00:00:30.000Z' })
|
|
59
|
+
expect(await FundingIdempotency.claim(db, claimed)).toEqual({
|
|
60
|
+
response: '{"id":"ftr_test"}',
|
|
61
|
+
type: 'replay',
|
|
62
|
+
})
|
|
63
|
+
// A different request against the completed key still conflicts.
|
|
64
|
+
expect(await FundingIdempotency.claim(db, { ...claimed, requestHash: 'req_bbbb' })).toEqual({
|
|
65
|
+
type: 'mismatch',
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('completes non-transfer resources without a transfer id', async () => {
|
|
70
|
+
const claimed = input()
|
|
71
|
+
const result = await FundingIdempotency.claim(db, claimed)
|
|
72
|
+
expect(result.type).toBe('claimed')
|
|
73
|
+
if (result.type !== 'claimed') return
|
|
74
|
+
await FundingIdempotency.complete(db, {
|
|
75
|
+
apiKeyId: claimed.apiKeyId,
|
|
76
|
+
createdAt: result.createdAt,
|
|
77
|
+
keyHash: claimed.keyHash,
|
|
78
|
+
replayTtlMs,
|
|
79
|
+
response: '{"id":"fda_test"}',
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
await expect(
|
|
83
|
+
db.kysely
|
|
84
|
+
.selectFrom('funding_idempotency_requests')
|
|
85
|
+
.select('transferId')
|
|
86
|
+
.where('apiKeyId', '=', claimed.apiKeyId)
|
|
87
|
+
.where('keyHash', '=', claimed.keyHash)
|
|
88
|
+
.executeTakeFirstOrThrow(),
|
|
89
|
+
).resolves.toEqual({ transferId: null })
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('reclaims an expired row in place', async () => {
|
|
93
|
+
const claimed = input()
|
|
94
|
+
await FundingIdempotency.claim(db, claimed)
|
|
95
|
+
const afterExpiry = new Date('2026-01-01T00:01:00.001Z')
|
|
96
|
+
vi.setSystemTime(afterExpiry)
|
|
97
|
+
expect(await FundingIdempotency.claim(db, claimed)).toEqual({
|
|
98
|
+
createdAt: afterExpiry.toISOString(),
|
|
99
|
+
type: 'claimed',
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('release frees a pending claim for retry', async () => {
|
|
104
|
+
const claimed = input()
|
|
105
|
+
const result = await FundingIdempotency.claim(db, claimed)
|
|
106
|
+
expect(result.type).toBe('claimed')
|
|
107
|
+
if (result.type !== 'claimed') return
|
|
108
|
+
await FundingIdempotency.release(db, {
|
|
109
|
+
apiKeyId: claimed.apiKeyId,
|
|
110
|
+
createdAt: result.createdAt,
|
|
111
|
+
keyHash: claimed.keyHash,
|
|
112
|
+
})
|
|
113
|
+
expect(await FundingIdempotency.claim(db, claimed)).toEqual({
|
|
114
|
+
createdAt: now.toISOString(),
|
|
115
|
+
type: 'claimed',
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
test('stale completion and release cannot mutate a replacement claim', async () => {
|
|
120
|
+
const claimed = input()
|
|
121
|
+
const original = await FundingIdempotency.claim(db, claimed)
|
|
122
|
+
expect(original.type).toBe('claimed')
|
|
123
|
+
if (original.type !== 'claimed') return
|
|
124
|
+
|
|
125
|
+
const afterExpiry = new Date('2026-01-01T00:01:00.001Z')
|
|
126
|
+
vi.setSystemTime(afterExpiry)
|
|
127
|
+
const replacement = await FundingIdempotency.claim(db, claimed)
|
|
128
|
+
expect(replacement.type).toBe('claimed')
|
|
129
|
+
if (replacement.type !== 'claimed') return
|
|
130
|
+
|
|
131
|
+
const identity = {
|
|
132
|
+
apiKeyId: claimed.apiKeyId,
|
|
133
|
+
createdAt: original.createdAt,
|
|
134
|
+
keyHash: claimed.keyHash,
|
|
135
|
+
}
|
|
136
|
+
expect(
|
|
137
|
+
await FundingIdempotency.complete(db, {
|
|
138
|
+
...identity,
|
|
139
|
+
replayTtlMs,
|
|
140
|
+
response: '{"id":"ftr_stale"}',
|
|
141
|
+
transferId: 'ftr_stale',
|
|
142
|
+
}),
|
|
143
|
+
).toBeUndefined()
|
|
144
|
+
await FundingIdempotency.release(db, identity)
|
|
145
|
+
expect(await FundingIdempotency.claim(db, claimed)).toEqual({
|
|
146
|
+
type: 'pending',
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('checkpoint', () => {
|
|
152
|
+
test('resumes a provider result and completes it', async () => {
|
|
153
|
+
const claimed = input()
|
|
154
|
+
const result = await FundingIdempotency.claim(db, claimed)
|
|
155
|
+
expect(result.type).toBe('claimed')
|
|
156
|
+
if (result.type !== 'claimed') return
|
|
157
|
+
await FundingIdempotency.checkpoint(db, {
|
|
158
|
+
apiKeyId: claimed.apiKeyId,
|
|
159
|
+
createdAt: result.createdAt,
|
|
160
|
+
keyHash: claimed.keyHash,
|
|
161
|
+
replayTtlMs,
|
|
162
|
+
response: '{"requestId":"relay_request_1"}',
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
expect(await FundingIdempotency.claim(db, claimed)).toEqual({
|
|
166
|
+
createdAt: now.toISOString(),
|
|
167
|
+
response: '{"requestId":"relay_request_1"}',
|
|
168
|
+
type: 'resume',
|
|
169
|
+
})
|
|
170
|
+
await FundingIdempotency.complete(db, {
|
|
171
|
+
apiKeyId: claimed.apiKeyId,
|
|
172
|
+
createdAt: result.createdAt,
|
|
173
|
+
keyHash: claimed.keyHash,
|
|
174
|
+
replayTtlMs,
|
|
175
|
+
response: '{"id":"fda_test"}',
|
|
176
|
+
})
|
|
177
|
+
expect(await FundingIdempotency.claim(db, claimed)).toEqual({
|
|
178
|
+
response: '{"id":"fda_test"}',
|
|
179
|
+
type: 'replay',
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
})
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
|
|
3
|
+
import type * as Db from '../Db.js'
|
|
4
|
+
import type * as db_Schema from '../Schema.js'
|
|
5
|
+
|
|
6
|
+
/** Columns of the `funding_idempotency_requests` table. */
|
|
7
|
+
export type Table = db_Schema.FundingIdempotencyRequest
|
|
8
|
+
/** A stored idempotency claim. */
|
|
9
|
+
export type Record = Selectable<Table>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Claims `(apiKeyId, keyHash)` for one creation attempt. A live claim rejects
|
|
13
|
+
* mismatches, blocks pending work, resumes checkpoints, or replays completion.
|
|
14
|
+
*/
|
|
15
|
+
export async function claim(db: Db.Db, input: claim.Input): Promise<claim.Result> {
|
|
16
|
+
const now = new Date()
|
|
17
|
+
const record: Record = {
|
|
18
|
+
apiKeyId: input.apiKeyId,
|
|
19
|
+
createdAt: now.toISOString(),
|
|
20
|
+
expiresAt: new Date(now.getTime() + input.ttlMs).toISOString(),
|
|
21
|
+
keyHash: input.keyHash,
|
|
22
|
+
requestHash: input.requestHash,
|
|
23
|
+
response: null,
|
|
24
|
+
status: 'pending',
|
|
25
|
+
transferId: null,
|
|
26
|
+
}
|
|
27
|
+
const inserted = await db.kysely
|
|
28
|
+
.insertInto('funding_idempotency_requests')
|
|
29
|
+
.values(record)
|
|
30
|
+
.onConflict((oc) => oc.columns(['apiKeyId', 'keyHash']).doNothing())
|
|
31
|
+
.returningAll()
|
|
32
|
+
.executeTakeFirst()
|
|
33
|
+
if (inserted) return { createdAt: inserted.createdAt, type: 'claimed' }
|
|
34
|
+
|
|
35
|
+
// Reclaim an expired row in place; the guard keeps two callers from both
|
|
36
|
+
// reclaiming (only one UPDATE matches the still-expired predicate).
|
|
37
|
+
const reclaimed = await db.kysely
|
|
38
|
+
.updateTable('funding_idempotency_requests')
|
|
39
|
+
.set(record)
|
|
40
|
+
.where('apiKeyId', '=', input.apiKeyId)
|
|
41
|
+
.where('keyHash', '=', input.keyHash)
|
|
42
|
+
.where('expiresAt', '<=', now.toISOString())
|
|
43
|
+
.returningAll()
|
|
44
|
+
.executeTakeFirst()
|
|
45
|
+
if (reclaimed) return { createdAt: reclaimed.createdAt, type: 'claimed' }
|
|
46
|
+
|
|
47
|
+
const existing = await db.kysely
|
|
48
|
+
.selectFrom('funding_idempotency_requests')
|
|
49
|
+
.selectAll()
|
|
50
|
+
.where('apiKeyId', '=', input.apiKeyId)
|
|
51
|
+
.where('keyHash', '=', input.keyHash)
|
|
52
|
+
.executeTakeFirst()
|
|
53
|
+
// The row vanished between the insert and the read (released claim); retry.
|
|
54
|
+
if (!existing) return claim(db, input)
|
|
55
|
+
if (existing.requestHash !== input.requestHash) return { type: 'mismatch' }
|
|
56
|
+
if (existing.status === 'pending') return { type: 'pending' }
|
|
57
|
+
if (existing.status === 'provisioned')
|
|
58
|
+
return {
|
|
59
|
+
createdAt: existing.createdAt,
|
|
60
|
+
response: existing.response ?? '',
|
|
61
|
+
type: 'resume',
|
|
62
|
+
}
|
|
63
|
+
return { response: existing.response ?? '', type: 'replay' }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export declare namespace claim {
|
|
67
|
+
/** Claim identity and retention. */
|
|
68
|
+
type Input = {
|
|
69
|
+
/** API key id (`key_…`) the claim is scoped to. */
|
|
70
|
+
apiKeyId: string
|
|
71
|
+
/** SHA-256 of the caller Idempotency-Key. */
|
|
72
|
+
keyHash: string
|
|
73
|
+
/** SHA-256 fingerprint of the canonical validated request. */
|
|
74
|
+
requestHash: string
|
|
75
|
+
/** Lease duration for the pending execution, in milliseconds. */
|
|
76
|
+
ttlMs: number
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Outcome of a claim attempt. */
|
|
80
|
+
type Result =
|
|
81
|
+
| { createdAt: string; type: 'claimed' }
|
|
82
|
+
| { type: 'mismatch' }
|
|
83
|
+
| { type: 'pending' }
|
|
84
|
+
| { response: string; type: 'replay' }
|
|
85
|
+
| { createdAt: string; response: string; type: 'resume' }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Stores a provider result before committing its API resource and replay response. */
|
|
89
|
+
export function checkpoint(db: Db.Db, input: checkpoint.Input): Promise<Record | undefined> {
|
|
90
|
+
const now = new Date()
|
|
91
|
+
return db.kysely
|
|
92
|
+
.updateTable('funding_idempotency_requests')
|
|
93
|
+
.set({
|
|
94
|
+
expiresAt: new Date(now.getTime() + input.replayTtlMs).toISOString(),
|
|
95
|
+
response: input.response,
|
|
96
|
+
status: 'provisioned',
|
|
97
|
+
})
|
|
98
|
+
.where('apiKeyId', '=', input.apiKeyId)
|
|
99
|
+
.where('createdAt', '=', input.createdAt)
|
|
100
|
+
.where('keyHash', '=', input.keyHash)
|
|
101
|
+
.where('status', '=', 'pending')
|
|
102
|
+
.returningAll()
|
|
103
|
+
.executeTakeFirst()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export declare namespace checkpoint {
|
|
107
|
+
/** Provider result and owned claim required for durable recovery. */
|
|
108
|
+
type Input = {
|
|
109
|
+
/** API key id (`key_…`) the claim is scoped to. */
|
|
110
|
+
apiKeyId: string
|
|
111
|
+
/** Creation time returned by the successful claim. */
|
|
112
|
+
createdAt: string
|
|
113
|
+
/** SHA-256 of the caller Idempotency-Key. */
|
|
114
|
+
keyHash: string
|
|
115
|
+
/** Recovery checkpoint retention in milliseconds. */
|
|
116
|
+
replayTtlMs: number
|
|
117
|
+
/** Serialized provider result required to resume resource creation. */
|
|
118
|
+
response: string
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Completes an owned pending or provisioned claim with its replay response. */
|
|
123
|
+
export function complete(db: Db.Db, input: complete.Input): Promise<Record | undefined> {
|
|
124
|
+
const now = new Date()
|
|
125
|
+
return db.kysely
|
|
126
|
+
.updateTable('funding_idempotency_requests')
|
|
127
|
+
.set({
|
|
128
|
+
expiresAt: new Date(now.getTime() + input.replayTtlMs).toISOString(),
|
|
129
|
+
response: input.response,
|
|
130
|
+
status: 'completed',
|
|
131
|
+
transferId: input.transferId ?? null,
|
|
132
|
+
})
|
|
133
|
+
.where('apiKeyId', '=', input.apiKeyId)
|
|
134
|
+
.where('createdAt', '=', input.createdAt)
|
|
135
|
+
.where('keyHash', '=', input.keyHash)
|
|
136
|
+
.where('status', 'in', ['pending', 'provisioned'])
|
|
137
|
+
.returningAll()
|
|
138
|
+
.executeTakeFirst()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export declare namespace complete {
|
|
142
|
+
/** Completion fields. */
|
|
143
|
+
type Input = {
|
|
144
|
+
/** API key id (`key_…`) the claim is scoped to. */
|
|
145
|
+
apiKeyId: string
|
|
146
|
+
/** Creation time returned by the successful claim. */
|
|
147
|
+
createdAt: string
|
|
148
|
+
/** SHA-256 of the caller Idempotency-Key. */
|
|
149
|
+
keyHash: string
|
|
150
|
+
/** Successful-response replay retention from completion, in milliseconds. */
|
|
151
|
+
replayTtlMs: number
|
|
152
|
+
/** Serialized success response replayed for the retention window. */
|
|
153
|
+
response: string
|
|
154
|
+
/** Transfer id (`ftr_…`) when the request created a funding transfer. */
|
|
155
|
+
transferId?: string | undefined
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Releases a pending claim after a retryable failure. */
|
|
160
|
+
export async function release(db: Db.Db, input: release.Input): Promise<void> {
|
|
161
|
+
await db.kysely
|
|
162
|
+
.deleteFrom('funding_idempotency_requests')
|
|
163
|
+
.where('apiKeyId', '=', input.apiKeyId)
|
|
164
|
+
.where('createdAt', '=', input.createdAt)
|
|
165
|
+
.where('keyHash', '=', input.keyHash)
|
|
166
|
+
.where('status', '=', 'pending')
|
|
167
|
+
.execute()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export declare namespace release {
|
|
171
|
+
/** Pending claim identity. */
|
|
172
|
+
type Input = {
|
|
173
|
+
/** API key id (`key_…`) the claim is scoped to. */
|
|
174
|
+
apiKeyId: string
|
|
175
|
+
/** Creation time returned by the successful claim. */
|
|
176
|
+
createdAt: string
|
|
177
|
+
/** SHA-256 of the caller Idempotency-Key. */
|
|
178
|
+
keyHash: string
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
|
|
3
|
+
import type * as Db from '../Db.js'
|
|
4
|
+
import type * as db_Schema from '../Schema.js'
|
|
5
|
+
|
|
6
|
+
/** Columns of the `funding_transfer_events` table. */
|
|
7
|
+
export type Table = db_Schema.FundingTransferEvent
|
|
8
|
+
/** One immutable public snapshot at a material version. */
|
|
9
|
+
export type Record = Selectable<Table>
|
|
10
|
+
|
|
11
|
+
/** Inserts an event row. Callers commit it with its transfer row in one transaction. */
|
|
12
|
+
export function insert(db: Db.Db, record: Record): Promise<Record> {
|
|
13
|
+
return db.kysely
|
|
14
|
+
.insertInto('funding_transfer_events')
|
|
15
|
+
.values(record)
|
|
16
|
+
.returningAll()
|
|
17
|
+
.executeTakeFirstOrThrow()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Lists a transfer's events, oldest version first. */
|
|
21
|
+
export function listByTransfer(db: Db.Db, transferId: string): Promise<Record[]> {
|
|
22
|
+
return db.kysely
|
|
23
|
+
.selectFrom('funding_transfer_events')
|
|
24
|
+
.selectAll()
|
|
25
|
+
.where('transferId', '=', transferId)
|
|
26
|
+
.orderBy('version', 'asc')
|
|
27
|
+
.execute()
|
|
28
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as TestApp from '../../../test/App.js'
|
|
2
|
+
import * as TestFunding from '../../../test/Funding.js'
|
|
3
|
+
import * as Transfer from '../../internal/funding/Transfer.js'
|
|
4
|
+
import * as FundingTransferTransactions from './fundingTransferTransactions.js'
|
|
5
|
+
|
|
6
|
+
const db = TestApp.database()
|
|
7
|
+
|
|
8
|
+
function createTransfer(id: string) {
|
|
9
|
+
return Transfer.create(db, {
|
|
10
|
+
apiKeyId: 'key_test',
|
|
11
|
+
environment: 'production',
|
|
12
|
+
id,
|
|
13
|
+
orgId: 'org_test',
|
|
14
|
+
snapshot: TestFunding.transferSnapshot(),
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe('insert', () => {
|
|
19
|
+
test('canonicalizes EVM hashes before enforcing source uniqueness', async () => {
|
|
20
|
+
const first = await createTransfer('ftr_evm_first')
|
|
21
|
+
const second = await createTransfer('ftr_evm_second')
|
|
22
|
+
const transactionRef = `0x${'aB'.repeat(32)}`
|
|
23
|
+
|
|
24
|
+
const inserted = await FundingTransferTransactions.insert(db, {
|
|
25
|
+
chainId: 'eip155:8453',
|
|
26
|
+
createdAt: '2026-01-01T00:00:01.000Z',
|
|
27
|
+
role: 'source',
|
|
28
|
+
transactionRef,
|
|
29
|
+
transferId: first.id,
|
|
30
|
+
})
|
|
31
|
+
expect(inserted?.transactionRef).toBe(transactionRef.toLowerCase())
|
|
32
|
+
|
|
33
|
+
await expect(
|
|
34
|
+
FundingTransferTransactions.insert(db, {
|
|
35
|
+
chainId: 'eip155:8453',
|
|
36
|
+
createdAt: '2026-01-01T00:00:02.000Z',
|
|
37
|
+
role: 'source',
|
|
38
|
+
transactionRef: transactionRef.toUpperCase(),
|
|
39
|
+
transferId: second.id,
|
|
40
|
+
}),
|
|
41
|
+
).rejects.toMatchObject({ constraint: 'funding_transfer_transactions_source_unique' })
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('preserves case-sensitive non-EVM transaction references', async () => {
|
|
45
|
+
const first = await createTransfer('ftr_solana_first')
|
|
46
|
+
const second = await createTransfer('ftr_solana_second')
|
|
47
|
+
const transactionRef = 'A'.repeat(87)
|
|
48
|
+
|
|
49
|
+
const uppercase = await FundingTransferTransactions.insert(db, {
|
|
50
|
+
chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
51
|
+
createdAt: '2026-01-01T00:00:01.000Z',
|
|
52
|
+
role: 'source',
|
|
53
|
+
transactionRef,
|
|
54
|
+
transferId: first.id,
|
|
55
|
+
})
|
|
56
|
+
const lowercase = await FundingTransferTransactions.insert(db, {
|
|
57
|
+
chainId: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
|
|
58
|
+
createdAt: '2026-01-01T00:00:02.000Z',
|
|
59
|
+
role: 'source',
|
|
60
|
+
transactionRef: transactionRef.toLowerCase(),
|
|
61
|
+
transferId: second.id,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
expect([uppercase?.transactionRef, lowercase?.transactionRef]).toEqual([
|
|
65
|
+
transactionRef,
|
|
66
|
+
transactionRef.toLowerCase(),
|
|
67
|
+
])
|
|
68
|
+
})
|
|
69
|
+
})
|