tapimo 0.6.0 → 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 +8641 -8263
- 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 +112 -11
- package/dist/admin/App.d.ts.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 +2 -2
- package/dist/admin/apps/early-access.d.ts.map +1 -1
- package/dist/admin/apps/early-access.js +5 -5
- package/dist/admin/apps/early-access.js.map +1 -1
- 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/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +95 -87
- 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 +5016 -4985
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.js +2 -15
- package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
- package/dist/apps/data/FxOracle.d.ts +1 -1
- package/dist/apps/data/FxOracle.d.ts.map +1 -1
- package/dist/apps/data/FxOracle.js +1 -1
- package/dist/apps/data/FxOracle.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +27 -27
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +21 -1
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +58 -58
- package/dist/apps/data/routes/blocks.d.ts +39 -39
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/exchanges.d.ts +113 -113
- package/dist/apps/data/routes/fee-amm.d.ts +105 -91
- 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 +72 -34
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +34 -26
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/receipts.d.ts +6 -6
- package/dist/apps/data/routes/rpc.d.ts +31 -31
- package/dist/apps/data/routes/tokens.d.ts +2 -2
- package/dist/apps/data/routes/tokens.js +1 -1
- package/dist/apps/data/routes/transactions.d.ts +4 -4
- package/dist/apps/data/routes/transfers.d.ts +99 -88
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +226 -141
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +34 -34
- package/dist/apps/data/routes/valuation.js +3 -3
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/data/routes/webhooks.d.ts +366 -366
- package/dist/apps/index.d.ts +1 -0
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +1 -0
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +460 -523
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +7 -23
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +20 -8
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +106 -151
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +28 -28
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +40 -26
- package/dist/apps/management/routes/faucet.d.ts.map +1 -1
- package/dist/apps/management/routes/faucet.js +33 -18
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +131 -131
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +0 -3
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +6 -8
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +0 -4
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +45 -45
- package/dist/apps/management/routes/orgs.d.ts +94 -94
- 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/usage.d.ts +32 -32
- package/dist/apps/management/routes/verified-token-requests.d.ts +94 -94
- package/dist/apps/management/routes/webhooks.d.ts +1 -1
- 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 +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +27 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +12 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +11 -0
- package/dist/db/Schema.js.map +1 -1
- 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 +1 -12
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/invitations.js +3 -23
- package/dist/db/tables/invitations.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/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 +0 -32
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +3 -51
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/FundingQuotes.d.ts +78 -32
- package/dist/internal/FundingQuotes.d.ts.map +1 -1
- package/dist/internal/FundingQuotes.js +45 -8
- package/dist/internal/FundingQuotes.js.map +1 -1
- package/dist/internal/Log.d.ts +18 -4
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +50 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +15 -0
- package/dist/internal/MetricSink.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/Viem.d.ts +1 -1
- package/package.json +7 -2
- package/src/App.test.ts +9 -4
- package/src/App.ts +14 -2
- package/src/Client.test-d.ts +109 -28
- package/src/Scope.ts +5 -0
- package/src/admin/App.test.ts +4 -0
- package/src/admin/apps/early-access.ts +6 -5
- 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/ui/src/lib/organizations.test.ts +81 -1
- package/src/admin/ui/src/lib/organizations.ts +92 -0
- package/src/admin/ui/src/routes/api-keys.tsx +1 -1
- package/src/admin/ui/src/routes/early-access.tsx +8 -3
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +103 -0
- package/src/admin/ui.generated.ts +95 -109
- 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/FundingQuoteProviders.test.ts +0 -5
- package/src/apps/data/FundingQuoteProviders.ts +2 -29
- package/src/apps/data/FxOracle.test.ts +2 -2
- package/src/apps/data/FxOracle.ts +2 -2
- package/src/apps/data/routes/activities.test.ts +6 -2
- package/src/apps/data/routes/activities.ts +39 -1
- package/src/apps/data/routes/balances.test.ts +6 -2
- package/src/apps/data/routes/exchanges.test.ts +7 -3
- 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 +29 -8
- package/src/apps/data/routes/funding.ts +42 -48
- package/src/apps/data/routes/receipts.test.ts +6 -2
- package/src/apps/data/routes/tokens.ts +1 -1
- package/src/apps/data/routes/transfers.test.ts +203 -35
- package/src/apps/data/routes/transfers.ts +294 -172
- package/src/apps/data/routes/valuation.test.ts +18 -3
- package/src/apps/data/routes/valuation.ts +4 -4
- package/src/apps/index.ts +1 -0
- package/src/apps/management/routes/api-keys.test.ts +2 -75
- package/src/apps/management/routes/api-keys.ts +30 -7
- package/src/apps/management/routes/billing.test.ts +106 -85
- package/src/apps/management/routes/billing.ts +32 -21
- package/src/apps/management/routes/faucet.test.ts +11 -3
- package/src/apps/management/routes/faucet.ts +46 -30
- package/src/apps/management/routes/invitations.test.ts +0 -172
- package/src/apps/management/routes/invitations.ts +0 -3
- package/src/apps/management/routes/me.test.ts +3 -145
- package/src/apps/management/routes/me.ts +0 -6
- 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/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 +2 -2
- package/src/db/Db.ts +30 -0
- package/src/db/Schema.ts +15 -0
- package/src/db/tables/enabledBillingSources.test.ts +303 -0
- package/src/db/tables/enabledBillingSources.ts +118 -0
- package/src/db/tables/invitations.ts +4 -26
- package/src/db/tables/organizations.test.ts +103 -0
- package/src/db/tables/organizations.ts +18 -2
- 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 +3 -63
- package/src/internal/FundingQuotes.test.ts +18 -5
- package/src/internal/FundingQuotes.ts +46 -11
- package/src/internal/Log.test.ts +91 -0
- package/src/internal/Log.ts +69 -5
- package/src/internal/MetricSink.test.ts +55 -0
- package/src/internal/MetricSink.ts +14 -0
- package/src/internal/Response.test.ts +28 -0
- package/src/internal/Response.ts +12 -4
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as Value from './Value.js'
|
|
2
|
+
|
|
1
3
|
/** Tempo mainnet as a CAIP-2 chain reference. */
|
|
2
4
|
const destinationChain = {
|
|
3
5
|
addressFormat: 'evm',
|
|
@@ -27,6 +29,7 @@ const sourceChains = [
|
|
|
27
29
|
{
|
|
28
30
|
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
29
31
|
coingeckoId: 'usd-coin',
|
|
32
|
+
currency: 'USD',
|
|
30
33
|
decimals: 6,
|
|
31
34
|
name: 'USD Coin',
|
|
32
35
|
standard: 'ERC-20',
|
|
@@ -35,6 +38,7 @@ const sourceChains = [
|
|
|
35
38
|
{
|
|
36
39
|
address: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
37
40
|
coingeckoId: 'tether',
|
|
41
|
+
currency: 'USD',
|
|
38
42
|
decimals: 6,
|
|
39
43
|
name: 'Tether USD',
|
|
40
44
|
standard: 'ERC-20',
|
|
@@ -43,6 +47,7 @@ const sourceChains = [
|
|
|
43
47
|
{
|
|
44
48
|
address: '0x6c3ea9036406852006290770bedfcaba0e23a0e8',
|
|
45
49
|
coingeckoId: 'paypal-usd',
|
|
50
|
+
currency: 'USD',
|
|
46
51
|
decimals: 6,
|
|
47
52
|
name: 'PayPal USD',
|
|
48
53
|
standard: 'ERC-20',
|
|
@@ -51,6 +56,7 @@ const sourceChains = [
|
|
|
51
56
|
{
|
|
52
57
|
address: '0x1abaea1f7c830bd89acc67ec4af516284b1bc33c',
|
|
53
58
|
coingeckoId: 'euro-coin',
|
|
59
|
+
currency: 'EUR',
|
|
54
60
|
decimals: 6,
|
|
55
61
|
name: 'Euro Coin',
|
|
56
62
|
standard: 'ERC-20',
|
|
@@ -59,6 +65,7 @@ const sourceChains = [
|
|
|
59
65
|
{
|
|
60
66
|
address: '0x6b175474e89094c44da98b954eedeac495271d0f',
|
|
61
67
|
coingeckoId: 'dai',
|
|
68
|
+
currency: 'USD',
|
|
62
69
|
decimals: 18,
|
|
63
70
|
name: 'Dai Stablecoin',
|
|
64
71
|
standard: 'ERC-20',
|
|
@@ -83,6 +90,7 @@ const sourceChains = [
|
|
|
83
90
|
{
|
|
84
91
|
address: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
|
|
85
92
|
coingeckoId: 'usd-coin',
|
|
93
|
+
currency: 'USD',
|
|
86
94
|
decimals: 6,
|
|
87
95
|
name: 'USD Coin',
|
|
88
96
|
standard: 'ERC-20',
|
|
@@ -91,6 +99,7 @@ const sourceChains = [
|
|
|
91
99
|
{
|
|
92
100
|
address: '0xfde4c96c8593536e31f229ea8f37b2ada2699bb2',
|
|
93
101
|
coingeckoId: 'tether',
|
|
102
|
+
currency: 'USD',
|
|
94
103
|
decimals: 6,
|
|
95
104
|
name: 'Tether USD',
|
|
96
105
|
standard: 'ERC-20',
|
|
@@ -99,6 +108,7 @@ const sourceChains = [
|
|
|
99
108
|
{
|
|
100
109
|
address: '0x60a3e35cc302bfa44cb288bc5a4f316fdb1adb42',
|
|
101
110
|
coingeckoId: 'euro-coin',
|
|
111
|
+
currency: 'EUR',
|
|
102
112
|
decimals: 6,
|
|
103
113
|
name: 'Euro Coin',
|
|
104
114
|
standard: 'ERC-20',
|
|
@@ -122,6 +132,7 @@ const sourceChains = [
|
|
|
122
132
|
{
|
|
123
133
|
address: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d',
|
|
124
134
|
coingeckoId: 'usd-coin',
|
|
135
|
+
currency: 'USD',
|
|
125
136
|
decimals: 18,
|
|
126
137
|
name: 'Binance-Peg USD Coin',
|
|
127
138
|
standard: 'BEP-20',
|
|
@@ -130,6 +141,7 @@ const sourceChains = [
|
|
|
130
141
|
{
|
|
131
142
|
address: '0x55d398326f99059ff775485246999027b3197955',
|
|
132
143
|
coingeckoId: 'tether',
|
|
144
|
+
currency: 'USD',
|
|
133
145
|
decimals: 18,
|
|
134
146
|
name: 'Tether USD',
|
|
135
147
|
standard: 'BEP-20',
|
|
@@ -151,6 +163,7 @@ const sourceChains = [
|
|
|
151
163
|
{
|
|
152
164
|
address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
153
165
|
coingeckoId: 'usd-coin',
|
|
166
|
+
currency: 'USD',
|
|
154
167
|
decimals: 6,
|
|
155
168
|
name: 'USD Coin',
|
|
156
169
|
standard: 'SPL',
|
|
@@ -173,6 +186,7 @@ const sourceChains = [
|
|
|
173
186
|
{
|
|
174
187
|
address: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
|
175
188
|
coingeckoId: 'tether',
|
|
189
|
+
currency: 'USD',
|
|
176
190
|
decimals: 6,
|
|
177
191
|
name: 'Tether USD',
|
|
178
192
|
standard: 'TRC-20',
|
|
@@ -186,6 +200,7 @@ const sourceChains = [
|
|
|
186
200
|
const destinationTokens = [
|
|
187
201
|
{
|
|
188
202
|
address: '0x20c0000000000000000000000000000000000000',
|
|
203
|
+
currency: 'USD',
|
|
189
204
|
decimals: 6,
|
|
190
205
|
name: 'pathUSD',
|
|
191
206
|
slug: 'pathusd',
|
|
@@ -194,6 +209,7 @@ const destinationTokens = [
|
|
|
194
209
|
},
|
|
195
210
|
{
|
|
196
211
|
address: '0x20c000000000000000000000b9537d11c60e8b50',
|
|
212
|
+
currency: 'USD',
|
|
197
213
|
decimals: 6,
|
|
198
214
|
name: 'Bridged USDC (Stargate)',
|
|
199
215
|
slug: 'usdce',
|
|
@@ -202,6 +218,7 @@ const destinationTokens = [
|
|
|
202
218
|
},
|
|
203
219
|
{
|
|
204
220
|
address: '0x20c0000000000000000000001621e21f71cf12fb',
|
|
221
|
+
currency: 'EUR',
|
|
205
222
|
decimals: 6,
|
|
206
223
|
name: 'Bridged EURC',
|
|
207
224
|
slug: 'eurce',
|
|
@@ -210,6 +227,7 @@ const destinationTokens = [
|
|
|
210
227
|
},
|
|
211
228
|
{
|
|
212
229
|
address: '0x20c00000000000000000000014f22ca97301eb73',
|
|
230
|
+
currency: 'USD',
|
|
213
231
|
decimals: 6,
|
|
214
232
|
name: 'USDT0',
|
|
215
233
|
slug: 'usdt0',
|
|
@@ -218,6 +236,7 @@ const destinationTokens = [
|
|
|
218
236
|
},
|
|
219
237
|
{
|
|
220
238
|
address: '0x20c0000000000000000000003554d28269e0f3c2',
|
|
239
|
+
currency: 'USD',
|
|
221
240
|
decimals: 6,
|
|
222
241
|
name: 'frxUSD',
|
|
223
242
|
slug: 'frxusd',
|
|
@@ -346,8 +365,6 @@ export type QuoteProbeResult = {
|
|
|
346
365
|
minimumOutputAmount?: string | undefined
|
|
347
366
|
/** Expected destination amount in base units. */
|
|
348
367
|
outputAmount?: string | undefined
|
|
349
|
-
/** Expected destination amount rendered with destination token decimals. */
|
|
350
|
-
outputAmountFormatted?: string | undefined
|
|
351
368
|
/** Timestamp for the live quote probe. */
|
|
352
369
|
sampledAt: string
|
|
353
370
|
/** Provider-specific quote status for the requested amount. */
|
|
@@ -659,6 +676,7 @@ function formatChain(chain: SourceChainInput) {
|
|
|
659
676
|
function formatDestinationToken(token: DestinationTokenInput) {
|
|
660
677
|
return {
|
|
661
678
|
address: token.address,
|
|
679
|
+
currency: token.currency,
|
|
662
680
|
decimals: token.decimals,
|
|
663
681
|
metadata: {},
|
|
664
682
|
name: token.name,
|
|
@@ -706,6 +724,7 @@ function formatQuoteCandidate(options: {
|
|
|
706
724
|
function formatSourceToken(chain: SourceChainInput, token: TokenInput) {
|
|
707
725
|
return {
|
|
708
726
|
address: token.address,
|
|
727
|
+
currency: token.currency,
|
|
709
728
|
decimals: token.decimals,
|
|
710
729
|
metadata: { coingeckoId: token.coingeckoId },
|
|
711
730
|
name: token.name,
|
|
@@ -741,7 +760,24 @@ type SuccessfulQuoteProbe = QuoteProbeResult & {
|
|
|
741
760
|
|
|
742
761
|
function formatFundingQuote(candidate: QuoteCandidate, quote: SuccessfulQuoteProbe) {
|
|
743
762
|
return {
|
|
744
|
-
|
|
763
|
+
destinationAmount: Value.tokenAmount({
|
|
764
|
+
baseUnits: quote.outputAmount,
|
|
765
|
+
currency: candidate.destinationToken.currency,
|
|
766
|
+
decimals: candidate.destinationToken.decimals,
|
|
767
|
+
}),
|
|
768
|
+
...(quote.minimumOutputAmount !== undefined
|
|
769
|
+
? {
|
|
770
|
+
destinationAmountMin: Value.tokenAmount({
|
|
771
|
+
baseUnits: quote.minimumOutputAmount,
|
|
772
|
+
currency: candidate.destinationToken.currency,
|
|
773
|
+
decimals: candidate.destinationToken.decimals,
|
|
774
|
+
}),
|
|
775
|
+
}
|
|
776
|
+
: {}),
|
|
777
|
+
destinationChain: candidate.destinationChain,
|
|
778
|
+
destinationToken: candidate.destinationToken,
|
|
779
|
+
id: candidate.id,
|
|
780
|
+
provider: candidate.provider,
|
|
745
781
|
quality: {
|
|
746
782
|
...(quote.quality?.estimatedSeconds !== undefined
|
|
747
783
|
? { estimatedSeconds: quote.quality.estimatedSeconds }
|
|
@@ -754,16 +790,15 @@ function formatFundingQuote(candidate: QuoteCandidate, quote: SuccessfulQuotePro
|
|
|
754
790
|
},
|
|
755
791
|
quote: {
|
|
756
792
|
...(quote.expiresAt !== undefined ? { expiresAt: quote.expiresAt } : {}),
|
|
757
|
-
inputAmount: candidate.sourceAmount.amount,
|
|
758
|
-
...(quote.minimumOutputAmount !== undefined
|
|
759
|
-
? { minimumOutputAmount: quote.minimumOutputAmount }
|
|
760
|
-
: {}),
|
|
761
|
-
outputAmount: quote.outputAmount,
|
|
762
|
-
outputAmountFormatted:
|
|
763
|
-
quote.outputAmountFormatted ??
|
|
764
|
-
decimalFromBaseUnits(quote.outputAmount, candidate.destinationToken.decimals),
|
|
765
793
|
sampledAt: quote.sampledAt,
|
|
766
794
|
},
|
|
795
|
+
sourceAmount: Value.tokenAmount({
|
|
796
|
+
baseUnits: candidate.sourceAmount.amount,
|
|
797
|
+
currency: candidate.sourceToken.currency,
|
|
798
|
+
decimals: candidate.sourceToken.decimals,
|
|
799
|
+
}),
|
|
800
|
+
sourceChain: candidate.sourceChain,
|
|
801
|
+
sourceToken: candidate.sourceToken,
|
|
767
802
|
} as const
|
|
768
803
|
}
|
|
769
804
|
|
package/src/internal/Log.test.ts
CHANGED
|
@@ -138,6 +138,97 @@ describe('middleware', () => {
|
|
|
138
138
|
`)
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
+
test('records a JSON-RPC error returned with HTTP 200', async () => {
|
|
142
|
+
const entries: Log.Entry[] = []
|
|
143
|
+
const api = app({ emit: (entry) => void entries.push(entry) })
|
|
144
|
+
api.post('/rpc/sponsor', (c) => {
|
|
145
|
+
const body = {
|
|
146
|
+
error: {
|
|
147
|
+
code: -32602,
|
|
148
|
+
data: { code: 'billing_required', retryable: false },
|
|
149
|
+
message: 'Sponsorship requires an active billing source.',
|
|
150
|
+
},
|
|
151
|
+
id: 1,
|
|
152
|
+
jsonrpc: '2.0',
|
|
153
|
+
}
|
|
154
|
+
c.set('rpcResponse', Log.rpcErrors(body))
|
|
155
|
+
return c.json(body)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const response = await api.request('/rpc/sponsor', { method: 'POST' })
|
|
159
|
+
|
|
160
|
+
expect(response.status).toBe(200)
|
|
161
|
+
expect(stable(entries[0]!)).toMatchInlineSnapshot(`
|
|
162
|
+
{
|
|
163
|
+
"level": "warn",
|
|
164
|
+
"method": "POST",
|
|
165
|
+
"path": "/rpc/sponsor",
|
|
166
|
+
"route": "/rpc/sponsor",
|
|
167
|
+
"rpc": {
|
|
168
|
+
"code": -32602,
|
|
169
|
+
"dataCode": "billing_required",
|
|
170
|
+
"errors": 1,
|
|
171
|
+
},
|
|
172
|
+
"status": 200,
|
|
173
|
+
}
|
|
174
|
+
`)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test('logs JSON-RPC server errors at error level', async () => {
|
|
178
|
+
const entries: Log.Entry[] = []
|
|
179
|
+
const api = app({ emit: (entry) => void entries.push(entry) })
|
|
180
|
+
api.post('/rpc/sponsor', (c) => {
|
|
181
|
+
const body = {
|
|
182
|
+
error: {
|
|
183
|
+
code: -32603,
|
|
184
|
+
data: { code: 'internal_error' },
|
|
185
|
+
message: 'Internal error',
|
|
186
|
+
},
|
|
187
|
+
id: 1,
|
|
188
|
+
jsonrpc: '2.0',
|
|
189
|
+
}
|
|
190
|
+
c.set('rpcResponse', Log.rpcErrors(body))
|
|
191
|
+
return c.json(body)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
await api.request('/rpc/sponsor', { method: 'POST' })
|
|
195
|
+
|
|
196
|
+
expect(entries[0]?.level).toBe('error')
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test('counts batch JSON-RPC errors without retaining mixed codes', async () => {
|
|
200
|
+
const entries: Log.Entry[] = []
|
|
201
|
+
const api = app({ emit: (entry) => void entries.push(entry) })
|
|
202
|
+
api.post('/rpc/relay', (c) => {
|
|
203
|
+
const body = [
|
|
204
|
+
{ id: 1, jsonrpc: '2.0', result: '0x1' },
|
|
205
|
+
{ error: { code: -32602, message: 'Invalid params.' }, id: 2, jsonrpc: '2.0' },
|
|
206
|
+
{
|
|
207
|
+
error: { code: -32603, data: { code: 'Internal Error' }, message: 'Internal error.' },
|
|
208
|
+
id: 3,
|
|
209
|
+
jsonrpc: '2.0',
|
|
210
|
+
},
|
|
211
|
+
]
|
|
212
|
+
c.set('rpcResponse', Log.rpcErrors(body))
|
|
213
|
+
return c.json(body)
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
await api.request('/rpc/relay', { method: 'POST' })
|
|
217
|
+
|
|
218
|
+
expect(stable(entries[0]!)).toMatchInlineSnapshot(`
|
|
219
|
+
{
|
|
220
|
+
"level": "warn",
|
|
221
|
+
"method": "POST",
|
|
222
|
+
"path": "/rpc/relay",
|
|
223
|
+
"route": "/rpc/relay",
|
|
224
|
+
"rpc": {
|
|
225
|
+
"errors": 2,
|
|
226
|
+
},
|
|
227
|
+
"status": 200,
|
|
228
|
+
}
|
|
229
|
+
`)
|
|
230
|
+
})
|
|
231
|
+
|
|
141
232
|
test('includes redacted provider failure details', async () => {
|
|
142
233
|
const entries: Log.Entry[] = []
|
|
143
234
|
const api = app({ emit: (entry) => void entries.push(entry) })
|
package/src/internal/Log.ts
CHANGED
|
@@ -17,6 +17,8 @@ export type Variables = {
|
|
|
17
17
|
providerFailure?: Entry['provider'] | undefined
|
|
18
18
|
/** Redacted provider failures when multiple upstream adapters fail. */
|
|
19
19
|
providerFailures?: Entry['providerFailures'] | undefined
|
|
20
|
+
/** Bounded JSON-RPC failure metadata recorded by a composed RPC handler. */
|
|
21
|
+
rpcResponse?: Entry['rpc'] | undefined
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
/** Hono environment shape used by the request logger. */
|
|
@@ -71,7 +73,7 @@ export type Entry = {
|
|
|
71
73
|
errorCode?: string | undefined
|
|
72
74
|
/** Bounded funding provider attempts made while serving the request. */
|
|
73
75
|
fundingProviderAttempts?: readonly FundingProviderAttempt[] | undefined
|
|
74
|
-
/** Log level
|
|
76
|
+
/** Log level: 5xx `error`; 4xx or JSON-RPC failure `warn`; otherwise `info`. */
|
|
75
77
|
level: Level
|
|
76
78
|
/** Request method. */
|
|
77
79
|
method: string
|
|
@@ -121,7 +123,16 @@ export type Entry = {
|
|
|
121
123
|
requestId: string
|
|
122
124
|
/** Matched handler path (bounded cardinality), e.g. `/v1/tokens/:address`; `/*` when a middleware (e.g. an edge-cache hit) short-circuited routing. */
|
|
123
125
|
route: string
|
|
124
|
-
/**
|
|
126
|
+
/** JSON-RPC failures returned in an otherwise successful HTTP response. */
|
|
127
|
+
rpc?: {
|
|
128
|
+
/** Numeric JSON-RPC error code when every failed response shares one code. */
|
|
129
|
+
code?: number | undefined
|
|
130
|
+
/** Stable application error code from `error.data.code`, when shared by every failed response. */
|
|
131
|
+
dataCode?: string | undefined
|
|
132
|
+
/** Number of failed responses in the single or batch JSON-RPC response. */
|
|
133
|
+
errors: number
|
|
134
|
+
}
|
|
135
|
+
/** HTTP response status code. JSON-RPC failures retain their protocol-native `200`. */
|
|
125
136
|
status: number
|
|
126
137
|
/** Upstream operation durations in milliseconds, from the request's Server-Timing metrics (e.g. RPC and TIDX calls). */
|
|
127
138
|
timings?: Record<string, number> | undefined
|
|
@@ -138,8 +149,9 @@ export type Emit = (entry: Entry) => Promise<void> | void
|
|
|
138
149
|
*
|
|
139
150
|
* The entry derives everything from state other layers already produce —
|
|
140
151
|
* `requestId`, the auth principal, `RateLimit-*` headers, Server-Timing
|
|
141
|
-
* metrics, the `errorCode` recorded by `Response.error`,
|
|
142
|
-
* hit marker
|
|
152
|
+
* metrics, the `errorCode` recorded by `Response.error`, JSON-RPC response
|
|
153
|
+
* errors, and the edge-cache hit marker, so handlers never log per-request
|
|
154
|
+
* lines themselves.
|
|
143
155
|
*/
|
|
144
156
|
export function middleware<environment extends Environment = Environment>(
|
|
145
157
|
options: middleware.Options = {},
|
|
@@ -164,6 +176,7 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
164
176
|
| undefined
|
|
165
177
|
const provider = c.get('providerFailure' as never) as Entry['provider']
|
|
166
178
|
const providerFailures = c.get('providerFailures' as never) as Entry['providerFailures']
|
|
179
|
+
const rpc = c.get('rpcResponse' as never) as Entry['rpc']
|
|
167
180
|
|
|
168
181
|
// The `request` total metric duplicates `duration` (measured here, one
|
|
169
182
|
// layer further out), so only operation timings are kept.
|
|
@@ -193,7 +206,12 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
193
206
|
duration: round(duration),
|
|
194
207
|
...(errorCode === undefined ? {} : { errorCode }),
|
|
195
208
|
...(fundingProviderAttempts === undefined ? {} : { fundingProviderAttempts }),
|
|
196
|
-
level:
|
|
209
|
+
level:
|
|
210
|
+
status >= 500 || rpcServerError(rpc?.code)
|
|
211
|
+
? 'error'
|
|
212
|
+
: status >= 400 || rpc
|
|
213
|
+
? 'warn'
|
|
214
|
+
: 'info',
|
|
197
215
|
method: c.req.method,
|
|
198
216
|
path: url.pathname,
|
|
199
217
|
...(principal?.payment === undefined ? {} : { payment: principal.payment.reason }),
|
|
@@ -220,6 +238,7 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
220
238
|
...(rateLimit === undefined ? {} : { rateLimit }),
|
|
221
239
|
requestId: c.get('requestId' as never) as string,
|
|
222
240
|
route: c.req.routePath,
|
|
241
|
+
...(rpc === undefined ? {} : { rpc }),
|
|
223
242
|
status,
|
|
224
243
|
...(timings === undefined ? {} : { timings }),
|
|
225
244
|
})
|
|
@@ -238,6 +257,51 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
238
257
|
}
|
|
239
258
|
}
|
|
240
259
|
|
|
260
|
+
const rpcDataCode = /^[a-z][a-z0-9_]{0,63}$/
|
|
261
|
+
|
|
262
|
+
/** Extracts bounded error metadata from an already-parsed JSON-RPC response. */
|
|
263
|
+
export function rpcErrors(body: unknown): Entry['rpc'] {
|
|
264
|
+
const values = Array.isArray(body) ? body : [body]
|
|
265
|
+
const errors = values.flatMap((value) => {
|
|
266
|
+
if (!value || typeof value !== 'object') return []
|
|
267
|
+
const record = value as Record<string, unknown>
|
|
268
|
+
if (record['jsonrpc'] !== '2.0' || !record['error'] || typeof record['error'] !== 'object')
|
|
269
|
+
return []
|
|
270
|
+
const error = record['error'] as Record<string, unknown>
|
|
271
|
+
if (
|
|
272
|
+
!Number.isInteger(error['code']) ||
|
|
273
|
+
Number(error['code']) < -2_147_483_648 ||
|
|
274
|
+
Number(error['code']) > 2_147_483_647
|
|
275
|
+
)
|
|
276
|
+
return []
|
|
277
|
+
const data = error['data']
|
|
278
|
+
const dataCode_value =
|
|
279
|
+
data && typeof data === 'object' ? (data as Record<string, unknown>)['code'] : undefined
|
|
280
|
+
const dataCode = typeof dataCode_value === 'string' ? dataCode_value : undefined
|
|
281
|
+
return [
|
|
282
|
+
{
|
|
283
|
+
code: error['code'] as number,
|
|
284
|
+
...(dataCode && rpcDataCode.test(dataCode) ? { dataCode } : {}),
|
|
285
|
+
},
|
|
286
|
+
]
|
|
287
|
+
})
|
|
288
|
+
if (errors.length === 0) return undefined
|
|
289
|
+
|
|
290
|
+
const codes = new Set(errors.map((error) => error.code))
|
|
291
|
+
const dataCodes = new Set(errors.map((error) => error.dataCode).filter(Boolean))
|
|
292
|
+
return {
|
|
293
|
+
...(codes.size === 1 ? { code: errors[0]!.code } : {}),
|
|
294
|
+
...(dataCodes.size === 1 && errors.every((error) => error.dataCode !== undefined)
|
|
295
|
+
? { dataCode: errors[0]!.dataCode }
|
|
296
|
+
: {}),
|
|
297
|
+
errors: Math.min(errors.length, 65_535),
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function rpcServerError(code: number | undefined) {
|
|
302
|
+
return code === -32603 || (code !== undefined && code >= -32099 && code <= -32000)
|
|
303
|
+
}
|
|
304
|
+
|
|
241
305
|
export declare namespace middleware {
|
|
242
306
|
/** Options for the request logger middleware. */
|
|
243
307
|
type Options = {
|
|
@@ -10,6 +10,61 @@ type MetricEvent = {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
describe('requests', () => {
|
|
13
|
+
test('records JSON-RPC errors with bounded code tags', () => {
|
|
14
|
+
const events: MetricEvent[] = []
|
|
15
|
+
const metrics = Metrics.from({
|
|
16
|
+
count(name, value, tags) {
|
|
17
|
+
events.push({ name, tags, type: 'count', value })
|
|
18
|
+
},
|
|
19
|
+
flush() {},
|
|
20
|
+
gauge() {},
|
|
21
|
+
histogram() {},
|
|
22
|
+
})
|
|
23
|
+
const record = MetricSink.requests(metrics)
|
|
24
|
+
|
|
25
|
+
record({
|
|
26
|
+
duration: 10,
|
|
27
|
+
level: 'warn',
|
|
28
|
+
method: 'POST',
|
|
29
|
+
path: '/rpc/relay',
|
|
30
|
+
requestId: 'request_private',
|
|
31
|
+
route: '/rpc/relay',
|
|
32
|
+
rpc: { code: -32602, dataCode: 'billing_required', errors: 2 },
|
|
33
|
+
status: 200,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
expect(events).toMatchInlineSnapshot(`
|
|
37
|
+
[
|
|
38
|
+
{
|
|
39
|
+
"name": "http_response_count",
|
|
40
|
+
"tags": {
|
|
41
|
+
"cache": "miss",
|
|
42
|
+
"method": "POST",
|
|
43
|
+
"principal_environment": "none",
|
|
44
|
+
"principal_type": "unknown",
|
|
45
|
+
"route": "/rpc/relay",
|
|
46
|
+
"status": 200,
|
|
47
|
+
},
|
|
48
|
+
"type": "count",
|
|
49
|
+
"value": 1,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "rpc_response_error_count",
|
|
53
|
+
"tags": {
|
|
54
|
+
"cache": "miss",
|
|
55
|
+
"method": "POST",
|
|
56
|
+
"principal_environment": "none",
|
|
57
|
+
"principal_type": "unknown",
|
|
58
|
+
"route": "/rpc/relay",
|
|
59
|
+
"rpc_error_code": "-32602",
|
|
60
|
+
},
|
|
61
|
+
"type": "count",
|
|
62
|
+
"value": 2,
|
|
63
|
+
},
|
|
64
|
+
]
|
|
65
|
+
`)
|
|
66
|
+
})
|
|
67
|
+
|
|
13
68
|
test('records bounded funding provider attempts without caller data', () => {
|
|
14
69
|
const events: MetricEvent[] = []
|
|
15
70
|
let flushes = 0
|
|
@@ -85,6 +85,12 @@ export function requests(backend: Metrics): RequestSink {
|
|
|
85
85
|
})
|
|
86
86
|
backend.histogram('http_response_duration_ms', entry.duration, tags)
|
|
87
87
|
|
|
88
|
+
if (entry.rpc)
|
|
89
|
+
backend.count('rpc_response_error_count', entry.rpc.errors, {
|
|
90
|
+
...tags,
|
|
91
|
+
rpc_error_code: rpcErrorCode(entry.rpc.code),
|
|
92
|
+
})
|
|
93
|
+
|
|
88
94
|
if (entry.status === 429 || entry.errorCode === 'rate_limit_exceeded')
|
|
89
95
|
backend.count('http_rate_limit_count', 1, {
|
|
90
96
|
...tags,
|
|
@@ -109,6 +115,14 @@ export function requests(backend: Metrics): RequestSink {
|
|
|
109
115
|
}
|
|
110
116
|
}
|
|
111
117
|
|
|
118
|
+
/** Maps arbitrary upstream JSON-RPC codes into bounded metric tags. */
|
|
119
|
+
function rpcErrorCode(code: number | undefined) {
|
|
120
|
+
if (code === undefined) return 'mixed'
|
|
121
|
+
if ([-32700, -32600, -32601, -32602, -32603].includes(code)) return String(code)
|
|
122
|
+
if (code >= -32099 && code <= -32000) return 'server'
|
|
123
|
+
return 'other'
|
|
124
|
+
}
|
|
125
|
+
|
|
112
126
|
function routeTags(entry: Log.Entry): RouteTags {
|
|
113
127
|
return {
|
|
114
128
|
cache: entry.cache ?? 'miss',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
|
|
3
|
+
import * as Response from './Response.js'
|
|
4
|
+
|
|
5
|
+
describe('upstream', () => {
|
|
6
|
+
test('returns a stable message and preserves the cause on context', async () => {
|
|
7
|
+
const app = new Hono()
|
|
8
|
+
const cause = new Error('provider URL contains secret credentials')
|
|
9
|
+
let captured: Error | undefined
|
|
10
|
+
|
|
11
|
+
app.use(async (c, next) => {
|
|
12
|
+
await next()
|
|
13
|
+
captured = c.error
|
|
14
|
+
})
|
|
15
|
+
app.get('/', (c) => Response.upstream(c, cause))
|
|
16
|
+
|
|
17
|
+
const response = await app.request('/')
|
|
18
|
+
expect(await response.json()).toMatchInlineSnapshot(`
|
|
19
|
+
{
|
|
20
|
+
"error": {
|
|
21
|
+
"code": "upstream_error",
|
|
22
|
+
"message": "Upstream service could not complete the request",
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
`)
|
|
26
|
+
expect(captured).toBe(cause)
|
|
27
|
+
})
|
|
28
|
+
})
|
package/src/internal/Response.ts
CHANGED
|
@@ -39,12 +39,20 @@ export function unsupportedChainId(c: Context, chainId: number, supported: Itera
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* Maps an unexpected upstream failure to a 502 JSON error envelope.
|
|
43
|
-
*
|
|
42
|
+
* Maps an unexpected upstream failure to a stable 502 JSON error envelope.
|
|
43
|
+
* Preserves `Error` causes for reporting and rethrows non-`Error` causes.
|
|
44
44
|
*/
|
|
45
45
|
export function upstream(c: Context, cause: unknown) {
|
|
46
|
-
if (cause instanceof Error)
|
|
47
|
-
|
|
46
|
+
if (cause instanceof Error) {
|
|
47
|
+
// Preserve the original error for error-reporting middleware without
|
|
48
|
+
// exposing provider URLs, payloads, or credentials in the response.
|
|
49
|
+
c.error = cause
|
|
50
|
+
return error(c, {
|
|
51
|
+
code: 'upstream_error',
|
|
52
|
+
message: 'Upstream service could not complete the request',
|
|
53
|
+
status: 502,
|
|
54
|
+
})
|
|
55
|
+
}
|
|
48
56
|
throw cause
|
|
49
57
|
}
|
|
50
58
|
|