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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Value as core_Value } from 'ox'
|
|
2
|
+
|
|
3
|
+
import * as Ttl from '../../internal/Ttl.js'
|
|
4
|
+
|
|
5
|
+
/** A pluggable fiat FX rate oracle consumed by the valuation endpoint. */
|
|
6
|
+
export type Oracle = {
|
|
7
|
+
/** Oracle identifier, surfaced as the valuation's `pricing.source` (e.g. `ecb`). */
|
|
8
|
+
name: string
|
|
9
|
+
/** Fetches the oracle's current rate set. */
|
|
10
|
+
rates: () => Promise<RateSet>
|
|
11
|
+
/** Cache lifetime for a fetched rate set, in milliseconds. */
|
|
12
|
+
ttl: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** One oracle-published set of exchange rates quoted against a base currency. */
|
|
16
|
+
export type RateSet = {
|
|
17
|
+
/** Publication date of the rate set as an ISO 8601 timestamp. */
|
|
18
|
+
asOf: string
|
|
19
|
+
/** Currency the rates are quoted against (e.g. `EUR`). */
|
|
20
|
+
base: string
|
|
21
|
+
/** Currency code to units of that currency per one `base` unit, as decimal strings. */
|
|
22
|
+
rates: Record<string, string>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Fixed-point scale (decimal places) of cross rates returned by {@link rate}. */
|
|
26
|
+
export const precision = 18
|
|
27
|
+
|
|
28
|
+
/** Canonical ECB daily reference-rate feed (public, no key required). */
|
|
29
|
+
export const ecbUrl = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Normalizes an oracle definition into an {@link Oracle}: applies the default
|
|
33
|
+
* `ttl` and rethrows `rates()` failures as {@link RatesError}.
|
|
34
|
+
*/
|
|
35
|
+
export function from(oracle: from.Value): Oracle {
|
|
36
|
+
return {
|
|
37
|
+
name: oracle.name,
|
|
38
|
+
rates: async () => {
|
|
39
|
+
try {
|
|
40
|
+
return await oracle.rates()
|
|
41
|
+
} catch (cause) {
|
|
42
|
+
throw new RatesError(oracle.name, { cause })
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
ttl: oracle.ttl ?? Ttl.hours(1),
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export declare namespace from {
|
|
50
|
+
/** Oracle definition accepted by {@link from}. */
|
|
51
|
+
type Value = Pick<Oracle, 'name' | 'rates'> & {
|
|
52
|
+
/** Cache lifetime for a fetched rate set, in milliseconds. @default `Ttl.hours(1)` */
|
|
53
|
+
ttl?: number | undefined
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* European Central Bank euro reference rates: one EUR-based set covering ~30
|
|
59
|
+
* currencies, published once per working day.
|
|
60
|
+
*/
|
|
61
|
+
export function ecb(options: ecb.Options = {}): Oracle {
|
|
62
|
+
const { fetch = globalThis.fetch, url = ecbUrl } = options
|
|
63
|
+
return from({
|
|
64
|
+
name: 'ecb',
|
|
65
|
+
rates: async () => {
|
|
66
|
+
const response = await fetch(url, {
|
|
67
|
+
headers: { accept: 'application/xml' },
|
|
68
|
+
signal: AbortSignal.timeout(10_000),
|
|
69
|
+
})
|
|
70
|
+
if (!response.ok) throw new ResponseError(response.status)
|
|
71
|
+
const text = await response.text()
|
|
72
|
+
|
|
73
|
+
// The daily file is a flat, stable XML shape; extract the `Cube`
|
|
74
|
+
// attributes directly rather than pulling in an XML parser.
|
|
75
|
+
const asOf = text.match(/<Cube time=['"](\d{4}-\d{2}-\d{2})['"]/)?.[1]
|
|
76
|
+
const rates: Record<string, string> = {}
|
|
77
|
+
for (const match of text.matchAll(
|
|
78
|
+
/<Cube currency=['"]([A-Z]{3})['"] rate=['"]([^'"]*)['"]/g,
|
|
79
|
+
)) {
|
|
80
|
+
const [, code, value] = match
|
|
81
|
+
if (
|
|
82
|
+
!code ||
|
|
83
|
+
!value ||
|
|
84
|
+
!/^\d+(?:\.\d+)?$/.test(value) ||
|
|
85
|
+
core_Value.from(value, precision) <= 0n
|
|
86
|
+
)
|
|
87
|
+
throw new ParseError()
|
|
88
|
+
rates[code] = value
|
|
89
|
+
}
|
|
90
|
+
if (!asOf || rates['USD'] === undefined) throw new ParseError()
|
|
91
|
+
return { asOf: `${asOf}T00:00:00.000Z`, base: 'EUR', rates }
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export declare namespace ecb {
|
|
97
|
+
/** Options for the ECB oracle. */
|
|
98
|
+
type Options = {
|
|
99
|
+
/** Fetch implementation used to retrieve the feed. @default `globalThis.fetch` */
|
|
100
|
+
fetch?: typeof globalThis.fetch | undefined
|
|
101
|
+
/** Feed URL. @default {@link ecbUrl} */
|
|
102
|
+
url?: string | undefined
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Derives the cross rate from one currency to another through the set's base,
|
|
108
|
+
* scaled to {@link precision} decimal places. Returns `undefined` when the set
|
|
109
|
+
* prices neither leg of a currency.
|
|
110
|
+
*/
|
|
111
|
+
export function rate(set: RateSet, options: rate.Options): bigint | undefined {
|
|
112
|
+
const scaled = (code: string) => {
|
|
113
|
+
if (code === set.base) return 10n ** BigInt(precision)
|
|
114
|
+
const value = set.rates[code]
|
|
115
|
+
return value === undefined ? undefined : core_Value.from(value, precision)
|
|
116
|
+
}
|
|
117
|
+
const source = scaled(options.from)
|
|
118
|
+
const target = scaled(options.to)
|
|
119
|
+
if (source === undefined || target === undefined || source === 0n) return undefined
|
|
120
|
+
return (target * 10n ** BigInt(precision)) / source
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export declare namespace rate {
|
|
124
|
+
/** Options for deriving a cross rate. */
|
|
125
|
+
type Options = {
|
|
126
|
+
/** Currency code to convert from. */
|
|
127
|
+
from: string
|
|
128
|
+
/** Currency code to convert to. */
|
|
129
|
+
to: string
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Thrown when an oracle fails to produce its rate set. */
|
|
134
|
+
export class RatesError extends Error {
|
|
135
|
+
override name = 'FxOracle.RatesError'
|
|
136
|
+
constructor(oracle: string, options: { cause: unknown }) {
|
|
137
|
+
super(`FX oracle "${oracle}" failed to produce rates`, options)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
class ParseError extends Error {
|
|
142
|
+
override name = 'FxOracle.ParseError'
|
|
143
|
+
constructor() {
|
|
144
|
+
super('Rate feed returned an unrecognized payload')
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
class ResponseError extends Error {
|
|
149
|
+
override name = 'FxOracle.ResponseError'
|
|
150
|
+
constructor(status: number) {
|
|
151
|
+
super(`Rate feed request failed with status ${status}`)
|
|
152
|
+
}
|
|
153
|
+
}
|
package/src/apps/data/index.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import { Address, Hex } from 'ox'
|
|
1
|
+
import { Address, Hex, Value as core_Value } from 'ox'
|
|
2
|
+
import { FxOracle } from 'tapimo/apps'
|
|
2
3
|
import { encodeAbiParameters, encodeEventTopics } from 'viem'
|
|
3
4
|
import { Abis } from 'viem/tempo'
|
|
4
5
|
|
|
5
6
|
import * as TestApp from '../../../../test/App.js'
|
|
6
7
|
import * as Runtime from '../../../../test/runtime.js'
|
|
8
|
+
import * as Cursor from '../../../internal/Cursor.js'
|
|
7
9
|
import * as Store from '../../../internal/Store.js'
|
|
8
10
|
import * as Activities from './activities.js'
|
|
9
11
|
|
|
12
|
+
// Deterministic EUR-based rate set so conversion math is exact in assertions.
|
|
13
|
+
const fixed = FxOracle.from({
|
|
14
|
+
name: 'fixed',
|
|
15
|
+
rates: async () => ({
|
|
16
|
+
asOf: '2026-01-01T00:00:00.000Z',
|
|
17
|
+
base: 'EUR',
|
|
18
|
+
rates: { AUD: '1.6', USD: '1.0' },
|
|
19
|
+
}),
|
|
20
|
+
})
|
|
21
|
+
|
|
10
22
|
/**
|
|
11
23
|
* Real Tempo (Moderato) accounts, each exercising specific activity types.
|
|
12
24
|
* Discovered by scanning indexed `logs` for the event each type classifies
|
|
@@ -102,6 +114,32 @@ function find(items: readonly Activities.Entry[], type: string): Activities.Entr
|
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
describe('GET /addresses/:address/activities', () => {
|
|
117
|
+
test('parses granular token includes for both activity endpoints', () => {
|
|
118
|
+
expect(
|
|
119
|
+
Activities.schema.getAddressActivities.Query.parse({
|
|
120
|
+
include: 'token.logoUri,token.verified',
|
|
121
|
+
}).include,
|
|
122
|
+
).toMatchInlineSnapshot(`
|
|
123
|
+
[
|
|
124
|
+
"token.logoUri",
|
|
125
|
+
"token.verified",
|
|
126
|
+
]
|
|
127
|
+
`)
|
|
128
|
+
expect(
|
|
129
|
+
Activities.schema.getTransactionActivities.Query.parse({
|
|
130
|
+
include: 'token.logoUri,token.verified',
|
|
131
|
+
}).include,
|
|
132
|
+
).toMatchInlineSnapshot(`
|
|
133
|
+
[
|
|
134
|
+
"token.logoUri",
|
|
135
|
+
"token.verified",
|
|
136
|
+
]
|
|
137
|
+
`)
|
|
138
|
+
expect(
|
|
139
|
+
Activities.schema.getAddressActivities.Query.safeParse({ include: 'token' }).success,
|
|
140
|
+
).toBe(false)
|
|
141
|
+
})
|
|
142
|
+
|
|
105
143
|
test('returns a newest-first, schema-valid feed with timing', async () => {
|
|
106
144
|
const response = await request(accounts.keychain, { limit: '10' })
|
|
107
145
|
expect(response.status).toBe(200)
|
|
@@ -130,7 +168,31 @@ describe('GET /addresses/:address/activities', () => {
|
|
|
130
168
|
expect(transfer.data.transactionHash).toMatch(/^0x[0-9a-f]{64}$/)
|
|
131
169
|
expect(typeof transfer.data.blockNumber).toBe('number')
|
|
132
170
|
expect(transfer.data.sourceToken.address).toMatch(/^0x[0-9a-f]{40}$/)
|
|
133
|
-
expect(transfer.data.sourceToken
|
|
171
|
+
expect(transfer.data.sourceToken).not.toHaveProperty('amount')
|
|
172
|
+
expect(typeof transfer.data.sourceToken.currency).toBe('string')
|
|
173
|
+
expect(typeof transfer.data.sourceToken.decimals).toBe('number')
|
|
174
|
+
expect(typeof transfer.data.sourceToken.name).toBe('string')
|
|
175
|
+
expect(typeof transfer.data.sourceToken.symbol).toBe('string')
|
|
176
|
+
expect(transfer.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
|
|
177
|
+
expect(transfer.data.sourceAmount.currency).toBe(transfer.data.sourceToken.currency)
|
|
178
|
+
expect(transfer.data.sourceAmount.decimals).toBe(transfer.data.sourceToken.decimals)
|
|
179
|
+
expect(transfer.data.sourceAmount.formatted).toMatch(/^\d+(\.\d+)?$/)
|
|
180
|
+
expect(transfer.data.sourceToken.logoUri).toBeUndefined()
|
|
181
|
+
expect(transfer.data.sourceToken.verified).toBeUndefined()
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test('includes requested token verification', async () => {
|
|
185
|
+
const transfer = find(
|
|
186
|
+
(
|
|
187
|
+
await activities(accounts.creator, {
|
|
188
|
+
include: 'token.logoUri,token.verified',
|
|
189
|
+
})
|
|
190
|
+
).data,
|
|
191
|
+
'transfer',
|
|
192
|
+
)
|
|
193
|
+
expect(transfer?.type).toBe('transfer')
|
|
194
|
+
if (transfer?.type !== 'transfer') return
|
|
195
|
+
expect(typeof transfer.data.sourceToken.verified).toBe('boolean')
|
|
134
196
|
})
|
|
135
197
|
|
|
136
198
|
test.skipIf(runtime.mode === 'localnet')('swap data carries both sides of the swap', async () => {
|
|
@@ -139,8 +201,30 @@ describe('GET /addresses/:address/activities', () => {
|
|
|
139
201
|
if (swap?.type !== 'swap') return
|
|
140
202
|
expect(swap.data.sourceToken.address).toMatch(/^0x[0-9a-f]{40}$/)
|
|
141
203
|
expect(swap.data.destinationToken.address).toMatch(/^0x[0-9a-f]{40}$/)
|
|
204
|
+
expect(swap.data.sourceToken).not.toHaveProperty('amount')
|
|
205
|
+
expect(swap.data.destinationToken).not.toHaveProperty('amount')
|
|
206
|
+
expect(swap.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
|
|
207
|
+
expect(swap.data.destinationAmount.baseUnits).toMatch(/^\d+$/)
|
|
142
208
|
})
|
|
143
209
|
|
|
210
|
+
test.skipIf(runtime.mode === 'localnet')(
|
|
211
|
+
'adds a structured refund amount when a session closes with a refund',
|
|
212
|
+
async () => {
|
|
213
|
+
const session = find((await activities(accounts.channel)).data, 'session-closed')
|
|
214
|
+
expect(session?.type).toBe('session-closed')
|
|
215
|
+
if (session?.type !== 'session-closed') return
|
|
216
|
+
if (!session.data.refund) {
|
|
217
|
+
expect(session.data.refundAmount).toBeUndefined()
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
expect(session.data.refundAmount).toBeDefined()
|
|
221
|
+
expect(session.data.refund).not.toHaveProperty('amount')
|
|
222
|
+
expect(session.data.refundAmount?.baseUnits).toMatch(/^\d+$/)
|
|
223
|
+
expect(session.data.refundAmount?.currency).toBe(session.data.refund.currency)
|
|
224
|
+
expect(session.data.refundAmount?.decimals).toBe(session.data.refund.decimals)
|
|
225
|
+
},
|
|
226
|
+
)
|
|
227
|
+
|
|
144
228
|
test.skipIf(runtime.mode !== 'localnet')(
|
|
145
229
|
'surfaces a cross-token transfer as outgoing in the sender feed',
|
|
146
230
|
async () => {
|
|
@@ -162,6 +246,10 @@ describe('GET /addresses/:address/activities', () => {
|
|
|
162
246
|
expect(transfer.data.recipient).toBe(crossToken.recipient)
|
|
163
247
|
expect(transfer.data.sourceToken.address).toBe(crossToken.sourceToken)
|
|
164
248
|
expect(transfer.data.destinationToken?.address).toBe(crossToken.destinationToken)
|
|
249
|
+
expect(transfer.data.sourceToken).not.toHaveProperty('amount')
|
|
250
|
+
expect(transfer.data.destinationToken).not.toHaveProperty('amount')
|
|
251
|
+
expect(transfer.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
|
|
252
|
+
expect(transfer.data.destinationAmount?.baseUnits).toMatch(/^\d+$/)
|
|
165
253
|
},
|
|
166
254
|
)
|
|
167
255
|
|
|
@@ -202,6 +290,39 @@ describe('GET /addresses/:address/activities', () => {
|
|
|
202
290
|
},
|
|
203
291
|
)
|
|
204
292
|
|
|
293
|
+
test.skipIf(runtime.mode !== 'localnet')('values curated activity amounts', async () => {
|
|
294
|
+
const db = TestApp.database()
|
|
295
|
+
await TestApp.verifiedSeed(db, runtime.chainId)
|
|
296
|
+
const client = TestApp.client({ db, fx: { oracle: fixed } })
|
|
297
|
+
const hash = runtime.fixtures!.faucetTransactionHashes[0]!
|
|
298
|
+
|
|
299
|
+
const response = await client.v1.transactions[':transactionHash'].activities.$get(
|
|
300
|
+
{ param: { transactionHash: hash }, query: { denomination: 'AUD' } },
|
|
301
|
+
TestApp.auth,
|
|
302
|
+
)
|
|
303
|
+
const body = await TestApp.json(response, Activities.schema.getTransactionActivities.Response)
|
|
304
|
+
expect(response.status).toBe(200)
|
|
305
|
+
|
|
306
|
+
// The faucet transaction moves curated USD tokens; their amounts value at
|
|
307
|
+
// the fixed 1.6 USD -> AUD rate.
|
|
308
|
+
const amounts = body.data.flatMap((item) =>
|
|
309
|
+
item.type === 'transfer' || item.type === 'mint' ? [item.data.sourceAmount] : [],
|
|
310
|
+
)
|
|
311
|
+
expect(amounts.length).toBeGreaterThan(0)
|
|
312
|
+
for (const amount of amounts)
|
|
313
|
+
expect(amount.valuation).toEqual({
|
|
314
|
+
amount: core_Value.format((BigInt(amount.baseUnits) * 16n) / 10n, 6),
|
|
315
|
+
currency: 'AUD',
|
|
316
|
+
})
|
|
317
|
+
expect(body.meta?.pricing).toMatchInlineSnapshot(`
|
|
318
|
+
{
|
|
319
|
+
"asOf": "2026-01-01T00:00:00.000Z",
|
|
320
|
+
"basis": "nominal",
|
|
321
|
+
"source": "fixed",
|
|
322
|
+
}
|
|
323
|
+
`)
|
|
324
|
+
})
|
|
325
|
+
|
|
205
326
|
test('returns every item at the root by default (no group entries)', async () => {
|
|
206
327
|
const body = await activities(accounts.channel)
|
|
207
328
|
expect(body.data.every((entry) => entry.type !== 'group')).toBe(true)
|
|
@@ -210,9 +331,34 @@ describe('GET /addresses/:address/activities', () => {
|
|
|
210
331
|
test('paginates with an opaque cursor', async () => {
|
|
211
332
|
const first = await activities(accounts.keychain, { limit: '5' })
|
|
212
333
|
if (!first.nextCursor) return
|
|
213
|
-
const
|
|
334
|
+
const response = await request(accounts.keychain, { limit: '5', cursor: first.nextCursor })
|
|
335
|
+
expect(response.headers.get('cache-control')).toMatchInlineSnapshot(
|
|
336
|
+
`"private, max-age=60, stale-while-revalidate=300"`,
|
|
337
|
+
)
|
|
338
|
+
const second = await TestApp.json(response, Activities.schema.getAddressActivities.Response)
|
|
214
339
|
expect(Array.isArray(second.data)).toBe(true)
|
|
215
340
|
})
|
|
341
|
+
|
|
342
|
+
test('validates denominations on empty feeds', async () => {
|
|
343
|
+
const client = TestApp.client({ fx: { oracle: fixed } })
|
|
344
|
+
const cursor = Cursor.encode([0, 0])
|
|
345
|
+
const emptyResponse = await client.v1.addresses[':address'].activities.$get(
|
|
346
|
+
{ param: { address: accounts.keychain }, query: { cursor, limit: '5' } },
|
|
347
|
+
TestApp.auth,
|
|
348
|
+
)
|
|
349
|
+
const empty = await TestApp.json(emptyResponse, Activities.schema.getAddressActivities.Response)
|
|
350
|
+
expect(emptyResponse.status).toBe(200)
|
|
351
|
+
expect(empty.data).toMatchInlineSnapshot(`[]`)
|
|
352
|
+
|
|
353
|
+
const response = await client.v1.addresses[':address'].activities.$get(
|
|
354
|
+
{
|
|
355
|
+
param: { address: accounts.keychain },
|
|
356
|
+
query: { cursor, denomination: 'JPY', limit: '5' },
|
|
357
|
+
},
|
|
358
|
+
TestApp.auth,
|
|
359
|
+
)
|
|
360
|
+
expect(response.status).toBe(400)
|
|
361
|
+
})
|
|
216
362
|
})
|
|
217
363
|
|
|
218
364
|
/** Resolves a real transaction hash from an address's (non-grouped) activity feed. */
|
|
@@ -239,6 +385,9 @@ describe('GET /transactions/:transactionHash/activities', () => {
|
|
|
239
385
|
|
|
240
386
|
const response = await transactionActivitiesRequest(transactionHash)
|
|
241
387
|
expect(response.status).toBe(200)
|
|
388
|
+
expect(response.headers.get('cache-control')).toMatchInlineSnapshot(
|
|
389
|
+
`"private, max-age=60, stale-while-revalidate=300"`,
|
|
390
|
+
)
|
|
242
391
|
expect(response.headers.get('server-timing')?.includes('transaction_activities;dur=')).toBe(
|
|
243
392
|
true,
|
|
244
393
|
)
|
|
@@ -262,6 +411,27 @@ describe('GET /transactions/:transactionHash/activities', () => {
|
|
|
262
411
|
)
|
|
263
412
|
})
|
|
264
413
|
|
|
414
|
+
test('supports requested token verification', async () => {
|
|
415
|
+
const address = await activities(accounts.creator)
|
|
416
|
+
const entry = address.data.find((item) => item.type !== 'group' && 'sourceToken' in item.data)
|
|
417
|
+
expect(entry?.type).not.toBe('group')
|
|
418
|
+
if (!entry || entry.type === 'group') return
|
|
419
|
+
|
|
420
|
+
const body = await TestApp.json(
|
|
421
|
+
await transactionActivitiesRequest(entry.transactionHash, {
|
|
422
|
+
include: 'token.verified',
|
|
423
|
+
}),
|
|
424
|
+
Activities.schema.getTransactionActivities.Response,
|
|
425
|
+
)
|
|
426
|
+
const item = body.data.find((item) => 'sourceToken' in item.data)
|
|
427
|
+
expect(item).toBeDefined()
|
|
428
|
+
if (!item || !('sourceToken' in item.data) || !item.data.sourceToken || !item.data.sourceAmount)
|
|
429
|
+
return
|
|
430
|
+
expect(typeof item.data.sourceToken.verified).toBe('boolean')
|
|
431
|
+
expect(item.data.sourceToken).not.toHaveProperty('amount')
|
|
432
|
+
expect(item.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
|
|
433
|
+
})
|
|
434
|
+
|
|
265
435
|
test.skipIf(runtime.mode !== 'localnet')(
|
|
266
436
|
'classifies a seeded cross-token transfer with both source and destination tokens',
|
|
267
437
|
async () => {
|
|
@@ -283,6 +453,10 @@ describe('GET /transactions/:transactionHash/activities', () => {
|
|
|
283
453
|
expect(transfer.data.recipient).toBe(crossToken.recipient)
|
|
284
454
|
expect(transfer.data.sourceToken.address).toBe(crossToken.sourceToken)
|
|
285
455
|
expect(transfer.data.destinationToken?.address).toBe(crossToken.destinationToken)
|
|
456
|
+
expect(transfer.data.sourceToken).not.toHaveProperty('amount')
|
|
457
|
+
expect(transfer.data.destinationToken).not.toHaveProperty('amount')
|
|
458
|
+
expect(transfer.data.sourceAmount.baseUnits).toMatch(/^\d+$/)
|
|
459
|
+
expect(transfer.data.destinationAmount?.baseUnits).toMatch(/^\d+$/)
|
|
286
460
|
},
|
|
287
461
|
)
|
|
288
462
|
|