tapimo 0.12.0 → 0.14.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 (398) hide show
  1. package/dist/App.d.ts +11333 -9563
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +39 -3
  4. package/dist/App.js.map +1 -1
  5. package/dist/Scope.d.ts +2 -0
  6. package/dist/Scope.d.ts.map +1 -1
  7. package/dist/Scope.js +17 -0
  8. package/dist/Scope.js.map +1 -1
  9. package/dist/Webhooks.js +2 -2
  10. package/dist/Webhooks.js.map +1 -1
  11. package/dist/admin/App.d.ts +1064 -924
  12. package/dist/admin/App.d.ts.map +1 -1
  13. package/dist/admin/apps/api-keys.d.ts +80 -0
  14. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  15. package/dist/admin/apps/api-keys.js +54 -0
  16. package/dist/admin/apps/api-keys.js.map +1 -1
  17. package/dist/admin/apps/earn-vaults.d.ts +63 -15
  18. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  19. package/dist/admin/apps/earn-vaults.js +2 -1
  20. package/dist/admin/apps/earn-vaults.js.map +1 -1
  21. package/dist/admin/apps/organizations.d.ts +92 -3
  22. package/dist/admin/apps/organizations.d.ts.map +1 -1
  23. package/dist/admin/apps/organizations.js +69 -7
  24. package/dist/admin/apps/organizations.js.map +1 -1
  25. package/dist/admin/apps/verified-tokens.d.ts +7 -7
  26. package/dist/admin/ui.generated.d.ts +1 -1
  27. package/dist/admin/ui.generated.d.ts.map +1 -1
  28. package/dist/admin/ui.generated.js +151 -151
  29. package/dist/admin/ui.generated.js.map +1 -1
  30. package/dist/apps/Zones.d.ts +28 -28
  31. package/dist/apps/Zones.js +7 -7
  32. package/dist/apps/data/App.d.ts +2909 -2523
  33. package/dist/apps/data/App.d.ts.map +1 -1
  34. package/dist/apps/data/App.js +26 -21
  35. package/dist/apps/data/App.js.map +1 -1
  36. package/dist/apps/data/ZoneSelection.d.ts +8 -8
  37. package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
  38. package/dist/apps/data/ZoneSelection.js +1 -1
  39. package/dist/apps/data/ZoneSelection.js.map +1 -1
  40. package/dist/apps/data/routes/activities.d.ts +588 -584
  41. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  42. package/dist/apps/data/routes/activities.js +1561 -1239
  43. package/dist/apps/data/routes/activities.js.map +1 -1
  44. package/dist/apps/data/routes/addresses.d.ts +22 -22
  45. package/dist/apps/data/routes/balances.d.ts +26 -26
  46. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  47. package/dist/apps/data/routes/balances.js +43 -16
  48. package/dist/apps/data/routes/balances.js.map +1 -1
  49. package/dist/apps/data/routes/blocks.d.ts +44 -44
  50. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  51. package/dist/apps/data/routes/blocks.js +21 -11
  52. package/dist/apps/data/routes/blocks.js.map +1 -1
  53. package/dist/apps/data/routes/coingecko.d.ts +3 -3
  54. package/dist/apps/data/routes/earn.d.ts +201 -25
  55. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  56. package/dist/apps/data/routes/earn.js +434 -75
  57. package/dist/apps/data/routes/earn.js.map +1 -1
  58. package/dist/apps/data/routes/exchanges.d.ts +160 -145
  59. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  60. package/dist/apps/data/routes/exchanges.js +180 -114
  61. package/dist/apps/data/routes/exchanges.js.map +1 -1
  62. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  63. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  64. package/dist/apps/data/routes/fee-amm.js +18 -19
  65. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  66. package/dist/apps/data/routes/receipts.d.ts +155 -55
  67. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  68. package/dist/apps/data/routes/receipts.js +28 -10
  69. package/dist/apps/data/routes/receipts.js.map +1 -1
  70. package/dist/apps/data/routes/tokenlist.d.ts +13 -13
  71. package/dist/apps/data/routes/tokens.d.ts +5 -5
  72. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  73. package/dist/apps/data/routes/tokens.js +51 -20
  74. package/dist/apps/data/routes/tokens.js.map +1 -1
  75. package/dist/apps/data/routes/transactions.d.ts +7 -2
  76. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  77. package/dist/apps/data/routes/transactions.js +37 -17
  78. package/dist/apps/data/routes/transactions.js.map +1 -1
  79. package/dist/apps/data/routes/transfers.d.ts +13 -13
  80. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  81. package/dist/apps/data/routes/transfers.js +18 -12
  82. package/dist/apps/data/routes/transfers.js.map +1 -1
  83. package/dist/apps/data/routes/valuation.d.ts +31 -31
  84. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  85. package/dist/apps/data/routes/valuation.js +12 -7
  86. package/dist/apps/data/routes/valuation.js.map +1 -1
  87. package/dist/apps/data/routes/verified-tokens.d.ts +8 -8
  88. package/dist/apps/data/routes/webhooks.d.ts +816 -113
  89. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  90. package/dist/apps/data/routes/webhooks.js +47 -5
  91. package/dist/apps/data/routes/webhooks.js.map +1 -1
  92. package/dist/apps/data/routes/zones.d.ts +14 -14
  93. package/dist/apps/data/routes/zones.js +1 -1
  94. package/dist/apps/funding/App.d.ts +466 -44
  95. package/dist/apps/funding/App.d.ts.map +1 -1
  96. package/dist/apps/funding/App.js +1 -1
  97. package/dist/apps/funding/App.js.map +1 -1
  98. package/dist/apps/funding/routes/deposit-addresses.d.ts +17 -17
  99. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  100. package/dist/apps/funding/routes/deposit-addresses.js +17 -12
  101. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  102. package/dist/apps/funding/routes/transfers.d.ts +650 -57
  103. package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
  104. package/dist/apps/funding/routes/transfers.js +238 -24
  105. package/dist/apps/funding/routes/transfers.js.map +1 -1
  106. package/dist/apps/management/App.d.ts +5120 -4152
  107. package/dist/apps/management/App.d.ts.map +1 -1
  108. package/dist/apps/management/Billing.d.ts +1 -1
  109. package/dist/apps/management/Billing.d.ts.map +1 -1
  110. package/dist/apps/management/Billing.js +17 -1
  111. package/dist/apps/management/Billing.js.map +1 -1
  112. package/dist/apps/management/routes/api-keys.d.ts +632 -81
  113. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  114. package/dist/apps/management/routes/api-keys.js +236 -4
  115. package/dist/apps/management/routes/api-keys.js.map +1 -1
  116. package/dist/apps/management/routes/billing.d.ts +76 -76
  117. package/dist/apps/management/routes/faucet.d.ts +6 -6
  118. package/dist/apps/management/routes/invitations.d.ts +24 -24
  119. package/dist/apps/management/routes/invite-links.d.ts +4 -4
  120. package/dist/apps/management/routes/members.d.ts +16 -16
  121. package/dist/apps/management/routes/orgs.d.ts +20 -20
  122. package/dist/apps/management/routes/projects.d.ts +4 -4
  123. package/dist/apps/management/routes/usage.d.ts +8 -8
  124. package/dist/apps/management/routes/verified-token-requests.d.ts +17 -17
  125. package/dist/apps/management/routes/webhooks.d.ts +675 -25
  126. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  127. package/dist/apps/management/routes/webhooks.js +21 -21
  128. package/dist/apps/management/routes/webhooks.js.map +1 -1
  129. package/dist/apps/relay/App.d.ts.map +1 -1
  130. package/dist/apps/relay/App.js +115 -23
  131. package/dist/apps/relay/App.js.map +1 -1
  132. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  133. package/dist/apps/relay/Sponsorships.js +27 -1
  134. package/dist/apps/relay/Sponsorships.js.map +1 -1
  135. package/dist/db/Db.d.ts.map +1 -1
  136. package/dist/db/Db.js +34 -1
  137. package/dist/db/Db.js.map +1 -1
  138. package/dist/db/Schema.d.ts +11 -5
  139. package/dist/db/Schema.d.ts.map +1 -1
  140. package/dist/db/Schema.js +21 -3
  141. package/dist/db/Schema.js.map +1 -1
  142. package/dist/db/tables/fundingCatalog.d.ts +4 -2
  143. package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
  144. package/dist/db/tables/fundingCatalog.js +5 -1
  145. package/dist/db/tables/fundingCatalog.js.map +1 -1
  146. package/dist/db/tables/fundingTransferTransactions.d.ts +38 -0
  147. package/dist/db/tables/fundingTransferTransactions.d.ts.map +1 -1
  148. package/dist/db/tables/fundingTransferTransactions.js +44 -3
  149. package/dist/db/tables/fundingTransferTransactions.js.map +1 -1
  150. package/dist/db/tables/fundingTransfers.d.ts +17 -0
  151. package/dist/db/tables/fundingTransfers.d.ts.map +1 -1
  152. package/dist/db/tables/fundingTransfers.js +21 -0
  153. package/dist/db/tables/fundingTransfers.js.map +1 -1
  154. package/dist/db/tables/organizations.d.ts +24 -0
  155. package/dist/db/tables/organizations.d.ts.map +1 -1
  156. package/dist/db/tables/organizations.js +27 -0
  157. package/dist/db/tables/organizations.js.map +1 -1
  158. package/dist/db/tables/projects.d.ts +25 -1
  159. package/dist/db/tables/projects.d.ts.map +1 -1
  160. package/dist/db/tables/projects.js +26 -0
  161. package/dist/db/tables/projects.js.map +1 -1
  162. package/dist/db/tables/sponsoredTransactions.d.ts +44 -0
  163. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  164. package/dist/db/tables/sponsoredTransactions.js +146 -13
  165. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  166. package/dist/db/tables/webhookSubscriptions.d.ts +10 -6
  167. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  168. package/dist/db/tables/webhookSubscriptions.js +9 -6
  169. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  170. package/dist/handlers/internal/utils.d.ts.map +1 -1
  171. package/dist/handlers/internal/utils.js +9 -0
  172. package/dist/handlers/internal/utils.js.map +1 -1
  173. package/dist/internal/Auth.d.ts +3 -1
  174. package/dist/internal/Auth.d.ts.map +1 -1
  175. package/dist/internal/Auth.js +6 -3
  176. package/dist/internal/Auth.js.map +1 -1
  177. package/dist/internal/EarnVaults.d.ts +3 -3
  178. package/dist/internal/EarnVaults.js +5 -5
  179. package/dist/internal/EarnVaults.js.map +1 -1
  180. package/dist/internal/Fetch.d.ts +23 -0
  181. package/dist/internal/Fetch.d.ts.map +1 -0
  182. package/dist/internal/Fetch.js +26 -0
  183. package/dist/internal/Fetch.js.map +1 -0
  184. package/dist/internal/Log.d.ts +4 -2
  185. package/dist/internal/Log.d.ts.map +1 -1
  186. package/dist/internal/Log.js +16 -3
  187. package/dist/internal/Log.js.map +1 -1
  188. package/dist/internal/OpenApi.d.ts +5 -3
  189. package/dist/internal/OpenApi.d.ts.map +1 -1
  190. package/dist/internal/OpenApi.js +13 -3
  191. package/dist/internal/OpenApi.js.map +1 -1
  192. package/dist/internal/Response.d.ts +1 -1
  193. package/dist/internal/Response.d.ts.map +1 -1
  194. package/dist/internal/Schema.d.ts +6 -3
  195. package/dist/internal/Schema.d.ts.map +1 -1
  196. package/dist/internal/Schema.js +8 -2
  197. package/dist/internal/Schema.js.map +1 -1
  198. package/dist/internal/Store.d.ts +16 -3
  199. package/dist/internal/Store.d.ts.map +1 -1
  200. package/dist/internal/Store.js +82 -16
  201. package/dist/internal/Store.js.map +1 -1
  202. package/dist/internal/Tidx.d.ts.map +1 -1
  203. package/dist/internal/Tidx.js +7 -2
  204. package/dist/internal/Tidx.js.map +1 -1
  205. package/dist/internal/Timeout.d.ts +36 -0
  206. package/dist/internal/Timeout.d.ts.map +1 -0
  207. package/dist/internal/Timeout.js +37 -0
  208. package/dist/internal/Timeout.js.map +1 -0
  209. package/dist/internal/Timing.d.ts +9 -0
  210. package/dist/internal/Timing.d.ts.map +1 -1
  211. package/dist/internal/Timing.js +7 -0
  212. package/dist/internal/Timing.js.map +1 -1
  213. package/dist/internal/Viem.d.ts +16 -1
  214. package/dist/internal/Viem.d.ts.map +1 -1
  215. package/dist/internal/Viem.js +12 -2
  216. package/dist/internal/Viem.js.map +1 -1
  217. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  218. package/dist/internal/WebhookDestination.js +3 -0
  219. package/dist/internal/WebhookDestination.js.map +1 -1
  220. package/dist/internal/funding/Action.d.ts +9 -0
  221. package/dist/internal/funding/Action.d.ts.map +1 -1
  222. package/dist/internal/funding/Action.js +16 -8
  223. package/dist/internal/funding/Action.js.map +1 -1
  224. package/dist/internal/funding/Catalog.d.ts +9 -2
  225. package/dist/internal/funding/Catalog.d.ts.map +1 -1
  226. package/dist/internal/funding/Catalog.js +19 -8
  227. package/dist/internal/funding/Catalog.js.map +1 -1
  228. package/dist/internal/funding/DepositWebhook.d.ts.map +1 -1
  229. package/dist/internal/funding/DepositWebhook.js +2 -1
  230. package/dist/internal/funding/DepositWebhook.js.map +1 -1
  231. package/dist/internal/funding/Evidence.d.ts.map +1 -1
  232. package/dist/internal/funding/Evidence.js +2 -10
  233. package/dist/internal/funding/Evidence.js.map +1 -1
  234. package/dist/internal/funding/Provider.d.ts +108 -13
  235. package/dist/internal/funding/Provider.d.ts.map +1 -1
  236. package/dist/internal/funding/Provider.js +34 -8
  237. package/dist/internal/funding/Provider.js.map +1 -1
  238. package/dist/internal/funding/SourceObservation.d.ts.map +1 -1
  239. package/dist/internal/funding/SourceObservation.js +5 -7
  240. package/dist/internal/funding/SourceObservation.js.map +1 -1
  241. package/dist/internal/funding/Transfer.d.ts +114 -18
  242. package/dist/internal/funding/Transfer.d.ts.map +1 -1
  243. package/dist/internal/funding/Transfer.js +185 -55
  244. package/dist/internal/funding/Transfer.js.map +1 -1
  245. package/dist/internal/funding/TransferReconciliation.d.ts +52 -0
  246. package/dist/internal/funding/TransferReconciliation.d.ts.map +1 -0
  247. package/dist/internal/funding/TransferReconciliation.js +192 -0
  248. package/dist/internal/funding/TransferReconciliation.js.map +1 -0
  249. package/dist/internal/funding/TransferWebhook.d.ts +21 -0
  250. package/dist/internal/funding/TransferWebhook.d.ts.map +1 -0
  251. package/dist/internal/funding/TransferWebhook.js +43 -0
  252. package/dist/internal/funding/TransferWebhook.js.map +1 -0
  253. package/dist/internal/funding/index.d.ts +1 -0
  254. package/dist/internal/funding/index.d.ts.map +1 -1
  255. package/dist/internal/funding/index.js +1 -0
  256. package/dist/internal/funding/index.js.map +1 -1
  257. package/dist/internal/funding/providers/relay.d.ts.map +1 -1
  258. package/dist/internal/funding/providers/relay.js +3 -12
  259. package/dist/internal/funding/providers/relay.js.map +1 -1
  260. package/dist/internal/funding/providers/stargate.d.ts +127 -9
  261. package/dist/internal/funding/providers/stargate.d.ts.map +1 -1
  262. package/dist/internal/funding/providers/stargate.js +548 -112
  263. package/dist/internal/funding/providers/stargate.js.map +1 -1
  264. package/dist/internal/index.d.ts +1 -0
  265. package/dist/internal/index.d.ts.map +1 -1
  266. package/dist/internal/index.js +1 -0
  267. package/dist/internal/index.js.map +1 -1
  268. package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
  269. package/dist/internal/webhookDestinations/slack.js +16 -0
  270. package/dist/internal/webhookDestinations/slack.js.map +1 -1
  271. package/package.json +2 -2
  272. package/src/App.test.ts +100 -0
  273. package/src/App.ts +43 -3
  274. package/src/Client.test-d.ts +129 -2
  275. package/src/Scope.test.ts +20 -0
  276. package/src/Scope.ts +16 -0
  277. package/src/Webhooks.ts +2 -2
  278. package/src/admin/apps/api-keys.test.ts +75 -0
  279. package/src/admin/apps/api-keys.ts +64 -0
  280. package/src/admin/apps/earn-vaults.test.ts +1 -1
  281. package/src/admin/apps/earn-vaults.ts +2 -1
  282. package/src/admin/apps/organizations.test.ts +53 -1
  283. package/src/admin/apps/organizations.ts +90 -5
  284. package/src/admin/ui/src/lib/api-keys.ts +19 -0
  285. package/src/admin/ui/src/lib/organizations.test.ts +112 -1
  286. package/src/admin/ui/src/lib/organizations.ts +55 -0
  287. package/src/admin/ui/src/routes/api-keys.tsx +89 -2
  288. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +116 -0
  289. package/src/admin/ui.generated.ts +189 -151
  290. package/src/apps/Zones.test.ts +7 -7
  291. package/src/apps/Zones.ts +7 -7
  292. package/src/apps/composition.test.ts +2 -1
  293. package/src/apps/data/App.test.ts +41 -0
  294. package/src/apps/data/App.ts +30 -21
  295. package/src/apps/data/ZoneSelection.test.ts +2 -2
  296. package/src/apps/data/ZoneSelection.ts +8 -8
  297. package/src/apps/data/routes/activities.test.ts +1526 -12
  298. package/src/apps/data/routes/activities.ts +1774 -1356
  299. package/src/apps/data/routes/balances.ts +133 -97
  300. package/src/apps/data/routes/blocks.test.ts +533 -0
  301. package/src/apps/data/routes/blocks.ts +35 -16
  302. package/src/apps/data/routes/earn.test.ts +373 -16
  303. package/src/apps/data/routes/earn.ts +548 -79
  304. package/src/apps/data/routes/earn.zone-access.test.ts +6 -6
  305. package/src/apps/data/routes/exchanges.test.ts +740 -15
  306. package/src/apps/data/routes/exchanges.ts +954 -753
  307. package/src/apps/data/routes/fee-amm.ts +17 -18
  308. package/src/apps/data/routes/receipts.ts +47 -16
  309. package/src/apps/data/routes/tokens.test.ts +578 -0
  310. package/src/apps/data/routes/tokens.ts +283 -225
  311. package/src/apps/data/routes/transactions.ts +68 -29
  312. package/src/apps/data/routes/transfers.test.ts +421 -0
  313. package/src/apps/data/routes/transfers.ts +45 -27
  314. package/src/apps/data/routes/valuation.ts +94 -78
  315. package/src/apps/data/routes/webhooks.test.ts +21 -5
  316. package/src/apps/data/routes/webhooks.ts +63 -8
  317. package/src/apps/data/routes/zones.test.ts +2 -2
  318. package/src/apps/data/routes/zones.ts +1 -1
  319. package/src/apps/funding/App.ts +12 -2
  320. package/src/apps/funding/routes/deposit-addresses.test.ts +29 -7
  321. package/src/apps/funding/routes/deposit-addresses.ts +19 -14
  322. package/src/apps/funding/routes/quotes.test.ts +5 -9
  323. package/src/apps/funding/routes/transfers.test.ts +901 -23
  324. package/src/apps/funding/routes/transfers.ts +347 -64
  325. package/src/apps/management/Billing.ts +18 -5
  326. package/src/apps/management/routes/api-keys.test.ts +220 -0
  327. package/src/apps/management/routes/api-keys.ts +280 -3
  328. package/src/apps/management/routes/webhooks.test.ts +3 -3
  329. package/src/apps/management/routes/webhooks.ts +24 -25
  330. package/src/apps/relay/App.test.ts +212 -1
  331. package/src/apps/relay/App.ts +158 -29
  332. package/src/apps/relay/Sponsorships.ts +24 -1
  333. package/src/db/Db.ts +48 -1
  334. package/src/db/Schema.ts +22 -4
  335. package/src/db/tables/earnVaults.test.ts +9 -9
  336. package/src/db/tables/fundingCatalog.test.ts +16 -2
  337. package/src/db/tables/fundingCatalog.ts +9 -3
  338. package/src/db/tables/fundingTransferTransactions.test.ts +43 -0
  339. package/src/db/tables/fundingTransferTransactions.ts +79 -3
  340. package/src/db/tables/fundingTransfers.test.ts +26 -0
  341. package/src/db/tables/fundingTransfers.ts +36 -0
  342. package/src/db/tables/organizations.test.ts +41 -0
  343. package/src/db/tables/organizations.ts +49 -0
  344. package/src/db/tables/projects.test.ts +55 -0
  345. package/src/db/tables/projects.ts +46 -1
  346. package/src/db/tables/sponsoredTransactions.test.ts +338 -0
  347. package/src/db/tables/sponsoredTransactions.ts +197 -13
  348. package/src/db/tables/webhookSubscriptions.ts +18 -11
  349. package/src/handlers/internal/utils.test.ts +53 -0
  350. package/src/handlers/internal/utils.ts +15 -0
  351. package/src/internal/Auth.ts +12 -4
  352. package/src/internal/EarnVaults.capabilities.test.ts +2 -2
  353. package/src/internal/EarnVaults.test.ts +1 -1
  354. package/src/internal/EarnVaults.ts +5 -5
  355. package/src/internal/Fetch.test.ts +46 -0
  356. package/src/internal/Fetch.ts +56 -0
  357. package/src/internal/Log.test-d.ts +2 -0
  358. package/src/internal/Log.test.ts +21 -0
  359. package/src/internal/Log.ts +22 -5
  360. package/src/internal/OpenApi.ts +14 -4
  361. package/src/internal/Response.ts +1 -1
  362. package/src/internal/Schema.test.ts +2 -0
  363. package/src/internal/Schema.ts +12 -2
  364. package/src/internal/Store.test.ts +178 -0
  365. package/src/internal/Store.ts +104 -18
  366. package/src/internal/Tidx.test.ts +2 -1
  367. package/src/internal/Tidx.ts +7 -2
  368. package/src/internal/Timeout.test.ts +35 -0
  369. package/src/internal/Timeout.ts +73 -0
  370. package/src/internal/Timing.ts +16 -0
  371. package/src/internal/Viem.ts +39 -3
  372. package/src/internal/WebhookDestination.ts +3 -0
  373. package/src/internal/Webhooks.test.ts +45 -0
  374. package/src/internal/funding/Action.test.ts +41 -1
  375. package/src/internal/funding/Action.ts +69 -41
  376. package/src/internal/funding/Catalog.test.ts +34 -0
  377. package/src/internal/funding/Catalog.ts +28 -11
  378. package/src/internal/funding/DepositWebhook.ts +2 -1
  379. package/src/internal/funding/Evidence.ts +2 -13
  380. package/src/internal/funding/Provider.test.ts +73 -0
  381. package/src/internal/funding/Provider.ts +125 -28
  382. package/src/internal/funding/SourceObservation.ts +5 -9
  383. package/src/internal/funding/Transfer.test.ts +155 -0
  384. package/src/internal/funding/Transfer.ts +387 -147
  385. package/src/internal/funding/TransferReconciliation.test.ts +147 -0
  386. package/src/internal/funding/TransferReconciliation.ts +264 -0
  387. package/src/internal/funding/TransferWebhook.test.ts +128 -0
  388. package/src/internal/funding/TransferWebhook.ts +67 -0
  389. package/src/internal/funding/index.test.ts +1 -0
  390. package/src/internal/funding/index.ts +1 -0
  391. package/src/internal/funding/providers/index.test.ts +4 -167
  392. package/src/internal/funding/providers/relay.test.ts +2 -2
  393. package/src/internal/funding/providers/relay.ts +3 -15
  394. package/src/internal/funding/providers/stargate.test.ts +328 -0
  395. package/src/internal/funding/providers/stargate.ts +807 -135
  396. package/src/internal/index.test.ts +1 -0
  397. package/src/internal/index.ts +1 -0
  398. package/src/internal/webhookDestinations/slack.ts +15 -0
@@ -3,6 +3,7 @@ import { Mpp as PublicMpp } from 'tapimo/mpp'
3
3
  import type * as z from 'zod/mini'
4
4
 
5
5
  import * as Activities from './apps/data/routes/activities.js'
6
+ import * as ApiKeys from './apps/management/routes/api-keys.js'
6
7
  import * as Balances from './apps/data/routes/balances.js'
7
8
  import * as Billing from './apps/management/routes/billing.js'
8
9
  import * as Blocks from './apps/data/routes/blocks.js'
@@ -82,6 +83,50 @@ test('returns typed client', async () => {
82
83
  })
83
84
 
84
85
  describe('narrows responses by status', () => {
86
+ test('POST /v1/orgs/:orgId/projects/:projectId/api-keys/:keyId/rotate', async () => {
87
+ const client = Client.create()
88
+ const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].projects[
89
+ ':projectId{prj_[A-Za-z0-9_-]+}'
90
+ ]['api-keys'][':keyId{key_[A-Za-z0-9_-]+}'].rotate.$post({
91
+ param: { keyId: 'key_test', orgId: 'org_test', projectId: 'prj_test' },
92
+ })
93
+
94
+ expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
95
+
96
+ if (res.status === 200) {
97
+ const json = await res.json()
98
+ expectTypeOf(json).toEqualTypeOf<z.output<typeof ApiKeys.schema.rotateApiKey.Response>>()
99
+ }
100
+ })
101
+
102
+ test('POST /v1/orgs/:orgId/api-keys/:keyId/rotate', async () => {
103
+ const client = Client.create()
104
+ const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}']['api-keys'][
105
+ ':keyId{key_[A-Za-z0-9_-]+}'
106
+ ].rotate.$post({ param: { keyId: 'key_test', orgId: 'org_test' } })
107
+
108
+ expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 502>()
109
+
110
+ if (res.status === 200) {
111
+ const json = await res.json()
112
+ expectTypeOf(json).toEqualTypeOf<z.output<typeof ApiKeys.schema.rotateApiKey.Response>>()
113
+ }
114
+ })
115
+
116
+ test('DELETE /v1/orgs/:orgId/api-keys/:keyId', async () => {
117
+ const client = Client.create()
118
+ const res = await client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}']['api-keys'][
119
+ ':keyId{key_[A-Za-z0-9_-]+}'
120
+ ].$delete({ param: { keyId: 'key_test', orgId: 'org_test' } })
121
+
122
+ expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 401 | 403 | 404 | 429 | 502>()
123
+
124
+ if (res.status === 200) {
125
+ const json = await res.json()
126
+ expectTypeOf(json).toEqualTypeOf<z.output<typeof ApiKeys.schema.revokeApiKey.Response>>()
127
+ }
128
+ })
129
+
85
130
  test('POST /v1/mpp/validate', async () => {
86
131
  const client = Client.create()
87
132
  const res = await client.v1.mpp.validate.$post({ json: mppInput })
@@ -196,6 +241,9 @@ describe('narrows responses by status', () => {
196
241
  expectTypeOf(json.data[0]!.capabilities?.deposit).toEqualTypeOf<boolean | undefined>()
197
242
  expectTypeOf(json.data[0]!.engine.type).toEqualTypeOf<'erc4626' | 'veda' | null>()
198
243
  expectTypeOf(json.data[0]!.instantLiquidity).toEqualTypeOf<string | null>()
244
+ expectTypeOf(json.data[0]!.instantLiquidityValue).toEqualTypeOf<
245
+ VaultValue | null | undefined
246
+ >()
199
247
  expectTypeOf(json.data[0]!.sharePrice?.amount).toEqualTypeOf<string | undefined>()
200
248
  expectTypeOf(json.data[0]!.slug).toEqualTypeOf<string | null>()
201
249
  expectTypeOf(json.data[0]!.state.openRedeemRequestCount).toEqualTypeOf<number>()
@@ -271,7 +319,7 @@ describe('narrows responses by status', () => {
271
319
  const client = Client.create()
272
320
  const res = await client.v1.earn.addresses[':address'].positions.$get({
273
321
  param: { address: `0x${'bb'.repeat(20)}` },
274
- query: { 'valuation.currency': 'USD', verified: 'true' },
322
+ query: { include: 'earnings', 'valuation.currency': 'USD', verified: 'true' },
275
323
  })
276
324
 
277
325
  expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 502 | PaidAccessStatus>()
@@ -286,6 +334,13 @@ describe('narrows responses by status', () => {
286
334
  expectTypeOf(json.data[0]!.assetToken.address).toEqualTypeOf<`0x${string}`>()
287
335
  expectTypeOf(json.data[0]!.assetToken.decimals).toEqualTypeOf<number>()
288
336
  expectTypeOf(json.data[0]!.id).toEqualTypeOf<`0x${string}`>()
337
+ expectTypeOf(json.data[0]!.lifetimeCashFlows?.status).toEqualTypeOf<
338
+ 'complete' | 'incomplete_history' | undefined
339
+ >()
340
+ if (json.data[0]!.lifetimeCashFlows?.status === 'complete') {
341
+ expectTypeOf(json.data[0]!.lifetimeCashFlows.totalDeposited).toEqualTypeOf<string>()
342
+ expectTypeOf(json.data[0]!.lifetimeCashFlows.totalWithdrawn).toEqualTypeOf<string>()
343
+ }
289
344
  expectTypeOf(json.data[0]!.shareAmount.amount).toEqualTypeOf<string>()
290
345
  expectTypeOf(json.data[0]!.shareAmount.decimals).toEqualTypeOf<number>()
291
346
  expectTypeOf(json.data[0]!.shareAmount.formatted).toEqualTypeOf<string>()
@@ -336,6 +391,7 @@ describe('narrows responses by status', () => {
336
391
  expectTypeOf(json.assetToken.address).toEqualTypeOf<`0x${string}`>()
337
392
  expectTypeOf(json.engine.type).toEqualTypeOf<'erc4626' | 'veda' | null>()
338
393
  expectTypeOf(json.instantLiquidity).toEqualTypeOf<string | null>()
394
+ expectTypeOf(json.instantLiquidityValue).toEqualTypeOf<VaultValue | null | undefined>()
339
395
  expectTypeOf(json.label).toEqualTypeOf<string>()
340
396
  expectTypeOf(json.meta?.valuation?.asOf).toEqualTypeOf<string | undefined>()
341
397
  expectTypeOf(json.sharePrice?.decimals).toEqualTypeOf<number | undefined>()
@@ -374,6 +430,7 @@ describe('narrows responses by status', () => {
374
430
  address: `0x${'bb'.repeat(20)}`,
375
431
  vaultId: `0x${'aa'.repeat(20)}`,
376
432
  },
433
+ query: { asOf: '2026-07-21T09:00:00.000Z' },
377
434
  })
378
435
 
379
436
  expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 404 | 502 | PaidAccessStatus>()
@@ -385,6 +442,9 @@ describe('narrows responses by status', () => {
385
442
  expectTypeOf(json.assetAllowance).toEqualTypeOf<string>()
386
443
  expectTypeOf(json.assetBalance).toEqualTypeOf<string>()
387
444
  expectTypeOf(json.assetToken).toEqualTypeOf<`0x${string}`>()
445
+ expectTypeOf(json.asOf).toEqualTypeOf<string | undefined>()
446
+ expectTypeOf(json.block?.number).toEqualTypeOf<number | undefined>()
447
+ expectTypeOf(json.block?.timestamp).toEqualTypeOf<string | undefined>()
388
448
  expectTypeOf(json.id).toEqualTypeOf<`0x${string}`>()
389
449
  expectTypeOf(json.shareAllowance).toEqualTypeOf<string>()
390
450
  expectTypeOf(json.shareBalance).toEqualTypeOf<string>()
@@ -442,7 +502,23 @@ describe('narrows responses by status', () => {
442
502
  if (json.status === 'complete' && json.period === 'active')
443
503
  expectTypeOf(json.activeEarnings).toEqualTypeOf<string>()
444
504
  if (json.status === 'complete' && json.period === 'lifetime')
445
- expectTypeOf(json.lifetimeEarnings).toEqualTypeOf<string>()
505
+ expectTypeOf({
506
+ lifetimeEarnings: json.lifetimeEarnings,
507
+ totalDeposited: json.totalDeposited,
508
+ totalWithdrawn: json.totalWithdrawn,
509
+ }).toEqualTypeOf<{
510
+ lifetimeEarnings: string
511
+ totalDeposited: string
512
+ totalWithdrawn: string
513
+ }>()
514
+ if (json.status === 'pending_redemption' && json.period === 'lifetime')
515
+ expectTypeOf({
516
+ totalDeposited: json.totalDeposited,
517
+ totalWithdrawn: json.totalWithdrawn,
518
+ }).toEqualTypeOf<{
519
+ totalDeposited: string
520
+ totalWithdrawn: string
521
+ }>()
446
522
  if (json.status === 'complete' && json.period === '30d')
447
523
  expectTypeOf(json.windowEarnings).toEqualTypeOf<string>()
448
524
  void json
@@ -2563,6 +2639,7 @@ describe('narrows responses by status', () => {
2563
2639
  amount: '1000000',
2564
2640
  destinationToken: '0x20c000000000000000000000b9537d11c60e8b50',
2565
2641
  mode: 'exactSource',
2642
+ provider: 'stargate',
2566
2643
  recipient: `0x${'11'.repeat(20)}`,
2567
2644
  sender: `0x${'22'.repeat(20)}`,
2568
2645
  sourceChain: 'eip155:8453',
@@ -2692,6 +2769,42 @@ describe('narrows responses by status', () => {
2692
2769
  }
2693
2770
  })
2694
2771
 
2772
+ test('POST /v1/funding/transfers/:id/source-transactions', async () => {
2773
+ const client = Client.create()
2774
+ const res = await client.v1.funding.transfers[':id{ftr_[A-Za-z0-9_-]+}'][
2775
+ 'source-transactions'
2776
+ ].$post({
2777
+ json: { transactionHash: `0x${'51'.repeat(32)}` },
2778
+ param: { id: 'ftr_test' },
2779
+ })
2780
+
2781
+ expectTypeOf(res.status).toEqualTypeOf<200 | 400 | 404 | 409 | 501 | 502 | PublicAccessStatus>()
2782
+
2783
+ switch (res.status) {
2784
+ case 200: {
2785
+ const json = await res.json()
2786
+ expectTypeOf(json.sourceTransactionHashes).toEqualTypeOf<string[] | undefined>()
2787
+ expectTypeOf(json.status).toEqualTypeOf<
2788
+ z.output<
2789
+ typeof FundingTransfers.schema.registerFundingTransferSourceTransaction.Response
2790
+ >['status']
2791
+ >()
2792
+ void json
2793
+ return
2794
+ }
2795
+ case 409: {
2796
+ const json = await res.json()
2797
+ expectTypeOf(json.error.code).toEqualTypeOf<
2798
+ | 'funding_transfer_not_awaiting_source'
2799
+ | 'source_transaction_conflict'
2800
+ | 'source_transaction_pending'
2801
+ >()
2802
+ void json
2803
+ return
2804
+ }
2805
+ }
2806
+ })
2807
+
2695
2808
  test('GET /v1/exchange/swaps', async () => {
2696
2809
  const client = Client.create()
2697
2810
  const res = await client.v1.exchange.swaps.$get()
@@ -3611,6 +3724,16 @@ describe('narrows responses by status', () => {
3611
3724
  },
3612
3725
  },
3613
3726
  })
3727
+ void client.v1.webhooks.$post({
3728
+ json: {
3729
+ destination: { type: 'url', url: 'https://example.com/webhook' },
3730
+ eventType: 'funding:transfer.updated',
3731
+ filters: {
3732
+ id: 'ftr_001785792000000_2ZPE2gvateYEQ0dQslgvkhjx',
3733
+ status: 'completed',
3734
+ },
3735
+ },
3736
+ })
3614
3737
  const res = await client.v1.webhooks.$post({
3615
3738
  json: {
3616
3739
  destination: { type: 'url', url: 'https://example.com/webhook' },
@@ -3902,6 +4025,10 @@ describe('narrows responses by status', () => {
3902
4025
  expectTypeOf(json.envelope.data.status).toEqualTypeOf<
3903
4026
  z.output<typeof Webhooks.schema.FundingDepositEvent>['status']
3904
4027
  >()
4028
+ if (json.envelope.type === 'funding:transfer.updated')
4029
+ expectTypeOf(json.envelope.data.status).toEqualTypeOf<
4030
+ z.output<typeof Webhooks.schema.FundingTransferEvent>['status']
4031
+ >()
3905
4032
  expectTypeOf(json.requestUrl).toEqualTypeOf<string>()
3906
4033
  void json
3907
4034
  }
package/src/Scope.test.ts CHANGED
@@ -52,3 +52,23 @@ describe('extend', () => {
52
52
  ).toThrowErrorMatchingInlineSnapshot(`[Error: Duplicate scope \`data:read\`.]`)
53
53
  })
54
54
  })
55
+
56
+ describe('expandAliases', () => {
57
+ test('adds the current scope for a legacy Zone read scope', () => {
58
+ expect(
59
+ Scope.expandAliases(['data:read', 'zone:1424310001:read', 'zone:1424310001:write']),
60
+ ).toEqual([
61
+ 'data:read',
62
+ 'zone:1424310001:read',
63
+ 'zone:1424310001:write',
64
+ 'zone:1424310003:read',
65
+ ])
66
+ })
67
+
68
+ test('does not duplicate an existing current scope', () => {
69
+ expect(Scope.expandAliases(['zone:1424310001:read', 'zone:1424310003:read'])).toEqual([
70
+ 'zone:1424310001:read',
71
+ 'zone:1424310003:read',
72
+ ])
73
+ })
74
+ })
package/src/Scope.ts CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  import * as z from 'zod/mini'
8
8
 
9
+ import * as Schema from './internal/Schema.js'
10
+
9
11
  /**
10
12
  * Wildcard scope. A key whose `scopes` contains this value satisfies every
11
13
  * required scope, so it never needs re-provisioning when new scopes are added.
@@ -154,6 +156,20 @@ export function includes(catalog: Catalog, scope: string): scope is Id {
154
156
  return schema.Zone.safeParse(scope).success || catalog.some((entry) => entry.scope === scope)
155
157
  }
156
158
 
159
+ /** Adds current read scopes granted by legacy Zone read scopes. */
160
+ export function expandAliases(scopes: readonly string[]): readonly string[] {
161
+ const aliases = new Set<string>()
162
+ for (const scope of scopes) {
163
+ const match = /^zone:([1-9]\d*):read$/.exec(scope)
164
+ if (!match) continue
165
+ const chainId = Number(match[1])
166
+ const resolved = Schema.resolveChainId(chainId)
167
+ if (resolved !== chainId) aliases.add(`zone:${resolved}:read`)
168
+ }
169
+ for (const scope of scopes) aliases.delete(scope)
170
+ return aliases.size ? [...scopes, ...aliases] : scopes
171
+ }
172
+
157
173
  /** Returns the self-issuable identifiers in a scope catalog. */
158
174
  export function selfServeFrom(catalog: Catalog): readonly Id[] {
159
175
  return catalog
package/src/Webhooks.ts CHANGED
@@ -5,6 +5,6 @@ export * from './internal/Webhooks.js'
5
5
 
6
6
  // Re-export the webhook resource's zod schemas so consumers can validate and
7
7
  // type delivery bodies: `Webhooks.schema.Envelope` (a discriminated union on
8
- // `type`), plus the per-event `TransferEvent` / `TransactionEvent` / `PingEvent`
9
- // payloads. Infer a type with `z.infer<typeof Webhooks.schema.Envelope>`.
8
+ // `type`), plus the per-event payload schemas such as `FundingTransferEvent`.
9
+ // Infer a type with `z.infer<typeof Webhooks.schema.Envelope>`.
10
10
  export { enrichEventData, eventTypes, scanBlock, schema } from './apps/data/routes/webhooks.js'
@@ -299,6 +299,81 @@ describe('DELETE /api-keys/:id', () => {
299
299
  })
300
300
  })
301
301
 
302
+ describe('POST /api-keys/:id/rotate', () => {
303
+ test('mints a replacement with the source access and attribution', async () => {
304
+ const { client, store } = await setup()
305
+ const { record: source, token: sourceToken } = await core_ApiKeys.mint(store, {
306
+ allowedIps: ['203.0.113.0/24'],
307
+ billingActive: true,
308
+ createdBy: 'customer@example.com',
309
+ environment: 'sandbox',
310
+ expiresAt: '2100-01-01T00:00:00.000Z',
311
+ name: 'Privy Zones',
312
+ orgId: 'org_privy',
313
+ projectId: 'prj_privy',
314
+ rateLimits: { '*': { limit: 10_000, period: 'minute' } },
315
+ scopes: ['zone:421700001:read', 'zone:421700001:write'],
316
+ })
317
+
318
+ const response = await client['api-keys'][':id'].rotate.$post({
319
+ param: { id: source.id },
320
+ })
321
+ const body = await TestApp.json(response, ApiKeys.schema.rotateApiKey.Response)
322
+
323
+ expect(response.status).toBe(200)
324
+ expect(body).toMatchObject({
325
+ allowedIps: source.allowedIps,
326
+ billingActive: source.billingActive,
327
+ createdBy: TestAdmin.identity.email,
328
+ environment: source.environment,
329
+ expiresAt: source.expiresAt,
330
+ name: source.name,
331
+ orgId: source.orgId,
332
+ projectId: source.projectId,
333
+ rateLimits: source.rateLimits,
334
+ scopes: source.scopes,
335
+ })
336
+ expect(body.id).not.toBe(source.id)
337
+ expect(body.token).not.toBe(sourceToken)
338
+ expect(await core_ApiKeys.resolve(store, sourceToken)).not.toBeNull()
339
+ expect(await core_ApiKeys.resolve(store, body.token)).toMatchObject({
340
+ id: body.id,
341
+ scopes: source.scopes,
342
+ })
343
+ })
344
+
345
+ test('unknown id → 404', async () => {
346
+ const { client } = await setup()
347
+ const response = await client['api-keys'][':id'].rotate.$post({
348
+ param: { id: 'key_missing' },
349
+ })
350
+
351
+ expect(response.status).toMatchInlineSnapshot(`404`)
352
+ })
353
+
354
+ test('keeps a rotated one-off key assignable to an organization', async () => {
355
+ const { client, db, store } = await setup()
356
+ const organization = await Organizations.create(db, { name: 'Tempo' })
357
+ const { record: source } = await core_ApiKeys.mint(store, {
358
+ name: 'One-off',
359
+ scopes: ['data:read'],
360
+ })
361
+
362
+ const rotateResponse = await client['api-keys'][':id'].rotate.$post({
363
+ param: { id: source.id },
364
+ })
365
+ const replacement = await TestApp.json(rotateResponse, ApiKeys.schema.rotateApiKey.Response)
366
+ expect(replacement.orgId).toBe(replacement.id)
367
+
368
+ const updateResponse = await client['api-keys'][':id'].$patch({
369
+ json: { orgId: organization.id },
370
+ param: { id: replacement.id },
371
+ })
372
+ expect(updateResponse.status).toBe(200)
373
+ expect((await core_ApiKeys.get(store, replacement.id))?.orgId).toBe(organization.id)
374
+ })
375
+ })
376
+
302
377
  describe('PATCH /api-keys/:id', () => {
303
378
  test('preserves the allowlist when omitted', async () => {
304
379
  const { client, store } = TestAdmin.setup()
@@ -173,6 +173,24 @@ export namespace schema {
173
173
  .object({ id: z.string().check(z.describe('Revoked key id.')) })
174
174
  .check(z.describe('API-key revocation result.'))
175
175
  }
176
+
177
+ /** Schemas for the rotateApiKey operation. */
178
+ export namespace rotateApiKey {
179
+ /** Path parameters for rotating a key. */
180
+ export const Params = z
181
+ .object({
182
+ id: z
183
+ .string()
184
+ .check(
185
+ z.describe('Stable id of the key to rotate.'),
186
+ z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
187
+ ),
188
+ })
189
+ .check(z.describe('Path parameters for rotating an API key.'))
190
+
191
+ /** Response: the replacement record plus its one-time plaintext token. */
192
+ export const Response = createApiKey.Response
193
+ }
176
194
  }
177
195
 
178
196
  /**
@@ -183,6 +201,7 @@ export namespace schema {
183
201
  * - `GET /` lists key records (metadata only), optionally filtered by `orgId`.
184
202
  * - `DELETE /:id` revokes a key by id (`404` if absent).
185
203
  * - `PATCH /:id` updates a key's allowlist, name, or project, or assigns its first organization.
204
+ * - `POST /:id/rotate` mints a replacement with the source key's access and attribution.
186
205
  * - `POST /backfill` rebuilds the id and org index entries for every record.
187
206
  */
188
207
  export function apiKeys() {
@@ -315,6 +334,51 @@ export function apiKeys() {
315
334
  return c.json(Response.validated(schema.revokeApiKey.Response, { id }))
316
335
  },
317
336
  )
337
+ .post(
338
+ '/:id/rotate',
339
+ OpenApi.validate('param', schema.rotateApiKey.Params, {
340
+ code: 'param_invalid',
341
+ message: 'Invalid path parameters',
342
+ }),
343
+ OpenApi.describeRoute({
344
+ description: 'Create a replacement that preserves the source key access and attribution. The source key remains active.', // prettier-ignore
345
+ operationId: 'rotateAdminApiKey',
346
+ responses: OpenApi.responses({
347
+ errors: { 404: 'API key not found.' },
348
+ success: {
349
+ description: 'Replacement key (includes the one-time token).',
350
+ schema: schema.rotateApiKey.Response,
351
+ },
352
+ }),
353
+ summary: 'Rotate API key',
354
+ tags: ['API keys'],
355
+ }),
356
+ async (c) => {
357
+ const { id } = c.req.valid('param')
358
+ const store = c.get('kv').store
359
+ const source = await ApiKeys.get(store, id)
360
+ if (!source)
361
+ return Response.error(c, {
362
+ code: 'not_found',
363
+ message: 'API key not found.',
364
+ status: 404,
365
+ })
366
+
367
+ const { record, token } = await ApiKeys.mint(store, {
368
+ allowedIps: source.allowedIps,
369
+ createdBy: c.get('identity')!.email,
370
+ environment: source.environment,
371
+ scopes: source.scopes,
372
+ ...(source.billingActive === undefined ? {} : { billingActive: source.billingActive }),
373
+ ...(source.expiresAt === undefined ? {} : { expiresAt: source.expiresAt }),
374
+ ...(source.name === undefined ? {} : { name: source.name }),
375
+ ...(source.orgId === source.id ? {} : { orgId: source.orgId }),
376
+ ...(source.projectId === undefined ? {} : { projectId: source.projectId }),
377
+ ...(source.rateLimits === undefined ? {} : { rateLimits: source.rateLimits }),
378
+ })
379
+ return c.json(Response.validated(schema.rotateApiKey.Response, { ...record, token }), 200)
380
+ },
381
+ )
318
382
  .patch(
319
383
  '/:id',
320
384
  OpenApi.validate('param', schema.updateApiKey.Params, {
@@ -204,7 +204,7 @@ describe('putVerifiedEarnVault', () => {
204
204
  expect(await response.json()).toMatchObject({
205
205
  error: {
206
206
  code: 'body_invalid',
207
- details: [{ message: 'Zone 1424310001 is configured more than once.' }],
207
+ details: [{ message: 'Zone 1424310003 is configured more than once.' }],
208
208
  },
209
209
  })
210
210
  },
@@ -94,7 +94,7 @@ export namespace schema {
94
94
  .check(z.describe('Custom vault slug, generated from the label when omitted.')),
95
95
  vaultAddress: Schema.Address.check(
96
96
  z.describe('Earn vault contract address.'),
97
- z.meta({ examples: ['0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a'] }),
97
+ z.meta({ examples: ['0x4f94590b636f5878bce585e82379de81e1ec174f'] }),
98
98
  ),
99
99
  zones: z
100
100
  .optional(z.array(EarnVaults.schema.ZoneRoute))
@@ -510,6 +510,7 @@ async function serializeVault(
510
510
  assetToken,
511
511
  discovery: options.discovery,
512
512
  include: options.include,
513
+ instantLiquidityValue: null,
513
514
  record: options.record,
514
515
  shareToken,
515
516
  tvl: null,
@@ -181,6 +181,7 @@ describe('GET /organizations/:orgId', () => {
181
181
  settings: { spendLimit: '1000', txFeeLimit: null },
182
182
  source: null,
183
183
  })
184
+ expect(body.sponsorshipSubsidy).toEqual({ durationDays: null, projectSpendLimit: null })
184
185
  })
185
186
 
186
187
  test('returns empty counts and billing for a memberless organization', async () => {
@@ -215,6 +216,57 @@ describe('GET /organizations/:orgId', () => {
215
216
  })
216
217
  })
217
218
 
219
+ describe('PUT /organizations/:orgId/sponsorship', () => {
220
+ test('enables and disables a 90-day per-project policy', async () => {
221
+ const { client, db } = TestAdmin.setup()
222
+ const organization = await Organizations.create(db, { name: 'Privy' })
223
+
224
+ const enabled = await client.organizations[':orgId'].sponsorship.$put({
225
+ json: { enabled: true, projectSpendLimit: '1000' },
226
+ param: { orgId: organization.id },
227
+ })
228
+ expect(
229
+ await TestApp.json(enabled, AdminOrganizations.schema.organizationSponsorship.SetResponse),
230
+ ).toEqual({ durationDays: 90, projectSpendLimit: '1000' })
231
+
232
+ const disabled = await client.organizations[':orgId'].sponsorship.$put({
233
+ json: { enabled: false },
234
+ param: { orgId: organization.id },
235
+ })
236
+ expect(
237
+ await TestApp.json(disabled, AdminOrganizations.schema.organizationSponsorship.SetResponse),
238
+ ).toEqual({ durationDays: null, projectSpendLimit: null })
239
+ })
240
+
241
+ test('enables an uncapped policy', async () => {
242
+ const { client, db } = TestAdmin.setup()
243
+ const organization = await Organizations.create(db, { name: 'Privy' })
244
+ const response = await client.organizations[':orgId'].sponsorship.$put({
245
+ json: { enabled: true },
246
+ param: { orgId: organization.id },
247
+ })
248
+ expect(
249
+ await TestApp.json(response, AdminOrganizations.schema.organizationSponsorship.SetResponse),
250
+ ).toEqual({ durationDays: 90, projectSpendLimit: null })
251
+ })
252
+
253
+ test('rejects invalid limits and unknown organizations', async () => {
254
+ const { app, client } = TestAdmin.setup()
255
+ const invalid = await app.request('/organizations/org_example/sponsorship', {
256
+ body: JSON.stringify({ enabled: true, projectSpendLimit: '-1' }),
257
+ headers: { 'content-type': 'application/json' },
258
+ method: 'PUT',
259
+ })
260
+ expect(invalid.status).toBe(400)
261
+
262
+ const missing = await client.organizations[':orgId'].sponsorship.$put({
263
+ json: { enabled: true, projectSpendLimit: '1000' },
264
+ param: { orgId: 'org_missing' },
265
+ })
266
+ expect(missing.status).toBe(404)
267
+ })
268
+ })
269
+
218
270
  describe('PUT/DELETE /organizations/:orgId/billing-sources/:source', () => {
219
271
  test('enables and disables sources idempotently', async () => {
220
272
  const { client, db } = TestAdmin.setup()
@@ -425,7 +477,7 @@ describe('GET /organizations/:orgId/sponsorship', () => {
425
477
  })
426
478
  const body = await TestApp.json(
427
479
  response,
428
- AdminOrganizations.schema.getOrganizationSponsorship.Response,
480
+ AdminOrganizations.schema.organizationSponsorship.GetResponse,
429
481
  )
430
482
 
431
483
  expect(body.production).toMatchObject({