tapimo 0.0.2 → 0.2.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 +38 -16
- package/dist/ApiKey.d.ts +14 -11
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +11 -12
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +207 -0
- package/dist/ApiKeys.d.ts.map +1 -0
- package/dist/ApiKeys.js +282 -0
- package/dist/ApiKeys.js.map +1 -0
- package/dist/App.d.ts +6771 -3819
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +145 -317
- package/dist/App.js.map +1 -1
- package/dist/Handler.d.ts +86 -0
- package/dist/Handler.d.ts.map +1 -0
- package/dist/Handler.js +83 -0
- package/dist/Handler.js.map +1 -0
- package/dist/Scope.d.ts +14 -4
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +16 -4
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +5 -7
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +11 -4
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/Access.d.ts +1 -3
- package/dist/admin/Access.d.ts.map +1 -1
- package/dist/admin/Access.js +1 -3
- package/dist/admin/Access.js.map +1 -1
- package/dist/admin/App.d.ts +167 -205
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +2 -4
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +105 -5
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +75 -9
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +6 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +35 -149
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +18 -39
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +1 -1
- package/dist/apps/data/App.d.ts +19176 -0
- package/dist/apps/data/App.d.ts.map +1 -0
- package/dist/apps/data/App.js +236 -0
- package/dist/apps/data/App.js.map +1 -0
- package/dist/apps/data/index.d.ts +3 -0
- package/dist/apps/data/index.d.ts.map +1 -0
- package/dist/apps/data/index.js +3 -0
- package/dist/apps/data/index.js.map +1 -0
- package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
- package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
- package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
- package/dist/apps/data/routes/activities.js.map +1 -0
- package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
- package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
- package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
- package/dist/apps/data/routes/addresses.js.map +1 -0
- package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +49 -49
- package/dist/apps/data/routes/balances.d.ts.map +1 -0
- package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
- package/dist/apps/data/routes/balances.js.map +1 -0
- package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
- package/dist/apps/data/routes/blocks.d.ts.map +1 -0
- package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
- package/dist/apps/data/routes/blocks.js.map +1 -0
- package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +183 -183
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
- package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
- package/dist/apps/data/routes/coingecko.js.map +1 -0
- package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +460 -460
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
- package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
- package/dist/apps/data/routes/exchanges.js.map +1 -0
- package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +94 -94
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
- package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
- package/dist/apps/data/routes/fee-amm.js.map +1 -0
- package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
- package/dist/apps/data/routes/indexer.d.ts.map +1 -0
- package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
- package/dist/apps/data/routes/indexer.js.map +1 -0
- package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +6 -6
- package/dist/apps/data/routes/receipts.d.ts.map +1 -0
- package/dist/apps/{receipts.js → data/routes/receipts.js} +12 -12
- package/dist/apps/data/routes/receipts.js.map +1 -0
- package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +4 -4
- package/dist/apps/data/routes/rpc.d.ts.map +1 -0
- package/dist/apps/{rpc.js → data/routes/rpc.js} +6 -6
- package/dist/apps/data/routes/rpc.js.map +1 -0
- package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +4 -4
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
- package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
- package/dist/apps/data/routes/tokenlist.js.map +1 -0
- package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +11 -11
- package/dist/apps/data/routes/tokens.d.ts.map +1 -0
- package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
- package/dist/apps/data/routes/tokens.js.map +1 -0
- package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +288 -288
- package/dist/apps/data/routes/transactions.d.ts.map +1 -0
- package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
- package/dist/apps/data/routes/transactions.js.map +1 -0
- package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +35 -35
- package/dist/apps/data/routes/transfers.d.ts.map +1 -0
- package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
- package/dist/apps/data/routes/transfers.js.map +1 -0
- package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +42 -42
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
- package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
- package/dist/apps/data/routes/verified-tokens.js.map +1 -0
- package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +66 -63
- package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
- package/dist/apps/{webhooks.js → data/routes/webhooks.js} +67 -59
- package/dist/apps/data/routes/webhooks.js.map +1 -0
- package/dist/apps/docs/App.d.ts +27 -0
- package/dist/apps/docs/App.d.ts.map +1 -0
- package/dist/apps/docs/App.js +122 -0
- package/dist/apps/docs/App.js.map +1 -0
- package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
- package/dist/apps/docs/fonts.d.ts.map +1 -0
- package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
- package/dist/apps/docs/fonts.js.map +1 -0
- package/dist/apps/docs/index.d.ts +2 -0
- package/dist/apps/docs/index.d.ts.map +1 -0
- package/dist/apps/docs/index.js +2 -0
- package/dist/apps/docs/index.js.map +1 -0
- package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
- package/dist/apps/docs/logo.d.ts.map +1 -0
- package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
- package/dist/apps/docs/logo.js.map +1 -0
- package/dist/apps/index.d.ts +4 -0
- package/dist/apps/index.d.ts.map +1 -0
- package/dist/apps/index.js +4 -0
- package/dist/apps/index.js.map +1 -0
- package/dist/apps/metadata.d.ts +7 -0
- package/dist/apps/metadata.d.ts.map +1 -0
- package/dist/apps/metadata.js +15 -0
- package/dist/apps/metadata.js.map +1 -0
- package/dist/apps/platform/App.d.ts +2985 -0
- package/dist/apps/platform/App.d.ts.map +1 -0
- package/dist/apps/platform/App.js +74 -0
- package/dist/apps/platform/App.js.map +1 -0
- package/dist/apps/platform/index.d.ts +2 -0
- package/dist/apps/platform/index.d.ts.map +1 -0
- package/dist/apps/platform/index.js +2 -0
- package/dist/apps/platform/index.js.map +1 -0
- package/dist/apps/platform/routes/api-keys.d.ts +681 -0
- package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/platform/routes/api-keys.js +328 -0
- package/dist/apps/platform/routes/api-keys.js.map +1 -0
- package/dist/apps/platform/routes/invitations.d.ts +733 -0
- package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
- package/dist/apps/platform/routes/invitations.js +413 -0
- package/dist/apps/platform/routes/invitations.js.map +1 -0
- package/dist/apps/platform/routes/me.d.ts +95 -0
- package/dist/apps/platform/routes/me.d.ts.map +1 -0
- package/dist/apps/platform/routes/me.js +81 -0
- package/dist/apps/platform/routes/me.js.map +1 -0
- package/dist/apps/platform/routes/members.d.ts +554 -0
- package/dist/apps/platform/routes/members.d.ts.map +1 -0
- package/dist/apps/platform/routes/members.js +251 -0
- package/dist/apps/platform/routes/members.js.map +1 -0
- package/dist/apps/platform/routes/orgs.d.ts +582 -0
- package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
- package/dist/apps/platform/routes/orgs.js +265 -0
- package/dist/apps/platform/routes/orgs.js.map +1 -0
- package/dist/apps/platform/routes/projects.d.ts +740 -0
- package/dist/apps/platform/routes/projects.d.ts.map +1 -0
- package/dist/apps/platform/routes/projects.js +286 -0
- package/dist/apps/platform/routes/projects.js.map +1 -0
- package/dist/apps/relay/App.d.ts +41 -0
- package/dist/apps/relay/App.d.ts.map +1 -0
- package/dist/apps/relay/App.js +103 -0
- package/dist/apps/relay/App.js.map +1 -0
- package/dist/apps/relay/Sponsorships.d.ts +107 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
- package/dist/apps/relay/Sponsorships.js +193 -0
- package/dist/apps/relay/Sponsorships.js.map +1 -0
- package/dist/apps/relay/index.d.ts +3 -0
- package/dist/apps/relay/index.d.ts.map +1 -0
- package/dist/apps/relay/index.js +3 -0
- package/dist/apps/relay/index.js.map +1 -0
- package/dist/{Cli.d.ts → cli/Cli.d.ts} +13 -2
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +19 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +15 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +60 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cloudflare.d.ts +7 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +9 -0
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +113 -0
- package/dist/db/Db.d.ts.map +1 -0
- package/dist/db/Db.js +402 -0
- package/dist/db/Db.js.map +1 -0
- package/dist/db/Schema.d.ts +168 -0
- package/dist/db/Schema.d.ts.map +1 -0
- package/dist/db/Schema.js +229 -0
- package/dist/db/Schema.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +84 -0
- package/dist/db/tables/invitations.d.ts.map +1 -0
- package/dist/db/tables/invitations.js +165 -0
- package/dist/db/tables/invitations.js.map +1 -0
- package/dist/db/tables/memberships.d.ts +108 -0
- package/dist/db/tables/memberships.d.ts.map +1 -0
- package/dist/db/tables/memberships.js +153 -0
- package/dist/db/tables/memberships.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +123 -0
- package/dist/db/tables/organizations.d.ts.map +1 -0
- package/dist/db/tables/organizations.js +170 -0
- package/dist/db/tables/organizations.js.map +1 -0
- package/dist/db/tables/projects.d.ts +65 -0
- package/dist/db/tables/projects.d.ts.map +1 -0
- package/dist/db/tables/projects.js +75 -0
- package/dist/db/tables/projects.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +120 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
- package/dist/db/tables/sponsoredTransactions.js +161 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -0
- package/dist/db/tables/users.d.ts +48 -0
- package/dist/db/tables/users.d.ts.map +1 -0
- package/dist/db/tables/users.js +65 -0
- package/dist/db/tables/users.js.map +1 -0
- package/dist/db/tables/verifiedTokens.d.ts +53 -0
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokens.js +74 -0
- package/dist/db/tables/verifiedTokens.js.map +1 -0
- package/dist/db/tables/webhookDeliveries.d.ts +71 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
- package/dist/db/tables/webhookDeliveries.js +119 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
- package/dist/db/tables/webhookSubscriptions.js +272 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts +25 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -0
- package/dist/handlers/internal/executionError.js +186 -0
- package/dist/handlers/internal/executionError.js.map +1 -0
- package/dist/handlers/internal/multisig.d.ts +233 -0
- package/dist/handlers/internal/multisig.d.ts.map +1 -0
- package/dist/handlers/internal/multisig.js +542 -0
- package/dist/handlers/internal/multisig.js.map +1 -0
- package/dist/handlers/internal/requestListener.d.ts +124 -0
- package/dist/handlers/internal/requestListener.d.ts.map +1 -0
- package/dist/handlers/internal/requestListener.js +173 -0
- package/dist/handlers/internal/requestListener.js.map +1 -0
- package/dist/handlers/internal/sponsorship.d.ts +113 -0
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
- package/dist/handlers/internal/sponsorship.js +128 -0
- package/dist/handlers/internal/sponsorship.js.map +1 -0
- package/dist/handlers/internal/types.d.ts +284 -0
- package/dist/handlers/internal/types.d.ts.map +1 -0
- package/dist/handlers/internal/types.js +2 -0
- package/dist/handlers/internal/types.js.map +1 -0
- package/dist/handlers/internal/utils.d.ts +34 -0
- package/dist/handlers/internal/utils.d.ts.map +1 -0
- package/dist/handlers/internal/utils.js +131 -0
- package/dist/handlers/internal/utils.js.map +1 -0
- package/dist/handlers/relay.d.ts +123 -0
- package/dist/handlers/relay.d.ts.map +1 -0
- package/dist/handlers/relay.js +1278 -0
- package/dist/handlers/relay.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +224 -16
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +572 -33
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +4 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +0 -19
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +0 -57
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RpcSchema.d.ts +10 -0
- package/dist/internal/RpcSchema.d.ts.map +1 -0
- package/dist/internal/RpcSchema.js +2 -0
- package/dist/internal/RpcSchema.js.map +1 -0
- package/dist/internal/Store.d.ts +49 -4
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +81 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts +15 -34
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +115 -159
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Viem.d.ts +84 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Webhooks.d.ts +50 -36
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +92 -205
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +37 -6
- package/src/ApiKey.test.ts +3 -3
- package/src/ApiKey.ts +11 -12
- package/src/ApiKeys.test.ts +278 -0
- package/src/ApiKeys.ts +358 -0
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +40508 -19083
- package/src/App.ts +239 -416
- package/src/Client.test-d.ts +307 -16
- package/src/Handler.ts +154 -0
- package/src/Scope.ts +17 -4
- package/src/Webhooks.test.ts +8 -7
- package/src/Webhooks.ts +13 -7
- package/src/admin/Access.ts +1 -3
- package/src/admin/App.ts +19 -24
- package/src/admin/apps/api-keys.test.ts +70 -18
- package/src/admin/apps/api-keys.ts +92 -9
- package/src/admin/apps/scopes.test.ts +8 -0
- package/src/admin/apps/verified-tokens.test.ts +3 -30
- package/src/admin/apps/verified-tokens.ts +18 -37
- package/src/admin/ui.generated.ts +1 -1
- package/src/apps/composition.test.ts +66 -0
- package/src/apps/data/App.ts +295 -0
- package/src/apps/data/index.ts +2 -0
- package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
- package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
- package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
- package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +6 -5
- package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
- package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +4 -4
- package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
- package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
- package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
- package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +2 -2
- package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
- package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
- package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
- package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +27 -6
- package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
- package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +4 -4
- package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
- package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +142 -13
- package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
- package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +8 -10
- package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
- package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +6 -5
- package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
- package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +4 -4
- package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
- package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +3 -3
- package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
- package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +27 -15
- package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
- package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +137 -150
- package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +83 -81
- package/src/apps/docs/App.ts +136 -0
- package/src/apps/docs/index.ts +1 -0
- package/src/apps/index.ts +3 -0
- package/src/apps/metadata.ts +23 -0
- package/src/apps/platform/App.ts +130 -0
- package/src/apps/platform/index.ts +1 -0
- package/src/apps/platform/routes/api-keys.test.ts +330 -0
- package/src/apps/platform/routes/api-keys.ts +427 -0
- package/src/apps/platform/routes/invitations.test.ts +361 -0
- package/src/apps/platform/routes/invitations.ts +519 -0
- package/src/apps/platform/routes/me.test.ts +121 -0
- package/src/apps/platform/routes/me.ts +106 -0
- package/src/apps/platform/routes/members.test.ts +195 -0
- package/src/apps/platform/routes/members.ts +313 -0
- package/src/apps/platform/routes/orgs.test.ts +313 -0
- package/src/apps/platform/routes/orgs.ts +343 -0
- package/src/apps/platform/routes/projects.test.ts +181 -0
- package/src/apps/platform/routes/projects.ts +367 -0
- package/src/apps/relay/App.test.ts +484 -0
- package/src/apps/relay/App.ts +128 -0
- package/src/apps/relay/Sponsorships.test.ts +375 -0
- package/src/apps/relay/Sponsorships.ts +305 -0
- package/src/apps/relay/index.ts +2 -0
- package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
- package/src/{Cli.ts → cli/Cli.ts} +16 -9
- package/src/cli/bin.ts +4 -0
- package/src/cli/commands/admin.test.ts +71 -0
- package/src/cli/commands/admin.ts +60 -0
- package/src/cloudflare.ts +10 -0
- package/src/db/Db.test.ts +84 -0
- package/src/db/Db.ts +542 -0
- package/src/db/Schema.ts +301 -0
- package/src/db/tables/invitations.ts +198 -0
- package/src/db/tables/memberships.ts +208 -0
- package/src/db/tables/organizations.test.ts +160 -0
- package/src/db/tables/organizations.ts +232 -0
- package/src/db/tables/projects.ts +107 -0
- package/src/db/tables/sponsoredTransactions.test.ts +218 -0
- package/src/db/tables/sponsoredTransactions.ts +236 -0
- package/src/db/tables/users.ts +85 -0
- package/src/db/tables/verifiedTokens.ts +111 -0
- package/src/db/tables/webhookDeliveries.ts +159 -0
- package/src/db/tables/webhookSubscriptions.ts +358 -0
- package/src/handlers/internal/executionError.ts +207 -0
- package/src/handlers/internal/multisig.test.ts +818 -0
- package/src/handlers/internal/multisig.ts +823 -0
- package/src/handlers/internal/requestListener.ts +273 -0
- package/src/handlers/internal/sponsorship.ts +245 -0
- package/src/handlers/internal/types.ts +378 -0
- package/src/handlers/internal/utils.ts +153 -0
- package/src/handlers/relay.test.ts +2035 -0
- package/src/handlers/relay.ts +1623 -0
- package/src/index.ts +4 -2
- package/src/internal/Auth.test.ts +337 -21
- package/src/internal/Auth.ts +783 -44
- package/src/internal/Cursor.test.ts +3 -2
- package/src/internal/Log.test.ts +1 -1
- package/src/internal/Log.ts +11 -3
- package/src/internal/MetricSink.ts +1 -1
- package/src/internal/OpenApi.ts +0 -59
- package/src/internal/RateLimit.test.ts +1 -1
- package/src/internal/RpcSchema.ts +10 -0
- package/src/internal/Store.test.ts +150 -10
- package/src/internal/Store.ts +136 -11
- package/src/internal/Tidx.local.test.ts +1 -1
- package/src/internal/VerifiedTokens.test.ts +99 -115
- package/src/internal/VerifiedTokens.ts +123 -175
- package/src/internal/WebhookDestination.test.ts +1 -1
- package/src/internal/Webhooks.test.ts +111 -111
- package/src/internal/Webhooks.ts +103 -221
- package/dist/ApiKeySource.d.ts +0 -166
- package/dist/ApiKeySource.d.ts.map +0 -1
- package/dist/ApiKeySource.js +0 -234
- package/dist/ApiKeySource.js.map +0 -1
- package/dist/Cli.d.ts.map +0 -1
- package/dist/Cli.js +0 -13
- package/dist/Cli.js.map +0 -1
- package/dist/apps/activities.js.map +0 -1
- package/dist/apps/addresses.js.map +0 -1
- package/dist/apps/balances.d.ts.map +0 -1
- package/dist/apps/balances.js.map +0 -1
- package/dist/apps/blocks.d.ts.map +0 -1
- package/dist/apps/blocks.js.map +0 -1
- package/dist/apps/coingecko.d.ts.map +0 -1
- package/dist/apps/coingecko.js.map +0 -1
- package/dist/apps/exchanges.d.ts.map +0 -1
- package/dist/apps/exchanges.js.map +0 -1
- package/dist/apps/fee-amm.d.ts.map +0 -1
- package/dist/apps/fee-amm.js.map +0 -1
- package/dist/apps/indexer.d.ts.map +0 -1
- package/dist/apps/indexer.js.map +0 -1
- package/dist/apps/receipts.d.ts.map +0 -1
- package/dist/apps/receipts.js.map +0 -1
- package/dist/apps/rpc.d.ts.map +0 -1
- package/dist/apps/rpc.js.map +0 -1
- package/dist/apps/tokenlist.d.ts.map +0 -1
- package/dist/apps/tokenlist.js.map +0 -1
- package/dist/apps/tokens.d.ts.map +0 -1
- package/dist/apps/tokens.js.map +0 -1
- package/dist/apps/transactions.d.ts.map +0 -1
- package/dist/apps/transactions.js.map +0 -1
- package/dist/apps/transfers.d.ts.map +0 -1
- package/dist/apps/transfers.js.map +0 -1
- package/dist/apps/verified-tokens.d.ts.map +0 -1
- package/dist/apps/verified-tokens.js.map +0 -1
- package/dist/apps/webhooks.js.map +0 -1
- package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
- package/dist/internal/OpenApi.fonts.js.map +0 -1
- package/dist/internal/OpenApi.logo.d.ts.map +0 -1
- package/dist/internal/OpenApi.logo.js.map +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/31318/verified-tokens.json +0 -30
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +0 -177
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
- package/seeds/42431/verified-tokens.json +0 -44
- package/seeds/openrpc/README.md +0 -27
- package/seeds/openrpc/execution-apis.json +0 -8989
- package/src/ApiKeySource.test-d.ts +0 -11
- package/src/ApiKeySource.test.ts +0 -295
- package/src/ApiKeySource.ts +0 -303
- /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
- /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid'
|
|
2
|
+
|
|
3
|
+
import { postgresUrl } from '../../../test/containers.js'
|
|
4
|
+
import * as Db from '../Db.js'
|
|
5
|
+
import * as SponsoredTransactions from './sponsoredTransactions.js'
|
|
6
|
+
|
|
7
|
+
const create = () => Db.postgres({ connectionString: postgresUrl, schema: `t_${nanoid()}` })
|
|
8
|
+
|
|
9
|
+
/** Baseline insert input; tests override per case. */
|
|
10
|
+
const input = {
|
|
11
|
+
apiKeyId: 'key_1',
|
|
12
|
+
billable: true,
|
|
13
|
+
chainId: 42431,
|
|
14
|
+
environment: 'production',
|
|
15
|
+
orgId: 'org_1',
|
|
16
|
+
projectId: 'prj_1',
|
|
17
|
+
signPayload: `0x${'bb'.repeat(32)}`,
|
|
18
|
+
transaction: `0x76${'cc'.repeat(16)}`,
|
|
19
|
+
transactionHash: `0x${'aa'.repeat(32)}`,
|
|
20
|
+
} satisfies SponsoredTransactions.upsert.Input
|
|
21
|
+
|
|
22
|
+
/** Redacts nondeterministic row fields (generated nanoid ids, timestamps). */
|
|
23
|
+
function redact(record: SponsoredTransactions.Record) {
|
|
24
|
+
return {
|
|
25
|
+
...record,
|
|
26
|
+
createdAt: '<timestamp>',
|
|
27
|
+
finalizedAt: record.finalizedAt === null ? null : '<timestamp>',
|
|
28
|
+
id: /^stx_[\w-]{21}$/.test(record.id) ? 'stx_<id>' : record.id,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('upsert', () => {
|
|
33
|
+
test('behavior: records a pending sponsorship with a generated id', async () => {
|
|
34
|
+
const db = create()
|
|
35
|
+
await db.migrate()
|
|
36
|
+
const record = await SponsoredTransactions.upsert(db, input)
|
|
37
|
+
expect(record.id).toMatch(/^stx_/)
|
|
38
|
+
expect(redact(record)).toMatchInlineSnapshot(`
|
|
39
|
+
{
|
|
40
|
+
"apiKeyId": "key_1",
|
|
41
|
+
"billable": true,
|
|
42
|
+
"chainId": 42431,
|
|
43
|
+
"createdAt": "<timestamp>",
|
|
44
|
+
"environment": "production",
|
|
45
|
+
"feeAmount": null,
|
|
46
|
+
"feeToken": null,
|
|
47
|
+
"finalizedAt": null,
|
|
48
|
+
"id": "stx_<id>",
|
|
49
|
+
"orgId": "org_1",
|
|
50
|
+
"projectId": "prj_1",
|
|
51
|
+
"signPayload": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
52
|
+
"status": "pending",
|
|
53
|
+
"transaction": "0x76cccccccccccccccccccccccccccccccc",
|
|
54
|
+
"transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
55
|
+
}
|
|
56
|
+
`)
|
|
57
|
+
expect(await SponsoredTransactions.get(db, record.id)).toStrictEqual(record)
|
|
58
|
+
await db.close()
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('behavior: preserves an explicit fee token', async () => {
|
|
62
|
+
const db = create()
|
|
63
|
+
await db.migrate()
|
|
64
|
+
const record = await SponsoredTransactions.upsert(db, { ...input, feeToken: `0x${'fe'.repeat(20)}` }) // prettier-ignore
|
|
65
|
+
expect(record.feeToken).toMatchInlineSnapshot(`"0xfefefefefefefefefefefefefefefefefefefefe"`)
|
|
66
|
+
await db.close()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('behavior: records fill intents without a transaction hash', async () => {
|
|
70
|
+
const db = create()
|
|
71
|
+
await db.migrate()
|
|
72
|
+
const { transactionHash: _, ...intent } = input
|
|
73
|
+
const record = await SponsoredTransactions.upsert(db, intent)
|
|
74
|
+
expect(record.transactionHash).toBeNull()
|
|
75
|
+
expect(record.status).toMatchInlineSnapshot(`"pending"`)
|
|
76
|
+
await db.close()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('behavior: a raw submission upgrades a fill intent in place', async () => {
|
|
80
|
+
const db = create()
|
|
81
|
+
await db.migrate()
|
|
82
|
+
const { transactionHash: _, ...intent } = input
|
|
83
|
+
const first = await SponsoredTransactions.upsert(db, intent)
|
|
84
|
+
const second = await SponsoredTransactions.upsert(db, input)
|
|
85
|
+
|
|
86
|
+
// Same commitment, one row: the raw record fills the intent's hash.
|
|
87
|
+
expect(second.id).toBe(first.id)
|
|
88
|
+
expect(second.transactionHash).toMatchInlineSnapshot(
|
|
89
|
+
`"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
|
|
90
|
+
)
|
|
91
|
+
expect(await SponsoredTransactions.listPending(db)).toHaveLength(1)
|
|
92
|
+
await db.close()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('behavior: a raw submission reopens a failed fill intent', async () => {
|
|
96
|
+
const db = create()
|
|
97
|
+
await db.migrate()
|
|
98
|
+
const { transactionHash: _, ...intent } = input
|
|
99
|
+
const first = await SponsoredTransactions.upsert(db, intent)
|
|
100
|
+
await SponsoredTransactions.fail(db, first.id, '2026-01-01T00:00:00.000Z')
|
|
101
|
+
|
|
102
|
+
const second = await SponsoredTransactions.upsert(db, input)
|
|
103
|
+
|
|
104
|
+
expect(second.id).toBe(first.id)
|
|
105
|
+
expect(second.status).toMatchInlineSnapshot(`"pending"`)
|
|
106
|
+
expect(second.finalizedAt).toBeNull()
|
|
107
|
+
expect(second.transactionHash).toMatchInlineSnapshot(
|
|
108
|
+
`"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
|
|
109
|
+
)
|
|
110
|
+
expect(await SponsoredTransactions.listPending(db)).toHaveLength(1)
|
|
111
|
+
await db.close()
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('behavior: a duplicate intent never clears a known hash', async () => {
|
|
115
|
+
const db = create()
|
|
116
|
+
await db.migrate()
|
|
117
|
+
const first = await SponsoredTransactions.upsert(db, input)
|
|
118
|
+
const { transactionHash: _, ...intent } = input
|
|
119
|
+
const second = await SponsoredTransactions.upsert(db, intent)
|
|
120
|
+
|
|
121
|
+
expect(second.id).toBe(first.id)
|
|
122
|
+
expect(second.transactionHash).toMatchInlineSnapshot(
|
|
123
|
+
`"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
|
|
124
|
+
)
|
|
125
|
+
await db.close()
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
describe('listPending', () => {
|
|
130
|
+
test('behavior: returns only pending rows, capped by limit', async () => {
|
|
131
|
+
const db = create()
|
|
132
|
+
await db.migrate()
|
|
133
|
+
await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b1'.repeat(32)}`, transactionHash: `0x${'a1'.repeat(32)}` }) // prettier-ignore
|
|
134
|
+
const second = await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b2'.repeat(32)}`, transactionHash: `0x${'a2'.repeat(32)}` }) // prettier-ignore
|
|
135
|
+
await SponsoredTransactions.upsert(db, { ...input, signPayload: `0x${'b3'.repeat(32)}`, transactionHash: `0x${'a3'.repeat(32)}` }) // prettier-ignore
|
|
136
|
+
await SponsoredTransactions.finalize(db, second.id, {
|
|
137
|
+
feeAmount: '100',
|
|
138
|
+
finalizedAt: new Date().toISOString(),
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const pending = await SponsoredTransactions.listPending(db)
|
|
142
|
+
// Inserts can share a millisecond, so assert membership, not order.
|
|
143
|
+
expect(pending.map((row) => row.transactionHash).sort()).toMatchInlineSnapshot(`
|
|
144
|
+
[
|
|
145
|
+
"0xa1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
|
|
146
|
+
"0xa3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3",
|
|
147
|
+
]
|
|
148
|
+
`)
|
|
149
|
+
expect(await SponsoredTransactions.listPending(db, { limit: 1 })).toHaveLength(1)
|
|
150
|
+
await db.close()
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
describe('assignTransactionHash', () => {
|
|
155
|
+
test('behavior: reopens a failed intent when reconciliation finds its hash', async () => {
|
|
156
|
+
const db = create()
|
|
157
|
+
await db.migrate()
|
|
158
|
+
const { transactionHash: _, ...intent } = input
|
|
159
|
+
const record = await SponsoredTransactions.upsert(db, intent)
|
|
160
|
+
await SponsoredTransactions.fail(db, record.id, '2026-01-01T00:00:00.000Z')
|
|
161
|
+
|
|
162
|
+
await SponsoredTransactions.assignTransactionHash(db, record.id, input.transactionHash)
|
|
163
|
+
|
|
164
|
+
const assigned = await SponsoredTransactions.get(db, record.id)
|
|
165
|
+
expect(assigned?.status).toMatchInlineSnapshot(`"pending"`)
|
|
166
|
+
expect(assigned?.finalizedAt).toBeNull()
|
|
167
|
+
expect(assigned?.transactionHash).toMatchInlineSnapshot(
|
|
168
|
+
`"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"`,
|
|
169
|
+
)
|
|
170
|
+
await db.close()
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
describe('finalize', () => {
|
|
175
|
+
test('behavior: transitions pending → finalized with the actual fee', async () => {
|
|
176
|
+
const db = create()
|
|
177
|
+
await db.migrate()
|
|
178
|
+
const record = await SponsoredTransactions.upsert(db, input)
|
|
179
|
+
await SponsoredTransactions.finalize(db, record.id, {
|
|
180
|
+
feeAmount: '21000',
|
|
181
|
+
finalizedAt: '2026-01-01T00:00:00.000Z',
|
|
182
|
+
})
|
|
183
|
+
const finalized = await SponsoredTransactions.get(db, record.id)
|
|
184
|
+
expect(finalized?.status).toMatchInlineSnapshot(`"finalized"`)
|
|
185
|
+
expect(finalized?.feeAmount).toMatchInlineSnapshot(`"21000"`)
|
|
186
|
+
expect(finalized?.finalizedAt).toMatchInlineSnapshot(`"2026-01-01T00:00:00.000Z"`)
|
|
187
|
+
await db.close()
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('behavior: no-op on rows that are no longer pending', async () => {
|
|
191
|
+
const db = create()
|
|
192
|
+
await db.migrate()
|
|
193
|
+
const record = await SponsoredTransactions.upsert(db, input)
|
|
194
|
+
await SponsoredTransactions.fail(db, record.id, '2026-01-01T00:00:00.000Z')
|
|
195
|
+
await SponsoredTransactions.finalize(db, record.id, {
|
|
196
|
+
feeAmount: '21000',
|
|
197
|
+
finalizedAt: '2026-01-02T00:00:00.000Z',
|
|
198
|
+
})
|
|
199
|
+
const row = await SponsoredTransactions.get(db, record.id)
|
|
200
|
+
expect(row?.status).toMatchInlineSnapshot(`"failed"`)
|
|
201
|
+
expect(row?.feeAmount).toBeNull()
|
|
202
|
+
await db.close()
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
describe('fail', () => {
|
|
207
|
+
test('behavior: transitions pending → failed without a fee', async () => {
|
|
208
|
+
const db = create()
|
|
209
|
+
await db.migrate()
|
|
210
|
+
const record = await SponsoredTransactions.upsert(db, input)
|
|
211
|
+
await SponsoredTransactions.fail(db, record.id, '2026-01-01T00:00:00.000Z')
|
|
212
|
+
const failed = await SponsoredTransactions.get(db, record.id)
|
|
213
|
+
expect(failed?.status).toMatchInlineSnapshot(`"failed"`)
|
|
214
|
+
expect(failed?.feeAmount).toBeNull()
|
|
215
|
+
expect(failed?.finalizedAt).toMatchInlineSnapshot(`"2026-01-01T00:00:00.000Z"`)
|
|
216
|
+
await db.close()
|
|
217
|
+
})
|
|
218
|
+
})
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import type { ExpressionBuilder, Selectable } from 'kysely'
|
|
2
|
+
import { sql } from 'kysely'
|
|
3
|
+
import { nanoid } from 'nanoid'
|
|
4
|
+
|
|
5
|
+
import type * as Db from '../Db.js'
|
|
6
|
+
import type * as db_Schema from '../Schema.js'
|
|
7
|
+
|
|
8
|
+
/** Columns of the `sponsored_transactions` table, derived from `Schema.SponsoredTransaction`. */
|
|
9
|
+
export type Table = db_Schema.SponsoredTransaction
|
|
10
|
+
|
|
11
|
+
/** A stored sponsored-transaction row. */
|
|
12
|
+
export type Record = Selectable<Table>
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Records one sponsorship commitment as `pending`, keyed by its fee-payer
|
|
16
|
+
* sign payload. Written after fee-payer signing and before any broadcast, so
|
|
17
|
+
* no sponsored transaction goes unrecorded; a later recording site for the
|
|
18
|
+
* same envelope (raw submission after a fill intent) upgrades the row with
|
|
19
|
+
* its transaction hash, reopening failed rows for finalization.
|
|
20
|
+
*
|
|
21
|
+
* @param db - The database.
|
|
22
|
+
* @param input - Attribution and envelope facts captured at signing time.
|
|
23
|
+
* @returns The stored record.
|
|
24
|
+
*/
|
|
25
|
+
export async function upsert(db: Db.Db, input: upsert.Input): Promise<Record> {
|
|
26
|
+
const record: Record = {
|
|
27
|
+
apiKeyId: input.apiKeyId,
|
|
28
|
+
billable: input.billable,
|
|
29
|
+
chainId: input.chainId,
|
|
30
|
+
createdAt: new Date().toISOString(),
|
|
31
|
+
environment: input.environment,
|
|
32
|
+
feeAmount: null,
|
|
33
|
+
feeToken: input.feeToken ?? null,
|
|
34
|
+
finalizedAt: null,
|
|
35
|
+
id: `stx_${nanoid()}`,
|
|
36
|
+
orgId: input.orgId,
|
|
37
|
+
projectId: input.projectId,
|
|
38
|
+
signPayload: input.signPayload,
|
|
39
|
+
status: 'pending',
|
|
40
|
+
transaction: input.transaction,
|
|
41
|
+
transactionHash: input.transactionHash ?? null,
|
|
42
|
+
}
|
|
43
|
+
return await db.kysely
|
|
44
|
+
.insertInto('sponsored_transactions')
|
|
45
|
+
.values(record)
|
|
46
|
+
.onConflict((oc) =>
|
|
47
|
+
oc.column('signPayload').doUpdateSet((eb) => ({
|
|
48
|
+
// A raw submission fills the intent's hash; a duplicate intent never
|
|
49
|
+
// clears an already-known hash.
|
|
50
|
+
transactionHash: eb.fn.coalesce(
|
|
51
|
+
eb.ref('excluded.transactionHash'),
|
|
52
|
+
eb.ref('sponsored_transactions.transactionHash'),
|
|
53
|
+
),
|
|
54
|
+
createdAt: sql`CASE WHEN ${eb.ref('sponsored_transactions.status')} = 'failed' THEN ${eb.ref('excluded.createdAt')} ELSE ${eb.ref('sponsored_transactions.createdAt')} END`,
|
|
55
|
+
finalizedAt: sql`CASE WHEN ${eb.ref('sponsored_transactions.status')} = 'failed' THEN NULL ELSE ${eb.ref('sponsored_transactions.finalizedAt')} END`,
|
|
56
|
+
status: sql`CASE WHEN ${eb.ref('sponsored_transactions.status')} = 'failed' THEN 'pending' ELSE ${eb.ref('sponsored_transactions.status')} END`,
|
|
57
|
+
})),
|
|
58
|
+
)
|
|
59
|
+
.returningAll()
|
|
60
|
+
.executeTakeFirstOrThrow()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export declare namespace upsert {
|
|
64
|
+
/** Attribution and envelope facts recorded at sponsorship time. */
|
|
65
|
+
type Input = {
|
|
66
|
+
/** API key id (`key_…`) that requested sponsorship. */
|
|
67
|
+
apiKeyId: string
|
|
68
|
+
/** Whether the sponsorship accrues billable spend; false for sandbox. */
|
|
69
|
+
billable: boolean
|
|
70
|
+
/** Chain the sponsored transaction targets. */
|
|
71
|
+
chainId: number
|
|
72
|
+
/** Key environment the sponsorship was requested under. */
|
|
73
|
+
environment: Table['environment']
|
|
74
|
+
/** Fee token the sponsorship resolved, when known. */
|
|
75
|
+
feeToken?: string | undefined
|
|
76
|
+
/** Organization id (`org_…`) the spend attributes to. */
|
|
77
|
+
orgId: string
|
|
78
|
+
/** Project id (`prj_…`) the spend attributes to. */
|
|
79
|
+
projectId: string
|
|
80
|
+
/** Fee-payer sign payload — a stable identity for the sponsored envelope. */
|
|
81
|
+
signPayload: string
|
|
82
|
+
/** Serialized sponsored transaction, kept for observability beyond log retention. */
|
|
83
|
+
transaction: string
|
|
84
|
+
/** Transaction hash; omit for fill intents, whose senders have not signed yet. */
|
|
85
|
+
transactionHash?: string | undefined
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Reads one sponsorship row by id.
|
|
91
|
+
*
|
|
92
|
+
* @param db - The database.
|
|
93
|
+
* @param id - The sponsored-transaction id (`stx_…`).
|
|
94
|
+
* @returns The record, or `undefined` when absent.
|
|
95
|
+
*/
|
|
96
|
+
export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
97
|
+
return db.kysely
|
|
98
|
+
.selectFrom('sponsored_transactions')
|
|
99
|
+
.selectAll()
|
|
100
|
+
.where('id', '=', id)
|
|
101
|
+
.executeTakeFirst()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Lists pending sponsorships, oldest first, for the finalization job.
|
|
106
|
+
*
|
|
107
|
+
* @param db - The database.
|
|
108
|
+
* @param options - Paging options.
|
|
109
|
+
* @returns The pending records.
|
|
110
|
+
*/
|
|
111
|
+
export function listPending(db: Db.Db, options: listPending.Options = {}): Promise<Record[]> {
|
|
112
|
+
let query = db.kysely
|
|
113
|
+
.selectFrom('sponsored_transactions')
|
|
114
|
+
.selectAll()
|
|
115
|
+
.where('status', '=', 'pending')
|
|
116
|
+
// `id` breaks same-millisecond `createdAt` ties for a deterministic scan.
|
|
117
|
+
.orderBy('createdAt', 'asc')
|
|
118
|
+
.orderBy('id', 'asc')
|
|
119
|
+
if (options.limit !== undefined) query = query.limit(options.limit)
|
|
120
|
+
return query.execute()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export declare namespace listPending {
|
|
124
|
+
/** Options for {@link listPending}. */
|
|
125
|
+
type Options = {
|
|
126
|
+
/** Maximum rows to return. */
|
|
127
|
+
limit?: number | undefined
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Lists hash-less fill intents, oldest first, for the reconciliation pass.
|
|
133
|
+
* Failed intents are included only when the caller supplies a recovery floor.
|
|
134
|
+
*
|
|
135
|
+
* @param db - The database.
|
|
136
|
+
* @param options - Paging options.
|
|
137
|
+
* @returns The pending intents.
|
|
138
|
+
*/
|
|
139
|
+
export function listIntents(db: Db.Db, options: listIntents.Options = {}): Promise<Record[]> {
|
|
140
|
+
let query = db.kysely
|
|
141
|
+
.selectFrom('sponsored_transactions')
|
|
142
|
+
.selectAll()
|
|
143
|
+
.where(intentStatus(options.failedSince))
|
|
144
|
+
.where('transactionHash', 'is', null)
|
|
145
|
+
// `pending` sorts after `failed`; descending keeps active intents first.
|
|
146
|
+
.orderBy('status', 'desc')
|
|
147
|
+
.orderBy('createdAt', 'asc')
|
|
148
|
+
.orderBy('id', 'asc')
|
|
149
|
+
if (options.limit !== undefined) query = query.limit(options.limit)
|
|
150
|
+
return query.execute()
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export declare namespace listIntents {
|
|
154
|
+
/** Options for {@link listIntents}. */
|
|
155
|
+
type Options = listPending.Options & {
|
|
156
|
+
/** Include failed intents whose terminal timestamp is at or after this ISO timestamp. */
|
|
157
|
+
failedSince?: string | undefined
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Fills a reconciled intent's transaction hash and reopens failed intents.
|
|
163
|
+
* A no-op once another pass already assigned the hash.
|
|
164
|
+
*
|
|
165
|
+
* @param db - The database.
|
|
166
|
+
* @param id - The sponsored-transaction id (`stx_…`).
|
|
167
|
+
* @param transactionHash - The matched on-chain transaction hash.
|
|
168
|
+
*/
|
|
169
|
+
export async function assignTransactionHash(
|
|
170
|
+
db: Db.Db,
|
|
171
|
+
id: string,
|
|
172
|
+
transactionHash: string,
|
|
173
|
+
): Promise<void> {
|
|
174
|
+
await db.kysely
|
|
175
|
+
.updateTable('sponsored_transactions')
|
|
176
|
+
.set({ finalizedAt: null, status: 'pending', transactionHash })
|
|
177
|
+
.where('id', '=', id)
|
|
178
|
+
.where('status', 'in', ['failed', 'pending'])
|
|
179
|
+
.where('transactionHash', 'is', null)
|
|
180
|
+
.execute()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Transitions a pending sponsorship to `finalized` with the receipt's actual
|
|
185
|
+
* fee. A no-op when the row is no longer pending (idempotent re-runs).
|
|
186
|
+
*
|
|
187
|
+
* @param db - The database.
|
|
188
|
+
* @param id - The sponsored-transaction id (`stx_…`).
|
|
189
|
+
* @param input - The finalized fee facts.
|
|
190
|
+
*/
|
|
191
|
+
export async function finalize(db: Db.Db, id: string, input: finalize.Input): Promise<void> {
|
|
192
|
+
await db.kysely
|
|
193
|
+
.updateTable('sponsored_transactions')
|
|
194
|
+
.set({ feeAmount: input.feeAmount, finalizedAt: input.finalizedAt, status: 'finalized' })
|
|
195
|
+
.where('id', '=', id)
|
|
196
|
+
.where('status', '=', 'pending')
|
|
197
|
+
.execute()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export declare namespace finalize {
|
|
201
|
+
/** Fee facts resolved from the transaction receipt. */
|
|
202
|
+
type Input = {
|
|
203
|
+
/** Actual fee paid in fee-token base units. */
|
|
204
|
+
feeAmount: string
|
|
205
|
+
/** When the sponsorship finalized (ISO 8601). */
|
|
206
|
+
finalizedAt: string
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Transitions a pending sponsorship to `failed` (never landed within the
|
|
212
|
+
* pending TTL). A no-op when the row is no longer pending.
|
|
213
|
+
*
|
|
214
|
+
* @param db - The database.
|
|
215
|
+
* @param id - The sponsored-transaction id (`stx_…`).
|
|
216
|
+
* @param finalizedAt - When the sponsorship was marked failed (ISO 8601).
|
|
217
|
+
*/
|
|
218
|
+
export async function fail(db: Db.Db, id: string, finalizedAt: string): Promise<void> {
|
|
219
|
+
await db.kysely
|
|
220
|
+
.updateTable('sponsored_transactions')
|
|
221
|
+
.set({ finalizedAt, status: 'failed' })
|
|
222
|
+
.where('id', '=', id)
|
|
223
|
+
.where('status', '=', 'pending')
|
|
224
|
+
.execute()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Intent status predicate; failed rows are recovery candidates only briefly. */
|
|
228
|
+
function intentStatus(failedSince: string | undefined) {
|
|
229
|
+
return (eb: ExpressionBuilder<Db.Database, 'sponsored_transactions'>) => {
|
|
230
|
+
if (failedSince === undefined) return eb('status', '=', 'pending')
|
|
231
|
+
return eb.or([
|
|
232
|
+
eb('status', '=', 'pending'),
|
|
233
|
+
eb.and([eb('status', '=', 'failed'), eb('finalizedAt', '>=', failedSince)]),
|
|
234
|
+
])
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
import { nanoid } from 'nanoid'
|
|
3
|
+
|
|
4
|
+
import type * as Db from '../Db.js'
|
|
5
|
+
import type * as db_Schema from '../Schema.js'
|
|
6
|
+
|
|
7
|
+
/** Columns of the `users` table, derived from `Schema.User`. */
|
|
8
|
+
export type Table = db_Schema.User
|
|
9
|
+
|
|
10
|
+
/** A stored user row. */
|
|
11
|
+
export type Record = Selectable<Table>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Reads a user by id (`usr_…`).
|
|
15
|
+
*
|
|
16
|
+
* @param db - The database.
|
|
17
|
+
* @param id - The user id.
|
|
18
|
+
* @returns The record, or `undefined` when absent.
|
|
19
|
+
*/
|
|
20
|
+
export function get(db: Db.Db, id: string): Promise<Record | undefined> {
|
|
21
|
+
return db.kysely.selectFrom('users').selectAll().where('id', '=', id).executeTakeFirst()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Reads a user by wallet address (compared lowercase).
|
|
26
|
+
*
|
|
27
|
+
* @param db - The database.
|
|
28
|
+
* @param address - The wallet address.
|
|
29
|
+
* @returns The record, or `undefined` when absent.
|
|
30
|
+
*/
|
|
31
|
+
export function getByAddress(db: Db.Db, address: string): Promise<Record | undefined> {
|
|
32
|
+
return db.kysely
|
|
33
|
+
.selectFrom('users')
|
|
34
|
+
.selectAll()
|
|
35
|
+
.where('address', '=', address.toLowerCase())
|
|
36
|
+
.executeTakeFirst()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Inserts a user for `address` when absent and returns the stored record.
|
|
41
|
+
* Existing users are returned unchanged, so repeated sign-ins are idempotent.
|
|
42
|
+
*
|
|
43
|
+
* @param db - The database.
|
|
44
|
+
* @param input - The user to ensure.
|
|
45
|
+
* @returns The stored record.
|
|
46
|
+
*/
|
|
47
|
+
export async function upsertByAddress(db: Db.Db, input: upsertByAddress.Input): Promise<Record> {
|
|
48
|
+
const address = input.address.toLowerCase()
|
|
49
|
+
const now = new Date().toISOString()
|
|
50
|
+
const inserted = await db.kysely
|
|
51
|
+
.insertInto('users')
|
|
52
|
+
.values({ address, createdAt: now, email: null, id: `usr_${nanoid()}`, updatedAt: now })
|
|
53
|
+
.onConflict((oc) => oc.column('address').doNothing())
|
|
54
|
+
.returningAll()
|
|
55
|
+
.executeTakeFirst()
|
|
56
|
+
if (inserted) return inserted
|
|
57
|
+
return db.kysely
|
|
58
|
+
.selectFrom('users')
|
|
59
|
+
.selectAll()
|
|
60
|
+
.where('address', '=', address)
|
|
61
|
+
.executeTakeFirstOrThrow()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export declare namespace upsertByAddress {
|
|
65
|
+
/** Fields accepted when ensuring a user. */
|
|
66
|
+
type Input = {
|
|
67
|
+
/** Wallet address that signed in (stored lowercase). */
|
|
68
|
+
address: string
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sets a user's verified email, bumping `updatedAt`.
|
|
74
|
+
*
|
|
75
|
+
* @param db - The database.
|
|
76
|
+
* @param id - The user id (`usr_…`).
|
|
77
|
+
* @param email - The verified email.
|
|
78
|
+
*/
|
|
79
|
+
export async function setEmail(db: Db.Db, id: string, email: string): Promise<void> {
|
|
80
|
+
await db.kysely
|
|
81
|
+
.updateTable('users')
|
|
82
|
+
.set({ email, updatedAt: new Date().toISOString() })
|
|
83
|
+
.where('id', '=', id)
|
|
84
|
+
.execute()
|
|
85
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Selectable } from 'kysely'
|
|
2
|
+
import type { Hex } from 'ox'
|
|
3
|
+
|
|
4
|
+
import type * as VerifiedTokens from '../../internal/VerifiedTokens.js'
|
|
5
|
+
import type * as Db from '../Db.js'
|
|
6
|
+
import type * as db_Schema from '../Schema.js'
|
|
7
|
+
|
|
8
|
+
/** Columns of the `verified_tokens` table, derived from `Schema.VerifiedToken`. */
|
|
9
|
+
export type Table = db_Schema.VerifiedToken
|
|
10
|
+
|
|
11
|
+
/** Columns of the `verified_token_lists` table, derived from `Schema.VerifiedTokenList`. */
|
|
12
|
+
export type ListTable = db_Schema.VerifiedTokenList
|
|
13
|
+
|
|
14
|
+
/** A stored verified-token row. */
|
|
15
|
+
export type Row = Selectable<Table>
|
|
16
|
+
|
|
17
|
+
/** A chain's list-level metadata. */
|
|
18
|
+
export type Meta = Selectable<ListTable>
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Reads a chain's list metadata — the "head" the soft-refresh cache compares
|
|
22
|
+
* versions against.
|
|
23
|
+
*
|
|
24
|
+
* @param db - The database.
|
|
25
|
+
* @param chainId - The chain id.
|
|
26
|
+
* @returns The metadata, or `undefined` when the chain has no list yet.
|
|
27
|
+
*/
|
|
28
|
+
export function head(db: Db.Db, chainId: number): Promise<Meta | undefined> {
|
|
29
|
+
return db.kysely
|
|
30
|
+
.selectFrom('verified_token_lists')
|
|
31
|
+
.selectAll()
|
|
32
|
+
.where('chainId', '=', chainId)
|
|
33
|
+
.executeTakeFirst()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Reads a chain's tokens in canonical list order.
|
|
38
|
+
*
|
|
39
|
+
* @param db - The database.
|
|
40
|
+
* @param chainId - The chain id.
|
|
41
|
+
* @returns The rows.
|
|
42
|
+
*/
|
|
43
|
+
export function list(db: Db.Db, chainId: number): Promise<Row[]> {
|
|
44
|
+
return db.kysely
|
|
45
|
+
.selectFrom('verified_tokens')
|
|
46
|
+
.selectAll()
|
|
47
|
+
.where('chainId', '=', chainId)
|
|
48
|
+
.orderBy('position')
|
|
49
|
+
.execute()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Publishes a chain's whole list: replaces its token rows (positions rewritten
|
|
54
|
+
* wholesale) and bumps the list metadata. Callers run this inside the
|
|
55
|
+
* per-chain publish lock/transaction, so the rewrite is atomic.
|
|
56
|
+
*
|
|
57
|
+
* @param db - The database (a transaction-scoped handle).
|
|
58
|
+
* @param chainId - The chain id.
|
|
59
|
+
* @param input - The validated list and its new version metadata.
|
|
60
|
+
*/
|
|
61
|
+
export async function publish(db: Db.Db, chainId: number, input: publish.Input): Promise<void> {
|
|
62
|
+
await db.kysely.deleteFrom('verified_tokens').where('chainId', '=', chainId).execute()
|
|
63
|
+
if (input.tokens.length > 0)
|
|
64
|
+
await db.kysely
|
|
65
|
+
.insertInto('verified_tokens')
|
|
66
|
+
.values(
|
|
67
|
+
input.tokens.map((token, position) => ({
|
|
68
|
+
address: token.address,
|
|
69
|
+
chainId,
|
|
70
|
+
currency: token.currency,
|
|
71
|
+
decimals: token.decimals,
|
|
72
|
+
logoUri: token.logoUri ?? null,
|
|
73
|
+
name: token.name,
|
|
74
|
+
position,
|
|
75
|
+
symbol: token.symbol,
|
|
76
|
+
})),
|
|
77
|
+
)
|
|
78
|
+
.execute()
|
|
79
|
+
await db.kysely
|
|
80
|
+
.insertInto('verified_token_lists')
|
|
81
|
+
.values({ chainId, updatedAt: input.updatedAt, version: input.version })
|
|
82
|
+
.onConflict((oc) =>
|
|
83
|
+
oc.column('chainId').doUpdateSet({ updatedAt: input.updatedAt, version: input.version }),
|
|
84
|
+
)
|
|
85
|
+
.execute()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export declare namespace publish {
|
|
89
|
+
/** A validated list to publish. */
|
|
90
|
+
type Input = {
|
|
91
|
+
/** Tokens in canonical order (addresses lowercased by the domain layer). */
|
|
92
|
+
tokens: readonly VerifiedTokens.Token[]
|
|
93
|
+
/** ISO timestamp of the publish. */
|
|
94
|
+
updatedAt: string
|
|
95
|
+
/** New opaque list version. */
|
|
96
|
+
version: string
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Maps a stored row to the domain token (null `logoUri` → absent field). */
|
|
101
|
+
export function toToken(row: Row): VerifiedTokens.Token {
|
|
102
|
+
return {
|
|
103
|
+
address: row.address as Hex.Hex,
|
|
104
|
+
currency: row.currency,
|
|
105
|
+
decimals: row.decimals,
|
|
106
|
+
id: row.address as Hex.Hex,
|
|
107
|
+
name: row.name,
|
|
108
|
+
symbol: row.symbol,
|
|
109
|
+
...(row.logoUri === null ? {} : { logoUri: row.logoUri }),
|
|
110
|
+
}
|
|
111
|
+
}
|