tapimo 0.1.0 → 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 +28 -15
- package/dist/ApiKey.d.ts +3 -1
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +1 -0
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +71 -3
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +117 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +7139 -4197
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +133 -329
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +11 -4
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +12 -4
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +2 -2
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +2 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +126 -53
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +104 -6
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +67 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +4 -1
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +115 -115
- package/dist/admin/apps/verified-tokens.js +1 -1
- 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} +49 -49
- 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} +468 -468
- 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} +304 -304
- 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} +6 -6
- 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} +62 -62
- package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
- package/dist/apps/{webhooks.js → data/routes/webhooks.js} +30 -26
- 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/Cli.d.ts +1 -1
- package/dist/cli/Cli.js +1 -1
- package/dist/cli/commands/admin.d.ts +1 -1
- package/dist/cli/commands/admin.js +2 -2
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/db/Db.d.ts +10 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +128 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +80 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +99 -0
- package/dist/db/Schema.js.map +1 -1
- 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 +44 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +89 -0
- package/dist/db/tables/organizations.js.map +1 -1
- 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/handlers/internal/executionError.d.ts.map +1 -1
- package/dist/handlers/internal/executionError.js +2 -0
- package/dist/handlers/internal/executionError.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +2 -6
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +11 -36
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +32 -2
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +34 -9
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/relay.d.ts +6 -2
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +16 -2
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +208 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +500 -21
- 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/Store.d.ts +7 -1
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +16 -2
- package/dist/internal/Store.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 +1 -1
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/package.json +31 -5
- package/src/ApiKey.ts +1 -0
- package/src/ApiKeys.test.ts +104 -1
- package/src/ApiKeys.ts +154 -1
- package/src/App.test.ts +11187 -179
- package/src/App.ts +200 -420
- package/src/Client.test-d.ts +306 -15
- package/src/Scope.ts +13 -4
- package/src/Webhooks.ts +2 -2
- package/src/admin/apps/api-keys.test.ts +51 -0
- package/src/admin/apps/api-keys.ts +84 -0
- package/src/admin/apps/scopes.test.ts +5 -1
- package/src/admin/apps/verified-tokens.ts +1 -1
- 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} +2 -2
- package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
- package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +3 -3
- 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} +1 -1
- 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} +26 -5
- package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
- package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +3 -3
- package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
- package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +44 -5
- package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
- package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +3 -3
- package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
- package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +2 -2
- package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
- package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +3 -3
- package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
- package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +2 -2
- package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
- package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +3 -3
- package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
- package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +6 -6
- package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +39 -35
- 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/Cli.ts +1 -1
- package/src/cli/commands/admin.ts +2 -2
- package/src/db/Db.ts +159 -0
- package/src/db/Schema.ts +137 -0
- package/src/db/tables/invitations.ts +198 -0
- package/src/db/tables/memberships.ts +208 -0
- package/src/db/tables/organizations.test.ts +37 -1
- package/src/db/tables/organizations.ts +105 -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/handlers/internal/executionError.ts +2 -0
- package/src/handlers/internal/multisig.test.ts +84 -10
- package/src/handlers/internal/multisig.ts +15 -50
- package/src/handlers/internal/sponsorship.ts +74 -15
- package/src/handlers/{internal/relay.localnet.test.ts → relay.test.ts} +2 -2
- package/src/handlers/relay.ts +23 -5
- package/src/internal/Auth.test.ts +316 -0
- package/src/internal/Auth.ts +691 -25
- 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/Store.test.ts +52 -0
- package/src/internal/Store.ts +24 -5
- package/src/internal/Tidx.local.test.ts +1 -1
- package/src/internal/VerifiedTokens.test.ts +1 -1
- package/src/internal/WebhookDestination.test.ts +1 -1
- package/src/internal/Webhooks.test.ts +4 -4
- package/src/internal/Webhooks.ts +1 -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/src/handlers/internal/multisig.localnet.test.ts +0 -146
- /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/Client.test-d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { Client } from 'tapimo'
|
|
2
2
|
import type * as z from 'zod/mini'
|
|
3
3
|
|
|
4
|
-
import * as Activities from './apps/activities.js'
|
|
5
|
-
import * as Balances from './apps/balances.js'
|
|
6
|
-
import * as Blocks from './apps/blocks.js'
|
|
7
|
-
import * as Exchanges from './apps/exchanges.js'
|
|
8
|
-
import * as FeeAmm from './apps/fee-amm.js'
|
|
9
|
-
import * as Indexer from './apps/indexer.js'
|
|
10
|
-
import * as
|
|
11
|
-
import * as
|
|
12
|
-
import * as
|
|
13
|
-
import * as
|
|
14
|
-
import * as
|
|
15
|
-
import * as
|
|
16
|
-
import * as
|
|
4
|
+
import * as Activities from './apps/data/routes/activities.js'
|
|
5
|
+
import * as Balances from './apps/data/routes/balances.js'
|
|
6
|
+
import * as Blocks from './apps/data/routes/blocks.js'
|
|
7
|
+
import * as Exchanges from './apps/data/routes/exchanges.js'
|
|
8
|
+
import * as FeeAmm from './apps/data/routes/fee-amm.js'
|
|
9
|
+
import * as Indexer from './apps/data/routes/indexer.js'
|
|
10
|
+
import * as Me from './apps/platform/routes/me.js'
|
|
11
|
+
import * as Orgs from './apps/platform/routes/orgs.js'
|
|
12
|
+
import * as Receipts from './apps/data/routes/receipts.js'
|
|
13
|
+
import * as Rpc from './apps/data/routes/rpc.js'
|
|
14
|
+
import * as Tokens from './apps/data/routes/tokens.js'
|
|
15
|
+
import * as Transactions from './apps/data/routes/transactions.js'
|
|
16
|
+
import * as Transfers from './apps/data/routes/transfers.js'
|
|
17
|
+
import * as VerifiedTokens from './apps/data/routes/verified-tokens.js'
|
|
18
|
+
import * as Webhooks from './apps/data/routes/webhooks.js'
|
|
17
19
|
|
|
18
20
|
type Access400<code extends string> = code | 'api_key_malformed'
|
|
19
21
|
type PaidAccessStatus = PublicAccessStatus | 402
|
|
@@ -97,6 +99,295 @@ describe('narrows responses by status', () => {
|
|
|
97
99
|
}
|
|
98
100
|
})
|
|
99
101
|
|
|
102
|
+
test('GET /v1/me', async () => {
|
|
103
|
+
const client = Client.create()
|
|
104
|
+
const res = await client.v1.me.$get()
|
|
105
|
+
|
|
106
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
107
|
+
|
|
108
|
+
switch (res.status) {
|
|
109
|
+
case 200: {
|
|
110
|
+
const json = await res.json()
|
|
111
|
+
expectTypeOf(json.id).toEqualTypeOf<z.output<typeof Me.schema.User>['id']>()
|
|
112
|
+
void json
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
case 403: {
|
|
116
|
+
const json = await res.json()
|
|
117
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'forbidden'>()
|
|
118
|
+
void json
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
case 404: {
|
|
122
|
+
const json = await res.json()
|
|
123
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'user_not_found'>()
|
|
124
|
+
void json
|
|
125
|
+
return
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test('POST /v1/orgs', async () => {
|
|
131
|
+
const client = Client.create()
|
|
132
|
+
const res = await client.v1.orgs.$post({ json: { name: 'Acme' } })
|
|
133
|
+
|
|
134
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 502>()
|
|
135
|
+
|
|
136
|
+
switch (res.status) {
|
|
137
|
+
case 200: {
|
|
138
|
+
const json = await res.json()
|
|
139
|
+
expectTypeOf(json.id).toEqualTypeOf<z.output<typeof Orgs.schema.Organization>['id']>()
|
|
140
|
+
void json
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
case 403: {
|
|
144
|
+
const json = await res.json()
|
|
145
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'forbidden'>()
|
|
146
|
+
void json
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('GET /v1/orgs/:orgId', async () => {
|
|
153
|
+
const client = Client.create()
|
|
154
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].$get({
|
|
155
|
+
param: { orgId: 'org_test' },
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404>()
|
|
159
|
+
|
|
160
|
+
switch (res.status) {
|
|
161
|
+
case 200: {
|
|
162
|
+
const json = await res.json()
|
|
163
|
+
expectTypeOf(json.name).toEqualTypeOf<string>()
|
|
164
|
+
void json
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
case 404: {
|
|
168
|
+
const json = await res.json()
|
|
169
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'organization_not_found'>()
|
|
170
|
+
void json
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
test('DELETE /v1/orgs/:orgId', async () => {
|
|
177
|
+
const client = Client.create()
|
|
178
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].$delete({
|
|
179
|
+
param: { orgId: 'org_test' },
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
183
|
+
|
|
184
|
+
switch (res.status) {
|
|
185
|
+
case 200: {
|
|
186
|
+
const json = await res.json()
|
|
187
|
+
expectTypeOf(json.id).toEqualTypeOf<string>()
|
|
188
|
+
void json
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
case 404: {
|
|
192
|
+
const json = await res.json()
|
|
193
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'organization_not_found'>()
|
|
194
|
+
void json
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
test('GET /v1/orgs/:orgId/projects/:projectId', async () => {
|
|
201
|
+
const client = Client.create()
|
|
202
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
|
|
203
|
+
':projectId{prj_[A-Za-z0-9_-]+}'
|
|
204
|
+
].$get({ param: { orgId: 'org_test', projectId: 'prj_test' } })
|
|
205
|
+
|
|
206
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404>()
|
|
207
|
+
|
|
208
|
+
switch (res.status) {
|
|
209
|
+
case 200: {
|
|
210
|
+
const json = await res.json()
|
|
211
|
+
expectTypeOf(json.environments[0]).toEqualTypeOf<'production' | 'sandbox' | undefined>()
|
|
212
|
+
void json
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
case 404: {
|
|
216
|
+
const json = await res.json()
|
|
217
|
+
expectTypeOf(json.error.code).toEqualTypeOf<
|
|
218
|
+
'organization_not_found' | 'project_not_found'
|
|
219
|
+
>()
|
|
220
|
+
void json
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
test('DELETE /v1/orgs/:orgId/projects/:projectId', async () => {
|
|
227
|
+
const client = Client.create()
|
|
228
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
|
|
229
|
+
':projectId{prj_[A-Za-z0-9_-]+}'
|
|
230
|
+
].$delete({ param: { orgId: 'org_test', projectId: 'prj_test' } })
|
|
231
|
+
|
|
232
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
233
|
+
|
|
234
|
+
switch (res.status) {
|
|
235
|
+
case 200: {
|
|
236
|
+
const json = await res.json()
|
|
237
|
+
expectTypeOf(json.id).toEqualTypeOf<string>()
|
|
238
|
+
void json
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
case 404: {
|
|
242
|
+
const json = await res.json()
|
|
243
|
+
expectTypeOf(json.error.code).toEqualTypeOf<
|
|
244
|
+
'organization_not_found' | 'project_not_found'
|
|
245
|
+
>()
|
|
246
|
+
void json
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
test('POST /v1/orgs/:orgId/projects/:projectId/api-keys', async () => {
|
|
253
|
+
const client = Client.create()
|
|
254
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
|
|
255
|
+
':projectId{prj_[A-Za-z0-9_-]+}'
|
|
256
|
+
]['api-keys'].$post({
|
|
257
|
+
json: { scopes: ['data:read'] },
|
|
258
|
+
param: { orgId: 'org_test', projectId: 'prj_test' },
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
262
|
+
|
|
263
|
+
switch (res.status) {
|
|
264
|
+
case 200: {
|
|
265
|
+
const json = await res.json()
|
|
266
|
+
expectTypeOf(json.token).toEqualTypeOf<string>()
|
|
267
|
+
expectTypeOf(json.id).toEqualTypeOf<string>()
|
|
268
|
+
void json
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
test('DELETE /v1/orgs/:orgId/projects/:projectId/api-keys/:keyId', async () => {
|
|
275
|
+
const client = Client.create()
|
|
276
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
|
|
277
|
+
':projectId{prj_[A-Za-z0-9_-]+}'
|
|
278
|
+
]['api-keys'][':keyId{key_[A-Za-z0-9_-]+}'].$delete({
|
|
279
|
+
param: { keyId: 'key_test', orgId: 'org_test', projectId: 'prj_test' },
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
283
|
+
|
|
284
|
+
switch (res.status) {
|
|
285
|
+
case 404: {
|
|
286
|
+
const json = await res.json()
|
|
287
|
+
expectTypeOf(json.error.code).toEqualTypeOf<
|
|
288
|
+
| 'api_key_not_found'
|
|
289
|
+
| 'api_keys_not_enabled'
|
|
290
|
+
| 'organization_not_found'
|
|
291
|
+
| 'project_not_found'
|
|
292
|
+
>()
|
|
293
|
+
void json
|
|
294
|
+
return
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
test('GET /v1/orgs/:orgId/members', async () => {
|
|
300
|
+
const client = Client.create()
|
|
301
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].members.$get({
|
|
302
|
+
param: { orgId: 'org_test' },
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
306
|
+
|
|
307
|
+
switch (res.status) {
|
|
308
|
+
case 200: {
|
|
309
|
+
const json = await res.json()
|
|
310
|
+
expectTypeOf(json.data[0]!.role).toEqualTypeOf<'admin' | 'member' | 'owner'>()
|
|
311
|
+
void json
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
test('PATCH /v1/orgs/:orgId/members/:userId', async () => {
|
|
318
|
+
const client = Client.create()
|
|
319
|
+
const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].members[
|
|
320
|
+
':userId{usr_[A-Za-z0-9_-]+}'
|
|
321
|
+
].$patch({ json: { role: 'admin' }, param: { orgId: 'org_test', userId: 'usr_test' } })
|
|
322
|
+
|
|
323
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 409 | 502>()
|
|
324
|
+
|
|
325
|
+
switch (res.status) {
|
|
326
|
+
case 409: {
|
|
327
|
+
const json = await res.json()
|
|
328
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'last_owner'>()
|
|
329
|
+
void json
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
test('POST /v1/invitations/:invitationId/accept', async () => {
|
|
336
|
+
const client = Client.create()
|
|
337
|
+
const res = await client.v1.invitations[':invitationId{inv_[A-Za-z0-9_-]+}'].accept.$post({
|
|
338
|
+
param: { invitationId: 'inv_test' },
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
|
|
342
|
+
|
|
343
|
+
switch (res.status) {
|
|
344
|
+
case 200: {
|
|
345
|
+
const json = await res.json()
|
|
346
|
+
expectTypeOf(json.role).toEqualTypeOf<'admin' | 'member' | 'owner'>()
|
|
347
|
+
void json
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
case 404: {
|
|
351
|
+
const json = await res.json()
|
|
352
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'invitation_not_found'>()
|
|
353
|
+
void json
|
|
354
|
+
return
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
test('GET /v1/orgs', async () => {
|
|
360
|
+
const client = Client.create()
|
|
361
|
+
const res = await client.v1.orgs.$get()
|
|
362
|
+
|
|
363
|
+
expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 502>()
|
|
364
|
+
|
|
365
|
+
switch (res.status) {
|
|
366
|
+
case 200: {
|
|
367
|
+
const json = await res.json()
|
|
368
|
+
expectTypeOf(json.data[0]!.id).toEqualTypeOf<
|
|
369
|
+
z.output<typeof Orgs.schema.listOrganizations.Response>['data'][number]['id']
|
|
370
|
+
>()
|
|
371
|
+
void json
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
case 403: {
|
|
375
|
+
const json = await res.json()
|
|
376
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'forbidden'>()
|
|
377
|
+
expectTypeOf(json.error.message).toEqualTypeOf<string>()
|
|
378
|
+
void json
|
|
379
|
+
return
|
|
380
|
+
}
|
|
381
|
+
case 502: {
|
|
382
|
+
const json = await res.json()
|
|
383
|
+
expectTypeOf(json.error.code).toEqualTypeOf<'upstream_error'>()
|
|
384
|
+
expectTypeOf(json.error.message).toEqualTypeOf<string>()
|
|
385
|
+
void json
|
|
386
|
+
return
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
|
|
100
391
|
test('GET /v1/blocks/:block', async () => {
|
|
101
392
|
const client = Client.create()
|
|
102
393
|
const res = await client.v1.blocks[':block'].$get({ param: { block: '1' } })
|
|
@@ -1176,7 +1467,7 @@ describe('narrows responses by status', () => {
|
|
|
1176
1467
|
|
|
1177
1468
|
test('POST /rpc/:chain', async () => {
|
|
1178
1469
|
const client = Client.create()
|
|
1179
|
-
const res = await client.rpc[':chain{mainnet|testnet|[0-9]+}?'].$post({
|
|
1470
|
+
const res = await client.rpc[':chain{(mainnet|testnet|[0-9]+)}?'].$post({
|
|
1180
1471
|
param: { chain: undefined },
|
|
1181
1472
|
})
|
|
1182
1473
|
|
|
@@ -1208,7 +1499,7 @@ describe('narrows responses by status', () => {
|
|
|
1208
1499
|
|
|
1209
1500
|
test('POST /rpc/:chain testnet shortcut', async () => {
|
|
1210
1501
|
const client = Client.create()
|
|
1211
|
-
const res = await client.rpc[':chain{mainnet|testnet|[0-9]+}?'].$post({
|
|
1502
|
+
const res = await client.rpc[':chain{(mainnet|testnet|[0-9]+)}?'].$post({
|
|
1212
1503
|
param: { chain: 'testnet' },
|
|
1213
1504
|
})
|
|
1214
1505
|
|
package/src/Scope.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The issuable API-key scope vocabulary: the single source of truth for the
|
|
3
3
|
* `/scopes` catalog, for key minting (`ApiKeys.mint`), and for the scopes
|
|
4
|
-
* required by route policies (`Auth.policy`). Exposing it publicly lets
|
|
5
|
-
* tooling
|
|
6
|
-
* server enforces.
|
|
4
|
+
* required by route policies (`Auth.policy`). Exposing it publicly lets super
|
|
5
|
+
* admin tooling validate scopes against the same list the server enforces.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
/**
|
|
@@ -38,7 +37,11 @@ export const catalog = [
|
|
|
38
37
|
},
|
|
39
38
|
{
|
|
40
39
|
description: 'Fill and submit transactions through the relay.',
|
|
41
|
-
scope: 'rpc-relay',
|
|
40
|
+
scope: 'rpc-relay:read',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
description: 'Sponsor transaction fees through the relay as the managed fee payer.',
|
|
44
|
+
scope: 'rpc-relay:sponsor',
|
|
42
45
|
},
|
|
43
46
|
{
|
|
44
47
|
description: 'Read webhook subscriptions.',
|
|
@@ -52,3 +55,9 @@ export const catalog = [
|
|
|
52
55
|
|
|
53
56
|
/** Issuable API-key scope identifier — the union of every {@link catalog} entry. */
|
|
54
57
|
export type Id = (typeof catalog)[number]['scope']
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Scopes a session may self-mint through the developer platform. Empty: every
|
|
61
|
+
* scope requires super admin issuance.
|
|
62
|
+
*/
|
|
63
|
+
export const selfServe: readonly Id[] = []
|
package/src/Webhooks.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as AppWebhooks from './apps/webhooks.js'
|
|
1
|
+
import * as AppWebhooks from './apps/data/routes/webhooks.js'
|
|
2
2
|
import * as Db from './db/Db.js'
|
|
3
3
|
import * as MetricSink from './internal/MetricSink.js'
|
|
4
4
|
import * as Store from './internal/Store.js'
|
|
@@ -16,7 +16,7 @@ export * from './internal/Webhooks.js'
|
|
|
16
16
|
// type delivery bodies: `Webhooks.schema.Envelope` (a discriminated union on
|
|
17
17
|
// `type`), plus the per-event `TransferEvent` / `TransactionEvent` / `PingEvent`
|
|
18
18
|
// payloads. Infer a type with `z.infer<typeof Webhooks.schema.Envelope>`.
|
|
19
|
-
export { eventTypes, schema } from './apps/webhooks.js'
|
|
19
|
+
export { eventTypes, schema } from './apps/data/routes/webhooks.js'
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Builds a scheduled webhook poller bound to a state store and chain config.
|
|
@@ -155,3 +155,54 @@ describe('DELETE /api-keys/:id', () => {
|
|
|
155
155
|
expect(body.error?.code).toMatchInlineSnapshot(`"not_found"`)
|
|
156
156
|
})
|
|
157
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
|
+
})
|
|
@@ -53,6 +53,37 @@ export namespace schema {
|
|
|
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. */
|
|
@@ -76,9 +107,30 @@ export namespace schema {
|
|
|
76
107
|
* returning the one-time token.
|
|
77
108
|
* - `GET /` lists key records (metadata only), optionally filtered by `orgId`.
|
|
78
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.
|
|
79
112
|
*/
|
|
80
113
|
export function apiKeys() {
|
|
81
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
|
+
)
|
|
82
134
|
.post(
|
|
83
135
|
'/',
|
|
84
136
|
OpenApi.validate('json', schema.createApiKey.Body, {
|
|
@@ -153,4 +205,36 @@ export function apiKeys() {
|
|
|
153
205
|
return c.json(Response.validated(schema.revokeApiKey.Response, { id }))
|
|
154
206
|
},
|
|
155
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
|
+
)
|
|
156
240
|
}
|
|
@@ -24,7 +24,11 @@ describe('GET /scopes', () => {
|
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
"description": "Fill and submit transactions through the relay.",
|
|
27
|
-
"scope": "rpc-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",
|
|
28
32
|
},
|
|
29
33
|
{
|
|
30
34
|
"description": "Read webhook subscriptions.",
|
|
@@ -6,7 +6,7 @@ import * as Response from '../../internal/Response.js'
|
|
|
6
6
|
import * as Schema from '../../internal/Schema.js'
|
|
7
7
|
import * as Db from '../../db/Db.js'
|
|
8
8
|
import * as VerifiedTokens from '../../internal/VerifiedTokens.js'
|
|
9
|
-
import { schema as readSchema } from '../../apps/verified-tokens.js'
|
|
9
|
+
import { schema as readSchema } from '../../apps/data/routes/verified-tokens.js'
|
|
10
10
|
import type * as App from '../App.js'
|
|
11
11
|
|
|
12
12
|
/** Required `chainId` query: admin mutations always address a chain explicitly. */
|
|
@@ -11,7 +11,7 @@ export type Asset = {
|
|
|
11
11
|
|
|
12
12
|
/** The prerendered SPA shell HTML (assets normalized to relative URLs). */
|
|
13
13
|
export const shell =
|
|
14
|
-
'<!DOCTYPE html><html lang="en" data-theme="dark" data-regen-radius="none"><head><meta charSet="utf-8"/><meta content="width=device-width, initial-scale=1" name="viewport"/><link rel="stylesheet" href="./assets/styles-Cd7Fp5b_.css" data-precedence="default"/><title>Tempo API Admin</title><link rel="modulepreload" href="./assets/index-CPTihwDe.js"/><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20269%20269%22%3E%3Crect%20width%3D%22269%22%20height%3D%22269%22%20fill%3D%22%23000%22%2F%3E%3Cpath%20d%3D%22M123.273%20190.794H93.445L121.09%20105.318H85.7334L93.445%2080.2642H191.95L184.238%20105.318H150.773L123.273%20190.794Z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E"/></head><body><div id="root"></div><script class="$tsr" id="$tsr-stream-barrier">(self.$R=self.$R||{})["tsr"]=[];self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]};$_TSR.router=($R=>$R[0]={manifest:$R[1]={routes:$R[2]={__root__:$R[3]={preloads:$R[4]=["./assets/index-CPTihwDe.js"],scripts:$R[5]=[$R[6]={attrs:$R[7]={type:"module",async:!0,src:"./assets/index-CPTihwDe.js"}}]}}},matches:$R[8]=[$R[9]={i:"__root__\u0000",u:
|
|
14
|
+
'<!DOCTYPE html><html lang="en" data-theme="dark" data-regen-radius="none"><head><meta charSet="utf-8"/><meta content="width=device-width, initial-scale=1" name="viewport"/><link rel="stylesheet" href="./assets/styles-Cd7Fp5b_.css" data-precedence="default"/><title>Tempo API Admin</title><link rel="modulepreload" href="./assets/index-CPTihwDe.js"/><link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20269%20269%22%3E%3Crect%20width%3D%22269%22%20height%3D%22269%22%20fill%3D%22%23000%22%2F%3E%3Cpath%20d%3D%22M123.273%20190.794H93.445L121.09%20105.318H85.7334L93.445%2080.2642H191.95L184.238%20105.318H150.773L123.273%20190.794Z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E"/></head><body><div id="root"></div><script class="$tsr" id="$tsr-stream-barrier">(self.$R=self.$R||{})["tsr"]=[];self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]};$_TSR.router=($R=>$R[0]={manifest:$R[1]={routes:$R[2]={__root__:$R[3]={preloads:$R[4]=["./assets/index-CPTihwDe.js"],scripts:$R[5]=[$R[6]={attrs:$R[7]={type:"module",async:!0,src:"./assets/index-CPTihwDe.js"}}]}}},matches:$R[8]=[$R[9]={i:"__root__\u0000",u:1783292569178,s:"success",ssr:!0}],lastMatchId:"__root__\u0000"})($R["tsr"]);$_TSR.e();document.currentScript.remove()</script><script type="module" async="" src="./assets/index-CPTihwDe.js"></script></body></html>'
|
|
15
15
|
|
|
16
16
|
/** Content-hashed UI assets, keyed by their path under the mount (e.g. `assets/index-*.js`). */
|
|
17
17
|
export const assets: Record<string, Asset> = {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { App, Store } from 'tapimo'
|
|
2
|
+
import { data, platform, relay } from 'tapimo/apps'
|
|
3
|
+
import * as TestApp from '../../test/App.js'
|
|
4
|
+
|
|
5
|
+
// Each test mounts one group and asserts its routes exist while the omitted
|
|
6
|
+
// group's are absent (404 and not in the document). Only `paths` are checked;
|
|
7
|
+
// tags/schemes stay a superset (Decision C).
|
|
8
|
+
|
|
9
|
+
/** Paths (sans method) present in a composed app's OpenAPI document. */
|
|
10
|
+
async function paths(app: { request: (path: string) => Promise<Response> | Response }) {
|
|
11
|
+
const res = await app.request('/openapi.json')
|
|
12
|
+
const spec = (await res.json()) as { paths: Record<string, unknown> }
|
|
13
|
+
return Object.keys(spec.paths)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('data()', () => {
|
|
17
|
+
test('mounts data routes and omits platform routes', async () => {
|
|
18
|
+
const app = App.create({ db: TestApp.database() }).route('/', data())
|
|
19
|
+
|
|
20
|
+
const keys = await paths(app)
|
|
21
|
+
expect(keys.some((path) => path.startsWith('/v1/tokens'))).toBe(true)
|
|
22
|
+
expect(keys.some((path) => path.startsWith('/v1/blocks'))).toBe(true)
|
|
23
|
+
expect(keys.some((path) => path.startsWith('/v1/orgs'))).toBe(false)
|
|
24
|
+
expect(keys.some((path) => path.startsWith('/v1/me'))).toBe(false)
|
|
25
|
+
|
|
26
|
+
// The omitted platform route resolves to a 404 (never mounted), not a 401.
|
|
27
|
+
const orgs = await app.request('/v1/orgs')
|
|
28
|
+
expect(orgs.status).toBe(404)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('relay()', () => {
|
|
33
|
+
test('mounts the relay after data() and stays out of the document', async () => {
|
|
34
|
+
const composed = App.create({ db: TestApp.database() }).route('/', data()).route('/', relay())
|
|
35
|
+
|
|
36
|
+
// Mounted but default-closed and hidden: unauthenticated requests are
|
|
37
|
+
// refused, and the path never appears in the OpenAPI document.
|
|
38
|
+
const mounted = await composed.request('/rpc/relay')
|
|
39
|
+
expect(mounted.status).toBe(401)
|
|
40
|
+
expect((await paths(composed)).some((path) => path.startsWith('/rpc/relay'))).toBe(false)
|
|
41
|
+
|
|
42
|
+
// Without the relay group, the data group no longer serves the path.
|
|
43
|
+
const dataOnly = App.create({ db: TestApp.database() }).route('/', data())
|
|
44
|
+
expect((await dataOnly.request('/rpc/relay')).status).toBe(404)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('platform()', () => {
|
|
49
|
+
test('mounts platform routes and omits data routes', async () => {
|
|
50
|
+
const app = App.create({
|
|
51
|
+
auth: { session: { wallet: { origin: 'https://test.example' } } },
|
|
52
|
+
db: TestApp.database(),
|
|
53
|
+
kv: { store: Store.memory() },
|
|
54
|
+
}).route('/', platform())
|
|
55
|
+
|
|
56
|
+
const keys = await paths(app)
|
|
57
|
+
expect(keys.some((path) => path.startsWith('/v1/orgs'))).toBe(true)
|
|
58
|
+
expect(keys.some((path) => path.startsWith('/v1/me'))).toBe(true)
|
|
59
|
+
expect(keys.some((path) => path.startsWith('/v1/tokens'))).toBe(false)
|
|
60
|
+
expect(keys.some((path) => path.startsWith('/v1/blocks'))).toBe(false)
|
|
61
|
+
|
|
62
|
+
// The omitted data route resolves to a 404 (never mounted).
|
|
63
|
+
const token = await app.request('/v1/tokens/0x20c0000000000000000000000000000000000000')
|
|
64
|
+
expect(token.status).toBe(404)
|
|
65
|
+
})
|
|
66
|
+
})
|