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.
Files changed (376) hide show
  1. package/dist/App.d.ts +15830 -7220
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +9 -1
  4. package/dist/App.js.map +1 -1
  5. package/dist/Scope.d.ts +4 -0
  6. package/dist/Scope.d.ts.map +1 -1
  7. package/dist/Scope.js +5 -0
  8. package/dist/Scope.js.map +1 -1
  9. package/dist/admin/App.d.ts +1011 -412
  10. package/dist/admin/App.d.ts.map +1 -1
  11. package/dist/admin/App.js +4 -0
  12. package/dist/admin/App.js.map +1 -1
  13. package/dist/admin/apps/api-keys.d.ts +2 -1
  14. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  15. package/dist/admin/apps/early-access.d.ts +148 -0
  16. package/dist/admin/apps/early-access.d.ts.map +1 -0
  17. package/dist/admin/apps/early-access.js +133 -0
  18. package/dist/admin/apps/early-access.js.map +1 -0
  19. package/dist/admin/apps/organizations.d.ts +124 -1
  20. package/dist/admin/apps/organizations.d.ts.map +1 -1
  21. package/dist/admin/apps/organizations.js +97 -6
  22. package/dist/admin/apps/organizations.js.map +1 -1
  23. package/dist/admin/apps/verified-tokens.d.ts +526 -1
  24. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  25. package/dist/admin/apps/verified-tokens.js +214 -1
  26. package/dist/admin/apps/verified-tokens.js.map +1 -1
  27. package/dist/admin/ui.generated.d.ts +1 -1
  28. package/dist/admin/ui.generated.d.ts.map +1 -1
  29. package/dist/admin/ui.generated.js +95 -75
  30. package/dist/admin/ui.generated.js.map +1 -1
  31. package/dist/analytics/Analytics.d.ts.map +1 -1
  32. package/dist/analytics/Analytics.js +20 -0
  33. package/dist/analytics/Analytics.js.map +1 -1
  34. package/dist/analytics/tables/requestEvents.d.ts +18 -0
  35. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  36. package/dist/analytics/tables/requestEvents.js +36 -7
  37. package/dist/analytics/tables/requestEvents.js.map +1 -1
  38. package/dist/apps/data/App.d.ts +6260 -4924
  39. package/dist/apps/data/App.d.ts.map +1 -1
  40. package/dist/apps/data/App.js +11 -6
  41. package/dist/apps/data/App.js.map +1 -1
  42. package/dist/apps/data/FundingQuoteProviders.d.ts +34 -1
  43. package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -1
  44. package/dist/apps/data/FundingQuoteProviders.js +194 -16
  45. package/dist/apps/data/FundingQuoteProviders.js.map +1 -1
  46. package/dist/apps/data/FxOracle.d.ts +71 -0
  47. package/dist/apps/data/FxOracle.d.ts.map +1 -0
  48. package/dist/apps/data/FxOracle.js +97 -0
  49. package/dist/apps/data/FxOracle.js.map +1 -0
  50. package/dist/apps/data/index.d.ts +1 -0
  51. package/dist/apps/data/index.d.ts.map +1 -1
  52. package/dist/apps/data/index.js +1 -0
  53. package/dist/apps/data/index.js.map +1 -1
  54. package/dist/apps/data/routes/activities.d.ts +3599 -1382
  55. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  56. package/dist/apps/data/routes/activities.js +250 -88
  57. package/dist/apps/data/routes/activities.js.map +1 -1
  58. package/dist/apps/data/routes/addresses.d.ts +872 -251
  59. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  60. package/dist/apps/data/routes/addresses.js +11 -9
  61. package/dist/apps/data/routes/addresses.js.map +1 -1
  62. package/dist/apps/data/routes/balances.d.ts +77 -26
  63. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  64. package/dist/apps/data/routes/balances.js +88 -45
  65. package/dist/apps/data/routes/balances.js.map +1 -1
  66. package/dist/apps/data/routes/blocks.d.ts +39 -39
  67. package/dist/apps/data/routes/coingecko.d.ts +54 -54
  68. package/dist/apps/data/routes/exchanges.d.ts +856 -105
  69. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  70. package/dist/apps/data/routes/exchanges.js +518 -76
  71. package/dist/apps/data/routes/exchanges.js.map +1 -1
  72. package/dist/apps/data/routes/fee-amm.d.ts +81 -67
  73. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  74. package/dist/apps/data/routes/fee-amm.js +76 -91
  75. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  76. package/dist/apps/data/routes/funding.d.ts +80 -36
  77. package/dist/apps/data/routes/funding.d.ts.map +1 -1
  78. package/dist/apps/data/routes/funding.js +65 -31
  79. package/dist/apps/data/routes/funding.js.map +1 -1
  80. package/dist/apps/data/routes/receipts.d.ts +392 -315
  81. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  82. package/dist/apps/data/routes/receipts.js +152 -77
  83. package/dist/apps/data/routes/receipts.js.map +1 -1
  84. package/dist/apps/data/routes/tokens.d.ts +167 -174
  85. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  86. package/dist/apps/data/routes/tokens.js +15 -13
  87. package/dist/apps/data/routes/tokens.js.map +1 -1
  88. package/dist/apps/data/routes/transactions.d.ts +277 -536
  89. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  90. package/dist/apps/data/routes/transactions.js +96 -77
  91. package/dist/apps/data/routes/transactions.js.map +1 -1
  92. package/dist/apps/data/routes/transfers.d.ts +157 -81
  93. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  94. package/dist/apps/data/routes/transfers.js +272 -130
  95. package/dist/apps/data/routes/transfers.js.map +1 -1
  96. package/dist/apps/data/routes/valuation.d.ts +307 -0
  97. package/dist/apps/data/routes/valuation.d.ts.map +1 -0
  98. package/dist/apps/data/routes/valuation.js +292 -0
  99. package/dist/apps/data/routes/valuation.js.map +1 -0
  100. package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
  101. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  102. package/dist/apps/data/routes/verified-tokens.js +7 -5
  103. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  104. package/dist/apps/data/routes/webhooks.d.ts +103 -123
  105. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  106. package/dist/apps/data/routes/webhooks.js +124 -25
  107. package/dist/apps/data/routes/webhooks.js.map +1 -1
  108. package/dist/apps/index.d.ts +2 -1
  109. package/dist/apps/index.d.ts.map +1 -1
  110. package/dist/apps/index.js +2 -1
  111. package/dist/apps/index.js.map +1 -1
  112. package/dist/apps/management/App.d.ts +8554 -1692
  113. package/dist/apps/management/App.d.ts.map +1 -1
  114. package/dist/apps/management/App.js +12 -1
  115. package/dist/apps/management/App.js.map +1 -1
  116. package/dist/apps/management/routes/api-keys.d.ts +7 -0
  117. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  118. package/dist/apps/management/routes/api-keys.js +17 -3
  119. package/dist/apps/management/routes/api-keys.js.map +1 -1
  120. package/dist/apps/management/routes/billing.d.ts +157 -162
  121. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  122. package/dist/apps/management/routes/billing.js +31 -23
  123. package/dist/apps/management/routes/billing.js.map +1 -1
  124. package/dist/apps/management/routes/faucet.d.ts +232 -0
  125. package/dist/apps/management/routes/faucet.d.ts.map +1 -0
  126. package/dist/apps/management/routes/faucet.js +154 -0
  127. package/dist/apps/management/routes/faucet.js.map +1 -0
  128. package/dist/apps/management/routes/invitations.d.ts +60 -60
  129. package/dist/apps/management/routes/invite-links.d.ts +49 -20
  130. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  131. package/dist/apps/management/routes/invite-links.js +26 -1
  132. package/dist/apps/management/routes/invite-links.js.map +1 -1
  133. package/dist/apps/management/routes/me.d.ts +6 -6
  134. package/dist/apps/management/routes/members.d.ts +6 -6
  135. package/dist/apps/management/routes/orgs.d.ts +42 -42
  136. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  137. package/dist/apps/management/routes/orgs.js +5 -0
  138. package/dist/apps/management/routes/orgs.js.map +1 -1
  139. package/dist/apps/management/routes/projects.d.ts +44 -44
  140. package/dist/apps/management/routes/usage.d.ts +3 -0
  141. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  142. package/dist/apps/management/routes/usage.js +4 -0
  143. package/dist/apps/management/routes/usage.js.map +1 -1
  144. package/dist/apps/management/routes/verified-token-requests.d.ts +697 -0
  145. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -0
  146. package/dist/apps/management/routes/verified-token-requests.js +271 -0
  147. package/dist/apps/management/routes/verified-token-requests.js.map +1 -0
  148. package/dist/apps/management/routes/webhooks.d.ts +6977 -0
  149. package/dist/apps/management/routes/webhooks.d.ts.map +1 -0
  150. package/dist/apps/management/routes/webhooks.js +573 -0
  151. package/dist/apps/management/routes/webhooks.js.map +1 -0
  152. package/dist/apps/mpp/App.d.ts +363 -0
  153. package/dist/apps/mpp/App.d.ts.map +1 -0
  154. package/dist/apps/mpp/App.js +72 -0
  155. package/dist/apps/mpp/App.js.map +1 -0
  156. package/dist/apps/mpp/Mpp.d.ts +178 -0
  157. package/dist/apps/mpp/Mpp.d.ts.map +1 -0
  158. package/dist/apps/mpp/Mpp.js +183 -0
  159. package/dist/apps/mpp/Mpp.js.map +1 -0
  160. package/dist/apps/mpp/index.d.ts +3 -0
  161. package/dist/apps/mpp/index.d.ts.map +1 -0
  162. package/dist/apps/mpp/index.js +3 -0
  163. package/dist/apps/mpp/index.js.map +1 -0
  164. package/dist/apps/relay/App.d.ts.map +1 -1
  165. package/dist/apps/relay/App.js +56 -9
  166. package/dist/apps/relay/App.js.map +1 -1
  167. package/dist/db/Db.d.ts +6 -0
  168. package/dist/db/Db.d.ts.map +1 -1
  169. package/dist/db/Db.js +110 -0
  170. package/dist/db/Db.js.map +1 -1
  171. package/dist/db/Schema.d.ts +53 -0
  172. package/dist/db/Schema.d.ts.map +1 -1
  173. package/dist/db/Schema.js +56 -0
  174. package/dist/db/Schema.js.map +1 -1
  175. package/dist/db/tables/earlyAccess.d.ts +50 -0
  176. package/dist/db/tables/earlyAccess.d.ts.map +1 -0
  177. package/dist/db/tables/earlyAccess.js +63 -0
  178. package/dist/db/tables/earlyAccess.js.map +1 -0
  179. package/dist/db/tables/enabledBillingSources.d.ts +73 -0
  180. package/dist/db/tables/enabledBillingSources.d.ts.map +1 -0
  181. package/dist/db/tables/enabledBillingSources.js +69 -0
  182. package/dist/db/tables/enabledBillingSources.js.map +1 -0
  183. package/dist/db/tables/invitations.d.ts.map +1 -1
  184. package/dist/db/tables/invitations.js +3 -0
  185. package/dist/db/tables/invitations.js.map +1 -1
  186. package/dist/db/tables/inviteLinks.d.ts +10 -2
  187. package/dist/db/tables/inviteLinks.d.ts.map +1 -1
  188. package/dist/db/tables/inviteLinks.js +10 -1
  189. package/dist/db/tables/inviteLinks.js.map +1 -1
  190. package/dist/db/tables/organizations.d.ts +5 -2
  191. package/dist/db/tables/organizations.d.ts.map +1 -1
  192. package/dist/db/tables/organizations.js +13 -2
  193. package/dist/db/tables/organizations.js.map +1 -1
  194. package/dist/db/tables/sponsoredTransactions.d.ts +2 -0
  195. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  196. package/dist/db/tables/sponsoredTransactions.js +2 -0
  197. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  198. package/dist/db/tables/verifiedTokenRequests.d.ts +94 -0
  199. package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -0
  200. package/dist/db/tables/verifiedTokenRequests.js +120 -0
  201. package/dist/db/tables/verifiedTokenRequests.js.map +1 -0
  202. package/dist/db/tables/webhookSubscriptions.d.ts +14 -0
  203. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  204. package/dist/db/tables/webhookSubscriptions.js +16 -0
  205. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  206. package/dist/handlers/internal/utils.d.ts +1 -16
  207. package/dist/handlers/internal/utils.d.ts.map +1 -1
  208. package/dist/handlers/internal/utils.js +17 -6
  209. package/dist/handlers/internal/utils.js.map +1 -1
  210. package/dist/handlers/relay.d.ts.map +1 -1
  211. package/dist/handlers/relay.js +37 -5
  212. package/dist/handlers/relay.js.map +1 -1
  213. package/dist/internal/Auth.d.ts +11 -2
  214. package/dist/internal/Auth.d.ts.map +1 -1
  215. package/dist/internal/Auth.js +14 -47
  216. package/dist/internal/Auth.js.map +1 -1
  217. package/dist/internal/FundingQuotes.d.ts +147 -47
  218. package/dist/internal/FundingQuotes.d.ts.map +1 -1
  219. package/dist/internal/FundingQuotes.js +119 -33
  220. package/dist/internal/FundingQuotes.js.map +1 -1
  221. package/dist/internal/Log.d.ts +37 -5
  222. package/dist/internal/Log.d.ts.map +1 -1
  223. package/dist/internal/Log.js +52 -3
  224. package/dist/internal/Log.js.map +1 -1
  225. package/dist/internal/MetricSink.d.ts.map +1 -1
  226. package/dist/internal/MetricSink.js +24 -0
  227. package/dist/internal/MetricSink.js.map +1 -1
  228. package/dist/internal/OpenApi.d.ts +2 -2
  229. package/dist/internal/OpenApi.d.ts.map +1 -1
  230. package/dist/internal/OpenApi.js +3 -0
  231. package/dist/internal/OpenApi.js.map +1 -1
  232. package/dist/internal/Response.d.ts +2 -2
  233. package/dist/internal/Response.d.ts.map +1 -1
  234. package/dist/internal/Response.js +12 -4
  235. package/dist/internal/Response.js.map +1 -1
  236. package/dist/internal/Schema.d.ts +14 -5
  237. package/dist/internal/Schema.d.ts.map +1 -1
  238. package/dist/internal/Schema.js +23 -5
  239. package/dist/internal/Schema.js.map +1 -1
  240. package/dist/internal/Value.d.ts +18 -0
  241. package/dist/internal/Value.d.ts.map +1 -1
  242. package/dist/internal/Value.js +11 -1
  243. package/dist/internal/Value.js.map +1 -1
  244. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  245. package/dist/internal/VerifiedTokens.js +10 -1
  246. package/dist/internal/VerifiedTokens.js.map +1 -1
  247. package/dist/internal/Webhooks.d.ts +24 -3
  248. package/dist/internal/Webhooks.d.ts.map +1 -1
  249. package/dist/internal/Webhooks.js +34 -8
  250. package/dist/internal/Webhooks.js.map +1 -1
  251. package/package.json +7 -2
  252. package/src/App.test.ts +9 -4
  253. package/src/App.ts +23 -3
  254. package/src/Client.test-d.ts +733 -20
  255. package/src/Scope.ts +5 -0
  256. package/src/admin/App.test.ts +4 -0
  257. package/src/admin/App.ts +4 -0
  258. package/src/admin/apps/early-access.test.ts +125 -0
  259. package/src/admin/apps/early-access.ts +176 -0
  260. package/src/admin/apps/organizations.test.ts +86 -2
  261. package/src/admin/apps/organizations.ts +155 -31
  262. package/src/admin/apps/scopes.test.ts +5 -0
  263. package/src/admin/apps/verified-tokens.test.ts +201 -0
  264. package/src/admin/apps/verified-tokens.ts +532 -286
  265. package/src/admin/ui/plugin.ts +2 -1
  266. package/src/admin/ui/src/lib/early-access.ts +63 -0
  267. package/src/admin/ui/src/lib/organizations.test.ts +81 -1
  268. package/src/admin/ui/src/lib/organizations.ts +92 -0
  269. package/src/admin/ui/src/lib/verified-tokens.ts +79 -0
  270. package/src/admin/ui/src/routeTree.gen.ts +33 -2
  271. package/src/admin/ui/src/routes/__root.tsx +2 -1
  272. package/src/admin/ui/src/routes/api-keys.tsx +1 -1
  273. package/src/admin/ui/src/routes/early-access.tsx +162 -0
  274. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +103 -0
  275. package/src/admin/ui/src/routes/verified-tokens.tsx +230 -19
  276. package/src/admin/ui.generated.ts +95 -94
  277. package/src/analytics/Analytics.test.ts +83 -0
  278. package/src/analytics/Analytics.ts +20 -0
  279. package/src/analytics/tables/requestEvents.ts +60 -7
  280. package/src/apps/composition.test.ts +11 -2
  281. package/src/apps/data/App.test.ts +1 -1
  282. package/src/apps/data/App.ts +22 -14
  283. package/src/apps/data/FundingQuoteProviders.test.ts +297 -4
  284. package/src/apps/data/FundingQuoteProviders.ts +255 -29
  285. package/src/apps/data/FxOracle.test.ts +118 -0
  286. package/src/apps/data/FxOracle.ts +153 -0
  287. package/src/apps/data/index.ts +1 -0
  288. package/src/apps/data/routes/activities.test.ts +177 -3
  289. package/src/apps/data/routes/activities.ts +441 -132
  290. package/src/apps/data/routes/addresses.ts +19 -9
  291. package/src/apps/data/routes/balances.test.ts +148 -11
  292. package/src/apps/data/routes/balances.ts +140 -51
  293. package/src/apps/data/routes/exchanges.test.ts +544 -9
  294. package/src/apps/data/routes/exchanges.ts +690 -103
  295. package/src/apps/data/routes/fee-amm.test.ts +47 -23
  296. package/src/apps/data/routes/fee-amm.ts +98 -119
  297. package/src/apps/data/routes/funding.test.ts +113 -8
  298. package/src/apps/data/routes/funding.ts +77 -51
  299. package/src/apps/data/routes/receipts.test.ts +129 -23
  300. package/src/apps/data/routes/receipts.ts +205 -100
  301. package/src/apps/data/routes/tokens.test.ts +43 -0
  302. package/src/apps/data/routes/tokens.ts +28 -13
  303. package/src/apps/data/routes/transactions.test.ts +72 -19
  304. package/src/apps/data/routes/transactions.ts +162 -92
  305. package/src/apps/data/routes/transfers.test.ts +341 -31
  306. package/src/apps/data/routes/transfers.ts +358 -158
  307. package/src/apps/data/routes/valuation.test.ts +437 -0
  308. package/src/apps/data/routes/valuation.ts +423 -0
  309. package/src/apps/data/routes/verified-tokens.ts +14 -2
  310. package/src/apps/data/routes/webhooks.test.ts +56 -8
  311. package/src/apps/data/routes/webhooks.ts +144 -27
  312. package/src/apps/index.ts +2 -1
  313. package/src/apps/management/App.ts +13 -0
  314. package/src/apps/management/routes/api-keys.test.ts +14 -0
  315. package/src/apps/management/routes/api-keys.ts +27 -3
  316. package/src/apps/management/routes/billing.test.ts +152 -20
  317. package/src/apps/management/routes/billing.ts +34 -18
  318. package/src/apps/management/routes/faucet.test.ts +87 -0
  319. package/src/apps/management/routes/faucet.ts +201 -0
  320. package/src/apps/management/routes/invite-links.test.ts +117 -0
  321. package/src/apps/management/routes/invite-links.ts +43 -1
  322. package/src/apps/management/routes/me.test.ts +9 -99
  323. package/src/apps/management/routes/orgs.test.ts +45 -2
  324. package/src/apps/management/routes/orgs.ts +6 -0
  325. package/src/apps/management/routes/scopes.test.ts +1 -0
  326. package/src/apps/management/routes/usage.test.ts +6 -0
  327. package/src/apps/management/routes/usage.ts +7 -0
  328. package/src/apps/management/routes/verified-token-requests.test.ts +377 -0
  329. package/src/apps/management/routes/verified-token-requests.ts +397 -0
  330. package/src/apps/management/routes/webhooks.test.ts +426 -0
  331. package/src/apps/management/routes/webhooks.ts +672 -0
  332. package/src/apps/mpp/App.ts +86 -0
  333. package/src/apps/mpp/Mpp.test.ts +193 -0
  334. package/src/apps/mpp/Mpp.ts +353 -0
  335. package/src/apps/mpp/index.ts +2 -0
  336. package/src/apps/mpp/internal/Adapter.ts +11 -0
  337. package/src/apps/mpp/internal/Error.ts +9 -0
  338. package/src/apps/mpp/internal/Idempotency.ts +7 -0
  339. package/src/apps/mpp/internal/Screening.ts +10 -0
  340. package/src/apps/relay/App.test.ts +88 -6
  341. package/src/apps/relay/App.ts +61 -9
  342. package/src/db/Db.test.ts +19 -0
  343. package/src/db/Db.ts +125 -0
  344. package/src/db/Schema.ts +68 -0
  345. package/src/db/tables/earlyAccess.ts +86 -0
  346. package/src/db/tables/enabledBillingSources.test.ts +303 -0
  347. package/src/db/tables/enabledBillingSources.ts +118 -0
  348. package/src/db/tables/invitations.ts +3 -0
  349. package/src/db/tables/inviteLinks.ts +22 -3
  350. package/src/db/tables/organizations.test.ts +103 -0
  351. package/src/db/tables/organizations.ts +18 -2
  352. package/src/db/tables/sponsoredTransactions.ts +4 -0
  353. package/src/db/tables/verifiedTokenRequests.test.ts +200 -0
  354. package/src/db/tables/verifiedTokenRequests.ts +182 -0
  355. package/src/db/tables/webhookSubscriptions.ts +31 -0
  356. package/src/handlers/internal/utils.ts +22 -6
  357. package/src/handlers/relay.errors.test.ts +153 -0
  358. package/src/handlers/relay.ts +42 -7
  359. package/src/internal/Auth.test.ts +3 -3
  360. package/src/internal/Auth.ts +15 -47
  361. package/src/internal/FundingQuotes.test.ts +161 -6
  362. package/src/internal/FundingQuotes.ts +141 -39
  363. package/src/internal/Log.test-d.ts +21 -0
  364. package/src/internal/Log.test.ts +141 -0
  365. package/src/internal/Log.ts +93 -6
  366. package/src/internal/MetricSink.test.ts +215 -0
  367. package/src/internal/MetricSink.ts +24 -0
  368. package/src/internal/OpenApi.ts +3 -0
  369. package/src/internal/Response.test.ts +28 -0
  370. package/src/internal/Response.ts +12 -4
  371. package/src/internal/Schema.ts +50 -5
  372. package/src/internal/Value.test.ts +20 -0
  373. package/src/internal/Value.ts +24 -1
  374. package/src/internal/VerifiedTokens.ts +9 -1
  375. package/src/internal/Webhooks.test.ts +140 -0
  376. package/src/internal/Webhooks.ts +53 -9
@@ -5,9 +5,11 @@ import type * as App from '../../../App.js'
5
5
  import * as Auth from '../../../internal/Auth.js'
6
6
  import * as Cache from '../../../internal/Cache.js'
7
7
  import * as FundingQuotes from '../../../internal/FundingQuotes.js'
8
+ import type * as Log from '../../../internal/Log.js'
8
9
  import * as OpenApi from '../../../internal/OpenApi.js'
9
10
  import * as Response from '../../../internal/Response.js'
10
11
  import * as Schema from '../../../internal/Schema.js'
12
+ import * as Value from '../../../internal/Value.js'
11
13
  import * as FundingQuoteProviders from '../FundingQuoteProviders.js'
12
14
 
13
15
  /** Zod schemas owned by funding quote resources. */
@@ -57,6 +59,12 @@ export namespace schema {
57
59
  z.describe('Contract address, mint, or issuer address on the token chain.'),
58
60
  z.meta({ examples: ['0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'] }),
59
61
  ),
62
+ currency: z
63
+ .string()
64
+ .check(
65
+ z.describe('Monetary denomination represented by this token.'),
66
+ z.meta({ examples: ['USD'] }),
67
+ ),
60
68
  decimals: z
61
69
  .number()
62
70
  .check(
@@ -96,29 +104,17 @@ export namespace schema {
96
104
  'A normalized token reference for funding quotes.',
97
105
  )
98
106
 
99
- /** Source amount echoed by a funding quote response. */
107
+ /** Self-contained source or destination amount in a funding quote. */
100
108
  export const TokenAmount = Schema.describe(
101
- z.object({
102
- amount: Schema.DecimalString.check(
103
- z.describe("The requested source amount in the token's smallest unit."),
104
- ),
105
- formatted: z
106
- .string()
107
- .check(
108
- z.describe(
109
- 'The same amount in human-readable decimal form, using the source token’s `decimals`.',
110
- ),
111
- z.meta({ examples: ['1'] }),
112
- ),
113
- }),
114
- 'The requested source amount in provider-safe base units and display form.',
109
+ Schema.TokenAmount,
110
+ 'A funding amount in base units and human-readable form.',
115
111
  )
116
112
 
117
113
  /** Provider summary embedded in a funding quote. */
118
114
  export const ProviderRef = Schema.describe(
119
115
  z.object({
120
116
  id: z
121
- .enum(['across', 'relay', 'rhino', 'squid'])
117
+ .enum(['across', 'relay', 'rhino', 'squid', 'symbiosis'])
122
118
  .check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
123
119
  kind: z
124
120
  .string()
@@ -170,7 +166,7 @@ export namespace schema {
170
166
  'Machine-readable liquidity, fee, and source signals for a successful quote.',
171
167
  )
172
168
 
173
- /** Provider-derived output, limits, and freshness data. */
169
+ /** Provider quote freshness data. */
174
170
  export const QuoteDetails = Schema.describe(
175
171
  z.object({
176
172
  expiresAt: z
@@ -179,29 +175,6 @@ export namespace schema {
179
175
  z.describe('Timestamp after which the provider quote is no longer valid.'),
180
176
  z.meta({ examples: ['2026-01-01T00:01:00Z'] }),
181
177
  ),
182
- inputAmount: Schema.DecimalString.check(
183
- z.describe('Source amount sent to the provider in base units.'),
184
- z.meta({ examples: ['1000000'] }),
185
- ),
186
- minimumOutputAmount: z
187
- .optional(Schema.DecimalString)
188
- .check(
189
- z.describe('Slippage-adjusted minimum destination amount in base units.'),
190
- z.meta({ examples: ['988000'] }),
191
- ),
192
- outputAmount: z
193
- .string()
194
- .check(z.regex(/^\d+$/))
195
- .check(
196
- z.describe('Expected destination amount in base units.'),
197
- z.meta({ examples: ['989102'] }),
198
- ),
199
- outputAmountFormatted: z
200
- .string()
201
- .check(
202
- z.describe('Expected destination amount rendered with destination token decimals.'),
203
- z.meta({ examples: ['0.989102'] }),
204
- ),
205
178
  sampledAt: z.iso
206
179
  .datetime()
207
180
  .check(
@@ -209,12 +182,20 @@ export namespace schema {
209
182
  z.meta({ examples: ['2026-01-01T00:00:00Z'] }),
210
183
  ),
211
184
  }),
212
- 'Provider-derived output, limits, and freshness data for a funding quote.',
185
+ 'Freshness data for a provider funding quote.',
213
186
  )
214
187
 
215
188
  /** Successful live funding quote. */
216
189
  export const FundingQuote = Schema.describe(
217
190
  z.object({
191
+ destinationAmount: TokenAmount.check(z.describe('Expected destination amount.')),
192
+ destinationAmountMin: z
193
+ .optional(TokenAmount)
194
+ .check(
195
+ z.describe(
196
+ 'Provider-derived minimum destination amount. Symbiosis and Squid quotes use a fixed 1% slippage tolerance.',
197
+ ),
198
+ ),
218
199
  destinationChain: Chain.check(z.describe('Destination chain, always Tempo mainnet in V1.')),
219
200
  destinationToken: Token.check(z.describe('Tempo token expected from this quote.')),
220
201
  id: z
@@ -237,7 +218,7 @@ export namespace schema {
237
218
  export const Provider = Schema.describe(
238
219
  z.object({
239
220
  id: z
240
- .enum(['across', 'relay', 'rhino', 'squid'])
221
+ .enum(['across', 'relay', 'rhino', 'squid', 'symbiosis'])
241
222
  .check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
242
223
  kind: z
243
224
  .string()
@@ -285,10 +266,10 @@ export namespace schema {
285
266
  z.meta({ examples: ['USDC.e'] }),
286
267
  ),
287
268
  provider: z
288
- .optional(z.enum(['across', 'relay', 'rhino', 'squid']))
269
+ .optional(z.enum(['across', 'relay', 'rhino', 'squid', 'symbiosis']))
289
270
  .check(
290
271
  z.describe(
291
- 'Only request a quote from this provider. Supported ids are `across`, `relay`, `rhino`, and `squid`; omit it to query every configured provider.',
272
+ 'Only request a quote from this provider. Supported ids are `across`, `relay`, `rhino`, `squid`, and `symbiosis`; omit it to query every configured provider.',
292
273
  ),
293
274
  z.meta({ examples: ['relay'] }),
294
275
  ),
@@ -374,7 +355,20 @@ const fundingQuoteResponseExample = (() => {
374
355
  return {
375
356
  data: [
376
357
  {
377
- ...candidate,
358
+ destinationAmount: Value.tokenAmount({
359
+ baseUnits: '979295',
360
+ currency: candidate.destinationToken.currency,
361
+ decimals: candidate.destinationToken.decimals,
362
+ }),
363
+ destinationAmountMin: Value.tokenAmount({
364
+ baseUnits: '939242',
365
+ currency: candidate.destinationToken.currency,
366
+ decimals: candidate.destinationToken.decimals,
367
+ }),
368
+ destinationChain: candidate.destinationChain,
369
+ destinationToken: candidate.destinationToken,
370
+ id: candidate.id,
371
+ provider: candidate.provider,
378
372
  quality: {
379
373
  estimatedSeconds: 1,
380
374
  liquiditySource: 'providerQuote',
@@ -382,12 +376,15 @@ const fundingQuoteResponseExample = (() => {
382
376
  tier: 'liquid',
383
377
  },
384
378
  quote: {
385
- inputAmount: '1000000',
386
- minimumOutputAmount: '939242',
387
- outputAmount: '979295',
388
- outputAmountFormatted: '0.979295',
389
379
  sampledAt: '2026-01-01T00:00:00.000Z',
390
380
  },
381
+ sourceAmount: Value.tokenAmount({
382
+ baseUnits: candidate.sourceAmount.amount,
383
+ currency: candidate.sourceToken.currency,
384
+ decimals: candidate.sourceToken.decimals,
385
+ }),
386
+ sourceChain: candidate.sourceChain,
387
+ sourceToken: candidate.sourceToken,
391
388
  },
392
389
  ],
393
390
  }
@@ -416,7 +413,7 @@ export function funding(options: funding.Options = {}) {
416
413
  }),
417
414
  OpenApi.describeRoute({
418
415
  description:
419
- 'Returns live quotes for funding Tempo with a stablecoin. Omit `provider` to query all configured providers. This endpoint does not execute a transfer.',
416
+ 'Returns live quotes for funding Tempo with a stablecoin. Omit `provider` to query all configured providers. Provider minimums can use provider-specific slippage policies; Symbiosis and Squid use 1%. This endpoint does not execute a transfer.',
420
417
  operationId: 'quoteFunding',
421
418
  responses: OpenApi.responses({
422
419
  errors: {
@@ -445,6 +442,7 @@ export function funding(options: funding.Options = {}) {
445
442
  })
446
443
 
447
444
  const query = c.req.valid('query')
445
+ const attempts: FundingQuotes.ProviderAttempt[] = []
448
446
  try {
449
447
  c.header('Cache-Control', 'no-store')
450
448
  return c.json(
@@ -454,6 +452,7 @@ export function funding(options: funding.Options = {}) {
454
452
  adapterTimeoutMs: options.adapterTimeoutMs,
455
453
  cache: { bypass: cacheBypass(c.req.raw) },
456
454
  destinationToken: query.destinationToken,
455
+ onAttempt: (attempt) => attempts.push(attempt),
457
456
  provider: query.provider,
458
457
  sourceAmount: query.sourceAmount,
459
458
  sourceAmountUnits: query.sourceAmountUnits,
@@ -478,6 +477,9 @@ export function funding(options: funding.Options = {}) {
478
477
  })
479
478
  }
480
479
  throw cause
480
+ } finally {
481
+ if (attempts.length > 0)
482
+ c.set('fundingProviderAttempts', attempts.map(fundingProviderAttempt))
481
483
  }
482
484
  },
483
485
  )
@@ -500,7 +502,7 @@ export function funding(options: funding.Options = {}) {
500
502
  }),
501
503
  Cache.response<App.Environment>({
502
504
  cacheControl: Cache.policies.stable,
503
- name: 'tempo-api:funding-chains:v1',
505
+ name: 'tempo-api:funding-chains:v2',
504
506
  key: (c) => c.req.url,
505
507
  }),
506
508
  (c) => {
@@ -557,6 +559,30 @@ export declare namespace funding {
557
559
  }
558
560
  }
559
561
 
562
+ function fundingProviderAttempt(
563
+ attempt: FundingQuotes.ProviderAttempt,
564
+ ): Log.FundingProviderAttempt {
565
+ const operation = FundingQuoteProviders.providerOperation(attempt.provider)
566
+ if (attempt.outcome !== 'failed')
567
+ return {
568
+ durationMs: attempt.durationMs,
569
+ id: attempt.provider,
570
+ operation,
571
+ outcome: attempt.outcome,
572
+ }
573
+
574
+ return {
575
+ durationMs: attempt.durationMs,
576
+ failure: FundingQuoteProviders.providerFailure({
577
+ cause: attempt.cause,
578
+ provider: attempt.provider,
579
+ }).failure,
580
+ id: attempt.provider,
581
+ operation,
582
+ outcome: attempt.outcome,
583
+ }
584
+ }
585
+
560
586
  // Maps caller-input errors to a specific 400 message; anything else rethrows.
561
587
  function requestErrorMessage(cause: unknown) {
562
588
  if (cause instanceof FundingQuotes.InvalidAmountError) return 'Invalid `sourceAmount`.'
@@ -1,5 +1,6 @@
1
1
  import { Schema } from 'tapimo'
2
- import { Hex } from 'ox'
2
+ import { FxOracle } from 'tapimo/apps'
3
+ import { Hex, Value as core_Value } from 'ox'
3
4
  import { zeroHash } from 'viem'
4
5
 
5
6
  import * as TestApp from '../../../../test/App.js'
@@ -7,6 +8,16 @@ import * as Runtime from '../../../../test/runtime.js'
7
8
  import * as Viem from '../../../../test/Viem.js'
8
9
  import * as Receipts from './receipts.js'
9
10
 
11
+ // Deterministic EUR-based rate set so conversion math is exact in assertions.
12
+ const fixed = FxOracle.from({
13
+ name: 'fixed',
14
+ rates: async () => ({
15
+ asOf: '2026-01-01T00:00:00.000Z',
16
+ base: 'EUR',
17
+ rates: { AUD: '1.6', USD: '1.0' },
18
+ }),
19
+ })
20
+
10
21
  /** The decoded `type` names a humanized receipt may report. */
11
22
  const transactionTypes = ['legacy', 'eip2930', 'eip1559', 'eip4844', 'eip7702', 'tempo', 'unknown']
12
23
 
@@ -40,28 +51,44 @@ describe('GET /transactions/:transactionHash/receipt', () => {
40
51
  expect(typeof body.gasUsed).toBe('number')
41
52
  expect(Array.isArray(body.logs)).toBe(true)
42
53
  // `feeAmount` is the fee charged to the fee payer, derived as
43
- // ceil(gasUsed * effectiveGasPrice / 1e12), in the fee token base units.
44
- expect(body.feeAmount).toMatch(/^\d+$/)
54
+ // ceil(gasUsed * effectiveGasPrice / 1e12), in USD base units.
45
55
  const expectedFee =
46
56
  (BigInt(body.gasUsed) * BigInt(body.effectiveGasPrice) + 10n ** 12n - 1n) / 10n ** 12n
47
- expect(body.feeAmount).toBe(expectedFee.toString())
48
- // Fee-token metadata is opt-in: the base response must not embed it.
49
- expect(body.meta.feeToken).toBeUndefined()
57
+ expect(body.feeAmount.baseUnits).toBe(expectedFee.toString())
58
+ expect(body.feeAmount.currency).toBe('USD')
59
+ expect(body.feeAmount.decimals).toBe(6)
60
+ expect(body.feeAmount.formatted).toMatch(/^\d+(\.\d+)?$/)
61
+ // Core fee-token metadata is present by default while the raw address stays
62
+ // under `meta.rpc`. Curated fields remain opt-in.
63
+ if (body.meta.rpc.feeToken) {
64
+ expect(body.feeToken?.address).toBe(body.meta.rpc.feeToken)
65
+ expect(typeof body.feeToken?.currency).toBe('string')
66
+ expect(typeof body.feeToken?.decimals).toBe('number')
67
+ expect(typeof body.feeToken?.name).toBe('string')
68
+ expect(typeof body.feeToken?.symbol).toBe('string')
69
+ expect(body.feeToken?.logoUri).toBeUndefined()
70
+ expect(body.feeToken?.verified).toBeUndefined()
71
+ } else expect(body.feeToken).toBeUndefined()
72
+ expect(body.meta).not.toHaveProperty('feeToken')
50
73
  // The verbatim JSON-RPC receipt is always available under `meta.rpc`, where
51
74
  // `status` is the raw `0x1`/`0x0` flag and gas values stay hex-encoded.
52
75
  expect(['0x0', '0x1']).toContain(body.meta.rpc.status)
53
76
  expect(body.meta.rpc.gasUsed).toMatch(/^0x[0-9a-f]+$/)
54
77
 
55
- // include=feeToken: resolved metadata is embedded under meta (best-effort).
78
+ // Curated fee-token fields are opt-in on the top-level reference.
56
79
  const includedResponse = await client.v1.transactions[':transactionHash'].receipt.$get(
57
- { param: { transactionHash: transactionHash! }, query: { include: 'feeToken' } },
80
+ {
81
+ param: { transactionHash: transactionHash! },
82
+ query: { include: 'feeToken.logoUri,feeToken.verified' },
83
+ },
58
84
  TestApp.auth,
59
85
  )
60
86
  const includedBody = await TestApp.json(includedResponse, Receipts.schema.getReceipt.Response)
61
87
  expect(includedResponse.status).toBe(200)
62
- if (includedBody.feeToken && includedBody.meta?.feeToken) {
63
- expect(includedBody.meta.feeToken.address).toBe(includedBody.feeToken)
64
- expect(typeof includedBody.meta.feeToken.symbol).toBe('string')
88
+ if (includedBody.feeToken) {
89
+ expect(includedBody.feeToken.address).toBe(includedBody.meta.rpc.feeToken)
90
+ expect(typeof includedBody.feeToken.verified).toBe('boolean')
91
+ if (includedBody.feeToken.logoUri) expect(typeof includedBody.feeToken.logoUri).toBe('string')
65
92
  }
66
93
  })
67
94
 
@@ -90,7 +117,7 @@ describe('GET /transactions/:transactionHash/receipt', () => {
90
117
  })
91
118
 
92
119
  describe('GET /transactions/receipts', () => {
93
- test('returns a humanized receipt page, embedding fee tokens on demand', async () => {
120
+ test('returns a humanized receipt page with fee-token references', async () => {
94
121
  const client = TestApp.client()
95
122
  const response = await client.v1.transactions.receipts.$get(
96
123
  { query: { limit: '5' } },
@@ -105,6 +132,17 @@ describe('GET /transactions/receipts', () => {
105
132
  expect(body.nextCursor === null || typeof body.nextCursor === 'string').toBe(true)
106
133
  expect(body.data.length).toBeLessThanOrEqual(5)
107
134
 
135
+ if (body.nextCursor) {
136
+ const cursorResponse = await client.v1.transactions.receipts.$get(
137
+ { query: { cursor: body.nextCursor, limit: '5' } },
138
+ TestApp.auth,
139
+ )
140
+ expect(cursorResponse.status).toBe(200)
141
+ expect(cursorResponse.headers.get('cache-control')).toMatchInlineSnapshot(
142
+ `"private, max-age=60, stale-while-revalidate=300"`,
143
+ )
144
+ }
145
+
108
146
  if (body.data.length > 0) {
109
147
  const [receipt] = body.data
110
148
  // List rows reuse the detail endpoint's humanized shape: decoded
@@ -115,23 +153,35 @@ describe('GET /transactions/receipts', () => {
115
153
  expect(['success', 'reverted']).toContain(receipt!.status)
116
154
  expect(transactionTypes).toContain(receipt!.type)
117
155
  expect(typeof receipt!.gasUsed).toBe('number')
118
- expect(receipt!.feeAmount).toMatch(/^\d+$/)
156
+ expect(receipt!.feeAmount.baseUnits).toMatch(/^\d+$/)
157
+ expect(receipt!.feeAmount.currency).toBe('USD')
158
+ expect(receipt!.feeAmount.decimals).toBe(6)
159
+ expect(receipt!.feeAmount.formatted).toMatch(/^\d+(\.\d+)?$/)
119
160
  expect(receipt!.meta.rpc.status).toMatch(/^0x[0-9a-f]+$/)
120
- // Fee-token metadata is opt-in: the base response must not embed it.
121
- expect(receipt!.meta.feeToken).toBeUndefined()
161
+ if (receipt!.meta.rpc.feeToken) {
162
+ expect(receipt!.feeToken?.address).toBe(receipt!.meta.rpc.feeToken)
163
+ expect(typeof receipt!.feeToken?.currency).toBe('string')
164
+ expect(typeof receipt!.feeToken?.decimals).toBe('number')
165
+ expect(typeof receipt!.feeToken?.name).toBe('string')
166
+ expect(typeof receipt!.feeToken?.symbol).toBe('string')
167
+ expect(receipt!.feeToken?.logoUri).toBeUndefined()
168
+ expect(receipt!.feeToken?.verified).toBeUndefined()
169
+ } else expect(receipt!.feeToken).toBeUndefined()
170
+ expect(receipt!.meta).not.toHaveProperty('feeToken')
122
171
  }
123
172
 
124
173
  const includedResponse = await client.v1.transactions.receipts.$get(
125
- { query: { limit: '5', include: 'feeToken' } },
174
+ { query: { limit: '5', include: 'feeToken.logoUri,feeToken.verified' } },
126
175
  TestApp.auth,
127
176
  )
128
177
  const includedBody = await TestApp.json(includedResponse, Receipts.schema.getReceipts.Response)
129
178
  expect(includedResponse.status).toBe(200)
130
- const withFeeToken = includedBody.data.find((receipt) => receipt.meta?.feeToken)
179
+ const withFeeToken = includedBody.data.find((receipt) => receipt.feeToken)
131
180
  if (withFeeToken) {
132
- // When metadata resolves, it must describe the receipt's fee token.
133
- expect(withFeeToken.meta.feeToken!.address).toBe(withFeeToken.feeToken)
134
- expect(typeof withFeeToken.meta.feeToken!.symbol).toBe('string')
181
+ expect(withFeeToken.feeToken!.address).toBe(withFeeToken.meta.rpc.feeToken)
182
+ expect(typeof withFeeToken.feeToken!.verified).toBe('boolean')
183
+ if (withFeeToken.feeToken!.logoUri)
184
+ expect(typeof withFeeToken.feeToken!.logoUri).toBe('string')
135
185
  }
136
186
  })
137
187
 
@@ -149,10 +199,39 @@ describe('GET /transactions/receipts', () => {
149
199
  expect(body.error.code).toBe('query_invalid')
150
200
  })
151
201
 
202
+ test('values the fee in a requested denomination', async () => {
203
+ expect(transactionHash).toBeDefined()
204
+ const client = TestApp.client({ fx: { oracle: fixed } })
205
+
206
+ // Denominations are case-insensitive.
207
+ const response = await client.v1.transactions[':transactionHash'].receipt.$get(
208
+ { param: { transactionHash: transactionHash! }, query: { denomination: 'aud' } },
209
+ TestApp.auth,
210
+ )
211
+ const body = await TestApp.json(response, Receipts.schema.getReceipt.Response)
212
+
213
+ expect(response.status).toBe(200)
214
+ expect(response.headers.get('cache-control')).toMatchInlineSnapshot(
215
+ `"private, max-age=60, stale-while-revalidate=300"`,
216
+ )
217
+ // USD -> AUD at the fixed 1.6 cross rate, floored to 6 dp.
218
+ expect(body.feeAmount.valuation).toEqual({
219
+ amount: core_Value.format((BigInt(body.feeAmount.baseUnits) * 16n) / 10n, 6),
220
+ currency: 'AUD',
221
+ })
222
+ expect(body.meta.pricing).toMatchInlineSnapshot(`
223
+ {
224
+ "asOf": "2026-01-01T00:00:00.000Z",
225
+ "basis": "nominal",
226
+ "source": "fixed",
227
+ }
228
+ `)
229
+ })
230
+
152
231
  test('rejects the transactions-only include=receipt member', async () => {
153
232
  // `receipt` is a transactions-list embed; the receipts endpoints own their
154
- // own `include` enum (`feeToken` only) and must reject it. The typed client
155
- // would refuse the literal, so exercise the validator via `app.request`.
233
+ // own include enum and must reject it. The typed client would refuse the
234
+ // literal, so exercise the validator via `app.request`.
156
235
  const response = await TestApp.create().request('/v1/transactions/receipts?include=receipt', {
157
236
  headers: { authorization: `Bearer ${TestApp.key.token}` },
158
237
  })
@@ -161,6 +240,25 @@ describe('GET /transactions/receipts', () => {
161
240
  expect(body.error.code).toBe('query_invalid')
162
241
  })
163
242
 
243
+ test('rejects the legacy include=feeToken member', async () => {
244
+ const response = await TestApp.create().request('/v1/transactions/receipts?include=feeToken', {
245
+ headers: { authorization: `Bearer ${TestApp.key.token}` },
246
+ })
247
+ const body = await TestApp.json(response, Schema.ErrorResponse)
248
+ expect(response.status).toBe(400)
249
+ expect(body.error.code).toBe('query_invalid')
250
+ })
251
+
252
+ test('rejects generic token fields', async () => {
253
+ const response = await TestApp.create().request(
254
+ '/v1/transactions/receipts?include=token.logoUri',
255
+ { headers: { authorization: `Bearer ${TestApp.key.token}` } },
256
+ )
257
+ const body = await TestApp.json(response, Schema.ErrorResponse)
258
+ expect(response.status).toBe(400)
259
+ expect(body.error.code).toBe('query_invalid')
260
+ })
261
+
164
262
  test('narrows receipts by execution status', async () => {
165
263
  const client = TestApp.client()
166
264
  const response = await client.v1.transactions.receipts.$get(
@@ -193,7 +291,15 @@ describe('GET /transactions/receipts', () => {
193
291
  expect(Number.isInteger(body.meta?.totalCount)).toBe(true)
194
292
  expect(body.meta!.totalCount).toBeGreaterThanOrEqual(body.data.length)
195
293
  expect(body.meta!.totalCount).toBeLessThanOrEqual(Schema.countCap)
196
- expect(body.meta!.totalCountCapped).toBe(body.meta!.totalCount >= Schema.countCap)
294
+ expect(body.meta!.totalCountCapped).toBe(body.meta!.totalCount! >= Schema.countCap)
295
+ // Fees are USD, so the default denomination values them at identity with
296
+ // no rate provenance.
297
+ for (const receipt of body.data)
298
+ expect(receipt.feeAmount.valuation).toEqual({
299
+ amount: receipt.feeAmount.formatted,
300
+ currency: 'USD',
301
+ })
302
+ expect(body.meta!.pricing).toBeUndefined()
197
303
 
198
304
  // Without `include=totalCount`, the same page omits `meta` and the count.
199
305
  const bare = await client.v1.transactions.receipts.$get(