tapimo 0.11.0 → 0.13.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/dist/App.d.ts +6396 -4575
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +39 -4
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +15 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +7 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts +2 -0
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +17 -0
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +176 -78
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +84 -4
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +54 -0
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +123 -9
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +60 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +4 -2
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +90 -90
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +71 -71
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/Zones.d.ts +16 -16
- package/dist/apps/Zones.js +4 -4
- package/dist/apps/data/App.d.ts +1699 -749
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +58 -9
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +62 -0
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
- package/dist/apps/data/ZoneSelection.js +44 -0
- package/dist/apps/data/ZoneSelection.js.map +1 -0
- package/dist/apps/data/routes/activities.d.ts +2417 -50
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +1896 -1293
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +471 -340
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +12 -12
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +44 -17
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +42 -42
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +22 -12
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +179 -179
- package/dist/apps/data/routes/earn.d.ts +144 -19
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +160 -28
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +719 -13
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +16 -13
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +2 -2
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +9 -11
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +34 -34
- package/dist/apps/data/routes/receipts.d.ts +363 -263
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +29 -11
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.js +24 -10
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +13 -13
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +16 -15
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +112 -98
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +85 -35
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +7 -2
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +38 -18
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +1 -1
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +25 -21
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +1 -1
- package/dist/apps/data/routes/valuation.d.ts.map +1 -1
- package/dist/apps/data/routes/valuation.js +12 -7
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +3 -3
- package/dist/apps/data/routes/webhooks.d.ts +15 -15
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +2 -2
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +32 -32
- package/dist/apps/data/routes/zones.js +1 -1
- package/dist/apps/funding/App.d.ts +38 -27
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.js +5 -4
- package/dist/apps/funding/routes/chains.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +24 -19
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/providers.d.ts +13 -13
- package/dist/apps/funding/routes/providers.d.ts.map +1 -1
- package/dist/apps/funding/routes/providers.js +3 -2
- package/dist/apps/funding/routes/providers.js.map +1 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
- package/dist/apps/funding/routes/quotes.js +2 -2
- package/dist/apps/funding/routes/quotes.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +60 -48
- package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
- package/dist/apps/funding/routes/transfers.js +27 -19
- package/dist/apps/funding/routes/transfers.js.map +1 -1
- package/dist/apps/management/App.d.ts +4558 -3700
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +19 -6
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +786 -175
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +312 -34
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +103 -30
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +91 -32
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +35 -35
- package/dist/apps/management/routes/faucet.d.ts.map +1 -1
- package/dist/apps/management/routes/faucet.js +23 -12
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +46 -13
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +79 -29
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +120 -75
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +100 -41
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +5 -5
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +14 -10
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +99 -78
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +37 -18
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +48 -8
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +48 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +108 -46
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +72 -21
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +8 -5
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +82 -82
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +41 -31
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +35 -7
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +36 -17
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +200 -183
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +80 -35
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +12 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/db/Db.d.ts +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +52 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +26 -3
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +24 -5
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +5 -0
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/fundingCatalog.d.ts +4 -2
- package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
- package/dist/db/tables/fundingCatalog.js +5 -1
- package/dist/db/tables/fundingCatalog.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +10 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
- package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
- package/dist/db/tables/webhookQueueCompletions.js +32 -0
- package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
- package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +68 -47
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +29 -5
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +9 -0
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/internal/Auth.d.ts +11 -2
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +19 -6
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +11 -7
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +43 -4
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +167 -0
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/Fetch.d.ts +23 -0
- package/dist/internal/Fetch.d.ts.map +1 -0
- package/dist/internal/Fetch.js +26 -0
- package/dist/internal/Fetch.js.map +1 -0
- package/dist/internal/Log.d.ts +3 -1
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +16 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +30 -24
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +140 -41
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +14 -9
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +16 -5
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +11 -10
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +14 -9
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +28 -6
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +121 -25
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +2 -0
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +23 -6
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Timeout.d.ts +36 -0
- package/dist/internal/Timeout.d.ts.map +1 -0
- package/dist/internal/Timeout.js +37 -0
- package/dist/internal/Timeout.js.map +1 -0
- package/dist/internal/Timing.d.ts +9 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +7 -0
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/WebhookDestination.d.ts.map +1 -1
- package/dist/internal/WebhookDestination.js +3 -0
- package/dist/internal/WebhookDestination.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +29 -12
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +37 -20
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/Action.d.ts +9 -0
- package/dist/internal/funding/Action.d.ts.map +1 -1
- package/dist/internal/funding/Action.js +16 -8
- package/dist/internal/funding/Action.js.map +1 -1
- package/dist/internal/funding/Catalog.d.ts +9 -2
- package/dist/internal/funding/Catalog.d.ts.map +1 -1
- package/dist/internal/funding/Catalog.js +19 -8
- package/dist/internal/funding/Catalog.js.map +1 -1
- package/dist/internal/funding/Deposit.d.ts +2 -2
- package/dist/internal/funding/Deposit.d.ts.map +1 -1
- package/dist/internal/funding/Deposit.js +9 -8
- package/dist/internal/funding/Deposit.js.map +1 -1
- package/dist/internal/funding/DepositAddress.d.ts +4 -4
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
- package/dist/internal/funding/DepositAddress.js +9 -8
- package/dist/internal/funding/DepositAddress.js.map +1 -1
- package/dist/internal/funding/Provider.d.ts +68 -13
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +42 -20
- package/dist/internal/funding/Provider.js.map +1 -1
- package/dist/internal/funding/Transfer.d.ts +13 -12
- package/dist/internal/funding/Transfer.d.ts.map +1 -1
- package/dist/internal/funding/Transfer.js +23 -21
- package/dist/internal/funding/Transfer.js.map +1 -1
- package/dist/internal/funding/providers/stargate.d.ts +38 -0
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
- package/dist/internal/funding/providers/stargate.js +277 -0
- package/dist/internal/funding/providers/stargate.js.map +1 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +1 -0
- package/dist/internal/index.js.map +1 -1
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +3 -3
- package/src/App.test.ts +148 -0
- package/src/App.ts +45 -4
- package/src/Assets.test.ts +18 -0
- package/src/Assets.ts +22 -0
- package/src/Client.test-d.ts +311 -16
- package/src/Scope.test.ts +20 -0
- package/src/Scope.ts +16 -0
- package/src/admin/apps/api-keys.test.ts +75 -0
- package/src/admin/apps/api-keys.ts +64 -0
- package/src/admin/apps/earn-vaults.test.ts +143 -0
- package/src/admin/apps/earn-vaults.ts +84 -7
- package/src/admin/apps/organizations.ts +6 -2
- package/src/admin/ui/src/lib/api-keys.ts +19 -0
- package/src/admin/ui/src/routes/api-keys.tsx +125 -2
- package/src/admin/ui.generated.ts +71 -71
- package/src/apps/Zones.test.ts +4 -4
- package/src/apps/Zones.ts +4 -4
- package/src/apps/composition.test.ts +1 -1
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +58 -10
- package/src/apps/data/ZoneSelection.test.ts +196 -0
- package/src/apps/data/ZoneSelection.ts +108 -0
- package/src/apps/data/routes/activities.test.ts +1843 -2
- package/src/apps/data/routes/activities.ts +2211 -1388
- package/src/apps/data/routes/balances.ts +134 -98
- package/src/apps/data/routes/blocks.test.ts +533 -0
- package/src/apps/data/routes/blocks.ts +36 -17
- package/src/apps/data/routes/earn.test.ts +187 -25
- package/src/apps/data/routes/earn.ts +228 -32
- package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
- package/src/apps/data/routes/exchanges.test.ts +31 -1
- package/src/apps/data/routes/exchanges.ts +19 -15
- package/src/apps/data/routes/fee-amm.ts +18 -11
- package/src/apps/data/routes/receipts.ts +48 -17
- package/src/apps/data/routes/rpc.test.ts +75 -0
- package/src/apps/data/routes/rpc.ts +23 -9
- package/src/apps/data/routes/tokenlist.ts +21 -18
- package/src/apps/data/routes/tokens.test.ts +607 -0
- package/src/apps/data/routes/tokens.ts +312 -231
- package/src/apps/data/routes/transactions.ts +69 -30
- package/src/apps/data/routes/transfers.test.ts +424 -3
- package/src/apps/data/routes/transfers.ts +57 -36
- package/src/apps/data/routes/valuation.ts +94 -78
- package/src/apps/data/routes/webhooks.ts +6 -2
- package/src/apps/data/routes/zones.test.ts +21 -15
- package/src/apps/data/routes/zones.ts +1 -1
- package/src/apps/funding/routes/chains.test.ts +211 -7
- package/src/apps/funding/routes/chains.ts +19 -12
- package/src/apps/funding/routes/deposit-addresses.test.ts +416 -0
- package/src/apps/funding/routes/deposit-addresses.ts +101 -84
- package/src/apps/funding/routes/providers.ts +9 -5
- package/src/apps/funding/routes/quotes.test.ts +42 -0
- package/src/apps/funding/routes/quotes.ts +8 -5
- package/src/apps/funding/routes/transfers.test.ts +430 -40
- package/src/apps/funding/routes/transfers.ts +76 -59
- package/src/apps/management/Billing.test.ts +26 -0
- package/src/apps/management/Billing.ts +24 -7
- package/src/apps/management/routes/api-keys.test.ts +398 -0
- package/src/apps/management/routes/api-keys.ts +481 -145
- package/src/apps/management/routes/billing.test.ts +209 -0
- package/src/apps/management/routes/billing.ts +254 -177
- package/src/apps/management/routes/faucet.test.ts +39 -0
- package/src/apps/management/routes/faucet.ts +75 -41
- package/src/apps/management/routes/invitations.test.ts +216 -0
- package/src/apps/management/routes/invitations.ts +186 -109
- package/src/apps/management/routes/invite-links.test.ts +263 -1
- package/src/apps/management/routes/invite-links.ts +295 -214
- package/src/apps/management/routes/me.test.ts +49 -0
- package/src/apps/management/routes/me.ts +42 -32
- package/src/apps/management/routes/members.test.ts +124 -1
- package/src/apps/management/routes/members.ts +81 -51
- package/src/apps/management/routes/orgs.test.ts +176 -0
- package/src/apps/management/routes/orgs.ts +101 -59
- package/src/apps/management/routes/projects.test.ts +183 -0
- package/src/apps/management/routes/projects.ts +124 -60
- package/src/apps/management/routes/scopes.test.ts +44 -0
- package/src/apps/management/routes/scopes.ts +37 -28
- package/src/apps/management/routes/usage.test.ts +92 -0
- package/src/apps/management/routes/usage.ts +186 -151
- package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
- package/src/apps/management/routes/verified-token-requests.ts +166 -133
- package/src/apps/management/routes/webhooks.test.ts +234 -0
- package/src/apps/management/routes/webhooks.ts +191 -78
- package/src/apps/mpp/internal/Adapter.ts +13 -1
- package/src/db/Db.test.ts +41 -0
- package/src/db/Db.ts +75 -1
- package/src/db/Schema.ts +33 -5
- package/src/db/tables/earnVaults.test.ts +22 -0
- package/src/db/tables/earnVaults.ts +11 -1
- package/src/db/tables/fundingCatalog.test.ts +16 -2
- package/src/db/tables/fundingCatalog.ts +9 -3
- package/src/db/tables/webhookDeliveries.ts +13 -0
- package/src/db/tables/webhookQueueCompletions.ts +55 -0
- package/src/db/tables/webhookQueueEvents.ts +95 -61
- package/src/db/tables/webhookSubscriptions.ts +45 -6
- package/src/handlers/internal/utils.test.ts +53 -0
- package/src/handlers/internal/utils.ts +15 -0
- package/src/internal/Auth.ts +35 -9
- package/src/internal/Cache.ts +14 -7
- package/src/internal/EarnVaults.capabilities.test.ts +33 -0
- package/src/internal/EarnVaults.test.ts +79 -0
- package/src/internal/EarnVaults.ts +277 -0
- package/src/internal/Fetch.test.ts +46 -0
- package/src/internal/Fetch.ts +56 -0
- package/src/internal/Log.test.ts +21 -0
- package/src/internal/Log.ts +20 -5
- package/src/internal/OpenApi.ts +177 -51
- package/src/internal/Response.test.ts +95 -0
- package/src/internal/Response.ts +41 -3
- package/src/internal/Schema.test.ts +18 -0
- package/src/internal/Schema.ts +19 -9
- package/src/internal/Store.test.ts +364 -0
- package/src/internal/Store.ts +153 -27
- package/src/internal/Tidx.test.ts +21 -1
- package/src/internal/Tidx.ts +23 -6
- package/src/internal/Timeout.test.ts +35 -0
- package/src/internal/Timeout.ts +73 -0
- package/src/internal/Timing.ts +16 -0
- package/src/internal/WebhookDestination.ts +3 -0
- package/src/internal/Webhooks.test.ts +122 -8
- package/src/internal/Webhooks.ts +59 -29
- package/src/internal/funding/Action.test.ts +41 -1
- package/src/internal/funding/Action.ts +69 -41
- package/src/internal/funding/Catalog.test.ts +34 -0
- package/src/internal/funding/Catalog.ts +28 -11
- package/src/internal/funding/Deposit.ts +71 -64
- package/src/internal/funding/DepositAddress.ts +50 -43
- package/src/internal/funding/Provider.test.ts +73 -0
- package/src/internal/funding/Provider.ts +246 -170
- package/src/internal/funding/Transfer.ts +133 -110
- package/src/internal/funding/providers/index.test.ts +22 -0
- package/src/internal/funding/providers/relay.test.ts +2 -2
- package/src/internal/funding/providers/stargate.test.ts +163 -0
- package/src/internal/funding/providers/stargate.ts +409 -0
- package/src/internal/index.test.ts +1 -0
- package/src/internal/index.ts +1 -0
- package/src/providers/index.test.ts +1 -0
- package/src/providers/index.ts +9 -0
|
@@ -20,6 +20,15 @@ const input = {
|
|
|
20
20
|
privateOutputTokens: [],
|
|
21
21
|
slug: 'btpathusd-earn',
|
|
22
22
|
vaultAddress,
|
|
23
|
+
zones: [],
|
|
24
|
+
} as const
|
|
25
|
+
|
|
26
|
+
const zoneInput = {
|
|
27
|
+
...input,
|
|
28
|
+
label: 'Moderato Earn',
|
|
29
|
+
slug: 'moderato-earn',
|
|
30
|
+
vaultAddress: TestEarn.zoneVaultAddress,
|
|
31
|
+
zones: [TestEarn.zoneRoute],
|
|
23
32
|
} as const
|
|
24
33
|
|
|
25
34
|
describe('authentication', () => {
|
|
@@ -179,6 +188,140 @@ describe('putVerifiedEarnVault', () => {
|
|
|
179
188
|
expect(await response.json()).toMatchObject({ error: { code: 'body_invalid' } })
|
|
180
189
|
})
|
|
181
190
|
|
|
191
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
192
|
+
'rejects duplicate Zone routes',
|
|
193
|
+
async () => {
|
|
194
|
+
const { app } = TestAdmin.setup({ zones: [TestEarn.zone] })
|
|
195
|
+
const response = await app.request('/earn/verified-vaults', {
|
|
196
|
+
body: JSON.stringify({
|
|
197
|
+
...zoneInput,
|
|
198
|
+
zones: [TestEarn.zoneRoute, TestEarn.zoneRoute],
|
|
199
|
+
}),
|
|
200
|
+
headers: { 'content-type': 'application/json' },
|
|
201
|
+
method: 'PUT',
|
|
202
|
+
})
|
|
203
|
+
expect(response.status).toBe(400)
|
|
204
|
+
expect(await response.json()).toMatchObject({
|
|
205
|
+
error: {
|
|
206
|
+
code: 'body_invalid',
|
|
207
|
+
details: [{ message: 'Zone 1424310003 is configured more than once.' }],
|
|
208
|
+
},
|
|
209
|
+
})
|
|
210
|
+
},
|
|
211
|
+
60_000,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
215
|
+
'rejects a router bound to a different vault',
|
|
216
|
+
async () => {
|
|
217
|
+
const { app } = TestAdmin.setup({ zones: [TestEarn.zone] })
|
|
218
|
+
const response = await app.request('/earn/verified-vaults', {
|
|
219
|
+
body: JSON.stringify({ ...zoneInput, vaultAddress }),
|
|
220
|
+
headers: { 'content-type': 'application/json' },
|
|
221
|
+
method: 'PUT',
|
|
222
|
+
})
|
|
223
|
+
expect(response.status).toBe(409)
|
|
224
|
+
expect(await response.json()).toEqual(
|
|
225
|
+
expect.objectContaining({
|
|
226
|
+
error: expect.objectContaining({
|
|
227
|
+
code: 'earn_vault_verification_failed',
|
|
228
|
+
details: expect.arrayContaining([
|
|
229
|
+
{ message: 'Earn router is configured for a different Earn vault.' },
|
|
230
|
+
]),
|
|
231
|
+
}),
|
|
232
|
+
}),
|
|
233
|
+
)
|
|
234
|
+
},
|
|
235
|
+
60_000,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
239
|
+
'verifies, stores, and preserves a Zone route',
|
|
240
|
+
async () => {
|
|
241
|
+
const { app, db } = TestAdmin.setup({ zones: [TestEarn.zone] })
|
|
242
|
+
const response = await app.request('/earn/verified-vaults', {
|
|
243
|
+
body: JSON.stringify(zoneInput),
|
|
244
|
+
headers: { 'content-type': 'application/json' },
|
|
245
|
+
method: 'PUT',
|
|
246
|
+
})
|
|
247
|
+
expect(response.status).toBe(200)
|
|
248
|
+
const vault = await TestApp.json(response, App.schema.putVerifiedEarnVault.Response)
|
|
249
|
+
expect(vault.capabilities).toMatchObject({ privateRouting: true, routerSwaps: true })
|
|
250
|
+
expect(vault.zones).toHaveLength(1)
|
|
251
|
+
expect(vault.zones?.[0]).toMatchObject(TestEarn.zoneRoute)
|
|
252
|
+
expect(vault.zone).toStrictEqual(
|
|
253
|
+
vault.zones?.[0]
|
|
254
|
+
? {
|
|
255
|
+
chainId: vault.zones[0].chainId,
|
|
256
|
+
inputTokens: vault.zones[0].inputTokens,
|
|
257
|
+
name: vault.zones[0].name,
|
|
258
|
+
outputTokens: vault.zones[0].outputTokens,
|
|
259
|
+
}
|
|
260
|
+
: null,
|
|
261
|
+
)
|
|
262
|
+
expect(vault.zones?.[0]?.inputTokens).toHaveLength(1)
|
|
263
|
+
expect(vault.zones?.[0]?.outputTokens).toStrictEqual(vault.zones?.[0]?.inputTokens)
|
|
264
|
+
|
|
265
|
+
const updatedResponse = await app.request('/earn/verified-vaults', {
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
chainId: zoneInput.chainId,
|
|
268
|
+
label: 'Updated Moderato Earn',
|
|
269
|
+
vaultAddress: zoneInput.vaultAddress,
|
|
270
|
+
}),
|
|
271
|
+
headers: { 'content-type': 'application/json' },
|
|
272
|
+
method: 'PUT',
|
|
273
|
+
})
|
|
274
|
+
expect(updatedResponse.status).toBe(200)
|
|
275
|
+
expect(
|
|
276
|
+
(await TestApp.json(updatedResponse, App.schema.putVerifiedEarnVault.Response)).zones,
|
|
277
|
+
).toStrictEqual(vault.zones)
|
|
278
|
+
expect(
|
|
279
|
+
await core_EarnVaults.get(db, {
|
|
280
|
+
chainId: zoneInput.chainId,
|
|
281
|
+
vaultAddress: zoneInput.vaultAddress,
|
|
282
|
+
}),
|
|
283
|
+
).toMatchObject({ zones: [TestEarn.zoneRoute] })
|
|
284
|
+
},
|
|
285
|
+
90_000,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
289
|
+
'migrates preserved private tokens to a verified Zone route',
|
|
290
|
+
async () => {
|
|
291
|
+
const { app, db } = TestAdmin.setup({ zones: [TestEarn.zone] })
|
|
292
|
+
await core_EarnVaults.upsert(db, {
|
|
293
|
+
...TestEarn.zoneVerifiedVault,
|
|
294
|
+
privateInputTokens: [asset],
|
|
295
|
+
privateOutputTokens: [asset],
|
|
296
|
+
zones: [],
|
|
297
|
+
})
|
|
298
|
+
const response = await app.request('/earn/verified-vaults', {
|
|
299
|
+
body: JSON.stringify({
|
|
300
|
+
chainId: zoneInput.chainId,
|
|
301
|
+
vaultAddress: zoneInput.vaultAddress,
|
|
302
|
+
zones: zoneInput.zones,
|
|
303
|
+
}),
|
|
304
|
+
headers: { 'content-type': 'application/json' },
|
|
305
|
+
method: 'PUT',
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
expect(response.status).toBe(200)
|
|
309
|
+
const vault = await TestApp.json(response, App.schema.putVerifiedEarnVault.Response)
|
|
310
|
+
expect(vault.zones).toHaveLength(1)
|
|
311
|
+
expect(
|
|
312
|
+
await core_EarnVaults.get(db, {
|
|
313
|
+
chainId: zoneInput.chainId,
|
|
314
|
+
vaultAddress: zoneInput.vaultAddress,
|
|
315
|
+
}),
|
|
316
|
+
).toMatchObject({
|
|
317
|
+
privateInputTokens: [asset],
|
|
318
|
+
privateOutputTokens: [asset],
|
|
319
|
+
zones: [TestEarn.zoneRoute],
|
|
320
|
+
})
|
|
321
|
+
},
|
|
322
|
+
90_000,
|
|
323
|
+
)
|
|
324
|
+
|
|
182
325
|
test.runIf(Runtime.get().mode === 'testnet')(
|
|
183
326
|
'rejects private tokens without a configured router',
|
|
184
327
|
async () => {
|
|
@@ -94,8 +94,11 @@ export namespace schema {
|
|
|
94
94
|
.check(z.describe('Custom vault slug, generated from the label when omitted.')),
|
|
95
95
|
vaultAddress: Schema.Address.check(
|
|
96
96
|
z.describe('Earn vault contract address.'),
|
|
97
|
-
z.meta({ examples: ['
|
|
97
|
+
z.meta({ examples: ['0x140a09b7c5826d34dfa38ea7bfde1c7e478c4408'] }),
|
|
98
98
|
),
|
|
99
|
+
zones: z
|
|
100
|
+
.optional(z.array(EarnVaults.schema.ZoneRoute))
|
|
101
|
+
.check(z.describe('Curated private Zone routes.')),
|
|
99
102
|
})
|
|
100
103
|
.check(z.describe('Curated fields used to verify and store one Earn vault.'))
|
|
101
104
|
|
|
@@ -240,11 +243,22 @@ export function earnVaults() {
|
|
|
240
243
|
const privateInputTokens = input.privateInputTokens ?? existing?.privateInputTokens ?? []
|
|
241
244
|
const privateOutputTokens =
|
|
242
245
|
input.privateOutputTokens ?? existing?.privateOutputTokens ?? []
|
|
246
|
+
const zoneRoutes = input.zones ?? existing?.zones ?? []
|
|
243
247
|
const hasPrivateInputs = privateInputTokens.length > 0
|
|
244
248
|
const hasPrivateOutputs = privateOutputTokens.length > 0
|
|
245
249
|
if (hasPrivateInputs !== hasPrivateOutputs)
|
|
246
250
|
return verificationFailed(c, 'Private input and output tokens must both be configured.')
|
|
247
|
-
|
|
251
|
+
const resolvedZoneRoutes = await EarnVaults.resolveZoneRoutes({
|
|
252
|
+
discovery,
|
|
253
|
+
getClient: c.get('getClient'),
|
|
254
|
+
routes: zoneRoutes,
|
|
255
|
+
zones: c.get('zones'),
|
|
256
|
+
})
|
|
257
|
+
const capabilities =
|
|
258
|
+
resolvedZoneRoutes.length > 0
|
|
259
|
+
? EarnVaults.addZoneRouteCapabilities(discovery.capabilities)
|
|
260
|
+
: discovery.capabilities
|
|
261
|
+
if (hasPrivateInputs && !capabilities.privateRouting)
|
|
248
262
|
return verificationFailed(c, 'The chain does not support private Earn routing.')
|
|
249
263
|
|
|
250
264
|
await core_EarnVaults.upsert(db, {
|
|
@@ -256,10 +270,11 @@ export function earnVaults() {
|
|
|
256
270
|
privateOutputTokens,
|
|
257
271
|
...(input.slug !== undefined ? { slug: input.slug } : {}),
|
|
258
272
|
vaultAddress: input.vaultAddress,
|
|
273
|
+
zones: zoneRoutes,
|
|
259
274
|
})
|
|
260
275
|
const data = await getVault(c, {
|
|
261
276
|
chainId: input.chainId,
|
|
262
|
-
include: ['access', 'capabilities', 'zone'],
|
|
277
|
+
include: ['access', 'capabilities', 'zone', 'zones'],
|
|
263
278
|
vaultAddress: input.vaultAddress,
|
|
264
279
|
})
|
|
265
280
|
return c.json(Response.validated(schema.putVerifiedEarnVault.Response, data), 200)
|
|
@@ -326,13 +341,19 @@ async function listVerifiedVaults(
|
|
|
326
341
|
const matches: listVerifiedVaults.Match[] = []
|
|
327
342
|
|
|
328
343
|
for (const record of candidates) {
|
|
329
|
-
const
|
|
344
|
+
const discovered = await resolveVault(c, {
|
|
330
345
|
chainId: options.chainId,
|
|
331
346
|
include: discoveryInclude(options),
|
|
332
347
|
vaultAddress: record.vaultAddress,
|
|
333
348
|
})
|
|
349
|
+
const { discovery, zoneRoutes } = await resolveVaultRoutes(c, {
|
|
350
|
+
capability: options.capability,
|
|
351
|
+
discovery: discovered,
|
|
352
|
+
include: options.include,
|
|
353
|
+
record,
|
|
354
|
+
})
|
|
334
355
|
if (!Earn.matchesVaultFilters(discovery, options)) continue
|
|
335
|
-
matches.push({ discovery, record })
|
|
356
|
+
matches.push({ discovery, record, zoneRoutes })
|
|
336
357
|
if (matches.length > options.limit) break
|
|
337
358
|
}
|
|
338
359
|
|
|
@@ -361,6 +382,8 @@ declare namespace listVerifiedVaults {
|
|
|
361
382
|
discovery: EarnVaults.Discovery
|
|
362
383
|
/** Curated registry row. */
|
|
363
384
|
record: core_EarnVaults.Record
|
|
385
|
+
/** Verified private Zone routes selected for serialization. */
|
|
386
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
364
387
|
}
|
|
365
388
|
|
|
366
389
|
type Options = z.output<typeof schema.listVerifiedEarnVaults.Query> & {
|
|
@@ -373,14 +396,20 @@ async function getVault(c: Context<App.Environment>, options: getVault.Options)
|
|
|
373
396
|
const db = Db.get(c.get('db'))
|
|
374
397
|
const record = await core_EarnVaults.get(db, options)
|
|
375
398
|
try {
|
|
376
|
-
const [
|
|
399
|
+
const [discovered, snapshot] = await Promise.all([
|
|
377
400
|
resolveVault(c, {
|
|
378
401
|
...options,
|
|
379
402
|
include: discoveryInclude({ capability: [], include: options.include }),
|
|
380
403
|
}),
|
|
381
404
|
VerifiedTokens.read(db, options.chainId),
|
|
382
405
|
])
|
|
383
|
-
|
|
406
|
+
const { discovery, zoneRoutes } = await resolveVaultRoutes(c, {
|
|
407
|
+
capability: [],
|
|
408
|
+
discovery: discovered,
|
|
409
|
+
include: options.include,
|
|
410
|
+
record,
|
|
411
|
+
})
|
|
412
|
+
return serializeVault(c, { ...options, discovery, record, snapshot, zoneRoutes })
|
|
384
413
|
} catch (cause) {
|
|
385
414
|
if (Earn.isIncompatible(cause)) throw new Earn.NotFoundError()
|
|
386
415
|
throw cause
|
|
@@ -421,6 +450,51 @@ declare namespace resolveVault {
|
|
|
421
450
|
}
|
|
422
451
|
}
|
|
423
452
|
|
|
453
|
+
async function resolveVaultRoutes(
|
|
454
|
+
c: Context<App.Environment>,
|
|
455
|
+
options: resolveVaultRoutes.Options,
|
|
456
|
+
): Promise<resolveVaultRoutes.Result> {
|
|
457
|
+
const { discovery, record } = options
|
|
458
|
+
if (!record || record.zones.length === 0) return { discovery, zoneRoutes: [] }
|
|
459
|
+
|
|
460
|
+
const includesRoutes = options.include.includes('zone') || options.include.includes('zones')
|
|
461
|
+
const needsCapabilities =
|
|
462
|
+
options.include.includes('capabilities') ||
|
|
463
|
+
options.capability.includes('privateRouting') ||
|
|
464
|
+
options.capability.includes('routerSwaps')
|
|
465
|
+
if (!includesRoutes && !needsCapabilities) return { discovery, zoneRoutes: [] }
|
|
466
|
+
|
|
467
|
+
const zoneRoutes = await EarnVaults.resolveZoneRoutes({
|
|
468
|
+
discovery,
|
|
469
|
+
getClient: c.get('getClient'),
|
|
470
|
+
routes: record.zones,
|
|
471
|
+
zones: c.get('zones'),
|
|
472
|
+
})
|
|
473
|
+
const capabilities = discovery.capabilities
|
|
474
|
+
if (needsCapabilities && !capabilities)
|
|
475
|
+
throw new Error('Earn vault capabilities were not resolved.')
|
|
476
|
+
return {
|
|
477
|
+
discovery: capabilities
|
|
478
|
+
? { ...discovery, capabilities: EarnVaults.addZoneRouteCapabilities(capabilities) }
|
|
479
|
+
: discovery,
|
|
480
|
+
zoneRoutes: includesRoutes ? zoneRoutes : [],
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
declare namespace resolveVaultRoutes {
|
|
485
|
+
type Options = {
|
|
486
|
+
capability: z.output<typeof schema.listVerifiedEarnVaults.Query>['capability']
|
|
487
|
+
discovery: EarnVaults.Discovery
|
|
488
|
+
include: z.output<typeof schema.getVerifiedEarnVault.Query>['include']
|
|
489
|
+
record?: core_EarnVaults.Record | undefined
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
type Result = {
|
|
493
|
+
discovery: EarnVaults.Discovery
|
|
494
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
424
498
|
async function serializeVault(
|
|
425
499
|
c: Context<App.Environment>,
|
|
426
500
|
options: serializeVault.Options,
|
|
@@ -439,6 +513,7 @@ async function serializeVault(
|
|
|
439
513
|
record: options.record,
|
|
440
514
|
shareToken,
|
|
441
515
|
tvl: null,
|
|
516
|
+
zoneRoutes: options.zoneRoutes,
|
|
442
517
|
zones: c.get('zones'),
|
|
443
518
|
})
|
|
444
519
|
}
|
|
@@ -455,6 +530,8 @@ declare namespace serializeVault {
|
|
|
455
530
|
record?: core_EarnVaults.Record | undefined
|
|
456
531
|
/** Verified-token snapshot, when configured. */
|
|
457
532
|
snapshot: VerifiedTokens.Snapshot | null
|
|
533
|
+
/** Verified private Zone routes selected for serialization. */
|
|
534
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
458
535
|
}
|
|
459
536
|
}
|
|
460
537
|
|
|
@@ -504,11 +504,15 @@ export namespace schema {
|
|
|
504
504
|
.check(
|
|
505
505
|
z.int(),
|
|
506
506
|
z.nonnegative(),
|
|
507
|
-
z.describe('Consecutive delivery failures.'),
|
|
507
|
+
z.describe('Consecutive delivery failures, capped at the auto-disable threshold.'),
|
|
508
508
|
z.meta({ examples: [2] }),
|
|
509
509
|
),
|
|
510
510
|
id: z.string().check(z.describe('Subscription id.'), z.meta({ examples: ['wh_123'] })),
|
|
511
|
-
lastDeliveryAt: z
|
|
511
|
+
lastDeliveryAt: z
|
|
512
|
+
.nullable(timestamp)
|
|
513
|
+
.check(
|
|
514
|
+
z.describe('Last successful delivery (refreshed at most once per minute), or null.'),
|
|
515
|
+
),
|
|
512
516
|
status: z
|
|
513
517
|
.enum(['active', 'disabled', 'paused'])
|
|
514
518
|
.check(z.describe('Subscription status.'), z.meta({ examples: ['active'] })),
|
|
@@ -93,6 +93,25 @@ export namespace update {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/** Rotates an API key while preserving its access and attribution. */
|
|
97
|
+
export namespace rotate {
|
|
98
|
+
export async function fn(id: string) {
|
|
99
|
+
const response = await client['api-keys'][':id'].rotate.$post({ param: { id } })
|
|
100
|
+
if (!response.ok)
|
|
101
|
+
throw new Error(
|
|
102
|
+
await Response.errorMessage(response, { fallback: 'Failed to rotate the API key.' }),
|
|
103
|
+
)
|
|
104
|
+
return response.json()
|
|
105
|
+
}
|
|
106
|
+
export function useMutation() {
|
|
107
|
+
const queryClient = ReactQuery.useQueryClient()
|
|
108
|
+
return ReactQuery.useMutation({
|
|
109
|
+
mutationFn: fn,
|
|
110
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: get.baseKey }),
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
96
115
|
/** Revoke an API key by id. */
|
|
97
116
|
export namespace revoke {
|
|
98
117
|
export async function fn(id: string) {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Copy as CopyIcon,
|
|
9
9
|
Pencil,
|
|
10
10
|
Plus,
|
|
11
|
+
RefreshCw,
|
|
11
12
|
Search,
|
|
12
13
|
Trash2,
|
|
13
14
|
TriangleAlert,
|
|
@@ -59,6 +60,14 @@ function RouteComponent() {
|
|
|
59
60
|
alert('Enter a name that identifies what uses this key.')
|
|
60
61
|
return
|
|
61
62
|
}
|
|
63
|
+
const allowedIps = [
|
|
64
|
+
...new Set(
|
|
65
|
+
field('allowedIps')
|
|
66
|
+
.split(/[,\n]/)
|
|
67
|
+
.map((value) => value.trim())
|
|
68
|
+
.filter(Boolean),
|
|
69
|
+
),
|
|
70
|
+
]
|
|
62
71
|
const expiresAt_value = field('expiresAt')
|
|
63
72
|
const expiresAt = expiresAt_value ? new Date(expiresAt_value).toISOString() : undefined
|
|
64
73
|
const orgId = filters.orgId ?? field('orgId')
|
|
@@ -88,6 +97,7 @@ function RouteComponent() {
|
|
|
88
97
|
}
|
|
89
98
|
provision.mutate(
|
|
90
99
|
{
|
|
100
|
+
allowedIps,
|
|
91
101
|
environment,
|
|
92
102
|
...(expiresAt === undefined ? {} : { expiresAt }),
|
|
93
103
|
name,
|
|
@@ -198,13 +208,13 @@ function RouteComponent() {
|
|
|
198
208
|
)
|
|
199
209
|
}
|
|
200
210
|
|
|
201
|
-
function TokenBanner(props: { onDismiss: () => void; token: string }) {
|
|
211
|
+
function TokenBanner(props: { onDismiss: () => void; title?: string; token: string }) {
|
|
202
212
|
const { copy, notifying } = useCopy()
|
|
203
213
|
return (
|
|
204
214
|
<Card className="flex flex-col gap-3 p-4">
|
|
205
215
|
<div className="flex items-start justify-between gap-3">
|
|
206
216
|
<div className="flex flex-col gap-1">
|
|
207
|
-
<span className="text-label-14 text-foreground">Key provisioned</span>
|
|
217
|
+
<span className="text-label-14 text-foreground">{props.title ?? 'Key provisioned'}</span>
|
|
208
218
|
<span className="text-label-12 text-foreground-secondary">
|
|
209
219
|
Copy this token now, it won't be shown again.
|
|
210
220
|
</span>
|
|
@@ -309,6 +319,19 @@ function ProvisionForm(props: {
|
|
|
309
319
|
suffix="req/min"
|
|
310
320
|
type="number"
|
|
311
321
|
/>
|
|
322
|
+
<label className="flex min-w-0 flex-col gap-2">
|
|
323
|
+
<span className="text-label-13 text-foreground-secondary">IP allowlist (optional)</span>
|
|
324
|
+
<textarea
|
|
325
|
+
className="min-h-24 w-full resize-y rounded-body border-2 border-transparent bg-secondary px-3 py-2.5 font-mono text-copy-13 text-foreground outline-none placeholder:font-sans placeholder:text-foreground-secondary/50 hover:bg-secondary-hover focus-visible:border-focus focus-visible:bg-secondary-hover"
|
|
326
|
+
name="allowedIps"
|
|
327
|
+
placeholder={'203.0.113.10\n198.51.100.0/24'}
|
|
328
|
+
rows={4}
|
|
329
|
+
/>
|
|
330
|
+
<span className="text-label-12 text-foreground-secondary">
|
|
331
|
+
Separate exact IP addresses or CIDR ranges with commas or new lines. Leave empty for
|
|
332
|
+
unrestricted access.
|
|
333
|
+
</span>
|
|
334
|
+
</label>
|
|
312
335
|
<div className="flex flex-col gap-2">
|
|
313
336
|
<span className="label-13 text-foreground-secondary">Scopes</span>
|
|
314
337
|
{scopes.isPending ? (
|
|
@@ -681,6 +704,19 @@ function KeyRow(props: { currentUser?: string | undefined; record: ApiKeys.ApiKe
|
|
|
681
704
|
{record.expiresAt ? (
|
|
682
705
|
<Detail label="Expires">{Format.date(record.expiresAt)}</Detail>
|
|
683
706
|
) : null}
|
|
707
|
+
<Detail className="w-full" label="IP allowlist">
|
|
708
|
+
{record.allowedIps.length === 0 ? (
|
|
709
|
+
'Unrestricted'
|
|
710
|
+
) : (
|
|
711
|
+
<span className="flex flex-wrap gap-x-3 gap-y-1 font-mono">
|
|
712
|
+
{record.allowedIps.map((address) => (
|
|
713
|
+
<span className="break-all" key={address}>
|
|
714
|
+
{address}
|
|
715
|
+
</span>
|
|
716
|
+
))}
|
|
717
|
+
</span>
|
|
718
|
+
)}
|
|
719
|
+
</Detail>
|
|
684
720
|
<Detail className="w-full" label="Scopes">
|
|
685
721
|
{record.scopes.length === 0 ? (
|
|
686
722
|
'—'
|
|
@@ -697,6 +733,7 @@ function KeyRow(props: { currentUser?: string | undefined; record: ApiKeys.ApiKe
|
|
|
697
733
|
</dl>
|
|
698
734
|
<div className="flex justify-end gap-2 border-t border-border px-5 py-3">
|
|
699
735
|
<EditDialog record={record} />
|
|
736
|
+
<RotateDialog record={record} />
|
|
700
737
|
<RevokeDialog currentUser={currentUser} record={record} />
|
|
701
738
|
</div>
|
|
702
739
|
</Rows.Panel>
|
|
@@ -777,6 +814,91 @@ declare namespace EditDialog {
|
|
|
777
814
|
}
|
|
778
815
|
}
|
|
779
816
|
|
|
817
|
+
function RotateDialog(options: RotateDialog.Props) {
|
|
818
|
+
const { record } = options
|
|
819
|
+
const [open, setOpen] = useState(false)
|
|
820
|
+
const rotate = ApiKeys.rotate.useMutation()
|
|
821
|
+
|
|
822
|
+
return (
|
|
823
|
+
<Dialog.Root
|
|
824
|
+
onOpenChange={(value) => {
|
|
825
|
+
if (!value && rotate.isPending) return
|
|
826
|
+
setOpen(value)
|
|
827
|
+
if (!value) rotate.reset()
|
|
828
|
+
}}
|
|
829
|
+
open={open}
|
|
830
|
+
>
|
|
831
|
+
<Dialog.Trigger
|
|
832
|
+
render={
|
|
833
|
+
<Button size="small">
|
|
834
|
+
<RefreshCw className="size-4" />
|
|
835
|
+
Rotate key
|
|
836
|
+
</Button>
|
|
837
|
+
}
|
|
838
|
+
/>
|
|
839
|
+
<Dialog.Popup>
|
|
840
|
+
{rotate.data ? (
|
|
841
|
+
<>
|
|
842
|
+
<Dialog.Title>Key rotated</Dialog.Title>
|
|
843
|
+
<Dialog.Description>
|
|
844
|
+
Copy the replacement token now. The source key remains active until it is revoked.
|
|
845
|
+
</Dialog.Description>
|
|
846
|
+
<div className="mt-5">
|
|
847
|
+
<TokenBanner
|
|
848
|
+
onDismiss={() => setOpen(false)}
|
|
849
|
+
title="Replacement key provisioned"
|
|
850
|
+
token={rotate.data.token}
|
|
851
|
+
/>
|
|
852
|
+
</div>
|
|
853
|
+
</>
|
|
854
|
+
) : (
|
|
855
|
+
<>
|
|
856
|
+
<Dialog.Title>Rotate {record.name ?? 'API key'}?</Dialog.Title>
|
|
857
|
+
<Dialog.Description>
|
|
858
|
+
This creates a replacement with the same scopes, ownership, limits, and restrictions.
|
|
859
|
+
The source key remains active.
|
|
860
|
+
</Dialog.Description>
|
|
861
|
+
<dl className="mt-5 grid grid-cols-2 gap-4 border border-border bg-secondary p-4">
|
|
862
|
+
<Detail className="col-span-2" label="Key ID">
|
|
863
|
+
<code className="break-all">{record.id}</code>
|
|
864
|
+
</Detail>
|
|
865
|
+
<Detail label="Environment">{record.environment}</Detail>
|
|
866
|
+
<Detail label="Organization">{organization(record)}</Detail>
|
|
867
|
+
<Detail label="Project">{project(record)}</Detail>
|
|
868
|
+
<Detail label="Scopes">{record.scopes.length}</Detail>
|
|
869
|
+
</dl>
|
|
870
|
+
{rotate.error ? (
|
|
871
|
+
<p className="mt-3 text-copy-13 text-negative">{rotate.error.message}</p>
|
|
872
|
+
) : null}
|
|
873
|
+
<div className="mt-6 flex justify-end gap-2">
|
|
874
|
+
<Dialog.Close
|
|
875
|
+
render={
|
|
876
|
+
<Button disabled={rotate.isPending} type="button">
|
|
877
|
+
Cancel
|
|
878
|
+
</Button>
|
|
879
|
+
}
|
|
880
|
+
/>
|
|
881
|
+
<Button
|
|
882
|
+
loading={rotate.isPending}
|
|
883
|
+
onClick={() => rotate.mutate(record.id)}
|
|
884
|
+
variant="primary"
|
|
885
|
+
>
|
|
886
|
+
Rotate key
|
|
887
|
+
</Button>
|
|
888
|
+
</div>
|
|
889
|
+
</>
|
|
890
|
+
)}
|
|
891
|
+
</Dialog.Popup>
|
|
892
|
+
</Dialog.Root>
|
|
893
|
+
)
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
declare namespace RotateDialog {
|
|
897
|
+
type Props = {
|
|
898
|
+
record: ApiKeys.ApiKey
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
780
902
|
function RevokeDialog(props: { currentUser?: string | undefined; record: ApiKeys.ApiKey }) {
|
|
781
903
|
const { currentUser, record } = props
|
|
782
904
|
const [confirmation, setConfirmation] = useState('')
|
|
@@ -893,6 +1015,7 @@ function matches(record: ApiKeys.ApiKey, query?: string) {
|
|
|
893
1015
|
record.projectId,
|
|
894
1016
|
record.projectName,
|
|
895
1017
|
record.tokenLast4,
|
|
1018
|
+
...record.allowedIps,
|
|
896
1019
|
...record.scopes,
|
|
897
1020
|
].some((value) => value?.toLowerCase().includes(normalized))
|
|
898
1021
|
}
|