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
package/src/admin/App.ts
CHANGED
|
@@ -3,10 +3,10 @@ import { HTTPException } from 'hono/http-exception'
|
|
|
3
3
|
import { requestId, type RequestIdVariables } from 'hono/request-id'
|
|
4
4
|
|
|
5
5
|
import * as ApiKey from '../ApiKey.js'
|
|
6
|
-
import * as ApiKeySource from '../ApiKeySource.js'
|
|
7
6
|
import type * as Assets from '../Assets.js'
|
|
8
|
-
import * as
|
|
7
|
+
import type * as Db from '../db/Db.js'
|
|
9
8
|
import type * as Store from '../internal/Store.js'
|
|
9
|
+
import * as Response from '../internal/Response.js'
|
|
10
10
|
|
|
11
11
|
import { apiKeys } from './apps/api-keys.js'
|
|
12
12
|
import { scopes } from './apps/scopes.js'
|
|
@@ -24,12 +24,12 @@ export type Environment = {
|
|
|
24
24
|
Variables: RequestIdVariables & {
|
|
25
25
|
/** Static-asset writer (e.g. the R2 icon bucket), when configured. */
|
|
26
26
|
assets: create.Assets | undefined
|
|
27
|
+
/** Authoritative Postgres store, or a per-request factory. Resolve at the leaf with `Db.get`. */
|
|
28
|
+
db: Db.Source
|
|
29
|
+
/** KV state store backing API-key records (mint/list/revoke). */
|
|
30
|
+
kv: { store: Store.State }
|
|
27
31
|
/** The admin identity, or `null` when unauthenticated (gated routes reject). */
|
|
28
32
|
identity: Identity | null
|
|
29
|
-
/** The API-key source provisioned against (mint/list/revoke). */
|
|
30
|
-
source: ApiKeySource.Source
|
|
31
|
-
/** Verified-token state store, when management is enabled. */
|
|
32
|
-
verifiedTokens: { store: Store.State } | undefined
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -39,7 +39,6 @@ export type App = ReturnType<typeof create>
|
|
|
39
39
|
/** Creates the admin portal Hono app. */
|
|
40
40
|
export function create(options: create.Options) {
|
|
41
41
|
const { identify } = options
|
|
42
|
-
const { source } = options.apiKey
|
|
43
42
|
// `false` (disabled) collapses to `undefined` so only a real config surfaces
|
|
44
43
|
// `loginUrl`/`logoutUrl` in `/config.json`.
|
|
45
44
|
const ui = options.ui || undefined
|
|
@@ -55,9 +54,9 @@ export function create(options: create.Options) {
|
|
|
55
54
|
app.use('*', async (c, next) => {
|
|
56
55
|
// Admin data is per-principal and mutating: never cache.
|
|
57
56
|
c.header('Cache-Control', 'no-store')
|
|
58
|
-
c.set('source', source)
|
|
59
57
|
c.set('assets', options.assets)
|
|
60
|
-
c.set('
|
|
58
|
+
c.set('db', options.db)
|
|
59
|
+
c.set('kv', options.kv)
|
|
61
60
|
c.set('identity', await identify(c.req.raw))
|
|
62
61
|
return next()
|
|
63
62
|
})
|
|
@@ -173,16 +172,22 @@ export declare namespace create {
|
|
|
173
172
|
|
|
174
173
|
/** Options for {@link create}. */
|
|
175
174
|
type Options = {
|
|
176
|
-
/** API-key provisioning config (mirrors the API app's `apiKey` option). */
|
|
177
|
-
apiKey: {
|
|
178
|
-
/** Source to provision against (mint/list/revoke). */
|
|
179
|
-
source: ApiKeySource.Source
|
|
180
|
-
}
|
|
181
175
|
/**
|
|
182
176
|
* Static-asset writer for logo uploads (shared with the main API's `assets`
|
|
183
177
|
* loader) to enable `PUT /verified-tokens/:address/logo`; omit for `404`.
|
|
184
178
|
*/
|
|
185
179
|
assets?: Assets | undefined
|
|
180
|
+
/**
|
|
181
|
+
* Authoritative Postgres store shared with the main API (verified
|
|
182
|
+
* tokens). Pass a long-lived `Db.postgres(...)` singleton on Node, or a
|
|
183
|
+
* factory (`() => Db.postgres(...)`) on Workers.
|
|
184
|
+
*/
|
|
185
|
+
db: Db.Source
|
|
186
|
+
/**
|
|
187
|
+
* KV state store backing API-key records (shared with the main API's
|
|
188
|
+
* `kv` option), provisioned against by the `/api-keys` routes.
|
|
189
|
+
*/
|
|
190
|
+
kv: { store: Store.State }
|
|
186
191
|
/**
|
|
187
192
|
* Extracts the verified admin identity from a request, or `null` to deny.
|
|
188
193
|
* Must only return an identity for an already-authenticated request (a
|
|
@@ -194,16 +199,6 @@ export declare namespace create {
|
|
|
194
199
|
* `loginUrl`/`logoutUrl` are surfaced in `GET /config.json`.
|
|
195
200
|
*/
|
|
196
201
|
ui?: Ui | false | undefined
|
|
197
|
-
/**
|
|
198
|
-
* Verified-token management config (store shared with the main API's reads)
|
|
199
|
-
* to enable the `/verified-tokens` routes; omit to serve them as `404`.
|
|
200
|
-
*/
|
|
201
|
-
verifiedTokens?:
|
|
202
|
-
| {
|
|
203
|
-
/** Verified-token state store (shared with the main API's reads). */
|
|
204
|
-
store: Store.State
|
|
205
|
-
}
|
|
206
|
-
| undefined
|
|
207
202
|
}
|
|
208
203
|
|
|
209
204
|
/** Admin UI options surfaced to the SPA via `GET /config.json`. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as ApiKey from '../../ApiKey.js'
|
|
2
|
+
import * as core_ApiKeys from '../../ApiKeys.js'
|
|
2
3
|
|
|
3
4
|
import * as TestAdmin from '../../../test/Admin.js'
|
|
4
5
|
import * as TestApp from '../../../test/App.js'
|
|
@@ -9,7 +10,7 @@ const validBody = { orgId: 'org_test', scopes: ['data:read'] } as const
|
|
|
9
10
|
|
|
10
11
|
describe('POST /api-keys', () => {
|
|
11
12
|
test('mints a key, returns the token once, persists a hashed record', async () => {
|
|
12
|
-
const { client,
|
|
13
|
+
const { client, store } = TestAdmin.setup()
|
|
13
14
|
const response = await client['api-keys'].$post({ json: { ...validBody, name: 'CI' } })
|
|
14
15
|
const body = await TestApp.json(response, ApiKeys.schema.createApiKey.Response)
|
|
15
16
|
|
|
@@ -34,26 +35,26 @@ describe('POST /api-keys', () => {
|
|
|
34
35
|
}
|
|
35
36
|
`)
|
|
36
37
|
|
|
37
|
-
// The token resolves through the
|
|
38
|
+
// The token resolves through the module (proving the record persisted),
|
|
38
39
|
// and at rest it is keyed by the token hash — never the plaintext token.
|
|
39
|
-
const resolved = await
|
|
40
|
+
const resolved = await core_ApiKeys.resolve(store, body.token)
|
|
40
41
|
expect(resolved?.orgId).toBe('org_test')
|
|
41
42
|
expect(await store.get(body.token)).toBeNull()
|
|
42
43
|
expect(await store.get(ApiKey.keyFor(body.token))).not.toBeNull()
|
|
43
44
|
})
|
|
44
45
|
|
|
45
46
|
test('defaults to the production environment', async () => {
|
|
46
|
-
const { client,
|
|
47
|
+
const { client, store } = TestAdmin.setup()
|
|
47
48
|
const response = await client['api-keys'].$post({ json: validBody })
|
|
48
49
|
const body = await TestApp.json(response, ApiKeys.schema.createApiKey.Response)
|
|
49
50
|
|
|
50
51
|
expect(response.status).toBe(200)
|
|
51
52
|
expect(body.environment).toBe('production')
|
|
52
|
-
expect((await
|
|
53
|
+
expect((await core_ApiKeys.list(store))[0]?.environment).toBe('production')
|
|
53
54
|
})
|
|
54
55
|
|
|
55
56
|
test('persists a sandbox environment when provided', async () => {
|
|
56
|
-
const { client,
|
|
57
|
+
const { client, store } = TestAdmin.setup()
|
|
57
58
|
const response = await client['api-keys'].$post({
|
|
58
59
|
json: { ...validBody, environment: 'sandbox' },
|
|
59
60
|
})
|
|
@@ -63,19 +64,19 @@ describe('POST /api-keys', () => {
|
|
|
63
64
|
expect(body.environment).toBe('sandbox')
|
|
64
65
|
// Sandbox tokens carry a distinct prefix for recognizability/leak detection.
|
|
65
66
|
expect(body.token).toMatch(/^tempo_sandbox:sk:[a-f0-9]{48}$/)
|
|
66
|
-
const resolved = await
|
|
67
|
+
const resolved = await core_ApiKeys.resolve(store, body.token)
|
|
67
68
|
expect(resolved?.environment).toBe('sandbox')
|
|
68
69
|
})
|
|
69
70
|
|
|
70
71
|
test('records the expiry when provided', async () => {
|
|
71
|
-
const { client,
|
|
72
|
+
const { client, store } = TestAdmin.setup()
|
|
72
73
|
const expiresAt = '2100-01-01T00:00:00.000Z'
|
|
73
74
|
const response = await client['api-keys'].$post({ json: { ...validBody, expiresAt } })
|
|
74
75
|
const body = await TestApp.json(response, ApiKeys.schema.createApiKey.Response)
|
|
75
76
|
|
|
76
77
|
expect(response.status).toBe(200)
|
|
77
78
|
expect(body.expiresAt).toBe(expiresAt)
|
|
78
|
-
expect((await
|
|
79
|
+
expect((await core_ApiKeys.list(store))[0]?.expiresAt).toBe(expiresAt)
|
|
79
80
|
})
|
|
80
81
|
|
|
81
82
|
test('rejects an unknown scope with 400', async () => {
|
|
@@ -106,8 +107,8 @@ describe('POST /api-keys', () => {
|
|
|
106
107
|
|
|
107
108
|
describe('GET /api-keys', () => {
|
|
108
109
|
test('lists records as metadata only (never the token)', async () => {
|
|
109
|
-
const { client,
|
|
110
|
-
const { token } = await
|
|
110
|
+
const { client, store } = TestAdmin.setup()
|
|
111
|
+
const { token } = await core_ApiKeys.mint(store, validBody)
|
|
111
112
|
|
|
112
113
|
const response = await client['api-keys'].$get({ query: {} })
|
|
113
114
|
const body = await TestApp.json(response, ApiKeys.schema.listApiKeys.Response)
|
|
@@ -120,9 +121,9 @@ describe('GET /api-keys', () => {
|
|
|
120
121
|
})
|
|
121
122
|
|
|
122
123
|
test('filters by orgId', async () => {
|
|
123
|
-
const { client,
|
|
124
|
-
await
|
|
125
|
-
await
|
|
124
|
+
const { client, store } = TestAdmin.setup()
|
|
125
|
+
await core_ApiKeys.mint(store, { orgId: 'org_a', scopes: ['data:read'] })
|
|
126
|
+
await core_ApiKeys.mint(store, { orgId: 'org_b', scopes: ['data:read'] })
|
|
126
127
|
|
|
127
128
|
const response = await client['api-keys'].$get({ query: { orgId: 'org_a' } })
|
|
128
129
|
const body = await TestApp.json(response, ApiKeys.schema.listApiKeys.Response)
|
|
@@ -133,16 +134,16 @@ describe('GET /api-keys', () => {
|
|
|
133
134
|
|
|
134
135
|
describe('DELETE /api-keys/:id', () => {
|
|
135
136
|
test('revokes a key, after which it no longer resolves or lists', async () => {
|
|
136
|
-
const { client,
|
|
137
|
-
const { record, token } = await
|
|
137
|
+
const { client, store } = TestAdmin.setup()
|
|
138
|
+
const { record, token } = await core_ApiKeys.mint(store, validBody)
|
|
138
139
|
|
|
139
140
|
const response = await client['api-keys'][':id'].$delete({ param: { id: record.id } })
|
|
140
141
|
const body = await TestApp.json(response, ApiKeys.schema.revokeApiKey.Response)
|
|
141
142
|
|
|
142
143
|
expect(response.status).toBe(200)
|
|
143
144
|
expect(body).toEqual({ id: record.id })
|
|
144
|
-
expect(await
|
|
145
|
-
expect(await
|
|
145
|
+
expect(await core_ApiKeys.resolve(store, token)).toBeNull()
|
|
146
|
+
expect(await core_ApiKeys.list(store)).toEqual([])
|
|
146
147
|
})
|
|
147
148
|
|
|
148
149
|
test('unknown id → 404', async () => {
|
|
@@ -154,3 +155,54 @@ describe('DELETE /api-keys/:id', () => {
|
|
|
154
155
|
expect(body.error?.code).toMatchInlineSnapshot(`"not_found"`)
|
|
155
156
|
})
|
|
156
157
|
})
|
|
158
|
+
|
|
159
|
+
describe('PATCH /api-keys/:id', () => {
|
|
160
|
+
test('re-attributes a key to an org and project', async () => {
|
|
161
|
+
const { client, store } = TestAdmin.setup()
|
|
162
|
+
const { record, token } = await core_ApiKeys.mint(store, validBody)
|
|
163
|
+
|
|
164
|
+
const response = await client['api-keys'][':id'].$patch({
|
|
165
|
+
json: { orgId: 'org_real', projectId: 'prj_real' },
|
|
166
|
+
param: { id: record.id },
|
|
167
|
+
})
|
|
168
|
+
expect(response.status).toBe(200)
|
|
169
|
+
const body = await TestApp.json(response, core_ApiKeys.schema.Record)
|
|
170
|
+
expect(body.orgId).toBe('org_real')
|
|
171
|
+
expect(body.projectId).toBe('prj_real')
|
|
172
|
+
|
|
173
|
+
// The original token keeps resolving, now carrying the attribution.
|
|
174
|
+
const resolved = await core_ApiKeys.resolve(store, token)
|
|
175
|
+
expect(resolved?.projectId).toBe('prj_real')
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
test('unknown id → 404', async () => {
|
|
179
|
+
const { client } = TestAdmin.setup()
|
|
180
|
+
const response = await client['api-keys'][':id'].$patch({
|
|
181
|
+
json: { projectId: 'prj_x' },
|
|
182
|
+
param: { id: 'key_missing' },
|
|
183
|
+
})
|
|
184
|
+
expect(response.status).toMatchInlineSnapshot(`404`)
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
describe('POST /api-keys/backfill', () => {
|
|
189
|
+
test('rebuilds index entries for legacy records', async () => {
|
|
190
|
+
const { client, store } = TestAdmin.setup()
|
|
191
|
+
const { record } = await core_ApiKeys.mint(store, validBody)
|
|
192
|
+
|
|
193
|
+
// Legacy state: records exist, index entries do not.
|
|
194
|
+
for (const prefix of ['apikey_id:', 'apikey_org:'])
|
|
195
|
+
for (const { name } of (await store.list({ prefix })).keys) await store.delete(name)
|
|
196
|
+
expect(await core_ApiKeys.listByOrg(store, 'org_test')).toEqual([])
|
|
197
|
+
|
|
198
|
+
const response = await client['api-keys'].backfill.$post()
|
|
199
|
+
expect(response.status).toBe(200)
|
|
200
|
+
expect(await TestApp.json(response, ApiKeys.schema.backfillApiKeys.Response)).toEqual({
|
|
201
|
+
indexed: 1,
|
|
202
|
+
scanned: 1,
|
|
203
|
+
})
|
|
204
|
+
expect((await core_ApiKeys.listByOrg(store, 'org_test')).map(({ id }) => id)).toEqual([
|
|
205
|
+
record.id,
|
|
206
|
+
])
|
|
207
|
+
})
|
|
208
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from 'hono'
|
|
2
2
|
import * as z from 'zod/mini'
|
|
3
3
|
|
|
4
|
-
import * as
|
|
4
|
+
import * as ApiKeys from '../../ApiKeys.js'
|
|
5
5
|
import * as OpenApi from '../../internal/OpenApi.js'
|
|
6
6
|
import * as Response from '../../internal/Response.js'
|
|
7
7
|
import * as Schema from '../../internal/Schema.js'
|
|
@@ -16,13 +16,13 @@ export namespace schema {
|
|
|
16
16
|
* server sets from the verified identity so it can't be spoofed).
|
|
17
17
|
*/
|
|
18
18
|
export const Body = Schema.describe(
|
|
19
|
-
z.omit(
|
|
19
|
+
z.omit(ApiKeys.schema.MintInput, { createdBy: true }),
|
|
20
20
|
'Fields accepted when minting an API key.',
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
/** Response: the record plus the one-time plaintext token. */
|
|
24
24
|
export const Response = Schema.describe(
|
|
25
|
-
z.extend(
|
|
25
|
+
z.extend(ApiKeys.schema.Record, {
|
|
26
26
|
token: z
|
|
27
27
|
.string()
|
|
28
28
|
.check(z.describe('The plaintext token, shown once and unrecoverable afterward.')),
|
|
@@ -46,13 +46,44 @@ export namespace schema {
|
|
|
46
46
|
export const Response = Schema.describe(
|
|
47
47
|
z.object({
|
|
48
48
|
data: z
|
|
49
|
-
.array(
|
|
49
|
+
.array(ApiKeys.schema.Record)
|
|
50
50
|
.check(z.describe('API-key records, newest first (metadata only — never tokens).')),
|
|
51
51
|
}),
|
|
52
52
|
'A list of API-key records.',
|
|
53
53
|
)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/** Schemas for the attributeApiKey operation. */
|
|
57
|
+
export namespace attributeApiKey {
|
|
58
|
+
/** Request body re-attributing a key; omitted fields keep their value. */
|
|
59
|
+
export const Body = Schema.describe(
|
|
60
|
+
z.object({
|
|
61
|
+
orgId: z.optional(z.string()).check(z.describe('New owning organization id (`org_…`).')),
|
|
62
|
+
projectId: z.optional(z.string()).check(z.describe('New owning project id (`prj_…`).')),
|
|
63
|
+
}),
|
|
64
|
+
'Attribution to apply to an API key.',
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
/** Path parameters for attributing a key. */
|
|
68
|
+
export const Params = z
|
|
69
|
+
.object({
|
|
70
|
+
id: z.string().check(z.describe('Stable id of the key to attribute.')),
|
|
71
|
+
})
|
|
72
|
+
.check(z.describe('Path parameters for attributing an API key.'))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Schemas for the backfillApiKeys operation. */
|
|
76
|
+
export namespace backfillApiKeys {
|
|
77
|
+
/** Result counts from the index rebuild. */
|
|
78
|
+
export const Response = Schema.describe(
|
|
79
|
+
z.object({
|
|
80
|
+
indexed: z.number().check(z.describe('Records whose index entries were written.')),
|
|
81
|
+
scanned: z.number().check(z.describe('Stored records scanned.')),
|
|
82
|
+
}),
|
|
83
|
+
'Result of rebuilding the API-key indexes.',
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
56
87
|
/** Schemas for the revokeApiKey operation. */
|
|
57
88
|
export namespace revokeApiKey {
|
|
58
89
|
/** Path parameters for revoking a key. */
|
|
@@ -70,16 +101,36 @@ export namespace schema {
|
|
|
70
101
|
}
|
|
71
102
|
|
|
72
103
|
/**
|
|
73
|
-
* Provisioning routes for API keys, backed by the
|
|
74
|
-
* {@link App.Environment} `source`:
|
|
104
|
+
* Provisioning routes for API keys, backed by the app's KV state store:
|
|
75
105
|
*
|
|
76
106
|
* - `POST /` mints a key, recording `createdBy` from the verified identity and
|
|
77
107
|
* returning the one-time token.
|
|
78
108
|
* - `GET /` lists key records (metadata only), optionally filtered by `orgId`.
|
|
79
109
|
* - `DELETE /:id` revokes a key by id (`404` if absent).
|
|
110
|
+
* - `PATCH /:id` re-attributes a key to an org/project (the legacy backfill path).
|
|
111
|
+
* - `POST /backfill` rebuilds the id and org index entries for every record.
|
|
80
112
|
*/
|
|
81
113
|
export function apiKeys() {
|
|
82
114
|
return new Hono<App.Environment>()
|
|
115
|
+
.post(
|
|
116
|
+
'/backfill',
|
|
117
|
+
OpenApi.describeRoute({
|
|
118
|
+
description: 'Rebuild the id and org index entries for every stored key record. Records are never modified, so existing tokens keep resolving.', // prettier-ignore
|
|
119
|
+
operationId: 'backfillApiKeys',
|
|
120
|
+
responses: OpenApi.responses({
|
|
121
|
+
success: {
|
|
122
|
+
description: 'Scanned and indexed record counts.',
|
|
123
|
+
schema: schema.backfillApiKeys.Response,
|
|
124
|
+
},
|
|
125
|
+
}),
|
|
126
|
+
summary: 'Backfill key indexes',
|
|
127
|
+
tags: ['API keys'],
|
|
128
|
+
}),
|
|
129
|
+
async (c) => {
|
|
130
|
+
const result = await ApiKeys.backfill(c.get('kv').store)
|
|
131
|
+
return c.json(Response.validated(schema.backfillApiKeys.Response, result))
|
|
132
|
+
},
|
|
133
|
+
)
|
|
83
134
|
.post(
|
|
84
135
|
'/',
|
|
85
136
|
OpenApi.validate('json', schema.createApiKey.Body, {
|
|
@@ -100,7 +151,7 @@ export function apiKeys() {
|
|
|
100
151
|
async (c) => {
|
|
101
152
|
// `createdBy` is the verified admin email, never client-supplied.
|
|
102
153
|
// `requireAuth` guarantees identity on this gated route.
|
|
103
|
-
const { record, token } = await c.get('
|
|
154
|
+
const { record, token } = await ApiKeys.mint(c.get('kv').store, {
|
|
104
155
|
...c.req.valid('json'),
|
|
105
156
|
createdBy: c.get('identity')!.email,
|
|
106
157
|
})
|
|
@@ -123,7 +174,7 @@ export function apiKeys() {
|
|
|
123
174
|
}),
|
|
124
175
|
async (c) => {
|
|
125
176
|
const { orgId } = c.req.valid('query')
|
|
126
|
-
const data = await c.get('
|
|
177
|
+
const data = await ApiKeys.list(c.get('kv').store, orgId ? { orgId } : {})
|
|
127
178
|
return c.json(Response.validated(schema.listApiKeys.Response, { data }))
|
|
128
179
|
},
|
|
129
180
|
)
|
|
@@ -144,7 +195,7 @@ export function apiKeys() {
|
|
|
144
195
|
}),
|
|
145
196
|
async (c) => {
|
|
146
197
|
const { id } = c.req.valid('param')
|
|
147
|
-
const revoked = await c.get('
|
|
198
|
+
const revoked = await ApiKeys.revoke(c.get('kv').store, id)
|
|
148
199
|
if (!revoked)
|
|
149
200
|
return Response.error(c, {
|
|
150
201
|
code: 'not_found',
|
|
@@ -154,4 +205,36 @@ export function apiKeys() {
|
|
|
154
205
|
return c.json(Response.validated(schema.revokeApiKey.Response, { id }))
|
|
155
206
|
},
|
|
156
207
|
)
|
|
208
|
+
.patch(
|
|
209
|
+
'/:id',
|
|
210
|
+
OpenApi.validate('param', schema.attributeApiKey.Params, {
|
|
211
|
+
code: 'param_invalid',
|
|
212
|
+
message: 'Invalid path parameters',
|
|
213
|
+
}),
|
|
214
|
+
OpenApi.validate('json', schema.attributeApiKey.Body, {
|
|
215
|
+
code: 'body_invalid',
|
|
216
|
+
message: 'Invalid request body',
|
|
217
|
+
}),
|
|
218
|
+
OpenApi.describeRoute({
|
|
219
|
+
description: 'Re-attribute a key to an organization and/or project. The token is unchanged.', // prettier-ignore
|
|
220
|
+
operationId: 'attributeApiKey',
|
|
221
|
+
responses: OpenApi.responses({
|
|
222
|
+
errors: { 404: 'API key not found.' },
|
|
223
|
+
success: { description: 'The updated key record.', schema: ApiKeys.schema.Record },
|
|
224
|
+
}),
|
|
225
|
+
summary: 'Attribute API key',
|
|
226
|
+
tags: ['API keys'],
|
|
227
|
+
}),
|
|
228
|
+
async (c) => {
|
|
229
|
+
const { id } = c.req.valid('param')
|
|
230
|
+
const updated = await ApiKeys.attribute(c.get('kv').store, id, c.req.valid('json'))
|
|
231
|
+
if (!updated)
|
|
232
|
+
return Response.error(c, {
|
|
233
|
+
code: 'not_found',
|
|
234
|
+
message: 'API key not found.',
|
|
235
|
+
status: 404,
|
|
236
|
+
})
|
|
237
|
+
return c.json(Response.validated(ApiKeys.schema.Record, updated))
|
|
238
|
+
},
|
|
239
|
+
)
|
|
157
240
|
}
|
|
@@ -22,6 +22,14 @@ describe('GET /scopes', () => {
|
|
|
22
22
|
"description": "Run ad-hoc queries against the raw indexer passthrough.",
|
|
23
23
|
"scope": "indexer:query",
|
|
24
24
|
},
|
|
25
|
+
{
|
|
26
|
+
"description": "Fill and submit transactions through the relay.",
|
|
27
|
+
"scope": "rpc-relay:read",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"description": "Sponsor transaction fees through the relay as the managed fee payer.",
|
|
31
|
+
"scope": "rpc-relay:sponsor",
|
|
32
|
+
},
|
|
25
33
|
{
|
|
26
34
|
"description": "Read webhook subscriptions.",
|
|
27
35
|
"scope": "webhooks:read",
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Store } from 'cadent'
|
|
2
|
-
|
|
3
1
|
import * as TestAdmin from '../../../test/Admin.js'
|
|
4
2
|
import * as TestApp from '../../../test/App.js'
|
|
5
3
|
import * as Verified from './verified-tokens.js'
|
|
@@ -15,29 +13,14 @@ const novel = {
|
|
|
15
13
|
|
|
16
14
|
const chainId = '42431' as const
|
|
17
15
|
|
|
18
|
-
/** Write-enabled admin client backed by a fresh
|
|
16
|
+
/** Write-enabled admin client backed by a fresh schema-isolated database. */
|
|
19
17
|
function writes() {
|
|
20
|
-
return TestAdmin.setup(
|
|
18
|
+
return TestAdmin.setup()
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
describe('feature gate', () => {
|
|
24
|
-
test('write routes return 404 when no store is configured', async () => {
|
|
25
|
-
const { client } = TestAdmin.setup()
|
|
26
|
-
const response = await client['verified-tokens'].$post({
|
|
27
|
-
json: { ...novel, chainId: 42431 },
|
|
28
|
-
})
|
|
29
|
-
expect(response.status).toBe(404)
|
|
30
|
-
const body = (await response.json()) as { error?: { code?: string } }
|
|
31
|
-
expect(body.error?.code).toBe('verified_tokens_not_enabled')
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
21
|
describe('authentication', () => {
|
|
36
22
|
test('denied identity → 401', async () => {
|
|
37
|
-
const { client } = TestAdmin.setup({
|
|
38
|
-
identify: () => null,
|
|
39
|
-
verifiedTokens: { store: Store.memory() },
|
|
40
|
-
})
|
|
23
|
+
const { client } = TestAdmin.setup({ identify: () => null })
|
|
41
24
|
const response = await client['verified-tokens'].$post({
|
|
42
25
|
json: { ...novel, chainId: 42431 },
|
|
43
26
|
})
|
|
@@ -46,12 +29,6 @@ describe('authentication', () => {
|
|
|
46
29
|
})
|
|
47
30
|
|
|
48
31
|
describe('list', () => {
|
|
49
|
-
test('returns 404 when no store is configured', async () => {
|
|
50
|
-
const { client } = TestAdmin.setup()
|
|
51
|
-
const response = await client['verified-tokens'].$get({ query: { chainId } })
|
|
52
|
-
expect(response.status).toBe(404)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
32
|
test('empty list → data [] and null version', async () => {
|
|
56
33
|
const { client } = writes()
|
|
57
34
|
const response = await client['verified-tokens'].$get({ query: { chainId } })
|
|
@@ -176,7 +153,6 @@ describe('create with inline logo', () => {
|
|
|
176
153
|
get: async (key) => stored.find((entry) => entry.key === key)?.content,
|
|
177
154
|
put: async (key, content) => void stored.push({ content, key }),
|
|
178
155
|
},
|
|
179
|
-
verifiedTokens: { store: Store.memory() },
|
|
180
156
|
})
|
|
181
157
|
return { client, stored }
|
|
182
158
|
}
|
|
@@ -219,7 +195,6 @@ describe('create with inline logo', () => {
|
|
|
219
195
|
throw new Error('upload failed')
|
|
220
196
|
},
|
|
221
197
|
},
|
|
222
|
-
verifiedTokens: { store: Store.memory() },
|
|
223
198
|
})
|
|
224
199
|
const response = await client['verified-tokens'].$post({
|
|
225
200
|
json: { ...novel, chainId: 42431, logo: svg },
|
|
@@ -297,7 +272,6 @@ describe('PUT /verified-tokens/:address/logo', () => {
|
|
|
297
272
|
stored.push({ content, key })
|
|
298
273
|
},
|
|
299
274
|
},
|
|
300
|
-
verifiedTokens: { store: Store.memory() },
|
|
301
275
|
})
|
|
302
276
|
return { client, stored }
|
|
303
277
|
}
|
|
@@ -375,7 +349,6 @@ describe('GET /verified-tokens/:address/logo', () => {
|
|
|
375
349
|
get: async (key) => objects.get(key),
|
|
376
350
|
put: async (key, content) => void objects.set(key, content),
|
|
377
351
|
},
|
|
378
|
-
verifiedTokens: { store: Store.memory() },
|
|
379
352
|
})
|
|
380
353
|
return { client, objects }
|
|
381
354
|
}
|