tapimo 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -8
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +5 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +28 -1
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +34 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +7532 -4850
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +11 -3
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +11 -2
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +14 -3
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +63 -53
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +7 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/scopes.d.ts +8 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +3 -0
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +57 -57
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +13 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +151 -0
- package/dist/analytics/Analytics.d.ts.map +1 -0
- package/dist/analytics/Analytics.js +212 -0
- package/dist/analytics/Analytics.js.map +1 -0
- package/dist/analytics/tables/requestEvents.d.ts +215 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
- package/dist/analytics/tables/requestEvents.js +264 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -0
- package/dist/apps/data/App.d.ts +1049 -624
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +36 -0
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingRouteProviders.d.ts +54 -0
- package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -0
- package/dist/apps/data/FundingRouteProviders.js +355 -0
- package/dist/apps/data/FundingRouteProviders.js.map +1 -0
- package/dist/apps/data/index.d.ts +1 -0
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +1 -0
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +45 -45
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/exchanges.d.ts +455 -455
- package/dist/apps/data/routes/fee-amm.d.ts +101 -101
- package/dist/apps/data/routes/funding.d.ts +843 -0
- package/dist/apps/data/routes/funding.d.ts.map +1 -0
- package/dist/apps/data/routes/funding.js +443 -0
- package/dist/apps/data/routes/funding.js.map +1 -0
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +2 -8
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +29 -36
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +29 -1
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/transfers.d.ts +56 -56
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/data/routes/webhooks.d.ts +45 -45
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +8 -8
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/docs/App.d.ts +5 -3
- package/dist/apps/docs/App.d.ts.map +1 -1
- package/dist/apps/docs/App.js +28 -96
- package/dist/apps/docs/App.js.map +1 -1
- package/dist/apps/docs/reference.d.ts +21 -0
- package/dist/apps/docs/reference.d.ts.map +1 -0
- package/dist/apps/docs/reference.js +112 -0
- package/dist/apps/docs/reference.js.map +1 -0
- package/dist/apps/index.d.ts +3 -2
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +3 -2
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/{platform → management}/App.d.ts +3015 -738
- package/dist/apps/management/App.d.ts.map +1 -0
- package/dist/apps/{platform → management}/App.js +20 -10
- package/dist/apps/management/App.js.map +1 -0
- package/dist/apps/management/Billing.d.ts +279 -0
- package/dist/apps/management/Billing.d.ts.map +1 -0
- package/dist/apps/management/Billing.js +477 -0
- package/dist/apps/management/Billing.js.map +1 -0
- package/dist/apps/management/index.d.ts +3 -0
- package/dist/apps/management/index.d.ts.map +1 -0
- package/dist/apps/management/index.js +3 -0
- package/dist/apps/management/index.js.map +1 -0
- package/dist/apps/{platform → management}/routes/api-keys.d.ts +341 -49
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/api-keys.js +116 -14
- package/dist/apps/management/routes/api-keys.js.map +1 -0
- package/dist/apps/management/routes/billing.d.ts +1520 -0
- package/dist/apps/management/routes/billing.d.ts.map +1 -0
- package/dist/apps/management/routes/billing.js +795 -0
- package/dist/apps/management/routes/billing.js.map +1 -0
- package/dist/apps/{platform → management}/routes/invitations.d.ts +202 -84
- package/dist/apps/management/routes/invitations.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/invitations.js +59 -1
- package/dist/apps/management/routes/invitations.js.map +1 -0
- package/dist/apps/{platform → management}/routes/me.d.ts +17 -17
- package/dist/apps/management/routes/me.d.ts.map +1 -0
- package/dist/apps/management/routes/me.js.map +1 -0
- package/dist/apps/management/routes/members.d.ts.map +1 -0
- package/dist/apps/management/routes/members.js.map +1 -0
- package/dist/apps/{platform → management}/routes/orgs.d.ts +50 -36
- package/dist/apps/management/routes/orgs.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/orgs.js +14 -3
- package/dist/apps/management/routes/orgs.js.map +1 -0
- package/dist/apps/{platform → management}/routes/projects.d.ts +97 -97
- package/dist/apps/{platform → management}/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js.map +1 -0
- package/dist/apps/management/routes/scopes.d.ts +107 -0
- package/dist/apps/management/routes/scopes.d.ts.map +1 -0
- package/dist/apps/management/routes/scopes.js +66 -0
- package/dist/apps/management/routes/scopes.js.map +1 -0
- package/dist/apps/management/routes/usage.d.ts +588 -0
- package/dist/apps/management/routes/usage.d.ts.map +1 -0
- package/dist/apps/management/routes/usage.js +391 -0
- package/dist/apps/management/routes/usage.js.map +1 -0
- package/dist/apps/mcp.d.ts +76 -0
- package/dist/apps/mcp.d.ts.map +1 -0
- package/dist/apps/mcp.js +188 -0
- package/dist/apps/mcp.js.map +1 -0
- package/dist/apps/relay/App.d.ts +4 -1
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +118 -10
- 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 +2 -1
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/cli/Cli.d.ts +8 -1
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +11 -3
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +4 -0
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +80 -1
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/db/Db.d.ts +7 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +126 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +79 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +88 -2
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/billingSettings.d.ts +55 -0
- package/dist/db/tables/billingSettings.d.ts.map +1 -0
- package/dist/db/tables/billingSettings.js +70 -0
- package/dist/db/tables/billingSettings.js.map +1 -0
- package/dist/db/tables/invitations.js +2 -2
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +6 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +10 -4
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.js +2 -2
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +121 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -0
- package/dist/db/tables/requestUsage.js +150 -0
- package/dist/db/tables/requestUsage.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +119 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +155 -2
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/stripeCustomers.d.ts +81 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
- package/dist/db/tables/stripeCustomers.js +120 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -0
- package/dist/db/tables/users.js +2 -2
- package/dist/db/tables/users.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +5 -2
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +19 -5
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +10 -3
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +14 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +18 -4
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +149 -77
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +4 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts +10 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +39 -8
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Fees.d.ts +27 -0
- package/dist/internal/Fees.d.ts.map +1 -0
- package/dist/internal/Fees.js +48 -0
- package/dist/internal/Fees.js.map +1 -0
- package/dist/internal/FundingRoutes.d.ts +915 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -0
- package/dist/internal/FundingRoutes.js +625 -0
- package/dist/internal/FundingRoutes.js.map +1 -0
- package/dist/internal/Id.d.ts +15 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +22 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/Log.d.ts +2 -0
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +3 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +10 -1
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +8 -1
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +25 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +51 -0
- package/dist/internal/RateLimit.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 +8 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +7 -0
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +3 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +8 -7
- package/src/ApiKey.ts +9 -2
- package/src/ApiKeys.test.ts +51 -0
- package/src/ApiKeys.ts +50 -1
- package/src/App.test.ts +33 -86718
- package/src/App.ts +26 -8
- package/src/Client.test-d.ts +353 -2
- package/src/Scope.ts +16 -3
- package/src/admin/apps/scopes.test.ts +6 -0
- package/src/admin/apps/scopes.ts +3 -0
- package/src/admin/ui/src/components/Page.tsx +2 -3
- package/src/admin/ui/src/routes/__root.tsx +2 -2
- package/src/admin/ui/src/routes/api-keys.tsx +2 -2
- package/src/admin/ui.generated.ts +13 -13
- package/src/analytics/Analytics.test.ts +527 -0
- package/src/analytics/Analytics.ts +318 -0
- package/src/analytics/tables/requestEvents.ts +523 -0
- package/src/apps/composition.test.ts +26 -13
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +37 -0
- package/src/apps/data/FundingRouteProviders.test.ts +281 -0
- package/src/apps/data/FundingRouteProviders.ts +459 -0
- package/src/apps/data/index.ts +1 -0
- package/src/apps/data/routes/funding.test.ts +314 -0
- package/src/apps/data/routes/funding.ts +698 -0
- package/src/apps/data/routes/receipts.ts +2 -9
- package/src/apps/data/routes/rpc.test.ts +78 -2
- package/src/apps/data/routes/rpc.ts +31 -1
- package/src/apps/data/routes/webhooks.test.ts +1 -1
- package/src/apps/data/routes/webhooks.ts +11 -8
- package/src/apps/docs/App.ts +30 -101
- package/src/apps/docs/reference.ts +132 -0
- package/src/apps/index.ts +3 -2
- package/src/apps/{platform → management}/App.ts +56 -17
- package/src/apps/management/Billing.test.ts +530 -0
- package/src/apps/management/Billing.ts +682 -0
- package/src/apps/management/index.ts +2 -0
- package/src/apps/{platform → management}/routes/api-keys.test.ts +172 -9
- package/src/apps/{platform → management}/routes/api-keys.ts +137 -21
- package/src/apps/management/routes/billing.test.ts +1100 -0
- package/src/apps/management/routes/billing.ts +966 -0
- package/src/apps/{platform → management}/routes/invitations.test.ts +55 -7
- package/src/apps/{platform → management}/routes/invitations.ts +69 -1
- package/src/apps/management/routes/me.test.ts +351 -0
- package/src/apps/{platform → management}/routes/orgs.ts +26 -4
- package/src/apps/management/routes/scopes.test.ts +29 -0
- package/src/apps/management/routes/scopes.ts +85 -0
- package/src/apps/management/routes/usage.test.ts +422 -0
- package/src/apps/management/routes/usage.ts +527 -0
- package/src/apps/mcp.test.ts +206 -0
- package/src/apps/mcp.ts +250 -0
- package/src/apps/relay/App.test.ts +457 -8
- package/src/apps/relay/App.ts +120 -12
- package/src/apps/relay/Sponsorships.test.ts +1 -1
- package/src/apps/relay/Sponsorships.ts +2 -1
- package/src/cli/Cli.test.ts +25 -2
- package/src/cli/Cli.ts +17 -2
- package/src/cli/commands/admin.test.ts +83 -0
- package/src/cli/commands/admin.ts +89 -1
- package/src/db/Db.ts +137 -0
- package/src/db/Schema.ts +104 -2
- package/src/db/tables/billingSettings.test.ts +87 -0
- package/src/db/tables/billingSettings.ts +108 -0
- package/src/db/tables/invitations.ts +2 -2
- package/src/db/tables/organizations.test.ts +1 -1
- package/src/db/tables/organizations.ts +15 -5
- package/src/db/tables/projects.ts +2 -2
- package/src/db/tables/requestUsage.ts +231 -0
- package/src/db/tables/sponsoredTransactions.test.ts +108 -1
- package/src/db/tables/sponsoredTransactions.ts +230 -2
- package/src/db/tables/stripeCustomers.test.ts +109 -0
- package/src/db/tables/stripeCustomers.ts +162 -0
- package/src/db/tables/users.ts +2 -2
- package/src/handlers/internal/sponsorship.ts +34 -7
- package/src/handlers/internal/utils.ts +19 -7
- package/src/index.ts +1 -0
- package/src/internal/Auth.test.ts +175 -25
- package/src/internal/Auth.ts +176 -87
- package/src/internal/Cache.ts +5 -1
- package/src/internal/EdgeCache.test.ts +27 -4
- package/src/internal/EdgeCache.ts +47 -9
- package/src/internal/Fees.test.ts +32 -0
- package/src/internal/Fees.ts +51 -0
- package/src/internal/FundingRoutes.test.ts +213 -0
- package/src/internal/FundingRoutes.ts +898 -0
- package/src/internal/Id.test.ts +17 -0
- package/src/internal/Id.ts +24 -0
- package/src/internal/Log.test.ts +1 -0
- package/src/internal/Log.ts +5 -0
- package/src/internal/OpenApi.ts +12 -1
- package/src/internal/RateLimit.test.ts +84 -0
- package/src/internal/RateLimit.ts +70 -0
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.ts +8 -0
- package/src/internal/Webhooks.test.ts +3 -3
- package/src/internal/Webhooks.ts +3 -3
- package/dist/apps/platform/App.d.ts.map +0 -1
- package/dist/apps/platform/App.js.map +0 -1
- package/dist/apps/platform/index.d.ts +0 -2
- package/dist/apps/platform/index.d.ts.map +0 -1
- package/dist/apps/platform/index.js +0 -2
- package/dist/apps/platform/index.js.map +0 -1
- package/dist/apps/platform/routes/api-keys.d.ts.map +0 -1
- package/dist/apps/platform/routes/api-keys.js.map +0 -1
- package/dist/apps/platform/routes/invitations.d.ts.map +0 -1
- package/dist/apps/platform/routes/invitations.js.map +0 -1
- package/dist/apps/platform/routes/me.d.ts.map +0 -1
- package/dist/apps/platform/routes/me.js.map +0 -1
- package/dist/apps/platform/routes/members.d.ts.map +0 -1
- package/dist/apps/platform/routes/members.js.map +0 -1
- package/dist/apps/platform/routes/orgs.d.ts.map +0 -1
- package/dist/apps/platform/routes/orgs.js.map +0 -1
- package/dist/apps/platform/routes/projects.js.map +0 -1
- package/src/apps/platform/index.ts +0 -1
- package/src/apps/platform/routes/me.test.ts +0 -121
- /package/dist/apps/{platform → management}/routes/me.js +0 -0
- /package/dist/apps/{platform → management}/routes/members.d.ts +0 -0
- /package/dist/apps/{platform → management}/routes/members.js +0 -0
- /package/dist/apps/{platform → management}/routes/projects.js +0 -0
- /package/src/apps/{platform → management}/routes/me.ts +0 -0
- /package/src/apps/{platform → management}/routes/members.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/members.ts +0 -0
- /package/src/apps/{platform → management}/routes/orgs.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/projects.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/projects.ts +0 -0
package/src/apps/data/App.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { blocks, blocksByTimestampCompat } from './routes/blocks.js'
|
|
|
17
17
|
import { coingecko } from './routes/coingecko.js'
|
|
18
18
|
import { exchanges } from './routes/exchanges.js'
|
|
19
19
|
import { feeAmm } from './routes/fee-amm.js'
|
|
20
|
+
import { funding } from './routes/funding.js'
|
|
20
21
|
import { indexer } from './routes/indexer.js'
|
|
21
22
|
import { receipts } from './routes/receipts.js'
|
|
22
23
|
import { rpc } from './routes/rpc.js'
|
|
@@ -94,6 +95,34 @@ export function data(options: data.Options = {}) {
|
|
|
94
95
|
if (!parsed.success || supportedChainIds.has(parsed.data)) return next()
|
|
95
96
|
return Response.unsupportedChainId(c, parsed.data, supportedChainIds)
|
|
96
97
|
})
|
|
98
|
+
// Sandbox keys are testnet-only. A chain-scoped data route defaults to
|
|
99
|
+
// mainnet, so a sandbox key that omits `chainId` (or targets mainnet) is
|
|
100
|
+
// refused with a clear message telling the caller to pass a testnet
|
|
101
|
+
// `chainId`. The relay resolves its chain from the request body, not the
|
|
102
|
+
// query, so it is skipped and enforces the rule in its sponsor validation.
|
|
103
|
+
.use('*', async (c, next) => {
|
|
104
|
+
const relay = Path.join(c.get('basePath') ?? '', 'rpc/relay')
|
|
105
|
+
if (c.req.path === relay || c.req.path.startsWith(`${relay}/`)) return next()
|
|
106
|
+
|
|
107
|
+
const principal = Auth.getPrincipal(c)
|
|
108
|
+
if (principal?.type !== 'api_key' || principal.environment !== 'sandbox') return next()
|
|
109
|
+
|
|
110
|
+
const raw = c.req.query('chainId') ?? c.req.query('chain_id')
|
|
111
|
+
// Absent falls back to the group default (mainnet); a malformed value
|
|
112
|
+
// stays with the route's own validator rather than the sandbox message.
|
|
113
|
+
const chainId = (() => {
|
|
114
|
+
if (raw === undefined) return defaultChainId
|
|
115
|
+
const parsed = Schema.ChainId.safeParse(raw)
|
|
116
|
+
return parsed.success ? parsed.data : undefined
|
|
117
|
+
})()
|
|
118
|
+
if (chainId === undefined || !Viem.isMainnet(chainId)) return next()
|
|
119
|
+
|
|
120
|
+
return Response.error(c, {
|
|
121
|
+
code: 'api_key_forbidden',
|
|
122
|
+
message: 'Sandbox API keys only support testnet. Pass a testnet `chainId`.',
|
|
123
|
+
status: 403,
|
|
124
|
+
})
|
|
125
|
+
})
|
|
97
126
|
// Serve static API assets (e.g. verified-token icons) from the configured
|
|
98
127
|
// store; a no-op fall-through when no store is configured (logo URIs simply
|
|
99
128
|
// go unresolved).
|
|
@@ -111,6 +140,7 @@ export function data(options: data.Options = {}) {
|
|
|
111
140
|
.route('/', blocks())
|
|
112
141
|
.route('/', exchanges())
|
|
113
142
|
.route('/', feeAmm())
|
|
143
|
+
.route('/', funding(options.fundingRoutes))
|
|
114
144
|
.route('/', indexer())
|
|
115
145
|
.route('/', receipts())
|
|
116
146
|
.route('/', tokenlist())
|
|
@@ -133,6 +163,8 @@ export declare namespace data {
|
|
|
133
163
|
assets?: Assets.Assets | undefined
|
|
134
164
|
/** Default Tempo chain id for requests that omit `chainId`. */
|
|
135
165
|
defaultChainId?: Viem.ChainId | undefined
|
|
166
|
+
/** Funding route provider adapter configuration. Omit to serve static inventory only. */
|
|
167
|
+
fundingRoutes?: funding.Options | undefined
|
|
136
168
|
/** Tempo RPC options: a static config, or a per-request resolver that routes by request principal to a separate (e.g. public, no-auth) RPC. */
|
|
137
169
|
rpc?: Viem.getClient.Rpc | undefined
|
|
138
170
|
/** Extra chain ids this deployment serves, beyond the built-in public chains and `defaultChainId`. A `chainId` outside this set is rejected with a 400. */
|
|
@@ -178,6 +210,8 @@ const openapi = {
|
|
|
178
210
|
{ name: 'Blocks', description: 'The ordered batches of transactions making up the chain.' },
|
|
179
211
|
{ name: 'Exchange', description: "Tempo's built-in stablecoin exchange: pairs, swaps, orders, prices." }, // prettier-ignore
|
|
180
212
|
{ name: 'Fee AMM', description: 'Pools that convert stablecoins to pay fees.' },
|
|
213
|
+
{ name: 'Funding', description: 'Routes and inventory for moving stablecoins into Tempo.' },
|
|
214
|
+
{ name: 'Providers', description: 'Provider metadata, capabilities, and integration status.' },
|
|
181
215
|
{ name: 'Tokens', description: 'TIP-20 token details, supply, and holders.' },
|
|
182
216
|
{ name: 'Transactions', description: 'Transactions submitted to Tempo, and their receipts.' },
|
|
183
217
|
{ name: 'Transfers', description: 'Token movements from executing transactions.' },
|
|
@@ -196,6 +230,8 @@ const openapi = {
|
|
|
196
230
|
'Blocks',
|
|
197
231
|
'Exchange',
|
|
198
232
|
'Fee AMM',
|
|
233
|
+
'Funding',
|
|
234
|
+
'Providers',
|
|
199
235
|
'Tokens',
|
|
200
236
|
'Transactions',
|
|
201
237
|
'Transfers',
|
|
@@ -203,6 +239,7 @@ const openapi = {
|
|
|
203
239
|
'Webhooks',
|
|
204
240
|
'Indexer',
|
|
205
241
|
'RPC',
|
|
242
|
+
'MCP',
|
|
206
243
|
'CoinGecko',
|
|
207
244
|
],
|
|
208
245
|
},
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import * as FundingRoutes from '../../internal/FundingRoutes.js'
|
|
2
|
+
import * as FundingRouteProviders from './FundingRouteProviders.js'
|
|
3
|
+
|
|
4
|
+
const now = () => new Date('2026-01-01T00:00:00.000Z')
|
|
5
|
+
|
|
6
|
+
describe('FundingRouteProviders', () => {
|
|
7
|
+
test('maps Across suggested-fees responses into quote probes', async () => {
|
|
8
|
+
const requests: RecordedRequest[] = []
|
|
9
|
+
const fetch = recordingFetch(requests, async () =>
|
|
10
|
+
jsonResponse({
|
|
11
|
+
estimatedFillTimeSec: 2,
|
|
12
|
+
limits: {
|
|
13
|
+
maxDeposit: '2000000',
|
|
14
|
+
maxDepositInstant: '1500000',
|
|
15
|
+
minDeposit: '500000',
|
|
16
|
+
},
|
|
17
|
+
outputAmount: '990000',
|
|
18
|
+
relayFeePct: '1200000000000000',
|
|
19
|
+
timestamp: '1767225600',
|
|
20
|
+
}),
|
|
21
|
+
)
|
|
22
|
+
const adapter = FundingRouteProviders.across({
|
|
23
|
+
apiKey: 'across-api-key',
|
|
24
|
+
baseUrl: 'https://across.test/api/',
|
|
25
|
+
fetch,
|
|
26
|
+
integratorId: 'tempo',
|
|
27
|
+
now,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const result = await adapter.probeQuote(
|
|
31
|
+
await probeInput('across'),
|
|
32
|
+
new AbortController().signal,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
expect(requests).toHaveLength(1)
|
|
36
|
+
expect(requests[0]?.url.pathname).toBe('/api/suggested-fees')
|
|
37
|
+
expect(requests[0]?.url.searchParams.get('originChainId')).toBe('8453')
|
|
38
|
+
expect(requests[0]?.url.searchParams.get('destinationChainId')).toBe('4217')
|
|
39
|
+
expect(requests[0]?.url.searchParams.get('amount')).toBe('1000000')
|
|
40
|
+
expect(requests[0]?.url.searchParams.get('integratorId')).toBe('tempo')
|
|
41
|
+
expect(requests[0]?.url.searchParams.get('allowUnmatchedDecimals')).toBe('true')
|
|
42
|
+
expect(new Headers(requests[0]?.init?.headers).get('authorization')).toBe(
|
|
43
|
+
'Bearer across-api-key',
|
|
44
|
+
)
|
|
45
|
+
expect(result).toMatchObject({
|
|
46
|
+
expiresAt: '2026-01-01T00:10:00.000Z',
|
|
47
|
+
limits: {
|
|
48
|
+
instantSourceAmount: '1500000',
|
|
49
|
+
maxSourceAmount: '2000000',
|
|
50
|
+
minSourceAmount: '500000',
|
|
51
|
+
},
|
|
52
|
+
outputAmount: '990000',
|
|
53
|
+
outputAmountFormatted: '0.99',
|
|
54
|
+
quality: {
|
|
55
|
+
availableVolumeUsd: '2',
|
|
56
|
+
estimatedSeconds: 2,
|
|
57
|
+
feeBps: 12,
|
|
58
|
+
instantVolumeUsd: '1.5',
|
|
59
|
+
liquiditySource: 'providerLimit',
|
|
60
|
+
sourceDetail: 'across:suggested-fees',
|
|
61
|
+
tier: 'liquid',
|
|
62
|
+
},
|
|
63
|
+
sampledAt: '2026-01-01T00:00:00.000Z',
|
|
64
|
+
status: 'available',
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('maps recognized Across quote errors to unavailable probes', async () => {
|
|
69
|
+
const fetch = recordingFetch([], async () =>
|
|
70
|
+
jsonResponse({ code: 'AMOUNT_TOO_HIGH', message: 'Amount exceeds max deposit' }, 400),
|
|
71
|
+
)
|
|
72
|
+
const adapter = FundingRouteProviders.across({
|
|
73
|
+
apiKey: 'across-api-key',
|
|
74
|
+
fetch,
|
|
75
|
+
integratorId: 'tempo',
|
|
76
|
+
now,
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const result = await adapter.probeQuote(
|
|
80
|
+
await probeInput('across'),
|
|
81
|
+
new AbortController().signal,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
expect(result).toMatchObject({
|
|
85
|
+
quality: {
|
|
86
|
+
liquiditySource: 'providerLimit',
|
|
87
|
+
score: 0,
|
|
88
|
+
sourceDetail: 'across:suggested-fees:AMOUNT_TOO_HIGH',
|
|
89
|
+
tier: 'unavailable',
|
|
90
|
+
},
|
|
91
|
+
sampledAt: '2026-01-01T00:00:00.000Z',
|
|
92
|
+
status: 'unavailable',
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('maps Relay liquidity and quote responses into quote probes', async () => {
|
|
97
|
+
const requests: RecordedRequest[] = []
|
|
98
|
+
const route = await staticRoute('relay')
|
|
99
|
+
const fetch = recordingFetch(requests, async (request) => {
|
|
100
|
+
if (request.url.pathname === '/quote/v2')
|
|
101
|
+
return jsonResponse({
|
|
102
|
+
details: {
|
|
103
|
+
currencyOut: {
|
|
104
|
+
amount: '990000',
|
|
105
|
+
minimumAmount: '980000',
|
|
106
|
+
},
|
|
107
|
+
timeEstimate: 15,
|
|
108
|
+
totalImpact: { percent: '-1.20' },
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
return jsonResponse({
|
|
112
|
+
liquidity: [
|
|
113
|
+
{
|
|
114
|
+
address: route.destinationToken.address.toUpperCase(),
|
|
115
|
+
amountUsd: '5.00',
|
|
116
|
+
balance: '5000000',
|
|
117
|
+
chainId: 4217,
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
const adapter = FundingRouteProviders.relay({
|
|
123
|
+
apiKey: 'relay-api-key',
|
|
124
|
+
fetch,
|
|
125
|
+
now,
|
|
126
|
+
userAddress: '0x1111111111111111111111111111111111111111',
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const result = await adapter.probeQuote(
|
|
130
|
+
probeInputFromRoute(route),
|
|
131
|
+
new AbortController().signal,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
expect(requests.map((request) => request.url.pathname)).toEqual([
|
|
135
|
+
'/quote/v2',
|
|
136
|
+
'/chains/liquidity',
|
|
137
|
+
])
|
|
138
|
+
expect(requests[1]?.url.searchParams.get('chainId')).toBe('4217')
|
|
139
|
+
expect(new Headers(requests[0]?.init?.headers).get('x-api-key')).toBe('relay-api-key')
|
|
140
|
+
expect(jsonRequestBody(requests[0])).toMatchObject({
|
|
141
|
+
amount: '1000000',
|
|
142
|
+
destinationChainId: 4217,
|
|
143
|
+
destinationCurrency: route.destinationToken.address,
|
|
144
|
+
originChainId: 8453,
|
|
145
|
+
originCurrency: route.sourceToken.address,
|
|
146
|
+
tradeType: 'EXACT_INPUT',
|
|
147
|
+
user: '0x1111111111111111111111111111111111111111',
|
|
148
|
+
})
|
|
149
|
+
expect(result).toMatchObject({
|
|
150
|
+
limits: null,
|
|
151
|
+
minimumOutputAmount: '980000',
|
|
152
|
+
outputAmount: '990000',
|
|
153
|
+
outputAmountFormatted: '0.99',
|
|
154
|
+
quality: {
|
|
155
|
+
availableVolumeUsd: '5.00',
|
|
156
|
+
estimatedSeconds: 15,
|
|
157
|
+
feeBps: null,
|
|
158
|
+
instantVolumeUsd: '5.00',
|
|
159
|
+
liquiditySource: 'providerQuote',
|
|
160
|
+
sourceDetail: 'relay:quote-v2',
|
|
161
|
+
tier: 'liquid',
|
|
162
|
+
},
|
|
163
|
+
sampledAt: '2026-01-01T00:00:00.000Z',
|
|
164
|
+
status: 'available',
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('keeps Relay quotes when the liquidity probe fails', async () => {
|
|
169
|
+
const route = await staticRoute('relay')
|
|
170
|
+
const fetch = recordingFetch([], async (request) => {
|
|
171
|
+
if (request.url.pathname === '/quote/v2')
|
|
172
|
+
return jsonResponse({
|
|
173
|
+
details: {
|
|
174
|
+
currencyOut: {
|
|
175
|
+
amount: '990000',
|
|
176
|
+
minimumAmount: '980000',
|
|
177
|
+
},
|
|
178
|
+
timeEstimate: 15,
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
return jsonResponse({ message: 'temporarily unavailable' }, 503)
|
|
182
|
+
})
|
|
183
|
+
const adapter = FundingRouteProviders.relay({
|
|
184
|
+
fetch,
|
|
185
|
+
now,
|
|
186
|
+
userAddress: '0x1111111111111111111111111111111111111111',
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
const result = await adapter.probeQuote(
|
|
190
|
+
probeInputFromRoute(route),
|
|
191
|
+
new AbortController().signal,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
expect(result).toMatchObject({
|
|
195
|
+
outputAmount: '990000',
|
|
196
|
+
quality: {
|
|
197
|
+
availableVolumeUsd: null,
|
|
198
|
+
instantVolumeUsd: null,
|
|
199
|
+
liquiditySource: 'providerQuote',
|
|
200
|
+
tier: 'unknown',
|
|
201
|
+
},
|
|
202
|
+
status: 'unknown',
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
type RecordedRequest = {
|
|
208
|
+
init: RequestInit | undefined
|
|
209
|
+
url: URL
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async function staticRoute(
|
|
213
|
+
provider: FundingRoutes.ProviderId,
|
|
214
|
+
): Promise<FundingRoutes.QuoteProbeInput['route']> {
|
|
215
|
+
const [route] = await FundingRoutes.listRoutes({
|
|
216
|
+
limit: 10,
|
|
217
|
+
provider,
|
|
218
|
+
sourceAmount: '1000000',
|
|
219
|
+
sourceAmountUnits: 'baseUnits',
|
|
220
|
+
sourceToken: 'USDC',
|
|
221
|
+
sourceChain: 'base',
|
|
222
|
+
})
|
|
223
|
+
if (!route) throw new Error(`Missing ${provider} route`)
|
|
224
|
+
return route as FundingRoutes.QuoteProbeInput['route']
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function probeInput(provider: FundingRoutes.ProviderId) {
|
|
228
|
+
return probeInputFromRoute(await staticRoute(provider))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function probeInputFromRoute(
|
|
232
|
+
route: FundingRoutes.QuoteProbeInput['route'],
|
|
233
|
+
): FundingRoutes.QuoteProbeInput {
|
|
234
|
+
return {
|
|
235
|
+
cache: { bypass: false },
|
|
236
|
+
destinationChain: route.destinationChain,
|
|
237
|
+
destinationToken: route.destinationToken,
|
|
238
|
+
include: ['quotes'],
|
|
239
|
+
request: {
|
|
240
|
+
include: ['quotes'],
|
|
241
|
+
limit: 10,
|
|
242
|
+
provider: route.provider.id,
|
|
243
|
+
sourceAmount: route.sourceAmount.amount,
|
|
244
|
+
sourceAmountUnits: 'baseUnits',
|
|
245
|
+
sourceChain: route.sourceChain.id,
|
|
246
|
+
sourceToken: route.sourceToken.symbol,
|
|
247
|
+
},
|
|
248
|
+
route,
|
|
249
|
+
sourceAmount: route.sourceAmount,
|
|
250
|
+
sourceChain: route.sourceChain,
|
|
251
|
+
sourceToken: route.sourceToken,
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function recordingFetch(
|
|
256
|
+
requests: RecordedRequest[],
|
|
257
|
+
respond: (request: RecordedRequest) => Response | Promise<Response>,
|
|
258
|
+
): typeof globalThis.fetch {
|
|
259
|
+
return async (input, init) => {
|
|
260
|
+
const request = { init, url: toUrl(input) }
|
|
261
|
+
requests.push(request)
|
|
262
|
+
return respond(request)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function toUrl(input: Parameters<typeof globalThis.fetch>[0]) {
|
|
267
|
+
if (input instanceof Request) return new URL(input.url)
|
|
268
|
+
return new URL(String(input))
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function jsonResponse(body: unknown, status = 200) {
|
|
272
|
+
return new Response(JSON.stringify(body), {
|
|
273
|
+
headers: { 'content-type': 'application/json' },
|
|
274
|
+
status,
|
|
275
|
+
})
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function jsonRequestBody(request: RecordedRequest | undefined) {
|
|
279
|
+
if (typeof request?.init?.body !== 'string') throw new Error('Expected JSON request body')
|
|
280
|
+
return JSON.parse(request.init.body) as unknown
|
|
281
|
+
}
|