tapimo 0.12.0 → 0.14.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 +11333 -9563
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +39 -3
- package/dist/App.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/Webhooks.js +2 -2
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +1064 -924
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +80 -0
- 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 +63 -15
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +2 -1
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +92 -3
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +69 -7
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +7 -7
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +151 -151
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/Zones.d.ts +28 -28
- package/dist/apps/Zones.js +7 -7
- package/dist/apps/data/App.d.ts +2909 -2523
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +26 -21
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +8 -8
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
- package/dist/apps/data/ZoneSelection.js +1 -1
- package/dist/apps/data/ZoneSelection.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +588 -584
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +1561 -1239
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts +26 -26
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +43 -16
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +44 -44
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +21 -11
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +3 -3
- package/dist/apps/data/routes/earn.d.ts +201 -25
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +434 -75
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +160 -145
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +180 -114
- 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 +18 -19
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +155 -55
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +28 -10
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +13 -13
- package/dist/apps/data/routes/tokens.d.ts +5 -5
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +51 -20
- 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 +37 -17
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +13 -13
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +18 -12
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +31 -31
- 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 +8 -8
- package/dist/apps/data/routes/webhooks.d.ts +816 -113
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +47 -5
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +14 -14
- package/dist/apps/data/routes/zones.js +1 -1
- package/dist/apps/funding/App.d.ts +466 -44
- package/dist/apps/funding/App.d.ts.map +1 -1
- package/dist/apps/funding/App.js +1 -1
- package/dist/apps/funding/App.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +17 -17
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +17 -12
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +650 -57
- package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
- package/dist/apps/funding/routes/transfers.js +238 -24
- package/dist/apps/funding/routes/transfers.js.map +1 -1
- package/dist/apps/management/App.d.ts +5120 -4152
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +17 -1
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +632 -81
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +236 -4
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +76 -76
- package/dist/apps/management/routes/faucet.d.ts +6 -6
- package/dist/apps/management/routes/invitations.d.ts +24 -24
- package/dist/apps/management/routes/invite-links.d.ts +4 -4
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +20 -20
- package/dist/apps/management/routes/projects.d.ts +4 -4
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +17 -17
- package/dist/apps/management/routes/webhooks.d.ts +675 -25
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +21 -21
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +115 -23
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +27 -1
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +34 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +11 -5
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +21 -3
- package/dist/db/Schema.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/fundingTransferTransactions.d.ts +38 -0
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -1
- package/dist/db/tables/fundingTransferTransactions.js +44 -3
- package/dist/db/tables/fundingTransferTransactions.js.map +1 -1
- package/dist/db/tables/fundingTransfers.d.ts +17 -0
- package/dist/db/tables/fundingTransfers.d.ts.map +1 -1
- package/dist/db/tables/fundingTransfers.js +21 -0
- package/dist/db/tables/fundingTransfers.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +24 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +27 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +25 -1
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +26 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +44 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +146 -13
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +10 -6
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +9 -6
- 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 +3 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +6 -3
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +3 -3
- package/dist/internal/EarnVaults.js +5 -5
- 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 +4 -2
- 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 +5 -3
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +13 -3
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Schema.d.ts +6 -3
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +8 -2
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +16 -3
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +82 -16
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +7 -2
- 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/Viem.d.ts +16 -1
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +12 -2
- package/dist/internal/Viem.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/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/DepositWebhook.d.ts.map +1 -1
- package/dist/internal/funding/DepositWebhook.js +2 -1
- package/dist/internal/funding/DepositWebhook.js.map +1 -1
- package/dist/internal/funding/Evidence.d.ts.map +1 -1
- package/dist/internal/funding/Evidence.js +2 -10
- package/dist/internal/funding/Evidence.js.map +1 -1
- package/dist/internal/funding/Provider.d.ts +108 -13
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +34 -8
- package/dist/internal/funding/Provider.js.map +1 -1
- package/dist/internal/funding/SourceObservation.d.ts.map +1 -1
- package/dist/internal/funding/SourceObservation.js +5 -7
- package/dist/internal/funding/SourceObservation.js.map +1 -1
- package/dist/internal/funding/Transfer.d.ts +114 -18
- package/dist/internal/funding/Transfer.d.ts.map +1 -1
- package/dist/internal/funding/Transfer.js +185 -55
- package/dist/internal/funding/Transfer.js.map +1 -1
- package/dist/internal/funding/TransferReconciliation.d.ts +52 -0
- package/dist/internal/funding/TransferReconciliation.d.ts.map +1 -0
- package/dist/internal/funding/TransferReconciliation.js +192 -0
- package/dist/internal/funding/TransferReconciliation.js.map +1 -0
- package/dist/internal/funding/TransferWebhook.d.ts +21 -0
- package/dist/internal/funding/TransferWebhook.d.ts.map +1 -0
- package/dist/internal/funding/TransferWebhook.js +43 -0
- package/dist/internal/funding/TransferWebhook.js.map +1 -0
- package/dist/internal/funding/index.d.ts +1 -0
- package/dist/internal/funding/index.d.ts.map +1 -1
- package/dist/internal/funding/index.js +1 -0
- package/dist/internal/funding/index.js.map +1 -1
- package/dist/internal/funding/providers/relay.d.ts.map +1 -1
- package/dist/internal/funding/providers/relay.js +3 -12
- package/dist/internal/funding/providers/relay.js.map +1 -1
- package/dist/internal/funding/providers/stargate.d.ts +127 -9
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -1
- package/dist/internal/funding/providers/stargate.js +548 -112
- package/dist/internal/funding/providers/stargate.js.map +1 -1
- 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/internal/webhookDestinations/slack.d.ts.map +1 -1
- package/dist/internal/webhookDestinations/slack.js +16 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/package.json +2 -2
- package/src/App.test.ts +100 -0
- package/src/App.ts +43 -3
- package/src/Client.test-d.ts +129 -2
- package/src/Scope.test.ts +20 -0
- package/src/Scope.ts +16 -0
- package/src/Webhooks.ts +2 -2
- 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 +1 -1
- package/src/admin/apps/earn-vaults.ts +2 -1
- package/src/admin/apps/organizations.test.ts +53 -1
- package/src/admin/apps/organizations.ts +90 -5
- package/src/admin/ui/src/lib/api-keys.ts +19 -0
- package/src/admin/ui/src/lib/organizations.test.ts +112 -1
- package/src/admin/ui/src/lib/organizations.ts +55 -0
- package/src/admin/ui/src/routes/api-keys.tsx +89 -2
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +116 -0
- package/src/admin/ui.generated.ts +189 -151
- package/src/apps/Zones.test.ts +7 -7
- package/src/apps/Zones.ts +7 -7
- package/src/apps/composition.test.ts +2 -1
- package/src/apps/data/App.test.ts +41 -0
- package/src/apps/data/App.ts +30 -21
- package/src/apps/data/ZoneSelection.test.ts +2 -2
- package/src/apps/data/ZoneSelection.ts +8 -8
- package/src/apps/data/routes/activities.test.ts +1526 -12
- package/src/apps/data/routes/activities.ts +1774 -1356
- package/src/apps/data/routes/balances.ts +133 -97
- package/src/apps/data/routes/blocks.test.ts +533 -0
- package/src/apps/data/routes/blocks.ts +35 -16
- package/src/apps/data/routes/earn.test.ts +373 -16
- package/src/apps/data/routes/earn.ts +548 -79
- package/src/apps/data/routes/earn.zone-access.test.ts +6 -6
- package/src/apps/data/routes/exchanges.test.ts +740 -15
- package/src/apps/data/routes/exchanges.ts +954 -753
- package/src/apps/data/routes/fee-amm.ts +17 -18
- package/src/apps/data/routes/receipts.ts +47 -16
- package/src/apps/data/routes/tokens.test.ts +578 -0
- package/src/apps/data/routes/tokens.ts +283 -225
- package/src/apps/data/routes/transactions.ts +68 -29
- package/src/apps/data/routes/transfers.test.ts +421 -0
- package/src/apps/data/routes/transfers.ts +45 -27
- package/src/apps/data/routes/valuation.ts +94 -78
- package/src/apps/data/routes/webhooks.test.ts +21 -5
- package/src/apps/data/routes/webhooks.ts +63 -8
- package/src/apps/data/routes/zones.test.ts +2 -2
- package/src/apps/data/routes/zones.ts +1 -1
- package/src/apps/funding/App.ts +12 -2
- package/src/apps/funding/routes/deposit-addresses.test.ts +29 -7
- package/src/apps/funding/routes/deposit-addresses.ts +19 -14
- package/src/apps/funding/routes/quotes.test.ts +5 -9
- package/src/apps/funding/routes/transfers.test.ts +901 -23
- package/src/apps/funding/routes/transfers.ts +347 -64
- package/src/apps/management/Billing.ts +18 -5
- package/src/apps/management/routes/api-keys.test.ts +220 -0
- package/src/apps/management/routes/api-keys.ts +280 -3
- package/src/apps/management/routes/webhooks.test.ts +3 -3
- package/src/apps/management/routes/webhooks.ts +24 -25
- package/src/apps/relay/App.test.ts +212 -1
- package/src/apps/relay/App.ts +158 -29
- package/src/apps/relay/Sponsorships.ts +24 -1
- package/src/db/Db.ts +48 -1
- package/src/db/Schema.ts +22 -4
- package/src/db/tables/earnVaults.test.ts +9 -9
- package/src/db/tables/fundingCatalog.test.ts +16 -2
- package/src/db/tables/fundingCatalog.ts +9 -3
- package/src/db/tables/fundingTransferTransactions.test.ts +43 -0
- package/src/db/tables/fundingTransferTransactions.ts +79 -3
- package/src/db/tables/fundingTransfers.test.ts +26 -0
- package/src/db/tables/fundingTransfers.ts +36 -0
- package/src/db/tables/organizations.test.ts +41 -0
- package/src/db/tables/organizations.ts +49 -0
- package/src/db/tables/projects.test.ts +55 -0
- package/src/db/tables/projects.ts +46 -1
- package/src/db/tables/sponsoredTransactions.test.ts +338 -0
- package/src/db/tables/sponsoredTransactions.ts +197 -13
- package/src/db/tables/webhookSubscriptions.ts +18 -11
- package/src/handlers/internal/utils.test.ts +53 -0
- package/src/handlers/internal/utils.ts +15 -0
- package/src/internal/Auth.ts +12 -4
- package/src/internal/EarnVaults.capabilities.test.ts +2 -2
- package/src/internal/EarnVaults.test.ts +1 -1
- package/src/internal/EarnVaults.ts +5 -5
- package/src/internal/Fetch.test.ts +46 -0
- package/src/internal/Fetch.ts +56 -0
- package/src/internal/Log.test-d.ts +2 -0
- package/src/internal/Log.test.ts +21 -0
- package/src/internal/Log.ts +22 -5
- package/src/internal/OpenApi.ts +14 -4
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.test.ts +2 -0
- package/src/internal/Schema.ts +12 -2
- package/src/internal/Store.test.ts +178 -0
- package/src/internal/Store.ts +104 -18
- package/src/internal/Tidx.test.ts +2 -1
- package/src/internal/Tidx.ts +7 -2
- 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/Viem.ts +39 -3
- package/src/internal/WebhookDestination.ts +3 -0
- package/src/internal/Webhooks.test.ts +45 -0
- 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/DepositWebhook.ts +2 -1
- package/src/internal/funding/Evidence.ts +2 -13
- package/src/internal/funding/Provider.test.ts +73 -0
- package/src/internal/funding/Provider.ts +125 -28
- package/src/internal/funding/SourceObservation.ts +5 -9
- package/src/internal/funding/Transfer.test.ts +155 -0
- package/src/internal/funding/Transfer.ts +387 -147
- package/src/internal/funding/TransferReconciliation.test.ts +147 -0
- package/src/internal/funding/TransferReconciliation.ts +264 -0
- package/src/internal/funding/TransferWebhook.test.ts +128 -0
- package/src/internal/funding/TransferWebhook.ts +67 -0
- package/src/internal/funding/index.test.ts +1 -0
- package/src/internal/funding/index.ts +1 -0
- package/src/internal/funding/providers/index.test.ts +4 -167
- package/src/internal/funding/providers/relay.test.ts +2 -2
- package/src/internal/funding/providers/relay.ts +3 -15
- package/src/internal/funding/providers/stargate.test.ts +328 -0
- package/src/internal/funding/providers/stargate.ts +807 -135
- package/src/internal/index.test.ts +1 -0
- package/src/internal/index.ts +1 -0
- package/src/internal/webhookDestinations/slack.ts +15 -0
|
@@ -71,6 +71,18 @@ export namespace schema {
|
|
|
71
71
|
'An organization visible to an authenticated administrator.',
|
|
72
72
|
)
|
|
73
73
|
|
|
74
|
+
const SponsorshipSubsidy = Schema.describe(
|
|
75
|
+
z.object({
|
|
76
|
+
durationDays: z
|
|
77
|
+
.nullable(z.literal(90))
|
|
78
|
+
.check(z.describe('Promotion duration in days, or null when disabled.'), z.meta({ examples: [90] })), // prettier-ignore
|
|
79
|
+
projectSpendLimit: z
|
|
80
|
+
.nullable(z.string())
|
|
81
|
+
.check(z.describe('Optional per-project promotion cap in USD.'), z.meta({ examples: ['1000'] })), // prettier-ignore
|
|
82
|
+
}),
|
|
83
|
+
'Current per-project sponsorship subsidy policy.',
|
|
84
|
+
)
|
|
85
|
+
|
|
74
86
|
/** Schemas for the listOrganizations operation. */
|
|
75
87
|
export namespace listOrganizations {
|
|
76
88
|
/** Query parameters for organization lookup. */
|
|
@@ -287,6 +299,7 @@ export namespace schema {
|
|
|
287
299
|
],
|
|
288
300
|
}),
|
|
289
301
|
),
|
|
302
|
+
sponsorshipSubsidy: SponsorshipSubsidy,
|
|
290
303
|
}),
|
|
291
304
|
'Detailed organization information for administrators.',
|
|
292
305
|
)
|
|
@@ -435,8 +448,8 @@ export namespace schema {
|
|
|
435
448
|
)
|
|
436
449
|
}
|
|
437
450
|
|
|
438
|
-
/** Schemas for
|
|
439
|
-
export namespace
|
|
451
|
+
/** Schemas for organization sponsorship operations. */
|
|
452
|
+
export namespace organizationSponsorship {
|
|
440
453
|
const Environment = z.object({
|
|
441
454
|
committedSpend: z
|
|
442
455
|
.string()
|
|
@@ -454,7 +467,7 @@ export namespace schema {
|
|
|
454
467
|
})
|
|
455
468
|
|
|
456
469
|
/** Current-period sponsorship spend by key environment. */
|
|
457
|
-
export const
|
|
470
|
+
export const GetResponse = Schema.describe(
|
|
458
471
|
z.object({
|
|
459
472
|
production: Environment,
|
|
460
473
|
sandbox: Environment,
|
|
@@ -462,6 +475,28 @@ export namespace schema {
|
|
|
462
475
|
}),
|
|
463
476
|
'Current-period sponsorship spend for an organization.',
|
|
464
477
|
)
|
|
478
|
+
|
|
479
|
+
/** Replacement subsidy policy. */
|
|
480
|
+
export const SetBody = z
|
|
481
|
+
.union([
|
|
482
|
+
z.object({
|
|
483
|
+
enabled: z.literal(true),
|
|
484
|
+
projectSpendLimit: z.optional(
|
|
485
|
+
z
|
|
486
|
+
.string()
|
|
487
|
+
.check(
|
|
488
|
+
z.regex(/^(?:0|[1-9]\d*)(?:\.\d{1,6})?$/),
|
|
489
|
+
z.describe('Optional per-project promotion cap in USD.'),
|
|
490
|
+
z.meta({ examples: ['1000'] }),
|
|
491
|
+
),
|
|
492
|
+
),
|
|
493
|
+
}),
|
|
494
|
+
z.object({ enabled: z.literal(false) }),
|
|
495
|
+
])
|
|
496
|
+
.check(z.describe('Replacement per-project sponsorship subsidy policy.'))
|
|
497
|
+
|
|
498
|
+
/** Current subsidy policy. */
|
|
499
|
+
export const SetResponse = SponsorshipSubsidy
|
|
465
500
|
}
|
|
466
501
|
|
|
467
502
|
/** Schemas for the getOrganizationWebhooks operation. */
|
|
@@ -640,6 +675,56 @@ export function organizations() {
|
|
|
640
675
|
production: serializeBilling(productionSettings, productionSource),
|
|
641
676
|
sandbox: serializeBilling(sandboxSettings, sandboxSource),
|
|
642
677
|
},
|
|
678
|
+
sponsorshipSubsidy: {
|
|
679
|
+
durationDays: organization.sponsorshipSubsidyDurationDays,
|
|
680
|
+
projectSpendLimit: organization.sponsorshipSubsidyProjectSpendLimit,
|
|
681
|
+
},
|
|
682
|
+
}),
|
|
683
|
+
200,
|
|
684
|
+
)
|
|
685
|
+
} catch (cause) {
|
|
686
|
+
return Response.upstream(c, cause)
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
)
|
|
690
|
+
.put(
|
|
691
|
+
'/:orgId/sponsorship',
|
|
692
|
+
OpenApi.validate('param', schema.getOrganization.Params, {
|
|
693
|
+
code: 'param_invalid',
|
|
694
|
+
message: 'Invalid path parameters',
|
|
695
|
+
}),
|
|
696
|
+
OpenApi.validate('json', schema.organizationSponsorship.SetBody, {
|
|
697
|
+
code: 'body_invalid',
|
|
698
|
+
message: 'Invalid request body',
|
|
699
|
+
}),
|
|
700
|
+
OpenApi.describeRoute({
|
|
701
|
+
operationId: 'setAdminOrganizationSponsorshipSubsidy',
|
|
702
|
+
responses: OpenApi.responses({
|
|
703
|
+
errors: { 404: 'Organization not found.' },
|
|
704
|
+
success: {
|
|
705
|
+
description: 'Current sponsorship subsidy policy.',
|
|
706
|
+
schema: schema.organizationSponsorship.SetResponse,
|
|
707
|
+
},
|
|
708
|
+
}),
|
|
709
|
+
summary: 'Set sponsorship subsidy',
|
|
710
|
+
tags: ['Organizations'],
|
|
711
|
+
}),
|
|
712
|
+
async (c) => {
|
|
713
|
+
const { orgId } = c.req.valid('param')
|
|
714
|
+
const policy = c.req.valid('json')
|
|
715
|
+
try {
|
|
716
|
+
const organization = await Organizations.setSponsorshipSubsidy(
|
|
717
|
+
Db.get(c.get('db')),
|
|
718
|
+
orgId,
|
|
719
|
+
policy.enabled
|
|
720
|
+
? { durationDays: 90, projectSpendLimit: policy.projectSpendLimit ?? null }
|
|
721
|
+
: { durationDays: null, projectSpendLimit: null },
|
|
722
|
+
)
|
|
723
|
+
if (!organization) return organizationNotFound(c)
|
|
724
|
+
return c.json(
|
|
725
|
+
Response.validated(schema.organizationSponsorship.SetResponse, {
|
|
726
|
+
durationDays: organization.sponsorshipSubsidyDurationDays,
|
|
727
|
+
projectSpendLimit: organization.sponsorshipSubsidyProjectSpendLimit,
|
|
643
728
|
}),
|
|
644
729
|
200,
|
|
645
730
|
)
|
|
@@ -933,7 +1018,7 @@ export function organizations() {
|
|
|
933
1018
|
errors: { 404: 'Organization not found.' },
|
|
934
1019
|
success: {
|
|
935
1020
|
description: 'Recent organization sponsorship activity.',
|
|
936
|
-
schema: schema.
|
|
1021
|
+
schema: schema.organizationSponsorship.GetResponse,
|
|
937
1022
|
},
|
|
938
1023
|
}),
|
|
939
1024
|
summary: 'Get sponsorship activity',
|
|
@@ -969,7 +1054,7 @@ export function organizations() {
|
|
|
969
1054
|
}),
|
|
970
1055
|
)
|
|
971
1056
|
return c.json(
|
|
972
|
-
Response.validated(schema.
|
|
1057
|
+
Response.validated(schema.organizationSponsorship.GetResponse, {
|
|
973
1058
|
production,
|
|
974
1059
|
sandbox,
|
|
975
1060
|
to,
|
|
@@ -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) {
|
|
@@ -5,7 +5,11 @@ import { renderToStaticMarkup } from 'react-dom/server'
|
|
|
5
5
|
import { describe, expect, it, vi } from 'vite-plus/test'
|
|
6
6
|
|
|
7
7
|
import { routeTree } from '../routeTree.gen.js'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
BillingSourcesCard,
|
|
10
|
+
Route as DetailRoute,
|
|
11
|
+
SponsorshipSubsidyCard,
|
|
12
|
+
} from '../routes/organizations_.$orgId.js'
|
|
9
13
|
import { Route as ListRoute } from '../routes/organizations.js'
|
|
10
14
|
import * as Organizations from './organizations.js'
|
|
11
15
|
|
|
@@ -75,6 +79,7 @@ describe('withEnabledSources', () => {
|
|
|
75
79
|
memberCount: 0,
|
|
76
80
|
name: 'Example',
|
|
77
81
|
projectCount: 0,
|
|
82
|
+
sponsorshipSubsidy: { durationDays: null, projectSpendLimit: null },
|
|
78
83
|
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
79
84
|
userId: null,
|
|
80
85
|
} satisfies Organizations.Detail
|
|
@@ -101,6 +106,50 @@ describe('withEnabledSources', () => {
|
|
|
101
106
|
})
|
|
102
107
|
})
|
|
103
108
|
|
|
109
|
+
describe('withSponsorshipSubsidy', () => {
|
|
110
|
+
it('replaces only the organization subsidy policy', () => {
|
|
111
|
+
const detail = {
|
|
112
|
+
billing: {
|
|
113
|
+
enabledSources: [],
|
|
114
|
+
production: { settings: null, source: null },
|
|
115
|
+
sandbox: { settings: null, source: null },
|
|
116
|
+
},
|
|
117
|
+
createdAt: '2026-01-01T00:00:00.000Z',
|
|
118
|
+
createdBy: null,
|
|
119
|
+
id: 'org_example',
|
|
120
|
+
memberCount: 0,
|
|
121
|
+
name: 'Example',
|
|
122
|
+
projectCount: 0,
|
|
123
|
+
sponsorshipSubsidy: { durationDays: null, projectSpendLimit: null },
|
|
124
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
125
|
+
userId: null,
|
|
126
|
+
} satisfies Organizations.Detail
|
|
127
|
+
|
|
128
|
+
const updated = Organizations.withSponsorshipSubsidy({
|
|
129
|
+
detail,
|
|
130
|
+
sponsorshipSubsidy: { durationDays: 90, projectSpendLimit: '1000' },
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
expect({
|
|
134
|
+
billingPreserved: updated.billing === detail.billing,
|
|
135
|
+
original: detail.sponsorshipSubsidy,
|
|
136
|
+
updated: updated.sponsorshipSubsidy,
|
|
137
|
+
}).toMatchInlineSnapshot(`
|
|
138
|
+
{
|
|
139
|
+
"billingPreserved": true,
|
|
140
|
+
"original": {
|
|
141
|
+
"durationDays": null,
|
|
142
|
+
"projectSpendLimit": null,
|
|
143
|
+
},
|
|
144
|
+
"updated": {
|
|
145
|
+
"durationDays": 90,
|
|
146
|
+
"projectSpendLimit": "1000",
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
`)
|
|
150
|
+
})
|
|
151
|
+
})
|
|
152
|
+
|
|
104
153
|
describe('BillingSourcesCard', () => {
|
|
105
154
|
it('renders source state and the setup-only warning', () => {
|
|
106
155
|
const markup = renderToStaticMarkup(
|
|
@@ -139,6 +188,68 @@ describe('BillingSourcesCard', () => {
|
|
|
139
188
|
})
|
|
140
189
|
})
|
|
141
190
|
|
|
191
|
+
describe('SponsorshipSubsidyCard', () => {
|
|
192
|
+
it('renders an enabled policy with its fixed duration and optional cap', () => {
|
|
193
|
+
const markup = renderToStaticMarkup(
|
|
194
|
+
createElement(SponsorshipSubsidyCard, {
|
|
195
|
+
error: null,
|
|
196
|
+
onSave() {},
|
|
197
|
+
pending: false,
|
|
198
|
+
policy: { durationDays: 90, projectSpendLimit: '1000' },
|
|
199
|
+
}),
|
|
200
|
+
)
|
|
201
|
+
const marker = 'aria-label="Sponsorship subsidy"'
|
|
202
|
+
const markerIndex = markup.indexOf(marker)
|
|
203
|
+
const switchTag = markup.slice(
|
|
204
|
+
markup.lastIndexOf('<', markerIndex),
|
|
205
|
+
markup.indexOf('>', markerIndex),
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
expect({
|
|
209
|
+
cap: markup.includes('value="1000"'),
|
|
210
|
+
duration: markup.includes('value="90 days"'),
|
|
211
|
+
enabled: switchTag.includes('aria-checked="true"'),
|
|
212
|
+
startsAt: markup.includes('first mainnet sponsorship'),
|
|
213
|
+
}).toMatchInlineSnapshot(`
|
|
214
|
+
{
|
|
215
|
+
"cap": true,
|
|
216
|
+
"duration": true,
|
|
217
|
+
"enabled": true,
|
|
218
|
+
"startsAt": true,
|
|
219
|
+
}
|
|
220
|
+
`)
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
it('renders a disabled policy', () => {
|
|
224
|
+
const markup = renderToStaticMarkup(
|
|
225
|
+
createElement(SponsorshipSubsidyCard, {
|
|
226
|
+
error: null,
|
|
227
|
+
onSave() {},
|
|
228
|
+
pending: false,
|
|
229
|
+
policy: { durationDays: null, projectSpendLimit: null },
|
|
230
|
+
}),
|
|
231
|
+
)
|
|
232
|
+
const marker = 'aria-label="Sponsorship subsidy"'
|
|
233
|
+
const markerIndex = markup.indexOf(marker)
|
|
234
|
+
const switchTag = markup.slice(
|
|
235
|
+
markup.lastIndexOf('<', markerIndex),
|
|
236
|
+
markup.indexOf('>', markerIndex),
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
expect({
|
|
240
|
+
billedNormally: markup.includes('billed normally'),
|
|
241
|
+
disabled: switchTag.includes('aria-checked="false"'),
|
|
242
|
+
spendCapHidden: !markup.includes('Per-project spend cap'),
|
|
243
|
+
}).toMatchInlineSnapshot(`
|
|
244
|
+
{
|
|
245
|
+
"billedNormally": true,
|
|
246
|
+
"disabled": true,
|
|
247
|
+
"spendCapHidden": true,
|
|
248
|
+
}
|
|
249
|
+
`)
|
|
250
|
+
})
|
|
251
|
+
})
|
|
252
|
+
|
|
142
253
|
describe('organization routes', () => {
|
|
143
254
|
it('matches a direct detail URL without the list route as a parent', () => {
|
|
144
255
|
const router = createRouter({
|
|
@@ -26,6 +26,10 @@ type SponsorshipResponse = InferResponseType<
|
|
|
26
26
|
(typeof client)['organizations'][':orgId']['sponsorship']['$get'],
|
|
27
27
|
200
|
|
28
28
|
>
|
|
29
|
+
type SponsorshipSubsidyResponse = InferResponseType<
|
|
30
|
+
(typeof client)['organizations'][':orgId']['sponsorship']['$put'],
|
|
31
|
+
200
|
|
32
|
+
>
|
|
29
33
|
type UsageResponse = InferResponseType<
|
|
30
34
|
(typeof client)['organizations'][':orgId']['usage']['$get'],
|
|
31
35
|
200
|
|
@@ -172,6 +176,24 @@ export declare namespace withEnabledSources {
|
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
178
|
|
|
179
|
+
/** Returns organization detail with its sponsorship subsidy policy replaced. */
|
|
180
|
+
export function withSponsorshipSubsidy(options: withSponsorshipSubsidy.Options): Detail {
|
|
181
|
+
return {
|
|
182
|
+
...options.detail,
|
|
183
|
+
sponsorshipSubsidy: options.sponsorshipSubsidy,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export declare namespace withSponsorshipSubsidy {
|
|
188
|
+
/** Inputs for replacing an organization's cached subsidy policy. */
|
|
189
|
+
type Options = {
|
|
190
|
+
/** Organization detail to update. */
|
|
191
|
+
detail: Detail
|
|
192
|
+
/** Current sponsorship subsidy policy. */
|
|
193
|
+
sponsorshipSubsidy: Detail['sponsorshipSubsidy']
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
175
197
|
/** Enable an organization-wide billing source. */
|
|
176
198
|
export namespace enableBillingSource {
|
|
177
199
|
/** Billing source to enable for an organization. */
|
|
@@ -236,6 +258,39 @@ export namespace disableBillingSource {
|
|
|
236
258
|
}
|
|
237
259
|
}
|
|
238
260
|
|
|
261
|
+
/** Replace an organization's sponsorship subsidy policy. */
|
|
262
|
+
export namespace setSponsorshipSubsidy {
|
|
263
|
+
/** Sponsorship subsidy policy accepted by the admin API. */
|
|
264
|
+
export type Input = { enabled: false } | { enabled: true; projectSpendLimit?: string | undefined }
|
|
265
|
+
|
|
266
|
+
/** Replaces the policy and returns its current value. */
|
|
267
|
+
export async function fn(options: Input & { orgId: string }) {
|
|
268
|
+
const json = ((): Input => {
|
|
269
|
+
if (!options.enabled) return { enabled: false }
|
|
270
|
+
if (!options.projectSpendLimit) return { enabled: true }
|
|
271
|
+
return { enabled: true, projectSpendLimit: options.projectSpendLimit }
|
|
272
|
+
})()
|
|
273
|
+
const response = await client.organizations[':orgId'].sponsorship.$put({
|
|
274
|
+
json,
|
|
275
|
+
param: { orgId: options.orgId },
|
|
276
|
+
})
|
|
277
|
+
if (!response.ok) throw new Error('Failed to update sponsorship subsidy.')
|
|
278
|
+
return (await response.json()) as SponsorshipSubsidyResponse
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/** Creates a mutation that replaces the subsidy policy. */
|
|
282
|
+
export function useMutation(orgId: string) {
|
|
283
|
+
const queryClient = ReactQuery.useQueryClient()
|
|
284
|
+
return ReactQuery.useMutation({
|
|
285
|
+
mutationFn: (input: Input) => fn({ ...input, orgId }),
|
|
286
|
+
onSuccess: (response) =>
|
|
287
|
+
queryClient.setQueryData(get.key(orgId), (detail: Detail | undefined) =>
|
|
288
|
+
detail ? withSponsorshipSubsidy({ detail, sponsorshipSubsidy: response }) : detail,
|
|
289
|
+
),
|
|
290
|
+
})
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
239
294
|
/** List members for one organization. */
|
|
240
295
|
export namespace members {
|
|
241
296
|
export function key(orgId: 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,
|
|
@@ -207,13 +208,13 @@ function RouteComponent() {
|
|
|
207
208
|
)
|
|
208
209
|
}
|
|
209
210
|
|
|
210
|
-
function TokenBanner(props: { onDismiss: () => void; token: string }) {
|
|
211
|
+
function TokenBanner(props: { onDismiss: () => void; title?: string; token: string }) {
|
|
211
212
|
const { copy, notifying } = useCopy()
|
|
212
213
|
return (
|
|
213
214
|
<Card className="flex flex-col gap-3 p-4">
|
|
214
215
|
<div className="flex items-start justify-between gap-3">
|
|
215
216
|
<div className="flex flex-col gap-1">
|
|
216
|
-
<span className="text-label-14 text-foreground">Key provisioned</span>
|
|
217
|
+
<span className="text-label-14 text-foreground">{props.title ?? 'Key provisioned'}</span>
|
|
217
218
|
<span className="text-label-12 text-foreground-secondary">
|
|
218
219
|
Copy this token now, it won't be shown again.
|
|
219
220
|
</span>
|
|
@@ -732,6 +733,7 @@ function KeyRow(props: { currentUser?: string | undefined; record: ApiKeys.ApiKe
|
|
|
732
733
|
</dl>
|
|
733
734
|
<div className="flex justify-end gap-2 border-t border-border px-5 py-3">
|
|
734
735
|
<EditDialog record={record} />
|
|
736
|
+
<RotateDialog record={record} />
|
|
735
737
|
<RevokeDialog currentUser={currentUser} record={record} />
|
|
736
738
|
</div>
|
|
737
739
|
</Rows.Panel>
|
|
@@ -812,6 +814,91 @@ declare namespace EditDialog {
|
|
|
812
814
|
}
|
|
813
815
|
}
|
|
814
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
|
+
|
|
815
902
|
function RevokeDialog(props: { currentUser?: string | undefined; record: ApiKeys.ApiKey }) {
|
|
816
903
|
const { currentUser, record } = props
|
|
817
904
|
const [confirmation, setConfirmation] = useState('')
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from '@tanstack/react-router'
|
|
15
15
|
import { Button, Rows, Select } from 'regen-ui'
|
|
16
16
|
import { ArrowLeft, RefreshCw } from 'lucide-react'
|
|
17
|
+
import { useEffect, useState } from 'react'
|
|
17
18
|
|
|
18
19
|
import { Card, Notice, Page } from '../components/Page.js'
|
|
19
20
|
import * as core_Format from '../lib/format.js'
|
|
@@ -34,6 +35,7 @@ function PageComponent() {
|
|
|
34
35
|
const period = period_search ?? '7d'
|
|
35
36
|
const disableBillingSource = Organizations.disableBillingSource.useMutation(orgId)
|
|
36
37
|
const enableBillingSource = Organizations.enableBillingSource.useMutation(orgId)
|
|
38
|
+
const setSponsorshipSubsidy = Organizations.setSponsorshipSubsidy.useMutation(orgId)
|
|
37
39
|
const organizationQuery = useSuspenseQuery(Organizations.get.options(orgId))
|
|
38
40
|
const organization = organizationQuery.data
|
|
39
41
|
const members = useInfiniteQuery(Organizations.members.options(orgId))
|
|
@@ -198,6 +200,12 @@ function PageComponent() {
|
|
|
198
200
|
onChange={setBillingSource}
|
|
199
201
|
pending={billingSourcePending}
|
|
200
202
|
/>
|
|
203
|
+
<SponsorshipSubsidyCard
|
|
204
|
+
error={setSponsorshipSubsidy.error}
|
|
205
|
+
onSave={(policy) => setSponsorshipSubsidy.mutate(policy)}
|
|
206
|
+
pending={setSponsorshipSubsidy.isPending}
|
|
207
|
+
policy={organization.sponsorshipSubsidy}
|
|
208
|
+
/>
|
|
201
209
|
<div className="grid gap-3 md:grid-cols-2">
|
|
202
210
|
<BillingCard
|
|
203
211
|
environment="Production"
|
|
@@ -655,6 +663,114 @@ export declare namespace BillingSourcesCard {
|
|
|
655
663
|
}
|
|
656
664
|
}
|
|
657
665
|
|
|
666
|
+
/** Organization-wide per-project sponsorship subsidy controls. */
|
|
667
|
+
export function SponsorshipSubsidyCard(options: SponsorshipSubsidyCard.Props) {
|
|
668
|
+
const [enabled, setEnabled] = useState(options.policy.durationDays !== null)
|
|
669
|
+
const [projectSpendLimit, setProjectSpendLimit] = useState(options.policy.projectSpendLimit ?? '')
|
|
670
|
+
|
|
671
|
+
useEffect(() => {
|
|
672
|
+
setEnabled(options.policy.durationDays !== null)
|
|
673
|
+
setProjectSpendLimit(options.policy.projectSpendLimit ?? '')
|
|
674
|
+
}, [options.policy.durationDays, options.policy.projectSpendLimit])
|
|
675
|
+
|
|
676
|
+
return (
|
|
677
|
+
<Card>
|
|
678
|
+
<form
|
|
679
|
+
onSubmit={(event) => {
|
|
680
|
+
event.preventDefault()
|
|
681
|
+
if (!enabled) return options.onSave({ enabled: false })
|
|
682
|
+
if (!projectSpendLimit) return options.onSave({ enabled: true })
|
|
683
|
+
return options.onSave({ enabled: true, projectSpendLimit })
|
|
684
|
+
}}
|
|
685
|
+
>
|
|
686
|
+
<div className="flex items-start justify-between gap-4 p-4">
|
|
687
|
+
<div className="min-w-0">
|
|
688
|
+
<h3 className="text-label-14 text-foreground">Sponsorship subsidy</h3>
|
|
689
|
+
<p className="mt-1 text-copy-13 text-foreground-secondary">
|
|
690
|
+
Waive sponsored transaction charges for each project's first 90 days.
|
|
691
|
+
</p>
|
|
692
|
+
</div>
|
|
693
|
+
<Switch.Root
|
|
694
|
+
aria-label="Sponsorship subsidy"
|
|
695
|
+
checked={enabled}
|
|
696
|
+
className="flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-border bg-secondary p-0.5 outline-none transition-colors hover:bg-secondary-hover focus-visible:border-focus data-[checked]:bg-invert disabled:cursor-not-allowed disabled:opacity-50"
|
|
697
|
+
disabled={options.pending}
|
|
698
|
+
onCheckedChange={setEnabled}
|
|
699
|
+
>
|
|
700
|
+
<Switch.Thumb className="block size-4 translate-x-0 rounded-full bg-foreground-secondary transition-transform data-[checked]:translate-x-4 data-[checked]:bg-on-invert" />
|
|
701
|
+
</Switch.Root>
|
|
702
|
+
</div>
|
|
703
|
+
{enabled ? (
|
|
704
|
+
<div className="grid gap-4 border-t border-border p-4 md:grid-cols-2">
|
|
705
|
+
<label className="flex min-w-0 flex-col gap-2">
|
|
706
|
+
<span className="text-label-13 text-foreground-secondary">Duration per project</span>
|
|
707
|
+
<input
|
|
708
|
+
className="h-10 rounded-body border-2 border-transparent bg-secondary px-3 text-copy-14 text-foreground-secondary"
|
|
709
|
+
disabled
|
|
710
|
+
value="90 days"
|
|
711
|
+
/>
|
|
712
|
+
<span className="text-label-12 text-foreground-secondary">
|
|
713
|
+
Starts with the project's first mainnet sponsorship.
|
|
714
|
+
</span>
|
|
715
|
+
</label>
|
|
716
|
+
<label className="flex min-w-0 flex-col gap-2">
|
|
717
|
+
<span className="text-label-13 text-foreground-secondary">
|
|
718
|
+
Per-project spend cap (optional)
|
|
719
|
+
</span>
|
|
720
|
+
<span className="flex h-10 items-center rounded-body border-2 border-transparent bg-secondary px-3 focus-within:border-focus">
|
|
721
|
+
<span className="text-copy-14 text-foreground-secondary">$</span>
|
|
722
|
+
<input
|
|
723
|
+
aria-label="Per-project spend cap"
|
|
724
|
+
className="min-w-0 flex-1 bg-transparent px-2 text-copy-14 text-foreground outline-none"
|
|
725
|
+
disabled={options.pending}
|
|
726
|
+
inputMode="decimal"
|
|
727
|
+
min="0"
|
|
728
|
+
onChange={(event) => setProjectSpendLimit(event.target.value)}
|
|
729
|
+
placeholder="No cap"
|
|
730
|
+
step="0.000001"
|
|
731
|
+
type="number"
|
|
732
|
+
value={projectSpendLimit}
|
|
733
|
+
/>
|
|
734
|
+
</span>
|
|
735
|
+
<span className="text-label-12 text-foreground-secondary">
|
|
736
|
+
Leave blank for no spend cap.
|
|
737
|
+
</span>
|
|
738
|
+
</label>
|
|
739
|
+
</div>
|
|
740
|
+
) : (
|
|
741
|
+
<p className="border-t border-border p-4 text-copy-13 text-foreground-secondary">
|
|
742
|
+
New sponsorships for this organization are billed normally.
|
|
743
|
+
</p>
|
|
744
|
+
)}
|
|
745
|
+
<div className="flex items-center justify-end gap-3 border-t border-border p-4">
|
|
746
|
+
{options.error ? (
|
|
747
|
+
<p className="mr-auto text-copy-13 text-negative" role="alert">
|
|
748
|
+
{options.error.message}
|
|
749
|
+
</p>
|
|
750
|
+
) : null}
|
|
751
|
+
<Button loading={options.pending} type="submit">
|
|
752
|
+
Save policy
|
|
753
|
+
</Button>
|
|
754
|
+
</div>
|
|
755
|
+
</form>
|
|
756
|
+
</Card>
|
|
757
|
+
)
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
export declare namespace SponsorshipSubsidyCard {
|
|
761
|
+
/** Sponsorship subsidy control properties. */
|
|
762
|
+
type Props = {
|
|
763
|
+
/** Latest mutation error. */
|
|
764
|
+
error: Error | null
|
|
765
|
+
/** Saves a replacement policy. */
|
|
766
|
+
onSave: (policy: Organizations.setSponsorshipSubsidy.Input) => void
|
|
767
|
+
/** Whether a policy change is pending. */
|
|
768
|
+
pending: boolean
|
|
769
|
+
/** Current organization policy. */
|
|
770
|
+
policy: Organizations.Detail['sponsorshipSubsidy']
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
658
774
|
function BillingCard(options: BillingCard.Props) {
|
|
659
775
|
const { settings, source } = options.record
|
|
660
776
|
const remaining =
|