tapimo 0.10.2 → 0.12.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 (386) hide show
  1. package/dist/App.d.ts +4896 -2166
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +2 -2
  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/Webhooks.d.ts +0 -75
  10. package/dist/Webhooks.d.ts.map +1 -1
  11. package/dist/Webhooks.js +1 -143
  12. package/dist/Webhooks.js.map +1 -1
  13. package/dist/admin/App.d.ts +127 -78
  14. package/dist/admin/App.d.ts.map +1 -1
  15. package/dist/admin/apps/earn-vaults.d.ts +115 -1
  16. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  17. package/dist/admin/apps/earn-vaults.js +59 -6
  18. package/dist/admin/apps/earn-vaults.js.map +1 -1
  19. package/dist/admin/apps/organizations.d.ts +3 -3
  20. package/dist/admin/apps/organizations.d.ts.map +1 -1
  21. package/dist/admin/apps/organizations.js +4 -2
  22. package/dist/admin/apps/organizations.js.map +1 -1
  23. package/dist/admin/apps/verified-tokens.d.ts +83 -83
  24. package/dist/admin/ui.generated.d.ts +1 -1
  25. package/dist/admin/ui.generated.d.ts.map +1 -1
  26. package/dist/admin/ui.generated.js +151 -151
  27. package/dist/admin/ui.generated.js.map +1 -1
  28. package/dist/apps/data/App.d.ts +5924 -4310
  29. package/dist/apps/data/App.d.ts.map +1 -1
  30. package/dist/apps/data/App.js +61 -9
  31. package/dist/apps/data/App.js.map +1 -1
  32. package/dist/apps/data/ZoneSelection.d.ts +62 -0
  33. package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
  34. package/dist/apps/data/ZoneSelection.js +44 -0
  35. package/dist/apps/data/ZoneSelection.js.map +1 -0
  36. package/dist/apps/data/routes/activities.d.ts +2368 -5
  37. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  38. package/dist/apps/data/routes/activities.js +423 -114
  39. package/dist/apps/data/routes/activities.js.map +1 -1
  40. package/dist/apps/data/routes/addresses.d.ts +131 -0
  41. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  42. package/dist/apps/data/routes/balances.d.ts +25 -25
  43. package/dist/apps/data/routes/balances.js +1 -1
  44. package/dist/apps/data/routes/balances.js.map +1 -1
  45. package/dist/apps/data/routes/blocks.d.ts +1 -1
  46. package/dist/apps/data/routes/blocks.js +1 -1
  47. package/dist/apps/data/routes/blocks.js.map +1 -1
  48. package/dist/apps/data/routes/earn.d.ts +135 -10
  49. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  50. package/dist/apps/data/routes/earn.js +157 -25
  51. package/dist/apps/data/routes/earn.js.map +1 -1
  52. package/dist/apps/data/routes/exchanges.d.ts +829 -123
  53. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  54. package/dist/apps/data/routes/exchanges.js +16 -13
  55. package/dist/apps/data/routes/exchanges.js.map +1 -1
  56. package/dist/apps/data/routes/fee-amm.d.ts +26 -26
  57. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  58. package/dist/apps/data/routes/fee-amm.js +9 -11
  59. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  60. package/dist/apps/data/routes/receipts.d.ts +54 -54
  61. package/dist/apps/data/routes/receipts.js +1 -1
  62. package/dist/apps/data/routes/receipts.js.map +1 -1
  63. package/dist/apps/data/routes/rpc.js +24 -10
  64. package/dist/apps/data/routes/rpc.js.map +1 -1
  65. package/dist/apps/data/routes/tokenlist.d.ts +12 -12
  66. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  67. package/dist/apps/data/routes/tokenlist.js +16 -15
  68. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  69. package/dist/apps/data/routes/tokens.d.ts +17 -3
  70. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  71. package/dist/apps/data/routes/tokens.js +34 -15
  72. package/dist/apps/data/routes/tokens.js.map +1 -1
  73. package/dist/apps/data/routes/transactions.d.ts +1 -1
  74. package/dist/apps/data/routes/transactions.js +1 -1
  75. package/dist/apps/data/routes/transactions.js.map +1 -1
  76. package/dist/apps/data/routes/transfers.d.ts +13 -13
  77. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  78. package/dist/apps/data/routes/transfers.js +7 -9
  79. package/dist/apps/data/routes/transfers.js.map +1 -1
  80. package/dist/apps/data/routes/valuation.d.ts +21 -21
  81. package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
  82. package/dist/apps/data/routes/webhooks.d.ts +1011 -151
  83. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  84. package/dist/apps/data/routes/webhooks.js +126 -739
  85. package/dist/apps/data/routes/webhooks.js.map +1 -1
  86. package/dist/apps/data/routes/zones.d.ts +15 -15
  87. package/dist/apps/funding/App.d.ts +27 -27
  88. package/dist/apps/funding/routes/chains.d.ts.map +1 -1
  89. package/dist/apps/funding/routes/chains.js +5 -4
  90. package/dist/apps/funding/routes/chains.js.map +1 -1
  91. package/dist/apps/funding/routes/deposit-addresses.d.ts +18 -18
  92. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  93. package/dist/apps/funding/routes/deposit-addresses.js +8 -8
  94. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  95. package/dist/apps/funding/routes/providers.d.ts.map +1 -1
  96. package/dist/apps/funding/routes/providers.js +3 -2
  97. package/dist/apps/funding/routes/providers.js.map +1 -1
  98. package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
  99. package/dist/apps/funding/routes/quotes.js +2 -2
  100. package/dist/apps/funding/routes/quotes.js.map +1 -1
  101. package/dist/apps/funding/routes/transfers.d.ts +33 -33
  102. package/dist/apps/management/App.d.ts +1433 -322
  103. package/dist/apps/management/App.d.ts.map +1 -1
  104. package/dist/apps/management/Billing.d.ts.map +1 -1
  105. package/dist/apps/management/Billing.js +19 -6
  106. package/dist/apps/management/Billing.js.map +1 -1
  107. package/dist/apps/management/routes/api-keys.d.ts +154 -94
  108. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  109. package/dist/apps/management/routes/api-keys.js +76 -30
  110. package/dist/apps/management/routes/api-keys.js.map +1 -1
  111. package/dist/apps/management/routes/billing.d.ts +103 -30
  112. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  113. package/dist/apps/management/routes/billing.js +91 -32
  114. package/dist/apps/management/routes/billing.js.map +1 -1
  115. package/dist/apps/management/routes/faucet.d.ts +12 -12
  116. package/dist/apps/management/routes/faucet.d.ts.map +1 -1
  117. package/dist/apps/management/routes/faucet.js +23 -12
  118. package/dist/apps/management/routes/faucet.js.map +1 -1
  119. package/dist/apps/management/routes/invitations.d.ts +46 -13
  120. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  121. package/dist/apps/management/routes/invitations.js +79 -29
  122. package/dist/apps/management/routes/invitations.js.map +1 -1
  123. package/dist/apps/management/routes/invite-links.d.ts +128 -83
  124. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  125. package/dist/apps/management/routes/invite-links.js +100 -41
  126. package/dist/apps/management/routes/invite-links.js.map +1 -1
  127. package/dist/apps/management/routes/me.d.ts +5 -5
  128. package/dist/apps/management/routes/me.d.ts.map +1 -1
  129. package/dist/apps/management/routes/me.js +14 -10
  130. package/dist/apps/management/routes/me.js.map +1 -1
  131. package/dist/apps/management/routes/members.d.ts +68 -47
  132. package/dist/apps/management/routes/members.d.ts.map +1 -1
  133. package/dist/apps/management/routes/members.js +37 -18
  134. package/dist/apps/management/routes/members.js.map +1 -1
  135. package/dist/apps/management/routes/orgs.d.ts +48 -8
  136. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  137. package/dist/apps/management/routes/orgs.js +48 -19
  138. package/dist/apps/management/routes/orgs.js.map +1 -1
  139. package/dist/apps/management/routes/projects.d.ts +130 -68
  140. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  141. package/dist/apps/management/routes/projects.js +72 -21
  142. package/dist/apps/management/routes/projects.js.map +1 -1
  143. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  144. package/dist/apps/management/routes/scopes.js +8 -5
  145. package/dist/apps/management/routes/scopes.js.map +1 -1
  146. package/dist/apps/management/routes/usage.d.ts +38 -38
  147. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  148. package/dist/apps/management/routes/usage.js +41 -31
  149. package/dist/apps/management/routes/usage.js.map +1 -1
  150. package/dist/apps/management/routes/verified-token-requests.d.ts +34 -6
  151. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  152. package/dist/apps/management/routes/verified-token-requests.js +36 -17
  153. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  154. package/dist/apps/management/routes/webhooks.d.ts +1186 -197
  155. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  156. package/dist/apps/management/routes/webhooks.js +106 -38
  157. package/dist/apps/management/routes/webhooks.js.map +1 -1
  158. package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
  159. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  160. package/dist/apps/mpp/internal/Adapter.js +12 -0
  161. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  162. package/dist/db/Db.d.ts +2 -0
  163. package/dist/db/Db.d.ts.map +1 -1
  164. package/dist/db/Db.js +61 -0
  165. package/dist/db/Db.js.map +1 -1
  166. package/dist/db/Schema.d.ts +30 -2
  167. package/dist/db/Schema.d.ts.map +1 -1
  168. package/dist/db/Schema.js +28 -3
  169. package/dist/db/Schema.js.map +1 -1
  170. package/dist/db/tables/earnVaults.d.ts +5 -1
  171. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  172. package/dist/db/tables/earnVaults.js +5 -0
  173. package/dist/db/tables/earnVaults.js.map +1 -1
  174. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
  175. package/dist/db/tables/webhookDeliveries.js +10 -0
  176. package/dist/db/tables/webhookDeliveries.js.map +1 -1
  177. package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
  178. package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
  179. package/dist/db/tables/webhookQueueCompletions.js +32 -0
  180. package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
  181. package/dist/db/tables/webhookQueueEvents.d.ts +16 -20
  182. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  183. package/dist/db/tables/webhookQueueEvents.js +68 -43
  184. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  185. package/dist/db/tables/webhookSubscriptions.d.ts +47 -72
  186. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  187. package/dist/db/tables/webhookSubscriptions.js +92 -105
  188. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  189. package/dist/internal/Auth.d.ts +8 -1
  190. package/dist/internal/Auth.d.ts.map +1 -1
  191. package/dist/internal/Auth.js +13 -3
  192. package/dist/internal/Auth.js.map +1 -1
  193. package/dist/internal/Cache.d.ts.map +1 -1
  194. package/dist/internal/Cache.js +11 -7
  195. package/dist/internal/Cache.js.map +1 -1
  196. package/dist/internal/EarnVaults.d.ts +41 -2
  197. package/dist/internal/EarnVaults.d.ts.map +1 -1
  198. package/dist/internal/EarnVaults.js +167 -0
  199. package/dist/internal/EarnVaults.js.map +1 -1
  200. package/dist/internal/MetricSink.d.ts +35 -125
  201. package/dist/internal/MetricSink.d.ts.map +1 -1
  202. package/dist/internal/MetricSink.js +50 -121
  203. package/dist/internal/MetricSink.js.map +1 -1
  204. package/dist/internal/OpenApi.d.ts +26 -22
  205. package/dist/internal/OpenApi.d.ts.map +1 -1
  206. package/dist/internal/OpenApi.js +128 -39
  207. package/dist/internal/OpenApi.js.map +1 -1
  208. package/dist/internal/Response.d.ts +13 -8
  209. package/dist/internal/Response.d.ts.map +1 -1
  210. package/dist/internal/Response.js +16 -5
  211. package/dist/internal/Response.js.map +1 -1
  212. package/dist/internal/Schema.d.ts +8 -8
  213. package/dist/internal/Schema.d.ts.map +1 -1
  214. package/dist/internal/Schema.js +10 -9
  215. package/dist/internal/Schema.js.map +1 -1
  216. package/dist/internal/Store.d.ts +15 -6
  217. package/dist/internal/Store.d.ts.map +1 -1
  218. package/dist/internal/Store.js +45 -15
  219. package/dist/internal/Store.js.map +1 -1
  220. package/dist/internal/Tidx.d.ts +2 -0
  221. package/dist/internal/Tidx.d.ts.map +1 -1
  222. package/dist/internal/Tidx.js +16 -4
  223. package/dist/internal/Tidx.js.map +1 -1
  224. package/dist/internal/WebhookTransfer.d.ts +1 -55
  225. package/dist/internal/WebhookTransfer.d.ts.map +1 -1
  226. package/dist/internal/WebhookTransfer.js +1 -239
  227. package/dist/internal/WebhookTransfer.js.map +1 -1
  228. package/dist/internal/Webhooks.d.ts +112 -56
  229. package/dist/internal/Webhooks.d.ts.map +1 -1
  230. package/dist/internal/Webhooks.js +124 -93
  231. package/dist/internal/Webhooks.js.map +1 -1
  232. package/dist/internal/funding/Deposit.d.ts +2 -2
  233. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  234. package/dist/internal/funding/Deposit.js +9 -8
  235. package/dist/internal/funding/Deposit.js.map +1 -1
  236. package/dist/internal/funding/DepositAddress.d.ts +4 -4
  237. package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
  238. package/dist/internal/funding/DepositAddress.js +9 -8
  239. package/dist/internal/funding/DepositAddress.js.map +1 -1
  240. package/dist/internal/funding/DepositWebhook.d.ts +25 -0
  241. package/dist/internal/funding/DepositWebhook.d.ts.map +1 -0
  242. package/dist/internal/funding/DepositWebhook.js +74 -0
  243. package/dist/internal/funding/DepositWebhook.js.map +1 -0
  244. package/dist/internal/funding/Provider.d.ts.map +1 -1
  245. package/dist/internal/funding/Provider.js +13 -12
  246. package/dist/internal/funding/Provider.js.map +1 -1
  247. package/dist/internal/funding/Reconciliation.d.ts +6 -0
  248. package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
  249. package/dist/internal/funding/Reconciliation.js +42 -10
  250. package/dist/internal/funding/Reconciliation.js.map +1 -1
  251. package/dist/internal/funding/index.d.ts +1 -0
  252. package/dist/internal/funding/index.d.ts.map +1 -1
  253. package/dist/internal/funding/index.js +1 -0
  254. package/dist/internal/funding/index.js.map +1 -1
  255. package/dist/internal/funding/providers/stargate.d.ts +19 -0
  256. package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
  257. package/dist/internal/funding/providers/stargate.js +143 -0
  258. package/dist/internal/funding/providers/stargate.js.map +1 -0
  259. package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
  260. package/dist/internal/webhookDestinations/slack.js +16 -0
  261. package/dist/internal/webhookDestinations/slack.js.map +1 -1
  262. package/dist/providers/index.d.ts +7 -0
  263. package/dist/providers/index.d.ts.map +1 -1
  264. package/dist/providers/index.js +3 -0
  265. package/dist/providers/index.js.map +1 -1
  266. package/package.json +2 -2
  267. package/src/App.test.ts +48 -0
  268. package/src/App.ts +7 -2
  269. package/src/Assets.test.ts +18 -0
  270. package/src/Assets.ts +22 -0
  271. package/src/Client.test-d.ts +287 -17
  272. package/src/Webhooks.ts +1 -220
  273. package/src/admin/apps/earn-vaults.test.ts +143 -0
  274. package/src/admin/apps/earn-vaults.ts +83 -6
  275. package/src/admin/apps/organizations.ts +6 -2
  276. package/src/admin/ui/src/routes/api-keys.tsx +36 -0
  277. package/src/admin/ui.generated.ts +151 -189
  278. package/src/apps/data/App.test.ts +31 -0
  279. package/src/apps/data/App.ts +64 -10
  280. package/src/apps/data/ZoneSelection.test.ts +196 -0
  281. package/src/apps/data/ZoneSelection.ts +108 -0
  282. package/src/apps/data/routes/activities.test.ts +435 -12
  283. package/src/apps/data/routes/activities.ts +562 -125
  284. package/src/apps/data/routes/balances.ts +1 -1
  285. package/src/apps/data/routes/blocks.ts +1 -1
  286. package/src/apps/data/routes/earn.test.ts +183 -23
  287. package/src/apps/data/routes/earn.ts +225 -29
  288. package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
  289. package/src/apps/data/routes/exchanges.test.ts +31 -1
  290. package/src/apps/data/routes/exchanges.ts +19 -15
  291. package/src/apps/data/routes/fee-amm.ts +18 -11
  292. package/src/apps/data/routes/receipts.ts +1 -1
  293. package/src/apps/data/routes/rpc.test.ts +75 -0
  294. package/src/apps/data/routes/rpc.ts +23 -9
  295. package/src/apps/data/routes/tokenlist.ts +21 -18
  296. package/src/apps/data/routes/tokens.test.ts +29 -0
  297. package/src/apps/data/routes/tokens.ts +38 -15
  298. package/src/apps/data/routes/transactions.ts +1 -1
  299. package/src/apps/data/routes/transfers.test.ts +3 -3
  300. package/src/apps/data/routes/transfers.ts +12 -9
  301. package/src/apps/data/routes/webhooks.test.ts +179 -1497
  302. package/src/apps/data/routes/webhooks.ts +156 -976
  303. package/src/apps/data/routes/zones.test.ts +19 -13
  304. package/src/apps/funding/routes/chains.test.ts +211 -7
  305. package/src/apps/funding/routes/chains.ts +19 -12
  306. package/src/apps/funding/routes/deposit-addresses.test.ts +394 -0
  307. package/src/apps/funding/routes/deposit-addresses.ts +84 -72
  308. package/src/apps/funding/routes/providers.ts +9 -5
  309. package/src/apps/funding/routes/quotes.test.ts +46 -0
  310. package/src/apps/funding/routes/quotes.ts +8 -5
  311. package/src/apps/funding/routes/transfers.test.ts +35 -32
  312. package/src/apps/management/Billing.test.ts +26 -0
  313. package/src/apps/management/Billing.ts +24 -7
  314. package/src/apps/management/routes/api-keys.test.ts +178 -0
  315. package/src/apps/management/routes/api-keys.ts +203 -144
  316. package/src/apps/management/routes/billing.test.ts +209 -0
  317. package/src/apps/management/routes/billing.ts +254 -177
  318. package/src/apps/management/routes/faucet.test.ts +39 -0
  319. package/src/apps/management/routes/faucet.ts +75 -41
  320. package/src/apps/management/routes/invitations.test.ts +216 -0
  321. package/src/apps/management/routes/invitations.ts +186 -109
  322. package/src/apps/management/routes/invite-links.test.ts +263 -1
  323. package/src/apps/management/routes/invite-links.ts +295 -214
  324. package/src/apps/management/routes/me.test.ts +49 -0
  325. package/src/apps/management/routes/me.ts +42 -32
  326. package/src/apps/management/routes/members.test.ts +124 -1
  327. package/src/apps/management/routes/members.ts +81 -51
  328. package/src/apps/management/routes/orgs.test.ts +176 -0
  329. package/src/apps/management/routes/orgs.ts +101 -59
  330. package/src/apps/management/routes/projects.test.ts +183 -0
  331. package/src/apps/management/routes/projects.ts +124 -60
  332. package/src/apps/management/routes/scopes.test.ts +44 -0
  333. package/src/apps/management/routes/scopes.ts +37 -28
  334. package/src/apps/management/routes/usage.test.ts +92 -0
  335. package/src/apps/management/routes/usage.ts +186 -151
  336. package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
  337. package/src/apps/management/routes/verified-token-requests.ts +166 -133
  338. package/src/apps/management/routes/webhooks.test.ts +313 -1
  339. package/src/apps/management/routes/webhooks.ts +220 -71
  340. package/src/apps/mpp/internal/Adapter.ts +13 -1
  341. package/src/db/Db.test.ts +42 -5
  342. package/src/db/Db.ts +85 -0
  343. package/src/db/Schema.ts +41 -3
  344. package/src/db/tables/earnVaults.test.ts +22 -0
  345. package/src/db/tables/earnVaults.ts +11 -1
  346. package/src/db/tables/organizations.test.ts +5 -2
  347. package/src/db/tables/webhookDeliveries.ts +13 -0
  348. package/src/db/tables/webhookQueueCompletions.ts +55 -0
  349. package/src/db/tables/webhookQueueEvents.ts +97 -57
  350. package/src/db/tables/webhookSubscriptions.ts +134 -144
  351. package/src/internal/Auth.ts +23 -5
  352. package/src/internal/Cache.ts +14 -7
  353. package/src/internal/EarnVaults.capabilities.test.ts +33 -0
  354. package/src/internal/EarnVaults.test.ts +79 -0
  355. package/src/internal/EarnVaults.ts +277 -0
  356. package/src/internal/MetricSink.test.ts +41 -373
  357. package/src/internal/MetricSink.ts +92 -273
  358. package/src/internal/OpenApi.ts +165 -49
  359. package/src/internal/Response.test.ts +95 -0
  360. package/src/internal/Response.ts +40 -2
  361. package/src/internal/Schema.test.ts +34 -0
  362. package/src/internal/Schema.ts +20 -9
  363. package/src/internal/Store.test.ts +186 -0
  364. package/src/internal/Store.ts +57 -17
  365. package/src/internal/Tidx.test.ts +19 -0
  366. package/src/internal/Tidx.ts +16 -4
  367. package/src/internal/WebhookTransfer.ts +1 -351
  368. package/src/internal/Webhooks.test.ts +222 -145
  369. package/src/internal/Webhooks.ts +234 -135
  370. package/src/internal/funding/Deposit.ts +71 -64
  371. package/src/internal/funding/DepositAddress.ts +50 -43
  372. package/src/internal/funding/DepositWebhook.test.ts +131 -0
  373. package/src/internal/funding/DepositWebhook.ts +101 -0
  374. package/src/internal/funding/Provider.ts +164 -142
  375. package/src/internal/funding/Reconciliation.test.ts +14 -0
  376. package/src/internal/funding/Reconciliation.ts +161 -86
  377. package/src/internal/funding/index.test.ts +1 -0
  378. package/src/internal/funding/index.ts +1 -0
  379. package/src/internal/funding/providers/index.test.ts +185 -0
  380. package/src/internal/funding/providers/stargate.ts +184 -0
  381. package/src/internal/webhookDestinations/slack.ts +15 -0
  382. package/src/providers/index.test.ts +1 -0
  383. package/src/providers/index.ts +9 -0
  384. package/src/Webhooks.bench.ts +0 -714
  385. package/src/Webhooks.memory.bench.ts +0 -250
  386. package/src/Webhooks.test.ts +0 -146
@@ -1,6 +1,7 @@
1
1
  import type { ExpressionBuilder, Selectable } from 'kysely'
2
2
  import { sql } from 'kysely'
3
3
 
4
+ import * as Scope from '../../Scope.js'
4
5
  import type * as Webhooks from '../../internal/Webhooks.js'
5
6
  import type * as Db from '../Db.js'
6
7
  import type * as db_Schema from '../Schema.js'
@@ -40,6 +41,7 @@ export function toSubscription(row: Record): Webhooks.Subscription {
40
41
  ...(row.context === null ? {} : { context: row.context }),
41
42
  createdAt: row.createdAt,
42
43
  destination: row.destination,
44
+ ...(row.environment === null ? {} : { environment: row.environment }),
43
45
  eventType: row.eventType,
44
46
  ...(row.expiresAt === null ? {} : { expiresAt: row.expiresAt }),
45
47
  failureCount: row.failureCount,
@@ -50,6 +52,7 @@ export function toSubscription(row: Record): Webhooks.Subscription {
50
52
  row.ownerType === 'api_key'
51
53
  ? { orgId: row.ownerId, type: 'api_key' }
52
54
  : { payer: row.ownerId, type: 'mpp' },
55
+ ...(row.projectId === null ? {} : { projectId: row.projectId }),
53
56
  secret: row.secret,
54
57
  status: row.status,
55
58
  updatedAt: row.updatedAt,
@@ -75,6 +78,7 @@ export async function insert(
75
78
  context: subscription.context ?? null,
76
79
  createdAt: subscription.createdAt,
77
80
  destination: subscription.destination,
81
+ environment: subscription.environment ?? null,
78
82
  eventType: subscription.eventType,
79
83
  expiresAt: subscription.expiresAt ?? null,
80
84
  failureCount: subscription.failureCount,
@@ -84,6 +88,7 @@ export async function insert(
84
88
  ownerId: ownerId(subscription.owner),
85
89
  ownerType: subscription.owner.type,
86
90
  pollerCursor: options.pollerCursor ?? null,
91
+ projectId: subscription.projectId ?? null,
87
92
  secret: subscription.secret,
88
93
  status: subscription.status,
89
94
  updatedAt: subscription.updatedAt,
@@ -94,7 +99,7 @@ export async function insert(
94
99
  export declare namespace insert {
95
100
  /** Options for {@link insert}. */
96
101
  type Options = {
97
- /** Initial poller cursor committed with the subscription. */
102
+ /** Initial cursor committed with the subscription. */
98
103
  pollerCursor?: string | undefined
99
104
  }
100
105
  }
@@ -129,7 +134,7 @@ export declare namespace insertWithinLimit {
129
134
  maxPerOwner: number
130
135
  /** ISO timestamp used to exclude expired rows from the count. */
131
136
  now: string
132
- /** Initial poller cursor committed with the subscription. */
137
+ /** Initial cursor committed with the subscription. */
133
138
  pollerCursor?: string | undefined
134
139
  }
135
140
  }
@@ -149,15 +154,17 @@ export async function get(
149
154
  owner: Webhooks.Owner,
150
155
  id: string,
151
156
  now: string,
157
+ access?: Webhooks.Access,
152
158
  ): Promise<Webhooks.Subscription | null> {
153
- const row = await db.kysely
159
+ let query = db.kysely
154
160
  .selectFrom('webhook_subscriptions')
155
161
  .selectAll()
156
162
  .where('id', '=', id)
157
163
  .where('ownerType', '=', owner.type)
158
164
  .where('ownerId', '=', ownerId(owner))
159
165
  .where(live(now))
160
- .executeTakeFirst()
166
+ if (access) query = query.where(privateResourceAccess(access))
167
+ const row = await query.executeTakeFirst()
161
168
  return row ? toSubscription(row) : null
162
169
  }
163
170
 
@@ -183,6 +190,7 @@ export async function list(
183
190
  .where('ownerId', '=', ownerId(owner))
184
191
  .where(live(options.now))
185
192
  .orderBy('id', 'desc')
193
+ if (options.access) query = query.where(privateResourceAccess(options.access))
186
194
  if (options.cursor) query = query.where('id', '<', options.cursor)
187
195
  if (options.offset) query = query.offset(options.offset)
188
196
  if (options.limit !== undefined) query = query.limit(options.limit)
@@ -192,6 +200,8 @@ export async function list(
192
200
  export declare namespace list {
193
201
  /** Options for {@link list}. */
194
202
  type Options = {
203
+ /** Private-resource visibility scope. */
204
+ access?: Webhooks.Access | undefined
195
205
  /** Return subscriptions older than this id (keyset paging, newest first). */
196
206
  cursor?: string | undefined
197
207
  /** Maximum subscriptions to return. */
@@ -211,14 +221,20 @@ export declare namespace list {
211
221
  * @param now - ISO timestamp expiry is evaluated against.
212
222
  * @returns The count.
213
223
  */
214
- export async function count(db: Db.Db, owner: Webhooks.Owner, now: string): Promise<number> {
215
- const row = await db.kysely
224
+ export async function count(
225
+ db: Db.Db,
226
+ owner: Webhooks.Owner,
227
+ now: string,
228
+ access?: Webhooks.Access,
229
+ ): Promise<number> {
230
+ let query = db.kysely
216
231
  .selectFrom('webhook_subscriptions')
217
232
  .select((eb) => eb.fn.countAll().as('count'))
218
233
  .where('ownerType', '=', owner.type)
219
234
  .where('ownerId', '=', ownerId(owner))
220
235
  .where(live(now))
221
- .executeTakeFirstOrThrow()
236
+ if (access) query = query.where(privateResourceAccess(access))
237
+ const row = await query.executeTakeFirstOrThrow()
222
238
  return Number(row.count)
223
239
  }
224
240
 
@@ -275,21 +291,42 @@ export async function remove(
275
291
  owner: Webhooks.Owner,
276
292
  id: string,
277
293
  now: string,
294
+ access?: Webhooks.Access,
278
295
  ): Promise<boolean> {
279
- const result = await db.kysely
296
+ let query = db.kysely
280
297
  .deleteFrom('webhook_subscriptions')
281
298
  .where('id', '=', id)
282
299
  .where('ownerType', '=', owner.type)
283
300
  .where('ownerId', '=', ownerId(owner))
284
301
  .where(live(now))
285
- .executeTakeFirst()
302
+ if (access) query = query.where(privateResourceAccess(access))
303
+ const result = await query.executeTakeFirst()
286
304
  return result.numDeletedRows > 0n
287
305
  }
288
306
 
307
+ function privateResourceAccess(access: Webhooks.Access) {
308
+ const fundingRead = access.scopes.some(
309
+ (scope) => scope === Scope.wildcard || scope === 'funding:read',
310
+ )
311
+ return (eb: ExpressionBuilder<Db.Database, 'webhook_subscriptions'>) =>
312
+ eb.or([
313
+ eb('eventType', '!=', 'funding:deposit.updated'),
314
+ ...(fundingRead
315
+ ? [
316
+ eb.and([
317
+ eb('eventType', '=', 'funding:deposit.updated'),
318
+ eb('environment', '=', access.environment),
319
+ ...(access.projectId === undefined ? [] : [eb('projectId', '=', access.projectId)]),
320
+ ]),
321
+ ]
322
+ : []),
323
+ ])
324
+ }
325
+
289
326
  /**
290
- * Lists live `active` subscriptions for a `(chainId, eventType)` stream — the
291
- * poller's per-stream lookup, served by the partial status index. Each row
292
- * carries its poller cursor so the poller avoids a per-subscription read.
327
+ * Lists live `active` subscriptions for a `(chainId, eventType)` stream,
328
+ * served by the partial status index. Each row carries its cursor so callers
329
+ * avoid a per-subscription read.
293
330
  *
294
331
  * @param db - The database.
295
332
  * @param chainId - Chain the stream belongs to.
@@ -316,8 +353,8 @@ export async function listActive(
316
353
  }
317
354
 
318
355
  /**
319
- * Lists every live `active` subscription on a chain in one read. The poller
320
- * groups the rows by event type so empty streams cost no extra database reads.
356
+ * Lists every live `active` subscription on a chain in one read. Callers
357
+ * group the rows by event type so empty streams cost no extra database reads.
321
358
  *
322
359
  * @param db - The database.
323
360
  * @param options - Chain, configured event types, and expiry time.
@@ -342,43 +379,58 @@ export async function listActiveForChain(
342
379
  }
343
380
 
344
381
  export declare namespace listActiveForChain {
345
- /** Filters for the poller's chain-level subscription read. */
382
+ /** Filters for the chain-level subscription read. */
346
383
  type Options = {
347
384
  /** Chain whose subscriptions to read. */
348
385
  chainId: number
349
- /** Event types configured for this poller tick. */
386
+ /** Event types eligible for the read. */
350
387
  eventTypes: readonly Webhooks.EventType[]
351
388
  /** ISO timestamp expiry is evaluated against. */
352
389
  now: string
353
390
  }
354
391
  }
355
392
 
356
- /**
357
- * Reads the poller cursors of every live `active` subscription on a chain,
358
- * across event types. Feeds the cron's cursor-freshness fallback gate.
359
- *
360
- * @param db - The database.
361
- * @param chainId - Chain whose cursors to read.
362
- * @param now - ISO timestamp expiry is evaluated against.
363
- * @returns The non-null cursors, unordered.
364
- */
365
- export async function listActiveCursors(
393
+ /** Lists live funding deposit subscriptions visible to one deposit owner. */
394
+ export async function listActiveForFundingDeposit(
366
395
  db: Db.Db,
367
- chainId: number,
368
- now: string,
369
- ): Promise<string[]> {
370
- const rows = await db.kysely
396
+ options: listActiveForFundingDeposit.Options,
397
+ ): Promise<Webhooks.Subscription[]> {
398
+ let query = db.kysely
371
399
  .selectFrom('webhook_subscriptions')
372
- .select('pollerCursor')
373
- .where('chainId', '=', chainId)
400
+ .selectAll()
401
+ .where('chainId', '=', options.chainId)
402
+ .where('environment', '=', options.environment)
403
+ .where('eventType', '=', 'funding:deposit.updated')
404
+ .where('ownerId', '=', options.orgId)
405
+ .where('ownerType', '=', 'api_key')
374
406
  .where('status', '=', 'active')
375
- .where(live(now))
376
- .execute()
377
- return rows.flatMap((row) => (row.pollerCursor === null ? [] : [row.pollerCursor]))
407
+ .where(live(options.now))
408
+ const projectId = options.projectId
409
+ query =
410
+ projectId === undefined
411
+ ? query.where('projectId', 'is', null)
412
+ : query.where((eb) => eb.or([eb('projectId', 'is', null), eb('projectId', '=', projectId)]))
413
+ return (await query.orderBy('id').execute()).map(toSubscription)
414
+ }
415
+
416
+ export declare namespace listActiveForFundingDeposit {
417
+ /** Ownership scope and chain for a funding deposit event. */
418
+ type Options = {
419
+ /** Destination Tempo chain id. */
420
+ chainId: number
421
+ /** Deposit API-key environment. */
422
+ environment: 'production' | 'sandbox'
423
+ /** ISO timestamp used to exclude expired subscriptions. */
424
+ now: string
425
+ /** Owning organization id. */
426
+ orgId: string
427
+ /** Attributed deposit project, when present. */
428
+ projectId?: string | undefined
429
+ }
378
430
  }
379
431
 
380
432
  /**
381
- * Reads a subscription's poller cursor.
433
+ * Reads a subscription's keyset cursor.
382
434
  *
383
435
  * @param db - The database.
384
436
  * @param id - The subscription id (`wh_…`).
@@ -393,140 +445,59 @@ export async function getCursor(db: Db.Db, id: string): Promise<string | null> {
393
445
  return row?.pollerCursor ?? null
394
446
  }
395
447
 
396
- /**
397
- * Writes a subscription's poller cursor. Deliberately does not touch
398
- * `updatedAt` — the cursor advances every tick and is not a user mutation.
399
- *
400
- * @param db - The database.
401
- * @param id - The subscription id (`wh_…`).
402
- * @param cursor - The keyset cursor to store.
403
- */
404
- export async function setCursor(db: Db.Db, id: string, cursor: string): Promise<void> {
405
- await db.kysely
406
- .updateTable('webhook_subscriptions')
407
- .set({ pollerCursor: cursor })
408
- .where('id', '=', id)
409
- .execute()
410
- }
411
-
412
- /**
413
- * Writes a poller cursor only when the stored cursor still matches the caller's
414
- * observed value.
415
- *
416
- * @param db - The database.
417
- * @param options - Subscription, expected cursor, and next cursor.
418
- * @returns Whether the cursor was updated.
419
- */
420
- export async function compareAndSetCursor(
421
- db: Db.Db,
422
- options: compareAndSetCursor.Options,
423
- ): Promise<boolean> {
424
- let query = db.kysely
425
- .updateTable('webhook_subscriptions')
426
- .set({ pollerCursor: options.cursor })
427
- .where('id', '=', options.subscriptionId)
428
- query =
429
- options.expectedCursor === null
430
- ? query.where('pollerCursor', 'is', null)
431
- : query.where('pollerCursor', '=', options.expectedCursor)
432
- const result = await query.executeTakeFirst()
433
- return result.numUpdatedRows > 0n
434
- }
435
-
436
- export declare namespace compareAndSetCursor {
437
- /** Options for {@link compareAndSetCursor}. */
438
- type Options = {
439
- /** Next keyset cursor. */
440
- cursor: string
441
- /** Cursor observed before scanning, or null for an uninitialized subscription. */
442
- expectedCursor: string | null
443
- /** Subscription whose cursor advances. */
444
- subscriptionId: string
445
- }
446
- }
447
-
448
- /**
449
- * Writes multiple poller cursors when each stored value still matches the
450
- * caller's observed value.
451
- *
452
- * @param db - The database.
453
- * @param options - Candidate cursor writes.
454
- * @returns Subscription ids whose cursors were updated.
455
- */
456
- export async function compareAndSetCursors(
457
- db: Db.Db,
458
- options: compareAndSetCursors.Options,
459
- ): Promise<Set<string>> {
460
- if (options.cursors.length === 0) return new Set()
461
- const values = JSON.stringify(options.cursors)
462
- type Candidate = {
463
- cursor: string
464
- expectedCursor: string | null
465
- subscriptionId: string
466
- }
467
- const result = await db.kysely
468
- .with(
469
- 'candidates',
470
- () => sql<Candidate>`(
471
- SELECT
472
- candidate."subscriptionId" AS subscription_id,
473
- candidate."expectedCursor" AS expected_cursor,
474
- candidate.cursor
475
- FROM jsonb_to_recordset(${values}::jsonb)
476
- AS candidate("subscriptionId" text, "expectedCursor" text, cursor text)
477
- )`,
478
- )
479
- .updateTable('webhook_subscriptions as subscription')
480
- .from('candidates as candidate')
481
- .set((eb) => ({ pollerCursor: eb.ref('candidate.cursor') }))
482
- .whereRef('subscription.id', '=', 'candidate.subscriptionId')
483
- .whereRef('subscription.pollerCursor', 'is not distinct from', 'candidate.expectedCursor')
484
- .returning('subscription.id as subscriptionId')
485
- .execute()
486
- return new Set(result.map((row) => row.subscriptionId))
487
- }
488
-
489
- export declare namespace compareAndSetCursors {
490
- /** Options for {@link compareAndSetCursors}. */
491
- type Options = {
492
- /** Candidate cursor writes. */
493
- cursors: readonly compareAndSetCursor.Options[]
494
- }
495
- }
496
-
497
448
  /**
498
449
  * Records a successful delivery: resets the consecutive-failure counter and
499
- * stamps `lastDeliveryAt`.
450
+ * stamps `lastDeliveryAt`. Skipped when neither field would move, so
451
+ * deliveries stop contending on the row's lock.
500
452
  *
501
453
  * @param db - The database.
502
454
  * @param id - The subscription id (`wh_…`).
503
- * @param now - Delivery timestamp (ISO).
504
- * @returns The updated subscription, or `undefined` when the row is absent.
455
+ * @param options - Delivery timestamp and stamp-staleness bound.
456
+ * @returns The updated subscription, or `undefined` when nothing was written.
505
457
  */
506
458
  export async function recordSuccess(
507
459
  db: Db.Db,
508
460
  id: string,
509
- now: string,
461
+ options: recordSuccess.Options,
510
462
  ): Promise<Webhooks.Subscription | undefined> {
463
+ const { now, staleBefore } = options
511
464
  const row = await db.kysely
512
465
  .updateTable('webhook_subscriptions')
513
466
  .set({ failureCount: 0, lastDeliveryAt: now, updatedAt: now })
514
467
  .where('id', '=', id)
468
+ .where((eb) =>
469
+ eb.or([
470
+ eb('failureCount', '>', 0),
471
+ eb('lastDeliveryAt', 'is', null),
472
+ eb('lastDeliveryAt', '<', staleBefore),
473
+ ]),
474
+ )
515
475
  .returningAll()
516
476
  .executeTakeFirst()
517
477
  return row ? toSubscription(row) : undefined
518
478
  }
519
479
 
480
+ export declare namespace recordSuccess {
481
+ /** Clock bounds for one success record. */
482
+ type Options = {
483
+ /** Delivery timestamp (ISO). */
484
+ now: string
485
+ /** Rewrite the stamp only when it predates this (ISO). */
486
+ staleBefore: string
487
+ }
488
+ }
489
+
520
490
  /**
521
491
  * Records a failed delivery: atomically increments the consecutive-failure
522
492
  * counter and disables the subscription once it reaches `maxFailures` (raw
523
493
  * fragments use storage column names — they bypass the camelCase mapping).
494
+ * Skipped once disabled at the cap, when nothing would move.
524
495
  *
525
496
  * @param db - The database.
526
497
  * @param id - The subscription id (`wh_…`).
527
498
  * @param maxFailures - Consecutive failures before auto-disabling.
528
499
  * @param now - Failure timestamp (ISO).
529
- * @returns The updated subscription, or `undefined` when the row is absent.
500
+ * @returns The updated subscription, or `undefined` when nothing was written.
530
501
  */
531
502
  export async function recordFailure(
532
503
  db: Db.Db,
@@ -542,24 +513,43 @@ export async function recordFailure(
542
513
  updatedAt: now,
543
514
  })
544
515
  .where('id', '=', id)
516
+ // In-flight failures race the disable and would queue on the row lock. A
517
+ // re-enabled subscription keeps its capped counter; the status arm lets
518
+ // its next failure re-disable it.
519
+ .where((eb) => eb.or([eb('failureCount', '<', maxFailures), eb('status', '!=', 'disabled')]))
545
520
  .returningAll()
546
521
  .executeTakeFirst()
547
522
  return row ? toSubscription(row) : undefined
548
523
  }
549
524
 
525
+ // Smaller than the ledger-table bounds: each subscription delete cascades
526
+ // into deliveries, queue events, and completions, fanning the statement out.
527
+ const pruneBatchLimit = 1_000
528
+
550
529
  /**
551
530
  * Deletes expired subscriptions (their delivery rows cascade). Called
552
- * best-effort from the poller tick.
531
+ * best-effort on a schedule.
553
532
  *
554
533
  * @param db - The database.
555
534
  * @param now - ISO timestamp expiry is evaluated against.
556
535
  * @returns The number of rows deleted.
557
536
  */
558
537
  export async function pruneExpired(db: Db.Db, now: string): Promise<number> {
538
+ // Bounded like the ledger prunes: this delete cascades into deliveries,
539
+ // queue events, and completions, so it fans out the widest of the four.
559
540
  const result = await db.kysely
560
541
  .deleteFrom('webhook_subscriptions')
561
- .where('expiresAt', 'is not', null)
542
+ // Repeated on the outer delete: the row recheck under concurrency re-runs
543
+ // only this predicate, so a subscription renewed mid-statement survives.
562
544
  .where('expiresAt', '<=', now)
545
+ .where('id', 'in', (eb) =>
546
+ eb
547
+ .selectFrom('webhook_subscriptions')
548
+ .select('id')
549
+ .where('expiresAt', 'is not', null)
550
+ .where('expiresAt', '<=', now)
551
+ .limit(pruneBatchLimit),
552
+ )
563
553
  .executeTakeFirst()
564
554
  return Number(result.numDeletedRows)
565
555
  }
@@ -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()
@@ -1000,12 +1010,20 @@ export declare namespace install {
1000
1010
  }
1001
1011
 
1002
1012
  /** Creates route middleware that contributes an auth policy override. */
1003
- export function policy(options: PolicyOverride): MiddlewareHandler {
1013
+ export function policy(options: policy.Options): MiddlewareHandler {
1004
1014
  const middleware = createMiddleware((_, next) => next()) as MiddlewareHandler & PolicyHandler
1005
1015
  middleware[policySymbol] = options
1006
1016
  return middleware
1007
1017
  }
1008
1018
 
1019
+ export declare namespace policy {
1020
+ /** Route policy plus metadata for compatibility aliases. */
1021
+ type Options = PolicyOverride & {
1022
+ /** HTTP method whose configured override this route inherits when its own is absent. */
1023
+ inheritOverridesFrom?: string | undefined
1024
+ }
1025
+ }
1026
+
1009
1027
  /** Adds management POSTs for OpenAPI-registered MPP GET resources. */
1010
1028
  export function installMppManagementRoutes(
1011
1029
  app: Hono<any, any>,
@@ -1106,7 +1124,7 @@ type OpenApiRoute = {
1106
1124
  }
1107
1125
 
1108
1126
  type PolicyHandler = {
1109
- [policySymbol]?: PolicyOverride | undefined
1127
+ [policySymbol]?: policy.Options | undefined
1110
1128
  }
1111
1129
 
1112
1130
  type MppManagementHandler = {
@@ -1283,7 +1301,7 @@ function policies(c: hono_Context) {
1283
1301
  return matchedRoutes(c)
1284
1302
  .slice(c.req.routeIndex + 1)
1285
1303
  .map(policyFromRoute)
1286
- .filter((policy): policy is PolicyOverride => policy !== undefined)
1304
+ .filter((routePolicy): routePolicy is policy.Options => routePolicy !== undefined)
1287
1305
  }
1288
1306
 
1289
1307
  function openApiSpec(route: RouterRoute) {
@@ -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_001),
25
+ ]).toStrictEqual([6, 1])
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
+ })