tapimo 0.11.0 → 0.13.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 (443) hide show
  1. package/dist/App.d.ts +6396 -4575
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +39 -4
  4. package/dist/App.js.map +1 -1
  5. package/dist/Assets.d.ts +15 -0
  6. package/dist/Assets.d.ts.map +1 -1
  7. package/dist/Assets.js +7 -0
  8. package/dist/Assets.js.map +1 -1
  9. package/dist/Scope.d.ts +2 -0
  10. package/dist/Scope.d.ts.map +1 -1
  11. package/dist/Scope.js +17 -0
  12. package/dist/Scope.js.map +1 -1
  13. package/dist/admin/App.d.ts +176 -78
  14. package/dist/admin/App.d.ts.map +1 -1
  15. package/dist/admin/apps/api-keys.d.ts +84 -4
  16. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  17. package/dist/admin/apps/api-keys.js +54 -0
  18. package/dist/admin/apps/api-keys.js.map +1 -1
  19. package/dist/admin/apps/earn-vaults.d.ts +123 -9
  20. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  21. package/dist/admin/apps/earn-vaults.js +60 -7
  22. package/dist/admin/apps/earn-vaults.js.map +1 -1
  23. package/dist/admin/apps/organizations.d.ts.map +1 -1
  24. package/dist/admin/apps/organizations.js +4 -2
  25. package/dist/admin/apps/organizations.js.map +1 -1
  26. package/dist/admin/apps/verified-tokens.d.ts +90 -90
  27. package/dist/admin/ui.generated.d.ts +1 -1
  28. package/dist/admin/ui.generated.js +71 -71
  29. package/dist/admin/ui.generated.js.map +1 -1
  30. package/dist/apps/Zones.d.ts +16 -16
  31. package/dist/apps/Zones.js +4 -4
  32. package/dist/apps/data/App.d.ts +1699 -749
  33. package/dist/apps/data/App.d.ts.map +1 -1
  34. package/dist/apps/data/App.js +58 -9
  35. package/dist/apps/data/App.js.map +1 -1
  36. package/dist/apps/data/ZoneSelection.d.ts +62 -0
  37. package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
  38. package/dist/apps/data/ZoneSelection.js +44 -0
  39. package/dist/apps/data/ZoneSelection.js.map +1 -0
  40. package/dist/apps/data/routes/activities.d.ts +2417 -50
  41. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  42. package/dist/apps/data/routes/activities.js +1896 -1293
  43. package/dist/apps/data/routes/activities.js.map +1 -1
  44. package/dist/apps/data/routes/addresses.d.ts +471 -340
  45. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  46. package/dist/apps/data/routes/balances.d.ts +12 -12
  47. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  48. package/dist/apps/data/routes/balances.js +44 -17
  49. package/dist/apps/data/routes/balances.js.map +1 -1
  50. package/dist/apps/data/routes/blocks.d.ts +42 -42
  51. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  52. package/dist/apps/data/routes/blocks.js +22 -12
  53. package/dist/apps/data/routes/blocks.js.map +1 -1
  54. package/dist/apps/data/routes/coingecko.d.ts +179 -179
  55. package/dist/apps/data/routes/earn.d.ts +144 -19
  56. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  57. package/dist/apps/data/routes/earn.js +160 -28
  58. package/dist/apps/data/routes/earn.js.map +1 -1
  59. package/dist/apps/data/routes/exchanges.d.ts +719 -13
  60. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  61. package/dist/apps/data/routes/exchanges.js +16 -13
  62. package/dist/apps/data/routes/exchanges.js.map +1 -1
  63. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  64. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  65. package/dist/apps/data/routes/fee-amm.js +9 -11
  66. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  67. package/dist/apps/data/routes/indexer.d.ts +34 -34
  68. package/dist/apps/data/routes/receipts.d.ts +363 -263
  69. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  70. package/dist/apps/data/routes/receipts.js +29 -11
  71. package/dist/apps/data/routes/receipts.js.map +1 -1
  72. package/dist/apps/data/routes/rpc.js +24 -10
  73. package/dist/apps/data/routes/rpc.js.map +1 -1
  74. package/dist/apps/data/routes/tokenlist.d.ts +13 -13
  75. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  76. package/dist/apps/data/routes/tokenlist.js +16 -15
  77. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  78. package/dist/apps/data/routes/tokens.d.ts +112 -98
  79. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  80. package/dist/apps/data/routes/tokens.js +85 -35
  81. package/dist/apps/data/routes/tokens.js.map +1 -1
  82. package/dist/apps/data/routes/transactions.d.ts +7 -2
  83. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  84. package/dist/apps/data/routes/transactions.js +38 -18
  85. package/dist/apps/data/routes/transactions.js.map +1 -1
  86. package/dist/apps/data/routes/transfers.d.ts +1 -1
  87. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  88. package/dist/apps/data/routes/transfers.js +25 -21
  89. package/dist/apps/data/routes/transfers.js.map +1 -1
  90. package/dist/apps/data/routes/valuation.d.ts +1 -1
  91. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  92. package/dist/apps/data/routes/valuation.js +12 -7
  93. package/dist/apps/data/routes/valuation.js.map +1 -1
  94. package/dist/apps/data/routes/verified-tokens.d.ts +3 -3
  95. package/dist/apps/data/routes/webhooks.d.ts +15 -15
  96. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  97. package/dist/apps/data/routes/webhooks.js +2 -2
  98. package/dist/apps/data/routes/webhooks.js.map +1 -1
  99. package/dist/apps/data/routes/zones.d.ts +32 -32
  100. package/dist/apps/data/routes/zones.js +1 -1
  101. package/dist/apps/funding/App.d.ts +38 -27
  102. package/dist/apps/funding/App.d.ts.map +1 -1
  103. package/dist/apps/funding/routes/chains.d.ts.map +1 -1
  104. package/dist/apps/funding/routes/chains.js +5 -4
  105. package/dist/apps/funding/routes/chains.js.map +1 -1
  106. package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
  107. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  108. package/dist/apps/funding/routes/deposit-addresses.js +24 -19
  109. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  110. package/dist/apps/funding/routes/providers.d.ts +13 -13
  111. package/dist/apps/funding/routes/providers.d.ts.map +1 -1
  112. package/dist/apps/funding/routes/providers.js +3 -2
  113. package/dist/apps/funding/routes/providers.js.map +1 -1
  114. package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
  115. package/dist/apps/funding/routes/quotes.js +2 -2
  116. package/dist/apps/funding/routes/quotes.js.map +1 -1
  117. package/dist/apps/funding/routes/transfers.d.ts +60 -48
  118. package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
  119. package/dist/apps/funding/routes/transfers.js +27 -19
  120. package/dist/apps/funding/routes/transfers.js.map +1 -1
  121. package/dist/apps/management/App.d.ts +4558 -3700
  122. package/dist/apps/management/App.d.ts.map +1 -1
  123. package/dist/apps/management/Billing.d.ts.map +1 -1
  124. package/dist/apps/management/Billing.js +19 -6
  125. package/dist/apps/management/Billing.js.map +1 -1
  126. package/dist/apps/management/routes/api-keys.d.ts +786 -175
  127. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  128. package/dist/apps/management/routes/api-keys.js +312 -34
  129. package/dist/apps/management/routes/api-keys.js.map +1 -1
  130. package/dist/apps/management/routes/billing.d.ts +103 -30
  131. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  132. package/dist/apps/management/routes/billing.js +91 -32
  133. package/dist/apps/management/routes/billing.js.map +1 -1
  134. package/dist/apps/management/routes/faucet.d.ts +35 -35
  135. package/dist/apps/management/routes/faucet.d.ts.map +1 -1
  136. package/dist/apps/management/routes/faucet.js +23 -12
  137. package/dist/apps/management/routes/faucet.js.map +1 -1
  138. package/dist/apps/management/routes/invitations.d.ts +46 -13
  139. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  140. package/dist/apps/management/routes/invitations.js +79 -29
  141. package/dist/apps/management/routes/invitations.js.map +1 -1
  142. package/dist/apps/management/routes/invite-links.d.ts +120 -75
  143. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  144. package/dist/apps/management/routes/invite-links.js +100 -41
  145. package/dist/apps/management/routes/invite-links.js.map +1 -1
  146. package/dist/apps/management/routes/me.d.ts +5 -5
  147. package/dist/apps/management/routes/me.d.ts.map +1 -1
  148. package/dist/apps/management/routes/me.js +14 -10
  149. package/dist/apps/management/routes/me.js.map +1 -1
  150. package/dist/apps/management/routes/members.d.ts +99 -78
  151. package/dist/apps/management/routes/members.d.ts.map +1 -1
  152. package/dist/apps/management/routes/members.js +37 -18
  153. package/dist/apps/management/routes/members.js.map +1 -1
  154. package/dist/apps/management/routes/orgs.d.ts +48 -8
  155. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  156. package/dist/apps/management/routes/orgs.js +48 -19
  157. package/dist/apps/management/routes/orgs.js.map +1 -1
  158. package/dist/apps/management/routes/projects.d.ts +108 -46
  159. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  160. package/dist/apps/management/routes/projects.js +72 -21
  161. package/dist/apps/management/routes/projects.js.map +1 -1
  162. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  163. package/dist/apps/management/routes/scopes.js +8 -5
  164. package/dist/apps/management/routes/scopes.js.map +1 -1
  165. package/dist/apps/management/routes/usage.d.ts +82 -82
  166. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  167. package/dist/apps/management/routes/usage.js +41 -31
  168. package/dist/apps/management/routes/usage.js.map +1 -1
  169. package/dist/apps/management/routes/verified-token-requests.d.ts +35 -7
  170. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  171. package/dist/apps/management/routes/verified-token-requests.js +36 -17
  172. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  173. package/dist/apps/management/routes/webhooks.d.ts +200 -183
  174. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  175. package/dist/apps/management/routes/webhooks.js +80 -35
  176. package/dist/apps/management/routes/webhooks.js.map +1 -1
  177. package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
  178. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  179. package/dist/apps/mpp/internal/Adapter.js +12 -0
  180. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  181. package/dist/db/Db.d.ts +2 -0
  182. package/dist/db/Db.d.ts.map +1 -1
  183. package/dist/db/Db.js +52 -1
  184. package/dist/db/Db.js.map +1 -1
  185. package/dist/db/Schema.d.ts +26 -3
  186. package/dist/db/Schema.d.ts.map +1 -1
  187. package/dist/db/Schema.js +24 -5
  188. package/dist/db/Schema.js.map +1 -1
  189. package/dist/db/tables/earnVaults.d.ts +5 -1
  190. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  191. package/dist/db/tables/earnVaults.js +5 -0
  192. package/dist/db/tables/earnVaults.js.map +1 -1
  193. package/dist/db/tables/fundingCatalog.d.ts +4 -2
  194. package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
  195. package/dist/db/tables/fundingCatalog.js +5 -1
  196. package/dist/db/tables/fundingCatalog.js.map +1 -1
  197. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
  198. package/dist/db/tables/webhookDeliveries.js +10 -0
  199. package/dist/db/tables/webhookDeliveries.js.map +1 -1
  200. package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
  201. package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
  202. package/dist/db/tables/webhookQueueCompletions.js +32 -0
  203. package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
  204. package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
  205. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  206. package/dist/db/tables/webhookQueueEvents.js +68 -47
  207. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  208. package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
  209. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  210. package/dist/db/tables/webhookSubscriptions.js +29 -5
  211. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  212. package/dist/handlers/internal/utils.d.ts.map +1 -1
  213. package/dist/handlers/internal/utils.js +9 -0
  214. package/dist/handlers/internal/utils.js.map +1 -1
  215. package/dist/internal/Auth.d.ts +11 -2
  216. package/dist/internal/Auth.d.ts.map +1 -1
  217. package/dist/internal/Auth.js +19 -6
  218. package/dist/internal/Auth.js.map +1 -1
  219. package/dist/internal/Cache.d.ts.map +1 -1
  220. package/dist/internal/Cache.js +11 -7
  221. package/dist/internal/Cache.js.map +1 -1
  222. package/dist/internal/EarnVaults.d.ts +43 -4
  223. package/dist/internal/EarnVaults.d.ts.map +1 -1
  224. package/dist/internal/EarnVaults.js +167 -0
  225. package/dist/internal/EarnVaults.js.map +1 -1
  226. package/dist/internal/Fetch.d.ts +23 -0
  227. package/dist/internal/Fetch.d.ts.map +1 -0
  228. package/dist/internal/Fetch.js +26 -0
  229. package/dist/internal/Fetch.js.map +1 -0
  230. package/dist/internal/Log.d.ts +3 -1
  231. package/dist/internal/Log.d.ts.map +1 -1
  232. package/dist/internal/Log.js +16 -3
  233. package/dist/internal/Log.js.map +1 -1
  234. package/dist/internal/OpenApi.d.ts +30 -24
  235. package/dist/internal/OpenApi.d.ts.map +1 -1
  236. package/dist/internal/OpenApi.js +140 -41
  237. package/dist/internal/OpenApi.js.map +1 -1
  238. package/dist/internal/Response.d.ts +14 -9
  239. package/dist/internal/Response.d.ts.map +1 -1
  240. package/dist/internal/Response.js +16 -5
  241. package/dist/internal/Response.js.map +1 -1
  242. package/dist/internal/Schema.d.ts +11 -10
  243. package/dist/internal/Schema.d.ts.map +1 -1
  244. package/dist/internal/Schema.js +14 -9
  245. package/dist/internal/Schema.js.map +1 -1
  246. package/dist/internal/Store.d.ts +28 -6
  247. package/dist/internal/Store.d.ts.map +1 -1
  248. package/dist/internal/Store.js +121 -25
  249. package/dist/internal/Store.js.map +1 -1
  250. package/dist/internal/Tidx.d.ts +2 -0
  251. package/dist/internal/Tidx.d.ts.map +1 -1
  252. package/dist/internal/Tidx.js +23 -6
  253. package/dist/internal/Tidx.js.map +1 -1
  254. package/dist/internal/Timeout.d.ts +36 -0
  255. package/dist/internal/Timeout.d.ts.map +1 -0
  256. package/dist/internal/Timeout.js +37 -0
  257. package/dist/internal/Timeout.js.map +1 -0
  258. package/dist/internal/Timing.d.ts +9 -0
  259. package/dist/internal/Timing.d.ts.map +1 -1
  260. package/dist/internal/Timing.js +7 -0
  261. package/dist/internal/Timing.js.map +1 -1
  262. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  263. package/dist/internal/WebhookDestination.js +3 -0
  264. package/dist/internal/WebhookDestination.js.map +1 -1
  265. package/dist/internal/Webhooks.d.ts +29 -12
  266. package/dist/internal/Webhooks.d.ts.map +1 -1
  267. package/dist/internal/Webhooks.js +37 -20
  268. package/dist/internal/Webhooks.js.map +1 -1
  269. package/dist/internal/funding/Action.d.ts +9 -0
  270. package/dist/internal/funding/Action.d.ts.map +1 -1
  271. package/dist/internal/funding/Action.js +16 -8
  272. package/dist/internal/funding/Action.js.map +1 -1
  273. package/dist/internal/funding/Catalog.d.ts +9 -2
  274. package/dist/internal/funding/Catalog.d.ts.map +1 -1
  275. package/dist/internal/funding/Catalog.js +19 -8
  276. package/dist/internal/funding/Catalog.js.map +1 -1
  277. package/dist/internal/funding/Deposit.d.ts +2 -2
  278. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  279. package/dist/internal/funding/Deposit.js +9 -8
  280. package/dist/internal/funding/Deposit.js.map +1 -1
  281. package/dist/internal/funding/DepositAddress.d.ts +4 -4
  282. package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
  283. package/dist/internal/funding/DepositAddress.js +9 -8
  284. package/dist/internal/funding/DepositAddress.js.map +1 -1
  285. package/dist/internal/funding/Provider.d.ts +68 -13
  286. package/dist/internal/funding/Provider.d.ts.map +1 -1
  287. package/dist/internal/funding/Provider.js +42 -20
  288. package/dist/internal/funding/Provider.js.map +1 -1
  289. package/dist/internal/funding/Transfer.d.ts +13 -12
  290. package/dist/internal/funding/Transfer.d.ts.map +1 -1
  291. package/dist/internal/funding/Transfer.js +23 -21
  292. package/dist/internal/funding/Transfer.js.map +1 -1
  293. package/dist/internal/funding/providers/stargate.d.ts +38 -0
  294. package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
  295. package/dist/internal/funding/providers/stargate.js +277 -0
  296. package/dist/internal/funding/providers/stargate.js.map +1 -0
  297. package/dist/internal/index.d.ts +1 -0
  298. package/dist/internal/index.d.ts.map +1 -1
  299. package/dist/internal/index.js +1 -0
  300. package/dist/internal/index.js.map +1 -1
  301. package/dist/providers/index.d.ts +7 -0
  302. package/dist/providers/index.d.ts.map +1 -1
  303. package/dist/providers/index.js +3 -0
  304. package/dist/providers/index.js.map +1 -1
  305. package/package.json +3 -3
  306. package/src/App.test.ts +148 -0
  307. package/src/App.ts +45 -4
  308. package/src/Assets.test.ts +18 -0
  309. package/src/Assets.ts +22 -0
  310. package/src/Client.test-d.ts +311 -16
  311. package/src/Scope.test.ts +20 -0
  312. package/src/Scope.ts +16 -0
  313. package/src/admin/apps/api-keys.test.ts +75 -0
  314. package/src/admin/apps/api-keys.ts +64 -0
  315. package/src/admin/apps/earn-vaults.test.ts +143 -0
  316. package/src/admin/apps/earn-vaults.ts +84 -7
  317. package/src/admin/apps/organizations.ts +6 -2
  318. package/src/admin/ui/src/lib/api-keys.ts +19 -0
  319. package/src/admin/ui/src/routes/api-keys.tsx +125 -2
  320. package/src/admin/ui.generated.ts +71 -71
  321. package/src/apps/Zones.test.ts +4 -4
  322. package/src/apps/Zones.ts +4 -4
  323. package/src/apps/composition.test.ts +1 -1
  324. package/src/apps/data/App.test.ts +72 -0
  325. package/src/apps/data/App.ts +58 -10
  326. package/src/apps/data/ZoneSelection.test.ts +196 -0
  327. package/src/apps/data/ZoneSelection.ts +108 -0
  328. package/src/apps/data/routes/activities.test.ts +1843 -2
  329. package/src/apps/data/routes/activities.ts +2211 -1388
  330. package/src/apps/data/routes/balances.ts +134 -98
  331. package/src/apps/data/routes/blocks.test.ts +533 -0
  332. package/src/apps/data/routes/blocks.ts +36 -17
  333. package/src/apps/data/routes/earn.test.ts +187 -25
  334. package/src/apps/data/routes/earn.ts +228 -32
  335. package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
  336. package/src/apps/data/routes/exchanges.test.ts +31 -1
  337. package/src/apps/data/routes/exchanges.ts +19 -15
  338. package/src/apps/data/routes/fee-amm.ts +18 -11
  339. package/src/apps/data/routes/receipts.ts +48 -17
  340. package/src/apps/data/routes/rpc.test.ts +75 -0
  341. package/src/apps/data/routes/rpc.ts +23 -9
  342. package/src/apps/data/routes/tokenlist.ts +21 -18
  343. package/src/apps/data/routes/tokens.test.ts +607 -0
  344. package/src/apps/data/routes/tokens.ts +312 -231
  345. package/src/apps/data/routes/transactions.ts +69 -30
  346. package/src/apps/data/routes/transfers.test.ts +424 -3
  347. package/src/apps/data/routes/transfers.ts +57 -36
  348. package/src/apps/data/routes/valuation.ts +94 -78
  349. package/src/apps/data/routes/webhooks.ts +6 -2
  350. package/src/apps/data/routes/zones.test.ts +21 -15
  351. package/src/apps/data/routes/zones.ts +1 -1
  352. package/src/apps/funding/routes/chains.test.ts +211 -7
  353. package/src/apps/funding/routes/chains.ts +19 -12
  354. package/src/apps/funding/routes/deposit-addresses.test.ts +416 -0
  355. package/src/apps/funding/routes/deposit-addresses.ts +101 -84
  356. package/src/apps/funding/routes/providers.ts +9 -5
  357. package/src/apps/funding/routes/quotes.test.ts +42 -0
  358. package/src/apps/funding/routes/quotes.ts +8 -5
  359. package/src/apps/funding/routes/transfers.test.ts +430 -40
  360. package/src/apps/funding/routes/transfers.ts +76 -59
  361. package/src/apps/management/Billing.test.ts +26 -0
  362. package/src/apps/management/Billing.ts +24 -7
  363. package/src/apps/management/routes/api-keys.test.ts +398 -0
  364. package/src/apps/management/routes/api-keys.ts +481 -145
  365. package/src/apps/management/routes/billing.test.ts +209 -0
  366. package/src/apps/management/routes/billing.ts +254 -177
  367. package/src/apps/management/routes/faucet.test.ts +39 -0
  368. package/src/apps/management/routes/faucet.ts +75 -41
  369. package/src/apps/management/routes/invitations.test.ts +216 -0
  370. package/src/apps/management/routes/invitations.ts +186 -109
  371. package/src/apps/management/routes/invite-links.test.ts +263 -1
  372. package/src/apps/management/routes/invite-links.ts +295 -214
  373. package/src/apps/management/routes/me.test.ts +49 -0
  374. package/src/apps/management/routes/me.ts +42 -32
  375. package/src/apps/management/routes/members.test.ts +124 -1
  376. package/src/apps/management/routes/members.ts +81 -51
  377. package/src/apps/management/routes/orgs.test.ts +176 -0
  378. package/src/apps/management/routes/orgs.ts +101 -59
  379. package/src/apps/management/routes/projects.test.ts +183 -0
  380. package/src/apps/management/routes/projects.ts +124 -60
  381. package/src/apps/management/routes/scopes.test.ts +44 -0
  382. package/src/apps/management/routes/scopes.ts +37 -28
  383. package/src/apps/management/routes/usage.test.ts +92 -0
  384. package/src/apps/management/routes/usage.ts +186 -151
  385. package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
  386. package/src/apps/management/routes/verified-token-requests.ts +166 -133
  387. package/src/apps/management/routes/webhooks.test.ts +234 -0
  388. package/src/apps/management/routes/webhooks.ts +191 -78
  389. package/src/apps/mpp/internal/Adapter.ts +13 -1
  390. package/src/db/Db.test.ts +41 -0
  391. package/src/db/Db.ts +75 -1
  392. package/src/db/Schema.ts +33 -5
  393. package/src/db/tables/earnVaults.test.ts +22 -0
  394. package/src/db/tables/earnVaults.ts +11 -1
  395. package/src/db/tables/fundingCatalog.test.ts +16 -2
  396. package/src/db/tables/fundingCatalog.ts +9 -3
  397. package/src/db/tables/webhookDeliveries.ts +13 -0
  398. package/src/db/tables/webhookQueueCompletions.ts +55 -0
  399. package/src/db/tables/webhookQueueEvents.ts +95 -61
  400. package/src/db/tables/webhookSubscriptions.ts +45 -6
  401. package/src/handlers/internal/utils.test.ts +53 -0
  402. package/src/handlers/internal/utils.ts +15 -0
  403. package/src/internal/Auth.ts +35 -9
  404. package/src/internal/Cache.ts +14 -7
  405. package/src/internal/EarnVaults.capabilities.test.ts +33 -0
  406. package/src/internal/EarnVaults.test.ts +79 -0
  407. package/src/internal/EarnVaults.ts +277 -0
  408. package/src/internal/Fetch.test.ts +46 -0
  409. package/src/internal/Fetch.ts +56 -0
  410. package/src/internal/Log.test.ts +21 -0
  411. package/src/internal/Log.ts +20 -5
  412. package/src/internal/OpenApi.ts +177 -51
  413. package/src/internal/Response.test.ts +95 -0
  414. package/src/internal/Response.ts +41 -3
  415. package/src/internal/Schema.test.ts +18 -0
  416. package/src/internal/Schema.ts +19 -9
  417. package/src/internal/Store.test.ts +364 -0
  418. package/src/internal/Store.ts +153 -27
  419. package/src/internal/Tidx.test.ts +21 -1
  420. package/src/internal/Tidx.ts +23 -6
  421. package/src/internal/Timeout.test.ts +35 -0
  422. package/src/internal/Timeout.ts +73 -0
  423. package/src/internal/Timing.ts +16 -0
  424. package/src/internal/WebhookDestination.ts +3 -0
  425. package/src/internal/Webhooks.test.ts +122 -8
  426. package/src/internal/Webhooks.ts +59 -29
  427. package/src/internal/funding/Action.test.ts +41 -1
  428. package/src/internal/funding/Action.ts +69 -41
  429. package/src/internal/funding/Catalog.test.ts +34 -0
  430. package/src/internal/funding/Catalog.ts +28 -11
  431. package/src/internal/funding/Deposit.ts +71 -64
  432. package/src/internal/funding/DepositAddress.ts +50 -43
  433. package/src/internal/funding/Provider.test.ts +73 -0
  434. package/src/internal/funding/Provider.ts +246 -170
  435. package/src/internal/funding/Transfer.ts +133 -110
  436. package/src/internal/funding/providers/index.test.ts +22 -0
  437. package/src/internal/funding/providers/relay.test.ts +2 -2
  438. package/src/internal/funding/providers/stargate.test.ts +163 -0
  439. package/src/internal/funding/providers/stargate.ts +409 -0
  440. package/src/internal/index.test.ts +1 -0
  441. package/src/internal/index.ts +1 -0
  442. package/src/providers/index.test.ts +1 -0
  443. package/src/providers/index.ts +9 -0
@@ -587,11 +587,21 @@ export function middleware<
587
587
  const overrides = options.overrides as
588
588
  | Record<string, PolicyOverride | false | undefined>
589
589
  | undefined
590
- const configuredOverride = overrides?.[key]
590
+ const routePolicies = policies(c)
591
+ const configuredOverride = (() => {
592
+ const configured = overrides?.[key]
593
+ if (configured !== undefined) return configured
594
+ const inheritedMethod = routePolicies.find(
595
+ (policy) => policy.inheritOverridesFrom,
596
+ )?.inheritOverridesFrom
597
+ if (inheritedMethod === undefined) return undefined
598
+ const inheritedKey = `${inheritedMethod.toUpperCase()} ${key.slice(key.indexOf(' ') + 1)}`
599
+ return overrides?.[inheritedKey]
600
+ })()
591
601
  const routeOverride =
592
602
  management && configuredOverride ? { mpp: configuredOverride.mpp } : configuredOverride
593
603
  const endpointPolicy = bindMppScope(
594
- resolvePolicy(base, defaults, [...policies(c), routeOverride], description),
604
+ resolvePolicy(base, defaults, [...routePolicies, routeOverride], description),
595
605
  scope,
596
606
  )
597
607
  if (!endpointPolicy) return next()
@@ -666,7 +676,10 @@ export declare namespace middleware {
666
676
  }
667
677
 
668
678
  /** MPP payment options used by auth middleware. */
669
- type MppOptions = Omit<NonNullable<Parameters<typeof Mppx.create>[0]>, 'methods'> & {
679
+ type MppOptions = Omit<
680
+ Parameters<typeof Mppx.create<readonly [ReturnType<typeof tempo.session>]>>[0],
681
+ 'methods'
682
+ > & {
670
683
  /** Paid-request quota per access principal. Defaults to 100 per minute. */
671
684
  rateLimit?: RateLimit.Limit | undefined
672
685
  /** Global Tempo Session options passed to the MPP method instantiator. */
@@ -1000,12 +1013,20 @@ export declare namespace install {
1000
1013
  }
1001
1014
 
1002
1015
  /** Creates route middleware that contributes an auth policy override. */
1003
- export function policy(options: PolicyOverride): MiddlewareHandler {
1016
+ export function policy(options: policy.Options): MiddlewareHandler {
1004
1017
  const middleware = createMiddleware((_, next) => next()) as MiddlewareHandler & PolicyHandler
1005
1018
  middleware[policySymbol] = options
1006
1019
  return middleware
1007
1020
  }
1008
1021
 
1022
+ export declare namespace policy {
1023
+ /** Route policy plus metadata for compatibility aliases. */
1024
+ type Options = PolicyOverride & {
1025
+ /** HTTP method whose configured override this route inherits when its own is absent. */
1026
+ inheritOverridesFrom?: string | undefined
1027
+ }
1028
+ }
1029
+
1009
1030
  /** Adds management POSTs for OpenAPI-registered MPP GET resources. */
1010
1031
  export function installMppManagementRoutes(
1011
1032
  app: Hono<any, any>,
@@ -1106,7 +1127,7 @@ type OpenApiRoute = {
1106
1127
  }
1107
1128
 
1108
1129
  type PolicyHandler = {
1109
- [policySymbol]?: PolicyOverride | undefined
1130
+ [policySymbol]?: policy.Options | undefined
1110
1131
  }
1111
1132
 
1112
1133
  type MppManagementHandler = {
@@ -1283,7 +1304,7 @@ function policies(c: hono_Context) {
1283
1304
  return matchedRoutes(c)
1284
1305
  .slice(c.req.routeIndex + 1)
1285
1306
  .map(policyFromRoute)
1286
- .filter((policy): policy is PolicyOverride => policy !== undefined)
1307
+ .filter((routePolicy): routePolicy is policy.Options => routePolicy !== undefined)
1287
1308
  }
1288
1309
 
1289
1310
  function openApiSpec(route: RouterRoute) {
@@ -1433,8 +1454,8 @@ export function require<environment extends Environment = Environment>(
1433
1454
  return proceed()
1434
1455
  }
1435
1456
 
1436
- const apiKey = await auth.apiKey?.resolve(c, credential.token)
1437
- if (!apiKey) {
1457
+ const apiKey_resolved = await auth.apiKey?.resolve(c, credential.token)
1458
+ if (!apiKey_resolved) {
1438
1459
  // A bearer session token is indistinguishable from an API key at the
1439
1460
  // header, so a failed key lookup falls through to the session lane
1440
1461
  // before rejecting.
@@ -1452,6 +1473,10 @@ export function require<environment extends Environment = Environment>(
1452
1473
  })
1453
1474
  }
1454
1475
 
1476
+ const scopes = Scope.expandAliases(apiKey_resolved.scopes)
1477
+ const apiKey =
1478
+ scopes === apiKey_resolved.scopes ? apiKey_resolved : { ...apiKey_resolved, scopes }
1479
+
1455
1480
  // Sandbox keys are testnet-only. A sandbox key that explicitly targets
1456
1481
  // mainnet (`?chainId`) is rejected with a clear message rather than
1457
1482
  // steered or downgraded to anonymous, so the caller learns their key does
@@ -1829,7 +1854,8 @@ function getRequestId(c: hono_Context) {
1829
1854
  return typeof variables['requestId'] === 'string' ? variables['requestId'] : undefined
1830
1855
  }
1831
1856
 
1832
- function hasPaymentCredential(c: hono_Context) {
1857
+ /** True when the request carries an `Authorization: Payment` MPP credential. */
1858
+ export function hasPaymentCredential(c: hono_Context) {
1833
1859
  const authorization = c.req.header('authorization')
1834
1860
  if (!authorization) return false
1835
1861
  return !!Credential.extractPaymentScheme(authorization)
@@ -58,10 +58,8 @@ export function response<environment extends Env>(
58
58
  ): MiddlewareHandler<environment> {
59
59
  const defaultCacheControl = options.cacheControl ?? policies.default
60
60
  const vary = options.vary ?? ['Accept-Encoding', 'Authorization', 'Tempo-API-Key', 'X-API-Key']
61
- // hono/cache suffixes its key with `::<directive>=<value>` for every
62
- // configured vary directive (trimmed, lowercased, deduped). Mirror that
63
- // normalization so the `no-cache` purge below deletes exactly the entry the
64
- // wrapped middleware reads — drift here would make refreshes silently miss.
61
+ // Mirror hono/cache's vary normalization so the `no-cache` purge below
62
+ // deletes exactly the entry the wrapped middleware reads.
65
63
  const varyKeyDirectives = [
66
64
  ...new Set(vary.map((name) => name.trim().toLowerCase()).filter(Boolean)),
67
65
  ]
@@ -95,10 +93,19 @@ export function response<environment extends Env>(
95
93
  type Caches = { open(name: string): Promise<{ delete(key: string): Promise<unknown> }> }
96
94
  const caches = (globalThis as { caches?: Caches }).caches
97
95
  if (noCache && !noStore && caches) {
98
- let key = await options.key(c)
96
+ // hono/cache 4.13 wraps generated keys in a canonical URL containing the
97
+ // request method and vary values. Keep this in sync with its
98
+ // `createCacheKey` so refreshes remove the stored GET response.
99
+ const key = await options.key(c)
100
+ const url = new URL('/.hono/cache', c.req.url)
101
+ url.searchParams.append('__hono_cache_key', key.split('#', 1)[0] ?? key)
102
+ url.searchParams.append('__hono_cache_method', c.req.method)
99
103
  for (const name of varyKeyDirectives)
100
- key += `::${name}=${encodeURIComponent(c.req.raw.headers.get(name) ?? '')}`
101
- await (await caches.open(options.name)).delete(key)
104
+ url.searchParams.append(
105
+ '__hono_cache_vary',
106
+ JSON.stringify([name, c.req.raw.headers.get(name) ?? '']),
107
+ )
108
+ await (await caches.open(options.name)).delete(url.href)
102
109
  }
103
110
 
104
111
  // Run ETag inside Hono's cache miss path so fresh responses are hashed
@@ -0,0 +1,33 @@
1
+ import * as EarnVaults from './EarnVaults.js'
2
+
3
+ describe('addZoneRouteCapabilities', () => {
4
+ test('adds private routing and router swaps', () => {
5
+ expect(
6
+ EarnVaults.addZoneRouteCapabilities({
7
+ asyncRedeem: false,
8
+ boundedRedeem: true,
9
+ deposit: true,
10
+ exactWithdraw: true,
11
+ inKindDeposit: true,
12
+ privateRouting: false,
13
+ redeem: true,
14
+ routerSwaps: false,
15
+ }),
16
+ ).toMatchObject({ privateRouting: true, routerSwaps: true })
17
+ })
18
+ })
19
+
20
+ describe('deriveZoneId', () => {
21
+ test('derives IDs from mainnet and testnet Zone chain schemes', () => {
22
+ expect([
23
+ EarnVaults.deriveZoneId(421_700_006),
24
+ EarnVaults.deriveZoneId(1_424_310_003),
25
+ ]).toStrictEqual([6, 3])
26
+ })
27
+
28
+ test('rejects a source chain ID', () => {
29
+ expect(() => EarnVaults.deriveZoneId(31_318)).toThrowErrorMatchingInlineSnapshot(
30
+ `[EarnVaults.InvalidRegistryError: Chain 31318 does not use a supported Zone chain-ID scheme.]`,
31
+ )
32
+ })
33
+ })
@@ -1,6 +1,7 @@
1
1
  import { parseAbi } from 'viem'
2
2
  import { tempoTestnet } from 'viem/tempo/chains'
3
3
 
4
+ import * as TestEarn from '../../test/Earn.js'
4
5
  import * as Runtime from '../../test/runtime.js'
5
6
  import * as TestViem from '../../test/Viem.js'
6
7
  import * as Zones from '../apps/Zones.js'
@@ -43,6 +44,17 @@ describe('schema.ResolveInput', () => {
43
44
  })
44
45
  })
45
46
 
47
+ describe('schema.ZoneRoute', () => {
48
+ test('normalizes the router address', () => {
49
+ expect(
50
+ EarnVaults.schema.ZoneRoute.parse({
51
+ ...TestEarn.zoneRoute,
52
+ earnRouter: TestEarn.zoneRoute.earnRouter.toUpperCase().replace('0X', '0x'),
53
+ }),
54
+ ).toStrictEqual(TestEarn.zoneRoute)
55
+ })
56
+ })
57
+
46
58
  describe('classifyEngineType', () => {
47
59
  test('classifies supported capability fingerprints', () => {
48
60
  expect([
@@ -193,3 +205,70 @@ describe('resolve', () => {
193
205
  60_000,
194
206
  )
195
207
  })
208
+
209
+ describe('resolveZoneRoutes', () => {
210
+ test.runIf(Runtime.get().mode === 'testnet')(
211
+ 'verifies immutable router bindings and derives private tokens',
212
+ async () => {
213
+ const getClient = Viem.createGetClient({
214
+ defaultChainId: tempoTestnet.id,
215
+ rpc: TestViem.rpc,
216
+ zones: [TestEarn.zone],
217
+ })
218
+ const discovery = await EarnVaults.resolve({
219
+ getClient,
220
+ input: {
221
+ chainId: tempoTestnet.id,
222
+ vaultAddress: TestEarn.zoneVaultAddress,
223
+ },
224
+ zones: [TestEarn.zone],
225
+ })
226
+ const routes = await EarnVaults.resolveZoneRoutes({
227
+ discovery,
228
+ getClient,
229
+ routes: [TestEarn.zoneRoute],
230
+ zones: [TestEarn.zone],
231
+ })
232
+
233
+ expect(routes).toHaveLength(1)
234
+ expect(routes[0]).toMatchObject({
235
+ ...TestEarn.zoneRoute,
236
+ name: TestEarn.zone.name,
237
+ })
238
+ expect(routes[0]?.inputTokens).toHaveLength(1)
239
+ expect(routes[0]?.outputTokens).toStrictEqual(routes[0]?.inputTokens)
240
+ await expect(
241
+ EarnVaults.resolveZoneRoutes({
242
+ discovery,
243
+ getClient,
244
+ routes: [TestEarn.zoneRoute, TestEarn.zoneRoute],
245
+ zones: [TestEarn.zone],
246
+ }),
247
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
248
+ `[EarnVaults.InvalidRegistryError: Zone 1424310003 is configured more than once.]`,
249
+ )
250
+ await expect(
251
+ EarnVaults.resolveZoneRoutes({
252
+ discovery,
253
+ getClient,
254
+ routes: [
255
+ { ...TestEarn.zoneRoute, deploymentBlock: TestEarn.zoneRoute.deploymentBlock + 1 },
256
+ ],
257
+ zones: [TestEarn.zone],
258
+ }),
259
+ ).rejects.toMatchObject({
260
+ result: {
261
+ issues: [
262
+ {
263
+ actual: String(TestEarn.zoneRoute.deploymentBlock + 1),
264
+ code: 'zone-deployment-block-mismatch',
265
+ message: 'Earn router deployment block does not match its code boundary.',
266
+ },
267
+ ],
268
+ status: 'mismatch',
269
+ },
270
+ })
271
+ },
272
+ 60_000,
273
+ )
274
+ })
@@ -1,3 +1,4 @@
1
+ import { ZoneId } from 'ox/tempo'
1
2
  import {
2
3
  ContractFunctionExecutionError,
3
4
  ContractFunctionRevertedError,
@@ -161,6 +162,28 @@ export namespace schema {
161
162
  })
162
163
  .check(z.describe('Onchain identity of an Earn vault.'))
163
164
 
165
+ /** Schema for one curated Earn route through a private Zone. */
166
+ export const ZoneRoute = z
167
+ .strictObject({
168
+ chainId: Schema.ChainId.check(
169
+ z.describe('Private Zone chain id.'),
170
+ z.meta({ examples: [1424310003] }),
171
+ ),
172
+ deploymentBlock: z
173
+ .number()
174
+ .check(
175
+ z.int(),
176
+ z.nonnegative(),
177
+ z.describe('Parent-chain block that deployed the Earn router.'),
178
+ z.meta({ examples: [31730087] }),
179
+ ),
180
+ earnRouter: Schema.Address.check(
181
+ z.describe('Parent-chain router for this Zone and Earn vault.'),
182
+ z.meta({ examples: ['0xebedc74ffeead186acc6cac05eb82fb9e093a7c7'] }),
183
+ ),
184
+ })
185
+ .check(z.describe('Curated Earn route through one private Zone.'))
186
+
164
187
  /** Schema for live state resolved from one Earn vault. */
165
188
  export const Discovery = z
166
189
  .strictObject({
@@ -228,12 +251,48 @@ export type Discovery = z.output<typeof schema.Discovery>
228
251
  /** Onchain identity of an Earn vault. */
229
252
  export type ResolveInput = z.output<typeof schema.ResolveInput>
230
253
 
254
+ /** Curated Earn route through one private Zone. */
255
+ export type ZoneRoute = z.output<typeof schema.ZoneRoute>
256
+
257
+ /** Curated Zone route with immutable router bindings resolved onchain. */
258
+ export type ResolvedZoneRoute = ZoneRoute & {
259
+ /** Tokens accepted by private deposits. */
260
+ inputTokens: readonly Address[]
261
+ /** Configured private Zone name. */
262
+ name: string
263
+ /** Tokens returned by private redemptions. */
264
+ outputTokens: readonly Address[]
265
+ }
266
+
267
+ /** Adds capabilities proven by a verified private Zone route. */
268
+ export function addZoneRouteCapabilities(
269
+ capabilities: NonNullable<Discovery['capabilities']>,
270
+ ): NonNullable<Discovery['capabilities']> {
271
+ return { ...capabilities, privateRouting: true, routerSwaps: true }
272
+ }
273
+
274
+ /** Derives a Zone ID from any supported Zone chain-ID scheme. */
275
+ export function deriveZoneId(chainId: number): number {
276
+ for (const sourceId of [4_217, 42_431] satisfies readonly ZoneId.SourceId[]) {
277
+ const zoneId = ZoneId.fromChainId(chainId, sourceId)
278
+ if (zoneId >= 0 && ZoneId.toChainId(zoneId, sourceId) === chainId) return zoneId
279
+ }
280
+ throw new InvalidRegistryError(`Chain ${chainId} does not use a supported Zone chain-ID scheme.`)
281
+ }
282
+
231
283
  /** Stable code describing an onchain verification issue. */
232
284
  export type VerificationIssueCode =
233
285
  | 'chain-mismatch'
234
286
  | 'engine-asset-mismatch'
235
287
  | 'policy-unsupported'
236
288
  | 'read-failed'
289
+ | 'zone-deployment-block-mismatch'
290
+ | 'zone-flow-unsupported'
291
+ | 'zone-id-mismatch'
292
+ | 'zone-router-invalid'
293
+ | 'zone-share-mismatch'
294
+ | 'zone-vault-asset-mismatch'
295
+ | 'zone-vault-mismatch'
237
296
 
238
297
  /** One onchain verification issue. */
239
298
  export type VerificationIssue = {
@@ -303,6 +362,16 @@ type RouterCapabilities = {
303
362
  redeem: boolean
304
363
  }
305
364
 
365
+ type ZoneRouteBindings = {
366
+ allowedZoneId: number
367
+ deposit: boolean
368
+ earnShare: Address
369
+ earnVault: Address
370
+ privateAsset: Address
371
+ redeem: boolean
372
+ vaultAsset: Address
373
+ }
374
+
306
375
  type TokenMetadata = Omit<Discovery['assetToken'], 'address'>
307
376
 
308
377
  const engineBindingsAbi = parseAbi(['function vault() view returns (address)'])
@@ -363,6 +432,139 @@ export declare namespace resolve {
363
432
  }
364
433
  }
365
434
 
435
+ /** Resolves and verifies every curated Zone route for one Earn vault. */
436
+ export async function resolveZoneRoutes(
437
+ options: resolveZoneRoutes.Options,
438
+ ): Promise<ResolvedZoneRoute[]> {
439
+ const result = z.array(schema.ZoneRoute).safeParse(options.routes)
440
+ if (!result.success) throw invalid(result.error)
441
+
442
+ const chainIds = new Set<number>()
443
+ const routers = new Set<string>()
444
+ for (const route of result.data) {
445
+ if (chainIds.has(route.chainId))
446
+ throw new InvalidRegistryError(`Zone ${route.chainId} is configured more than once.`)
447
+ if (routers.has(route.earnRouter))
448
+ throw new InvalidRegistryError(
449
+ `Earn router ${route.earnRouter} is configured more than once.`,
450
+ )
451
+ chainIds.add(route.chainId)
452
+ routers.add(route.earnRouter)
453
+ }
454
+ if (result.data.length === 0) return []
455
+
456
+ const client = options.getClient(options.discovery.chainId)
457
+ return Promise.all(
458
+ result.data.map(async (route) => {
459
+ const zone = options.zones.find((candidate) => candidate.id === route.chainId)
460
+ if (!zone) throw new InvalidRegistryError(`Zone ${route.chainId} is not configured.`)
461
+ if (zone.sourceId !== options.discovery.chainId)
462
+ throw new InvalidRegistryError(
463
+ `Zone ${route.chainId} does not belong to chain ${options.discovery.chainId}.`,
464
+ )
465
+ const expectedZoneId = deriveZoneId(route.chainId)
466
+
467
+ const [code, previousCode] = await Promise.all([
468
+ client.getCode({
469
+ address: route.earnRouter,
470
+ blockNumber: BigInt(route.deploymentBlock),
471
+ }),
472
+ route.deploymentBlock === 0
473
+ ? undefined
474
+ : client.getCode({
475
+ address: route.earnRouter,
476
+ blockNumber: BigInt(route.deploymentBlock - 1),
477
+ }),
478
+ ])
479
+ if (!code || code === '0x' || (previousCode !== undefined && previousCode !== '0x'))
480
+ throw mismatch({
481
+ discovery: options.discovery,
482
+ issues: [
483
+ {
484
+ actual: String(route.deploymentBlock),
485
+ code: 'zone-deployment-block-mismatch',
486
+ message: 'Earn router deployment block does not match its code boundary.',
487
+ },
488
+ ],
489
+ })
490
+
491
+ const bindings = await readZoneRouteBindings(client, { earnRouter: route.earnRouter }).catch(
492
+ (error) => {
493
+ if (!isMissingOptionalFunctionError(error)) throw error
494
+ throw mismatch({
495
+ discovery: options.discovery,
496
+ issues: [
497
+ {
498
+ actual: route.earnRouter,
499
+ code: 'zone-router-invalid',
500
+ message: 'Earn router does not expose the required immutable bindings.',
501
+ },
502
+ ],
503
+ })
504
+ },
505
+ )
506
+ const issues: VerificationIssue[] = []
507
+ if (bindings.allowedZoneId !== expectedZoneId)
508
+ issues.push({
509
+ actual: bindings.allowedZoneId.toString(),
510
+ code: 'zone-id-mismatch',
511
+ expected: String(expectedZoneId),
512
+ message: 'Earn router is configured for a different Zone.',
513
+ })
514
+ compareAddress(
515
+ issues,
516
+ 'zone-vault-mismatch',
517
+ 'Earn router is configured for a different Earn vault.',
518
+ options.discovery.vaultAddress,
519
+ bindings.earnVault,
520
+ )
521
+ compareAddress(
522
+ issues,
523
+ 'zone-vault-asset-mismatch',
524
+ 'Earn router vault asset does not match the Earn vault.',
525
+ options.discovery.assetToken.address,
526
+ bindings.vaultAsset,
527
+ )
528
+ compareAddress(
529
+ issues,
530
+ 'zone-share-mismatch',
531
+ 'Earn router share token does not match the Earn vault.',
532
+ options.discovery.shareToken.address,
533
+ bindings.earnShare,
534
+ )
535
+ if (!bindings.deposit || !bindings.redeem)
536
+ issues.push({
537
+ actual: `deposit=${bindings.deposit},redeem=${bindings.redeem}`,
538
+ code: 'zone-flow-unsupported',
539
+ expected: 'deposit=true,redeem=true',
540
+ message: 'Earn router must support private deposits and redemptions.',
541
+ })
542
+ if (issues.length > 0) throw mismatch({ discovery: options.discovery, issues })
543
+
544
+ return {
545
+ ...route,
546
+ inputTokens: [bindings.privateAsset],
547
+ name: zone.name,
548
+ outputTokens: [bindings.privateAsset],
549
+ }
550
+ }),
551
+ )
552
+ }
553
+
554
+ export declare namespace resolveZoneRoutes {
555
+ /** Inputs for resolving and verifying curated Zone routes. */
556
+ type Options = {
557
+ /** Live state of the Earn vault bound by every router. */
558
+ discovery: Discovery
559
+ /** Resolves the parent-chain client used to read each router. */
560
+ getClient: Viem.GetClient
561
+ /** Curated Zone routes to verify. */
562
+ routes: unknown
563
+ /** Private Zones configured by the API. */
564
+ zones: readonly Chain[]
565
+ }
566
+ }
567
+
366
568
  /** Infers the supported engine type from its capability fingerprint. */
367
569
  export function classifyEngineType(
368
570
  options: classifyEngineType.Options,
@@ -729,6 +931,60 @@ declare namespace readEngineBindings {
729
931
  }
730
932
  }
731
933
 
934
+ async function readZoneRouteBindings(
935
+ client: Client,
936
+ options: readZoneRouteBindings.Options,
937
+ ): Promise<ZoneRouteBindings> {
938
+ const [allowedZoneId, earnShare, earnVault, privateAsset, vaultAsset, deposit, redeem] =
939
+ await Promise.all([
940
+ client.readContract({
941
+ abi: Abis.earnRouter,
942
+ address: options.earnRouter,
943
+ functionName: 'allowedZoneId',
944
+ }),
945
+ client.readContract({
946
+ abi: Abis.earnRouter,
947
+ address: options.earnRouter,
948
+ functionName: 'earnShare',
949
+ }),
950
+ client.readContract({
951
+ abi: Abis.earnRouter,
952
+ address: options.earnRouter,
953
+ functionName: 'earnVault',
954
+ }),
955
+ client.readContract({
956
+ abi: Abis.earnRouter,
957
+ address: options.earnRouter,
958
+ functionName: 'privateAsset',
959
+ }),
960
+ client.readContract({
961
+ abi: Abis.earnRouter,
962
+ address: options.earnRouter,
963
+ functionName: 'vaultAsset',
964
+ }),
965
+ client.readContract({
966
+ abi: Abis.earnRouter,
967
+ address: options.earnRouter,
968
+ args: [0],
969
+ functionName: 'supportsFlow',
970
+ }),
971
+ client.readContract({
972
+ abi: Abis.earnRouter,
973
+ address: options.earnRouter,
974
+ args: [1],
975
+ functionName: 'supportsFlow',
976
+ }),
977
+ ])
978
+ return { allowedZoneId, deposit, earnShare, earnVault, privateAsset, redeem, vaultAsset }
979
+ }
980
+
981
+ declare namespace readZoneRouteBindings {
982
+ type Options = {
983
+ /** Parent-chain Earn router to inspect. */
984
+ earnRouter: Address
985
+ }
986
+ }
987
+
732
988
  async function readRouterCapabilities(
733
989
  client: Client,
734
990
  options: readRouterCapabilities.Options,
@@ -840,6 +1096,27 @@ function compareAddress(
840
1096
  if (!isAddressEqual(actual, expected)) issues.push({ actual, code, expected, message })
841
1097
  }
842
1098
 
1099
+ function mismatch(options: mismatch.Options): VerificationError {
1100
+ return new VerificationError({
1101
+ issues: options.issues,
1102
+ snapshot: {
1103
+ assetToken: options.discovery.assetToken,
1104
+ isSynced: options.discovery.state.isAccountingAligned,
1105
+ shareToken: options.discovery.shareToken,
1106
+ },
1107
+ status: 'mismatch',
1108
+ })
1109
+ }
1110
+
1111
+ declare namespace mismatch {
1112
+ type Options = {
1113
+ /** Live vault state captured with the mismatch. */
1114
+ discovery: Discovery
1115
+ /** Verification issues that rejected the deployment. */
1116
+ issues: readonly VerificationIssue[]
1117
+ }
1118
+ }
1119
+
843
1120
  function unavailable(): VerificationUnavailable {
844
1121
  return {
845
1122
  issues: [
@@ -0,0 +1,46 @@
1
+ import * as http from 'node:http'
2
+
3
+ import * as Fetch from './Fetch.js'
4
+
5
+ describe('withTimeout', () => {
6
+ test('aborts a fetch after the configured duration', async () => {
7
+ const server = http.createServer(() => {})
8
+ const url = await listen(server)
9
+
10
+ try {
11
+ const fetch = Fetch.withTimeout(globalThis.fetch, { timeout: 10 })
12
+ await expect(fetch(url)).rejects.toMatchObject({ name: 'TimeoutError' })
13
+ } finally {
14
+ server.closeAllConnections()
15
+ await close(server)
16
+ }
17
+ })
18
+ })
19
+
20
+ describe('resolveSignal', () => {
21
+ test('preserves caller and Request signals', () => {
22
+ const signal = AbortSignal.timeout(1_000)
23
+ const request = new Request('https://api.tempo.xyz', { signal })
24
+
25
+ expect(Fetch.resolveSignal('https://api.tempo.xyz', { init: { signal }, timeout: 10 })).toBe(
26
+ signal,
27
+ )
28
+ expect(Fetch.resolveSignal(request, { timeout: 10 })).toBe(request.signal)
29
+ })
30
+ })
31
+
32
+ function close(server: http.Server): Promise<void> {
33
+ return new Promise((resolve, reject) => {
34
+ server.close((error) => (error ? reject(error) : resolve()))
35
+ })
36
+ }
37
+
38
+ function listen(server: http.Server): Promise<string> {
39
+ return new Promise((resolve) => {
40
+ server.listen(0, '127.0.0.1', () => {
41
+ const address = server.address()
42
+ if (!address || typeof address === 'string') throw new Error('Expected a TCP server address.')
43
+ resolve(`http://127.0.0.1:${address.port}`)
44
+ })
45
+ })
46
+ }