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
@@ -304,44 +304,6 @@ describe('updateSubscription', () => {
304
304
  })
305
305
  })
306
306
 
307
- describe('listActive', () => {
308
- test('returns only active subscriptions for a stream', async () => {
309
- const db = TestApp.database()
310
- const a = await Webhooks.createSubscription(db, createInput())
311
- const b = await Webhooks.createSubscription(db, createInput({ owner: mppOwner }))
312
- await Webhooks.createSubscription(db, createInput({ eventType: 'transaction:included' }))
313
-
314
- let active = await Webhooks.listActive(db, 4217, 'token:transfer')
315
- expect(active.map((s) => s.id).sort()).toEqual([a.id, b.id].sort())
316
-
317
- await Webhooks.updateSubscription(db, apiKeyOwner, a.id, { status: 'paused' })
318
- active = await Webhooks.listActive(db, 4217, 'token:transfer')
319
- expect(active.map((s) => s.id)).toEqual([b.id])
320
- })
321
-
322
- test('drops a deleted subscription from the index', async () => {
323
- const db = TestApp.database()
324
- const a = await Webhooks.createSubscription(db, createInput())
325
-
326
- await Webhooks.deleteSubscription(db, apiKeyOwner, a.id)
327
- expect(await Webhooks.listActive(db, 4217, 'token:transfer')).toMatchInlineSnapshot(`[]`)
328
- })
329
- })
330
-
331
- describe('listActiveWithCursors', () => {
332
- test('pairs each subscription with its stored cursor from one read', async () => {
333
- const db = TestApp.database()
334
- const anchored = await Webhooks.createSubscription(db, createInput())
335
- const fresh = await Webhooks.createSubscription(db, createInput({ owner: mppOwner }))
336
- await Webhooks.setCursor(db, anchored.id, Cursor.encode([100, 5]))
337
-
338
- const pairs = await Webhooks.listActiveWithCursors(db, 4217, 'token:transfer')
339
- const byId = new Map(pairs.map((pair) => [pair.subscription.id, pair.cursor]))
340
- expect(Cursor.decode(byId.get(anchored.id)!, ['int', 'int'])).toEqual([100, 5])
341
- expect(byId.get(fresh.id)).toBeNull()
342
- })
343
- })
344
-
345
307
  describe('listActiveForChain', () => {
346
308
  test('returns active subscriptions across event types in one read', async () => {
347
309
  const db = TestApp.database()
@@ -365,102 +327,6 @@ describe('listActiveForChain', () => {
365
327
  })
366
328
  })
367
329
 
368
- describe('maxCursorBlock', () => {
369
- test('returns the freshest cursor block across event types', async () => {
370
- const db = TestApp.database()
371
- const transfer = await Webhooks.createSubscription(db, createInput())
372
- const tx = await Webhooks.createSubscription(
373
- db,
374
- createInput({ eventType: 'transaction:included' }),
375
- )
376
- await Webhooks.setCursor(db, transfer.id, Cursor.encode([100, 5]))
377
- await Webhooks.setCursor(db, tx.id, Cursor.encode([250, 0]))
378
-
379
- expect(await Webhooks.maxCursorBlock(db, 4217)).toBe(250)
380
- })
381
-
382
- test('counts creation checkpoints at their recorded head', async () => {
383
- const db = TestApp.database()
384
- await Webhooks.createSubscription(db, createInput(), { startBlockNumber: 900 })
385
-
386
- expect(await Webhooks.maxCursorBlock(db, 4217)).toBe(900)
387
- })
388
-
389
- test('ignores other chains and returns null without cursors', async () => {
390
- const db = TestApp.database()
391
- expect(await Webhooks.maxCursorBlock(db, 4217)).toBeNull()
392
-
393
- const other = await Webhooks.createSubscription(db, createInput({ chainId: 42431 }))
394
- await Webhooks.setCursor(db, other.id, Cursor.encode([999, 0]))
395
- // A cursorless subscription on the queried chain still reads as null.
396
- await Webhooks.createSubscription(db, createInput())
397
-
398
- expect(await Webhooks.maxCursorBlock(db, 4217)).toBeNull()
399
- expect(await Webhooks.maxCursorBlock(db, 42431)).toBe(999)
400
- })
401
- })
402
-
403
- describe('cursors', () => {
404
- test('round-trips a per-subscription cursor', async () => {
405
- const db = TestApp.database()
406
- // The cursor is a column on the subscription row, so it needs a real
407
- // subscription (the old key space allowed orphan cursors).
408
- const created = await Webhooks.createSubscription(db, createInput())
409
- expect(await Webhooks.getCursor(db, created.id)).toMatchInlineSnapshot(`null`)
410
-
411
- await Webhooks.setCursor(db, created.id, '12345:7')
412
- expect(await Webhooks.getCursor(db, created.id)).toMatchInlineSnapshot(`"12345:7"`)
413
- })
414
-
415
- test('atomically rejects a stale cursor write', async () => {
416
- const db = TestApp.database()
417
- const created = await Webhooks.createSubscription(db, createInput())
418
- const a = Cursor.encode([100, 1])
419
- const b = Cursor.encode([100, 2])
420
- const results = await Promise.all([
421
- Webhooks.compareAndSetCursor(db, {
422
- cursor: a,
423
- expectedCursor: null,
424
- subscriptionId: created.id,
425
- }),
426
- Webhooks.compareAndSetCursor(db, {
427
- cursor: b,
428
- expectedCursor: null,
429
- subscriptionId: created.id,
430
- }),
431
- ])
432
-
433
- expect(results.toSorted((a, b) => Number(a) - Number(b))).toEqual([false, true])
434
- expect([a, b]).toContain(await Webhooks.getCursor(db, created.id))
435
- })
436
- })
437
-
438
- describe('compareAndSetCursors', () => {
439
- test('atomically advances a batch and reports stale rows', async () => {
440
- const db = TestApp.database()
441
- const initialized = await Webhooks.createSubscription(db, createInput())
442
- const stale = await Webhooks.createSubscription(db, createInput())
443
- const uninitialized = await Webhooks.createSubscription(db, createInput())
444
- const initial = Cursor.encode([100, 1])
445
- const next = Cursor.encode([101, 1])
446
- await Webhooks.setCursor(db, initialized.id, initial)
447
- await Webhooks.setCursor(db, stale.id, initial)
448
-
449
- const committed = await Webhooks.compareAndSetCursors(db, {
450
- cursors: [
451
- { cursor: next, expectedCursor: initial, subscriptionId: initialized.id },
452
- { cursor: next, expectedCursor: null, subscriptionId: stale.id },
453
- { cursor: next, expectedCursor: null, subscriptionId: uninitialized.id },
454
- ],
455
- })
456
-
457
- expect([...committed].toSorted()).toEqual([initialized.id, uninitialized.id].toSorted())
458
- expect(await Webhooks.getCursor(db, initialized.id)).toBe(next)
459
- expect(await Webhooks.getCursor(db, stale.id)).toBe(initial)
460
- expect(await Webhooks.getCursor(db, uninitialized.id)).toBe(next)
461
- })
462
- })
463
-
464
330
  describe('recordSuccess / recordFailure', () => {
465
331
  test('recordSuccess resets failures and stamps lastDeliveryAt', async () => {
466
332
  const db = TestApp.database()
@@ -482,6 +348,41 @@ describe('recordSuccess / recordFailure', () => {
482
348
  expect(read?.lastDeliveryAt).toBe('2026-01-01T00:00:00.000Z')
483
349
  })
484
350
 
351
+ test('recordSuccess refreshes the stamp at most once per precision window', async () => {
352
+ const db = TestApp.database()
353
+ const created = await Webhooks.createSubscription(db, createInput())
354
+ const stamped = await Webhooks.recordSuccess(db, created, { now: fixedNow })
355
+ expect(stamped.lastDeliveryAt).toBe(fixedNow().toISOString())
356
+
357
+ // A success moments later has nothing to move: the counter is already zero
358
+ // and the stamp is inside its window, so the row is never rewritten.
359
+ const soon = new Date(fixedNow().getTime() + 1_000)
360
+ await Webhooks.recordSuccess(db, stamped, { now: () => soon })
361
+ const unmoved = await Webhooks.getSubscription(db, apiKeyOwner, created.id)
362
+ expect(unmoved?.lastDeliveryAt, 'the stored stamp must not move').toBe(fixedNow().toISOString())
363
+
364
+ // Past any plausible window; the exact bound is internal.
365
+ const later = new Date(fixedNow().getTime() + 3_600_000)
366
+ await Webhooks.recordSuccess(db, stamped, { now: () => later })
367
+ const moved = await Webhooks.getSubscription(db, apiKeyOwner, created.id)
368
+ expect(moved?.lastDeliveryAt).toBe(later.toISOString())
369
+ })
370
+
371
+ test('recordSuccess always resets a non-zero failure counter', async () => {
372
+ const db = TestApp.database()
373
+ const created = await Webhooks.createSubscription(db, createInput())
374
+ // Stamp first, so only the counter is out of date: the reset must not be
375
+ // suppressed by a fresh stamp.
376
+ const stamped = await Webhooks.recordSuccess(db, created, { now: fixedNow })
377
+ const failed = await Webhooks.recordFailure(db, stamped, { now: fixedNow })
378
+ expect(failed.failureCount).toBe(1)
379
+
380
+ await Webhooks.recordSuccess(db, failed, { now: fixedNow })
381
+
382
+ const read = await Webhooks.getSubscription(db, apiKeyOwner, created.id)
383
+ expect(read?.failureCount, 'a pending reset must never be skipped').toBe(0)
384
+ })
385
+
485
386
  test('recordFailure auto-disables at the threshold and drops from the active index', async () => {
486
387
  const db = TestApp.database()
487
388
  let subscription = await Webhooks.createSubscription(db, createInput())
@@ -490,11 +391,13 @@ describe('recordSuccess / recordFailure', () => {
490
391
  subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 3 })
491
392
  subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 3 })
492
393
  expect(subscription.status).toMatchInlineSnapshot(`"active"`)
493
- expect((await Webhooks.listActive(db, 4217, 'token:transfer')).map((s) => s.id)).toEqual([
494
- subscription.id,
495
- ])
394
+ expect(
395
+ (
396
+ await Webhooks.listActiveForChain(db, { chainId: 4217, eventTypes: ['token:transfer'] })
397
+ ).map((pair) => pair.subscription.id),
398
+ ).toEqual([subscription.id])
496
399
 
497
- // Hitting the threshold disables it and removes it from the poller's index.
400
+ // Hitting the threshold disables it and removes it from the active index.
498
401
  subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 3 })
499
402
  expect({ failureCount: subscription.failureCount, status: subscription.status })
500
403
  .toMatchInlineSnapshot(`
@@ -503,7 +406,40 @@ describe('recordSuccess / recordFailure', () => {
503
406
  "status": "disabled",
504
407
  }
505
408
  `)
506
- expect(await Webhooks.listActive(db, 4217, 'token:transfer')).toMatchInlineSnapshot(`[]`)
409
+ expect(
410
+ await Webhooks.listActiveForChain(db, { chainId: 4217, eventTypes: ['token:transfer'] }),
411
+ ).toMatchInlineSnapshot(`[]`)
412
+ })
413
+
414
+ test('recordFailure leaves an already-disabled subscription alone at the cap', async () => {
415
+ const db = TestApp.database()
416
+ let subscription = await Webhooks.createSubscription(db, createInput())
417
+ subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 2, now: fixedNow })
418
+ subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 2, now: fixedNow })
419
+ expect(subscription.status).toBe('disabled')
420
+
421
+ // A straggler failing after the disable has nothing to move: the row is
422
+ // never rewritten.
423
+ const later = new Date(fixedNow().getTime() + 1_000)
424
+ await Webhooks.recordFailure(db, subscription, { maxFailures: 2, now: () => later })
425
+
426
+ const read = await Webhooks.getSubscription(db, apiKeyOwner, subscription.id)
427
+ expect(read?.failureCount, 'the stored counter must not move').toBe(2)
428
+ expect(read?.updatedAt, 'the stored stamp must not move').toBe(fixedNow().toISOString())
429
+ })
430
+
431
+ test('recordFailure re-disables a re-enabled subscription still at the cap', async () => {
432
+ const db = TestApp.database()
433
+ let subscription = await Webhooks.createSubscription(db, createInput())
434
+ subscription = await Webhooks.recordFailure(db, subscription, { maxFailures: 1, now: fixedNow })
435
+ expect(subscription.status).toBe('disabled')
436
+
437
+ await Webhooks.updateSubscription(db, apiKeyOwner, subscription.id, { status: 'active' })
438
+
439
+ // The counter still sits at the cap, so this failure must write again.
440
+ await Webhooks.recordFailure(db, subscription, { maxFailures: 1, now: fixedNow })
441
+ const read = await Webhooks.getSubscription(db, apiKeyOwner, subscription.id)
442
+ expect(read?.status).toBe('disabled')
507
443
  })
508
444
  })
509
445
 
@@ -1014,6 +950,72 @@ describe('ensureQueueEvents', () => {
1014
950
  expect(histograms.has('webhook_delivery_subscription_read_ms')).toBe(true)
1015
951
  })
1016
952
 
953
+ test('measures observation to attempt from the staged head stamp', async () => {
954
+ const db = TestApp.database()
955
+ const subscription = await Webhooks.createSubscription(
956
+ db,
957
+ createInput({ eventType: 'transaction:included' }),
958
+ )
959
+ const envelope = Webhooks.buildEnvelope({
960
+ blockNumber: 123,
961
+ data: {},
962
+ logIndex: 4,
963
+ subscription,
964
+ })
965
+ const observedAt = Date.now() - 5_000
966
+ const { references: [reference] } = await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }], { observedAt }) // prettier-ignore
967
+ const histograms = new Map<string, number>()
968
+ const metrics = Metrics.from({
969
+ count() {},
970
+ flush() {},
971
+ gauge() {},
972
+ histogram(name, value) {
973
+ histograms.set(name, value)
974
+ },
975
+ })
976
+ const fetch = (async () => new Response(null, { status: 200 })) satisfies typeof globalThis.fetch // prettier-ignore
977
+
978
+ const result = await Webhooks.deliverQueueEventAndRecord(db, reference!, { fetch, metrics })
979
+
980
+ expect(result.status).toBe('delivered')
981
+ // Measured from the head stamp, so it covers the whole controllable span
982
+ // rather than only the time since this worker dequeued the message.
983
+ expect(histograms.get('webhook_observed_to_attempt_ms')).toBeGreaterThanOrEqual(5_000)
984
+ expect(histograms.has('webhook_delivery_preflight_ms')).toBe(true)
985
+ expect(histograms.has('webhook_delivery_settle_ms')).toBe(true)
986
+ })
987
+
988
+ test('omits observation timing for a replay with no staged head stamp', async () => {
989
+ const db = TestApp.database()
990
+ const subscription = await Webhooks.createSubscription(
991
+ db,
992
+ createInput({ eventType: 'transaction:included' }),
993
+ )
994
+ const envelope = Webhooks.buildEnvelope({
995
+ blockNumber: 124,
996
+ data: {},
997
+ logIndex: 4,
998
+ subscription,
999
+ })
1000
+ const { references: [reference] } = await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }]) // prettier-ignore
1001
+ const histograms = new Map<string, number>()
1002
+ const metrics = Metrics.from({
1003
+ count() {},
1004
+ flush() {},
1005
+ gauge() {},
1006
+ histogram(name, value) {
1007
+ histograms.set(name, value)
1008
+ },
1009
+ })
1010
+ const fetch = (async () => new Response(null, { status: 200 })) satisfies typeof globalThis.fetch // prettier-ignore
1011
+
1012
+ await Webhooks.deliverQueueEventAndRecord(db, reference!, { fetch, metrics })
1013
+
1014
+ // Absent rather than zero: a replay is unattributable, not instant.
1015
+ expect(histograms.has('webhook_observed_to_attempt_ms')).toBe(false)
1016
+ expect(histograms.has('webhook_event_to_attempt_ms')).toBe(true)
1017
+ })
1018
+
1017
1019
  test('skips a staged event after its subscription expires', async () => {
1018
1020
  vi.useFakeTimers({ now: fixedNow(), toFake: ['Date'] })
1019
1021
  try {
@@ -1079,7 +1081,7 @@ describe('ensureQueueEvents', () => {
1079
1081
  expect(await Webhooks.getQueueEvent(db, reference)).toBeNull()
1080
1082
  })
1081
1083
 
1082
- test('replaces an expired terminal row so replays stay deliverable', async () => {
1084
+ test('stages a replay once its completion has expired', async () => {
1083
1085
  vi.useFakeTimers({ toFake: ['Date'] })
1084
1086
  vi.setSystemTime(fixedNow())
1085
1087
  try {
@@ -1095,9 +1097,9 @@ describe('ensureQueueEvents', () => {
1095
1097
  }),
1096
1098
  ).toBe(true)
1097
1099
 
1098
- // Past the dedupe window an unpruned terminal row must not suppress a
1100
+ // Past the dedupe window an unpruned completion must not suppress a
1099
1101
  // replay.
1100
- vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.deliveryRetentionMs + 1_000))
1102
+ vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
1101
1103
  const replay = await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }])
1102
1104
  expect(replay.created).toBe(1)
1103
1105
  await expect(Webhooks.claimQueueEvent(db, reference)).resolves.toMatchObject({
@@ -1107,6 +1109,65 @@ describe('ensureQueueEvents', () => {
1107
1109
  vi.useRealTimers()
1108
1110
  }
1109
1111
  })
1112
+
1113
+ test('stamps a fresh observation on a post-expiry replay', async () => {
1114
+ vi.useFakeTimers({ toFake: ['Date'] })
1115
+ vi.setSystemTime(fixedNow())
1116
+ try {
1117
+ const db = TestApp.database()
1118
+ const { envelope, reference, subscription } = await stagedObligation(db)
1119
+ const claim = await Webhooks.claimQueueEvent(db, reference)
1120
+ if (claim.type !== 'claimed') throw new Error(`Unexpected claim: ${claim.type}`)
1121
+ await Webhooks.completeQueueEvent(db, reference, {
1122
+ claimedAt: claim.record.attemptingAt!,
1123
+ status: 'succeeded',
1124
+ })
1125
+
1126
+ vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
1127
+ const observedAt = Date.now() - 250
1128
+ await Webhooks.ensureQueueEvents(db, [{ envelope, subscription }], { observedAt })
1129
+
1130
+ // Carrying the replaced row's stamp would measure this delivery against
1131
+ // an observation from the retention window before it.
1132
+ const replayed = await Webhooks.claimQueueEvent(db, reference)
1133
+ if (replayed.type !== 'claimed') throw new Error(`Unexpected claim: ${replayed.type}`)
1134
+ expect(replayed.record.observedAt).toBe(new Date(observedAt).toISOString())
1135
+ } finally {
1136
+ vi.useRealTimers()
1137
+ }
1138
+ })
1139
+
1140
+ test('suppresses only the completed obligation when staging a mixed batch', async () => {
1141
+ const db = TestApp.database()
1142
+ const done = await stagedObligation(db, 4)
1143
+ const claim = await Webhooks.claimQueueEvent(db, done.reference)
1144
+ if (claim.type !== 'claimed') throw new Error(`Unexpected claim: ${claim.type}`)
1145
+ await Webhooks.completeQueueEvent(db, done.reference, {
1146
+ claimedAt: claim.record.attemptingAt!,
1147
+ status: 'failed',
1148
+ })
1149
+
1150
+ const fresh = Webhooks.buildEnvelope({
1151
+ blockNumber: 124,
1152
+ createdAt: new Date(),
1153
+ data: { amount: '1' },
1154
+ logIndex: 5,
1155
+ subscription: done.subscription,
1156
+ })
1157
+ const batch = await Webhooks.ensureQueueEvents(db, [
1158
+ { envelope: done.envelope, subscription: done.subscription },
1159
+ { envelope: fresh, subscription: done.subscription },
1160
+ ])
1161
+
1162
+ expect(batch.created).toBe(1)
1163
+ await expect(Webhooks.claimQueueEvent(db, done.reference)).resolves.toEqual({
1164
+ status: 'failed',
1165
+ type: 'terminal',
1166
+ })
1167
+ await expect(Webhooks.claimQueueEvent(db, batch.references[1]!)).resolves.toMatchObject({
1168
+ type: 'claimed',
1169
+ })
1170
+ })
1110
1171
  })
1111
1172
 
1112
1173
  describe('claimQueueEvent', () => {
@@ -1119,6 +1180,22 @@ describe('claimQueueEvent', () => {
1119
1180
  vi.useRealTimers()
1120
1181
  })
1121
1182
 
1183
+ test('reads an expired completion as missing', async () => {
1184
+ const db = TestApp.database()
1185
+ const { reference } = await stagedObligation(db)
1186
+ const claim = await Webhooks.claimQueueEvent(db, reference)
1187
+ if (claim.type !== 'claimed') throw new Error(`Unexpected claim: ${claim.type}`)
1188
+ await Webhooks.completeQueueEvent(db, reference, {
1189
+ claimedAt: claim.record.attemptingAt!,
1190
+ status: 'succeeded',
1191
+ })
1192
+
1193
+ // Matches a pruned terminal row: past the dedupe window the completion is
1194
+ // invisible everywhere, not only to staging.
1195
+ vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
1196
+ await expect(Webhooks.claimQueueEvent(db, reference)).resolves.toEqual({ type: 'missing' })
1197
+ })
1198
+
1122
1199
  test('claims a due obligation once and reclaims after staleness', async () => {
1123
1200
  const db = TestApp.database()
1124
1201
  const { reference } = await stagedObligation(db)
@@ -1183,17 +1260,17 @@ describe('claimQueueEvent', () => {
1183
1260
 
1184
1261
  // Pending obligations never expire; only terminal transitions stamp a
1185
1262
  // dedupe deadline.
1186
- vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.deliveryRetentionMs * 3))
1263
+ vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs * 3))
1187
1264
  await expect(Webhooks.claimQueueEvent(db, reference)).resolves.toMatchObject({
1188
1265
  type: 'claimed',
1189
1266
  })
1190
1267
  })
1191
1268
 
1192
- test('never prunes pending work', async () => {
1269
+ test('leaves pending obligations claimable across a prune', async () => {
1193
1270
  const db = TestApp.database()
1194
1271
  const { reference } = await stagedObligation(db)
1195
1272
 
1196
- vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.deliveryRetentionMs + 1_000))
1273
+ vi.setSystemTime(new Date(fixedNow().getTime() + Webhooks.dedupeRetentionMs + 1_000))
1197
1274
  await Webhooks.pruneExpired(db)
1198
1275
  const claim = await Webhooks.claimQueueEvent(db, reference)
1199
1276
  expect(claim.type).toBe('claimed')