tapimo 0.5.3 → 0.7.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 +15830 -7220
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +9 -1
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +4 -0
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +5 -0
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +1011 -412
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +4 -0
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +2 -1
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/early-access.d.ts +148 -0
- package/dist/admin/apps/early-access.d.ts.map +1 -0
- package/dist/admin/apps/early-access.js +133 -0
- package/dist/admin/apps/early-access.js.map +1 -0
- package/dist/admin/apps/organizations.d.ts +124 -1
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +97 -6
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +526 -1
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +214 -1
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +95 -75
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +20 -0
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +18 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +36 -7
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +6260 -4924
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +11 -6
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.js +194 -16
- package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +71 -0
- package/dist/apps/data/FxOracle.d.ts.map +1 -0
- package/dist/apps/data/FxOracle.js +97 -0
- package/dist/apps/data/FxOracle.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/activities.d.ts +3599 -1382
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +250 -88
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +872 -251
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/addresses.js +11 -9
- package/dist/apps/data/routes/addresses.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +77 -26
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +88 -45
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +39 -39
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/exchanges.d.ts +856 -105
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +518 -76
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +81 -67
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +76 -91
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/funding.d.ts +80 -36
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +65 -31
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +392 -315
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +152 -77
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +167 -174
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +15 -13
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +277 -536
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +96 -77
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +157 -81
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +272 -130
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +307 -0
- package/dist/apps/data/routes/valuation.d.ts.map +1 -0
- package/dist/apps/data/routes/valuation.js +292 -0
- package/dist/apps/data/routes/valuation.js.map +1 -0
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +7 -5
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +103 -123
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +124 -25
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/index.d.ts +2 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +2 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +8554 -1692
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +12 -1
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +7 -0
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +17 -3
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +157 -162
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +31 -23
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +232 -0
- package/dist/apps/management/routes/faucet.d.ts.map +1 -0
- package/dist/apps/management/routes/faucet.js +154 -0
- package/dist/apps/management/routes/faucet.js.map +1 -0
- package/dist/apps/management/routes/invitations.d.ts +60 -60
- package/dist/apps/management/routes/invite-links.d.ts +49 -20
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +26 -1
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/members.d.ts +6 -6
- package/dist/apps/management/routes/orgs.d.ts +42 -42
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +5 -0
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +44 -44
- package/dist/apps/management/routes/usage.d.ts +3 -0
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +4 -0
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
- package/dist/apps/management/routes/verified-token-requests.js +271 -0
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
- package/dist/apps/management/routes/webhooks.d.ts +6977 -0
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
- package/dist/apps/management/routes/webhooks.js +573 -0
- package/dist/apps/management/routes/webhooks.js.map +1 -0
- package/dist/apps/mpp/App.d.ts +363 -0
- package/dist/apps/mpp/App.d.ts.map +1 -0
- package/dist/apps/mpp/App.js +72 -0
- package/dist/apps/mpp/App.js.map +1 -0
- package/dist/apps/mpp/Mpp.d.ts +178 -0
- package/dist/apps/mpp/Mpp.d.ts.map +1 -0
- package/dist/apps/mpp/Mpp.js +183 -0
- package/dist/apps/mpp/Mpp.js.map +1 -0
- package/dist/apps/mpp/index.d.ts +3 -0
- package/dist/apps/mpp/index.d.ts.map +1 -0
- package/dist/apps/mpp/index.js +3 -0
- package/dist/apps/mpp/index.js.map +1 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +56 -9
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/db/Db.d.ts +6 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +110 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +53 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -0
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earlyAccess.d.ts +50 -0
- package/dist/db/tables/earlyAccess.d.ts.map +1 -0
- package/dist/db/tables/earlyAccess.js +63 -0
- package/dist/db/tables/earlyAccess.js.map +1 -0
- package/dist/db/tables/enabledBillingSources.d.ts +73 -0
- package/dist/db/tables/enabledBillingSources.d.ts.map +1 -0
- package/dist/db/tables/enabledBillingSources.js +69 -0
- package/dist/db/tables/enabledBillingSources.js.map +1 -0
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/invitations.js +3 -0
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/inviteLinks.d.ts +10 -2
- package/dist/db/tables/inviteLinks.d.ts.map +1 -1
- package/dist/db/tables/inviteLinks.js +10 -1
- package/dist/db/tables/inviteLinks.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +5 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +13 -2
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +2 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokenRequests.js +120 -0
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +16 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +1 -16
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +17 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +37 -5
- package/dist/handlers/relay.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 +14 -47
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/FundingQuotes.d.ts +147 -47
- package/dist/internal/FundingQuotes.d.ts.map +1 -1
- package/dist/internal/FundingQuotes.js +119 -33
- package/dist/internal/FundingQuotes.js.map +1 -1
- package/dist/internal/Log.d.ts +37 -5
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +52 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +24 -0
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +2 -2
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +3 -0
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +2 -2
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +12 -4
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +14 -5
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +23 -5
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Value.d.ts +18 -0
- package/dist/internal/Value.d.ts.map +1 -1
- package/dist/internal/Value.js +11 -1
- package/dist/internal/Value.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +10 -1
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +24 -3
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +34 -8
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +7 -2
- package/src/App.test.ts +9 -4
- package/src/App.ts +23 -3
- package/src/Client.test-d.ts +733 -20
- package/src/Scope.ts +5 -0
- package/src/admin/App.test.ts +4 -0
- package/src/admin/App.ts +4 -0
- package/src/admin/apps/early-access.test.ts +125 -0
- package/src/admin/apps/early-access.ts +176 -0
- package/src/admin/apps/organizations.test.ts +86 -2
- package/src/admin/apps/organizations.ts +155 -31
- package/src/admin/apps/scopes.test.ts +5 -0
- package/src/admin/apps/verified-tokens.test.ts +201 -0
- package/src/admin/apps/verified-tokens.ts +532 -286
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/lib/early-access.ts +63 -0
- package/src/admin/ui/src/lib/organizations.test.ts +81 -1
- package/src/admin/ui/src/lib/organizations.ts +92 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
- package/src/admin/ui/src/routeTree.gen.ts +33 -2
- package/src/admin/ui/src/routes/__root.tsx +2 -1
- package/src/admin/ui/src/routes/api-keys.tsx +1 -1
- package/src/admin/ui/src/routes/early-access.tsx +162 -0
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +103 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
- package/src/admin/ui.generated.ts +95 -94
- package/src/analytics/Analytics.test.ts +83 -0
- package/src/analytics/Analytics.ts +20 -0
- package/src/analytics/tables/requestEvents.ts +60 -7
- package/src/apps/composition.test.ts +11 -2
- package/src/apps/data/App.test.ts +1 -1
- package/src/apps/data/App.ts +22 -14
- package/src/apps/data/FundingQuoteProviders.test.ts +297 -4
- package/src/apps/data/FundingQuoteProviders.ts +255 -29
- package/src/apps/data/FxOracle.test.ts +118 -0
- package/src/apps/data/FxOracle.ts +153 -0
- package/src/apps/data/index.ts +1 -0
- package/src/apps/data/routes/activities.test.ts +177 -3
- package/src/apps/data/routes/activities.ts +441 -132
- package/src/apps/data/routes/addresses.ts +19 -9
- package/src/apps/data/routes/balances.test.ts +148 -11
- package/src/apps/data/routes/balances.ts +140 -51
- package/src/apps/data/routes/exchanges.test.ts +544 -9
- package/src/apps/data/routes/exchanges.ts +690 -103
- package/src/apps/data/routes/fee-amm.test.ts +47 -23
- package/src/apps/data/routes/fee-amm.ts +98 -119
- package/src/apps/data/routes/funding.test.ts +113 -8
- package/src/apps/data/routes/funding.ts +77 -51
- package/src/apps/data/routes/receipts.test.ts +129 -23
- package/src/apps/data/routes/receipts.ts +205 -100
- package/src/apps/data/routes/tokens.test.ts +43 -0
- package/src/apps/data/routes/tokens.ts +28 -13
- package/src/apps/data/routes/transactions.test.ts +72 -19
- package/src/apps/data/routes/transactions.ts +162 -92
- package/src/apps/data/routes/transfers.test.ts +341 -31
- package/src/apps/data/routes/transfers.ts +358 -158
- package/src/apps/data/routes/valuation.test.ts +437 -0
- package/src/apps/data/routes/valuation.ts +423 -0
- package/src/apps/data/routes/verified-tokens.ts +14 -2
- package/src/apps/data/routes/webhooks.test.ts +56 -8
- package/src/apps/data/routes/webhooks.ts +144 -27
- package/src/apps/index.ts +2 -1
- package/src/apps/management/App.ts +13 -0
- package/src/apps/management/routes/api-keys.test.ts +14 -0
- package/src/apps/management/routes/api-keys.ts +27 -3
- package/src/apps/management/routes/billing.test.ts +152 -20
- package/src/apps/management/routes/billing.ts +34 -18
- package/src/apps/management/routes/faucet.test.ts +87 -0
- package/src/apps/management/routes/faucet.ts +201 -0
- package/src/apps/management/routes/invite-links.test.ts +117 -0
- package/src/apps/management/routes/invite-links.ts +43 -1
- package/src/apps/management/routes/me.test.ts +9 -99
- package/src/apps/management/routes/orgs.test.ts +45 -2
- package/src/apps/management/routes/orgs.ts +6 -0
- package/src/apps/management/routes/scopes.test.ts +1 -0
- package/src/apps/management/routes/usage.test.ts +6 -0
- package/src/apps/management/routes/usage.ts +7 -0
- package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
- package/src/apps/management/routes/verified-token-requests.ts +397 -0
- package/src/apps/management/routes/webhooks.test.ts +426 -0
- package/src/apps/management/routes/webhooks.ts +672 -0
- package/src/apps/mpp/App.ts +86 -0
- package/src/apps/mpp/Mpp.test.ts +193 -0
- package/src/apps/mpp/Mpp.ts +353 -0
- package/src/apps/mpp/index.ts +2 -0
- package/src/apps/mpp/internal/Adapter.ts +11 -0
- package/src/apps/mpp/internal/Error.ts +9 -0
- package/src/apps/mpp/internal/Idempotency.ts +7 -0
- package/src/apps/mpp/internal/Screening.ts +10 -0
- package/src/apps/relay/App.test.ts +88 -6
- package/src/apps/relay/App.ts +61 -9
- package/src/db/Db.test.ts +19 -0
- package/src/db/Db.ts +125 -0
- package/src/db/Schema.ts +68 -0
- package/src/db/tables/earlyAccess.ts +86 -0
- package/src/db/tables/enabledBillingSources.test.ts +303 -0
- package/src/db/tables/enabledBillingSources.ts +118 -0
- package/src/db/tables/invitations.ts +3 -0
- package/src/db/tables/inviteLinks.ts +22 -3
- package/src/db/tables/organizations.test.ts +103 -0
- package/src/db/tables/organizations.ts +18 -2
- package/src/db/tables/sponsoredTransactions.ts +4 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
- package/src/db/tables/verifiedTokenRequests.ts +182 -0
- package/src/db/tables/webhookSubscriptions.ts +31 -0
- package/src/handlers/internal/utils.ts +22 -6
- package/src/handlers/relay.errors.test.ts +153 -0
- package/src/handlers/relay.ts +42 -7
- package/src/internal/Auth.test.ts +3 -3
- package/src/internal/Auth.ts +15 -47
- package/src/internal/FundingQuotes.test.ts +161 -6
- package/src/internal/FundingQuotes.ts +141 -39
- package/src/internal/Log.test-d.ts +21 -0
- package/src/internal/Log.test.ts +141 -0
- package/src/internal/Log.ts +93 -6
- package/src/internal/MetricSink.test.ts +215 -0
- package/src/internal/MetricSink.ts +24 -0
- package/src/internal/OpenApi.ts +3 -0
- package/src/internal/Response.test.ts +28 -0
- package/src/internal/Response.ts +12 -4
- package/src/internal/Schema.ts +50 -5
- package/src/internal/Value.test.ts +20 -0
- package/src/internal/Value.ts +24 -1
- package/src/internal/VerifiedTokens.ts +9 -1
- package/src/internal/Webhooks.test.ts +140 -0
- package/src/internal/Webhooks.ts +53 -9
package/src/handlers/relay.ts
CHANGED
|
@@ -639,20 +639,30 @@ export function relay(options: relay.Options = {}): Handler {
|
|
|
639
639
|
|
|
640
640
|
async function handlePost(c: { req: { raw: Request; param: (key: string) => string } }) {
|
|
641
641
|
const chainId = Utils.resolveChainId(c.req.param('chainId'))
|
|
642
|
-
const body = await c.req.raw.json()
|
|
642
|
+
const body = await c.req.raw.json().catch(() => undefined)
|
|
643
|
+
if (body === undefined) return Response.json(rpcProtocolError('parse'))
|
|
644
|
+
|
|
643
645
|
const isBatch = Array.isArray(body)
|
|
644
646
|
|
|
645
647
|
if (!isBatch) {
|
|
648
|
+
if (!isRpcRequest(body)) return Response.json(rpcProtocolError('invalid_request'))
|
|
646
649
|
const request = RpcRequest.from(body as never) as RpcRequest.RpcRequest<RpcSchema.Ox>
|
|
647
|
-
|
|
650
|
+
const response = await handleRequest(request, { chainId }).catch((error) =>
|
|
651
|
+
Utils.rpcErrorJson(request, error),
|
|
652
|
+
)
|
|
653
|
+
return Response.json(response)
|
|
648
654
|
}
|
|
649
655
|
|
|
656
|
+
if (body.length === 0) return Response.json(rpcProtocolError('invalid_request'))
|
|
657
|
+
|
|
650
658
|
const responses = await Promise.all(
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
659
|
+
body.map((item) => {
|
|
660
|
+
if (!isRpcRequest(item)) return Promise.resolve(rpcProtocolError('invalid_request'))
|
|
661
|
+
return handleRequest(
|
|
662
|
+
RpcRequest.from(item as never) as RpcRequest.RpcRequest<RpcSchema.Ox>,
|
|
663
|
+
{ chainId },
|
|
664
|
+
).catch((error) => Utils.rpcErrorJson(item as RpcRequest.RpcRequest, error))
|
|
665
|
+
}),
|
|
656
666
|
)
|
|
657
667
|
return Response.json(responses)
|
|
658
668
|
}
|
|
@@ -663,6 +673,31 @@ export function relay(options: relay.Options = {}): Handler {
|
|
|
663
673
|
return router
|
|
664
674
|
}
|
|
665
675
|
|
|
676
|
+
function isRpcRequest(value: unknown): value is Record<string, unknown> {
|
|
677
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false
|
|
678
|
+
const request = value as Record<string, unknown>
|
|
679
|
+
if (request['jsonrpc'] !== '2.0' || typeof request['method'] !== 'string') return false
|
|
680
|
+
|
|
681
|
+
const id = request['id']
|
|
682
|
+
if (id !== undefined && id !== null && typeof id !== 'number' && typeof id !== 'string')
|
|
683
|
+
return false
|
|
684
|
+
|
|
685
|
+
const params = request['params']
|
|
686
|
+
if (params === undefined || Array.isArray(params)) return true
|
|
687
|
+
return Boolean(params) && typeof params === 'object'
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function rpcProtocolError(type: 'invalid_request' | 'parse') {
|
|
691
|
+
return {
|
|
692
|
+
error:
|
|
693
|
+
type === 'parse'
|
|
694
|
+
? { code: RpcResponse.ParseError.code, message: 'Parse error' }
|
|
695
|
+
: { code: RpcResponse.InvalidRequestError.code, message: 'Invalid Request' },
|
|
696
|
+
id: null,
|
|
697
|
+
jsonrpc: '2.0',
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
666
701
|
function defaultGetClient(options: { apiKey?: string | undefined }) {
|
|
667
702
|
const clients = new Map<number, Client>()
|
|
668
703
|
for (const chain of defaultChains) {
|
|
@@ -671,7 +671,7 @@ describe('require', () => {
|
|
|
671
671
|
headers: { 'tempo-api-key': sandboxToken },
|
|
672
672
|
})
|
|
673
673
|
expect(response.status).toBe(200)
|
|
674
|
-
// The public ceiling (60), not the API-key default (
|
|
674
|
+
// The public ceiling (60), not the API-key default (10,000).
|
|
675
675
|
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"60"`)
|
|
676
676
|
})
|
|
677
677
|
|
|
@@ -684,8 +684,8 @@ describe('require', () => {
|
|
|
684
684
|
headers: { 'tempo-api-key': sandboxToken },
|
|
685
685
|
})
|
|
686
686
|
expect(response.status).toBe(200)
|
|
687
|
-
// The API-key default (
|
|
688
|
-
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"
|
|
687
|
+
// The API-key default (10,000), not the public ceiling (60).
|
|
688
|
+
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"10000"`)
|
|
689
689
|
})
|
|
690
690
|
|
|
691
691
|
test('throttles a sandbox key to the public quota when billing is unknown', async () => {
|
package/src/internal/Auth.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { createMiddleware } from 'hono/factory'
|
|
|
6
6
|
import { matchedRoutes } from 'hono/route'
|
|
7
7
|
import type { MergePath, RouterRoute, Schema as core_Schema } from 'hono/types'
|
|
8
8
|
import { findTargetHandler } from 'hono/utils/handler'
|
|
9
|
-
import { decodeJwt } from 'jose'
|
|
10
9
|
import { Challenge, Credential, type Method } from 'mppx'
|
|
11
10
|
import { Mppx, tempo } from 'mppx/hono'
|
|
12
11
|
import { Addresses } from 'viem/tempo'
|
|
@@ -17,7 +16,6 @@ import * as ApiKey from '../ApiKey.js'
|
|
|
17
16
|
import * as ApiKeys from '../ApiKeys.js'
|
|
18
17
|
import * as Db from '../db/Db.js'
|
|
19
18
|
import type * as Store from './Store.js'
|
|
20
|
-
import * as Invitations from '../db/tables/invitations.js'
|
|
21
19
|
import * as Memberships from '../db/tables/memberships.js'
|
|
22
20
|
import * as Metadata from '../apps/metadata.js'
|
|
23
21
|
import * as OpenApi from './OpenApi.js'
|
|
@@ -32,6 +30,7 @@ import * as Viem from './Viem.js'
|
|
|
32
30
|
|
|
33
31
|
const policySymbol = Symbol('tempo-api.auth.policy')
|
|
34
32
|
const mppManagementSymbol = Symbol('tempo-api.auth.mpp-management')
|
|
33
|
+
const defaultApiKeyRateLimit = { perMinute: 10_000 } satisfies RateLimit.Limit
|
|
35
34
|
const defaultMppRateLimit = { perMinute: 100 } satisfies RateLimit.Limit
|
|
36
35
|
|
|
37
36
|
/** Auth context consumed by Tempo API handlers. */
|
|
@@ -346,6 +345,9 @@ export function ensureProject(): MiddlewareHandler {
|
|
|
346
345
|
*/
|
|
347
346
|
export const narrowScope = false as boolean
|
|
348
347
|
|
|
348
|
+
/** Always false at runtime; lets handlers include organization role errors in inferred response unions. */
|
|
349
|
+
export const narrowOrgRole = false as boolean
|
|
350
|
+
|
|
349
351
|
/** Typed org-scope error response for Hono client inference. Never reached at runtime. */
|
|
350
352
|
export function ensureOrgError(c: hono_Context) {
|
|
351
353
|
return Response.error(c, {
|
|
@@ -355,6 +357,15 @@ export function ensureOrgError(c: hono_Context) {
|
|
|
355
357
|
})
|
|
356
358
|
}
|
|
357
359
|
|
|
360
|
+
/** Typed organization-role error response for Hono client inference. Never reached at runtime. */
|
|
361
|
+
export function ensureOrgRoleError(c: hono_Context) {
|
|
362
|
+
return Response.error(c, {
|
|
363
|
+
code: 'forbidden',
|
|
364
|
+
message: 'Insufficient organization role',
|
|
365
|
+
status: 403,
|
|
366
|
+
})
|
|
367
|
+
}
|
|
368
|
+
|
|
358
369
|
/** Typed project-scope error response for Hono client inference. Never reached at runtime. */
|
|
359
370
|
export function ensureProjectError(c: hono_Context) {
|
|
360
371
|
// Nested project routes run the org scope first, so either not-found can surface.
|
|
@@ -764,12 +775,6 @@ export function install(options: install.Options) {
|
|
|
764
775
|
if (!options_session || !kv) return undefined
|
|
765
776
|
const { issuer, origin, requireEmail, ttl } =
|
|
766
777
|
(typeof options_session === 'object' ? options_session.wallet : undefined) ?? {}
|
|
767
|
-
// Case-insensitive exact-match email-domain allowlist for new-user sign-ups.
|
|
768
|
-
const emailAllowlist = (
|
|
769
|
-
typeof options_session === 'object' ? options_session.emailAllowlist : undefined
|
|
770
|
-
)
|
|
771
|
-
?.map((domain) => domain.trim().toLowerCase())
|
|
772
|
-
.filter(Boolean)
|
|
773
778
|
|
|
774
779
|
const handler = Accounts.Handler.auth({
|
|
775
780
|
...(issuer || requireEmail
|
|
@@ -834,38 +839,6 @@ export function install(options: install.Options) {
|
|
|
834
839
|
const policy_session = policy({ public: true, session: true })
|
|
835
840
|
const describe = OpenApi.describeRoute({ hide: true })
|
|
836
841
|
|
|
837
|
-
// Sign-up gate: new addresses need an allowlisted identity email domain
|
|
838
|
-
// or a pending invitation; existing users pass. The claim decodes
|
|
839
|
-
// unverified; the mounted handler verifies the token before any session
|
|
840
|
-
// or user is created, so a forged claim never authenticates.
|
|
841
|
-
const gate_signup = createMiddleware<App.Environment>(async (c, next) => {
|
|
842
|
-
if (!emailAllowlist?.length) return next()
|
|
843
|
-
const { address, idToken } = (await c.req.json()) as z.output<typeof schema.verify.Body>
|
|
844
|
-
const database = Db.get(db)
|
|
845
|
-
const user = await Users.getByAddress(database, address)
|
|
846
|
-
if (!user) {
|
|
847
|
-
const email = (() => {
|
|
848
|
-
if (!idToken) return undefined
|
|
849
|
-
try {
|
|
850
|
-
const { email } = decodeJwt<{ email?: string }>(idToken)
|
|
851
|
-
return typeof email === 'string' ? email.toLowerCase() : undefined
|
|
852
|
-
} catch {
|
|
853
|
-
return undefined
|
|
854
|
-
}
|
|
855
|
-
})()
|
|
856
|
-
const allowed = await (async () => {
|
|
857
|
-
if (!email) return false
|
|
858
|
-
const at = email.lastIndexOf('@')
|
|
859
|
-
if (at > 0 && emailAllowlist.includes(email.slice(at + 1))) return true
|
|
860
|
-
// A pending invitation admits the email regardless of domain.
|
|
861
|
-
return (await Invitations.listByEmail(database, email)).length > 0
|
|
862
|
-
})()
|
|
863
|
-
if (!allowed)
|
|
864
|
-
return c.json({ error: 'sign-ups are restricted to approved email domains or invited emails' }, 403) // prettier-ignore
|
|
865
|
-
}
|
|
866
|
-
return next()
|
|
867
|
-
})
|
|
868
|
-
|
|
869
842
|
const app = new Hono<App.Environment>()
|
|
870
843
|
.use('/v1/auth/siwe', policy_public, describe)
|
|
871
844
|
.use('/v1/auth/siwe/*', policy_public, describe)
|
|
@@ -906,7 +879,6 @@ export function install(options: install.Options) {
|
|
|
906
879
|
code: 'body_invalid',
|
|
907
880
|
message: 'Invalid request body',
|
|
908
881
|
}),
|
|
909
|
-
gate_signup,
|
|
910
882
|
OpenApi.describeRoute({
|
|
911
883
|
description:
|
|
912
884
|
'Verifies the signed challenge and establishes a session. Sets a session cookie by default; pass `returnToken` to receive a bearer token instead.',
|
|
@@ -926,9 +898,6 @@ export function install(options: install.Options) {
|
|
|
926
898
|
},
|
|
927
899
|
400: handlerError('Invalid, expired, or mismatched challenge message; or a required identity token is missing.'), // prettier-ignore
|
|
928
900
|
401: handlerError('Signature or identity verification failed.'),
|
|
929
|
-
...(emailAllowlist?.length
|
|
930
|
-
? { 403: handlerError('Sign-up rejected: the identity email is neither on an allowlisted domain nor pending an invitation.') } // prettier-ignore
|
|
931
|
-
: {}),
|
|
932
901
|
409: handlerError('Challenge nonce already used or unknown.'),
|
|
933
902
|
429: OpenApi.standardError(429, 'Rate limited.'),
|
|
934
903
|
500: OpenApi.standardError(500, 'Internal server error.'),
|
|
@@ -997,8 +966,6 @@ export declare namespace install {
|
|
|
997
966
|
type Session =
|
|
998
967
|
| boolean
|
|
999
968
|
| {
|
|
1000
|
-
/** Restrict new-user sign-ups to verified emails on these domains (case-insensitive exact match); invited emails and existing users sign in unaffected. */
|
|
1001
|
-
emailAllowlist?: readonly string[] | undefined
|
|
1002
969
|
/** SIWE wallet sign-in configuration. */
|
|
1003
970
|
wallet?: Wallet | undefined
|
|
1004
971
|
}
|
|
@@ -1754,7 +1721,8 @@ function resolveApiKeyLimit(options: resolveApiKeyLimit.Options): RateLimit.Limi
|
|
|
1754
1721
|
policy?.rateLimit ?? // 2. route override (protective cap)
|
|
1755
1722
|
apiKey.rateLimits?.[Scope.wildcard] ?? // 3. per-key default
|
|
1756
1723
|
auth.apiKey?.rateLimits?.[scope] ?? // 4. config per-scope
|
|
1757
|
-
auth.apiKey?.rateLimits?.[Scope.wildcard] ??
|
|
1724
|
+
auth.apiKey?.rateLimits?.[Scope.wildcard] ?? // 5. config default
|
|
1725
|
+
defaultApiKeyRateLimit // 6. hardcoded fallback
|
|
1758
1726
|
)
|
|
1759
1727
|
}
|
|
1760
1728
|
|
|
@@ -10,6 +10,7 @@ const baseUsdcRequest = {
|
|
|
10
10
|
|
|
11
11
|
describe('listQuotes', () => {
|
|
12
12
|
test('returns normalized successful provider quotes', async () => {
|
|
13
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
13
14
|
let seen: FundingQuotes.QuoteProbeInput | undefined
|
|
14
15
|
const quotes = await FundingQuotes.listQuotes({
|
|
15
16
|
...baseUsdcRequest,
|
|
@@ -33,30 +34,54 @@ describe('listQuotes', () => {
|
|
|
33
34
|
},
|
|
34
35
|
},
|
|
35
36
|
},
|
|
37
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
36
38
|
})
|
|
37
39
|
|
|
38
40
|
expect(seen?.candidate.id).toBe('base-usdc-tempo-usdce-relay')
|
|
39
41
|
expect(quotes).toHaveLength(1)
|
|
40
42
|
expect(quotes[0]).toMatchObject({
|
|
43
|
+
destinationAmount: {
|
|
44
|
+
baseUnits: '990000',
|
|
45
|
+
currency: 'USD',
|
|
46
|
+
decimals: 6,
|
|
47
|
+
formatted: '0.99',
|
|
48
|
+
},
|
|
49
|
+
destinationAmountMin: {
|
|
50
|
+
baseUnits: '980000',
|
|
51
|
+
currency: 'USD',
|
|
52
|
+
decimals: 6,
|
|
53
|
+
formatted: '0.98',
|
|
54
|
+
},
|
|
41
55
|
id: 'base-usdc-tempo-usdce-relay',
|
|
42
56
|
quality: {
|
|
43
57
|
liquiditySource: 'providerQuote',
|
|
44
58
|
tier: 'liquid',
|
|
45
59
|
},
|
|
46
|
-
quote: {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
quote: { sampledAt: '2026-01-01T00:00:00Z' },
|
|
61
|
+
sourceAmount: {
|
|
62
|
+
baseUnits: '1000000',
|
|
63
|
+
currency: 'USD',
|
|
64
|
+
decimals: 6,
|
|
65
|
+
formatted: '1',
|
|
51
66
|
},
|
|
52
67
|
})
|
|
68
|
+
expect(attempts.map(stableAttempt)).toEqual([{ outcome: 'available', provider: 'relay' }])
|
|
69
|
+
expect(attempts[0]?.durationMs).toEqual(expect.any(Number))
|
|
53
70
|
})
|
|
54
71
|
|
|
55
72
|
test('returns no static candidates when no adapter is configured', async () => {
|
|
56
|
-
|
|
73
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
74
|
+
await expect(
|
|
75
|
+
FundingQuotes.listQuotes({
|
|
76
|
+
...baseUsdcRequest,
|
|
77
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
78
|
+
}),
|
|
79
|
+
).resolves.toEqual([])
|
|
80
|
+
expect(attempts).toEqual([])
|
|
57
81
|
})
|
|
58
82
|
|
|
59
83
|
test('omits provider-declared unavailable quotes', async () => {
|
|
84
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
60
85
|
const quotes = FundingQuotes.listQuotes({
|
|
61
86
|
...baseUsdcRequest,
|
|
62
87
|
adapters: {
|
|
@@ -66,12 +91,15 @@ describe('listQuotes', () => {
|
|
|
66
91
|
},
|
|
67
92
|
},
|
|
68
93
|
},
|
|
94
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
69
95
|
})
|
|
70
96
|
|
|
71
97
|
await expect(quotes).resolves.toEqual([])
|
|
98
|
+
expect(attempts.map(stableAttempt)).toEqual([{ outcome: 'unavailable', provider: 'relay' }])
|
|
72
99
|
})
|
|
73
100
|
|
|
74
101
|
test('rejects provider failures when no quote succeeds', async () => {
|
|
102
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
75
103
|
const quotes = FundingQuotes.listQuotes({
|
|
76
104
|
...baseUsdcRequest,
|
|
77
105
|
adapters: {
|
|
@@ -81,6 +109,7 @@ describe('listQuotes', () => {
|
|
|
81
109
|
},
|
|
82
110
|
},
|
|
83
111
|
},
|
|
112
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
84
113
|
})
|
|
85
114
|
|
|
86
115
|
const cause = await quotes.catch((error: unknown) => error)
|
|
@@ -88,6 +117,31 @@ describe('listQuotes', () => {
|
|
|
88
117
|
failures: [{ cause: expect.any(Error), provider: 'relay' }],
|
|
89
118
|
name: 'FundingQuotes.ProviderQuoteError',
|
|
90
119
|
})
|
|
120
|
+
expect(attempts.map(stableAttempt)).toEqual([
|
|
121
|
+
{ cause: expect.any(Error), outcome: 'failed', provider: 'relay' },
|
|
122
|
+
])
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('records thin quotes separately from available quotes', async () => {
|
|
126
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
127
|
+
const quotes = await FundingQuotes.listQuotes({
|
|
128
|
+
...baseUsdcRequest,
|
|
129
|
+
adapters: {
|
|
130
|
+
relay: {
|
|
131
|
+
async probeQuote() {
|
|
132
|
+
return {
|
|
133
|
+
outputAmount: '990000',
|
|
134
|
+
sampledAt: '2026-01-01T00:00:00Z',
|
|
135
|
+
status: 'thin',
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
expect(quotes).toHaveLength(1)
|
|
144
|
+
expect(attempts.map(stableAttempt)).toEqual([{ outcome: 'thin', provider: 'relay' }])
|
|
91
145
|
})
|
|
92
146
|
|
|
93
147
|
test('rejects successful provider responses without output amounts', async () => {
|
|
@@ -108,6 +162,7 @@ describe('listQuotes', () => {
|
|
|
108
162
|
})
|
|
109
163
|
|
|
110
164
|
test('aborts providers that exceed the quote deadline', async () => {
|
|
165
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
111
166
|
let aborted = false
|
|
112
167
|
const quotes = FundingQuotes.listQuotes({
|
|
113
168
|
...baseUsdcRequest,
|
|
@@ -122,12 +177,20 @@ describe('listQuotes', () => {
|
|
|
122
177
|
},
|
|
123
178
|
},
|
|
124
179
|
},
|
|
180
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
125
181
|
})
|
|
126
182
|
|
|
127
183
|
await expect(quotes).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
128
184
|
`[FundingQuotes.ProviderQuoteError]`,
|
|
129
185
|
)
|
|
130
186
|
expect(aborted).toBe(true)
|
|
187
|
+
expect(attempts.map(stableAttempt)).toEqual([
|
|
188
|
+
{
|
|
189
|
+
cause: expect.any(FundingQuotes.ProviderAdapterTimeoutError),
|
|
190
|
+
outcome: 'failed',
|
|
191
|
+
provider: 'relay',
|
|
192
|
+
},
|
|
193
|
+
])
|
|
131
194
|
})
|
|
132
195
|
|
|
133
196
|
test('passes cache policy through to providers', async () => {
|
|
@@ -149,6 +212,7 @@ describe('listQuotes', () => {
|
|
|
149
212
|
})
|
|
150
213
|
|
|
151
214
|
test('returns successful quotes when another provider fails', async () => {
|
|
215
|
+
const attempts: FundingQuotes.ProviderAttempt[] = []
|
|
152
216
|
const quotes = await FundingQuotes.listQuotes({
|
|
153
217
|
...baseUsdcRequest,
|
|
154
218
|
adapters: {
|
|
@@ -167,14 +231,63 @@ describe('listQuotes', () => {
|
|
|
167
231
|
},
|
|
168
232
|
},
|
|
169
233
|
},
|
|
234
|
+
onAttempt: (attempt) => attempts.push(attempt),
|
|
170
235
|
provider: undefined,
|
|
171
236
|
})
|
|
172
237
|
|
|
173
238
|
expect(quotes).toHaveLength(1)
|
|
174
239
|
expect(quotes[0]?.provider.id).toBe('relay')
|
|
240
|
+
expect(attempts.map(stableAttempt)).toEqual([
|
|
241
|
+
{ cause: expect.any(Error), outcome: 'failed', provider: 'across' },
|
|
242
|
+
{ outcome: 'available', provider: 'relay' },
|
|
243
|
+
])
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
test('does not let attempt observers change quote outcomes', async () => {
|
|
247
|
+
const adapters = {
|
|
248
|
+
relay: {
|
|
249
|
+
async probeQuote() {
|
|
250
|
+
return {
|
|
251
|
+
outputAmount: '990000',
|
|
252
|
+
sampledAt: '2026-01-01T00:00:00Z',
|
|
253
|
+
status: 'available' as const,
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
}
|
|
258
|
+
await expect(
|
|
259
|
+
FundingQuotes.listQuotes({
|
|
260
|
+
...baseUsdcRequest,
|
|
261
|
+
adapters,
|
|
262
|
+
onAttempt() {
|
|
263
|
+
throw new Error('observer failed')
|
|
264
|
+
},
|
|
265
|
+
}),
|
|
266
|
+
).resolves.toHaveLength(1)
|
|
267
|
+
|
|
268
|
+
await expect(
|
|
269
|
+
FundingQuotes.listQuotes({
|
|
270
|
+
...baseUsdcRequest,
|
|
271
|
+
adapters: {
|
|
272
|
+
relay: {
|
|
273
|
+
async probeQuote() {
|
|
274
|
+
throw new Error('provider failed')
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
onAttempt() {
|
|
279
|
+
throw new Error('observer failed')
|
|
280
|
+
},
|
|
281
|
+
}),
|
|
282
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(`[FundingQuotes.ProviderQuoteError]`)
|
|
175
283
|
})
|
|
176
284
|
})
|
|
177
285
|
|
|
286
|
+
function stableAttempt(attempt: FundingQuotes.ProviderAttempt) {
|
|
287
|
+
const { durationMs: _durationMs, ...rest } = attempt
|
|
288
|
+
return rest
|
|
289
|
+
}
|
|
290
|
+
|
|
178
291
|
describe('listChains', () => {
|
|
179
292
|
test('returns only chain and token inputs with quote inventory', () => {
|
|
180
293
|
expect(FundingQuotes.listChains().map((chain) => chain.id)).toEqual([
|
|
@@ -261,6 +374,41 @@ describe('listQuoteCandidates', () => {
|
|
|
261
374
|
'ethereum-usdt-tempo-usdt0-squid',
|
|
262
375
|
])
|
|
263
376
|
})
|
|
377
|
+
|
|
378
|
+
test('selects proven Symbiosis stablecoin corridors', () => {
|
|
379
|
+
const candidates = [
|
|
380
|
+
FundingQuotes.listQuoteCandidates({
|
|
381
|
+
destinationToken: 'USDC.e',
|
|
382
|
+
provider: 'symbiosis',
|
|
383
|
+
sourceAmount: '1000000',
|
|
384
|
+
sourceAmountUnits: 'baseUnits',
|
|
385
|
+
sourceChain: 'base',
|
|
386
|
+
sourceToken: 'USDC',
|
|
387
|
+
})[0],
|
|
388
|
+
FundingQuotes.listQuoteCandidates({
|
|
389
|
+
destinationToken: 'USDT0',
|
|
390
|
+
provider: 'symbiosis',
|
|
391
|
+
sourceAmount: '1000000',
|
|
392
|
+
sourceAmountUnits: 'baseUnits',
|
|
393
|
+
sourceChain: 'ethereum',
|
|
394
|
+
sourceToken: 'USDT',
|
|
395
|
+
})[0],
|
|
396
|
+
FundingQuotes.listQuoteCandidates({
|
|
397
|
+
destinationToken: 'USDT0',
|
|
398
|
+
provider: 'symbiosis',
|
|
399
|
+
sourceAmount: '1000000',
|
|
400
|
+
sourceAmountUnits: 'baseUnits',
|
|
401
|
+
sourceChain: 'tron',
|
|
402
|
+
sourceToken: 'USDT',
|
|
403
|
+
})[0],
|
|
404
|
+
]
|
|
405
|
+
|
|
406
|
+
expect(candidates.map((candidate) => candidate?.id)).toEqual([
|
|
407
|
+
'base-usdc-tempo-usdce-symbiosis',
|
|
408
|
+
'ethereum-usdt-tempo-usdt0-symbiosis',
|
|
409
|
+
'tron-usdt-tempo-usdt0-symbiosis',
|
|
410
|
+
])
|
|
411
|
+
})
|
|
264
412
|
})
|
|
265
413
|
|
|
266
414
|
describe('listProviders', () => {
|
|
@@ -295,6 +443,13 @@ describe('listProviders', () => {
|
|
|
295
443
|
"requiresApiKey": true,
|
|
296
444
|
"status": "unconfigured",
|
|
297
445
|
},
|
|
446
|
+
{
|
|
447
|
+
"id": "symbiosis",
|
|
448
|
+
"kind": "crossChainDex",
|
|
449
|
+
"name": "Symbiosis",
|
|
450
|
+
"requiresApiKey": false,
|
|
451
|
+
"status": "unconfigured",
|
|
452
|
+
},
|
|
298
453
|
]
|
|
299
454
|
`)
|
|
300
455
|
})
|