tapimo 0.7.0 → 0.7.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.
Files changed (689) hide show
  1. package/dist/ApiKeys.d.ts +24 -7
  2. package/dist/ApiKeys.d.ts.map +1 -1
  3. package/dist/ApiKeys.js +17 -5
  4. package/dist/ApiKeys.js.map +1 -1
  5. package/dist/App.d.ts +12104 -7861
  6. package/dist/App.d.ts.map +1 -1
  7. package/dist/App.js +191 -128
  8. package/dist/App.js.map +1 -1
  9. package/dist/Assets.d.ts +10 -0
  10. package/dist/Assets.d.ts.map +1 -1
  11. package/dist/Assets.js +17 -4
  12. package/dist/Assets.js.map +1 -1
  13. package/dist/Scope.d.ts +19 -8
  14. package/dist/Scope.d.ts.map +1 -1
  15. package/dist/Scope.js +25 -9
  16. package/dist/Scope.js.map +1 -1
  17. package/dist/Webhooks.d.ts +1 -1
  18. package/dist/admin/App.d.ts +601 -20
  19. package/dist/admin/App.d.ts.map +1 -1
  20. package/dist/admin/App.js +12 -2
  21. package/dist/admin/App.js.map +1 -1
  22. package/dist/admin/apps/api-keys.d.ts +94 -11
  23. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.js +141 -32
  25. package/dist/admin/apps/api-keys.js.map +1 -1
  26. package/dist/admin/apps/earn-vaults.d.ts +1069 -0
  27. package/dist/admin/apps/earn-vaults.d.ts.map +1 -0
  28. package/dist/admin/apps/earn-vaults.js +409 -0
  29. package/dist/admin/apps/earn-vaults.js.map +1 -0
  30. package/dist/admin/apps/verified-tokens.d.ts +166 -166
  31. package/dist/admin/ui.generated.d.ts +1 -1
  32. package/dist/admin/ui.generated.d.ts.map +1 -1
  33. package/dist/admin/ui.generated.js +151 -95
  34. package/dist/admin/ui.generated.js.map +1 -1
  35. package/dist/analytics/Analytics.d.ts +2 -0
  36. package/dist/analytics/Analytics.d.ts.map +1 -1
  37. package/dist/analytics/Analytics.js +18 -2
  38. package/dist/analytics/Analytics.js.map +1 -1
  39. package/dist/analytics/tables/requestEvents.d.ts +22 -1
  40. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  41. package/dist/analytics/tables/requestEvents.js +59 -39
  42. package/dist/analytics/tables/requestEvents.js.map +1 -1
  43. package/dist/apps/Zones.d.ts +8335 -0
  44. package/dist/apps/Zones.d.ts.map +1 -0
  45. package/dist/apps/Zones.js +38 -0
  46. package/dist/apps/Zones.js.map +1 -0
  47. package/dist/apps/data/App.d.ts +14377 -10165
  48. package/dist/apps/data/App.d.ts.map +1 -1
  49. package/dist/apps/data/App.js +91 -19
  50. package/dist/apps/data/App.js.map +1 -1
  51. package/dist/apps/data/FxOracle.d.ts +1 -1
  52. package/dist/apps/data/FxOracle.d.ts.map +1 -1
  53. package/dist/apps/data/index.d.ts +0 -1
  54. package/dist/apps/data/index.d.ts.map +1 -1
  55. package/dist/apps/data/index.js +0 -1
  56. package/dist/apps/data/index.js.map +1 -1
  57. package/dist/apps/data/routes/activities.d.ts +32 -32
  58. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  59. package/dist/apps/data/routes/activities.js +130 -65
  60. package/dist/apps/data/routes/activities.js.map +1 -1
  61. package/dist/apps/data/routes/addresses.d.ts +312 -312
  62. package/dist/apps/data/routes/balances.d.ts +18 -18
  63. package/dist/apps/data/routes/balances.js +5 -5
  64. package/dist/apps/data/routes/balances.js.map +1 -1
  65. package/dist/apps/data/routes/coingecko.d.ts +176 -176
  66. package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
  67. package/dist/apps/data/routes/coingecko.js +62 -35
  68. package/dist/apps/data/routes/coingecko.js.map +1 -1
  69. package/dist/apps/data/routes/earn.d.ts +2144 -0
  70. package/dist/apps/data/routes/earn.d.ts.map +1 -0
  71. package/dist/apps/data/routes/earn.js +947 -0
  72. package/dist/apps/data/routes/earn.js.map +1 -0
  73. package/dist/apps/data/routes/exchanges.d.ts +1231 -324
  74. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  75. package/dist/apps/data/routes/exchanges.js +656 -193
  76. package/dist/apps/data/routes/exchanges.js.map +1 -1
  77. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  78. package/dist/apps/data/routes/fee-amm.js +59 -8
  79. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  80. package/dist/apps/data/routes/funding.d.ts +4092 -387
  81. package/dist/apps/data/routes/funding.d.ts.map +1 -1
  82. package/dist/apps/data/routes/funding.js +1403 -256
  83. package/dist/apps/data/routes/funding.js.map +1 -1
  84. package/dist/apps/data/routes/indexer.d.ts +5 -5
  85. package/dist/apps/data/routes/indexer.d.ts.map +1 -1
  86. package/dist/apps/data/routes/indexer.js +19 -2
  87. package/dist/apps/data/routes/indexer.js.map +1 -1
  88. package/dist/apps/data/routes/receipts.d.ts +265 -265
  89. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  90. package/dist/apps/data/routes/receipts.js +11 -11
  91. package/dist/apps/data/routes/receipts.js.map +1 -1
  92. package/dist/apps/data/routes/rpc.d.ts +5 -5
  93. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  94. package/dist/apps/data/routes/rpc.js +211 -22
  95. package/dist/apps/data/routes/rpc.js.map +1 -1
  96. package/dist/apps/data/routes/tokenlist.d.ts +36 -36
  97. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  98. package/dist/apps/data/routes/tokenlist.js +49 -9
  99. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  100. package/dist/apps/data/routes/tokens.d.ts +116 -88
  101. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  102. package/dist/apps/data/routes/tokens.js +198 -91
  103. package/dist/apps/data/routes/tokens.js.map +1 -1
  104. package/dist/apps/data/routes/transactions.d.ts +55 -55
  105. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  106. package/dist/apps/data/routes/transactions.js +78 -39
  107. package/dist/apps/data/routes/transactions.js.map +1 -1
  108. package/dist/apps/data/routes/transfers.d.ts +78 -29
  109. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  110. package/dist/apps/data/routes/transfers.js +165 -67
  111. package/dist/apps/data/routes/transfers.js.map +1 -1
  112. package/dist/apps/data/routes/valuation.d.ts +10 -10
  113. package/dist/apps/data/routes/valuation.js +2 -2
  114. package/dist/apps/data/routes/valuation.js.map +1 -1
  115. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  116. package/dist/apps/data/routes/verified-tokens.js +34 -9
  117. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  118. package/dist/apps/data/routes/webhooks.d.ts +5 -3
  119. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  120. package/dist/apps/data/routes/webhooks.js +175 -65
  121. package/dist/apps/data/routes/webhooks.js.map +1 -1
  122. package/dist/apps/data/routes/zones.d.ts +281 -0
  123. package/dist/apps/data/routes/zones.d.ts.map +1 -0
  124. package/dist/apps/data/routes/zones.js +252 -0
  125. package/dist/apps/data/routes/zones.js.map +1 -0
  126. package/dist/apps/docs/reference.js +6 -5
  127. package/dist/apps/docs/reference.js.map +1 -1
  128. package/dist/apps/index.d.ts +2 -1
  129. package/dist/apps/index.d.ts.map +1 -1
  130. package/dist/apps/index.js +2 -1
  131. package/dist/apps/index.js.map +1 -1
  132. package/dist/apps/management/App.d.ts +670 -670
  133. package/dist/apps/management/Billing.d.ts +8 -0
  134. package/dist/apps/management/Billing.d.ts.map +1 -1
  135. package/dist/apps/management/Billing.js +12 -0
  136. package/dist/apps/management/Billing.js.map +1 -1
  137. package/dist/apps/management/Error.d.ts +12 -0
  138. package/dist/apps/management/Error.d.ts.map +1 -0
  139. package/dist/apps/management/Error.js +10 -0
  140. package/dist/apps/management/Error.js.map +1 -0
  141. package/dist/apps/management/routes/api-keys.d.ts +5 -5
  142. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  143. package/dist/apps/management/routes/api-keys.js +2 -8
  144. package/dist/apps/management/routes/api-keys.js.map +1 -1
  145. package/dist/apps/management/routes/billing.d.ts +119 -119
  146. package/dist/apps/management/routes/faucet.d.ts +35 -35
  147. package/dist/apps/management/routes/invitations.d.ts +62 -62
  148. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  149. package/dist/apps/management/routes/invitations.js +4 -10
  150. package/dist/apps/management/routes/invitations.js.map +1 -1
  151. package/dist/apps/management/routes/invite-links.d.ts +30 -30
  152. package/dist/apps/management/routes/me.d.ts +6 -6
  153. package/dist/apps/management/routes/members.d.ts +78 -78
  154. package/dist/apps/management/routes/orgs.d.ts +48 -48
  155. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  156. package/dist/apps/management/routes/orgs.js +2 -8
  157. package/dist/apps/management/routes/orgs.js.map +1 -1
  158. package/dist/apps/management/routes/projects.d.ts +9 -9
  159. package/dist/apps/management/routes/scopes.js +2 -2
  160. package/dist/apps/management/routes/scopes.js.map +1 -1
  161. package/dist/apps/management/routes/usage.d.ts +80 -80
  162. package/dist/apps/management/routes/verified-token-requests.d.ts +36 -36
  163. package/dist/apps/management/routes/webhooks.d.ts +50 -50
  164. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  165. package/dist/apps/management/routes/webhooks.js +15 -3
  166. package/dist/apps/management/routes/webhooks.js.map +1 -1
  167. package/dist/apps/mpp/App.d.ts +55 -56
  168. package/dist/apps/mpp/App.d.ts.map +1 -1
  169. package/dist/apps/mpp/App.js +192 -27
  170. package/dist/apps/mpp/App.js.map +1 -1
  171. package/dist/apps/mpp/Mpp.d.ts +0 -20
  172. package/dist/apps/mpp/Mpp.d.ts.map +1 -1
  173. package/dist/apps/mpp/Mpp.js +0 -24
  174. package/dist/apps/mpp/Mpp.js.map +1 -1
  175. package/dist/apps/mpp/internal/Adapter.d.ts +40 -0
  176. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -0
  177. package/dist/apps/mpp/internal/Adapter.js +66 -0
  178. package/dist/apps/mpp/internal/Adapter.js.map +1 -0
  179. package/dist/apps/mpp/internal/Error.d.ts +4 -0
  180. package/dist/apps/mpp/internal/Error.d.ts.map +1 -0
  181. package/dist/apps/mpp/internal/Error.js +41 -0
  182. package/dist/apps/mpp/internal/Error.js.map +1 -0
  183. package/dist/apps/mpp/internal/Idempotency.d.ts +33 -0
  184. package/dist/apps/mpp/internal/Idempotency.d.ts.map +1 -0
  185. package/dist/apps/mpp/internal/Idempotency.js +28 -0
  186. package/dist/apps/mpp/internal/Idempotency.js.map +1 -0
  187. package/dist/apps/mpp/internal/Policy.d.ts +46 -0
  188. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -0
  189. package/dist/apps/mpp/internal/Policy.js +57 -0
  190. package/dist/apps/mpp/internal/Policy.js.map +1 -0
  191. package/dist/apps/mpp/internal/ScreenManager.d.ts +27 -0
  192. package/dist/apps/mpp/internal/ScreenManager.d.ts.map +1 -0
  193. package/dist/apps/mpp/internal/ScreenManager.js +18 -0
  194. package/dist/apps/mpp/internal/ScreenManager.js.map +1 -0
  195. package/dist/apps/mpp/internal/Screening.d.ts +35 -0
  196. package/dist/apps/mpp/internal/Screening.d.ts.map +1 -0
  197. package/dist/apps/mpp/internal/Screening.js +20 -0
  198. package/dist/apps/mpp/internal/Screening.js.map +1 -0
  199. package/dist/apps/mpp/internal/Sponsorship.d.ts +36 -0
  200. package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -0
  201. package/dist/apps/mpp/internal/Sponsorship.js +103 -0
  202. package/dist/apps/mpp/internal/Sponsorship.js.map +1 -0
  203. package/dist/apps/mpp/internal/Utils.d.ts +7 -0
  204. package/dist/apps/mpp/internal/Utils.d.ts.map +1 -0
  205. package/dist/apps/mpp/internal/Utils.js +24 -0
  206. package/dist/apps/mpp/internal/Utils.js.map +1 -0
  207. package/dist/apps/relay/App.js +184 -24
  208. package/dist/apps/relay/App.js.map +1 -1
  209. package/dist/apps/relay/Sponsorships.d.ts +4 -0
  210. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  211. package/dist/apps/relay/Sponsorships.js +16 -7
  212. package/dist/apps/relay/Sponsorships.js.map +1 -1
  213. package/dist/db/Db.d.ts +20 -0
  214. package/dist/db/Db.d.ts.map +1 -1
  215. package/dist/db/Db.js +342 -0
  216. package/dist/db/Db.js.map +1 -1
  217. package/dist/db/Schema.d.ts +921 -1
  218. package/dist/db/Schema.d.ts.map +1 -1
  219. package/dist/db/Schema.js +269 -1
  220. package/dist/db/Schema.js.map +1 -1
  221. package/dist/db/tables/earnVaults.d.ts +68 -0
  222. package/dist/db/tables/earnVaults.d.ts.map +1 -0
  223. package/dist/db/tables/earnVaults.js +72 -0
  224. package/dist/db/tables/earnVaults.js.map +1 -0
  225. package/dist/db/tables/fundingCatalog.d.ts +56 -0
  226. package/dist/db/tables/fundingCatalog.d.ts.map +1 -0
  227. package/dist/db/tables/fundingCatalog.js +85 -0
  228. package/dist/db/tables/fundingCatalog.js.map +1 -0
  229. package/dist/db/tables/fundingDepositAddresses.d.ts +159 -0
  230. package/dist/db/tables/fundingDepositAddresses.d.ts.map +1 -0
  231. package/dist/db/tables/fundingDepositAddresses.js +206 -0
  232. package/dist/db/tables/fundingDepositAddresses.js.map +1 -0
  233. package/dist/db/tables/fundingDeposits.d.ts +115 -0
  234. package/dist/db/tables/fundingDeposits.d.ts.map +1 -0
  235. package/dist/db/tables/fundingDeposits.js +100 -0
  236. package/dist/db/tables/fundingDeposits.js.map +1 -0
  237. package/dist/db/tables/fundingIdempotency.d.ts +91 -0
  238. package/dist/db/tables/fundingIdempotency.d.ts.map +1 -0
  239. package/dist/db/tables/fundingIdempotency.js +103 -0
  240. package/dist/db/tables/fundingIdempotency.js.map +1 -0
  241. package/dist/db/tables/fundingTransferEvents.d.ts +12 -0
  242. package/dist/db/tables/fundingTransferEvents.d.ts.map +1 -0
  243. package/dist/db/tables/fundingTransferEvents.js +18 -0
  244. package/dist/db/tables/fundingTransferEvents.js.map +1 -0
  245. package/dist/db/tables/fundingTransferTransactions.d.ts +15 -0
  246. package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -0
  247. package/dist/db/tables/fundingTransferTransactions.js +27 -0
  248. package/dist/db/tables/fundingTransferTransactions.js.map +1 -0
  249. package/dist/db/tables/fundingTransfers.d.ts +82 -0
  250. package/dist/db/tables/fundingTransfers.d.ts.map +1 -0
  251. package/dist/db/tables/fundingTransfers.js +89 -0
  252. package/dist/db/tables/fundingTransfers.js.map +1 -0
  253. package/dist/db/tables/organizations.d.ts +8 -0
  254. package/dist/db/tables/organizations.d.ts.map +1 -1
  255. package/dist/db/tables/organizations.js +35 -0
  256. package/dist/db/tables/organizations.js.map +1 -1
  257. package/dist/db/tables/projects.d.ts +8 -0
  258. package/dist/db/tables/projects.d.ts.map +1 -1
  259. package/dist/db/tables/projects.js +16 -0
  260. package/dist/db/tables/projects.js.map +1 -1
  261. package/dist/db/tables/requestUsage.d.ts +13 -0
  262. package/dist/db/tables/requestUsage.d.ts.map +1 -1
  263. package/dist/db/tables/requestUsage.js +16 -0
  264. package/dist/db/tables/requestUsage.js.map +1 -1
  265. package/dist/db/tables/sponsoredTransactions.d.ts +4 -2
  266. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  267. package/dist/db/tables/sponsoredTransactions.js +14 -4
  268. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  269. package/dist/db/tables/users.d.ts +8 -0
  270. package/dist/db/tables/users.d.ts.map +1 -1
  271. package/dist/db/tables/users.js +16 -0
  272. package/dist/db/tables/users.js.map +1 -1
  273. package/dist/db/tables/verifiedTokens.d.ts +14 -7
  274. package/dist/db/tables/verifiedTokens.d.ts.map +1 -1
  275. package/dist/db/tables/verifiedTokens.js +9 -7
  276. package/dist/db/tables/verifiedTokens.js.map +1 -1
  277. package/dist/db/tables/webhookSubscriptions.d.ts +31 -1
  278. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  279. package/dist/db/tables/webhookSubscriptions.js +24 -3
  280. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  281. package/dist/handlers/relay.js +108 -108
  282. package/dist/handlers/relay.js.map +1 -1
  283. package/dist/internal/Auth.d.ts +26 -0
  284. package/dist/internal/Auth.d.ts.map +1 -1
  285. package/dist/internal/Auth.js +35 -2
  286. package/dist/internal/Auth.js.map +1 -1
  287. package/dist/internal/Cache.d.ts.map +1 -1
  288. package/dist/internal/Cache.js +16 -10
  289. package/dist/internal/Cache.js.map +1 -1
  290. package/dist/internal/Cursor.js +1 -1
  291. package/dist/internal/Cursor.js.map +1 -1
  292. package/dist/internal/EarnRates.d.ts +89 -0
  293. package/dist/internal/EarnRates.d.ts.map +1 -0
  294. package/dist/internal/EarnRates.js +266 -0
  295. package/dist/internal/EarnRates.js.map +1 -0
  296. package/dist/internal/EarnVaults.d.ts +171 -0
  297. package/dist/internal/EarnVaults.d.ts.map +1 -0
  298. package/dist/internal/EarnVaults.js +547 -0
  299. package/dist/internal/EarnVaults.js.map +1 -0
  300. package/dist/internal/EdgeCache.d.ts +9 -2
  301. package/dist/internal/EdgeCache.d.ts.map +1 -1
  302. package/dist/internal/EdgeCache.js +36 -9
  303. package/dist/internal/EdgeCache.js.map +1 -1
  304. package/dist/internal/Id.d.ts +11 -0
  305. package/dist/internal/Id.d.ts.map +1 -1
  306. package/dist/internal/Id.js +13 -0
  307. package/dist/internal/Id.js.map +1 -1
  308. package/dist/internal/Idempotency.d.ts +83 -0
  309. package/dist/internal/Idempotency.d.ts.map +1 -0
  310. package/dist/internal/Idempotency.js +113 -0
  311. package/dist/internal/Idempotency.js.map +1 -0
  312. package/dist/internal/Log.d.ts +64 -9
  313. package/dist/internal/Log.d.ts.map +1 -1
  314. package/dist/internal/Log.js +29 -7
  315. package/dist/internal/Log.js.map +1 -1
  316. package/dist/internal/MetricSink.d.ts.map +1 -1
  317. package/dist/internal/MetricSink.js +47 -1
  318. package/dist/internal/MetricSink.js.map +1 -1
  319. package/dist/internal/OpenApi.d.ts +1 -1
  320. package/dist/internal/OpenApi.d.ts.map +1 -1
  321. package/dist/internal/OpenApi.js +3 -0
  322. package/dist/internal/OpenApi.js.map +1 -1
  323. package/dist/internal/Provider.d.ts +14 -0
  324. package/dist/internal/Provider.d.ts.map +1 -0
  325. package/dist/internal/Provider.js +5 -0
  326. package/dist/internal/Provider.js.map +1 -0
  327. package/dist/internal/Schema.d.ts +8 -3
  328. package/dist/internal/Schema.d.ts.map +1 -1
  329. package/dist/internal/Schema.js +24 -13
  330. package/dist/internal/Schema.js.map +1 -1
  331. package/dist/internal/Store.d.ts +6 -0
  332. package/dist/internal/Store.d.ts.map +1 -1
  333. package/dist/internal/Store.js +35 -0
  334. package/dist/internal/Store.js.map +1 -1
  335. package/dist/internal/Tidx.d.ts +43 -24
  336. package/dist/internal/Tidx.d.ts.map +1 -1
  337. package/dist/internal/Tidx.js +79 -11
  338. package/dist/internal/Tidx.js.map +1 -1
  339. package/dist/internal/Viem.d.ts +82 -65
  340. package/dist/internal/Viem.d.ts.map +1 -1
  341. package/dist/internal/Viem.js +83 -12
  342. package/dist/internal/Viem.js.map +1 -1
  343. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  344. package/dist/internal/WebhookDestination.js +34 -28
  345. package/dist/internal/WebhookDestination.js.map +1 -1
  346. package/dist/internal/Webhooks.d.ts +9 -0
  347. package/dist/internal/Webhooks.d.ts.map +1 -1
  348. package/dist/internal/Webhooks.js +15 -10
  349. package/dist/internal/Webhooks.js.map +1 -1
  350. package/dist/internal/exchange/Provider.d.ts +219 -0
  351. package/dist/internal/exchange/Provider.d.ts.map +1 -0
  352. package/dist/internal/exchange/Provider.js +117 -0
  353. package/dist/internal/exchange/Provider.js.map +1 -0
  354. package/dist/internal/exchange/index.d.ts +2 -0
  355. package/dist/internal/exchange/index.d.ts.map +1 -0
  356. package/dist/internal/exchange/index.js +2 -0
  357. package/dist/internal/exchange/index.js.map +1 -0
  358. package/dist/internal/exchange/providers/uniswap.d.ts +57 -0
  359. package/dist/internal/exchange/providers/uniswap.d.ts.map +1 -0
  360. package/dist/internal/exchange/providers/uniswap.js +553 -0
  361. package/dist/internal/exchange/providers/uniswap.js.map +1 -0
  362. package/dist/internal/funding/Action.d.ts +55 -0
  363. package/dist/internal/funding/Action.d.ts.map +1 -0
  364. package/dist/internal/funding/Action.js +74 -0
  365. package/dist/internal/funding/Action.js.map +1 -0
  366. package/dist/internal/funding/Catalog.d.ts +107 -0
  367. package/dist/internal/funding/Catalog.d.ts.map +1 -0
  368. package/dist/internal/funding/Catalog.js +270 -0
  369. package/dist/internal/funding/Catalog.js.map +1 -0
  370. package/dist/internal/funding/Chain.d.ts +76 -0
  371. package/dist/internal/funding/Chain.d.ts.map +1 -0
  372. package/dist/internal/funding/Chain.js +38 -0
  373. package/dist/internal/funding/Chain.js.map +1 -0
  374. package/dist/internal/funding/Deposit.d.ts +366 -0
  375. package/dist/internal/funding/Deposit.d.ts.map +1 -0
  376. package/dist/internal/funding/Deposit.js +286 -0
  377. package/dist/internal/funding/Deposit.js.map +1 -0
  378. package/dist/internal/funding/DepositAddress.d.ts +345 -0
  379. package/dist/internal/funding/DepositAddress.d.ts.map +1 -0
  380. package/dist/internal/funding/DepositAddress.js +189 -0
  381. package/dist/internal/funding/DepositAddress.js.map +1 -0
  382. package/dist/internal/funding/Evidence.d.ts +52 -0
  383. package/dist/internal/funding/Evidence.d.ts.map +1 -0
  384. package/dist/internal/funding/Evidence.js +314 -0
  385. package/dist/internal/funding/Evidence.js.map +1 -0
  386. package/dist/internal/funding/Provider.d.ts +1186 -0
  387. package/dist/internal/funding/Provider.d.ts.map +1 -0
  388. package/dist/internal/funding/Provider.js +1081 -0
  389. package/dist/internal/funding/Provider.js.map +1 -0
  390. package/dist/internal/funding/Reconciliation.d.ts +113 -0
  391. package/dist/internal/funding/Reconciliation.d.ts.map +1 -0
  392. package/dist/internal/funding/Reconciliation.js +676 -0
  393. package/dist/internal/funding/Reconciliation.js.map +1 -0
  394. package/dist/internal/funding/Route.d.ts +21 -0
  395. package/dist/internal/funding/Route.d.ts.map +1 -0
  396. package/dist/internal/funding/Route.js +5 -0
  397. package/dist/internal/funding/Route.js.map +1 -0
  398. package/dist/internal/funding/Subsidy.d.ts +113 -0
  399. package/dist/internal/funding/Subsidy.d.ts.map +1 -0
  400. package/dist/internal/funding/Subsidy.js +138 -0
  401. package/dist/internal/funding/Subsidy.js.map +1 -0
  402. package/dist/internal/funding/Token.d.ts +41 -0
  403. package/dist/internal/funding/Token.d.ts.map +1 -0
  404. package/dist/internal/funding/Token.js +22 -0
  405. package/dist/internal/funding/Token.js.map +1 -0
  406. package/dist/internal/funding/Transfer.d.ts +643 -0
  407. package/dist/internal/funding/Transfer.d.ts.map +1 -0
  408. package/dist/internal/funding/Transfer.js +332 -0
  409. package/dist/internal/funding/Transfer.js.map +1 -0
  410. package/dist/internal/funding/index.d.ts +13 -0
  411. package/dist/internal/funding/index.d.ts.map +1 -0
  412. package/dist/internal/funding/index.js +13 -0
  413. package/dist/internal/funding/index.js.map +1 -0
  414. package/dist/internal/funding/providers/across.d.ts +21 -0
  415. package/dist/internal/funding/providers/across.d.ts.map +1 -0
  416. package/dist/internal/funding/providers/across.js +117 -0
  417. package/dist/internal/funding/providers/across.js.map +1 -0
  418. package/dist/internal/funding/providers/relay.d.ts +46 -0
  419. package/dist/internal/funding/providers/relay.d.ts.map +1 -0
  420. package/dist/internal/funding/providers/relay.js +464 -0
  421. package/dist/internal/funding/providers/relay.js.map +1 -0
  422. package/dist/internal/funding/providers/rhino.d.ts +15 -0
  423. package/dist/internal/funding/providers/rhino.d.ts.map +1 -0
  424. package/dist/internal/funding/providers/rhino.js +116 -0
  425. package/dist/internal/funding/providers/rhino.js.map +1 -0
  426. package/dist/internal/funding/providers/squid.d.ts +19 -0
  427. package/dist/internal/funding/providers/squid.d.ts.map +1 -0
  428. package/dist/internal/funding/providers/squid.js +120 -0
  429. package/dist/internal/funding/providers/squid.js.map +1 -0
  430. package/dist/internal/funding/providers/symbiosis.d.ts +20 -0
  431. package/dist/internal/funding/providers/symbiosis.d.ts.map +1 -0
  432. package/dist/internal/funding/providers/symbiosis.js +176 -0
  433. package/dist/internal/funding/providers/symbiosis.js.map +1 -0
  434. package/dist/internal/index.d.ts +5 -1
  435. package/dist/internal/index.d.ts.map +1 -1
  436. package/dist/internal/index.js +5 -1
  437. package/dist/internal/index.js.map +1 -1
  438. package/dist/internal/webhookDestinations/url.js +61 -57
  439. package/dist/internal/webhookDestinations/url.js.map +1 -1
  440. package/dist/providers/index.d.ts +43 -0
  441. package/dist/providers/index.d.ts.map +1 -0
  442. package/dist/providers/index.js +19 -0
  443. package/dist/providers/index.js.map +1 -0
  444. package/package.json +9 -4
  445. package/src/ApiKeys.test.ts +11 -7
  446. package/src/ApiKeys.ts +37 -9
  447. package/src/App.test.ts +85 -10
  448. package/src/App.ts +224 -137
  449. package/src/Assets.ts +29 -4
  450. package/src/Client.test-d.ts +650 -30
  451. package/src/Scope.test.ts +19 -0
  452. package/src/Scope.ts +28 -11
  453. package/src/Webhooks.test.ts +25 -0
  454. package/src/Webhooks.ts +1 -1
  455. package/src/admin/App.test.ts +9 -2
  456. package/src/admin/App.ts +32 -9
  457. package/src/admin/apps/api-keys.test.ts +167 -23
  458. package/src/admin/apps/api-keys.ts +166 -28
  459. package/src/admin/apps/earn-vaults.test.ts +338 -0
  460. package/src/admin/apps/earn-vaults.ts +572 -0
  461. package/src/admin/apps/scopes.test.ts +16 -1
  462. package/src/admin/ui/plugin.ts +2 -2
  463. package/src/admin/ui/src/components/EarnVaultForm.tsx +137 -0
  464. package/src/admin/ui/src/components/MobileProfile.tsx +2 -2
  465. package/src/admin/ui/src/components/Page.tsx +1 -1
  466. package/src/admin/ui/src/components/ThemeToggle.tsx +1 -1
  467. package/src/admin/ui/src/lib/api-keys.ts +37 -7
  468. package/src/admin/ui/src/lib/client.ts +1 -1
  469. package/src/admin/ui/src/lib/config.ts +1 -1
  470. package/src/admin/ui/src/lib/early-access.ts +8 -9
  471. package/src/admin/ui/src/lib/earn-vaults.ts +207 -0
  472. package/src/admin/ui/src/lib/format.ts +13 -0
  473. package/src/admin/ui/src/lib/organizations.test.ts +14 -4
  474. package/src/admin/ui/src/lib/organizations.ts +7 -1
  475. package/src/admin/ui/src/lib/response.ts +22 -0
  476. package/src/admin/ui/src/lib/scopes.test.ts +19 -11
  477. package/src/admin/ui/src/lib/scopes.ts +28 -7
  478. package/src/admin/ui/src/lib/verified-tokens.ts +10 -9
  479. package/src/admin/ui/src/routeTree.gen.ts +70 -7
  480. package/src/admin/ui/src/router.tsx +2 -2
  481. package/src/admin/ui/src/routes/__root.tsx +9 -8
  482. package/src/admin/ui/src/routes/api-keys.tsx +475 -64
  483. package/src/admin/ui/src/routes/early-access.tsx +5 -12
  484. package/src/admin/ui/src/routes/earn.vaults.tsx +348 -0
  485. package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +154 -0
  486. package/src/admin/ui/src/routes/earn.vaults_.new.tsx +190 -0
  487. package/src/admin/ui/src/routes/organizations.tsx +4 -7
  488. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +56 -54
  489. package/src/admin/ui/src/routes/verified-tokens.tsx +4 -4
  490. package/src/admin/ui/vite.config.ts +4 -1
  491. package/src/admin/ui.generated.ts +189 -95
  492. package/src/analytics/Analytics.test.ts +69 -10
  493. package/src/analytics/Analytics.ts +20 -1
  494. package/src/analytics/tables/requestEvents.ts +79 -37
  495. package/src/apps/Zones.test.ts +33 -0
  496. package/src/apps/Zones.ts +40 -0
  497. package/src/apps/composition.test.ts +84 -1
  498. package/src/apps/data/App.test.ts +38 -9
  499. package/src/apps/data/App.ts +96 -33
  500. package/src/apps/data/FxOracle.ts +1 -1
  501. package/src/apps/data/index.ts +0 -1
  502. package/src/apps/data/routes/activities.test.ts +82 -6
  503. package/src/apps/data/routes/activities.ts +131 -71
  504. package/src/apps/data/routes/balances.test.ts +50 -37
  505. package/src/apps/data/routes/balances.ts +5 -5
  506. package/src/apps/data/routes/blocks.test.ts +2 -0
  507. package/src/apps/data/routes/coingecko.test.ts +22 -0
  508. package/src/apps/data/routes/coingecko.ts +84 -48
  509. package/src/apps/data/routes/earn.test.ts +1108 -0
  510. package/src/apps/data/routes/earn.ts +1391 -0
  511. package/src/apps/data/routes/exchanges.test.ts +82 -33
  512. package/src/apps/data/routes/exchanges.ts +842 -227
  513. package/src/apps/data/routes/fee-amm.test.ts +4 -6
  514. package/src/apps/data/routes/fee-amm.ts +69 -12
  515. package/src/apps/data/routes/funding.test.ts +2712 -221
  516. package/src/apps/data/routes/funding.ts +1604 -387
  517. package/src/apps/data/routes/indexer.test.ts +43 -34
  518. package/src/apps/data/routes/indexer.ts +19 -2
  519. package/src/apps/data/routes/receipts.test.ts +5 -3
  520. package/src/apps/data/routes/receipts.ts +13 -11
  521. package/src/apps/data/routes/rpc.test.ts +446 -28
  522. package/src/apps/data/routes/rpc.ts +243 -25
  523. package/src/apps/data/routes/tokenlist.test.ts +15 -0
  524. package/src/apps/data/routes/tokenlist.ts +88 -22
  525. package/src/apps/data/routes/tokens.ts +262 -86
  526. package/src/apps/data/routes/transactions.test.ts +2 -0
  527. package/src/apps/data/routes/transactions.ts +77 -42
  528. package/src/apps/data/routes/transfers.test.ts +166 -4
  529. package/src/apps/data/routes/transfers.ts +216 -78
  530. package/src/apps/data/routes/valuation.test.ts +62 -9
  531. package/src/apps/data/routes/valuation.ts +2 -2
  532. package/src/apps/data/routes/verified-tokens.test.ts +51 -0
  533. package/src/apps/data/routes/verified-tokens.ts +52 -15
  534. package/src/apps/data/routes/webhooks.test.ts +432 -33
  535. package/src/apps/data/routes/webhooks.ts +189 -79
  536. package/src/apps/data/routes/zones.test.ts +473 -0
  537. package/src/apps/data/routes/zones.ts +338 -0
  538. package/src/apps/docs/reference.ts +8 -6
  539. package/src/apps/index.ts +2 -1
  540. package/src/apps/management/Billing.test.ts +29 -0
  541. package/src/apps/management/Billing.ts +23 -0
  542. package/src/apps/management/Error.ts +12 -0
  543. package/src/apps/management/routes/api-keys.test.ts +5 -3
  544. package/src/apps/management/routes/api-keys.ts +2 -9
  545. package/src/apps/management/routes/invitations.ts +4 -11
  546. package/src/apps/management/routes/orgs.ts +2 -9
  547. package/src/apps/management/routes/scopes.test.ts +7 -2
  548. package/src/apps/management/routes/scopes.ts +2 -2
  549. package/src/apps/management/routes/webhooks.test.ts +6 -1
  550. package/src/apps/management/routes/webhooks.ts +15 -3
  551. package/src/apps/mpp/App.ts +276 -29
  552. package/src/apps/mpp/Mpp.test.ts +631 -26
  553. package/src/apps/mpp/Mpp.ts +0 -42
  554. package/src/apps/mpp/internal/Adapter.ts +108 -3
  555. package/src/apps/mpp/internal/Error.test.ts +33 -0
  556. package/src/apps/mpp/internal/Error.ts +44 -6
  557. package/src/apps/mpp/internal/Idempotency.test.ts +213 -0
  558. package/src/apps/mpp/internal/Idempotency.ts +59 -5
  559. package/src/apps/mpp/internal/Policy.test.ts +122 -0
  560. package/src/apps/mpp/internal/Policy.ts +98 -0
  561. package/src/apps/mpp/internal/ScreenManager.test.ts +68 -0
  562. package/src/apps/mpp/internal/ScreenManager.ts +41 -0
  563. package/src/apps/mpp/internal/Screening.ts +40 -3
  564. package/src/apps/mpp/internal/Sponsorship.ts +144 -0
  565. package/src/apps/mpp/internal/Utils.ts +30 -0
  566. package/src/apps/relay/App.test.ts +495 -64
  567. package/src/apps/relay/App.ts +234 -24
  568. package/src/apps/relay/Sponsorships.test.ts +51 -0
  569. package/src/apps/relay/Sponsorships.ts +19 -7
  570. package/src/db/Db.ts +439 -0
  571. package/src/db/Schema.ts +325 -2
  572. package/src/db/tables/earnVaults.test.ts +185 -0
  573. package/src/db/tables/earnVaults.ts +151 -0
  574. package/src/db/tables/fundingCatalog.test.ts +108 -0
  575. package/src/db/tables/fundingCatalog.ts +157 -0
  576. package/src/db/tables/fundingDepositAddresses.test.ts +580 -0
  577. package/src/db/tables/fundingDepositAddresses.ts +376 -0
  578. package/src/db/tables/fundingDeposits.test.ts +261 -0
  579. package/src/db/tables/fundingDeposits.ts +229 -0
  580. package/src/db/tables/fundingIdempotency.test.ts +182 -0
  581. package/src/db/tables/fundingIdempotency.ts +180 -0
  582. package/src/db/tables/fundingTransferEvents.ts +28 -0
  583. package/src/db/tables/fundingTransferTransactions.test.ts +69 -0
  584. package/src/db/tables/fundingTransferTransactions.ts +37 -0
  585. package/src/db/tables/fundingTransfers.test.ts +89 -0
  586. package/src/db/tables/fundingTransfers.ts +153 -0
  587. package/src/db/tables/organizations.test.ts +88 -0
  588. package/src/db/tables/organizations.ts +42 -1
  589. package/src/db/tables/projects.ts +16 -0
  590. package/src/db/tables/requestUsage.ts +23 -0
  591. package/src/db/tables/sponsoredTransactions.test.ts +52 -2
  592. package/src/db/tables/sponsoredTransactions.ts +18 -6
  593. package/src/db/tables/users.ts +16 -0
  594. package/src/db/tables/verifiedTokens.ts +19 -14
  595. package/src/db/tables/webhookSubscriptions.ts +58 -3
  596. package/src/handlers/relay.test.ts +2 -0
  597. package/src/handlers/relay.ts +95 -99
  598. package/src/internal/Auth.test.ts +48 -0
  599. package/src/internal/Auth.ts +61 -2
  600. package/src/internal/Cache.ts +13 -9
  601. package/src/internal/Cursor.test.ts +2 -2
  602. package/src/internal/Cursor.ts +1 -1
  603. package/src/internal/EarnRates.test.ts +125 -0
  604. package/src/internal/EarnRates.ts +409 -0
  605. package/src/internal/EarnVaults.test.ts +195 -0
  606. package/src/internal/EarnVaults.ts +876 -0
  607. package/src/internal/EdgeCache.test.ts +37 -5
  608. package/src/internal/EdgeCache.ts +39 -7
  609. package/src/internal/Id.ts +14 -0
  610. package/src/internal/Idempotency.test.ts +109 -0
  611. package/src/internal/Idempotency.ts +237 -0
  612. package/src/internal/Log.test-d.ts +41 -8
  613. package/src/internal/Log.test.ts +189 -8
  614. package/src/internal/Log.ts +124 -17
  615. package/src/internal/MetricSink.test.ts +244 -4
  616. package/src/internal/MetricSink.ts +51 -1
  617. package/src/internal/OpenApi.ts +3 -0
  618. package/src/internal/Provider.test.ts +17 -0
  619. package/src/internal/Provider.ts +17 -0
  620. package/src/internal/Schema.test.ts +13 -0
  621. package/src/internal/Schema.ts +41 -24
  622. package/src/internal/Store.test.ts +25 -0
  623. package/src/internal/Store.ts +46 -0
  624. package/src/internal/Tidx.local.test.ts +78 -3
  625. package/src/internal/Tidx.test.ts +212 -18
  626. package/src/internal/Tidx.ts +112 -32
  627. package/src/internal/VerifiedTokens.test.ts +15 -0
  628. package/src/internal/Viem.test.ts +170 -17
  629. package/src/internal/Viem.ts +111 -28
  630. package/src/internal/WebhookDestination.ts +25 -23
  631. package/src/internal/Webhooks.test.ts +59 -0
  632. package/src/internal/Webhooks.ts +34 -10
  633. package/src/internal/exchange/Provider.test.ts +216 -0
  634. package/src/internal/exchange/Provider.ts +326 -0
  635. package/src/internal/exchange/index.test.ts +6 -0
  636. package/src/internal/exchange/index.ts +1 -0
  637. package/src/internal/exchange/providers/uniswap.test.ts +122 -0
  638. package/src/internal/exchange/providers/uniswap.ts +682 -0
  639. package/src/internal/funding/Action.test.ts +138 -0
  640. package/src/internal/funding/Action.ts +117 -0
  641. package/src/internal/funding/Catalog.test.ts +311 -0
  642. package/src/internal/funding/Catalog.ts +347 -0
  643. package/src/internal/funding/Chain.test.ts +79 -0
  644. package/src/internal/funding/Chain.ts +120 -0
  645. package/src/internal/funding/Deposit.test.ts +26 -0
  646. package/src/internal/funding/Deposit.ts +453 -0
  647. package/src/internal/funding/DepositAddress.test.ts +18 -0
  648. package/src/internal/funding/DepositAddress.ts +312 -0
  649. package/src/internal/funding/Evidence.test.ts +297 -0
  650. package/src/internal/funding/Evidence.ts +430 -0
  651. package/src/internal/funding/Provider.test.ts +1328 -0
  652. package/src/internal/funding/Provider.ts +1796 -0
  653. package/src/internal/funding/Reconciliation.local.test.ts +504 -0
  654. package/src/internal/funding/Reconciliation.test.ts +2020 -0
  655. package/src/internal/funding/Reconciliation.ts +930 -0
  656. package/src/internal/funding/Route.test.ts +66 -0
  657. package/src/internal/funding/Route.ts +29 -0
  658. package/src/internal/funding/Subsidy.local.test.ts +152 -0
  659. package/src/internal/funding/Subsidy.test.ts +75 -0
  660. package/src/internal/funding/Subsidy.ts +260 -0
  661. package/src/internal/funding/Token.test.ts +47 -0
  662. package/src/internal/funding/Token.ts +59 -0
  663. package/src/internal/funding/Transfer.test.ts +369 -0
  664. package/src/internal/funding/Transfer.ts +522 -0
  665. package/src/internal/funding/index.test.ts +20 -0
  666. package/src/internal/funding/index.ts +12 -0
  667. package/src/internal/funding/providers/across.ts +149 -0
  668. package/src/{apps/data/FundingQuoteProviders.test.ts → internal/funding/providers/index.test.ts} +178 -157
  669. package/src/internal/funding/providers/relay.test.ts +474 -0
  670. package/src/internal/funding/providers/relay.ts +559 -0
  671. package/src/internal/funding/providers/rhino.ts +139 -0
  672. package/src/internal/funding/providers/squid.ts +151 -0
  673. package/src/internal/funding/providers/symbiosis.ts +221 -0
  674. package/src/internal/index.test.ts +5 -1
  675. package/src/internal/index.ts +5 -1
  676. package/src/internal/webhookDestinations/url.ts +49 -45
  677. package/src/providers/index.test.ts +14 -0
  678. package/src/providers/index.ts +54 -0
  679. package/dist/apps/data/FundingQuoteProviders.d.ts +0 -174
  680. package/dist/apps/data/FundingQuoteProviders.d.ts.map +0 -1
  681. package/dist/apps/data/FundingQuoteProviders.js +0 -775
  682. package/dist/apps/data/FundingQuoteProviders.js.map +0 -1
  683. package/dist/internal/FundingQuotes.d.ts +0 -864
  684. package/dist/internal/FundingQuotes.d.ts.map +0 -1
  685. package/dist/internal/FundingQuotes.js +0 -672
  686. package/dist/internal/FundingQuotes.js.map +0 -1
  687. package/src/apps/data/FundingQuoteProviders.ts +0 -1043
  688. package/src/internal/FundingQuotes.test.ts +0 -456
  689. package/src/internal/FundingQuotes.ts +0 -944
@@ -1,13 +1,46 @@
1
+ import * as http from 'node:http'
2
+
3
+ import * as Mppx from 'mppx'
4
+ import { Mppx as MppxClient, tempo as tempoClient } from 'mppx/client'
5
+ import { Mppx as MppxServer, tempo as tempoServer } from 'mppx/server'
6
+ import { privateKeyToAccount } from 'viem/accounts'
7
+ import { Actions } from 'viem/tempo'
8
+
1
9
  import * as TestApp from '../../../test/App.js'
10
+ import * as Tempo from '../../../test/Tempo.js'
11
+ import * as App from '../../App.js'
12
+ import * as SponsoredTransactions from '../../db/tables/sponsoredTransactions.js'
13
+ import * as Store from '../../internal/Store.js'
2
14
  import * as Mpp from './Mpp.js'
15
+ import * as Adapter from './internal/Adapter.js'
16
+ import * as Idempotency from './internal/Idempotency.js'
3
17
 
4
18
  const key = {
5
19
  id: 'key_mpp',
6
20
  orgId: 'org_test',
21
+ projectId: 'prj_mpp',
7
22
  scopes: ['mpp:write'],
8
23
  token: 'secret_mpp',
9
24
  } satisfies TestApp.kvStore.Key
10
25
 
26
+ const organizationKey = {
27
+ id: 'key_mpp_org',
28
+ orgId: 'org_test',
29
+ scopes: ['mpp:write'],
30
+ token: 'secret_mpp_org',
31
+ } satisfies TestApp.kvStore.Key
32
+
33
+ const sandboxKey = {
34
+ ...key,
35
+ environment: 'sandbox',
36
+ id: 'key_mpp_sandbox',
37
+ token: 'secret_mpp_sandbox',
38
+ } satisfies TestApp.kvStore.Key
39
+
40
+ const idempotencyKey = 'mpp_broadcast_01j3j1k2l3m4n5p6q7r8s9t0u'
41
+
42
+ const modes = ['pull', 'push'] as const
43
+
11
44
  const input = {
12
45
  challenge: {
13
46
  description: 'Tempo API payment',
@@ -50,33 +83,375 @@ const errorDescriptions = [
50
83
  ] as const
51
84
 
52
85
  describe('MPP relay', () => {
53
- test.each(['/v1/mpp/verify', '/v1/mpp/broadcast'])('%s requires the MPP scope', async (path) => {
86
+ test('verifies a valid Tempo credential without broadcasting it', async () => {
54
87
  const app = TestApp.create({ auth: { keys: [key] } })
55
- const response = await app.fetch(
56
- new Request(`http://tempo-api.test${path}`, {
57
- body: JSON.stringify(input),
58
- headers: { 'content-type': 'application/json', authorization: 'Bearer secret_mpp' },
59
- method: 'POST',
60
- }),
88
+ const response = await post(app, '/v1/mpp/validate', await credential())
89
+
90
+ expect(response.status).toBe(200)
91
+ expect(await response.json()).toEqual({ success: true })
92
+ })
93
+
94
+ test('validates and finalizes a pushed credential without a second submission', async () => {
95
+ const app = TestApp.create({ auth: { keys: [key] } })
96
+ const input = await credential({ mode: 'push', supportedModes: ['push'] })
97
+ const hash = credentialHash(input)
98
+
99
+ expect(payloadType(input)).toBe('hash')
100
+ expect(await (await post(app, '/v1/mpp/validate', input)).json()).toEqual({ success: true })
101
+
102
+ const first = Mpp.schema.BroadcastResponse.parse(
103
+ await (await post(app, '/v1/mpp/broadcast', input)).json(),
61
104
  )
105
+ expect(first).toMatchObject({ receipt: { reference: hash }, success: true })
62
106
 
63
- expect(response.status).toBe(503)
64
- expect(response.headers.get('retry-after')).toBe('60')
65
- expect(await response.json()).toMatchInlineSnapshot(`
66
- {
67
- "error": {
68
- "code": "temporarily_unavailable",
69
- "message": "MPP relay is not enabled yet.",
107
+ const replay = Mpp.schema.BroadcastResponse.parse(
108
+ await (await post(app, '/v1/mpp/broadcast', input)).json(),
109
+ )
110
+ expect(replay.success).toBe(false)
111
+ if (replay.success)
112
+ throw new Error('Expected the relay to reject the pushed credential replay.')
113
+ expect([Mpp.relayErrorCode.alreadyUsed, Mpp.relayErrorCode.invalidPayment]).toContain(
114
+ replay.error.code,
115
+ )
116
+ })
117
+
118
+ test('replays a pushed credential receipt for an idempotency key', async () => {
119
+ const app = TestApp.create({ auth: { keys: [key] } })
120
+ const input = await credential({ mode: 'push', supportedModes: ['push'] })
121
+
122
+ const first = Mpp.schema.BroadcastResponse.parse(
123
+ await (await post(app, '/v1/mpp/broadcast', input, { idempotencyKey })).json(),
124
+ )
125
+ const replay = Mpp.schema.BroadcastResponse.parse(
126
+ await (await post(app, '/v1/mpp/broadcast', input, { idempotencyKey })).json(),
127
+ )
128
+
129
+ expect(payloadType(input)).toBe('hash')
130
+ expect(first.success).toBe(true)
131
+ expect(replay).toEqual(first)
132
+ })
133
+
134
+ test('validates a pulled credential before broadcasting it once', async () => {
135
+ const app = TestApp.create({ auth: { keys: [key] } })
136
+ const input = await credential({ mode: 'pull', supportedModes: ['pull'] })
137
+
138
+ expect(payloadType(input)).toBe('transaction')
139
+ expect(await (await post(app, '/v1/mpp/validate', input)).json()).toEqual({ success: true })
140
+
141
+ const first = Mpp.schema.BroadcastResponse.parse(
142
+ await (await post(app, '/v1/mpp/broadcast', input)).json(),
143
+ )
144
+ expect(first.success).toBe(true)
145
+
146
+ const replay = Mpp.schema.BroadcastResponse.parse(
147
+ await (await post(app, '/v1/mpp/broadcast', input)).json(),
148
+ )
149
+ expect(replay.success).toBe(false)
150
+ if (replay.success)
151
+ throw new Error('Expected the relay to reject the pulled credential replay.')
152
+ expect([Mpp.relayErrorCode.alreadyUsed, Mpp.relayErrorCode.invalidPayment]).toContain(
153
+ replay.error.code,
154
+ )
155
+ })
156
+
157
+ test('does not finalize an unverifiable pushed hash', async () => {
158
+ const app = TestApp.create({ auth: { keys: [key] } })
159
+ const input = await credential({ mode: 'push', supportedModes: ['push'] })
160
+ const invalid = {
161
+ ...input,
162
+ payload: { ...(input.payload as CredentialPayload), hash: `0x${'ff'.repeat(32)}` },
163
+ } satisfies Mpp.RelayInput
164
+
165
+ expect(payloadType(invalid)).toBe('hash')
166
+
167
+ const verification = Mpp.schema.VerifyResponse.parse(
168
+ await (await post(app, '/v1/mpp/validate', invalid)).json(),
169
+ )
170
+ expect(verification.success).toBe(false)
171
+
172
+ const broadcast = Mpp.schema.BroadcastResponse.parse(
173
+ await (await post(app, '/v1/mpp/broadcast', invalid)).json(),
174
+ )
175
+ expect(broadcast.success).toBe(false)
176
+ })
177
+
178
+ test.each(modes)('settles one concurrent %s credential across app instances', async (mode) => {
179
+ const state = Store.memory()
180
+ const input = await credential({ mode, supportedModes: [mode] })
181
+ const first = TestApp.create({ auth: { keys: [key] }, mpp: { state } })
182
+ const second = TestApp.create({ auth: { keys: [key] }, mpp: { state } })
183
+
184
+ const responses = await Promise.all([
185
+ post(first, '/v1/mpp/broadcast', input),
186
+ post(second, '/v1/mpp/broadcast', input),
187
+ ])
188
+ const results = await Promise.all(
189
+ responses.map(async (response) => Mpp.schema.BroadcastResponse.parse(await response.json())),
190
+ )
191
+ const successful = results.filter((result) => result.success)
192
+ const rejected = results.find((result) => !result.success)
193
+
194
+ expect(successful).toHaveLength(1)
195
+ expect(rejected?.success).toBe(false)
196
+ if (!rejected || rejected.success)
197
+ throw new Error('Expected one credential settlement to be rejected.')
198
+ expect([Mpp.relayErrorCode.alreadyUsed, Mpp.relayErrorCode.invalidPayment]).toContain(
199
+ rejected.error.code,
200
+ )
201
+ })
202
+
203
+ test.each(modes)('screens the sender and recipient of a %s credential', async (mode) => {
204
+ const addresses: string[] = []
205
+ const adapter = Adapter.create({
206
+ chainId: Tempo.chain.id,
207
+ getClient: () => Tempo.client,
208
+ provider: {
209
+ async screen({ address }) {
210
+ addresses.push(address)
211
+ return { allowed: true }
70
212
  },
71
- "success": false,
72
- }
73
- `)
213
+ },
214
+ screeningStore: Store.memory(),
215
+ state: Store.memory(),
216
+ })
217
+
218
+ await expect(
219
+ adapter.verify(await credential({ mode, supportedModes: [mode] })),
220
+ ).resolves.toEqual({
221
+ success: true,
222
+ })
223
+ expect(addresses.sort()).toEqual(
224
+ [Tempo.accounts[0].address, Tempo.accounts[1].address]
225
+ .map((address) => address.toLowerCase())
226
+ .sort(),
227
+ )
228
+ })
229
+
230
+ test.each([
231
+ { address: Tempo.accounts[1].address, mode: 'push' },
232
+ { address: Tempo.accounts[0].address, mode: 'push' },
233
+ { address: Tempo.accounts[1].address, mode: 'pull' },
234
+ { address: Tempo.accounts[0].address, mode: 'pull' },
235
+ ] as const)('rejects a screened $mode credential participant', async ({ address, mode }) => {
236
+ const adapter = Adapter.create({
237
+ chainId: Tempo.chain.id,
238
+ getClient: () => Tempo.client,
239
+ provider: {
240
+ async screen(options) {
241
+ return { allowed: options.address !== address.toLowerCase() }
242
+ },
243
+ },
244
+ screeningStore: Store.memory(),
245
+ state: Store.memory(),
246
+ })
247
+
248
+ await expect(
249
+ adapter.verify(await credential({ mode, supportedModes: [mode] })),
250
+ ).resolves.toEqual({
251
+ error: {
252
+ code: Mpp.relayErrorCode.screenRejected,
253
+ message: 'Address screening rejected the payment.',
254
+ },
255
+ success: false,
256
+ })
257
+ })
258
+
259
+ test('returns a screen rejection after validating a Tempo credential', async () => {
260
+ const adapter = Adapter.create({
261
+ chainId: Tempo.chain.id,
262
+ getClient: () => Tempo.client,
263
+ provider: {
264
+ async screen() {
265
+ return { allowed: false }
266
+ },
267
+ },
268
+ screeningStore: Store.memory(),
269
+ state: Store.memory(),
270
+ })
271
+
272
+ await expect(adapter.verify(await credential())).resolves.toEqual({
273
+ error: {
274
+ code: Mpp.relayErrorCode.screenRejected,
275
+ message: 'Address screening rejected the payment.',
276
+ },
277
+ success: false,
278
+ })
279
+ })
280
+
281
+ test('broadcasts once and replays the terminal receipt for an idempotency key', async () => {
282
+ const app = TestApp.create({ auth: { keys: [key] } })
283
+ const input = await credential()
284
+ const first = await post(app, '/v1/mpp/broadcast', input, { idempotencyKey })
285
+ const second = await post(app, '/v1/mpp/broadcast', input, { idempotencyKey })
286
+
287
+ expect(first.status).toBe(200)
288
+ expect(second.status).toBe(200)
289
+ expect(await second.json()).toEqual(await first.json())
290
+ })
291
+
292
+ test('lets MPPX reject a repeated credential without an idempotency key', async () => {
293
+ const app = TestApp.create({ auth: { keys: [key] } })
294
+ const input = await credential()
295
+ const first = await post(app, '/v1/mpp/broadcast', input)
296
+ const second = Mpp.schema.BroadcastResponse.parse(
297
+ await (await post(app, '/v1/mpp/broadcast', input)).json(),
298
+ )
299
+
300
+ expect(Mpp.schema.BroadcastResponse.parse(await first.json()).success).toBe(true)
301
+ expect(second.success).toBe(false)
302
+ if (second.success) throw new Error('Expected MPPX to reject the repeated credential.')
303
+ expect([Mpp.relayErrorCode.alreadyUsed, Mpp.relayErrorCode.invalidPayment]).toContain(
304
+ second.error.code,
305
+ )
306
+ })
307
+
308
+ test('returns a retryable result while the idempotent broadcast is pending', async () => {
309
+ const state = TestApp.kvStore({ keys: [key] })
310
+ const claim = await Idempotency.claim({
311
+ identity: { apiKeyId: key.id, idempotencyKey, inputHash: Idempotency.inputHash(input) },
312
+ state,
313
+ })
314
+ if (claim.type !== 'claimed') throw new Error('Expected an idempotency key claim.')
315
+ const app = TestApp.create({ auth: { keys: [key] }, mpp: { state } })
316
+
317
+ const response = await post(app, '/v1/mpp/broadcast', input, { idempotencyKey })
318
+
319
+ expect(response.status).toBe(200)
320
+ expect(await response.json()).toEqual({
321
+ error: {
322
+ code: Mpp.relayErrorCode.temporarilyUnavailable,
323
+ message: 'MPP credential broadcast is already in progress.',
324
+ },
325
+ success: false,
326
+ })
327
+ })
328
+
329
+ test('releases failed credentials for a corrected retry', async () => {
330
+ const state = TestApp.kvStore({ keys: [key] })
331
+ const app = TestApp.create({ auth: { keys: [key] }, mpp: { state } })
332
+
333
+ const response = await post(app, '/v1/mpp/broadcast', input, { idempotencyKey })
334
+
335
+ expect(response.status).toBe(200)
336
+ expect(Mpp.schema.BroadcastResponse.parse(await response.json()).success).toBe(false)
337
+
338
+ const corrected = Mpp.schema.BroadcastResponse.parse(
339
+ await (
340
+ await post(
341
+ app,
342
+ '/v1/mpp/broadcast',
343
+ await credential({ mode: 'pull', supportedModes: ['pull'] }),
344
+ { idempotencyKey },
345
+ )
346
+ ).json(),
347
+ )
348
+ expect(corrected.success).toBe(true)
74
349
  })
75
350
 
351
+ test('does not replay a receipt for a different credential sharing an idempotency key', async () => {
352
+ const app = TestApp.create({ auth: { keys: [key] } })
353
+ const first = await credential({ mode: 'push', supportedModes: ['push'] })
354
+ const second = await credential({ mode: 'push', supportedModes: ['push'] })
355
+
356
+ expect(
357
+ Mpp.schema.BroadcastResponse.parse(
358
+ await (await post(app, '/v1/mpp/broadcast', first, { idempotencyKey })).json(),
359
+ ).success,
360
+ ).toBe(true)
361
+
362
+ const collision = Mpp.schema.BroadcastResponse.parse(
363
+ await (await post(app, '/v1/mpp/broadcast', second, { idempotencyKey })).json(),
364
+ )
365
+ expect(collision).toEqual({
366
+ error: {
367
+ code: Mpp.relayErrorCode.invalidPayment,
368
+ message: 'Idempotency-Key was already used for a different credential.',
369
+ },
370
+ success: false,
371
+ })
372
+
373
+ expect(
374
+ Mpp.schema.BroadcastResponse.parse(
375
+ await (await post(app, '/v1/mpp/broadcast', second)).json(),
376
+ ).success,
377
+ ).toBe(true)
378
+ })
379
+
380
+ test('co-signs and records an organization-attributed sponsored pull credential', async () => {
381
+ const db = TestApp.database()
382
+ await Actions.faucet.fundSync(Tempo.client, { account: Tempo.accounts[2], timeout: 60_000 })
383
+ const app = TestApp.create({
384
+ auth: { keys: [organizationKey] },
385
+ db,
386
+ mpp: { feePayer: Tempo.accounts[2], state: Store.memory() },
387
+ })
388
+ const input = await credential({ feePayer: true, mode: 'pull', supportedModes: ['pull'] })
389
+
390
+ expect(payloadType(input)).toBe('transaction')
391
+ expect(input.challenge.request['methodDetails']).toMatchObject({ feePayer: true })
392
+ expect(
393
+ Mpp.schema.BroadcastResponse.parse(
394
+ await (
395
+ await post(app, '/v1/mpp/broadcast', input, { apiKey: organizationKey.token })
396
+ ).json(),
397
+ ).success,
398
+ ).toBe(true)
399
+ expect(await SponsoredTransactions.listPending(db)).toMatchObject([
400
+ {
401
+ apiKeyId: organizationKey.id,
402
+ chainId: Tempo.chain.id,
403
+ environment: 'production',
404
+ orgId: organizationKey.orgId,
405
+ projectId: null,
406
+ status: 'pending',
407
+ },
408
+ ])
409
+ })
410
+
411
+ test('runs MPPX verification, broadcast, and replay through a live HTTP server', async () => {
412
+ const app = TestApp.create({ auth: { keys: [key] } })
413
+ const server = await startServer(App.listener(app))
414
+
415
+ try {
416
+ const input = await credentialFromServer()
417
+ const verification = await postHttp(server.url, '/v1/mpp/validate', input)
418
+ const first = await postHttp(server.url, '/v1/mpp/broadcast', input, { idempotencyKey })
419
+ const second = await postHttp(server.url, '/v1/mpp/broadcast', input, { idempotencyKey })
420
+
421
+ expect(verification.status).toBe(200)
422
+ expect(await verification.json()).toEqual({ success: true })
423
+ expect(first.status).toBe(200)
424
+ expect(second.status).toBe(200)
425
+ const receipt = Mpp.schema.BroadcastResponse.parse(await first.json())
426
+ if (!receipt.success) throw new Error('Expected the MPP relay to broadcast the credential.')
427
+ expect(receipt.receipt.method).toBe('tempo')
428
+ expect(Mpp.schema.BroadcastResponse.parse(await second.json())).toEqual(receipt)
429
+ } finally {
430
+ await server.close()
431
+ }
432
+ })
433
+
434
+ test.each(['/v1/mpp/validate', '/v1/mpp/broadcast'])(
435
+ '%s validates credentials for API keys with the MPP scope',
436
+ async (path) => {
437
+ const app = TestApp.create({ auth: { keys: [key] } })
438
+ const response = await app.fetch(
439
+ new Request(`http://tempo-api.test${path}`, {
440
+ body: JSON.stringify(input),
441
+ headers: { 'content-type': 'application/json', authorization: 'Bearer secret_mpp' },
442
+ method: 'POST',
443
+ }),
444
+ )
445
+
446
+ expect(response.status).toBe(200)
447
+ expect(Mpp.schema.VerifyResponse.safeParse(await response.json()).success).toBe(true)
448
+ },
449
+ )
450
+
76
451
  test('rejects unscoped API keys', async () => {
77
452
  const app = TestApp.create({ auth: { keys: [key, TestApp.key] } })
78
453
  const response = await app.fetch(
79
- new Request('http://tempo-api.test/v1/mpp/verify', {
454
+ new Request('http://tempo-api.test/v1/mpp/validate', {
80
455
  body: JSON.stringify(input),
81
456
  headers: {
82
457
  'content-type': 'application/json',
@@ -93,7 +468,7 @@ describe('MPP relay', () => {
93
468
  test('requires API-key authentication', async () => {
94
469
  const app = TestApp.create()
95
470
  const response = await app.fetch(
96
- new Request('http://tempo-api.test/v1/mpp/verify', {
471
+ new Request('http://tempo-api.test/v1/mpp/validate', {
97
472
  body: JSON.stringify(input),
98
473
  headers: { 'content-type': 'application/json' },
99
474
  method: 'POST',
@@ -104,8 +479,69 @@ describe('MPP relay', () => {
104
479
  expect(await response.json()).toMatchObject({ error: { code: 'api_key_missing' } })
105
480
  })
106
481
 
107
- test.each(['/v1/mpp/verify', '/v1/mpp/broadcast'])(
108
- '%s rejects malformed credential input before the disabled handler',
482
+ test('rejects an unbilled mainnet fee-payer broadcast before MPPX processing', async () => {
483
+ const app = TestApp.create({
484
+ auth: { keys: [key] },
485
+ mpp: {
486
+ feePayer: privateKeyToAccount(`0x${'11'.repeat(32)}`),
487
+ state: Store.memory(),
488
+ },
489
+ })
490
+ const response = await post(app, '/v1/mpp/broadcast', {
491
+ ...input,
492
+ challenge: {
493
+ ...input.challenge,
494
+ request: { methodDetails: { chainId: 4217, feePayer: true } },
495
+ },
496
+ })
497
+
498
+ expect(response.status).toBe(200)
499
+ expect(await response.json()).toEqual({
500
+ error: {
501
+ code: Mpp.relayErrorCode.policyDenied,
502
+ message: 'Active billing is required for mainnet fee sponsorship.',
503
+ },
504
+ success: false,
505
+ })
506
+ })
507
+
508
+ test('rejects sandbox keys that request mainnet fee sponsorship', async () => {
509
+ const app = TestApp.create({
510
+ auth: { keys: [sandboxKey] },
511
+ mpp: {
512
+ feePayer: privateKeyToAccount(`0x${'11'.repeat(32)}`),
513
+ state: Store.memory(),
514
+ },
515
+ })
516
+ const response = await app.fetch(
517
+ new Request('http://tempo-api.test/v1/mpp/broadcast', {
518
+ body: JSON.stringify({
519
+ ...input,
520
+ challenge: {
521
+ ...input.challenge,
522
+ request: { methodDetails: { chainId: 4217, feePayer: true } },
523
+ },
524
+ }),
525
+ headers: {
526
+ authorization: `Bearer ${sandboxKey.token}`,
527
+ 'content-type': 'application/json',
528
+ },
529
+ method: 'POST',
530
+ }),
531
+ )
532
+
533
+ expect(response.status).toBe(200)
534
+ expect(await response.json()).toEqual({
535
+ error: {
536
+ code: Mpp.relayErrorCode.policyDenied,
537
+ message: 'Mainnet fee sponsorship requires a production API key.',
538
+ },
539
+ success: false,
540
+ })
541
+ })
542
+
543
+ test.each(['/v1/mpp/validate', '/v1/mpp/broadcast'])(
544
+ '%s rejects malformed credential input before relay processing',
109
545
  async (path) => {
110
546
  const app = TestApp.create({ auth: { keys: [key] } })
111
547
  const response = await app.fetch(
@@ -121,7 +557,7 @@ describe('MPP relay', () => {
121
557
  },
122
558
  )
123
559
 
124
- test.each(['/v1/mpp/verify', '/v1/mpp/broadcast'])(
560
+ test.each(['/v1/mpp/validate', '/v1/mpp/broadcast'])(
125
561
  '%s requires a credential payload',
126
562
  async (path) => {
127
563
  const app = TestApp.create({ auth: { keys: [key] } })
@@ -141,19 +577,188 @@ describe('MPP relay', () => {
141
577
  test('publishes the MPP endpoints', async () => {
142
578
  const app = TestApp.create()
143
579
  const spec = (await (await app.request('/openapi.json')).json()) as {
144
- paths: Record<string, { post?: { responses?: Record<string, unknown> } }>
580
+ paths: Record<
581
+ string,
582
+ {
583
+ post?: {
584
+ description?: string
585
+ parameters?: readonly { in?: string; name?: string }[]
586
+ responses?: Record<string, unknown>
587
+ }
588
+ }
589
+ >
590
+ tags?: readonly { description?: string; name?: string }[]
145
591
  }
146
592
 
147
- for (const path of ['/v1/mpp/verify', '/v1/mpp/broadcast']) {
593
+ expect(spec.tags).toContainEqual(expect.objectContaining({ name: 'MPP' }))
594
+
595
+ for (const path of ['/v1/mpp/validate', '/v1/mpp/broadcast']) {
148
596
  expect(spec.paths[path]?.post?.responses?.['200']).toBeDefined()
149
- expect(spec.paths[path]?.post?.responses?.['503']).toBeDefined()
597
+ expect(spec.paths[path]?.post?.responses?.['503']).toBeUndefined()
150
598
  }
151
599
 
152
- const response = JSON.stringify(spec.paths['/v1/mpp/verify']?.post?.responses?.['200'])
600
+ expect(spec.paths['/v1/mpp/validate']?.post?.description).toContain(
601
+ 'It does not settle, broadcast, reserve funds, or consume the credential.',
602
+ )
603
+ expect(spec.paths['/v1/mpp/broadcast']?.post?.description).toContain('Idempotency-Key')
604
+
605
+ const response = JSON.stringify(spec.paths['/v1/mpp/validate']?.post?.responses?.['200'])
153
606
  for (const description of errorDescriptions) expect(response).toContain(description)
607
+ expect(spec.paths['/v1/mpp/broadcast']?.post?.parameters).toContainEqual({
608
+ description:
609
+ 'Optional opaque retry key, scoped to the API key and credential. Reusing it after a successful broadcast returns the original receipt without another submission. Reusing it with a different credential returns `invalid_payment`. While the first request is running, duplicates return `temporarily_unavailable`. Failed attempts are not retained and may be retried with the same key.',
610
+ in: 'header',
611
+ name: 'Idempotency-Key',
612
+ required: false,
613
+ schema: { example: idempotencyKey, type: 'string' },
614
+ })
154
615
  })
155
616
  })
156
617
 
618
+ type CredentialPayload = { hash?: string; type?: unknown }
619
+
620
+ async function credential(options: credential.Options = {}): Promise<Mpp.RelayInput> {
621
+ const issuer = createIssuer(options)
622
+ const challenge = await issuer.challenge.tempo.charge({ amount: '1' })
623
+ const authorization = await createClient(options).createCredential(
624
+ new Response(null, {
625
+ headers: { 'www-authenticate': Mppx.Challenge.serialize(challenge) },
626
+ status: 402,
627
+ }),
628
+ )
629
+ return Mppx.Credential.deserialize(authorization)
630
+ }
631
+
632
+ declare namespace credential {
633
+ type Options = {
634
+ feePayer?: boolean | undefined
635
+ mode?: 'pull' | 'push' | undefined
636
+ supportedModes?: ('pull' | 'push')[] | undefined
637
+ }
638
+ }
639
+
640
+ async function credentialFromServer(): Promise<Mpp.RelayInput> {
641
+ const issuer = createIssuer()
642
+ const server = await startServer(
643
+ MppxServer.toNodeListener(issuer.charge({ amount: '1' })) as http.RequestListener,
644
+ )
645
+
646
+ try {
647
+ const paymentRequired = await fetch(server.url)
648
+ expect(paymentRequired.status).toBe(402)
649
+ return Mppx.Credential.deserialize(await createClient().createCredential(paymentRequired))
650
+ } finally {
651
+ await server.close()
652
+ }
653
+ }
654
+
655
+ function createClient(options: credential.Options = {}) {
656
+ return MppxClient.create({
657
+ methods: [
658
+ tempoClient({
659
+ account: Tempo.accounts[1],
660
+ getClient: () => Tempo.client,
661
+ ...(options.mode === undefined ? {} : { mode: options.mode }),
662
+ }),
663
+ ],
664
+ polyfill: false,
665
+ })
666
+ }
667
+
668
+ function createIssuer(options: credential.Options = {}) {
669
+ return MppxServer.create({
670
+ methods: [
671
+ tempoServer.charge({
672
+ account: Tempo.accounts[0],
673
+ currency: Tempo.currency,
674
+ ...(options.feePayer ? { feePayer: true } : {}),
675
+ getClient: () => Tempo.client,
676
+ ...(options.supportedModes === undefined ? {} : { supportedModes: options.supportedModes }),
677
+ }),
678
+ ],
679
+ realm: 'merchant.example',
680
+ secretKey: 'test-mpp-secret-key-for-payment-sessions',
681
+ })
682
+ }
683
+
684
+ function credentialHash(input: Mpp.RelayInput) {
685
+ const payload = input.payload as CredentialPayload
686
+ if (payload.type !== 'hash' || typeof payload.hash !== 'string')
687
+ throw new Error('Expected a pushed hash credential.')
688
+ return payload.hash
689
+ }
690
+
691
+ function payloadType(input: Mpp.RelayInput) {
692
+ return (input.payload as CredentialPayload).type
693
+ }
694
+
695
+ function post(
696
+ app: { fetch: (request: Request) => Response | Promise<Response> },
697
+ path: string,
698
+ input: Mpp.RelayInput,
699
+ options: post.Options = {},
700
+ ) {
701
+ return app.fetch(
702
+ new Request(`http://tempo-api.test${path}`, {
703
+ body: JSON.stringify(input),
704
+ headers: {
705
+ 'content-type': 'application/json',
706
+ authorization: `Bearer ${options.apiKey ?? key.token}`,
707
+ ...(options.idempotencyKey ? { 'idempotency-key': options.idempotencyKey } : {}),
708
+ },
709
+ method: 'POST',
710
+ }),
711
+ )
712
+ }
713
+
714
+ declare namespace post {
715
+ type Options = {
716
+ apiKey?: string | undefined
717
+ idempotencyKey?: string | undefined
718
+ }
719
+ }
720
+
721
+ function postHttp(url: string, path: string, input: Mpp.RelayInput, options: post.Options = {}) {
722
+ return fetch(new URL(path, url), {
723
+ body: JSON.stringify(input),
724
+ headers: {
725
+ 'content-type': 'application/json',
726
+ authorization: `Bearer ${key.token}`,
727
+ ...(options.idempotencyKey ? { 'idempotency-key': options.idempotencyKey } : {}),
728
+ },
729
+ method: 'POST',
730
+ })
731
+ }
732
+
733
+ async function startServer(listener: http.RequestListener): Promise<Server> {
734
+ const server = http.createServer(listener)
735
+ await new Promise<void>((resolve, reject) => {
736
+ server.once('error', reject)
737
+ server.listen(0, '127.0.0.1', () => {
738
+ server.off('error', reject)
739
+ resolve()
740
+ })
741
+ })
742
+ const address = server.address()
743
+ if (!address || typeof address === 'string') {
744
+ await closeServer(server)
745
+ throw new Error('Expected a TCP address.')
746
+ }
747
+
748
+ return { close: () => closeServer(server), url: `http://127.0.0.1:${address.port}` }
749
+ }
750
+
751
+ function closeServer(server: http.Server) {
752
+ return new Promise<void>((resolve, reject) => {
753
+ server.close((error) => (error ? reject(error) : resolve()))
754
+ })
755
+ }
756
+
757
+ type Server = {
758
+ close(): Promise<void>
759
+ url: string
760
+ }
761
+
157
762
  describe('MPP relay schemas', () => {
158
763
  test('parses public relay contracts', () => {
159
764
  expect(Mpp.schema.RelayInput.parse(input)).toEqual(input)