tapimo 0.0.0 → 0.0.2
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/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/ApiKey.d.ts +65 -0
- package/dist/ApiKey.d.ts.map +1 -0
- package/dist/ApiKey.js +105 -0
- package/dist/ApiKey.js.map +1 -0
- package/dist/ApiKeySource.d.ts +166 -0
- package/dist/ApiKeySource.d.ts.map +1 -0
- package/dist/ApiKeySource.js +234 -0
- package/dist/ApiKeySource.js.map +1 -0
- package/dist/App.d.ts +19317 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +612 -0
- package/dist/App.js.map +1 -0
- package/dist/Assets.d.ts +44 -0
- package/dist/Assets.d.ts.map +1 -0
- package/dist/Assets.js +23 -0
- package/dist/Assets.js.map +1 -0
- package/dist/Auth.d.ts +2 -0
- package/dist/Auth.d.ts.map +1 -0
- package/dist/Auth.js +2 -0
- package/dist/Auth.js.map +1 -0
- package/dist/Cli.d.ts +21 -0
- package/dist/Cli.d.ts.map +1 -0
- package/dist/Cli.js +13 -0
- package/dist/Cli.js.map +1 -0
- package/dist/Client.d.ts +20 -0
- package/dist/Client.d.ts.map +1 -0
- package/dist/Client.js +24 -0
- package/dist/Client.js.map +1 -0
- package/dist/Metrics.d.ts +70 -0
- package/dist/Metrics.d.ts.map +1 -0
- package/dist/Metrics.js +91 -0
- package/dist/Metrics.js.map +1 -0
- package/dist/Scope.d.ts +35 -0
- package/dist/Scope.d.ts.map +1 -0
- package/dist/Scope.js +38 -0
- package/dist/Scope.js.map +1 -0
- package/dist/Webhooks.d.ts +79 -0
- package/dist/Webhooks.d.ts.map +1 -0
- package/dist/Webhooks.js +107 -0
- package/dist/Webhooks.js.map +1 -0
- package/dist/admin/Access.d.ts +41 -0
- package/dist/admin/Access.d.ts.map +1 -0
- package/dist/admin/Access.js +75 -0
- package/dist/admin/Access.js.map +1 -0
- package/dist/admin/App.d.ts +1221 -0
- package/dist/admin/App.d.ts.map +1 -0
- package/dist/admin/App.js +113 -0
- package/dist/admin/App.js.map +1 -0
- package/dist/admin/apps/api-keys.d.ts +209 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -0
- package/dist/admin/apps/api-keys.js +129 -0
- package/dist/admin/apps/api-keys.js.map +1 -0
- package/dist/admin/apps/scopes.d.ts +46 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -0
- package/dist/admin/apps/scopes.js +41 -0
- package/dist/admin/apps/scopes.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +1206 -0
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -0
- package/dist/admin/apps/verified-tokens.js +485 -0
- package/dist/admin/apps/verified-tokens.js.map +1 -0
- package/dist/admin/index.d.ts +3 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +3 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/ui.generated.d.ts +11 -0
- package/dist/admin/ui.generated.d.ts.map +1 -0
- package/dist/admin/ui.generated.js +43 -0
- package/dist/admin/ui.generated.js.map +1 -0
- package/dist/apps/activities.d.ts +18725 -0
- package/dist/apps/activities.d.ts.map +1 -0
- package/dist/apps/activities.js +3138 -0
- package/dist/apps/activities.js.map +1 -0
- package/dist/apps/addresses.d.ts +3662 -0
- package/dist/apps/addresses.d.ts.map +1 -0
- package/dist/apps/addresses.js +22 -0
- package/dist/apps/addresses.js.map +1 -0
- package/dist/apps/balances.d.ts +342 -0
- package/dist/apps/balances.d.ts.map +1 -0
- package/dist/apps/balances.js +393 -0
- package/dist/apps/balances.js.map +1 -0
- package/dist/apps/blocks.d.ts +931 -0
- package/dist/apps/blocks.d.ts.map +1 -0
- package/dist/apps/blocks.js +689 -0
- package/dist/apps/blocks.js.map +1 -0
- package/dist/apps/coingecko.d.ts +1053 -0
- package/dist/apps/coingecko.d.ts.map +1 -0
- package/dist/apps/coingecko.js +1015 -0
- package/dist/apps/coingecko.js.map +1 -0
- package/dist/apps/exchanges.d.ts +3000 -0
- package/dist/apps/exchanges.d.ts.map +1 -0
- package/dist/apps/exchanges.js +3570 -0
- package/dist/apps/exchanges.js.map +1 -0
- package/dist/apps/fee-amm.d.ts +640 -0
- package/dist/apps/fee-amm.d.ts.map +1 -0
- package/dist/apps/fee-amm.js +815 -0
- package/dist/apps/fee-amm.js.map +1 -0
- package/dist/apps/indexer.d.ts +116 -0
- package/dist/apps/indexer.d.ts.map +1 -0
- package/dist/apps/indexer.js +270 -0
- package/dist/apps/indexer.js.map +1 -0
- package/dist/apps/receipts.d.ts +1438 -0
- package/dist/apps/receipts.d.ts.map +1 -0
- package/dist/apps/receipts.js +874 -0
- package/dist/apps/receipts.js.map +1 -0
- package/dist/apps/rpc.d.ts +173 -0
- package/dist/apps/rpc.d.ts.map +1 -0
- package/dist/apps/rpc.js +191 -0
- package/dist/apps/rpc.js.map +1 -0
- package/dist/apps/tokenlist.d.ts +192 -0
- package/dist/apps/tokenlist.d.ts.map +1 -0
- package/dist/apps/tokenlist.js +153 -0
- package/dist/apps/tokenlist.js.map +1 -0
- package/dist/apps/tokens.d.ts +2246 -0
- package/dist/apps/tokens.d.ts.map +1 -0
- package/dist/apps/tokens.js +1789 -0
- package/dist/apps/tokens.js.map +1 -0
- package/dist/apps/transactions.d.ts +2327 -0
- package/dist/apps/transactions.d.ts.map +1 -0
- package/dist/apps/transactions.js +975 -0
- package/dist/apps/transactions.js.map +1 -0
- package/dist/apps/transfers.d.ts +589 -0
- package/dist/apps/transfers.d.ts.map +1 -0
- package/dist/apps/transfers.js +769 -0
- package/dist/apps/transfers.js.map +1 -0
- package/dist/apps/verified-tokens.d.ts +544 -0
- package/dist/apps/verified-tokens.d.ts.map +1 -0
- package/dist/apps/verified-tokens.js +234 -0
- package/dist/apps/verified-tokens.js.map +1 -0
- package/dist/apps/webhooks.d.ts +7684 -0
- package/dist/apps/webhooks.d.ts.map +1 -0
- package/dist/apps/webhooks.js +2112 -0
- package/dist/apps/webhooks.js.map +1 -0
- package/dist/cloudflare.d.ts +32 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +45 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/Auth.d.ts +298 -0
- package/dist/internal/Auth.d.ts.map +1 -0
- package/dist/internal/Auth.js +618 -0
- package/dist/internal/Auth.js.map +1 -0
- package/dist/internal/Cache.d.ts +74 -0
- package/dist/internal/Cache.d.ts.map +1 -0
- package/dist/internal/Cache.js +215 -0
- package/dist/internal/Cache.js.map +1 -0
- package/dist/internal/Cursor.d.ts +79 -0
- package/dist/internal/Cursor.d.ts.map +1 -0
- package/dist/internal/Cursor.js +116 -0
- package/dist/internal/Cursor.js.map +1 -0
- package/dist/internal/EdgeCache.d.ts +59 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -0
- package/dist/internal/EdgeCache.js +174 -0
- package/dist/internal/EdgeCache.js.map +1 -0
- package/dist/internal/Log.d.ts +104 -0
- package/dist/internal/Log.d.ts.map +1 -0
- package/dist/internal/Log.js +118 -0
- package/dist/internal/Log.js.map +1 -0
- package/dist/internal/MetricSink.d.ts +65 -0
- package/dist/internal/MetricSink.d.ts.map +1 -0
- package/dist/internal/MetricSink.js +146 -0
- package/dist/internal/MetricSink.js.map +1 -0
- package/dist/internal/Mpp.d.ts +71 -0
- package/dist/internal/Mpp.d.ts.map +1 -0
- package/dist/internal/Mpp.js +105 -0
- package/dist/internal/Mpp.js.map +1 -0
- package/dist/internal/OpenApi.d.ts +313 -0
- package/dist/internal/OpenApi.d.ts.map +1 -0
- package/dist/internal/OpenApi.fonts.d.ts +2 -0
- package/dist/internal/OpenApi.fonts.d.ts.map +1 -0
- package/dist/internal/OpenApi.fonts.js +39 -0
- package/dist/internal/OpenApi.fonts.js.map +1 -0
- package/dist/internal/OpenApi.js +335 -0
- package/dist/internal/OpenApi.js.map +1 -0
- package/dist/internal/OpenApi.logo.d.ts +6 -0
- package/dist/internal/OpenApi.logo.d.ts.map +1 -0
- package/dist/internal/OpenApi.logo.js +19 -0
- package/dist/internal/OpenApi.logo.js.map +1 -0
- package/dist/internal/Path.d.ts +5 -0
- package/dist/internal/Path.d.ts.map +1 -0
- package/dist/internal/Path.js +16 -0
- package/dist/internal/Path.js.map +1 -0
- package/dist/internal/RateLimit.d.ts +60 -0
- package/dist/internal/RateLimit.d.ts.map +1 -0
- package/dist/internal/RateLimit.js +48 -0
- package/dist/internal/RateLimit.js.map +1 -0
- package/dist/internal/Response.d.ts +132 -0
- package/dist/internal/Response.d.ts.map +1 -0
- package/dist/internal/Response.js +72 -0
- package/dist/internal/Response.js.map +1 -0
- package/dist/internal/Schema.d.ts +257 -0
- package/dist/internal/Schema.d.ts.map +1 -0
- package/dist/internal/Schema.js +360 -0
- package/dist/internal/Schema.js.map +1 -0
- package/dist/internal/Store.d.ts +204 -0
- package/dist/internal/Store.d.ts.map +1 -0
- package/dist/internal/Store.js +291 -0
- package/dist/internal/Store.js.map +1 -0
- package/dist/internal/Tidx.d.ts +120 -0
- package/dist/internal/Tidx.d.ts.map +1 -0
- package/dist/internal/Tidx.js +156 -0
- package/dist/internal/Tidx.js.map +1 -0
- package/dist/internal/Timing.d.ts +22 -0
- package/dist/internal/Timing.d.ts.map +1 -0
- package/dist/internal/Timing.js +32 -0
- package/dist/internal/Timing.js.map +1 -0
- package/dist/internal/Ttl.d.ts +25 -0
- package/dist/internal/Ttl.d.ts.map +1 -0
- package/dist/internal/Ttl.js +49 -0
- package/dist/internal/Ttl.js.map +1 -0
- package/dist/internal/Value.d.ts +47 -0
- package/dist/internal/Value.d.ts.map +1 -0
- package/dist/internal/Value.js +122 -0
- package/dist/internal/Value.js.map +1 -0
- package/dist/internal/VerifiedTokens.d.ts +228 -0
- package/dist/internal/VerifiedTokens.d.ts.map +1 -0
- package/dist/internal/VerifiedTokens.js +450 -0
- package/dist/internal/VerifiedTokens.js.map +1 -0
- package/dist/internal/Viem.d.ts +2082 -0
- package/dist/internal/Viem.d.ts.map +1 -0
- package/dist/internal/Viem.js +63 -0
- package/dist/internal/Viem.js.map +1 -0
- package/dist/internal/WebhookDestination.d.ts +198 -0
- package/dist/internal/WebhookDestination.d.ts.map +1 -0
- package/dist/internal/WebhookDestination.js +170 -0
- package/dist/internal/WebhookDestination.js.map +1 -0
- package/dist/internal/Webhooks.d.ts +433 -0
- package/dist/internal/Webhooks.d.ts.map +1 -0
- package/dist/internal/Webhooks.js +489 -0
- package/dist/internal/Webhooks.js.map +1 -0
- package/dist/internal/webhookDestinations/betterStack.d.ts +26 -0
- package/dist/internal/webhookDestinations/betterStack.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/betterStack.js +76 -0
- package/dist/internal/webhookDestinations/betterStack.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.d.ts +59 -0
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/slack.js +422 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -0
- package/dist/internal/webhookDestinations/url.d.ts +17 -0
- package/dist/internal/webhookDestinations/url.d.ts.map +1 -0
- package/dist/internal/webhookDestinations/url.js +130 -0
- package/dist/internal/webhookDestinations/url.js.map +1 -0
- package/dist/openrpc.json +5302 -0
- package/package.json +46 -4
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
- package/seeds/31318/verified-tokens.json +30 -0
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +4 -0
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +30 -0
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +11 -0
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +1 -0
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +5 -0
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +1 -0
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +1 -0
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +177 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +25 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +1 -0
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +1 -0
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +1 -0
- package/seeds/42431/verified-tokens.json +44 -0
- package/seeds/openrpc/README.md +27 -0
- package/seeds/openrpc/execution-apis.json +8989 -0
- package/src/ApiKey.test.ts +91 -0
- package/src/ApiKey.ts +122 -0
- package/src/ApiKeySource.test-d.ts +11 -0
- package/src/ApiKeySource.test.ts +295 -0
- package/src/ApiKeySource.ts +303 -0
- package/src/App.test-d.ts +38 -0
- package/src/App.test.ts +65927 -0
- package/src/App.ts +855 -0
- package/src/Assets.ts +58 -0
- package/src/Auth.ts +1 -0
- package/src/Cli.test.ts +81 -0
- package/src/Cli.ts +38 -0
- package/src/Client.test-d.ts +1438 -0
- package/src/Client.test.ts +134 -0
- package/src/Client.ts +45 -0
- package/src/Metrics.ts +154 -0
- package/src/Scope.ts +50 -0
- package/src/Webhooks.test.ts +49 -0
- package/src/Webhooks.ts +172 -0
- package/src/admin/Access.test.ts +130 -0
- package/src/admin/Access.ts +87 -0
- package/src/admin/App.test.ts +225 -0
- package/src/admin/App.ts +216 -0
- package/src/admin/apps/api-keys.test.ts +156 -0
- package/src/admin/apps/api-keys.ts +157 -0
- package/src/admin/apps/scopes.test.ts +52 -0
- package/src/admin/apps/scopes.ts +47 -0
- package/src/admin/apps/verified-tokens.test.ts +415 -0
- package/src/admin/apps/verified-tokens.ts +566 -0
- package/src/admin/index.ts +2 -0
- package/src/admin/ui/plugin.ts +135 -0
- package/src/admin/ui/src/components/Checkbox.tsx +22 -0
- package/src/admin/ui/src/components/Dialog.tsx +32 -0
- package/src/admin/ui/src/components/MobileProfile.tsx +31 -0
- package/src/admin/ui/src/components/Page.tsx +53 -0
- package/src/admin/ui/src/components/TempoLogo.tsx +37 -0
- package/src/admin/ui/src/fonts/Pilat-Demi.woff2 +0 -0
- package/src/admin/ui/src/fonts/Pilat-Regular.woff2 +0 -0
- package/src/admin/ui/src/lib/api-keys.ts +63 -0
- package/src/admin/ui/src/lib/client.ts +15 -0
- package/src/admin/ui/src/lib/config.ts +57 -0
- package/src/admin/ui/src/lib/query-client.ts +26 -0
- package/src/admin/ui/src/lib/scopes.ts +25 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +89 -0
- package/src/admin/ui/src/lib/wagmi.ts +18 -0
- package/src/admin/ui/src/routeTree.gen.ts +104 -0
- package/src/admin/ui/src/router.tsx +25 -0
- package/src/admin/ui/src/routes/__root.tsx +219 -0
- package/src/admin/ui/src/routes/api-keys.tsx +329 -0
- package/src/admin/ui/src/routes/index.tsx +7 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +331 -0
- package/src/admin/ui/src/styles.css +20 -0
- package/src/admin/ui/tsconfig.json +16 -0
- package/src/admin/ui/vite.config.ts +29 -0
- package/src/admin/ui.generated.ts +60 -0
- package/src/apps/activities.test.ts +1020 -0
- package/src/apps/activities.ts +3934 -0
- package/src/apps/addresses.ts +24 -0
- package/src/apps/balances.test.ts +274 -0
- package/src/apps/balances.ts +533 -0
- package/src/apps/blocks.test.ts +385 -0
- package/src/apps/blocks.ts +896 -0
- package/src/apps/coingecko.test.ts +218 -0
- package/src/apps/coingecko.ts +1383 -0
- package/src/apps/exchanges.test.ts +958 -0
- package/src/apps/exchanges.ts +4773 -0
- package/src/apps/fee-amm.test.ts +321 -0
- package/src/apps/fee-amm.ts +1121 -0
- package/src/apps/indexer.test.ts +153 -0
- package/src/apps/indexer.ts +330 -0
- package/src/apps/receipts.test.ts +285 -0
- package/src/apps/receipts.ts +1193 -0
- package/src/apps/rpc.test.ts +302 -0
- package/src/apps/rpc.ts +222 -0
- package/src/apps/tokenlist.test.ts +80 -0
- package/src/apps/tokenlist.ts +207 -0
- package/src/apps/tokens.test.ts +1062 -0
- package/src/apps/tokens.ts +2292 -0
- package/src/apps/transactions.test.ts +408 -0
- package/src/apps/transactions.ts +1363 -0
- package/src/apps/transfers.test.ts +371 -0
- package/src/apps/transfers.ts +1116 -0
- package/src/apps/verified-tokens.test.ts +114 -0
- package/src/apps/verified-tokens.ts +295 -0
- package/src/apps/webhooks.test.ts +1937 -0
- package/src/apps/webhooks.ts +2926 -0
- package/src/cloudflare.ts +55 -0
- package/src/index.ts +15 -0
- package/src/internal/Auth.test.ts +980 -0
- package/src/internal/Auth.ts +1012 -0
- package/src/internal/Cache.test.ts +240 -0
- package/src/internal/Cache.ts +262 -0
- package/src/internal/Cursor.test.ts +100 -0
- package/src/internal/Cursor.ts +149 -0
- package/src/internal/EdgeCache.test.ts +234 -0
- package/src/internal/EdgeCache.ts +224 -0
- package/src/internal/Errors.ts +14 -0
- package/src/internal/Log.test.ts +244 -0
- package/src/internal/Log.ts +216 -0
- package/src/internal/MetricSink.ts +220 -0
- package/src/internal/Mpp.test.ts +64 -0
- package/src/internal/Mpp.ts +141 -0
- package/src/internal/OpenApi.fonts.ts +38 -0
- package/src/internal/OpenApi.logo.ts +18 -0
- package/src/internal/OpenApi.ts +488 -0
- package/src/internal/Path.test.ts +14 -0
- package/src/internal/Path.ts +15 -0
- package/src/internal/RateLimit.test.ts +93 -0
- package/src/internal/RateLimit.ts +93 -0
- package/src/internal/Response.ts +131 -0
- package/src/internal/Schema.test.ts +34 -0
- package/src/internal/Schema.ts +523 -0
- package/src/internal/Store.test.ts +545 -0
- package/src/internal/Store.ts +526 -0
- package/src/internal/Tidx.local.test.ts +33 -0
- package/src/internal/Tidx.test.ts +294 -0
- package/src/internal/Tidx.ts +238 -0
- package/src/internal/Timing.test.ts +22 -0
- package/src/internal/Timing.ts +62 -0
- package/src/internal/Ttl.test.ts +18 -0
- package/src/internal/Ttl.ts +59 -0
- package/src/internal/Value.ts +114 -0
- package/src/internal/VerifiedTokens.test.ts +333 -0
- package/src/internal/VerifiedTokens.ts +645 -0
- package/src/internal/Viem.test.ts +115 -0
- package/src/internal/Viem.ts +165 -0
- package/src/internal/WebhookDestination.test.ts +648 -0
- package/src/internal/WebhookDestination.ts +331 -0
- package/src/internal/Webhooks.test.ts +668 -0
- package/src/internal/Webhooks.ts +940 -0
- package/src/internal/webhookDestinations/betterStack.ts +91 -0
- package/src/internal/webhookDestinations/slack.ts +496 -0
- package/src/internal/webhookDestinations/url.ts +128 -0
- package/src/openrpc.json +5302 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import type * as z from 'zod/mini'
|
|
2
|
+
import { Schema } from 'cadent'
|
|
3
|
+
|
|
4
|
+
import * as TestApp from '../../test/App.js'
|
|
5
|
+
import * as Runtime from '../../test/runtime.js'
|
|
6
|
+
import * as Transfers from './transfers.js'
|
|
7
|
+
|
|
8
|
+
describe('GET /transfers', () => {
|
|
9
|
+
test('returns an unscoped transfer page, embedding tokens on demand', async () => {
|
|
10
|
+
const client = TestApp.client()
|
|
11
|
+
const baseResponse = await client.v1.transfers.$get({ query: { limit: '5' } }, TestApp.auth)
|
|
12
|
+
const base = await TestApp.json(baseResponse, Transfers.schema.getTransfers.Response)
|
|
13
|
+
|
|
14
|
+
expect(baseResponse.status).toBe(200)
|
|
15
|
+
expect(baseResponse.headers.get('server-timing')?.includes('transfers;dur=')).toBe(true)
|
|
16
|
+
expect(Array.isArray(base.data)).toBe(true)
|
|
17
|
+
expect(base.data.length).toBeLessThanOrEqual(5)
|
|
18
|
+
// Pagination fields stay at the response root; cursor pagination has no
|
|
19
|
+
// `page`, just an opaque `nextCursor`.
|
|
20
|
+
expect('page' in base).toBe(false)
|
|
21
|
+
expect(base.nextCursor === null || typeof base.nextCursor === 'string').toBe(true)
|
|
22
|
+
expect(
|
|
23
|
+
base.data.every(
|
|
24
|
+
(entry) =>
|
|
25
|
+
/^0x[0-9a-f]{40}$/.test(entry.sourceToken.address) &&
|
|
26
|
+
/^\d+$/.test(entry.sourceToken.amount) &&
|
|
27
|
+
Number.isInteger(entry.blockNumber) &&
|
|
28
|
+
/^0x[0-9a-f]{40}$/.test(entry.sender) &&
|
|
29
|
+
/^0x[0-9a-f]{40}$/.test(entry.recipient) &&
|
|
30
|
+
/^0x[0-9a-f]{64}$/.test(entry.transactionHash) &&
|
|
31
|
+
!Number.isNaN(Date.parse(entry.timestamp)),
|
|
32
|
+
),
|
|
33
|
+
).toBe(true)
|
|
34
|
+
// Transfers default to newest-first (descending block number).
|
|
35
|
+
const blocks = base.data.map((entry) => entry.blockNumber)
|
|
36
|
+
expect(blocks.every((block, index) => index === 0 || blocks[index - 1]! >= block)).toBe(true)
|
|
37
|
+
// Token metadata is opt-in: the base page's `sourceToken` carries only
|
|
38
|
+
// `address`/`amount`, with no metadata fields spread in.
|
|
39
|
+
expect(base.data.every((entry) => entry.sourceToken.symbol === undefined)).toBe(true)
|
|
40
|
+
|
|
41
|
+
const includedResponse = await client.v1.transfers.$get(
|
|
42
|
+
{ query: { limit: '5', include: 'token' } },
|
|
43
|
+
TestApp.auth,
|
|
44
|
+
)
|
|
45
|
+
const included = await TestApp.json(includedResponse, Transfers.schema.getTransfers.Response)
|
|
46
|
+
|
|
47
|
+
expect(includedResponse.status).toBe(200)
|
|
48
|
+
// Each `sourceToken` keeps its `address`/`amount`; when metadata resolves
|
|
49
|
+
// it is spread alongside. Resolution is best-effort, so a row whose
|
|
50
|
+
// metadata is unavailable simply omits the metadata fields.
|
|
51
|
+
expect(
|
|
52
|
+
included.data.every(
|
|
53
|
+
(entry) =>
|
|
54
|
+
/^0x[0-9a-f]{40}$/.test(entry.sourceToken.address) &&
|
|
55
|
+
/^\d+$/.test(entry.sourceToken.amount) &&
|
|
56
|
+
(entry.sourceToken.symbol === undefined ||
|
|
57
|
+
(typeof entry.sourceToken.symbol === 'string' &&
|
|
58
|
+
Number.isInteger(entry.sourceToken.decimals))),
|
|
59
|
+
),
|
|
60
|
+
).toBe(true)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('narrows transfers to a single token', async () => {
|
|
64
|
+
const client = TestApp.client()
|
|
65
|
+
const response = await client.v1.transfers.$get(
|
|
66
|
+
{ query: { limit: '5', token: TestApp.token } },
|
|
67
|
+
TestApp.auth,
|
|
68
|
+
)
|
|
69
|
+
const body = await TestApp.json(response, Transfers.schema.getTransfers.Response)
|
|
70
|
+
|
|
71
|
+
expect(response.status).toBe(200)
|
|
72
|
+
expect(body.data.every((entry) => entry.sourceToken.address === TestApp.token)).toBe(true)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('narrows transfers by address (either side)', async () => {
|
|
76
|
+
const client = TestApp.client()
|
|
77
|
+
// Seed a real account from a recent transfer.
|
|
78
|
+
const seedResponse = await client.v1.transfers.$get({ query: { limit: '5' } }, TestApp.auth)
|
|
79
|
+
const seed = await TestApp.json(seedResponse, Transfers.schema.getTransfers.Response)
|
|
80
|
+
expect(seedResponse.status).toBe(200)
|
|
81
|
+
const account = seed.data[0]!.sender
|
|
82
|
+
expect(account).toMatch(/^0x[0-9a-f]{40}$/)
|
|
83
|
+
|
|
84
|
+
const filteredResponse = await client.v1.transfers.$get(
|
|
85
|
+
{ query: { limit: '5', address: account } },
|
|
86
|
+
TestApp.auth,
|
|
87
|
+
)
|
|
88
|
+
const filtered = await TestApp.json(filteredResponse, Transfers.schema.getTransfers.Response)
|
|
89
|
+
expect(filteredResponse.status).toBe(200)
|
|
90
|
+
expect(
|
|
91
|
+
filtered.data.every((entry) => entry.sender === account || entry.recipient === account),
|
|
92
|
+
).toBe(true)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('narrows transfers by sender and recipient independently', async () => {
|
|
96
|
+
const client = TestApp.client()
|
|
97
|
+
const seedResponse = await client.v1.transfers.$get({ query: { limit: '5' } }, TestApp.auth)
|
|
98
|
+
const seed = await TestApp.json(seedResponse, Transfers.schema.getTransfers.Response)
|
|
99
|
+
expect(seedResponse.status).toBe(200)
|
|
100
|
+
const { sender, recipient } = seed.data[0]!
|
|
101
|
+
expect(sender).toMatch(/^0x[0-9a-f]{40}$/)
|
|
102
|
+
expect(recipient).toMatch(/^0x[0-9a-f]{40}$/)
|
|
103
|
+
|
|
104
|
+
const bySenderResponse = await client.v1.transfers.$get(
|
|
105
|
+
{ query: { limit: '5', sender } },
|
|
106
|
+
TestApp.auth,
|
|
107
|
+
)
|
|
108
|
+
const bySender = await TestApp.json(bySenderResponse, Transfers.schema.getTransfers.Response)
|
|
109
|
+
expect(bySenderResponse.status).toBe(200)
|
|
110
|
+
expect(bySender.data.every((entry) => entry.sender === sender)).toBe(true)
|
|
111
|
+
|
|
112
|
+
const byRecipientResponse = await client.v1.transfers.$get(
|
|
113
|
+
{ query: { limit: '5', recipient } },
|
|
114
|
+
TestApp.auth,
|
|
115
|
+
)
|
|
116
|
+
const byRecipient = await TestApp.json(
|
|
117
|
+
byRecipientResponse,
|
|
118
|
+
Transfers.schema.getTransfers.Response,
|
|
119
|
+
)
|
|
120
|
+
expect(byRecipientResponse.status).toBe(200)
|
|
121
|
+
expect(byRecipient.data.every((entry) => entry.recipient === recipient)).toBe(true)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('rejects mixing `address` with `sender` or `recipient`', async () => {
|
|
125
|
+
const client = TestApp.client()
|
|
126
|
+
const response = await client.v1.transfers.$get(
|
|
127
|
+
{ query: { address: TestApp.token, sender: TestApp.token } },
|
|
128
|
+
TestApp.auth,
|
|
129
|
+
)
|
|
130
|
+
const body = await TestApp.json(response, Schema.ErrorResponse)
|
|
131
|
+
|
|
132
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
133
|
+
expect(body.error.code).toMatchInlineSnapshot(`"query_invalid"`)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
test('walks the cursor to a disjoint next page', async () => {
|
|
137
|
+
const client = TestApp.client()
|
|
138
|
+
const firstResponse = await client.v1.transfers.$get({ query: { limit: '5' } }, TestApp.auth)
|
|
139
|
+
const first = await TestApp.json(firstResponse, Transfers.schema.getTransfers.Response)
|
|
140
|
+
expect(firstResponse.status).toBe(200)
|
|
141
|
+
if (!first.nextCursor) return
|
|
142
|
+
|
|
143
|
+
const secondResponse = await client.v1.transfers.$get(
|
|
144
|
+
{ query: { limit: '5', cursor: first.nextCursor } },
|
|
145
|
+
TestApp.auth,
|
|
146
|
+
)
|
|
147
|
+
const second = await TestApp.json(secondResponse, Transfers.schema.getTransfers.Response)
|
|
148
|
+
|
|
149
|
+
expect(secondResponse.status).toBe(200)
|
|
150
|
+
expect(second.data.length).toBeGreaterThan(0)
|
|
151
|
+
// Each row's identity on the unscoped feed is `(blockNumber, txHash,
|
|
152
|
+
// sourceToken, sender, recipient, amount)` — a single transaction can
|
|
153
|
+
// emit transfers across multiple contracts, so the per-token feed's
|
|
154
|
+
// `(txHash, blockNumber)` shortcut is not unique here.
|
|
155
|
+
type Entry = z.output<typeof Transfers.schema.getTransfers.Transfer>
|
|
156
|
+
const keyOf = (entry: Entry) =>
|
|
157
|
+
`${entry.blockNumber}:${entry.transactionHash}:${entry.sourceToken.address}:${entry.sender}:${entry.recipient}:${entry.sourceToken.amount}`
|
|
158
|
+
const firstKeys = new Set(first.data.map(keyOf))
|
|
159
|
+
expect(second.data.every((entry) => !firstKeys.has(keyOf(entry)))).toBe(true)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('rejects invalid timestamp bounds', async () => {
|
|
163
|
+
const client = TestApp.client()
|
|
164
|
+
const response = await client.v1.transfers.$get(
|
|
165
|
+
{ query: { 'timestamp.from': 'not-a-timestamp' } },
|
|
166
|
+
TestApp.auth,
|
|
167
|
+
)
|
|
168
|
+
const body = await TestApp.json(response, Schema.ErrorResponse)
|
|
169
|
+
|
|
170
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
171
|
+
expect(body.error.code).toMatchInlineSnapshot(`"query_invalid"`)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
test('rejects invalid pagination', async () => {
|
|
175
|
+
const client = TestApp.client()
|
|
176
|
+
const response = await client.v1.transfers.$get({ query: { limit: '0' } }, TestApp.auth)
|
|
177
|
+
const body = await TestApp.json(response, Schema.ErrorResponse)
|
|
178
|
+
|
|
179
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
180
|
+
expect(body.error.code).toMatchInlineSnapshot(`"query_invalid"`)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('serves a bounded positional page via `page`', async () => {
|
|
184
|
+
const client = TestApp.client()
|
|
185
|
+
// Ascending order anchors the feed at the first indexed transfer, so
|
|
186
|
+
// positional pages are deterministic: the offset page must equal the
|
|
187
|
+
// matching slice of the head page.
|
|
188
|
+
const headResponse = await client.v1.transfers.$get(
|
|
189
|
+
{ query: { limit: '10', order: 'asc' } },
|
|
190
|
+
TestApp.auth,
|
|
191
|
+
)
|
|
192
|
+
const head = await TestApp.json(headResponse, Transfers.schema.getTransfers.Response)
|
|
193
|
+
expect(headResponse.status).toBe(200)
|
|
194
|
+
expect(head.data.length).toBe(10)
|
|
195
|
+
|
|
196
|
+
const offsetResponse = await client.v1.transfers.$get(
|
|
197
|
+
{ query: { limit: '5', order: 'asc', page: '2' } },
|
|
198
|
+
TestApp.auth,
|
|
199
|
+
)
|
|
200
|
+
const page = await TestApp.json(offsetResponse, Transfers.schema.getTransfers.Response)
|
|
201
|
+
expect(offsetResponse.status).toBe(200)
|
|
202
|
+
|
|
203
|
+
type Entry = z.output<typeof Transfers.schema.getTransfers.Transfer>
|
|
204
|
+
const keyOf = (entry: Entry) =>
|
|
205
|
+
`${entry.blockNumber}:${entry.transactionHash}:${entry.sourceToken.address}:${entry.sender}:${entry.recipient}:${entry.sourceToken.amount}`
|
|
206
|
+
expect(page.data.map(keyOf)).toEqual(head.data.slice(5, 10).map(keyOf))
|
|
207
|
+
// Offset pages still return a keyset cursor so clients can switch to deep
|
|
208
|
+
// cursor traversal from a positional jump.
|
|
209
|
+
expect(typeof page.nextCursor).toBe('string')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
test('rejects `page` combined with `cursor`', async () => {
|
|
213
|
+
const client = TestApp.client()
|
|
214
|
+
const seedResponse = await client.v1.transfers.$get({ query: { limit: '5' } }, TestApp.auth)
|
|
215
|
+
const seed = await TestApp.json(seedResponse, Transfers.schema.getTransfers.Response)
|
|
216
|
+
expect(seedResponse.status).toBe(200)
|
|
217
|
+
if (!seed.nextCursor) return
|
|
218
|
+
|
|
219
|
+
const response = await client.v1.transfers.$get(
|
|
220
|
+
{ query: { cursor: seed.nextCursor, page: '2' } },
|
|
221
|
+
TestApp.auth,
|
|
222
|
+
)
|
|
223
|
+
const body = await TestApp.json(response, Schema.ErrorResponse)
|
|
224
|
+
|
|
225
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
226
|
+
expect(body.error.code).toMatchInlineSnapshot(`"query_invalid"`)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
test('rejects a page window beyond the bounded cap', async () => {
|
|
230
|
+
const client = TestApp.client()
|
|
231
|
+
const response = await client.v1.transfers.$get(
|
|
232
|
+
{ query: { limit: '20', page: '501' } },
|
|
233
|
+
TestApp.auth,
|
|
234
|
+
)
|
|
235
|
+
const body = await TestApp.json(response, Schema.ErrorResponse)
|
|
236
|
+
|
|
237
|
+
expect(response.status).toMatchInlineSnapshot(`400`)
|
|
238
|
+
expect(body.error.code).toMatchInlineSnapshot(`"query_invalid"`)
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
test.runIf(Runtime.get().mode === 'testnet')(
|
|
242
|
+
'resolves memo and attribution on demand via include=memo',
|
|
243
|
+
async () => {
|
|
244
|
+
const client = TestApp.client()
|
|
245
|
+
// Real Moderato account that both sends and receives MPP-attributed
|
|
246
|
+
// transfers (memos prefixed with the attribution tag).
|
|
247
|
+
const account = '0xd92087abdc3af63b284b6cf8282061df5f0f7dda'
|
|
248
|
+
const response = await client.v1.transfers.$get(
|
|
249
|
+
{ query: { address: account, include: 'memo', limit: '50' } },
|
|
250
|
+
TestApp.auth,
|
|
251
|
+
)
|
|
252
|
+
const body = await TestApp.json(response, Transfers.schema.getTransfers.Response)
|
|
253
|
+
|
|
254
|
+
expect(response.status).toBe(200)
|
|
255
|
+
// At least one transfer carries a resolved MPP service name; attribution
|
|
256
|
+
// fingerprints are suppressed from the display `memo`, so any present
|
|
257
|
+
// memo is decoded text.
|
|
258
|
+
expect(
|
|
259
|
+
body.data.some((t) => typeof t.attribution === 'string' && t.attribution.length > 0),
|
|
260
|
+
).toBe(true)
|
|
261
|
+
expect(body.data.every((t) => t.memo === undefined || typeof t.memo === 'string')).toBe(true)
|
|
262
|
+
|
|
263
|
+
// Without `include=memo`, the same page omits both fields.
|
|
264
|
+
const bareResponse = await client.v1.transfers.$get(
|
|
265
|
+
{ query: { address: account, limit: '50' } },
|
|
266
|
+
TestApp.auth,
|
|
267
|
+
)
|
|
268
|
+
const bare = await TestApp.json(bareResponse, Transfers.schema.getTransfers.Response)
|
|
269
|
+
expect(bareResponse.status).toBe(200)
|
|
270
|
+
expect(bare.data.every((t) => t.attribution === undefined && t.memo === undefined)).toBe(true)
|
|
271
|
+
},
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
test('embeds a capped total count on demand via include=totalCount', async () => {
|
|
275
|
+
const client = TestApp.client()
|
|
276
|
+
|
|
277
|
+
if (Runtime.get().mode === 'localnet') expect(TestApp.token).toBeDefined()
|
|
278
|
+
|
|
279
|
+
// A token-scoped page: the count is the matched-row total, independent of
|
|
280
|
+
// the page `limit`, and surfaces under `meta` (not the pagination fields).
|
|
281
|
+
const response = await client.v1.transfers.$get(
|
|
282
|
+
{ query: { token: TestApp.token, include: 'totalCount', limit: '5' } },
|
|
283
|
+
TestApp.auth,
|
|
284
|
+
)
|
|
285
|
+
const body = await TestApp.json(response, Transfers.schema.getTransfers.Response)
|
|
286
|
+
|
|
287
|
+
expect(response.status).toBe(200)
|
|
288
|
+
expect(response.headers.get('server-timing')?.includes('transfers_count;dur=')).toBe(true)
|
|
289
|
+
expect(body.meta).toBeDefined()
|
|
290
|
+
expect(Number.isInteger(body.meta?.totalCount)).toBe(true)
|
|
291
|
+
expect(body.meta!.totalCount).toBeGreaterThanOrEqual(body.data.length)
|
|
292
|
+
expect(typeof body.meta?.totalCountCapped).toBe('boolean')
|
|
293
|
+
// The count never exceeds the cap; `totalCountCapped` is set iff the cap was hit.
|
|
294
|
+
expect(body.meta!.totalCount).toBeLessThanOrEqual(Schema.countCap)
|
|
295
|
+
expect(body.meta!.totalCountCapped).toBe(body.meta!.totalCount >= Schema.countCap)
|
|
296
|
+
|
|
297
|
+
// Without `include=totalCount`, the same page omits `meta` entirely and
|
|
298
|
+
// does not run the count query.
|
|
299
|
+
const bareResponse = await client.v1.transfers.$get(
|
|
300
|
+
{ query: { token: TestApp.token, limit: '5' } },
|
|
301
|
+
TestApp.auth,
|
|
302
|
+
)
|
|
303
|
+
const bare = await TestApp.json(bareResponse, Transfers.schema.getTransfers.Response)
|
|
304
|
+
expect(bareResponse.status).toBe(200)
|
|
305
|
+
expect(bare.meta).toBeUndefined()
|
|
306
|
+
expect(bareResponse.headers.get('server-timing')?.includes('transfers_count;dur=')).toBe(false)
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
test.skipIf(Runtime.get().mode !== 'localnet')(
|
|
310
|
+
'folds a cross-token transfer into one row via include=crossToken',
|
|
311
|
+
async () => {
|
|
312
|
+
const crossToken = Runtime.get().fixtures?.crossTokenTransfer
|
|
313
|
+
expect(crossToken).toBeDefined()
|
|
314
|
+
if (!crossToken) return
|
|
315
|
+
|
|
316
|
+
const client = TestApp.client()
|
|
317
|
+
const response = await client.v1.transfers.$get(
|
|
318
|
+
{ query: { address: crossToken.sender, include: 'crossToken', limit: '50' } },
|
|
319
|
+
TestApp.auth,
|
|
320
|
+
)
|
|
321
|
+
const body = await TestApp.json(response, Transfers.schema.getTransfers.Response)
|
|
322
|
+
expect(response.status).toBe(200)
|
|
323
|
+
expect(response.headers.get('server-timing')?.includes('transfers_cross_token;dur=')).toBe(
|
|
324
|
+
true,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
// The transaction's several transfer legs fold into a single row: the
|
|
328
|
+
// token swapped into the DEX becomes `sourceToken`, and the token
|
|
329
|
+
// delivered to the recipient becomes `destinationToken`.
|
|
330
|
+
const folded = body.data.filter((entry) => entry.transactionHash === crossToken.hash)
|
|
331
|
+
expect(folded.length).toBe(1)
|
|
332
|
+
const transfer = folded[0]!
|
|
333
|
+
expect(transfer.sender).toBe(crossToken.sender)
|
|
334
|
+
expect(transfer.recipient).toBe(crossToken.recipient)
|
|
335
|
+
expect(transfer.sourceToken.address).toBe(crossToken.sourceToken)
|
|
336
|
+
expect(transfer.destinationToken?.address).toBe(crossToken.destinationToken)
|
|
337
|
+
|
|
338
|
+
// Without `include=crossToken`, the transaction stays as its raw per-log
|
|
339
|
+
// legs (more than one row) and no row carries `destinationToken`.
|
|
340
|
+
const bareResponse = await client.v1.transfers.$get(
|
|
341
|
+
{ query: { address: crossToken.sender, limit: '50' } },
|
|
342
|
+
TestApp.auth,
|
|
343
|
+
)
|
|
344
|
+
const bare = await TestApp.json(bareResponse, Transfers.schema.getTransfers.Response)
|
|
345
|
+
expect(bareResponse.status).toBe(200)
|
|
346
|
+
expect(
|
|
347
|
+
bare.data.filter((entry) => entry.transactionHash === crossToken.hash).length,
|
|
348
|
+
).toBeGreaterThan(1)
|
|
349
|
+
expect(bare.data.every((entry) => entry.destinationToken === undefined)).toBe(true)
|
|
350
|
+
},
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
test('surfaces a 502 when transfer data is unavailable', async () => {
|
|
354
|
+
// Point at an unreachable indexer so the upstream query fails deterministically.
|
|
355
|
+
const client = TestApp.client({ tidx: { baseUrl: 'http://127.0.0.1:1' } })
|
|
356
|
+
|
|
357
|
+
const response = await client.v1.transfers.$get({ query: {} }, TestApp.auth)
|
|
358
|
+
const body = await TestApp.json(response, Schema.ErrorResponse)
|
|
359
|
+
const { requestId, error } = body
|
|
360
|
+
const { message, ...stableError } = error
|
|
361
|
+
|
|
362
|
+
expect(response.status).toMatchInlineSnapshot(`502`)
|
|
363
|
+
expect(typeof requestId).toMatchInlineSnapshot(`"string"`)
|
|
364
|
+
expect(typeof message).toMatchInlineSnapshot(`"string"`)
|
|
365
|
+
expect(stableError).toMatchInlineSnapshot(`
|
|
366
|
+
{
|
|
367
|
+
"code": "upstream_error",
|
|
368
|
+
}
|
|
369
|
+
`)
|
|
370
|
+
})
|
|
371
|
+
})
|