tapimo 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ApiKeys.d.ts +24 -7
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +17 -5
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +12104 -7861
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +191 -128
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +10 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +17 -4
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts +19 -8
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +25 -9
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -1
- package/dist/admin/App.d.ts +601 -20
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +12 -2
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +94 -11
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +141 -32
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +1069 -0
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -0
- package/dist/admin/apps/earn-vaults.js +409 -0
- package/dist/admin/apps/earn-vaults.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +166 -166
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +151 -95
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +2 -0
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +18 -2
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +22 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +59 -39
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/Zones.d.ts +8335 -0
- package/dist/apps/Zones.d.ts.map +1 -0
- package/dist/apps/Zones.js +38 -0
- package/dist/apps/Zones.js.map +1 -0
- package/dist/apps/data/App.d.ts +14377 -10165
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +91 -19
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +1 -1
- package/dist/apps/data/FxOracle.d.ts.map +1 -1
- package/dist/apps/data/index.d.ts +0 -1
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +0 -1
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +32 -32
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +130 -65
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +312 -312
- package/dist/apps/data/routes/balances.d.ts +18 -18
- package/dist/apps/data/routes/balances.js +5 -5
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
- package/dist/apps/data/routes/coingecko.js +62 -35
- package/dist/apps/data/routes/coingecko.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +2144 -0
- package/dist/apps/data/routes/earn.d.ts.map +1 -0
- package/dist/apps/data/routes/earn.js +947 -0
- package/dist/apps/data/routes/earn.js.map +1 -0
- package/dist/apps/data/routes/exchanges.d.ts +1231 -324
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +656 -193
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +59 -8
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/funding.d.ts +4092 -387
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +1403 -256
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +19 -2
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +265 -265
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +11 -11
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +5 -5
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +211 -22
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +49 -9
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +116 -88
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +198 -91
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +55 -55
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +78 -39
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +78 -29
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +165 -67
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +10 -10
- package/dist/apps/data/routes/valuation.js +2 -2
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +34 -9
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +5 -3
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +175 -65
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +281 -0
- package/dist/apps/data/routes/zones.d.ts.map +1 -0
- package/dist/apps/data/routes/zones.js +252 -0
- package/dist/apps/data/routes/zones.js.map +1 -0
- package/dist/apps/docs/reference.js +6 -5
- package/dist/apps/docs/reference.js.map +1 -1
- package/dist/apps/index.d.ts +2 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +2 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +670 -670
- package/dist/apps/management/Billing.d.ts +8 -0
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +12 -0
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/Error.d.ts +12 -0
- package/dist/apps/management/Error.d.ts.map +1 -0
- package/dist/apps/management/Error.js +10 -0
- package/dist/apps/management/Error.js.map +1 -0
- package/dist/apps/management/routes/api-keys.d.ts +5 -5
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +2 -8
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +119 -119
- package/dist/apps/management/routes/faucet.d.ts +35 -35
- package/dist/apps/management/routes/invitations.d.ts +62 -62
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +4 -10
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +30 -30
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +78 -78
- package/dist/apps/management/routes/orgs.d.ts +48 -48
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +2 -8
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +9 -9
- package/dist/apps/management/routes/scopes.js +2 -2
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +80 -80
- package/dist/apps/management/routes/verified-token-requests.d.ts +36 -36
- package/dist/apps/management/routes/webhooks.d.ts +50 -50
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +15 -3
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/App.d.ts +55 -56
- package/dist/apps/mpp/App.d.ts.map +1 -1
- package/dist/apps/mpp/App.js +192 -27
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/Mpp.d.ts +0 -20
- package/dist/apps/mpp/Mpp.d.ts.map +1 -1
- package/dist/apps/mpp/Mpp.js +0 -24
- package/dist/apps/mpp/Mpp.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +40 -0
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Adapter.js +66 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -0
- package/dist/apps/mpp/internal/Error.d.ts +4 -0
- package/dist/apps/mpp/internal/Error.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Error.js +41 -0
- package/dist/apps/mpp/internal/Error.js.map +1 -0
- package/dist/apps/mpp/internal/Idempotency.d.ts +33 -0
- package/dist/apps/mpp/internal/Idempotency.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Idempotency.js +28 -0
- package/dist/apps/mpp/internal/Idempotency.js.map +1 -0
- package/dist/apps/mpp/internal/Policy.d.ts +46 -0
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Policy.js +57 -0
- package/dist/apps/mpp/internal/Policy.js.map +1 -0
- package/dist/apps/mpp/internal/ScreenManager.d.ts +27 -0
- package/dist/apps/mpp/internal/ScreenManager.d.ts.map +1 -0
- package/dist/apps/mpp/internal/ScreenManager.js +18 -0
- package/dist/apps/mpp/internal/ScreenManager.js.map +1 -0
- package/dist/apps/mpp/internal/Screening.d.ts +35 -0
- package/dist/apps/mpp/internal/Screening.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Screening.js +20 -0
- package/dist/apps/mpp/internal/Screening.js.map +1 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts +36 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Sponsorship.js +103 -0
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -0
- package/dist/apps/mpp/internal/Utils.d.ts +7 -0
- package/dist/apps/mpp/internal/Utils.d.ts.map +1 -0
- package/dist/apps/mpp/internal/Utils.js +24 -0
- package/dist/apps/mpp/internal/Utils.js.map +1 -0
- package/dist/apps/relay/App.js +184 -24
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +16 -7
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/db/Db.d.ts +20 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +342 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +921 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +269 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +68 -0
- package/dist/db/tables/earnVaults.d.ts.map +1 -0
- package/dist/db/tables/earnVaults.js +72 -0
- package/dist/db/tables/earnVaults.js.map +1 -0
- package/dist/db/tables/fundingCatalog.d.ts +56 -0
- package/dist/db/tables/fundingCatalog.d.ts.map +1 -0
- package/dist/db/tables/fundingCatalog.js +85 -0
- package/dist/db/tables/fundingCatalog.js.map +1 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts +159 -0
- package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -0
- package/dist/db/tables/fundingDepositAddresses.js +206 -0
- package/dist/db/tables/fundingDepositAddresses.js.map +1 -0
- package/dist/db/tables/fundingDeposits.d.ts +115 -0
- package/dist/db/tables/fundingDeposits.d.ts.map +1 -0
- package/dist/db/tables/fundingDeposits.js +100 -0
- package/dist/db/tables/fundingDeposits.js.map +1 -0
- package/dist/db/tables/fundingIdempotency.d.ts +91 -0
- package/dist/db/tables/fundingIdempotency.d.ts.map +1 -0
- package/dist/db/tables/fundingIdempotency.js +103 -0
- package/dist/db/tables/fundingIdempotency.js.map +1 -0
- package/dist/db/tables/fundingTransferEvents.d.ts +12 -0
- package/dist/db/tables/fundingTransferEvents.d.ts.map +1 -0
- package/dist/db/tables/fundingTransferEvents.js +18 -0
- package/dist/db/tables/fundingTransferEvents.js.map +1 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts +15 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -0
- package/dist/db/tables/fundingTransferTransactions.js +27 -0
- package/dist/db/tables/fundingTransferTransactions.js.map +1 -0
- package/dist/db/tables/fundingTransfers.d.ts +82 -0
- package/dist/db/tables/fundingTransfers.d.ts.map +1 -0
- package/dist/db/tables/fundingTransfers.js +89 -0
- package/dist/db/tables/fundingTransfers.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +8 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +35 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +8 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +16 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +13 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +16 -0
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +4 -2
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +14 -4
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +8 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +16 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokens.d.ts +14 -7
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokens.js +9 -7
- package/dist/db/tables/verifiedTokens.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +31 -1
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +24 -3
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/relay.js +108 -108
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +26 -0
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +35 -2
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +16 -10
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/Cursor.js +1 -1
- package/dist/internal/Cursor.js.map +1 -1
- package/dist/internal/EarnRates.d.ts +89 -0
- package/dist/internal/EarnRates.d.ts.map +1 -0
- package/dist/internal/EarnRates.js +266 -0
- package/dist/internal/EarnRates.js.map +1 -0
- package/dist/internal/EarnVaults.d.ts +171 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -0
- package/dist/internal/EarnVaults.js +547 -0
- package/dist/internal/EarnVaults.js.map +1 -0
- package/dist/internal/EdgeCache.d.ts +9 -2
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +36 -9
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Id.d.ts +11 -0
- package/dist/internal/Id.d.ts.map +1 -1
- package/dist/internal/Id.js +13 -0
- package/dist/internal/Id.js.map +1 -1
- package/dist/internal/Idempotency.d.ts +83 -0
- package/dist/internal/Idempotency.d.ts.map +1 -0
- package/dist/internal/Idempotency.js +113 -0
- package/dist/internal/Idempotency.js.map +1 -0
- package/dist/internal/Log.d.ts +64 -9
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +29 -7
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +47 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +1 -1
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +3 -0
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Provider.d.ts +14 -0
- package/dist/internal/Provider.d.ts.map +1 -0
- package/dist/internal/Provider.js +5 -0
- package/dist/internal/Provider.js.map +1 -0
- package/dist/internal/Schema.d.ts +8 -3
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +24 -13
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +35 -0
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +43 -24
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +79 -11
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Viem.d.ts +82 -65
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +83 -12
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/WebhookDestination.d.ts.map +1 -1
- package/dist/internal/WebhookDestination.js +34 -28
- package/dist/internal/WebhookDestination.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +9 -0
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +15 -10
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/exchange/Provider.d.ts +219 -0
- package/dist/internal/exchange/Provider.d.ts.map +1 -0
- package/dist/internal/exchange/Provider.js +117 -0
- package/dist/internal/exchange/Provider.js.map +1 -0
- package/dist/internal/exchange/index.d.ts +2 -0
- package/dist/internal/exchange/index.d.ts.map +1 -0
- package/dist/internal/exchange/index.js +2 -0
- package/dist/internal/exchange/index.js.map +1 -0
- package/dist/internal/exchange/providers/uniswap.d.ts +57 -0
- package/dist/internal/exchange/providers/uniswap.d.ts.map +1 -0
- package/dist/internal/exchange/providers/uniswap.js +553 -0
- package/dist/internal/exchange/providers/uniswap.js.map +1 -0
- package/dist/internal/funding/Action.d.ts +55 -0
- package/dist/internal/funding/Action.d.ts.map +1 -0
- package/dist/internal/funding/Action.js +74 -0
- package/dist/internal/funding/Action.js.map +1 -0
- package/dist/internal/funding/Catalog.d.ts +107 -0
- package/dist/internal/funding/Catalog.d.ts.map +1 -0
- package/dist/internal/funding/Catalog.js +270 -0
- package/dist/internal/funding/Catalog.js.map +1 -0
- package/dist/internal/funding/Chain.d.ts +76 -0
- package/dist/internal/funding/Chain.d.ts.map +1 -0
- package/dist/internal/funding/Chain.js +38 -0
- package/dist/internal/funding/Chain.js.map +1 -0
- package/dist/internal/funding/Deposit.d.ts +366 -0
- package/dist/internal/funding/Deposit.d.ts.map +1 -0
- package/dist/internal/funding/Deposit.js +286 -0
- package/dist/internal/funding/Deposit.js.map +1 -0
- package/dist/internal/funding/DepositAddress.d.ts +345 -0
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -0
- package/dist/internal/funding/DepositAddress.js +189 -0
- package/dist/internal/funding/DepositAddress.js.map +1 -0
- package/dist/internal/funding/Evidence.d.ts +52 -0
- package/dist/internal/funding/Evidence.d.ts.map +1 -0
- package/dist/internal/funding/Evidence.js +314 -0
- package/dist/internal/funding/Evidence.js.map +1 -0
- package/dist/internal/funding/Provider.d.ts +1186 -0
- package/dist/internal/funding/Provider.d.ts.map +1 -0
- package/dist/internal/funding/Provider.js +1081 -0
- package/dist/internal/funding/Provider.js.map +1 -0
- package/dist/internal/funding/Reconciliation.d.ts +113 -0
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -0
- package/dist/internal/funding/Reconciliation.js +676 -0
- package/dist/internal/funding/Reconciliation.js.map +1 -0
- package/dist/internal/funding/Route.d.ts +21 -0
- package/dist/internal/funding/Route.d.ts.map +1 -0
- package/dist/internal/funding/Route.js +5 -0
- package/dist/internal/funding/Route.js.map +1 -0
- package/dist/internal/funding/Subsidy.d.ts +113 -0
- package/dist/internal/funding/Subsidy.d.ts.map +1 -0
- package/dist/internal/funding/Subsidy.js +138 -0
- package/dist/internal/funding/Subsidy.js.map +1 -0
- package/dist/internal/funding/Token.d.ts +41 -0
- package/dist/internal/funding/Token.d.ts.map +1 -0
- package/dist/internal/funding/Token.js +22 -0
- package/dist/internal/funding/Token.js.map +1 -0
- package/dist/internal/funding/Transfer.d.ts +643 -0
- package/dist/internal/funding/Transfer.d.ts.map +1 -0
- package/dist/internal/funding/Transfer.js +332 -0
- package/dist/internal/funding/Transfer.js.map +1 -0
- package/dist/internal/funding/index.d.ts +13 -0
- package/dist/internal/funding/index.d.ts.map +1 -0
- package/dist/internal/funding/index.js +13 -0
- package/dist/internal/funding/index.js.map +1 -0
- package/dist/internal/funding/providers/across.d.ts +21 -0
- package/dist/internal/funding/providers/across.d.ts.map +1 -0
- package/dist/internal/funding/providers/across.js +117 -0
- package/dist/internal/funding/providers/across.js.map +1 -0
- package/dist/internal/funding/providers/relay.d.ts +46 -0
- package/dist/internal/funding/providers/relay.d.ts.map +1 -0
- package/dist/internal/funding/providers/relay.js +464 -0
- package/dist/internal/funding/providers/relay.js.map +1 -0
- package/dist/internal/funding/providers/rhino.d.ts +15 -0
- package/dist/internal/funding/providers/rhino.d.ts.map +1 -0
- package/dist/internal/funding/providers/rhino.js +116 -0
- package/dist/internal/funding/providers/rhino.js.map +1 -0
- package/dist/internal/funding/providers/squid.d.ts +19 -0
- package/dist/internal/funding/providers/squid.d.ts.map +1 -0
- package/dist/internal/funding/providers/squid.js +120 -0
- package/dist/internal/funding/providers/squid.js.map +1 -0
- package/dist/internal/funding/providers/symbiosis.d.ts +20 -0
- package/dist/internal/funding/providers/symbiosis.d.ts.map +1 -0
- package/dist/internal/funding/providers/symbiosis.js +176 -0
- package/dist/internal/funding/providers/symbiosis.js.map +1 -0
- package/dist/internal/index.d.ts +5 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +5 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/webhookDestinations/url.js +61 -57
- package/dist/internal/webhookDestinations/url.js.map +1 -1
- package/dist/providers/index.d.ts +43 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +19 -0
- package/dist/providers/index.js.map +1 -0
- package/package.json +9 -4
- package/src/ApiKeys.test.ts +11 -7
- package/src/ApiKeys.ts +37 -9
- package/src/App.test.ts +85 -10
- package/src/App.ts +224 -137
- package/src/Assets.ts +29 -4
- package/src/Client.test-d.ts +650 -30
- package/src/Scope.test.ts +19 -0
- package/src/Scope.ts +28 -11
- package/src/Webhooks.test.ts +25 -0
- package/src/Webhooks.ts +1 -1
- package/src/admin/App.test.ts +9 -2
- package/src/admin/App.ts +32 -9
- package/src/admin/apps/api-keys.test.ts +167 -23
- package/src/admin/apps/api-keys.ts +166 -28
- package/src/admin/apps/earn-vaults.test.ts +338 -0
- package/src/admin/apps/earn-vaults.ts +572 -0
- package/src/admin/apps/scopes.test.ts +16 -1
- package/src/admin/ui/plugin.ts +2 -2
- package/src/admin/ui/src/components/EarnVaultForm.tsx +137 -0
- package/src/admin/ui/src/components/MobileProfile.tsx +2 -2
- package/src/admin/ui/src/components/Page.tsx +1 -1
- package/src/admin/ui/src/components/ThemeToggle.tsx +1 -1
- package/src/admin/ui/src/lib/api-keys.ts +37 -7
- package/src/admin/ui/src/lib/client.ts +1 -1
- package/src/admin/ui/src/lib/config.ts +1 -1
- package/src/admin/ui/src/lib/early-access.ts +8 -9
- package/src/admin/ui/src/lib/earn-vaults.ts +207 -0
- package/src/admin/ui/src/lib/format.ts +13 -0
- package/src/admin/ui/src/lib/organizations.test.ts +14 -4
- package/src/admin/ui/src/lib/organizations.ts +7 -1
- package/src/admin/ui/src/lib/response.ts +22 -0
- package/src/admin/ui/src/lib/scopes.test.ts +19 -11
- package/src/admin/ui/src/lib/scopes.ts +28 -7
- package/src/admin/ui/src/lib/verified-tokens.ts +10 -9
- package/src/admin/ui/src/routeTree.gen.ts +70 -7
- package/src/admin/ui/src/router.tsx +2 -2
- package/src/admin/ui/src/routes/__root.tsx +9 -8
- package/src/admin/ui/src/routes/api-keys.tsx +475 -64
- package/src/admin/ui/src/routes/early-access.tsx +5 -12
- package/src/admin/ui/src/routes/earn.vaults.tsx +348 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +154 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +190 -0
- package/src/admin/ui/src/routes/organizations.tsx +4 -7
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +56 -54
- package/src/admin/ui/src/routes/verified-tokens.tsx +4 -4
- package/src/admin/ui/vite.config.ts +4 -1
- package/src/admin/ui.generated.ts +189 -95
- package/src/analytics/Analytics.test.ts +69 -10
- package/src/analytics/Analytics.ts +20 -1
- package/src/analytics/tables/requestEvents.ts +79 -37
- package/src/apps/Zones.test.ts +33 -0
- package/src/apps/Zones.ts +40 -0
- package/src/apps/composition.test.ts +84 -1
- package/src/apps/data/App.test.ts +38 -9
- package/src/apps/data/App.ts +96 -33
- package/src/apps/data/FxOracle.ts +1 -1
- package/src/apps/data/index.ts +0 -1
- package/src/apps/data/routes/activities.test.ts +82 -6
- package/src/apps/data/routes/activities.ts +131 -71
- package/src/apps/data/routes/balances.test.ts +50 -37
- package/src/apps/data/routes/balances.ts +5 -5
- package/src/apps/data/routes/blocks.test.ts +2 -0
- package/src/apps/data/routes/coingecko.test.ts +22 -0
- package/src/apps/data/routes/coingecko.ts +84 -48
- package/src/apps/data/routes/earn.test.ts +1108 -0
- package/src/apps/data/routes/earn.ts +1391 -0
- package/src/apps/data/routes/exchanges.test.ts +82 -33
- package/src/apps/data/routes/exchanges.ts +842 -227
- package/src/apps/data/routes/fee-amm.test.ts +4 -6
- package/src/apps/data/routes/fee-amm.ts +69 -12
- package/src/apps/data/routes/funding.test.ts +2712 -221
- package/src/apps/data/routes/funding.ts +1604 -387
- package/src/apps/data/routes/indexer.test.ts +43 -34
- package/src/apps/data/routes/indexer.ts +19 -2
- package/src/apps/data/routes/receipts.test.ts +5 -3
- package/src/apps/data/routes/receipts.ts +13 -11
- package/src/apps/data/routes/rpc.test.ts +446 -28
- package/src/apps/data/routes/rpc.ts +243 -25
- package/src/apps/data/routes/tokenlist.test.ts +15 -0
- package/src/apps/data/routes/tokenlist.ts +88 -22
- package/src/apps/data/routes/tokens.ts +262 -86
- package/src/apps/data/routes/transactions.test.ts +2 -0
- package/src/apps/data/routes/transactions.ts +77 -42
- package/src/apps/data/routes/transfers.test.ts +166 -4
- package/src/apps/data/routes/transfers.ts +216 -78
- package/src/apps/data/routes/valuation.test.ts +62 -9
- package/src/apps/data/routes/valuation.ts +2 -2
- package/src/apps/data/routes/verified-tokens.test.ts +51 -0
- package/src/apps/data/routes/verified-tokens.ts +52 -15
- package/src/apps/data/routes/webhooks.test.ts +432 -33
- package/src/apps/data/routes/webhooks.ts +189 -79
- package/src/apps/data/routes/zones.test.ts +473 -0
- package/src/apps/data/routes/zones.ts +338 -0
- package/src/apps/docs/reference.ts +8 -6
- package/src/apps/index.ts +2 -1
- package/src/apps/management/Billing.test.ts +29 -0
- package/src/apps/management/Billing.ts +23 -0
- package/src/apps/management/Error.ts +12 -0
- package/src/apps/management/routes/api-keys.test.ts +5 -3
- package/src/apps/management/routes/api-keys.ts +2 -9
- package/src/apps/management/routes/invitations.ts +4 -11
- package/src/apps/management/routes/orgs.ts +2 -9
- package/src/apps/management/routes/scopes.test.ts +7 -2
- package/src/apps/management/routes/scopes.ts +2 -2
- package/src/apps/management/routes/webhooks.test.ts +6 -1
- package/src/apps/management/routes/webhooks.ts +15 -3
- package/src/apps/mpp/App.ts +276 -29
- package/src/apps/mpp/Mpp.test.ts +631 -26
- package/src/apps/mpp/Mpp.ts +0 -42
- package/src/apps/mpp/internal/Adapter.ts +108 -3
- package/src/apps/mpp/internal/Error.test.ts +33 -0
- package/src/apps/mpp/internal/Error.ts +44 -6
- package/src/apps/mpp/internal/Idempotency.test.ts +213 -0
- package/src/apps/mpp/internal/Idempotency.ts +59 -5
- package/src/apps/mpp/internal/Policy.test.ts +122 -0
- package/src/apps/mpp/internal/Policy.ts +98 -0
- package/src/apps/mpp/internal/ScreenManager.test.ts +68 -0
- package/src/apps/mpp/internal/ScreenManager.ts +41 -0
- package/src/apps/mpp/internal/Screening.ts +40 -3
- package/src/apps/mpp/internal/Sponsorship.ts +144 -0
- package/src/apps/mpp/internal/Utils.ts +30 -0
- package/src/apps/relay/App.test.ts +495 -64
- package/src/apps/relay/App.ts +234 -24
- package/src/apps/relay/Sponsorships.test.ts +51 -0
- package/src/apps/relay/Sponsorships.ts +19 -7
- package/src/db/Db.ts +439 -0
- package/src/db/Schema.ts +325 -2
- package/src/db/tables/earnVaults.test.ts +185 -0
- package/src/db/tables/earnVaults.ts +151 -0
- package/src/db/tables/fundingCatalog.test.ts +108 -0
- package/src/db/tables/fundingCatalog.ts +157 -0
- package/src/db/tables/fundingDepositAddresses.test.ts +580 -0
- package/src/db/tables/fundingDepositAddresses.ts +376 -0
- package/src/db/tables/fundingDeposits.test.ts +261 -0
- package/src/db/tables/fundingDeposits.ts +229 -0
- package/src/db/tables/fundingIdempotency.test.ts +182 -0
- package/src/db/tables/fundingIdempotency.ts +180 -0
- package/src/db/tables/fundingTransferEvents.ts +28 -0
- package/src/db/tables/fundingTransferTransactions.test.ts +69 -0
- package/src/db/tables/fundingTransferTransactions.ts +37 -0
- package/src/db/tables/fundingTransfers.test.ts +89 -0
- package/src/db/tables/fundingTransfers.ts +153 -0
- package/src/db/tables/organizations.test.ts +88 -0
- package/src/db/tables/organizations.ts +42 -1
- package/src/db/tables/projects.ts +16 -0
- package/src/db/tables/requestUsage.ts +23 -0
- package/src/db/tables/sponsoredTransactions.test.ts +52 -2
- package/src/db/tables/sponsoredTransactions.ts +18 -6
- package/src/db/tables/users.ts +16 -0
- package/src/db/tables/verifiedTokens.ts +19 -14
- package/src/db/tables/webhookSubscriptions.ts +58 -3
- package/src/handlers/relay.test.ts +2 -0
- package/src/handlers/relay.ts +95 -99
- package/src/internal/Auth.test.ts +48 -0
- package/src/internal/Auth.ts +61 -2
- package/src/internal/Cache.ts +13 -9
- package/src/internal/Cursor.test.ts +2 -2
- package/src/internal/Cursor.ts +1 -1
- package/src/internal/EarnRates.test.ts +125 -0
- package/src/internal/EarnRates.ts +409 -0
- package/src/internal/EarnVaults.test.ts +195 -0
- package/src/internal/EarnVaults.ts +876 -0
- package/src/internal/EdgeCache.test.ts +37 -5
- package/src/internal/EdgeCache.ts +39 -7
- package/src/internal/Id.ts +14 -0
- package/src/internal/Idempotency.test.ts +109 -0
- package/src/internal/Idempotency.ts +237 -0
- package/src/internal/Log.test-d.ts +41 -8
- package/src/internal/Log.test.ts +189 -8
- package/src/internal/Log.ts +124 -17
- package/src/internal/MetricSink.test.ts +244 -4
- package/src/internal/MetricSink.ts +51 -1
- package/src/internal/OpenApi.ts +3 -0
- package/src/internal/Provider.test.ts +17 -0
- package/src/internal/Provider.ts +17 -0
- package/src/internal/Schema.test.ts +13 -0
- package/src/internal/Schema.ts +41 -24
- package/src/internal/Store.test.ts +25 -0
- package/src/internal/Store.ts +46 -0
- package/src/internal/Tidx.local.test.ts +78 -3
- package/src/internal/Tidx.test.ts +212 -18
- package/src/internal/Tidx.ts +112 -32
- package/src/internal/VerifiedTokens.test.ts +15 -0
- package/src/internal/Viem.test.ts +170 -17
- package/src/internal/Viem.ts +111 -28
- package/src/internal/WebhookDestination.ts +25 -23
- package/src/internal/Webhooks.test.ts +59 -0
- package/src/internal/Webhooks.ts +34 -10
- package/src/internal/exchange/Provider.test.ts +216 -0
- package/src/internal/exchange/Provider.ts +326 -0
- package/src/internal/exchange/index.test.ts +6 -0
- package/src/internal/exchange/index.ts +1 -0
- package/src/internal/exchange/providers/uniswap.test.ts +122 -0
- package/src/internal/exchange/providers/uniswap.ts +682 -0
- package/src/internal/funding/Action.test.ts +138 -0
- package/src/internal/funding/Action.ts +117 -0
- package/src/internal/funding/Catalog.test.ts +311 -0
- package/src/internal/funding/Catalog.ts +347 -0
- package/src/internal/funding/Chain.test.ts +79 -0
- package/src/internal/funding/Chain.ts +120 -0
- package/src/internal/funding/Deposit.test.ts +26 -0
- package/src/internal/funding/Deposit.ts +453 -0
- package/src/internal/funding/DepositAddress.test.ts +18 -0
- package/src/internal/funding/DepositAddress.ts +312 -0
- package/src/internal/funding/Evidence.test.ts +297 -0
- package/src/internal/funding/Evidence.ts +430 -0
- package/src/internal/funding/Provider.test.ts +1328 -0
- package/src/internal/funding/Provider.ts +1796 -0
- package/src/internal/funding/Reconciliation.local.test.ts +504 -0
- package/src/internal/funding/Reconciliation.test.ts +2020 -0
- package/src/internal/funding/Reconciliation.ts +930 -0
- package/src/internal/funding/Route.test.ts +66 -0
- package/src/internal/funding/Route.ts +29 -0
- package/src/internal/funding/Subsidy.local.test.ts +152 -0
- package/src/internal/funding/Subsidy.test.ts +75 -0
- package/src/internal/funding/Subsidy.ts +260 -0
- package/src/internal/funding/Token.test.ts +47 -0
- package/src/internal/funding/Token.ts +59 -0
- package/src/internal/funding/Transfer.test.ts +369 -0
- package/src/internal/funding/Transfer.ts +522 -0
- package/src/internal/funding/index.test.ts +20 -0
- package/src/internal/funding/index.ts +12 -0
- package/src/internal/funding/providers/across.ts +149 -0
- package/src/{apps/data/FundingQuoteProviders.test.ts → internal/funding/providers/index.test.ts} +178 -157
- package/src/internal/funding/providers/relay.test.ts +474 -0
- package/src/internal/funding/providers/relay.ts +559 -0
- package/src/internal/funding/providers/rhino.ts +139 -0
- package/src/internal/funding/providers/squid.ts +151 -0
- package/src/internal/funding/providers/symbiosis.ts +221 -0
- package/src/internal/index.test.ts +5 -1
- package/src/internal/index.ts +5 -1
- package/src/internal/webhookDestinations/url.ts +49 -45
- package/src/providers/index.test.ts +14 -0
- package/src/providers/index.ts +54 -0
- package/dist/apps/data/FundingQuoteProviders.d.ts +0 -174
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +0 -1
- package/dist/apps/data/FundingQuoteProviders.js +0 -775
- package/dist/apps/data/FundingQuoteProviders.js.map +0 -1
- package/dist/internal/FundingQuotes.d.ts +0 -864
- package/dist/internal/FundingQuotes.d.ts.map +0 -1
- package/dist/internal/FundingQuotes.js +0 -672
- package/dist/internal/FundingQuotes.js.map +0 -1
- package/src/apps/data/FundingQuoteProviders.ts +0 -1043
- package/src/internal/FundingQuotes.test.ts +0 -456
- package/src/internal/FundingQuotes.ts +0 -944
|
@@ -0,0 +1,37 @@
|
|
|
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_transactions` table. */
|
|
7
|
+
export type Table = db_Schema.FundingTransferTransaction
|
|
8
|
+
/** One verified transaction reference on a transfer. */
|
|
9
|
+
export type Record = Selectable<Table>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Inserts a transaction reference, lowercasing EVM hashes while preserving
|
|
13
|
+
* other references. Repeats return `undefined`; conflicting source ownership throws.
|
|
14
|
+
*/
|
|
15
|
+
export function insert(db: Db.Db, record: Record): Promise<Record | undefined> {
|
|
16
|
+
return db.kysely
|
|
17
|
+
.insertInto('funding_transfer_transactions')
|
|
18
|
+
.values({
|
|
19
|
+
...record,
|
|
20
|
+
transactionRef: record.chainId.startsWith('eip155:')
|
|
21
|
+
? record.transactionRef.toLowerCase()
|
|
22
|
+
: record.transactionRef,
|
|
23
|
+
})
|
|
24
|
+
.onConflict((oc) => oc.columns(['transferId', 'role', 'transactionRef']).doNothing())
|
|
25
|
+
.returningAll()
|
|
26
|
+
.executeTakeFirst()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Lists a transfer's transaction references, oldest first. */
|
|
30
|
+
export function listByTransfer(db: Db.Db, transferId: string): Promise<Record[]> {
|
|
31
|
+
return db.kysely
|
|
32
|
+
.selectFrom('funding_transfer_transactions')
|
|
33
|
+
.selectAll()
|
|
34
|
+
.where('transferId', '=', transferId)
|
|
35
|
+
.orderBy('createdAt', 'asc')
|
|
36
|
+
.execute()
|
|
37
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as Transfer from '../../internal/funding/Transfer.js'
|
|
2
|
+
import * as TestApp from '../../../test/App.js'
|
|
3
|
+
import * as TestFunding from '../../../test/Funding.js'
|
|
4
|
+
import * as FundingTransfers from './fundingTransfers.js'
|
|
5
|
+
|
|
6
|
+
const db = TestApp.database()
|
|
7
|
+
|
|
8
|
+
const owner = { environment: 'production', orgId: 'org_list' } as const
|
|
9
|
+
|
|
10
|
+
let counter = 0
|
|
11
|
+
function seed(input: Partial<Transfer.create.Input> = {}) {
|
|
12
|
+
// Distinct create times keep ids strictly ordered for paging assertions.
|
|
13
|
+
return Transfer.create(db, {
|
|
14
|
+
apiKeyId: 'key_test',
|
|
15
|
+
environment: 'production',
|
|
16
|
+
id: Transfer.generateId(new Date(Date.UTC(2026, 0, 1, 0, 0, counter++))),
|
|
17
|
+
orgId: owner.orgId,
|
|
18
|
+
snapshot: TestFunding.transferSnapshot(),
|
|
19
|
+
...input,
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('list', () => {
|
|
24
|
+
test('pages newest-first by id with owner isolation', async () => {
|
|
25
|
+
const first = await seed()
|
|
26
|
+
const second = await seed({ projectId: 'prj_a' })
|
|
27
|
+
const third = await seed()
|
|
28
|
+
await seed({ orgId: 'org_other' })
|
|
29
|
+
await seed({ environment: 'sandbox' })
|
|
30
|
+
|
|
31
|
+
const page = await FundingTransfers.list(db, owner, { limit: 3 })
|
|
32
|
+
expect(page.map((row) => row.id)).toEqual([third.id, second.id, first.id])
|
|
33
|
+
|
|
34
|
+
const rest = await FundingTransfers.list(db, owner, { cursor: third.id, limit: 3 })
|
|
35
|
+
expect(rest.map((row) => row.id)).toEqual([second.id, first.id])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('narrows project-attributed owners to their project', async () => {
|
|
39
|
+
const rows = await FundingTransfers.list(db, { ...owner, projectId: 'prj_a' }, { limit: 10 })
|
|
40
|
+
expect(rows.every((row) => row.projectId === 'prj_a')).toBe(true)
|
|
41
|
+
expect(rows.length).toBeGreaterThan(0)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('filters by status', async () => {
|
|
45
|
+
const record = await seed()
|
|
46
|
+
await Transfer.transition(db, { expectedVersion: 1, id: record.id, status: 'expired' })
|
|
47
|
+
const rows = await FundingTransfers.list(db, owner, { limit: 10, status: 'expired' })
|
|
48
|
+
expect(rows.map((row) => row.id)).toEqual([record.id])
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('count', () => {
|
|
53
|
+
test('shares the list filter and stops at the cap', async () => {
|
|
54
|
+
const total = await FundingTransfers.count(db, owner, { cap: 100 })
|
|
55
|
+
expect(total).toBeGreaterThanOrEqual(3)
|
|
56
|
+
expect(await FundingTransfers.count(db, owner, { cap: 2 })).toBe(3)
|
|
57
|
+
expect(await FundingTransfers.count(db, { ...owner, orgId: 'org_none' }, { cap: 100 })).toBe(0)
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe('getOwned', () => {
|
|
62
|
+
test('returns owned rows and hides foreign ones', async () => {
|
|
63
|
+
const record = await seed()
|
|
64
|
+
expect((await FundingTransfers.getOwned(db, owner, record.id))?.id).toBe(record.id)
|
|
65
|
+
expect(
|
|
66
|
+
await FundingTransfers.getOwned(db, { ...owner, orgId: 'org_other' }, record.id),
|
|
67
|
+
).toBeUndefined()
|
|
68
|
+
expect(
|
|
69
|
+
await FundingTransfers.getOwned(db, { ...owner, projectId: 'prj_a' }, record.id),
|
|
70
|
+
).toBeUndefined()
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
describe('update', () => {
|
|
75
|
+
test('applies only against the expected version', async () => {
|
|
76
|
+
const record = await seed()
|
|
77
|
+
const options = {
|
|
78
|
+
expectedVersion: 1,
|
|
79
|
+
id: record.id,
|
|
80
|
+
snapshot: record.snapshot,
|
|
81
|
+
status: 'processing',
|
|
82
|
+
statusReason: null,
|
|
83
|
+
updatedAt: '2026-01-01T00:10:00.000Z',
|
|
84
|
+
version: 2,
|
|
85
|
+
} as const
|
|
86
|
+
expect((await FundingTransfers.update(db, options))?.version).toBe(2)
|
|
87
|
+
expect(await FundingTransfers.update(db, options)).toBeUndefined()
|
|
88
|
+
})
|
|
89
|
+
})
|
|
@@ -0,0 +1,153 @@
|
|
|
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_transfers` table. */
|
|
7
|
+
export type Table = db_Schema.FundingTransfer
|
|
8
|
+
/** A stored funding transfer. */
|
|
9
|
+
export type Record = Selectable<Table>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Ownership filter derived from the API-key principal, never from the
|
|
13
|
+
* request. A `projectId` narrows reads to that project; organization-attributed
|
|
14
|
+
* keys omit it and see every project in their organization and environment.
|
|
15
|
+
*/
|
|
16
|
+
export type Owner = {
|
|
17
|
+
/** Key environment. */
|
|
18
|
+
environment: Record['environment']
|
|
19
|
+
/** Owning organization id (`org_…`). */
|
|
20
|
+
orgId: string
|
|
21
|
+
/** Attributed project id, for project-attributed keys. */
|
|
22
|
+
projectId?: string | undefined
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Inserts a transfer row. Callers commit the matching event in the same transaction. */
|
|
26
|
+
export function insert(db: Db.Db, record: Record): Promise<Record> {
|
|
27
|
+
return db.kysely
|
|
28
|
+
.insertInto('funding_transfers')
|
|
29
|
+
.values(record)
|
|
30
|
+
.returningAll()
|
|
31
|
+
.executeTakeFirstOrThrow()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Gets a transfer by id without ownership scoping (domain and reconciler use). */
|
|
35
|
+
export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
36
|
+
return db.kysely
|
|
37
|
+
.selectFrom('funding_transfers')
|
|
38
|
+
.selectAll()
|
|
39
|
+
.where('id', '=', id)
|
|
40
|
+
.executeTakeFirst()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Gets an owner-visible transfer by id; `undefined` for absent or foreign rows. */
|
|
44
|
+
export function getOwned(db: Db.Db, owner: Owner, id: string): Promise<Record | undefined> {
|
|
45
|
+
let query = db.kysely
|
|
46
|
+
.selectFrom('funding_transfers')
|
|
47
|
+
.selectAll()
|
|
48
|
+
.where('id', '=', id)
|
|
49
|
+
.where('orgId', '=', owner.orgId)
|
|
50
|
+
.where('environment', '=', owner.environment)
|
|
51
|
+
if (owner.projectId !== undefined) query = query.where('projectId', '=', owner.projectId)
|
|
52
|
+
return query.executeTakeFirst()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Lists an owner's transfers newest-first. Ids embed a timestamp, so lexical
|
|
57
|
+
* key order is chronological and the cursor is the last returned id.
|
|
58
|
+
*/
|
|
59
|
+
export function list(db: Db.Db, owner: Owner, options: list.Options): Promise<Record[]> {
|
|
60
|
+
let query = db.kysely
|
|
61
|
+
.selectFrom('funding_transfers')
|
|
62
|
+
.selectAll()
|
|
63
|
+
.where('orgId', '=', owner.orgId)
|
|
64
|
+
.where('environment', '=', owner.environment)
|
|
65
|
+
if (owner.projectId !== undefined) query = query.where('projectId', '=', owner.projectId)
|
|
66
|
+
if (options.status !== undefined) query = query.where('status', '=', options.status)
|
|
67
|
+
if (options.cursor !== undefined) query = query.where('id', '<', options.cursor)
|
|
68
|
+
return query.orderBy('id', 'desc').limit(options.limit).execute()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export declare namespace list {
|
|
72
|
+
/** Paging and filter options. */
|
|
73
|
+
type Options = {
|
|
74
|
+
/** Exclusive lower bound: the last id of the previous page. */
|
|
75
|
+
cursor?: string | undefined
|
|
76
|
+
/** Maximum rows to return (fetch one extra to detect a further page). */
|
|
77
|
+
limit: number
|
|
78
|
+
/** Restricts to one lifecycle status. */
|
|
79
|
+
status?: Record['status'] | undefined
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Counts an owner's transfers through a capped subquery sharing the list
|
|
85
|
+
* filter, so the count cannot scan unboundedly. A result above `cap` means
|
|
86
|
+
* the true count was truncated.
|
|
87
|
+
*/
|
|
88
|
+
export async function count(db: Db.Db, owner: Owner, options: count.Options): Promise<number> {
|
|
89
|
+
const row = await db.kysely
|
|
90
|
+
.selectFrom((eb) => {
|
|
91
|
+
let query = eb
|
|
92
|
+
.selectFrom('funding_transfers')
|
|
93
|
+
.select('id')
|
|
94
|
+
.where('orgId', '=', owner.orgId)
|
|
95
|
+
.where('environment', '=', owner.environment)
|
|
96
|
+
if (owner.projectId !== undefined) query = query.where('projectId', '=', owner.projectId)
|
|
97
|
+
if (options.status !== undefined) query = query.where('status', '=', options.status)
|
|
98
|
+
return query.limit(options.cap + 1).as('page')
|
|
99
|
+
})
|
|
100
|
+
.select(({ fn }) => fn.countAll<string>().as('count'))
|
|
101
|
+
.executeTakeFirstOrThrow()
|
|
102
|
+
return Number(row.count)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export declare namespace count {
|
|
106
|
+
/** Count options sharing the list filter. */
|
|
107
|
+
type Options = {
|
|
108
|
+
/** Row ceiling; a result above it signals a truncated count. */
|
|
109
|
+
cap: number
|
|
110
|
+
/** Restricts to one lifecycle status. */
|
|
111
|
+
status?: Record['status'] | undefined
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Applies a version-guarded update; `undefined` when the row moved past
|
|
117
|
+
* `expectedVersion` (or vanished) so the caller retries against fresh state.
|
|
118
|
+
*/
|
|
119
|
+
export function update(db: Db.Db, options: update.Options): Promise<Record | undefined> {
|
|
120
|
+
return db.kysely
|
|
121
|
+
.updateTable('funding_transfers')
|
|
122
|
+
.set({
|
|
123
|
+
snapshot: options.snapshot,
|
|
124
|
+
status: options.status,
|
|
125
|
+
statusReason: options.statusReason,
|
|
126
|
+
updatedAt: options.updatedAt,
|
|
127
|
+
version: options.version,
|
|
128
|
+
})
|
|
129
|
+
.where('id', '=', options.id)
|
|
130
|
+
.where('version', '=', options.expectedVersion)
|
|
131
|
+
.returningAll()
|
|
132
|
+
.executeTakeFirst()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export declare namespace update {
|
|
136
|
+
/** Guarded update fields. */
|
|
137
|
+
type Options = {
|
|
138
|
+
/** The version the update was computed against. */
|
|
139
|
+
expectedVersion: number
|
|
140
|
+
/** Transfer id (`ftr_…`). */
|
|
141
|
+
id: string
|
|
142
|
+
/** Replacement public snapshot. */
|
|
143
|
+
snapshot: Record['snapshot']
|
|
144
|
+
/** New lifecycle status. */
|
|
145
|
+
status: Record['status']
|
|
146
|
+
/** Customer-safe reason, or null to clear. */
|
|
147
|
+
statusReason: Record['statusReason']
|
|
148
|
+
/** Mutation timestamp (ISO 8601). */
|
|
149
|
+
updatedAt: string
|
|
150
|
+
/** The incremented version. */
|
|
151
|
+
version: number
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -2,6 +2,7 @@ import { nanoid } from 'nanoid'
|
|
|
2
2
|
|
|
3
3
|
import * as Runtime from '../../../test/runtime.js'
|
|
4
4
|
import * as Webhooks from '../../internal/Webhooks.js'
|
|
5
|
+
import * as Viem from '../../internal/Viem.js'
|
|
5
6
|
import * as Db from '../Db.js'
|
|
6
7
|
import * as EnabledBillingSources from './enabledBillingSources.js'
|
|
7
8
|
import * as Memberships from './memberships.js'
|
|
@@ -216,6 +217,7 @@ describe('deleteOrganization', () => {
|
|
|
216
217
|
transactionHash: `0x${'aa'.repeat(32)}`,
|
|
217
218
|
})
|
|
218
219
|
|
|
220
|
+
expect(await Organizations.hasUnreportedSponsorships(db, 'org_1')).toBe(true)
|
|
219
221
|
await expect(Organizations.deleteOrganization(db, 'org_1')).rejects.toThrow(
|
|
220
222
|
Organizations.UnreportedSponsorshipsError,
|
|
221
223
|
)
|
|
@@ -227,6 +229,92 @@ describe('deleteOrganization', () => {
|
|
|
227
229
|
await db.close()
|
|
228
230
|
})
|
|
229
231
|
|
|
232
|
+
test('behavior: deletes an org with only failed or non-mainnet sponsorships', async () => {
|
|
233
|
+
const db = create()
|
|
234
|
+
await db.migrate()
|
|
235
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
236
|
+
const failed = await SponsoredTransactions.upsert(db, {
|
|
237
|
+
apiKeyId: 'key_1',
|
|
238
|
+
billable: true,
|
|
239
|
+
chainId: Viem.chainId.mainnet,
|
|
240
|
+
environment: 'production',
|
|
241
|
+
orgId: 'org_1',
|
|
242
|
+
projectId: 'prj_1',
|
|
243
|
+
signPayload: `0x${'bb'.repeat(32)}`,
|
|
244
|
+
transaction: `0x76${'cc'.repeat(16)}`,
|
|
245
|
+
transactionHash: `0x${'aa'.repeat(32)}`,
|
|
246
|
+
})
|
|
247
|
+
await SponsoredTransactions.fail(db, failed.id, '2026-01-01T00:00:00.000Z')
|
|
248
|
+
const testnet = await SponsoredTransactions.upsert(db, {
|
|
249
|
+
apiKeyId: 'key_1',
|
|
250
|
+
billable: true,
|
|
251
|
+
chainId: Viem.chainId.testnet,
|
|
252
|
+
environment: 'production',
|
|
253
|
+
orgId: 'org_1',
|
|
254
|
+
projectId: 'prj_1',
|
|
255
|
+
signPayload: `0x${'dd'.repeat(32)}`,
|
|
256
|
+
transaction: `0x76${'ee'.repeat(16)}`,
|
|
257
|
+
transactionHash: `0x${'ff'.repeat(32)}`,
|
|
258
|
+
})
|
|
259
|
+
await SponsoredTransactions.finalize(db, testnet.id, {
|
|
260
|
+
feeAmount: '100',
|
|
261
|
+
finalizedAt: '2026-01-01T00:00:00.000Z',
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
expect(await Organizations.hasUnreportedSponsorships(db, 'org_1')).toBe(false)
|
|
265
|
+
expect(await Organizations.deleteOrganization(db, 'org_1')).toBe(true)
|
|
266
|
+
await db.close()
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
test('behavior: preserves an org with a recoverable failed fill intent', async () => {
|
|
270
|
+
const db = create()
|
|
271
|
+
await db.migrate()
|
|
272
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
273
|
+
const failed = await SponsoredTransactions.upsert(db, {
|
|
274
|
+
apiKeyId: 'key_1',
|
|
275
|
+
billable: true,
|
|
276
|
+
chainId: Viem.chainId.mainnet,
|
|
277
|
+
environment: 'production',
|
|
278
|
+
orgId: 'org_1',
|
|
279
|
+
projectId: 'prj_1',
|
|
280
|
+
signPayload: `0x${'bb'.repeat(32)}`,
|
|
281
|
+
transaction: `0x76${'cc'.repeat(16)}`,
|
|
282
|
+
})
|
|
283
|
+
await SponsoredTransactions.fail(db, failed.id, new Date().toISOString())
|
|
284
|
+
|
|
285
|
+
expect(await Organizations.hasUnreportedSponsorships(db, 'org_1')).toBe(true)
|
|
286
|
+
await expect(Organizations.deleteOrganization(db, 'org_1')).rejects.toThrow(
|
|
287
|
+
Organizations.UnreportedSponsorshipsError,
|
|
288
|
+
)
|
|
289
|
+
expect(await Organizations.get(db, 'org_1')).toBeDefined()
|
|
290
|
+
await db.close()
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('behavior: deletes an org with only expired failed fill intents', async () => {
|
|
294
|
+
const db = create()
|
|
295
|
+
await db.migrate()
|
|
296
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
297
|
+
const failed = await SponsoredTransactions.upsert(db, {
|
|
298
|
+
apiKeyId: 'key_1',
|
|
299
|
+
billable: true,
|
|
300
|
+
chainId: Viem.chainId.mainnet,
|
|
301
|
+
environment: 'production',
|
|
302
|
+
orgId: 'org_1',
|
|
303
|
+
projectId: 'prj_1',
|
|
304
|
+
signPayload: `0x${'bb'.repeat(32)}`,
|
|
305
|
+
transaction: `0x76${'cc'.repeat(16)}`,
|
|
306
|
+
})
|
|
307
|
+
await SponsoredTransactions.fail(
|
|
308
|
+
db,
|
|
309
|
+
failed.id,
|
|
310
|
+
new Date(Date.now() - SponsoredTransactions.failedIntentRecoveryTtlMs - 1).toISOString(),
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
expect(await Organizations.hasUnreportedSponsorships(db, 'org_1')).toBe(false)
|
|
314
|
+
expect(await Organizations.deleteOrganization(db, 'org_1')).toBe(true)
|
|
315
|
+
await db.close()
|
|
316
|
+
})
|
|
317
|
+
|
|
230
318
|
test('behavior: deletes enabled billing sources', async () => {
|
|
231
319
|
const db = create()
|
|
232
320
|
await db.migrate()
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { sql, type Selectable } from 'kysely'
|
|
1
|
+
import { sql, type ExpressionBuilder, type Selectable } from 'kysely'
|
|
2
2
|
|
|
3
3
|
import * as Id from '../../internal/Id.js'
|
|
4
|
+
import * as Viem from '../../internal/Viem.js'
|
|
5
|
+
import * as SponsoredTransactions from './sponsoredTransactions.js'
|
|
4
6
|
import type * as Db from '../Db.js'
|
|
5
7
|
import type * as db_Schema from '../Schema.js'
|
|
6
8
|
import type * as EnabledBillingSources from './enabledBillingSources.js'
|
|
@@ -120,12 +122,17 @@ export declare namespace createOwned {
|
|
|
120
122
|
*/
|
|
121
123
|
export function deleteOrganization(db: Db.Db, id: string): Promise<boolean> {
|
|
122
124
|
return db.kysely.transaction().execute(async (trx) => {
|
|
125
|
+
const failedSince = new Date(
|
|
126
|
+
Date.now() - SponsoredTransactions.failedIntentRecoveryTtlMs,
|
|
127
|
+
).toISOString()
|
|
123
128
|
const unreported = await trx
|
|
124
129
|
.selectFrom('sponsored_transactions')
|
|
125
130
|
.select('id')
|
|
126
131
|
.where('orgId', '=', id)
|
|
127
132
|
.where('billable', '=', true)
|
|
133
|
+
.where('chainId', '=', Viem.chainId.mainnet)
|
|
128
134
|
.where('meterReportedAt', 'is', null)
|
|
135
|
+
.where(unreportedSponsorshipStatus(failedSince))
|
|
129
136
|
.limit(1)
|
|
130
137
|
.executeTakeFirst()
|
|
131
138
|
if (unreported) throw new UnreportedSponsorshipsError()
|
|
@@ -152,12 +159,17 @@ export function deleteOrganization(db: Db.Db, id: string): Promise<boolean> {
|
|
|
152
159
|
|
|
153
160
|
/** Whether an organization has billable sponsorships awaiting settlement. */
|
|
154
161
|
export async function hasUnreportedSponsorships(db: Db.Db, id: string): Promise<boolean> {
|
|
162
|
+
const failedSince = new Date(
|
|
163
|
+
Date.now() - SponsoredTransactions.failedIntentRecoveryTtlMs,
|
|
164
|
+
).toISOString()
|
|
155
165
|
const record = await db.kysely
|
|
156
166
|
.selectFrom('sponsored_transactions')
|
|
157
167
|
.select('id')
|
|
158
168
|
.where('orgId', '=', id)
|
|
159
169
|
.where('billable', '=', true)
|
|
170
|
+
.where('chainId', '=', Viem.chainId.mainnet)
|
|
160
171
|
.where('meterReportedAt', 'is', null)
|
|
172
|
+
.where(unreportedSponsorshipStatus(failedSince))
|
|
161
173
|
.limit(1)
|
|
162
174
|
.executeTakeFirst()
|
|
163
175
|
return record !== undefined
|
|
@@ -174,6 +186,22 @@ export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
|
174
186
|
return db.kysely.selectFrom('organizations').selectAll().where('id', '=', id).executeTakeFirst()
|
|
175
187
|
}
|
|
176
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Reads organizations by id for operational attribution displays.
|
|
191
|
+
*
|
|
192
|
+
* @param db - The database.
|
|
193
|
+
* @param ids - Organization ids to read.
|
|
194
|
+
* @returns Matching organization records.
|
|
195
|
+
*/
|
|
196
|
+
export function listByIds(db: Db.Db, ids: readonly string[]): Promise<Record[]> {
|
|
197
|
+
if (ids.length === 0) return Promise.resolve([])
|
|
198
|
+
return db.kysely
|
|
199
|
+
.selectFrom('organizations')
|
|
200
|
+
.selectAll()
|
|
201
|
+
.where('id', 'in', [...ids])
|
|
202
|
+
.execute()
|
|
203
|
+
}
|
|
204
|
+
|
|
177
205
|
/**
|
|
178
206
|
* Reads an organization with current member and project counts.
|
|
179
207
|
*
|
|
@@ -429,6 +457,19 @@ export declare namespace upsert {
|
|
|
429
457
|
}
|
|
430
458
|
}
|
|
431
459
|
|
|
460
|
+
/** Blocks rows that can still settle or recover into billable mainnet spend. */
|
|
461
|
+
function unreportedSponsorshipStatus(failedSince: string) {
|
|
462
|
+
return (eb: ExpressionBuilder<Db.Database, 'sponsored_transactions'>) =>
|
|
463
|
+
eb.or([
|
|
464
|
+
eb('status', '!=', 'failed'),
|
|
465
|
+
eb.and([
|
|
466
|
+
eb('status', '=', 'failed'),
|
|
467
|
+
eb('transactionHash', 'is', null),
|
|
468
|
+
eb('finalizedAt', '>=', failedSince),
|
|
469
|
+
]),
|
|
470
|
+
])
|
|
471
|
+
}
|
|
472
|
+
|
|
432
473
|
/** Organization deletion is blocked until billable sponsorships settle. */
|
|
433
474
|
export class UnreportedSponsorshipsError extends Error {
|
|
434
475
|
override name = 'Organizations.UnreportedSponsorshipsError'
|
|
@@ -65,6 +65,22 @@ export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
|
65
65
|
return db.kysely.selectFrom('projects').selectAll().where('id', '=', id).executeTakeFirst()
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Reads projects by id for operational attribution displays.
|
|
70
|
+
*
|
|
71
|
+
* @param db - The database.
|
|
72
|
+
* @param ids - Project ids to read.
|
|
73
|
+
* @returns Matching project records.
|
|
74
|
+
*/
|
|
75
|
+
export function listByIds(db: Db.Db, ids: readonly string[]): Promise<Record[]> {
|
|
76
|
+
if (ids.length === 0) return Promise.resolve([])
|
|
77
|
+
return db.kysely
|
|
78
|
+
.selectFrom('projects')
|
|
79
|
+
.selectAll()
|
|
80
|
+
.where('id', 'in', [...ids])
|
|
81
|
+
.execute()
|
|
82
|
+
}
|
|
83
|
+
|
|
68
84
|
/**
|
|
69
85
|
* Lists an organization's projects, newest first.
|
|
70
86
|
*
|
|
@@ -43,6 +43,12 @@ export type Bucket = db_Schema.RequestUsageBucket
|
|
|
43
43
|
/** A stored request-count meter event. */
|
|
44
44
|
export type MeterEvent = db_Schema.RequestUsageMeterEvent
|
|
45
45
|
|
|
46
|
+
/** Aggregate state for pending meter events in one billing environment. */
|
|
47
|
+
export type PendingStatus = {
|
|
48
|
+
count: number
|
|
49
|
+
oldestAttemptedAt: string | undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
46
52
|
/** Identifies one hourly bucket for an org in an environment. */
|
|
47
53
|
export type BucketKey = {
|
|
48
54
|
/** UTC hour start (ISO 8601). */
|
|
@@ -91,6 +97,23 @@ export async function listPending(db: Db.Db, environment: Environment): Promise<
|
|
|
91
97
|
return rows.map(toMeterEvent)
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Reads the number and age anchor of meter events still awaiting Stripe.
|
|
102
|
+
*
|
|
103
|
+
* @param db - The database.
|
|
104
|
+
* @param environment - The billing environment to inspect.
|
|
105
|
+
* @returns The pending-event count and oldest first attempt.
|
|
106
|
+
*/
|
|
107
|
+
export async function getPendingStatus(db: Db.Db, environment: Environment): Promise<PendingStatus> {
|
|
108
|
+
const row = await db.kysely
|
|
109
|
+
.selectFrom('request_usage_meter_events')
|
|
110
|
+
.select((eb) => [eb.fn.countAll().as('count'), eb.fn.min('firstAttemptedAt').as('oldest')])
|
|
111
|
+
.where('environment', '=', environment)
|
|
112
|
+
.where('state', '=', 'pending')
|
|
113
|
+
.executeTakeFirstOrThrow()
|
|
114
|
+
return { count: Number(row.count), oldestAttemptedAt: row.oldest ?? undefined }
|
|
115
|
+
}
|
|
116
|
+
|
|
94
117
|
/**
|
|
95
118
|
* Inserts a frozen `pending` meter event, claiming a delta. Idempotent on the
|
|
96
119
|
* deterministic `identifier`: a re-seal after a crash resolves to the existing
|
|
@@ -2,6 +2,7 @@ import { nanoid } from 'nanoid'
|
|
|
2
2
|
|
|
3
3
|
import * as Runtime from '../../../test/runtime.js'
|
|
4
4
|
import * as Db from '../Db.js'
|
|
5
|
+
import * as Organizations from './organizations.js'
|
|
5
6
|
import * as SponsoredTransactions from './sponsoredTransactions.js'
|
|
6
7
|
|
|
7
8
|
const create = () => Db.postgres({ connectionString: Runtime.postgresUrl, schema: `t_${nanoid()}` })
|
|
@@ -61,6 +62,17 @@ describe('upsert', () => {
|
|
|
61
62
|
await db.close()
|
|
62
63
|
})
|
|
63
64
|
|
|
65
|
+
test('behavior: records organization-level sponsorship without a project', async () => {
|
|
66
|
+
const db = create()
|
|
67
|
+
await db.migrate()
|
|
68
|
+
const { projectId: _, ...organization } = input
|
|
69
|
+
const record = await SponsoredTransactions.upsert(db, organization)
|
|
70
|
+
|
|
71
|
+
expect(record.orgId).toMatchInlineSnapshot(`"org_1"`)
|
|
72
|
+
expect(record.projectId).toBeNull()
|
|
73
|
+
await db.close()
|
|
74
|
+
})
|
|
75
|
+
|
|
64
76
|
test('behavior: preserves an explicit fee token', async () => {
|
|
65
77
|
const db = create()
|
|
66
78
|
await db.migrate()
|
|
@@ -160,7 +172,8 @@ describe('listPending', () => {
|
|
|
160
172
|
|
|
161
173
|
const pending = await SponsoredTransactions.listPending(db)
|
|
162
174
|
// Inserts can share a millisecond, so assert membership, not order.
|
|
163
|
-
expect(pending.map((row) => row.transactionHash).sort()).
|
|
175
|
+
expect(pending.map((row) => row.transactionHash).sort((left, right) => String(left).localeCompare(String(right)))) // prettier-ignore
|
|
176
|
+
.toMatchInlineSnapshot(`
|
|
164
177
|
[
|
|
165
178
|
"0xa1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
|
|
166
179
|
"0xa3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3",
|
|
@@ -175,9 +188,10 @@ describe('assignTransactionHash', () => {
|
|
|
175
188
|
test('behavior: reopens a failed intent when reconciliation finds its hash', async () => {
|
|
176
189
|
const db = create()
|
|
177
190
|
await db.migrate()
|
|
191
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
178
192
|
const { transactionHash: _, ...intent } = input
|
|
179
193
|
const record = await SponsoredTransactions.upsert(db, intent)
|
|
180
|
-
await SponsoredTransactions.fail(db, record.id,
|
|
194
|
+
await SponsoredTransactions.fail(db, record.id, new Date().toISOString())
|
|
181
195
|
|
|
182
196
|
await SponsoredTransactions.assignTransactionHash(db, record.id, input.transactionHash)
|
|
183
197
|
|
|
@@ -190,9 +204,45 @@ describe('assignTransactionHash', () => {
|
|
|
190
204
|
await db.close()
|
|
191
205
|
})
|
|
192
206
|
|
|
207
|
+
test('behavior: does not reopen failed intents after the recovery window', async () => {
|
|
208
|
+
const db = create()
|
|
209
|
+
await db.migrate()
|
|
210
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
211
|
+
const { transactionHash: _, ...intent } = input
|
|
212
|
+
const record = await SponsoredTransactions.upsert(db, intent)
|
|
213
|
+
await SponsoredTransactions.fail(
|
|
214
|
+
db,
|
|
215
|
+
record.id,
|
|
216
|
+
new Date(Date.now() - SponsoredTransactions.failedIntentRecoveryTtlMs - 1).toISOString(),
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
await SponsoredTransactions.assignTransactionHash(db, record.id, input.transactionHash)
|
|
220
|
+
|
|
221
|
+
const assigned = await SponsoredTransactions.get(db, record.id)
|
|
222
|
+
expect(assigned?.status).toMatchInlineSnapshot(`"failed"`)
|
|
223
|
+
expect(assigned?.transactionHash).toBeNull()
|
|
224
|
+
await db.close()
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
test('behavior: does not reopen failed intents for deleted orgs', async () => {
|
|
228
|
+
const db = create()
|
|
229
|
+
await db.migrate()
|
|
230
|
+
const { transactionHash: _, ...intent } = input
|
|
231
|
+
const record = await SponsoredTransactions.upsert(db, intent)
|
|
232
|
+
await SponsoredTransactions.fail(db, record.id, new Date().toISOString())
|
|
233
|
+
|
|
234
|
+
await SponsoredTransactions.assignTransactionHash(db, record.id, input.transactionHash)
|
|
235
|
+
|
|
236
|
+
const assigned = await SponsoredTransactions.get(db, record.id)
|
|
237
|
+
expect(assigned?.status).toMatchInlineSnapshot(`"failed"`)
|
|
238
|
+
expect(assigned?.transactionHash).toBeNull()
|
|
239
|
+
await db.close()
|
|
240
|
+
})
|
|
241
|
+
|
|
193
242
|
test('behavior: keeps an over-limit failed intent retryable across a period rollover', async () => {
|
|
194
243
|
const db = create()
|
|
195
244
|
await db.migrate()
|
|
245
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
196
246
|
const { transactionHash: _, ...intent } = input
|
|
197
247
|
vi.useFakeTimers({ now: new Date('2026-01-31T23:59:00.000Z') })
|
|
198
248
|
try {
|