tapimo 0.15.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -0
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +4 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +37 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +163 -10
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +13085 -11974
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +46 -15
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +1 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +1 -1
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +896 -191
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +5 -1
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +33 -33
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +66 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +36 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +25 -25
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +5 -4
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/route-policies.d.ts +632 -0
- package/dist/admin/apps/route-policies.d.ts.map +1 -0
- package/dist/admin/apps/route-policies.js +257 -0
- package/dist/admin/apps/route-policies.js.map +1 -0
- package/dist/admin/apps/routes-support.js +39 -3
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +454 -1
- package/dist/admin/apps/routes.d.ts.map +1 -1
- package/dist/admin/apps/routes.js +82 -1
- package/dist/admin/apps/routes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +10 -4
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +24 -4
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/index.d.ts +0 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +99 -103
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +65 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +58 -59
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +2709 -2670
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +5 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +50 -0
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +248 -248
- package/dist/apps/data/routes/balances.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +5 -7
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/earn.d.ts +103 -12
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +456 -220
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +267 -97
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +1 -19
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +93 -56
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +10 -10
- package/dist/apps/data/routes/rpc.d.ts +30 -30
- package/dist/apps/data/routes/rpc.js +45 -11
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +11 -6
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +2 -0
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +30 -22
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +12 -12
- package/dist/apps/data/routes/valuation.d.ts +30 -30
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1 -1
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +18 -11
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +3 -3
- package/dist/apps/management/App.d.ts +3043 -2198
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -0
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +2 -4
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +65 -26
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +16 -4
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +70 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +84 -84
- package/dist/apps/management/routes/cli.d.ts +912 -0
- package/dist/apps/management/routes/cli.d.ts.map +1 -0
- package/dist/apps/management/routes/cli.js +416 -0
- package/dist/apps/management/routes/cli.js.map +1 -0
- package/dist/apps/management/routes/faucet.d.ts +8 -8
- package/dist/apps/management/routes/invitations.d.ts +24 -24
- package/dist/apps/management/routes/invite-links.d.ts +66 -66
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +20 -20
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +8 -2
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +76 -76
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +42 -42
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +7 -9
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +119 -119
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +16 -3
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +4 -2
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -4
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +8 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +16 -4
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -6
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +71 -60
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/routes/Access.d.ts +53 -0
- package/dist/apps/routes/Access.d.ts.map +1 -1
- package/dist/apps/routes/Access.js +121 -0
- package/dist/apps/routes/Access.js.map +1 -1
- package/dist/apps/routes/App.d.ts +397 -158
- package/dist/apps/routes/App.d.ts.map +1 -1
- package/dist/apps/routes/App.js.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.js +217 -32
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/routes/routes/quotes.d.ts +90 -0
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
- package/dist/apps/routes/routes/quotes.js +101 -27
- package/dist/apps/routes/routes/quotes.js.map +1 -1
- package/dist/apps/routes/routes/transfers.d.ts +187 -135
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
- package/dist/apps/routes/routes/transfers.js +182 -37
- package/dist/apps/routes/routes/transfers.js.map +1 -1
- package/dist/cli/ApiKeys.d.ts +120 -0
- package/dist/cli/ApiKeys.d.ts.map +1 -0
- package/dist/cli/ApiKeys.js +138 -0
- package/dist/cli/ApiKeys.js.map +1 -0
- package/dist/cli/Cli.d.ts +92 -34
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +188 -11
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/Credentials.d.ts +95 -0
- package/dist/cli/Credentials.d.ts.map +1 -0
- package/dist/cli/Credentials.js +110 -0
- package/dist/cli/Credentials.js.map +1 -0
- package/dist/cli/Spec.d.ts +59 -0
- package/dist/cli/Spec.d.ts.map +1 -0
- package/dist/cli/Spec.js +77 -0
- package/dist/cli/Spec.js.map +1 -0
- package/dist/cli/bin.js +5 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -5
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/auth.d.ts +73 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +204 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/keys.d.ts +17 -0
- package/dist/cli/commands/keys.d.ts.map +1 -0
- package/dist/cli/commands/keys.js +109 -0
- package/dist/cli/commands/keys.js.map +1 -0
- package/dist/cloudflare.d.ts +27 -2
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +144 -17
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +23 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +418 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +44 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.js +65 -9
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
- package/dist/db/tables/authAccounts.d.ts.map +1 -1
- package/dist/db/tables/authAccounts.js +1 -0
- package/dist/db/tables/authAccounts.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +12 -1
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +4 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +8 -34
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +5 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +10 -2
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +4 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.js +2 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
- package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
- package/dist/db/tables/routesDepositAddresses.js +84 -31
- package/dist/db/tables/routesDepositAddresses.js.map +1 -1
- package/dist/db/tables/routesDeposits.d.ts.map +1 -1
- package/dist/db/tables/routesDeposits.js +31 -21
- package/dist/db/tables/routesDeposits.js.map +1 -1
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
- package/dist/db/tables/routesIdempotency.js +2 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -1
- package/dist/db/tables/routesPolicies.d.ts +58 -0
- package/dist/db/tables/routesPolicies.d.ts.map +1 -0
- package/dist/db/tables/routesPolicies.js +198 -0
- package/dist/db/tables/routesPolicies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidies.js +41 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
- package/dist/db/tables/routesTransfers.d.ts +26 -1
- package/dist/db/tables/routesTransfers.d.ts.map +1 -1
- package/dist/db/tables/routesTransfers.js +36 -6
- package/dist/db/tables/routesTransfers.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +144 -33
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +2 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +11 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +21 -4
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.js +65 -44
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +1 -1
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +3 -2
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/relay.d.ts +2 -0
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +34 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +73 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +212 -85
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +22 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -1
- package/dist/internal/BetterAuth.js +17 -14
- package/dist/internal/BetterAuth.js.map +1 -1
- package/dist/internal/Cache.d.ts +5 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +3 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/CliAuth.d.ts +243 -0
- package/dist/internal/CliAuth.d.ts.map +1 -0
- package/dist/internal/CliAuth.js +249 -0
- package/dist/internal/CliAuth.js.map +1 -0
- package/dist/internal/EarnSharePrices.d.ts +1 -1
- package/dist/internal/EarnSharePrices.d.ts.map +1 -1
- package/dist/internal/EarnSharePrices.js +7 -3
- package/dist/internal/EarnSharePrices.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +47 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +188 -4
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/EarnWithdrawals.d.ts +73 -0
- package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
- package/dist/internal/EarnWithdrawals.js +189 -0
- package/dist/internal/EarnWithdrawals.js.map +1 -0
- package/dist/internal/ExecutionContext.d.ts +21 -0
- package/dist/internal/ExecutionContext.d.ts.map +1 -0
- package/dist/internal/ExecutionContext.js +16 -0
- package/dist/internal/ExecutionContext.js.map +1 -0
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +163 -130
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +26 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +67 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +174 -27
- package/dist/internal/RateLimit.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 +4 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Timing.d.ts +6 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +21 -1
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/Tron.d.ts +124 -0
- package/dist/internal/Tron.d.ts.map +1 -0
- package/dist/internal/Tron.js +202 -0
- package/dist/internal/Tron.js.map +1 -0
- package/dist/internal/Viem.d.ts +4 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +25 -6
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/rewards/Read.d.ts +2 -2
- package/dist/internal/rewards/Read.d.ts.map +1 -1
- package/dist/internal/rewards/Read.js +11 -2
- package/dist/internal/rewards/Read.js.map +1 -1
- package/dist/internal/routes/Action.d.ts +27 -0
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +49 -1
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Chain.d.ts +2 -0
- package/dist/internal/routes/Chain.d.ts.map +1 -1
- package/dist/internal/routes/Chain.js +4 -0
- package/dist/internal/routes/Chain.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +5 -0
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Evidence.d.ts.map +1 -1
- package/dist/internal/routes/Evidence.js +6 -2
- package/dist/internal/routes/Evidence.js.map +1 -1
- package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
- package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/EvmTransferSettlement.js +196 -0
- package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
- package/dist/internal/routes/Policy.d.ts +161 -0
- package/dist/internal/routes/Policy.d.ts.map +1 -0
- package/dist/internal/routes/Policy.js +249 -0
- package/dist/internal/routes/Policy.js.map +1 -0
- package/dist/internal/routes/Provider.d.ts +66 -3
- package/dist/internal/routes/Provider.d.ts.map +1 -1
- package/dist/internal/routes/Provider.js +106 -27
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Quota.d.ts +57 -0
- package/dist/internal/routes/Quota.d.ts.map +1 -0
- package/dist/internal/routes/Quota.js +144 -0
- package/dist/internal/routes/Quota.js.map +1 -0
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +163 -47
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
- package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/Subsidy.d.ts +2 -2
- package/dist/internal/routes/Subsidy.d.ts.map +1 -1
- package/dist/internal/routes/Subsidy.js +2 -2
- package/dist/internal/routes/Subsidy.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts +229 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +644 -7
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
- package/dist/internal/routes/TransferReconciliation.js +83 -159
- package/dist/internal/routes/TransferReconciliation.js.map +1 -1
- package/dist/internal/routes/TransferSettlement.d.ts +45 -0
- package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TransferSettlement.js +2 -0
- package/dist/internal/routes/TransferSettlement.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
- package/dist/internal/routes/TransferSubsidy.js +64 -5
- package/dist/internal/routes/TransferSubsidy.js.map +1 -1
- package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSettlement.js +201 -0
- package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.js +439 -0
- package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/index.d.ts +3 -0
- package/dist/internal/routes/index.d.ts.map +1 -1
- package/dist/internal/routes/index.js +3 -0
- package/dist/internal/routes/index.js.map +1 -1
- package/dist/internal/routes/providers/across.d.ts +3 -0
- package/dist/internal/routes/providers/across.d.ts.map +1 -1
- package/dist/internal/routes/providers/across.js +11 -0
- package/dist/internal/routes/providers/across.js.map +1 -1
- package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
- package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMesh.js +474 -0
- package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
- package/dist/internal/routes/providers/propAmm.d.ts +70 -0
- package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
- package/dist/internal/routes/providers/propAmm.js +524 -0
- package/dist/internal/routes/providers/propAmm.js.map +1 -0
- package/dist/internal/routes/providers/relay.d.ts +4 -1
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +353 -42
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/dist/internal/routes/providers/rhino.d.ts +3 -0
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
- package/dist/internal/routes/providers/rhino.js +11 -0
- package/dist/internal/routes/providers/rhino.js.map +1 -1
- package/dist/internal/routes/providers/squid.d.ts +3 -0
- package/dist/internal/routes/providers/squid.d.ts.map +1 -1
- package/dist/internal/routes/providers/squid.js +19 -0
- package/dist/internal/routes/providers/squid.js.map +1 -1
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
- package/dist/internal/routes/providers/stargate.js +22 -9
- package/dist/internal/routes/providers/stargate.js.map +1 -1
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
- package/dist/internal/routes/providers/symbiosis.js +13 -17
- package/dist/internal/routes/providers/symbiosis.js.map +1 -1
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +16 -6
- package/src/ApiKey.ts +7 -3
- package/src/ApiKeys.test.ts +652 -8
- package/src/ApiKeys.ts +191 -11
- package/src/App.test.ts +405 -18
- package/src/App.ts +51 -15
- package/src/Client.test-d.ts +157 -10
- package/src/Client.test.ts +4 -4
- package/src/Scope.ts +1 -2
- package/src/admin/App.ts +11 -5
- package/src/admin/apps/api-keys.test.ts +98 -2
- package/src/admin/apps/api-keys.ts +21 -12
- package/src/admin/apps/earn-vaults.test.ts +76 -7
- package/src/admin/apps/earn-vaults.ts +47 -8
- package/src/admin/apps/organizations.test.ts +147 -31
- package/src/admin/apps/organizations.ts +5 -4
- package/src/admin/apps/route-policies.test.ts +220 -0
- package/src/admin/apps/route-policies.ts +322 -0
- package/src/admin/apps/routes-support.test.ts +107 -2
- package/src/admin/apps/routes-support.ts +43 -3
- package/src/admin/apps/routes.test.ts +150 -0
- package/src/admin/apps/routes.ts +97 -1
- package/src/admin/apps/scopes.test.ts +1 -1
- package/src/admin/apps/verified-tokens.test.ts +32 -0
- package/src/admin/apps/verified-tokens.ts +30 -4
- package/src/admin/index.ts +0 -1
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/components/Dialog.tsx +1 -1
- package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
- package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
- package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
- package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
- package/src/admin/ui/src/lib/route-policies.ts +232 -0
- package/src/admin/ui/src/lib/routes.ts +34 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +24 -9
- package/src/admin/ui/src/routeTree.gen.ts +21 -0
- package/src/admin/ui/src/routes/__root.tsx +1 -1
- package/src/admin/ui/src/routes/api-keys.tsx +21 -2
- package/src/admin/ui/src/routes/early-access.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
- package/src/admin/ui/src/routes/organizations.tsx +35 -4
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
- package/src/admin/ui/src/routes/route-policies.tsx +678 -0
- package/src/admin/ui/src/routes/routes.tsx +85 -2
- package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
- package/src/admin/ui/src/routes/subsidies.tsx +1 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +65 -20
- package/src/admin/ui.generated.ts +99 -104
- package/src/analytics/Analytics.test.ts +4 -50
- package/src/analytics/Analytics.ts +65 -1
- package/src/analytics/tables/requestEvents.test.ts +402 -1
- package/src/analytics/tables/requestEvents.ts +62 -93
- package/src/apps/data/App.test.ts +26 -0
- package/src/apps/data/routes/activities.test.ts +315 -14
- package/src/apps/data/routes/activities.ts +60 -0
- package/src/apps/data/routes/balances.ts +5 -7
- package/src/apps/data/routes/earn.bench.ts +18 -0
- package/src/apps/data/routes/earn.local.test.ts +507 -0
- package/src/apps/data/routes/earn.test.ts +405 -127
- package/src/apps/data/routes/earn.ts +660 -270
- package/src/apps/data/routes/exchanges.bench.ts +3 -1
- package/src/apps/data/routes/exchanges.test.ts +166 -2
- package/src/apps/data/routes/exchanges.ts +308 -101
- package/src/apps/data/routes/fee-amm.test.ts +153 -2
- package/src/apps/data/routes/fee-amm.ts +132 -62
- package/src/apps/data/routes/receipts.test.ts +21 -18
- package/src/apps/data/routes/rpc.test.ts +34 -2
- package/src/apps/data/routes/rpc.ts +47 -10
- package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
- package/src/apps/data/routes/tokens.test.ts +4 -4
- package/src/apps/data/routes/tokens.ts +11 -6
- package/src/apps/data/routes/transactions.test.ts +29 -0
- package/src/apps/data/routes/transactions.ts +33 -22
- package/src/apps/data/routes/webhooks.scan.test.ts +29 -0
- package/src/apps/data/routes/webhooks.test.ts +18 -3
- package/src/apps/data/routes/webhooks.ts +27 -13
- package/src/apps/management/App.ts +4 -0
- package/src/apps/management/Billing.test.ts +253 -27
- package/src/apps/management/Billing.ts +83 -29
- package/src/apps/management/routes/api-keys.test.ts +1 -1
- package/src/apps/management/routes/api-keys.ts +85 -11
- package/src/apps/management/routes/billing.test.ts +68 -4
- package/src/apps/management/routes/cli.test.ts +370 -0
- package/src/apps/management/routes/cli.ts +533 -0
- package/src/apps/management/routes/me.test.ts +14 -4
- package/src/apps/management/routes/orgs.test.ts +108 -4
- package/src/apps/management/routes/orgs.ts +7 -2
- package/src/apps/management/routes/usage.test.ts +2 -2
- package/src/apps/management/routes/verified-token-requests.test.ts +16 -2
- package/src/apps/management/routes/verified-token-requests.ts +7 -10
- package/src/apps/mcp.test.ts +108 -25
- package/src/apps/mcp.ts +15 -3
- package/src/apps/mpp/internal/Policy.test.ts +51 -4
- package/src/apps/mpp/internal/Policy.ts +6 -2
- package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
- package/src/apps/mpp/internal/Sponsorship.ts +6 -4
- package/src/apps/relay/App.test.ts +85 -1
- package/src/apps/relay/App.ts +28 -4
- package/src/apps/relay/Sponsorships.test.ts +97 -1
- package/src/apps/relay/Sponsorships.ts +77 -66
- package/src/apps/routes/Access.test.ts +319 -0
- package/src/apps/routes/Access.ts +147 -0
- package/src/apps/routes/App.ts +10 -0
- package/src/apps/routes/routes/chains.test.ts +3 -2
- package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
- package/src/apps/routes/routes/deposit-addresses.ts +243 -32
- package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
- package/src/apps/routes/routes/quotes.test.ts +81 -8
- package/src/apps/routes/routes/quotes.ts +109 -27
- package/src/apps/routes/routes/transfers.test.ts +252 -15
- package/src/apps/routes/routes/transfers.ts +212 -33
- package/src/cli/ApiKeys.test.ts +265 -0
- package/src/cli/ApiKeys.ts +189 -0
- package/src/cli/Cli.test.ts +188 -0
- package/src/cli/Cli.ts +280 -12
- package/src/cli/Credentials.test.ts +122 -0
- package/src/cli/Credentials.ts +144 -0
- package/src/cli/Spec.test.ts +133 -0
- package/src/cli/Spec.ts +132 -0
- package/src/cli/bin.test.ts +49 -0
- package/src/cli/bin.ts +5 -1
- package/src/cli/commands/auth.test.ts +138 -0
- package/src/cli/commands/auth.ts +254 -0
- package/src/cli/commands/keys.test.ts +68 -0
- package/src/cli/commands/keys.ts +125 -0
- package/src/cloudflare.ts +184 -36
- package/src/db/Db.test.ts +877 -0
- package/src/db/Db.ts +507 -1
- package/src/db/Schema.ts +75 -4
- package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
- package/src/db/tables/apiKeyAdmissions.ts +101 -11
- package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
- package/src/db/tables/authAccounts.test.ts +30 -0
- package/src/db/tables/authAccounts.ts +1 -0
- package/src/db/tables/earnVaults.test.ts +34 -0
- package/src/db/tables/earnVaults.ts +17 -2
- package/src/db/tables/organizations.test.ts +148 -84
- package/src/db/tables/organizations.ts +11 -43
- package/src/db/tables/requestUsage.ts +13 -2
- package/src/db/tables/rewardCampaigns.test.ts +163 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
- package/src/db/tables/rewardRuns.ts +4 -0
- package/src/db/tables/rewardTransactionAttempts.ts +2 -0
- package/src/db/tables/routesDepositAddresses.test.ts +263 -0
- package/src/db/tables/routesDepositAddresses.ts +118 -34
- package/src/db/tables/routesDeposits.test.ts +133 -0
- package/src/db/tables/routesDeposits.ts +47 -26
- package/src/db/tables/routesIdempotency.test.ts +80 -0
- package/src/db/tables/routesIdempotency.ts +2 -0
- package/src/db/tables/routesPolicies.test.ts +143 -0
- package/src/db/tables/routesPolicies.ts +251 -0
- package/src/db/tables/routesTransferSubsidies.ts +64 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
- package/src/db/tables/routesTransfers.test.ts +183 -2
- package/src/db/tables/routesTransfers.ts +65 -6
- package/src/db/tables/sponsoredTransactions.test.ts +351 -76
- package/src/db/tables/sponsoredTransactions.ts +182 -38
- package/src/db/tables/users.test.ts +51 -0
- package/src/db/tables/users.ts +12 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +39 -20
- package/src/db/tables/verifiedTokenRequests.ts +80 -44
- package/src/handlers/internal/multisig.store.test.ts +120 -0
- package/src/handlers/internal/multisig.test.ts +389 -0
- package/src/handlers/internal/multisig.ts +13 -10
- package/src/handlers/relay.test.ts +259 -83
- package/src/handlers/relay.ts +36 -17
- package/src/internal/Auth.test.ts +383 -8
- package/src/internal/Auth.ts +272 -99
- package/src/internal/BetterAuth.test.ts +58 -22
- package/src/internal/BetterAuth.ts +23 -17
- package/src/internal/Cache.ts +3 -1
- package/src/internal/CliAuth.test.ts +279 -0
- package/src/internal/CliAuth.ts +319 -0
- package/src/internal/EarnSharePrices.test.ts +25 -0
- package/src/internal/EarnSharePrices.ts +9 -2
- package/src/internal/EarnVaults.test.ts +67 -0
- package/src/internal/EarnVaults.ts +299 -4
- package/src/internal/EarnWithdrawals.test.ts +315 -0
- package/src/internal/EarnWithdrawals.ts +266 -0
- package/src/internal/ExecutionContext.ts +31 -0
- package/src/internal/Log.test.ts +210 -0
- package/src/internal/Log.ts +180 -142
- package/src/internal/MetricSink.test.ts +190 -15
- package/src/internal/MetricSink.ts +27 -1
- package/src/internal/RateLimit.test.ts +144 -8
- package/src/internal/RateLimit.ts +254 -26
- package/src/internal/Store.ts +4 -5
- package/src/internal/Timing.test.ts +32 -0
- package/src/internal/Timing.ts +20 -1
- package/src/internal/Tron.test-d.ts +22 -0
- package/src/internal/Tron.test.ts +94 -0
- package/src/internal/Tron.ts +289 -0
- package/src/internal/Viem.rpc.test.ts +76 -0
- package/src/internal/Viem.ts +29 -6
- package/src/internal/rewards/Read.test.ts +109 -0
- package/src/internal/rewards/Read.ts +13 -4
- package/src/internal/routes/Action.test.ts +70 -0
- package/src/internal/routes/Action.ts +76 -1
- package/src/internal/routes/Chain.test.ts +18 -0
- package/src/internal/routes/Chain.ts +5 -0
- package/src/internal/routes/DepositAddress.ts +5 -0
- package/src/internal/routes/Evidence.test.ts +64 -0
- package/src/internal/routes/Evidence.ts +11 -3
- package/src/internal/routes/EvmTransferSettlement.ts +213 -0
- package/src/internal/routes/Policy.test.ts +316 -0
- package/src/internal/routes/Policy.ts +399 -0
- package/src/internal/routes/Provider.test.ts +103 -2
- package/src/internal/routes/Provider.ts +149 -27
- package/src/internal/routes/Quota.test.ts +149 -0
- package/src/internal/routes/Quota.ts +226 -0
- package/src/internal/routes/Reconciliation.local.test.ts +285 -0
- package/src/internal/routes/Reconciliation.test.ts +371 -13
- package/src/internal/routes/Reconciliation.ts +193 -42
- package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
- package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
- package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
- package/src/internal/routes/SourceObservation.test.ts +221 -0
- package/src/internal/routes/Subsidy.local.test.ts +46 -0
- package/src/internal/routes/Subsidy.ts +4 -2
- package/src/internal/routes/Transfer.solana.test.ts +389 -0
- package/src/internal/routes/Transfer.test.ts +130 -1
- package/src/internal/routes/Transfer.tron.test.ts +172 -0
- package/src/internal/routes/Transfer.ts +866 -8
- package/src/internal/routes/TransferReconciliation.test.ts +26 -4
- package/src/internal/routes/TransferReconciliation.ts +91 -166
- package/src/internal/routes/TransferSettlement.ts +48 -0
- package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
- package/src/internal/routes/TransferSubsidy.test.ts +34 -4
- package/src/internal/routes/TransferSubsidy.ts +87 -12
- package/src/internal/routes/TronTransferSettlement.ts +212 -0
- package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
- package/src/internal/routes/TronTransferSubsidy.ts +619 -0
- package/src/internal/routes/index.test.ts +3 -0
- package/src/internal/routes/index.ts +3 -0
- package/src/internal/routes/providers/across.ts +13 -0
- package/src/internal/routes/providers/index.test.ts +141 -0
- package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
- package/src/internal/routes/providers/legacyMesh.ts +633 -0
- package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
- package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
- package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
- package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
- package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
- package/src/internal/routes/providers/propAmm.ts +640 -0
- package/src/internal/routes/providers/relay.test.ts +1299 -18
- package/src/internal/routes/providers/relay.ts +424 -39
- package/src/internal/routes/providers/rhino.ts +14 -1
- package/src/internal/routes/providers/squid.ts +21 -0
- package/src/internal/routes/providers/stargate.test.ts +105 -1
- package/src/internal/routes/providers/stargate.ts +22 -9
- package/src/internal/routes/providers/symbiosis.ts +13 -47
- package/src/providers/index.test.ts +2 -0
- package/src/providers/index.ts +18 -0
- package/dist/admin/Access.d.ts +0 -39
- package/dist/admin/Access.d.ts.map +0 -1
- package/dist/admin/Access.js +0 -73
- package/dist/admin/Access.js.map +0 -1
- package/src/admin/Access.test.ts +0 -130
- package/src/admin/Access.ts +0 -85
|
@@ -13,9 +13,12 @@ import * as OpenApi from '../OpenApi.js'
|
|
|
13
13
|
import * as Schema from '../Schema.js'
|
|
14
14
|
import type * as Webhooks from '../Webhooks.js'
|
|
15
15
|
import * as Action from './Action.js'
|
|
16
|
+
import * as Policy from './Policy.js'
|
|
16
17
|
import * as Provider from './Provider.js'
|
|
18
|
+
import * as SolanaTransferSubsidy from './SolanaTransferSubsidy.js'
|
|
17
19
|
import * as TransferSubsidy from './TransferSubsidy.js'
|
|
18
20
|
import * as TransferWebhook from './TransferWebhook.js'
|
|
21
|
+
import * as TronTransferSubsidy from './TronTransferSubsidy.js'
|
|
19
22
|
|
|
20
23
|
/** Public route transfer statuses, in the order documented by the API. */
|
|
21
24
|
export const statuses = [
|
|
@@ -387,9 +390,11 @@ export namespace schema {
|
|
|
387
390
|
),
|
|
388
391
|
),
|
|
389
392
|
sourceChain: z
|
|
390
|
-
.string()
|
|
393
|
+
.optional(z.string())
|
|
391
394
|
.check(
|
|
392
|
-
z.describe(
|
|
395
|
+
z.describe(
|
|
396
|
+
'Source chain CAIP-2 id, slug, or alias. Defaults to the destination chain.',
|
|
397
|
+
),
|
|
393
398
|
z.meta({ examples: ['tempo', 'base', 'ethereum', 'eip155:4217'] }),
|
|
394
399
|
),
|
|
395
400
|
sourceToken: z
|
|
@@ -403,7 +408,7 @@ export namespace schema {
|
|
|
403
408
|
.optional(z.boolean())
|
|
404
409
|
.check(
|
|
405
410
|
z.describe(
|
|
406
|
-
'Guarantees normalized 1:1 delivery for exact-source
|
|
411
|
+
'Guarantees normalized 1:1 USD delivery for exact-source transfers to Tempo or from Tempo to Base, Ethereum, Solana, or Tron. Requires organization subsidy approval.',
|
|
407
412
|
),
|
|
408
413
|
z.meta({ examples: [true] }),
|
|
409
414
|
),
|
|
@@ -477,13 +482,21 @@ export async function createIn(tx: Db.Db, input: create.Input): Promise<createIn
|
|
|
477
482
|
status: 'awaiting-source',
|
|
478
483
|
statusReason: null,
|
|
479
484
|
statusUpdatedAt: now.toISOString(),
|
|
480
|
-
subsidyAccount: input.subsidyCommitment
|
|
485
|
+
subsidyAccount: input.subsidyCommitment
|
|
486
|
+
? input.subsidyCommitment.chainId.startsWith('eip155:')
|
|
487
|
+
? input.subsidyCommitment.account.toLowerCase()
|
|
488
|
+
: input.subsidyCommitment.account
|
|
489
|
+
: null,
|
|
481
490
|
subsidyAmount: null,
|
|
482
491
|
subsidyChainId: input.subsidyCommitment?.chainId ?? null,
|
|
483
492
|
subsidyCommitmentAmount: input.subsidyCommitment?.amount ?? null,
|
|
484
493
|
subsidyMeterReportedAt: null,
|
|
485
494
|
subsidyNativeAmount: input.subsidyCommitment?.nativeAmount ?? null,
|
|
486
|
-
subsidyTokenAddress: input.subsidyCommitment
|
|
495
|
+
subsidyTokenAddress: input.subsidyCommitment
|
|
496
|
+
? input.subsidyCommitment.chainId.startsWith('eip155:')
|
|
497
|
+
? input.subsidyCommitment.tokenAddress.toLowerCase()
|
|
498
|
+
: input.subsidyCommitment.tokenAddress
|
|
499
|
+
: null,
|
|
487
500
|
subsidyTransactionHash: null,
|
|
488
501
|
updatedAt: now.toISOString(),
|
|
489
502
|
version: 1,
|
|
@@ -954,6 +967,786 @@ export declare namespace reserveSubsidy {
|
|
|
954
967
|
| { type: 'not_found' }
|
|
955
968
|
}
|
|
956
969
|
|
|
970
|
+
/** Persists an unsigned Solana subsidy before contacting the signer. */
|
|
971
|
+
export async function prepareSolanaSubsidy(
|
|
972
|
+
db: Db.Db,
|
|
973
|
+
options: prepareSolanaSubsidy.Options,
|
|
974
|
+
): Promise<prepareSolanaSubsidy.Result> {
|
|
975
|
+
return db.transaction(async (tx) => {
|
|
976
|
+
await RoutesSubsidies.lockOrganization(tx, options.orgId)
|
|
977
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
978
|
+
if (!current) return { type: 'not_found' }
|
|
979
|
+
if (current.orgId !== options.orgId || current.status !== 'processing')
|
|
980
|
+
return { current, type: 'invalid' }
|
|
981
|
+
const signed = SolanaTransferSubsidy.readSigned(current.providerState?.['transferSubsidy'])
|
|
982
|
+
if (signed) {
|
|
983
|
+
if (
|
|
984
|
+
!SolanaTransferSubsidy.matchesTerms(signed, {
|
|
985
|
+
account: options.account,
|
|
986
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
987
|
+
chainId: options.chainId,
|
|
988
|
+
recipient: current.snapshot.recipient,
|
|
989
|
+
token: options.tokenAddress,
|
|
990
|
+
})
|
|
991
|
+
)
|
|
992
|
+
throw new SubsidyEvidenceError()
|
|
993
|
+
return { record: current, signed, type: 'signed' }
|
|
994
|
+
}
|
|
995
|
+
const existing = SolanaTransferSubsidy.readPrepared(
|
|
996
|
+
current.providerState?.['solanaTransferSubsidyPrepared'],
|
|
997
|
+
)
|
|
998
|
+
if (existing) {
|
|
999
|
+
if (
|
|
1000
|
+
!SolanaTransferSubsidy.matchesTerms(existing, {
|
|
1001
|
+
account: options.account,
|
|
1002
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1003
|
+
chainId: options.chainId,
|
|
1004
|
+
recipient: current.snapshot.recipient,
|
|
1005
|
+
token: options.tokenAddress,
|
|
1006
|
+
})
|
|
1007
|
+
)
|
|
1008
|
+
throw new SubsidyEvidenceError()
|
|
1009
|
+
if (!(await options.expiring(existing)))
|
|
1010
|
+
return { prepared: existing, record: current, type: 'prepared' }
|
|
1011
|
+
}
|
|
1012
|
+
if (
|
|
1013
|
+
!current.subsidyCommitmentAmount ||
|
|
1014
|
+
BigInt(options.subsidyAmount.baseUnits) > BigInt(current.subsidyCommitmentAmount.baseUnits)
|
|
1015
|
+
)
|
|
1016
|
+
throw new SubsidyCommitmentExceededError()
|
|
1017
|
+
const transactionRef = current.snapshot.sourceTransactionHashes?.[0]
|
|
1018
|
+
const source = transactionRef
|
|
1019
|
+
? await RoutesTransferTransactions.getSource(tx, {
|
|
1020
|
+
chainId: current.snapshot.sourceChain.id,
|
|
1021
|
+
transactionRef,
|
|
1022
|
+
transferId: current.id,
|
|
1023
|
+
})
|
|
1024
|
+
: undefined
|
|
1025
|
+
if (source?.transferId !== current.id) throw new SubsidyEvidenceError()
|
|
1026
|
+
const settlement = await RoutesTransferSubsidies.getForUpdateIn(tx, {
|
|
1027
|
+
sourceChainId: source.chainId,
|
|
1028
|
+
transactionRef: source.transactionRef,
|
|
1029
|
+
})
|
|
1030
|
+
if (settlement) {
|
|
1031
|
+
const signed = SolanaTransferSubsidy.readSigned(settlement.transaction)
|
|
1032
|
+
if (
|
|
1033
|
+
!signed ||
|
|
1034
|
+
settlement.destinationChainId !== options.chainId ||
|
|
1035
|
+
settlement.recipient !== current.snapshot.recipient ||
|
|
1036
|
+
settlement.tokenAddress !== options.tokenAddress ||
|
|
1037
|
+
!SolanaTransferSubsidy.matchesTerms(signed, {
|
|
1038
|
+
account: signed.account,
|
|
1039
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1040
|
+
chainId: options.chainId,
|
|
1041
|
+
recipient: current.snapshot.recipient,
|
|
1042
|
+
token: options.tokenAddress,
|
|
1043
|
+
})
|
|
1044
|
+
)
|
|
1045
|
+
throw new SubsidyEvidenceError()
|
|
1046
|
+
// The original owner alone can replace the expired canonical transaction.
|
|
1047
|
+
if (settlement.status === 'expired') {
|
|
1048
|
+
if (settlement.transferId !== current.id) return { type: 'pending' }
|
|
1049
|
+
} else {
|
|
1050
|
+
const result = await transitionIn(tx, {
|
|
1051
|
+
current,
|
|
1052
|
+
expectedVersion: current.version,
|
|
1053
|
+
id: current.id,
|
|
1054
|
+
// Preserve Solana transaction bytes as serialized text for exact replay.
|
|
1055
|
+
providerState: {
|
|
1056
|
+
...current.providerState,
|
|
1057
|
+
transferSubsidy: JSON.stringify(signed),
|
|
1058
|
+
transferSubsidyOwnerId: settlement.transferId,
|
|
1059
|
+
},
|
|
1060
|
+
subsidyAccount: signed.account,
|
|
1061
|
+
subsidyAmount: null,
|
|
1062
|
+
subsidyChainId: signed.chainId,
|
|
1063
|
+
subsidyCommitmentAmount: null,
|
|
1064
|
+
subsidyNativeAmount: null,
|
|
1065
|
+
subsidyTokenAddress: settlement.tokenAddress,
|
|
1066
|
+
subsidyTransactionHash: signed.hash,
|
|
1067
|
+
})
|
|
1068
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1069
|
+
return { record: result.record, references: result.references, signed, type: 'shared' }
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
await RoutesTransferSubsidyNonces.lockAvailableIn(tx, {
|
|
1073
|
+
account: options.account,
|
|
1074
|
+
chainId: options.chainId,
|
|
1075
|
+
}).catch((cause) => {
|
|
1076
|
+
if (cause instanceof RoutesTransferSubsidyNonces.BlockedError)
|
|
1077
|
+
throw new SubsidySignerBlockedError()
|
|
1078
|
+
throw cause
|
|
1079
|
+
})
|
|
1080
|
+
const reservations = await RoutesTransfers.subsidyReservations(tx, {
|
|
1081
|
+
account: options.account,
|
|
1082
|
+
chainId: options.chainId,
|
|
1083
|
+
excludeId: current.id,
|
|
1084
|
+
tokenAddress: options.tokenAddress,
|
|
1085
|
+
})
|
|
1086
|
+
const prepared = await options.prepare({ reservations })
|
|
1087
|
+
if (
|
|
1088
|
+
!SolanaTransferSubsidy.matchesTerms(prepared, {
|
|
1089
|
+
account: options.account,
|
|
1090
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1091
|
+
chainId: options.chainId,
|
|
1092
|
+
recipient: current.snapshot.recipient,
|
|
1093
|
+
token: options.tokenAddress,
|
|
1094
|
+
})
|
|
1095
|
+
)
|
|
1096
|
+
throw new SubsidyEvidenceError()
|
|
1097
|
+
const result = await transitionIn(tx, {
|
|
1098
|
+
current,
|
|
1099
|
+
expectedVersion: current.version,
|
|
1100
|
+
id: current.id,
|
|
1101
|
+
// Keep the native transaction bytes and Horcrux request intact across database round trips.
|
|
1102
|
+
providerState: {
|
|
1103
|
+
...current.providerState,
|
|
1104
|
+
solanaTransferSubsidyPrepared: JSON.stringify(prepared),
|
|
1105
|
+
},
|
|
1106
|
+
subsidyAccount: options.account,
|
|
1107
|
+
subsidyAmount: options.subsidyAmount,
|
|
1108
|
+
subsidyChainId: options.chainId,
|
|
1109
|
+
subsidyNativeAmount: prepared.nativeAmount,
|
|
1110
|
+
subsidyTokenAddress: options.tokenAddress,
|
|
1111
|
+
})
|
|
1112
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1113
|
+
return { prepared, record: result.record, references: result.references, type: 'prepared' }
|
|
1114
|
+
})
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
export declare namespace prepareSolanaSubsidy {
|
|
1118
|
+
/** Solana subsidy preparation under the organization and signer locks. */
|
|
1119
|
+
type Options = {
|
|
1120
|
+
/** Horcrux-managed Solana account. */
|
|
1121
|
+
account: string
|
|
1122
|
+
/** Destination chain identifier. */
|
|
1123
|
+
chainId: string
|
|
1124
|
+
/** Checks whether a persisted unsigned transaction needs a fresh blockhash. */
|
|
1125
|
+
expiring: (prepared: SolanaTransferSubsidy.Prepared) => Promise<boolean>
|
|
1126
|
+
/** Route transfer identifier. */
|
|
1127
|
+
id: string
|
|
1128
|
+
/** Owning organization identifier. */
|
|
1129
|
+
orgId: string
|
|
1130
|
+
/** Builds an unsigned transaction against reserved inventory. */
|
|
1131
|
+
prepare: (options: {
|
|
1132
|
+
reservations: RoutesTransfers.subsidyReservations.Result
|
|
1133
|
+
}) => Promise<SolanaTransferSubsidy.Prepared>
|
|
1134
|
+
/** Subsidy amount approved by policy. */
|
|
1135
|
+
subsidyAmount: NonNullable<Snapshot['destinationAmountRequired']>
|
|
1136
|
+
/** Solana USDC contract address. */
|
|
1137
|
+
tokenAddress: string
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/** Durable preparation or existing signed settlement. */
|
|
1141
|
+
type Result =
|
|
1142
|
+
| { current: RoutesTransfers.Record; type: 'invalid' }
|
|
1143
|
+
| { type: 'not_found' }
|
|
1144
|
+
| { type: 'pending' }
|
|
1145
|
+
| {
|
|
1146
|
+
prepared: SolanaTransferSubsidy.Prepared
|
|
1147
|
+
record: RoutesTransfers.Record
|
|
1148
|
+
references?: readonly Webhooks.QueueReference[] | undefined
|
|
1149
|
+
type: 'prepared'
|
|
1150
|
+
}
|
|
1151
|
+
| { record: RoutesTransfers.Record; signed: SolanaTransferSubsidy.Signed; type: 'signed' }
|
|
1152
|
+
| {
|
|
1153
|
+
record: RoutesTransfers.Record
|
|
1154
|
+
references: readonly Webhooks.QueueReference[]
|
|
1155
|
+
signed: SolanaTransferSubsidy.Signed
|
|
1156
|
+
type: 'shared'
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/** Persists a verified Solana signature before broadcasting the transaction. */
|
|
1161
|
+
export async function signSolanaSubsidy(
|
|
1162
|
+
db: Db.Db,
|
|
1163
|
+
options: signSolanaSubsidy.Options,
|
|
1164
|
+
): Promise<signSolanaSubsidy.Result> {
|
|
1165
|
+
return db.transaction(async (tx) => {
|
|
1166
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
1167
|
+
if (!current) return { type: 'not_found' }
|
|
1168
|
+
if (current.status !== 'processing') return { current, type: 'invalid' }
|
|
1169
|
+
const existing = SolanaTransferSubsidy.readSigned(current.providerState?.['transferSubsidy'])
|
|
1170
|
+
if (existing) return { record: current, signed: existing, type: 'replayed' }
|
|
1171
|
+
const prepared = SolanaTransferSubsidy.readPrepared(
|
|
1172
|
+
current.providerState?.['solanaTransferSubsidyPrepared'],
|
|
1173
|
+
)
|
|
1174
|
+
if (
|
|
1175
|
+
!prepared ||
|
|
1176
|
+
prepared.request.transaction !== options.signed.request.transaction ||
|
|
1177
|
+
prepared.lastValidBlockHeight !== options.signed.lastValidBlockHeight ||
|
|
1178
|
+
prepared.account !== options.signed.account ||
|
|
1179
|
+
prepared.amount !== options.signed.amount ||
|
|
1180
|
+
prepared.chainId !== options.signed.chainId ||
|
|
1181
|
+
!SolanaTransferSubsidy.matchesTerms(options.signed, {
|
|
1182
|
+
account: prepared.account,
|
|
1183
|
+
amount: BigInt(prepared.amount),
|
|
1184
|
+
chainId: prepared.chainId,
|
|
1185
|
+
recipient: current.snapshot.recipient,
|
|
1186
|
+
token: current.snapshot.destinationToken.address,
|
|
1187
|
+
})
|
|
1188
|
+
)
|
|
1189
|
+
throw new SubsidyEvidenceError()
|
|
1190
|
+
const transactionRef = current.snapshot.sourceTransactionHashes?.[0]
|
|
1191
|
+
const source = transactionRef
|
|
1192
|
+
? await RoutesTransferTransactions.getSource(tx, {
|
|
1193
|
+
chainId: current.snapshot.sourceChain.id,
|
|
1194
|
+
transactionRef,
|
|
1195
|
+
transferId: current.id,
|
|
1196
|
+
})
|
|
1197
|
+
: undefined
|
|
1198
|
+
if (source?.transferId !== current.id) throw new SubsidyEvidenceError()
|
|
1199
|
+
const settlement = await RoutesTransferSubsidies.getForUpdateIn(tx, {
|
|
1200
|
+
sourceChainId: source.chainId,
|
|
1201
|
+
transactionRef: source.transactionRef,
|
|
1202
|
+
})
|
|
1203
|
+
const signed =
|
|
1204
|
+
settlement?.status === 'active'
|
|
1205
|
+
? SolanaTransferSubsidy.readSigned(settlement.transaction)
|
|
1206
|
+
: options.signed
|
|
1207
|
+
if (
|
|
1208
|
+
!signed ||
|
|
1209
|
+
(settlement &&
|
|
1210
|
+
(settlement.destinationChainId !== prepared.chainId ||
|
|
1211
|
+
settlement.recipient !== current.snapshot.recipient ||
|
|
1212
|
+
settlement.tokenAddress !== current.snapshot.destinationToken.address ||
|
|
1213
|
+
(settlement.status === 'expired' && settlement.transferId !== current.id) ||
|
|
1214
|
+
!SolanaTransferSubsidy.matchesTerms(signed, {
|
|
1215
|
+
account: signed.account,
|
|
1216
|
+
amount: BigInt(prepared.amount),
|
|
1217
|
+
chainId: prepared.chainId,
|
|
1218
|
+
recipient: current.snapshot.recipient,
|
|
1219
|
+
token: current.snapshot.destinationToken.address,
|
|
1220
|
+
})))
|
|
1221
|
+
)
|
|
1222
|
+
throw new SubsidyEvidenceError()
|
|
1223
|
+
const result = await transitionIn(tx, {
|
|
1224
|
+
current,
|
|
1225
|
+
expectedVersion: current.version,
|
|
1226
|
+
id: current.id,
|
|
1227
|
+
providerState: {
|
|
1228
|
+
...current.providerState,
|
|
1229
|
+
transferSubsidy: JSON.stringify(signed),
|
|
1230
|
+
...(settlement?.status === 'active'
|
|
1231
|
+
? { transferSubsidyOwnerId: settlement.transferId }
|
|
1232
|
+
: {}),
|
|
1233
|
+
},
|
|
1234
|
+
...(settlement?.status === 'active'
|
|
1235
|
+
? { subsidyAmount: null, subsidyCommitmentAmount: null, subsidyNativeAmount: null }
|
|
1236
|
+
: {}),
|
|
1237
|
+
subsidyTransactionHash: signed.hash,
|
|
1238
|
+
})
|
|
1239
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1240
|
+
return {
|
|
1241
|
+
record: result.record,
|
|
1242
|
+
references: result.references,
|
|
1243
|
+
signed,
|
|
1244
|
+
type: settlement?.status === 'active' ? 'shared' : 'signed',
|
|
1245
|
+
}
|
|
1246
|
+
})
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
export declare namespace signSolanaSubsidy {
|
|
1250
|
+
/** Signed transaction and owning route transfer. */
|
|
1251
|
+
type Options = { id: string; signed: SolanaTransferSubsidy.Signed }
|
|
1252
|
+
/** Persisted signed settlement or a stale transfer. */
|
|
1253
|
+
type Result =
|
|
1254
|
+
| { current: RoutesTransfers.Record; type: 'invalid' }
|
|
1255
|
+
| { type: 'not_found' }
|
|
1256
|
+
| { record: RoutesTransfers.Record; signed: SolanaTransferSubsidy.Signed; type: 'replayed' }
|
|
1257
|
+
| {
|
|
1258
|
+
record: RoutesTransfers.Record
|
|
1259
|
+
references: readonly Webhooks.QueueReference[]
|
|
1260
|
+
signed: SolanaTransferSubsidy.Signed
|
|
1261
|
+
type: 'shared' | 'signed'
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/** Follows the canonical subsidy when another transfer owns the source payment. */
|
|
1266
|
+
export async function syncSharedSolanaSubsidy(
|
|
1267
|
+
db: Db.Db,
|
|
1268
|
+
options: syncSharedSolanaSubsidy.Options,
|
|
1269
|
+
): Promise<syncSharedSolanaSubsidy.Result> {
|
|
1270
|
+
return db.transaction(async (tx) => {
|
|
1271
|
+
await RoutesSubsidies.lockOrganization(tx, options.orgId)
|
|
1272
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
1273
|
+
if (!current) return { type: 'not_found' }
|
|
1274
|
+
if (current.orgId !== options.orgId || current.status !== 'processing')
|
|
1275
|
+
return { type: 'pending' }
|
|
1276
|
+
const signed = SolanaTransferSubsidy.readSigned(current.providerState?.['transferSubsidy'])
|
|
1277
|
+
if (
|
|
1278
|
+
!signed ||
|
|
1279
|
+
signed.hash !== options.signed.hash ||
|
|
1280
|
+
current.subsidyTransactionHash !== signed.hash
|
|
1281
|
+
)
|
|
1282
|
+
return { type: 'pending' }
|
|
1283
|
+
const transactionRef = current.snapshot.sourceTransactionHashes?.[0]
|
|
1284
|
+
const source = transactionRef
|
|
1285
|
+
? await RoutesTransferTransactions.getSource(tx, {
|
|
1286
|
+
chainId: current.snapshot.sourceChain.id,
|
|
1287
|
+
transactionRef,
|
|
1288
|
+
transferId: current.id,
|
|
1289
|
+
})
|
|
1290
|
+
: undefined
|
|
1291
|
+
if (source?.transferId !== current.id) throw new SubsidyEvidenceError()
|
|
1292
|
+
const settlement = await RoutesTransferSubsidies.getForUpdateIn(tx, {
|
|
1293
|
+
sourceChainId: source.chainId,
|
|
1294
|
+
transactionRef: source.transactionRef,
|
|
1295
|
+
})
|
|
1296
|
+
if (
|
|
1297
|
+
!settlement ||
|
|
1298
|
+
settlement.destinationChainId !== signed.chainId ||
|
|
1299
|
+
settlement.recipient !== signed.recipient ||
|
|
1300
|
+
settlement.tokenAddress !== signed.token
|
|
1301
|
+
)
|
|
1302
|
+
throw new SubsidyEvidenceError()
|
|
1303
|
+
if (settlement.transferId === current.id) return { type: 'unchanged' }
|
|
1304
|
+
// The owner has already proved expiry; shared transfers wait for its replacement.
|
|
1305
|
+
if (settlement.status === 'expired') return { type: 'pending' }
|
|
1306
|
+
const replacement = SolanaTransferSubsidy.readSigned(settlement.transaction)
|
|
1307
|
+
if (
|
|
1308
|
+
!replacement ||
|
|
1309
|
+
!SolanaTransferSubsidy.matchesTerms(replacement, {
|
|
1310
|
+
account: signed.account,
|
|
1311
|
+
amount: BigInt(signed.amount),
|
|
1312
|
+
chainId: signed.chainId,
|
|
1313
|
+
recipient: signed.recipient,
|
|
1314
|
+
token: signed.token,
|
|
1315
|
+
})
|
|
1316
|
+
)
|
|
1317
|
+
throw new SubsidyEvidenceError()
|
|
1318
|
+
if (replacement.hash === signed.hash) return { type: 'unchanged' }
|
|
1319
|
+
const result = await transitionIn(tx, {
|
|
1320
|
+
current,
|
|
1321
|
+
expectedVersion: current.version,
|
|
1322
|
+
id: current.id,
|
|
1323
|
+
providerState: {
|
|
1324
|
+
...current.providerState,
|
|
1325
|
+
solanaTransferSubsidyPrepared: null,
|
|
1326
|
+
transferSubsidy: JSON.stringify(replacement),
|
|
1327
|
+
transferSubsidyOwnerId: settlement.transferId,
|
|
1328
|
+
},
|
|
1329
|
+
subsidyTransactionHash: replacement.hash,
|
|
1330
|
+
})
|
|
1331
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1332
|
+
return {
|
|
1333
|
+
record: result.record,
|
|
1334
|
+
references: result.references,
|
|
1335
|
+
signed: replacement,
|
|
1336
|
+
type: 'synchronized',
|
|
1337
|
+
}
|
|
1338
|
+
})
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
export declare namespace syncSharedSolanaSubsidy {
|
|
1342
|
+
/** Transfer and previously shared signed transaction. */
|
|
1343
|
+
type Options = {
|
|
1344
|
+
/** Route transfer identifier. */
|
|
1345
|
+
id: string
|
|
1346
|
+
/** Owning organization identifier. */
|
|
1347
|
+
orgId: string
|
|
1348
|
+
/** Signed attempt currently stored on the transfer. */
|
|
1349
|
+
signed: SolanaTransferSubsidy.Signed
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
/** Canonical replacement, unchanged transaction, or a pending owner refresh. */
|
|
1353
|
+
type Result =
|
|
1354
|
+
| { type: 'not_found' }
|
|
1355
|
+
| { type: 'pending' }
|
|
1356
|
+
| { type: 'unchanged' }
|
|
1357
|
+
| {
|
|
1358
|
+
record: RoutesTransfers.Record
|
|
1359
|
+
references: readonly Webhooks.QueueReference[]
|
|
1360
|
+
signed: SolanaTransferSubsidy.Signed
|
|
1361
|
+
type: 'synchronized'
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/** Retires an unlanded signed Solana attempt so its billing owner can prepare again. */
|
|
1366
|
+
export async function recoverExpiredSolanaSubsidy(
|
|
1367
|
+
db: Db.Db,
|
|
1368
|
+
options: recoverExpiredSolanaSubsidy.Options,
|
|
1369
|
+
): Promise<recoverExpiredSolanaSubsidy.Result> {
|
|
1370
|
+
return db.transaction(async (tx) => {
|
|
1371
|
+
await RoutesSubsidies.lockOrganization(tx, options.orgId)
|
|
1372
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
1373
|
+
if (!current) return { type: 'not_found' }
|
|
1374
|
+
if (current.orgId !== options.orgId || current.status !== 'processing')
|
|
1375
|
+
return { type: 'pending' }
|
|
1376
|
+
const signed = SolanaTransferSubsidy.readSigned(current.providerState?.['transferSubsidy'])
|
|
1377
|
+
if (
|
|
1378
|
+
!signed ||
|
|
1379
|
+
signed.hash !== options.signed.hash ||
|
|
1380
|
+
current.subsidyTransactionHash !== signed.hash
|
|
1381
|
+
)
|
|
1382
|
+
return { type: 'pending' }
|
|
1383
|
+
if (
|
|
1384
|
+
!SolanaTransferSubsidy.matchesTerms(signed, {
|
|
1385
|
+
account: signed.account,
|
|
1386
|
+
amount: BigInt(signed.amount),
|
|
1387
|
+
chainId: current.snapshot.destinationChain.id,
|
|
1388
|
+
recipient: current.snapshot.recipient,
|
|
1389
|
+
token: current.snapshot.destinationToken.address,
|
|
1390
|
+
})
|
|
1391
|
+
)
|
|
1392
|
+
throw new SubsidyEvidenceError()
|
|
1393
|
+
const transactionRef = current.snapshot.sourceTransactionHashes?.[0]
|
|
1394
|
+
const source = transactionRef
|
|
1395
|
+
? await RoutesTransferTransactions.getSource(tx, {
|
|
1396
|
+
chainId: current.snapshot.sourceChain.id,
|
|
1397
|
+
transactionRef,
|
|
1398
|
+
transferId: current.id,
|
|
1399
|
+
})
|
|
1400
|
+
: undefined
|
|
1401
|
+
if (source?.transferId !== current.id) throw new SubsidyEvidenceError()
|
|
1402
|
+
const outcome = await RoutesTransferSubsidies.markExpiredIn(tx, {
|
|
1403
|
+
signedHash: signed.hash,
|
|
1404
|
+
signedTransaction: JSON.stringify(signed),
|
|
1405
|
+
sourceChainId: source.chainId,
|
|
1406
|
+
transactionRef: source.transactionRef,
|
|
1407
|
+
transferId: current.id,
|
|
1408
|
+
})
|
|
1409
|
+
if (outcome.type === 'not_found') throw new SubsidyEvidenceError()
|
|
1410
|
+
const settlement = outcome.settlement
|
|
1411
|
+
if (
|
|
1412
|
+
settlement.destinationChainId !== signed.chainId ||
|
|
1413
|
+
settlement.recipient !== signed.recipient ||
|
|
1414
|
+
settlement.tokenAddress !== signed.token
|
|
1415
|
+
)
|
|
1416
|
+
throw new SubsidyEvidenceError()
|
|
1417
|
+
if (outcome.type === 'expired') {
|
|
1418
|
+
const result = await transitionIn(tx, {
|
|
1419
|
+
current,
|
|
1420
|
+
expectedVersion: current.version,
|
|
1421
|
+
id: current.id,
|
|
1422
|
+
providerState: {
|
|
1423
|
+
...current.providerState,
|
|
1424
|
+
solanaTransferSubsidyPrepared: null,
|
|
1425
|
+
transferSubsidy: null,
|
|
1426
|
+
transferSubsidyOwnerId: null,
|
|
1427
|
+
},
|
|
1428
|
+
subsidyTransactionHash: null,
|
|
1429
|
+
})
|
|
1430
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1431
|
+
return { record: result.record, references: result.references, type: 'recovered' }
|
|
1432
|
+
}
|
|
1433
|
+
if (settlement.status !== 'active') return { type: 'pending' }
|
|
1434
|
+
const replacement = SolanaTransferSubsidy.readSigned(settlement.transaction)
|
|
1435
|
+
if (!replacement || replacement.hash === signed.hash || replacement.amount !== signed.amount)
|
|
1436
|
+
return { type: 'pending' }
|
|
1437
|
+
const result = await transitionIn(tx, {
|
|
1438
|
+
current,
|
|
1439
|
+
expectedVersion: current.version,
|
|
1440
|
+
id: current.id,
|
|
1441
|
+
providerState: {
|
|
1442
|
+
...current.providerState,
|
|
1443
|
+
solanaTransferSubsidyPrepared: null,
|
|
1444
|
+
transferSubsidy: JSON.stringify(replacement),
|
|
1445
|
+
transferSubsidyOwnerId: settlement.transferId,
|
|
1446
|
+
},
|
|
1447
|
+
subsidyTransactionHash: replacement.hash,
|
|
1448
|
+
})
|
|
1449
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1450
|
+
return { record: result.record, references: result.references, type: 'recovered' }
|
|
1451
|
+
})
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
export declare namespace recoverExpiredSolanaSubsidy {
|
|
1455
|
+
/** The current transfer and verified expired signed attempt. */
|
|
1456
|
+
type Options = {
|
|
1457
|
+
/** Route transfer identifier. */
|
|
1458
|
+
id: string
|
|
1459
|
+
/** Owning organization identifier. */
|
|
1460
|
+
orgId: string
|
|
1461
|
+
/** Signed transaction proven absent after finality. */
|
|
1462
|
+
signed: SolanaTransferSubsidy.Signed
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
/** Recovery or a concurrent settlement change. */
|
|
1466
|
+
type Result =
|
|
1467
|
+
| { type: 'not_found' | 'pending' }
|
|
1468
|
+
| {
|
|
1469
|
+
record: RoutesTransfers.Record
|
|
1470
|
+
references: readonly Webhooks.QueueReference[]
|
|
1471
|
+
type: 'recovered'
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
/** Persists an unsigned Tron subsidy before contacting the signer. */
|
|
1476
|
+
export async function prepareTronSubsidy(
|
|
1477
|
+
db: Db.Db,
|
|
1478
|
+
options: prepareTronSubsidy.Options,
|
|
1479
|
+
): Promise<prepareTronSubsidy.Result> {
|
|
1480
|
+
return db.transaction(async (tx) => {
|
|
1481
|
+
await RoutesSubsidies.lockOrganization(tx, options.orgId)
|
|
1482
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
1483
|
+
if (!current) return { type: 'not_found' }
|
|
1484
|
+
if (current.orgId !== options.orgId || current.status !== 'processing')
|
|
1485
|
+
return { current, type: 'invalid' }
|
|
1486
|
+
const signed = TronTransferSubsidy.readSigned(current.providerState?.['transferSubsidy'])
|
|
1487
|
+
if (signed) {
|
|
1488
|
+
if (
|
|
1489
|
+
!TronTransferSubsidy.matchesTerms(signed, {
|
|
1490
|
+
account: options.account,
|
|
1491
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1492
|
+
chainId: options.chainId,
|
|
1493
|
+
recipient: current.snapshot.recipient,
|
|
1494
|
+
token: options.tokenAddress,
|
|
1495
|
+
})
|
|
1496
|
+
)
|
|
1497
|
+
throw new SubsidyEvidenceError()
|
|
1498
|
+
return { record: current, signed, type: 'signed' }
|
|
1499
|
+
}
|
|
1500
|
+
const existing = TronTransferSubsidy.readPrepared(
|
|
1501
|
+
current.providerState?.['tronTransferSubsidyPrepared'],
|
|
1502
|
+
)
|
|
1503
|
+
if (existing) {
|
|
1504
|
+
if (
|
|
1505
|
+
!TronTransferSubsidy.matchesTerms(existing, {
|
|
1506
|
+
account: options.account,
|
|
1507
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1508
|
+
chainId: options.chainId,
|
|
1509
|
+
recipient: current.snapshot.recipient,
|
|
1510
|
+
token: options.tokenAddress,
|
|
1511
|
+
})
|
|
1512
|
+
)
|
|
1513
|
+
throw new SubsidyEvidenceError()
|
|
1514
|
+
return { prepared: existing, record: current, type: 'prepared' }
|
|
1515
|
+
}
|
|
1516
|
+
if (
|
|
1517
|
+
!current.subsidyCommitmentAmount ||
|
|
1518
|
+
BigInt(options.subsidyAmount.baseUnits) > BigInt(current.subsidyCommitmentAmount.baseUnits)
|
|
1519
|
+
)
|
|
1520
|
+
throw new SubsidyCommitmentExceededError()
|
|
1521
|
+
const transactionRef = current.snapshot.sourceTransactionHashes?.[0]
|
|
1522
|
+
const source = transactionRef
|
|
1523
|
+
? await RoutesTransferTransactions.getSource(tx, {
|
|
1524
|
+
chainId: current.snapshot.sourceChain.id,
|
|
1525
|
+
transactionRef,
|
|
1526
|
+
transferId: current.id,
|
|
1527
|
+
})
|
|
1528
|
+
: undefined
|
|
1529
|
+
if (source?.transferId !== current.id) throw new SubsidyEvidenceError()
|
|
1530
|
+
const settlement = await RoutesTransferSubsidies.getForUpdateIn(tx, {
|
|
1531
|
+
sourceChainId: source.chainId,
|
|
1532
|
+
transactionRef: source.transactionRef,
|
|
1533
|
+
})
|
|
1534
|
+
if (settlement) {
|
|
1535
|
+
const signed = TronTransferSubsidy.readSigned(settlement.transaction)
|
|
1536
|
+
if (
|
|
1537
|
+
!signed ||
|
|
1538
|
+
settlement.destinationChainId !== options.chainId ||
|
|
1539
|
+
settlement.recipient !== current.snapshot.recipient ||
|
|
1540
|
+
settlement.tokenAddress !== options.tokenAddress ||
|
|
1541
|
+
!TronTransferSubsidy.matchesTerms(signed, {
|
|
1542
|
+
account: signed.account,
|
|
1543
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1544
|
+
chainId: options.chainId,
|
|
1545
|
+
recipient: current.snapshot.recipient,
|
|
1546
|
+
token: options.tokenAddress,
|
|
1547
|
+
})
|
|
1548
|
+
)
|
|
1549
|
+
throw new SubsidyEvidenceError()
|
|
1550
|
+
const result = await transitionIn(tx, {
|
|
1551
|
+
current,
|
|
1552
|
+
expectedVersion: current.version,
|
|
1553
|
+
id: current.id,
|
|
1554
|
+
// The database maps nested JSON keys to camelCase; preserve Tron raw_data for exact replay.
|
|
1555
|
+
providerState: {
|
|
1556
|
+
...current.providerState,
|
|
1557
|
+
transferSubsidy: JSON.stringify(signed),
|
|
1558
|
+
transferSubsidyOwnerId: settlement.transferId,
|
|
1559
|
+
},
|
|
1560
|
+
subsidyAccount: signed.account,
|
|
1561
|
+
subsidyAmount: null,
|
|
1562
|
+
subsidyChainId: signed.chainId,
|
|
1563
|
+
subsidyCommitmentAmount: null,
|
|
1564
|
+
subsidyNativeAmount: null,
|
|
1565
|
+
subsidyTokenAddress: settlement.tokenAddress,
|
|
1566
|
+
subsidyTransactionHash: signed.hash,
|
|
1567
|
+
})
|
|
1568
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1569
|
+
return { record: result.record, references: result.references, signed, type: 'shared' }
|
|
1570
|
+
}
|
|
1571
|
+
await RoutesTransferSubsidyNonces.lockAvailableIn(tx, {
|
|
1572
|
+
account: options.account,
|
|
1573
|
+
chainId: options.chainId,
|
|
1574
|
+
}).catch((cause) => {
|
|
1575
|
+
if (cause instanceof RoutesTransferSubsidyNonces.BlockedError)
|
|
1576
|
+
throw new SubsidySignerBlockedError()
|
|
1577
|
+
throw cause
|
|
1578
|
+
})
|
|
1579
|
+
const reservations = await RoutesTransfers.subsidyReservations(tx, {
|
|
1580
|
+
account: options.account,
|
|
1581
|
+
chainId: options.chainId,
|
|
1582
|
+
excludeId: current.id,
|
|
1583
|
+
tokenAddress: options.tokenAddress,
|
|
1584
|
+
})
|
|
1585
|
+
const prepared = await options.prepare({ reservations })
|
|
1586
|
+
if (
|
|
1587
|
+
!TronTransferSubsidy.matchesTerms(prepared, {
|
|
1588
|
+
account: options.account,
|
|
1589
|
+
amount: BigInt(options.subsidyAmount.baseUnits),
|
|
1590
|
+
chainId: options.chainId,
|
|
1591
|
+
recipient: current.snapshot.recipient,
|
|
1592
|
+
token: options.tokenAddress,
|
|
1593
|
+
})
|
|
1594
|
+
)
|
|
1595
|
+
throw new SubsidyEvidenceError()
|
|
1596
|
+
const result = await transitionIn(tx, {
|
|
1597
|
+
current,
|
|
1598
|
+
expectedVersion: current.version,
|
|
1599
|
+
id: current.id,
|
|
1600
|
+
// Keep the native transaction bytes and Horcrux request field names intact across database round trips.
|
|
1601
|
+
providerState: {
|
|
1602
|
+
...current.providerState,
|
|
1603
|
+
tronTransferSubsidyPrepared: JSON.stringify(prepared),
|
|
1604
|
+
},
|
|
1605
|
+
subsidyAccount: options.account,
|
|
1606
|
+
subsidyAmount: options.subsidyAmount,
|
|
1607
|
+
subsidyChainId: options.chainId,
|
|
1608
|
+
subsidyNativeAmount: prepared.nativeAmount,
|
|
1609
|
+
subsidyTokenAddress: options.tokenAddress,
|
|
1610
|
+
})
|
|
1611
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1612
|
+
return { prepared, record: result.record, references: result.references, type: 'prepared' }
|
|
1613
|
+
})
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
export declare namespace prepareTronSubsidy {
|
|
1617
|
+
/** Tron subsidy preparation under the organization and signer locks. */
|
|
1618
|
+
type Options = {
|
|
1619
|
+
/** Horcrux-managed Tron account. */
|
|
1620
|
+
account: string
|
|
1621
|
+
/** Destination chain identifier. */
|
|
1622
|
+
chainId: string
|
|
1623
|
+
/** Route transfer identifier. */
|
|
1624
|
+
id: string
|
|
1625
|
+
/** Owning organization identifier. */
|
|
1626
|
+
orgId: string
|
|
1627
|
+
/** Builds an unsigned transaction against reserved inventory. */
|
|
1628
|
+
prepare: (options: {
|
|
1629
|
+
reservations: RoutesTransfers.subsidyReservations.Result
|
|
1630
|
+
}) => Promise<TronTransferSubsidy.Prepared>
|
|
1631
|
+
/** Subsidy amount approved by policy. */
|
|
1632
|
+
subsidyAmount: NonNullable<Snapshot['destinationAmountRequired']>
|
|
1633
|
+
/** Tron USDT contract address. */
|
|
1634
|
+
tokenAddress: string
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
/** Durable preparation or existing signed settlement. */
|
|
1638
|
+
type Result =
|
|
1639
|
+
| { current: RoutesTransfers.Record; type: 'invalid' }
|
|
1640
|
+
| { type: 'not_found' }
|
|
1641
|
+
| {
|
|
1642
|
+
prepared: TronTransferSubsidy.Prepared
|
|
1643
|
+
record: RoutesTransfers.Record
|
|
1644
|
+
references?: readonly Webhooks.QueueReference[] | undefined
|
|
1645
|
+
type: 'prepared'
|
|
1646
|
+
}
|
|
1647
|
+
| { record: RoutesTransfers.Record; signed: TronTransferSubsidy.Signed; type: 'signed' }
|
|
1648
|
+
| {
|
|
1649
|
+
record: RoutesTransfers.Record
|
|
1650
|
+
references: readonly Webhooks.QueueReference[]
|
|
1651
|
+
signed: TronTransferSubsidy.Signed
|
|
1652
|
+
type: 'shared'
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
/** Persists a verified Tron signature before broadcasting the transaction. */
|
|
1657
|
+
export async function signTronSubsidy(
|
|
1658
|
+
db: Db.Db,
|
|
1659
|
+
options: signTronSubsidy.Options,
|
|
1660
|
+
): Promise<signTronSubsidy.Result> {
|
|
1661
|
+
return db.transaction(async (tx) => {
|
|
1662
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
1663
|
+
if (!current) return { type: 'not_found' }
|
|
1664
|
+
if (current.status !== 'processing') return { current, type: 'invalid' }
|
|
1665
|
+
const existing = TronTransferSubsidy.readSigned(current.providerState?.['transferSubsidy'])
|
|
1666
|
+
if (existing) return { record: current, signed: existing, type: 'replayed' }
|
|
1667
|
+
const prepared = TronTransferSubsidy.readPrepared(
|
|
1668
|
+
current.providerState?.['tronTransferSubsidyPrepared'],
|
|
1669
|
+
)
|
|
1670
|
+
if (
|
|
1671
|
+
!prepared ||
|
|
1672
|
+
prepared.hash !== options.signed.hash ||
|
|
1673
|
+
prepared.account !== options.signed.account ||
|
|
1674
|
+
prepared.amount !== options.signed.amount ||
|
|
1675
|
+
prepared.chainId !== options.signed.chainId ||
|
|
1676
|
+
!TronTransferSubsidy.matchesTerms(options.signed, {
|
|
1677
|
+
account: prepared.account,
|
|
1678
|
+
amount: BigInt(prepared.amount),
|
|
1679
|
+
chainId: prepared.chainId,
|
|
1680
|
+
recipient: current.snapshot.recipient,
|
|
1681
|
+
token: current.snapshot.destinationToken.address,
|
|
1682
|
+
})
|
|
1683
|
+
)
|
|
1684
|
+
throw new SubsidyEvidenceError()
|
|
1685
|
+
const transactionRef = current.snapshot.sourceTransactionHashes?.[0]
|
|
1686
|
+
const source = transactionRef
|
|
1687
|
+
? await RoutesTransferTransactions.getSource(tx, {
|
|
1688
|
+
chainId: current.snapshot.sourceChain.id,
|
|
1689
|
+
transactionRef,
|
|
1690
|
+
transferId: current.id,
|
|
1691
|
+
})
|
|
1692
|
+
: undefined
|
|
1693
|
+
if (source?.transferId !== current.id) throw new SubsidyEvidenceError()
|
|
1694
|
+
const settlement = await RoutesTransferSubsidies.getForUpdateIn(tx, {
|
|
1695
|
+
sourceChainId: source.chainId,
|
|
1696
|
+
transactionRef: source.transactionRef,
|
|
1697
|
+
})
|
|
1698
|
+
const signed = settlement
|
|
1699
|
+
? TronTransferSubsidy.readSigned(settlement.transaction)
|
|
1700
|
+
: options.signed
|
|
1701
|
+
if (
|
|
1702
|
+
!signed ||
|
|
1703
|
+
(settlement &&
|
|
1704
|
+
(settlement.destinationChainId !== prepared.chainId ||
|
|
1705
|
+
settlement.recipient !== current.snapshot.recipient ||
|
|
1706
|
+
settlement.tokenAddress !== current.snapshot.destinationToken.address ||
|
|
1707
|
+
signed.amount !== prepared.amount))
|
|
1708
|
+
)
|
|
1709
|
+
throw new SubsidyEvidenceError()
|
|
1710
|
+
const result = await transitionIn(tx, {
|
|
1711
|
+
current,
|
|
1712
|
+
expectedVersion: current.version,
|
|
1713
|
+
id: current.id,
|
|
1714
|
+
providerState: {
|
|
1715
|
+
...current.providerState,
|
|
1716
|
+
transferSubsidy: JSON.stringify(signed),
|
|
1717
|
+
...(settlement ? { transferSubsidyOwnerId: settlement.transferId } : {}),
|
|
1718
|
+
},
|
|
1719
|
+
...(settlement
|
|
1720
|
+
? { subsidyAmount: null, subsidyCommitmentAmount: null, subsidyNativeAmount: null }
|
|
1721
|
+
: {}),
|
|
1722
|
+
subsidyTransactionHash: signed.hash,
|
|
1723
|
+
})
|
|
1724
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1725
|
+
return {
|
|
1726
|
+
record: result.record,
|
|
1727
|
+
references: result.references,
|
|
1728
|
+
signed,
|
|
1729
|
+
type: settlement ? 'shared' : 'signed',
|
|
1730
|
+
}
|
|
1731
|
+
})
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
export declare namespace signTronSubsidy {
|
|
1735
|
+
/** Signed transaction and owning route transfer. */
|
|
1736
|
+
type Options = { id: string; signed: TronTransferSubsidy.Signed }
|
|
1737
|
+
/** Persisted signed settlement or a stale transfer. */
|
|
1738
|
+
type Result =
|
|
1739
|
+
| { current: RoutesTransfers.Record; type: 'invalid' }
|
|
1740
|
+
| { type: 'not_found' }
|
|
1741
|
+
| { record: RoutesTransfers.Record; signed: TronTransferSubsidy.Signed; type: 'replayed' }
|
|
1742
|
+
| {
|
|
1743
|
+
record: RoutesTransfers.Record
|
|
1744
|
+
references: readonly Webhooks.QueueReference[]
|
|
1745
|
+
signed: TronTransferSubsidy.Signed
|
|
1746
|
+
type: 'shared' | 'signed'
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
|
|
957
1750
|
/** Atomically records a verified destination transaction and completes a transfer. */
|
|
958
1751
|
export async function complete(db: Db.Db, options: complete.Options): Promise<complete.Result> {
|
|
959
1752
|
return db.transaction(async (tx) => {
|
|
@@ -966,7 +1759,8 @@ export async function complete(db: Db.Db, options: complete.Options): Promise<co
|
|
|
966
1759
|
(transaction) =>
|
|
967
1760
|
transaction.chainId === options.chainId &&
|
|
968
1761
|
transaction.role === 'destination' &&
|
|
969
|
-
transaction.transactionRef ===
|
|
1762
|
+
transaction.transactionRef ===
|
|
1763
|
+
RoutesTransferTransactions.normalize(options.chainId, transactionHash),
|
|
970
1764
|
),
|
|
971
1765
|
)
|
|
972
1766
|
return existing ? { record: current, type: 'replayed' } : { current, type: 'invalid' }
|
|
@@ -1024,6 +1818,59 @@ export declare namespace complete {
|
|
|
1024
1818
|
| { type: 'not_found' }
|
|
1025
1819
|
}
|
|
1026
1820
|
|
|
1821
|
+
/**
|
|
1822
|
+
* Returns an `action-required` transfer to `processing` so reconciliation re-verifies it.
|
|
1823
|
+
* Refuses transfers holding a prepared or signed subsidy, which need on-chain recovery first.
|
|
1824
|
+
*/
|
|
1825
|
+
export async function retry(db: Db.Db, options: retry.Options): Promise<retry.Result> {
|
|
1826
|
+
return db.transaction(async (tx) => {
|
|
1827
|
+
const current = await RoutesTransfers.getForUpdate(tx, options.id)
|
|
1828
|
+
if (!current) return { type: 'not_found' }
|
|
1829
|
+
if (current.version !== options.expectedVersion) return { current, type: 'stale' }
|
|
1830
|
+
if (current.status !== 'action-required') return { current, type: 'invalid' }
|
|
1831
|
+
// A prepared or signed subsidy may still land; reconciling again could prepare a replacement.
|
|
1832
|
+
const state = current.providerState
|
|
1833
|
+
if (
|
|
1834
|
+
current.subsidyTransactionHash !== null ||
|
|
1835
|
+
state?.['transferSubsidy'] ||
|
|
1836
|
+
state?.['solanaTransferSubsidyPrepared'] ||
|
|
1837
|
+
state?.['tronTransferSubsidyPrepared']
|
|
1838
|
+
)
|
|
1839
|
+
return { current, type: 'subsidy_pending' }
|
|
1840
|
+
const result = await transitionIn(tx, {
|
|
1841
|
+
current,
|
|
1842
|
+
expectedVersion: current.version,
|
|
1843
|
+
id: current.id,
|
|
1844
|
+
status: 'processing',
|
|
1845
|
+
})
|
|
1846
|
+
if (result.type !== 'applied') throw new AtomicTransitionError()
|
|
1847
|
+
return {
|
|
1848
|
+
previous: current,
|
|
1849
|
+
record: result.record,
|
|
1850
|
+
references: result.references,
|
|
1851
|
+
type: 'retried',
|
|
1852
|
+
}
|
|
1853
|
+
})
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
export declare namespace retry {
|
|
1857
|
+
/** Transfer to retry. */
|
|
1858
|
+
type Options = {
|
|
1859
|
+
/** The version the operator reviewed. */
|
|
1860
|
+
expectedVersion: number
|
|
1861
|
+
/** Transfer id (`rtr_…`). */
|
|
1862
|
+
id: string
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
/** Transfer retry outcome. */
|
|
1866
|
+
type Result =
|
|
1867
|
+
| (Staged & { previous: RoutesTransfers.Record; type: 'retried' })
|
|
1868
|
+
| { current: RoutesTransfers.Record; type: 'invalid' }
|
|
1869
|
+
| { current: RoutesTransfers.Record; type: 'stale' }
|
|
1870
|
+
| { current: RoutesTransfers.Record; type: 'subsidy_pending' }
|
|
1871
|
+
| { type: 'not_found' }
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1027
1874
|
/**
|
|
1028
1875
|
* Applies a version-guarded material change: a status transition, a snapshot
|
|
1029
1876
|
* update, or both. The row update and its immutable event commit in one
|
|
@@ -1049,12 +1896,23 @@ async function transitionIn(
|
|
|
1049
1896
|
if (status !== current.status && !canTransition(current.status, status))
|
|
1050
1897
|
return { current, type: 'invalid' }
|
|
1051
1898
|
|
|
1899
|
+
// Provider evidence can be replaced or cleared after a reorg; accepted
|
|
1900
|
+
// financial terms remain immutable across every lifecycle transition.
|
|
1901
|
+
const routePolicy = Policy.commitment(current.providerState)
|
|
1902
|
+
let providerState =
|
|
1903
|
+
options.providerState === undefined ? current.providerState : options.providerState
|
|
1904
|
+
if (routePolicy)
|
|
1905
|
+
providerState = {
|
|
1906
|
+
...providerState,
|
|
1907
|
+
routePolicy,
|
|
1908
|
+
routePolicyKey: Policy.commitmentKey(routePolicy),
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1052
1911
|
const updated = await RoutesTransfers.update(tx, {
|
|
1053
1912
|
expectedVersion: options.expectedVersion,
|
|
1054
1913
|
id: options.id,
|
|
1055
1914
|
providerDeliveredAt: current.providerDeliveredAt,
|
|
1056
|
-
providerState
|
|
1057
|
-
options.providerState === undefined ? current.providerState : options.providerState,
|
|
1915
|
+
providerState,
|
|
1058
1916
|
snapshot: options.snapshot === undefined ? current.snapshot : parseSnapshot(options.snapshot),
|
|
1059
1917
|
status,
|
|
1060
1918
|
statusReason: options.statusReason ?? (status === current.status ? current.statusReason : null),
|