tapimo 0.19.0 → 0.20.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 (494) hide show
  1. package/README.md +13 -5
  2. package/dist/ApiKey.d.ts +2 -2
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +2 -2
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +85 -11
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +218 -56
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +12543 -13912
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +4 -5
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +12 -20
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +20 -36
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/admin/App.d.ts +871 -828
  19. package/dist/admin/App.d.ts.map +1 -1
  20. package/dist/admin/App.js +14 -26
  21. package/dist/admin/App.js.map +1 -1
  22. package/dist/admin/apps/api-keys.d.ts +93 -186
  23. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.js +3 -5
  25. package/dist/admin/apps/api-keys.js.map +1 -1
  26. package/dist/admin/apps/audit-logs.d.ts +18 -18
  27. package/dist/admin/apps/audit-logs.js +1 -1
  28. package/dist/admin/apps/audit-logs.js.map +1 -1
  29. package/dist/admin/apps/earn-vaults.d.ts +27 -27
  30. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  31. package/dist/admin/apps/earn-vaults.js +11 -5
  32. package/dist/admin/apps/earn-vaults.js.map +1 -1
  33. package/dist/admin/apps/organizations.d.ts +17 -17
  34. package/dist/admin/apps/prop-amms.d.ts +4 -4
  35. package/dist/admin/apps/routes-support.js +1 -38
  36. package/dist/admin/apps/routes-support.js.map +1 -1
  37. package/dist/admin/apps/routes.d.ts +153 -153
  38. package/dist/admin/apps/sentinel.d.ts +4 -4
  39. package/dist/admin/apps/verified-tokens.d.ts +24 -24
  40. package/dist/admin/apps/zone-delegation-requests.d.ts +332 -0
  41. package/dist/admin/apps/zone-delegation-requests.d.ts.map +1 -0
  42. package/dist/admin/apps/zone-delegation-requests.js +200 -0
  43. package/dist/admin/apps/zone-delegation-requests.js.map +1 -0
  44. package/dist/admin/apps/zone-delegations.d.ts +512 -52
  45. package/dist/admin/apps/zone-delegations.d.ts.map +1 -1
  46. package/dist/admin/apps/zone-delegations.js +134 -44
  47. package/dist/admin/apps/zone-delegations.js.map +1 -1
  48. package/dist/admin/index.d.ts +1 -1
  49. package/dist/admin/index.d.ts.map +1 -1
  50. package/dist/admin/index.js +1 -1
  51. package/dist/admin/index.js.map +1 -1
  52. package/dist/admin/ui.generated.d.ts +1 -1
  53. package/dist/admin/ui.generated.d.ts.map +1 -1
  54. package/dist/admin/ui.generated.js +341 -397
  55. package/dist/admin/ui.generated.js.map +1 -1
  56. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  57. package/dist/analytics/tables/requestEvents.js +4 -2
  58. package/dist/analytics/tables/requestEvents.js.map +1 -1
  59. package/dist/apps/data/App.d.ts +11932 -13214
  60. package/dist/apps/data/App.d.ts.map +1 -1
  61. package/dist/apps/data/App.js +32 -13
  62. package/dist/apps/data/App.js.map +1 -1
  63. package/dist/apps/data/ZoneSelection.d.ts +1 -1
  64. package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
  65. package/dist/apps/data/ZoneSelection.js +2 -2
  66. package/dist/apps/data/ZoneSelection.js.map +1 -1
  67. package/dist/apps/data/routes/activities.d.ts +60 -27
  68. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  69. package/dist/apps/data/routes/activities.js +91 -16
  70. package/dist/apps/data/routes/activities.js.map +1 -1
  71. package/dist/apps/data/routes/addresses.d.ts +893 -875
  72. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  73. package/dist/apps/data/routes/balances.d.ts +36 -36
  74. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  75. package/dist/apps/data/routes/balances.js +3 -1
  76. package/dist/apps/data/routes/balances.js.map +1 -1
  77. package/dist/apps/data/routes/blocks.d.ts +40 -40
  78. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  79. package/dist/apps/data/routes/blocks.js +3 -7
  80. package/dist/apps/data/routes/blocks.js.map +1 -1
  81. package/dist/apps/data/routes/coingecko.d.ts +236 -236
  82. package/dist/apps/data/routes/earn-transactions.d.ts +14 -14
  83. package/dist/apps/data/routes/earn.d.ts +261 -1445
  84. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  85. package/dist/apps/data/routes/earn.js +64 -490
  86. package/dist/apps/data/routes/earn.js.map +1 -1
  87. package/dist/apps/data/routes/exchanges.d.ts +144 -144
  88. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  89. package/dist/apps/data/routes/exchanges.js +5 -15
  90. package/dist/apps/data/routes/exchanges.js.map +1 -1
  91. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  92. package/dist/apps/data/routes/fee-amm.js +3 -9
  93. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  94. package/dist/apps/data/routes/indexer.d.ts +13 -13
  95. package/dist/apps/data/routes/receipts.d.ts +53 -53
  96. package/dist/apps/data/routes/receipts.js +1 -1
  97. package/dist/apps/data/routes/receipts.js.map +1 -1
  98. package/dist/apps/data/routes/rpc.d.ts +52 -0
  99. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  100. package/dist/apps/data/routes/rpc.js +19 -18
  101. package/dist/apps/data/routes/rpc.js.map +1 -1
  102. package/dist/apps/data/routes/tokenlist.d.ts +14 -14
  103. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  104. package/dist/apps/data/routes/tokenlist.js +1 -3
  105. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  106. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  107. package/dist/apps/data/routes/tokens.js +7 -5
  108. package/dist/apps/data/routes/tokens.js.map +1 -1
  109. package/dist/apps/data/routes/transactions.d.ts +281 -281
  110. package/dist/apps/data/routes/transactions.js +3 -3
  111. package/dist/apps/data/routes/transactions.js.map +1 -1
  112. package/dist/apps/data/routes/transfers.d.ts +12 -12
  113. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  114. package/dist/apps/data/routes/transfers.js +1 -3
  115. package/dist/apps/data/routes/transfers.js.map +1 -1
  116. package/dist/apps/data/routes/valuation.d.ts +30 -30
  117. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  118. package/dist/apps/data/routes/valuation.js +1 -3
  119. package/dist/apps/data/routes/valuation.js.map +1 -1
  120. package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
  121. package/dist/apps/data/routes/webhooks.d.ts +102 -102
  122. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  123. package/dist/apps/data/routes/webhooks.js +9 -23
  124. package/dist/apps/data/routes/webhooks.js.map +1 -1
  125. package/dist/apps/data/routes/zone-deposits.d.ts +16 -16
  126. package/dist/apps/data/routes/zone-withdrawals.d.ts +31 -31
  127. package/dist/apps/data/routes/zones.d.ts +28 -28
  128. package/dist/apps/management/App.d.ts +18 -102
  129. package/dist/apps/management/App.d.ts.map +1 -1
  130. package/dist/apps/management/App.js +1 -1
  131. package/dist/apps/management/App.js.map +1 -1
  132. package/dist/apps/management/routes/api-keys.d.ts +253 -339
  133. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  134. package/dist/apps/management/routes/api-keys.js +25 -11
  135. package/dist/apps/management/routes/api-keys.js.map +1 -1
  136. package/dist/apps/management/routes/billing.d.ts +92 -92
  137. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  138. package/dist/apps/management/routes/billing.js +5 -13
  139. package/dist/apps/management/routes/billing.js.map +1 -1
  140. package/dist/apps/management/routes/cli.d.ts.map +1 -1
  141. package/dist/apps/management/routes/cli.js +3 -9
  142. package/dist/apps/management/routes/cli.js.map +1 -1
  143. package/dist/apps/management/routes/faucet.d.ts +16 -16
  144. package/dist/apps/management/routes/fee-payer-usage.d.ts +38 -38
  145. package/dist/apps/management/routes/fee-payer-usage.d.ts.map +1 -1
  146. package/dist/apps/management/routes/fee-payer-usage.js +2 -4
  147. package/dist/apps/management/routes/fee-payer-usage.js.map +1 -1
  148. package/dist/apps/management/routes/invitations.d.ts +52 -52
  149. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  150. package/dist/apps/management/routes/invitations.js +4 -12
  151. package/dist/apps/management/routes/invitations.js.map +1 -1
  152. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  153. package/dist/apps/management/routes/invite-links.js +6 -14
  154. package/dist/apps/management/routes/invite-links.js.map +1 -1
  155. package/dist/apps/management/routes/me.d.ts +6 -6
  156. package/dist/apps/management/routes/me.d.ts.map +1 -1
  157. package/dist/apps/management/routes/me.js +3 -7
  158. package/dist/apps/management/routes/me.js.map +1 -1
  159. package/dist/apps/management/routes/members.d.ts +84 -84
  160. package/dist/apps/management/routes/members.d.ts.map +1 -1
  161. package/dist/apps/management/routes/members.js +2 -4
  162. package/dist/apps/management/routes/members.js.map +1 -1
  163. package/dist/apps/management/routes/orgs.d.ts +44 -44
  164. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  165. package/dist/apps/management/routes/orgs.js +2 -6
  166. package/dist/apps/management/routes/orgs.js.map +1 -1
  167. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  168. package/dist/apps/management/routes/projects.js +2 -6
  169. package/dist/apps/management/routes/projects.js.map +1 -1
  170. package/dist/apps/management/routes/route-usage.d.ts +34 -34
  171. package/dist/apps/management/routes/route-usage.d.ts.map +1 -1
  172. package/dist/apps/management/routes/route-usage.js +2 -4
  173. package/dist/apps/management/routes/route-usage.js.map +1 -1
  174. package/dist/apps/management/routes/routes-access-requests.d.ts +120 -91
  175. package/dist/apps/management/routes/routes-access-requests.d.ts.map +1 -1
  176. package/dist/apps/management/routes/routes-access-requests.js +49 -9
  177. package/dist/apps/management/routes/routes-access-requests.js.map +1 -1
  178. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  179. package/dist/apps/management/routes/usage.js +8 -16
  180. package/dist/apps/management/routes/usage.js.map +1 -1
  181. package/dist/apps/management/routes/verified-token-requests.d.ts +39 -39
  182. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  183. package/dist/apps/management/routes/verified-token-requests.js +3 -7
  184. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  185. package/dist/apps/management/routes/webhooks.d.ts +2089 -2089
  186. package/dist/apps/management/routes/zone-delegations.d.ts +14 -17
  187. package/dist/apps/management/routes/zone-delegations.d.ts.map +1 -1
  188. package/dist/apps/management/routes/zone-delegations.js +1 -6
  189. package/dist/apps/management/routes/zone-delegations.js.map +1 -1
  190. package/dist/apps/mpp/App.d.ts +44 -44
  191. package/dist/apps/mpp/App.js +3 -3
  192. package/dist/apps/mpp/App.js.map +1 -1
  193. package/dist/apps/mpp/internal/Adapter.js +1 -1
  194. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  195. package/dist/apps/mpp/internal/Error.d.ts.map +1 -1
  196. package/dist/apps/mpp/internal/Error.js +1 -0
  197. package/dist/apps/mpp/internal/Error.js.map +1 -1
  198. package/dist/apps/mpp/internal/Policy.d.ts +5 -1
  199. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
  200. package/dist/apps/mpp/internal/Policy.js +35 -13
  201. package/dist/apps/mpp/internal/Policy.js.map +1 -1
  202. package/dist/apps/relay/App.d.ts +2 -2
  203. package/dist/apps/relay/App.d.ts.map +1 -1
  204. package/dist/apps/relay/App.js +25 -16
  205. package/dist/apps/relay/App.js.map +1 -1
  206. package/dist/apps/routes/App.d.ts +311 -311
  207. package/dist/apps/routes/routes/deposit-addresses.d.ts +1099 -1099
  208. package/dist/apps/routes/routes/list.d.ts +74 -74
  209. package/dist/apps/routes/routes/transfers.d.ts +94 -94
  210. package/dist/cli/ApiKeys.d.ts +19 -26
  211. package/dist/cli/ApiKeys.d.ts.map +1 -1
  212. package/dist/db/Db.d.ts +3 -3
  213. package/dist/db/Db.d.ts.map +1 -1
  214. package/dist/db/Db.js +27 -0
  215. package/dist/db/Db.js.map +1 -1
  216. package/dist/db/Schema.d.ts +28 -62
  217. package/dist/db/Schema.d.ts.map +1 -1
  218. package/dist/db/Schema.js +18 -18
  219. package/dist/db/Schema.js.map +1 -1
  220. package/dist/db/tables/rewardRuns.d.ts +21 -0
  221. package/dist/db/tables/rewardRuns.d.ts.map +1 -1
  222. package/dist/db/tables/rewardRuns.js +19 -0
  223. package/dist/db/tables/rewardRuns.js.map +1 -1
  224. package/dist/db/tables/routesAccessRequests.d.ts +13 -0
  225. package/dist/db/tables/routesAccessRequests.d.ts.map +1 -1
  226. package/dist/db/tables/routesAccessRequests.js +12 -0
  227. package/dist/db/tables/routesAccessRequests.js.map +1 -1
  228. package/dist/db/tables/zoneDelegationRequests.d.ts +165 -0
  229. package/dist/db/tables/zoneDelegationRequests.d.ts.map +1 -0
  230. package/dist/db/tables/{zoneKeyRequests.js → zoneDelegationRequests.js} +43 -42
  231. package/dist/db/tables/zoneDelegationRequests.js.map +1 -0
  232. package/dist/db/tables/zoneDelegations.d.ts +11 -5
  233. package/dist/db/tables/zoneDelegations.d.ts.map +1 -1
  234. package/dist/db/tables/zoneDelegations.js +21 -3
  235. package/dist/db/tables/zoneDelegations.js.map +1 -1
  236. package/dist/handlers/internal/accounts.d.ts +7 -0
  237. package/dist/handlers/internal/accounts.d.ts.map +1 -0
  238. package/dist/handlers/internal/{multisig.js → accounts.js} +10 -10
  239. package/dist/handlers/internal/{multisig.js.map → accounts.js.map} +1 -1
  240. package/dist/handlers/internal/sponsorship.js +17 -17
  241. package/dist/handlers/internal/sponsorship.js.map +1 -1
  242. package/dist/handlers/relay.d.ts +6 -6
  243. package/dist/handlers/relay.d.ts.map +1 -1
  244. package/dist/handlers/relay.js +15 -15
  245. package/dist/handlers/relay.js.map +1 -1
  246. package/dist/internal/Auth.d.ts.map +1 -1
  247. package/dist/internal/Auth.js +4 -8
  248. package/dist/internal/Auth.js.map +1 -1
  249. package/dist/internal/EarnRates.d.ts.map +1 -1
  250. package/dist/internal/EarnRates.js +1 -3
  251. package/dist/internal/EarnRates.js.map +1 -1
  252. package/dist/internal/EarnVaults.js +2 -2
  253. package/dist/internal/Log.d.ts +2 -4
  254. package/dist/internal/Log.d.ts.map +1 -1
  255. package/dist/internal/Log.js +0 -3
  256. package/dist/internal/Log.js.map +1 -1
  257. package/dist/internal/Response.d.ts +1 -1
  258. package/dist/internal/Response.d.ts.map +1 -1
  259. package/dist/internal/Response.js +0 -3
  260. package/dist/internal/Response.js.map +1 -1
  261. package/dist/internal/Schema.d.ts +11 -0
  262. package/dist/internal/Schema.d.ts.map +1 -1
  263. package/dist/internal/Schema.js +24 -1
  264. package/dist/internal/Schema.js.map +1 -1
  265. package/dist/internal/ZoneAccess.d.ts +70 -35
  266. package/dist/internal/ZoneAccess.d.ts.map +1 -1
  267. package/dist/internal/ZoneAccess.js +312 -131
  268. package/dist/internal/ZoneAccess.js.map +1 -1
  269. package/dist/internal/ZoneDelegation.d.ts +7 -19
  270. package/dist/internal/ZoneDelegation.d.ts.map +1 -1
  271. package/dist/internal/ZoneDelegation.js +8 -29
  272. package/dist/internal/ZoneDelegation.js.map +1 -1
  273. package/dist/internal/{ZoneKeyApproval.d.ts → ZoneDelegationApproval.d.ts} +3 -5
  274. package/dist/internal/ZoneDelegationApproval.d.ts.map +1 -0
  275. package/dist/internal/ZoneDelegationApproval.js +16 -0
  276. package/dist/internal/ZoneDelegationApproval.js.map +1 -0
  277. package/dist/internal/ZoneKeyRewrite.d.ts +98 -0
  278. package/dist/internal/ZoneKeyRewrite.d.ts.map +1 -0
  279. package/dist/internal/ZoneKeyRewrite.js +151 -0
  280. package/dist/internal/ZoneKeyRewrite.js.map +1 -0
  281. package/dist/internal/rewards/Campaigns.d.ts +2 -0
  282. package/dist/internal/rewards/Campaigns.d.ts.map +1 -1
  283. package/dist/internal/rewards/Campaigns.js.map +1 -1
  284. package/dist/internal/rewards/Distributions.d.ts.map +1 -1
  285. package/dist/internal/rewards/Distributions.js +2 -6
  286. package/dist/internal/rewards/Distributions.js.map +1 -1
  287. package/dist/internal/rewards/Monitor.d.ts +4 -1
  288. package/dist/internal/rewards/Monitor.d.ts.map +1 -1
  289. package/dist/internal/rewards/Monitor.js +19 -2
  290. package/dist/internal/rewards/Monitor.js.map +1 -1
  291. package/dist/internal/rewards/Runner.d.ts.map +1 -1
  292. package/dist/internal/rewards/Runner.js +9 -1
  293. package/dist/internal/rewards/Runner.js.map +1 -1
  294. package/dist/internal/routes/Action.d.ts.map +1 -1
  295. package/dist/internal/routes/Action.js +2 -3
  296. package/dist/internal/routes/Action.js.map +1 -1
  297. package/dist/internal/routes/Deposit.d.ts.map +1 -1
  298. package/dist/internal/routes/Deposit.js +2 -6
  299. package/dist/internal/routes/Deposit.js.map +1 -1
  300. package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
  301. package/dist/internal/routes/DepositAddress.js +4 -10
  302. package/dist/internal/routes/DepositAddress.js.map +1 -1
  303. package/dist/internal/routes/Policy.d.ts.map +1 -1
  304. package/dist/internal/routes/Policy.js +2 -1
  305. package/dist/internal/routes/Policy.js.map +1 -1
  306. package/dist/internal/routes/Provider.js +8 -8
  307. package/dist/internal/routes/Provider.js.map +1 -1
  308. package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
  309. package/dist/internal/routes/Reconciliation.js +3 -2
  310. package/dist/internal/routes/Reconciliation.js.map +1 -1
  311. package/dist/internal/routes/Transfer.d.ts.map +1 -1
  312. package/dist/internal/routes/Transfer.js +4 -12
  313. package/dist/internal/routes/Transfer.js.map +1 -1
  314. package/dist/internal/routes/UniversalDepositAddress.d.ts.map +1 -1
  315. package/dist/internal/routes/UniversalDepositAddress.js +3 -6
  316. package/dist/internal/routes/UniversalDepositAddress.js.map +1 -1
  317. package/dist/internal/routes/providers/SquidOrder.d.ts.map +1 -1
  318. package/dist/internal/routes/providers/SquidOrder.js +3 -2
  319. package/dist/internal/routes/providers/SquidOrder.js.map +1 -1
  320. package/dist/internal/routes/providers/relay.d.ts.map +1 -1
  321. package/dist/internal/routes/providers/relay.js +4 -3
  322. package/dist/internal/routes/providers/relay.js.map +1 -1
  323. package/package.json +20 -5
  324. package/src/ApiKey.ts +2 -2
  325. package/src/ApiKeys.test.ts +284 -51
  326. package/src/ApiKeys.ts +297 -64
  327. package/src/App.ts +4 -5
  328. package/src/Client.test-d.ts +33 -126
  329. package/src/Scope.test.ts +26 -45
  330. package/src/Scope.ts +24 -37
  331. package/src/admin/App.test.ts +51 -4
  332. package/src/admin/App.ts +25 -33
  333. package/src/admin/Mcp.test.ts +2 -1
  334. package/src/admin/apps/api-keys.test.ts +90 -20
  335. package/src/admin/apps/api-keys.ts +5 -8
  336. package/src/admin/apps/audit-logs.ts +1 -1
  337. package/src/admin/apps/earn-vaults.test.ts +19 -19
  338. package/src/admin/apps/earn-vaults.ts +11 -5
  339. package/src/admin/apps/routes-support.test.ts +254 -3
  340. package/src/admin/apps/routes-support.ts +1 -44
  341. package/src/admin/apps/scopes.test.ts +3 -3
  342. package/src/admin/apps/zone-delegation-requests.test.ts +246 -0
  343. package/src/admin/apps/zone-delegation-requests.ts +240 -0
  344. package/src/admin/apps/zone-delegations.test.ts +218 -58
  345. package/src/admin/apps/zone-delegations.ts +146 -46
  346. package/src/admin/index.ts +1 -1
  347. package/src/admin/ui/src/components/ApiKeyForm.tsx +4 -3
  348. package/src/admin/ui/src/lib/config.ts +3 -3
  349. package/src/admin/ui/src/lib/query-client.ts +1 -1
  350. package/src/admin/ui/src/lib/review-queues.ts +10 -10
  351. package/src/admin/ui/src/lib/routes-setup.test.ts +1 -2
  352. package/src/admin/ui/src/lib/routes-setup.ts +3 -5
  353. package/src/admin/ui/src/lib/scopes.test.ts +3 -6
  354. package/src/admin/ui/src/lib/scopes.ts +2 -9
  355. package/src/admin/ui/src/lib/{zone-key-requests.ts → zone-delegation-requests.ts} +27 -31
  356. package/src/admin/ui/src/routeTree.gen.ts +17 -17
  357. package/src/admin/ui/src/routes/__root.tsx +1 -1
  358. package/src/admin/ui/src/routes/api-keys.tsx +2 -15
  359. package/src/admin/ui/src/routes/audit-logs.tsx +2 -2
  360. package/src/admin/ui/src/routes/index.tsx +11 -11
  361. package/src/admin/ui/src/routes/organizations.tsx +3 -1
  362. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +3 -1
  363. package/src/admin/ui/src/routes/organizations_.$orgId_.setup.tsx +1 -3
  364. package/src/admin/ui/src/routes/{zone-key-requests.tsx → zone-delegation-requests.tsx} +228 -172
  365. package/src/admin/ui/vite.config.ts +14 -1
  366. package/src/admin/ui.generated.ts +412 -583
  367. package/src/analytics/tables/requestEvents.test.ts +13 -3
  368. package/src/analytics/tables/requestEvents.ts +4 -3
  369. package/src/apps/data/App.test.ts +72 -35
  370. package/src/apps/data/App.ts +29 -13
  371. package/src/apps/data/ZoneSelection.test.ts +53 -70
  372. package/src/apps/data/ZoneSelection.ts +2 -2
  373. package/src/apps/data/routes/activities.test.ts +140 -6
  374. package/src/apps/data/routes/activities.ts +124 -18
  375. package/src/apps/data/routes/balances.ts +5 -1
  376. package/src/apps/data/routes/blocks.ts +9 -13
  377. package/src/apps/data/routes/earn-transactions.local.test.ts +6 -1
  378. package/src/apps/data/routes/earn-transactions.test.ts +7 -3
  379. package/src/apps/data/routes/earn.bench.ts +0 -14
  380. package/src/apps/data/routes/earn.discovery.test.ts +4 -39
  381. package/src/apps/data/routes/earn.local.test.ts +27 -34
  382. package/src/apps/data/routes/earn.test.ts +172 -490
  383. package/src/apps/data/routes/earn.ts +103 -652
  384. package/src/apps/data/routes/exchanges.ts +20 -30
  385. package/src/apps/data/routes/fee-amm.ts +12 -18
  386. package/src/apps/data/routes/indexer.test.ts +14 -12
  387. package/src/apps/data/routes/receipts.ts +1 -1
  388. package/src/apps/data/routes/rpc.test.ts +23 -18
  389. package/src/apps/data/routes/rpc.ts +21 -21
  390. package/src/apps/data/routes/rpc.zone.test.ts +60 -6
  391. package/src/apps/data/routes/tokenlist.ts +4 -6
  392. package/src/apps/data/routes/tokens.test.ts +20 -0
  393. package/src/apps/data/routes/tokens.ts +10 -5
  394. package/src/apps/data/routes/transactions.ts +3 -3
  395. package/src/apps/data/routes/transfers.ts +4 -6
  396. package/src/apps/data/routes/valuation.test.ts +2 -4
  397. package/src/apps/data/routes/valuation.ts +4 -6
  398. package/src/apps/data/routes/webhooks.test.ts +1 -5
  399. package/src/apps/data/routes/webhooks.ts +30 -44
  400. package/src/apps/data/routes/zones.test.ts +35 -19
  401. package/src/apps/management/App.ts +3 -1
  402. package/src/apps/management/routes/api-keys.test.ts +112 -22
  403. package/src/apps/management/routes/api-keys.ts +30 -15
  404. package/src/apps/management/routes/billing.ts +17 -25
  405. package/src/apps/management/routes/cli.ts +12 -18
  406. package/src/apps/management/routes/fee-payer-usage.ts +5 -4
  407. package/src/apps/management/routes/invitations.ts +16 -21
  408. package/src/apps/management/routes/invite-links.ts +18 -26
  409. package/src/apps/management/routes/me.ts +9 -13
  410. package/src/apps/management/routes/members.ts +5 -7
  411. package/src/apps/management/routes/orgs.ts +8 -12
  412. package/src/apps/management/routes/projects.ts +8 -12
  413. package/src/apps/management/routes/route-usage.ts +5 -4
  414. package/src/apps/management/routes/routes-access-requests.test.ts +64 -2
  415. package/src/apps/management/routes/routes-access-requests.ts +99 -15
  416. package/src/apps/management/routes/scopes.test.ts +3 -3
  417. package/src/apps/management/routes/usage.ts +20 -28
  418. package/src/apps/management/routes/verified-token-requests.ts +9 -13
  419. package/src/apps/management/routes/zone-delegations.test.ts +3 -5
  420. package/src/apps/management/routes/zone-delegations.ts +4 -9
  421. package/src/apps/mpp/App.ts +3 -3
  422. package/src/apps/mpp/Mpp.zone.test.ts +49 -18
  423. package/src/apps/mpp/internal/Adapter.ts +1 -1
  424. package/src/apps/mpp/internal/Error.test.ts +3 -0
  425. package/src/apps/mpp/internal/Error.ts +1 -0
  426. package/src/apps/mpp/internal/Policy.test.ts +9 -8
  427. package/src/apps/mpp/internal/Policy.ts +37 -14
  428. package/src/apps/relay/App.sandbox.test.ts +15 -14
  429. package/src/apps/relay/App.test.ts +120 -61
  430. package/src/apps/relay/App.ts +28 -18
  431. package/src/apps/relay/App.zone-billing.test.ts +9 -4
  432. package/src/apps/routes/App.test.ts +21 -22
  433. package/src/db/Db.ts +34 -3
  434. package/src/db/Schema.ts +26 -26
  435. package/src/db/tables/rewardRuns.ts +39 -0
  436. package/src/db/tables/routesAccessRequests.test.ts +65 -0
  437. package/src/db/tables/routesAccessRequests.ts +25 -0
  438. package/src/db/tables/{zoneKeyRequests.test.ts → zoneDelegationRequests.test.ts} +36 -77
  439. package/src/db/tables/{zoneKeyRequests.ts → zoneDelegationRequests.ts} +69 -52
  440. package/src/db/tables/zoneDelegations.test.ts +5 -6
  441. package/src/db/tables/zoneDelegations.ts +25 -8
  442. package/src/handlers/internal/{multisig.store.test.ts → accounts.store.test.ts} +16 -16
  443. package/src/handlers/internal/{multisig.test.ts → accounts.test.ts} +85 -82
  444. package/src/handlers/internal/{multisig.ts → accounts.ts} +9 -9
  445. package/src/handlers/internal/sponsorship.ts +20 -20
  446. package/src/handlers/relay.test.ts +48 -46
  447. package/src/handlers/relay.ts +26 -26
  448. package/src/internal/Auth.test.ts +6 -2
  449. package/src/internal/Auth.ts +4 -10
  450. package/src/internal/EarnRates.ts +4 -6
  451. package/src/internal/EarnVaults.ts +2 -2
  452. package/src/internal/Log.test-d.ts +1 -0
  453. package/src/internal/Log.test.ts +4 -6
  454. package/src/internal/Log.ts +2 -6
  455. package/src/internal/Response.ts +0 -3
  456. package/src/internal/Schema.test.ts +42 -0
  457. package/src/internal/Schema.ts +36 -1
  458. package/src/internal/ZoneAccess.test.ts +515 -312
  459. package/src/internal/ZoneAccess.ts +410 -158
  460. package/src/internal/ZoneDelegation.test.ts +1 -41
  461. package/src/internal/ZoneDelegation.ts +10 -48
  462. package/src/internal/ZoneDelegationApproval.test.ts +22 -0
  463. package/src/internal/{ZoneKeyApproval.ts → ZoneDelegationApproval.ts} +4 -11
  464. package/src/internal/ZoneKeyRewrite.ts +231 -0
  465. package/src/internal/rewards/Campaigns.ts +2 -0
  466. package/src/internal/rewards/Distributions.ts +8 -12
  467. package/src/internal/rewards/Monitor.test.ts +64 -0
  468. package/src/internal/rewards/Monitor.ts +27 -4
  469. package/src/internal/rewards/Runner.ts +9 -1
  470. package/src/internal/routes/Action.ts +5 -6
  471. package/src/internal/routes/Deposit.ts +8 -12
  472. package/src/internal/routes/DepositAddress.ts +13 -19
  473. package/src/internal/routes/Policy.ts +2 -1
  474. package/src/internal/routes/Provider.ts +8 -8
  475. package/src/internal/routes/Reconciliation.ts +3 -2
  476. package/src/internal/routes/Transfer.ts +16 -24
  477. package/src/internal/routes/UniversalDepositAddress.ts +9 -12
  478. package/src/internal/routes/providers/SquidOrder.ts +3 -2
  479. package/src/internal/routes/providers/relay.ts +4 -3
  480. package/dist/admin/apps/zone-key-requests.d.ts +0 -406
  481. package/dist/admin/apps/zone-key-requests.d.ts.map +0 -1
  482. package/dist/admin/apps/zone-key-requests.js +0 -183
  483. package/dist/admin/apps/zone-key-requests.js.map +0 -1
  484. package/dist/db/tables/zoneKeyRequests.d.ts +0 -289
  485. package/dist/db/tables/zoneKeyRequests.d.ts.map +0 -1
  486. package/dist/db/tables/zoneKeyRequests.js.map +0 -1
  487. package/dist/handlers/internal/multisig.d.ts +0 -7
  488. package/dist/handlers/internal/multisig.d.ts.map +0 -1
  489. package/dist/internal/ZoneKeyApproval.d.ts.map +0 -1
  490. package/dist/internal/ZoneKeyApproval.js +0 -21
  491. package/dist/internal/ZoneKeyApproval.js.map +0 -1
  492. package/src/admin/apps/zone-key-requests.test.ts +0 -272
  493. package/src/admin/apps/zone-key-requests.ts +0 -231
  494. package/src/internal/ZoneKeyApproval.test.ts +0 -46
@@ -30,11 +30,6 @@ import * as Earn from './earn.js'
30
30
  const cache = { edge: false, store: Store.memory() } as const
31
31
 
32
32
  /** Fields every vault read enriches with live state, value, and rate data. */
33
- type EnrichedVault = Pick<
34
- z.output<typeof Earn.schema.Vault>,
35
- 'apy' | 'instantLiquidity' | 'sharePrice' | 'state' | 'tvl'
36
- >
37
-
38
33
  type OpenApiSchema = { $ref?: string }
39
34
 
40
35
  type OpenApiOperation = {
@@ -528,12 +523,10 @@ describe('GET /v1/earn/rewards/eligibility', () => {
528
523
  rpcUrl: 'https://mainnet-zone.example',
529
524
  sourceChainId: Viem.chainId.mainnet,
530
525
  })
531
- const key = {
532
- ...readKey,
533
- environment: 'sandbox',
534
- scopes: [...readKey.scopes, `zone:${zone.id}:read`],
535
- } satisfies TestApp.kvStore.Key
536
- const response = await TestApp.create({ auth: { keys: [key] }, zones: [zone] }).request(
526
+ const key = TestApp.zoneReader({ ...readKey, environment: 'sandbox' }, [zone.id])
527
+ const db = TestApp.database()
528
+ await TestApp.delegateZone(db, { chainIds: [zone.id], environment: 'sandbox', orgId: key.orgId }) // prettier-ignore
529
+ const response = await TestApp.create({ auth: { keys: [key] }, db, zones: [zone] }).request(
537
530
  `/v1/earn/rewards/eligibility?chainId=${zone.id}&vaultAddress=${vaultAddress}`,
538
531
  { headers: { authorization: `Bearer ${key.token}` } },
539
532
  )
@@ -546,12 +539,10 @@ describe('GET /v1/earn/rewards/eligibility', () => {
546
539
  chainId: 421_700_001,
547
540
  rpcUrl: 'https://unknown-zone.example',
548
541
  })
549
- const key = {
550
- ...readKey,
551
- environment: 'sandbox',
552
- scopes: [...readKey.scopes, `zone:${zone.id}:read`],
553
- } satisfies TestApp.kvStore.Key
554
- const response = await TestApp.create({ auth: { keys: [key] }, zones: [zone] }).request(
542
+ const key = TestApp.zoneReader({ ...readKey, environment: 'sandbox' }, [zone.id])
543
+ const db = TestApp.database()
544
+ await TestApp.delegateZone(db, { chainIds: [zone.id], environment: 'sandbox', orgId: key.orgId }) // prettier-ignore
545
+ const response = await TestApp.create({ auth: { keys: [key] }, db, zones: [zone] }).request(
555
546
  `/v1/earn/rewards/eligibility?chainId=${zone.id}&vaultAddress=${vaultAddress}`,
556
547
  { headers: { authorization: `Bearer ${key.token}` } },
557
548
  )
@@ -606,12 +597,12 @@ describe('GET /v1/earn/rewards/eligibility', () => {
606
597
  })
607
598
  })
608
599
  })
609
- describe('schema.getEarnVaults.Query', () => {
600
+ describe('schema.VaultCollectionQuery', () => {
610
601
  test('parses collection filters', () => {
611
- const query = Earn.schema.getEarnVaults.Query.parse({
602
+ const query = Earn.schema.VaultCollectionQuery.parse({
612
603
  capability: 'deposit,exactWithdraw',
613
604
  'engine.type': 'erc4626',
614
- include: 'access,apy,capabilities,zone,zones,token.logoUri,tvl',
605
+ include: 'access,capabilities,zone,zones,token.logoUri',
615
606
  limit: '10',
616
607
  })
617
608
 
@@ -619,37 +610,37 @@ describe('schema.getEarnVaults.Query', () => {
619
610
  expect(query['engine.type']).toBe('erc4626')
620
611
  expect(query.include).toStrictEqual([
621
612
  'access',
622
- 'apy',
623
613
  'capabilities',
624
614
  'zone',
625
615
  'zones',
626
616
  'token.logoUri',
627
- 'tvl',
628
617
  ])
629
618
  expect(query.limit).toBe(10)
630
619
  })
631
620
 
632
621
  test('defaults the page size', () => {
633
- expect(Earn.schema.getEarnVaults.Query.parse({}).limit).toBe(10)
622
+ expect(Earn.schema.VaultCollectionQuery.parse({}).limit).toBe(10)
634
623
  })
635
624
 
636
625
  test('rejects obsolete and detail-only parameters', () => {
637
- expect(() => Earn.schema.getEarnVaults.Query.parse({ 'engine.kind': 'erc4626' })).toThrow()
638
- expect(() => Earn.schema.getEarnVaults.Query.parse({ status: 'live-demo' })).toThrow()
626
+ expect(() => Earn.schema.VaultCollectionQuery.parse({ 'engine.kind': 'erc4626' })).toThrow()
627
+ expect(() => Earn.schema.VaultCollectionQuery.parse({ status: 'live-demo' })).toThrow()
639
628
  expect(() =>
640
629
  Earn.schema.getEarnVault.Query.parse({
641
630
  gateway: '0x0000000000000000000000000000000000000001',
642
631
  }),
643
632
  ).toThrow()
644
633
  })
634
+ })
645
635
 
646
- test('accepts every selectable rate window across every vault read', () => {
636
+ describe('schema.getEarnVault.Query', () => {
637
+ test('accepts every selectable rate window', () => {
647
638
  expect([
648
639
  // An omitted window stays absent, so no rate is measured.
649
- Earn.schema.getEarnVaults.Query.parse({})['apy.window'],
650
- Earn.schema.getEarnVaults.Query.parse({ 'apy.window': '1h' })['apy.window'],
651
- Earn.schema.getEarnVaults.Query.parse({ 'apy.window': '1d' })['apy.window'],
652
- Earn.schema.getVerifiedEarnVaults.Query.parse({ 'apy.window': '7d' })['apy.window'],
640
+ Earn.schema.getEarnVault.Query.parse({})['apy.window'],
641
+ Earn.schema.getEarnVault.Query.parse({ 'apy.window': '1h' })['apy.window'],
642
+ Earn.schema.getEarnVault.Query.parse({ 'apy.window': '1d' })['apy.window'],
643
+ Earn.schema.getEarnVault.Query.parse({ 'apy.window': '7d' })['apy.window'],
653
644
  Earn.schema.getEarnVault.Query.parse({ 'apy.window': '30d' })['apy.window'],
654
645
  ]).toStrictEqual([undefined, '1h', '1d', '7d', '30d'])
655
646
  })
@@ -1407,249 +1398,18 @@ describe('discoveryBatchLimit', () => {
1407
1398
  })
1408
1399
  })
1409
1400
 
1410
- describe('GET /v1/earn/vaults/verified', () => {
1411
- test('registers the static verified path before the vault path', async () => {
1401
+ describe('vault lists', () => {
1402
+ test('are not served', async () => {
1412
1403
  const app = TestApp.create({ auth: false, cache })
1413
- const response = await app.request('/v1/earn/vaults/verified')
1404
+ const [all, verified] = await Promise.all([
1405
+ app.request('/v1/earn/vaults'),
1406
+ app.request('/v1/earn/vaults/verified'),
1407
+ ])
1414
1408
 
1415
- expect(response.status).toBe(200)
1416
- expect(await TestApp.json(response, Earn.schema.getVerifiedEarnVaults.Response)).toStrictEqual({
1417
- data: [],
1418
- nextCursor: null,
1419
- })
1409
+ expect(all.status).toBe(404)
1410
+ expect(verified.status).toBe(400)
1411
+ expect((await TestApp.json(verified, Schema.ErrorResponse)).error.code).toBe('vault_id_invalid')
1420
1412
  })
1421
-
1422
- test.runIf(Runtime.get().mode === 'testnet')(
1423
- 'returns null for an inaccessible legacy Zone route',
1424
- async () => {
1425
- const db = TestApp.database()
1426
- await core_EarnVaults.upsert(db, {
1427
- ...TestEarn.zoneVerifiedVault,
1428
- privateInputTokens: [TestEarn.assetTokenAddress],
1429
- privateOutputTokens: [TestEarn.assetTokenAddress],
1430
- zones: [],
1431
- })
1432
- const zone = {
1433
- ...TestEarn.zone,
1434
- contracts: {
1435
- ...TestEarn.zone.contracts,
1436
- earnRouter: { address: TestEarn.zoneRoute.earnRouter },
1437
- },
1438
- }
1439
- const app = TestApp.create({ auth: false, cache, db, zones: [zone] })
1440
- const query = `chainId=${TestEarn.chain.id}&include=zone`
1441
- const [detail, list] = await Promise.all([
1442
- app.request(`/v1/earn/vaults/${TestEarn.zoneVaultAddress}?${query}`),
1443
- app.request(`/v1/earn/vaults/verified?${query}`),
1444
- ])
1445
-
1446
- expect([detail.status, list.status]).toStrictEqual([200, 200])
1447
- expect((await TestApp.json(detail, Earn.schema.getEarnVault.Response)).zone).toBeNull()
1448
- expect(
1449
- (await TestApp.json(list, Earn.schema.getVerifiedEarnVaults.Response)).data[0]?.zone,
1450
- ).toBeNull()
1451
- },
1452
- 90_000,
1453
- )
1454
-
1455
- test.runIf(Runtime.get().mode === 'testnet')(
1456
- 'returns curated fields for a public-only vault',
1457
- async () => {
1458
- const db = TestApp.database()
1459
- const record = await core_EarnVaults.upsert(db, TestEarn.verifiedVault)
1460
- const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
1461
- const response = await app.request(
1462
- `/v1/earn/vaults/verified?chainId=${TestEarn.verifiedVault.chainId}&include=access,capabilities,zone&limit=5`,
1463
- )
1464
-
1465
- expect(response.status).toBe(200)
1466
- const body = await TestApp.json(response, Earn.schema.getVerifiedEarnVaults.Response)
1467
- expect(body.nextCursor).toBeNull()
1468
- expect(body.data).toHaveLength(1)
1469
- const [vault] = body.data
1470
- expect(vault).toBeDefined()
1471
- if (!vault) return
1472
- expect(vault.slug).toBe(record.slug)
1473
- expect(vault).not.toHaveProperty('gateway')
1474
- // The rate and the valuation are include-gated, and neither was requested.
1475
- expect(vault).not.toHaveProperty('apy')
1476
- expect(vault).not.toHaveProperty('tvl')
1477
- const capabilities = vault.capabilities
1478
- expect(capabilities).toBeDefined()
1479
- if (!capabilities) return
1480
- expect({
1481
- access: vault.access,
1482
- assetTokenVerified: vault.assetToken.verified,
1483
- description: vault.description,
1484
- engine: vault.engine,
1485
- id: vault.id,
1486
- label: vault.label,
1487
- privateRouting: capabilities.privateRouting,
1488
- routerSwaps: capabilities.routerSwaps,
1489
- shareTokenVerified: vault.shareToken.verified,
1490
- vaultAddress: vault.vaultAddress,
1491
- verified: vault.verified,
1492
- zone: vault.zone,
1493
- }).toMatchInlineSnapshot(`
1494
- {
1495
- "access": {
1496
- "status": "allowlisted",
1497
- },
1498
- "assetTokenVerified": false,
1499
- "description": "Bridge test PATHUSD deposited into the canonical Earn v1 stack.",
1500
- "engine": {
1501
- "address": "0xd85fc943333a6cd7c0e3391acd54fc4e572f0baf",
1502
- "type": "erc4626",
1503
- "venue": "0xa8b4f0e69cd4b0e56b676343f02acd8c3b355322",
1504
- },
1505
- "id": "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
1506
- "label": "btPATHUSD Earn",
1507
- "privateRouting": false,
1508
- "routerSwaps": false,
1509
- "shareTokenVerified": false,
1510
- "vaultAddress": "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
1511
- "verified": true,
1512
- "zone": null,
1513
- }
1514
- `)
1515
- },
1516
- 60_000,
1517
- )
1518
-
1519
- test.runIf(Runtime.get().mode === 'testnet')(
1520
- 'hides stale private fields without a configured router',
1521
- async () => {
1522
- const db = TestApp.database()
1523
- await core_EarnVaults.upsert(db, {
1524
- ...TestEarn.verifiedVault,
1525
- privateInputTokens: [TestEarn.assetTokenAddress],
1526
- privateOutputTokens: [TestEarn.assetTokenAddress],
1527
- })
1528
- const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
1529
- const response = await app.request(
1530
- `/v1/earn/vaults/verified?chainId=${TestEarn.verifiedVault.chainId}&include=access,capabilities,zone&limit=5`,
1531
- )
1532
-
1533
- expect(response.status).toBe(200)
1534
- const body = await TestApp.json(response, Earn.schema.getVerifiedEarnVaults.Response)
1535
- expect(body.data[0]).toMatchObject({
1536
- capabilities: { privateRouting: false, routerSwaps: false },
1537
- verified: true,
1538
- zone: null,
1539
- })
1540
- expect(body.data[0]).not.toHaveProperty('gateway')
1541
- },
1542
- 60_000,
1543
- )
1544
-
1545
- test.runIf(Runtime.get().mode === 'testnet')(
1546
- 'reuses live discovery across public endpoints',
1547
- async () => {
1548
- const db = TestApp.database()
1549
- await core_EarnVaults.upsert(db, TestEarn.verifiedVault)
1550
- // Its own cache: the assertion needs a cold discovery followed by a warm one.
1551
- const app = TestApp.create({
1552
- auth: false,
1553
- cache: { edge: false, store: Store.memory() },
1554
- db,
1555
- zones: [TestEarn.zone],
1556
- })
1557
- const detail = await app.request(
1558
- `/v1/earn/vaults/${TestEarn.vaultAddress}?chainId=${TestEarn.chain.id}&include=access,capabilities,zone`,
1559
- )
1560
- const verified = await app.request(
1561
- `/v1/earn/vaults/verified?chainId=${TestEarn.chain.id}&include=access,capabilities,zone&limit=5`,
1562
- )
1563
-
1564
- expect([detail.status, verified.status]).toStrictEqual([200, 200])
1565
- expect(detail.headers.get('server-timing')).toContain('earn_vault_discovery')
1566
- expect(verified.headers.get('server-timing')).not.toContain('earn_vault_discovery')
1567
- },
1568
- 60_000,
1569
- )
1570
-
1571
- test.runIf(Runtime.get().mode === 'testnet')(
1572
- 'shares live enrichment across all three vault reads',
1573
- async () => {
1574
- const db = TestApp.database()
1575
- await core_EarnVaults.upsert(db, TestEarn.verifiedVault)
1576
- const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
1577
- const cursor = Cursor.encode([
1578
- TestEarn.indexedDeployment.blockNumber,
1579
- TestEarn.indexedDeployment.logIndex,
1580
- ])
1581
- const query = `chainId=${TestEarn.chain.id}&apy.window=1h&include=tvl`
1582
- const [all, verified, detail] = await Promise.all([
1583
- app.request(`/v1/earn/vaults?${query}&cursor=${encodeURIComponent(cursor)}&limit=5`),
1584
- app.request(`/v1/earn/vaults/verified?${query}&limit=5`),
1585
- app.request(`/v1/earn/vaults/${TestEarn.vaultAddress}?${query}`),
1586
- ])
1587
-
1588
- expect([all.status, verified.status, detail.status]).toStrictEqual([200, 200, 200])
1589
- for (const response of [all, verified, detail])
1590
- expect(response.headers.get('cache-control')).toBe(
1591
- 'private, max-age=30, stale-while-revalidate=120',
1592
- )
1593
- const [allBody, verifiedBody, vault] = await Promise.all([
1594
- TestApp.json(all, Earn.schema.getEarnVaults.Response),
1595
- TestApp.json(verified, Earn.schema.getVerifiedEarnVaults.Response),
1596
- TestApp.json(detail, Earn.schema.getEarnVault.Response),
1597
- ])
1598
- const enriched = ({ apy, instantLiquidity, sharePrice, state, tvl }: EnrichedVault) => ({
1599
- apy,
1600
- instantLiquidity,
1601
- sharePrice,
1602
- state,
1603
- tvl,
1604
- })
1605
- const rows = [allBody, verifiedBody].map((body) =>
1606
- body.data.find((candidate) => candidate.id === vault.id),
1607
- )
1608
- expect(rows.every((row) => row !== undefined)).toBe(true)
1609
- // The window promotes the rate and `include` selects the valuation, so all
1610
- // three reads carry both fields.
1611
- expect(['apy' in vault, 'tvl' in vault]).toStrictEqual([true, true])
1612
- for (const row of rows) if (row) expect(enriched(row)).toStrictEqual(enriched(vault))
1613
- // Every asset on these pages is USD-denominated, so no rate was consulted.
1614
- expect([allBody.meta, verifiedBody.meta, vault.meta]).toStrictEqual([
1615
- undefined,
1616
- undefined,
1617
- undefined,
1618
- ])
1619
- },
1620
- 90_000,
1621
- )
1622
-
1623
- test.runIf(Runtime.get().mode === 'testnet')(
1624
- 'applies the verified-vault address cursor',
1625
- async () => {
1626
- const db = TestApp.database()
1627
- const vaultAddresses = [
1628
- TestEarn.vaultAddress,
1629
- TestEarn.indexedDeployment.vaultAddress,
1630
- ] as const
1631
- for (const vaultAddress of vaultAddresses)
1632
- await core_EarnVaults.upsert(db, {
1633
- chainId: TestEarn.chain.id,
1634
- description: null,
1635
- label: 'Pagination vault',
1636
- privateInputTokens: [],
1637
- privateOutputTokens: [],
1638
- vaultAddress,
1639
- zones: [],
1640
- })
1641
- const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
1642
- const cursor = Cursor.encode([TestEarn.indexedDeployment.vaultAddress])
1643
- const response = await app.request(
1644
- `/v1/earn/vaults/verified?chainId=${TestEarn.chain.id}&limit=5&cursor=${encodeURIComponent(cursor)}`,
1645
- )
1646
- expect(response.status).toBe(200)
1647
- const body = await TestApp.json(response, Earn.schema.getVerifiedEarnVaults.Response)
1648
- expect(body.data.map((vault) => vault.id)).toStrictEqual([TestEarn.vaultAddress])
1649
- expect(body.nextCursor).toBeNull()
1650
- },
1651
- 90_000,
1652
- )
1653
1413
  })
1654
1414
 
1655
1415
  describe('GET /v1/earn/addresses/:address/positions', () => {
@@ -1705,13 +1465,13 @@ describe('GET /v1/earn/addresses/:address/positions', () => {
1705
1465
  })
1706
1466
 
1707
1467
  test('rejects Zone earnings includes', async () => {
1708
- const key = {
1709
- ...TestApp.key,
1710
- id: 'key_earn_zone_positions',
1711
- scopes: ['data:read', `zone:${TestEarn.zone.id}:read`],
1712
- token: 'secret_earn_zone_positions',
1713
- } satisfies TestApp.kvStore.Key
1714
- const app = TestApp.create({ auth: { keys: [key] }, cache, zones: [TestEarn.zone] })
1468
+ const key = TestApp.zoneReader(
1469
+ { ...TestApp.key, id: 'key_earn_zone_positions', scopes: ['data:read'], token: 'secret_earn_zone_positions' }, // prettier-ignore
1470
+ [TestEarn.zone.id],
1471
+ )
1472
+ const db = TestApp.database()
1473
+ await TestApp.delegateZone(db, { chainIds: [TestEarn.zone.id] })
1474
+ const app = TestApp.create({ auth: { keys: [key] }, cache, db, zones: [TestEarn.zone] })
1715
1475
  const response = await app.request(
1716
1476
  `/v1/earn/addresses/${TestEarn.positionAddress}/positions?chainId=${TestEarn.zone.id}&include=earnings`,
1717
1477
  { headers: { 'tempo-api-key': key.token } },
@@ -1873,6 +1633,116 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
1873
1633
  expect((await TestApp.json(response, Schema.ErrorResponse)).error.code).toBe('vault_id_invalid')
1874
1634
  })
1875
1635
 
1636
+ test.runIf(Runtime.get().mode === 'testnet')(
1637
+ 'returns null for an inaccessible legacy Zone route',
1638
+ async () => {
1639
+ const db = TestApp.database()
1640
+ await core_EarnVaults.upsert(db, {
1641
+ ...TestEarn.zoneVerifiedVault,
1642
+ privateInputTokens: [TestEarn.assetTokenAddress],
1643
+ privateOutputTokens: [TestEarn.assetTokenAddress],
1644
+ zones: [],
1645
+ })
1646
+ const zone = {
1647
+ ...TestEarn.zone,
1648
+ contracts: {
1649
+ ...TestEarn.zone.contracts,
1650
+ earnRouter: { address: TestEarn.zoneRoute.earnRouter },
1651
+ },
1652
+ }
1653
+ const app = TestApp.create({ auth: false, cache, db, zones: [zone] })
1654
+ const query = `chainId=${TestEarn.chain.id}&include=zone`
1655
+ const response = await app.request(`/v1/earn/vaults/${TestEarn.zoneVaultAddress}?${query}`)
1656
+
1657
+ expect(response.status).toBe(200)
1658
+ expect((await TestApp.json(response, Earn.schema.getEarnVault.Response)).zone).toBeNull()
1659
+ },
1660
+ 90_000,
1661
+ )
1662
+
1663
+ test.runIf(Runtime.get().mode === 'testnet')(
1664
+ 'returns a public-only verified vault without its curated branding',
1665
+ async () => {
1666
+ const db = TestApp.database()
1667
+ await core_EarnVaults.upsert(db, TestEarn.verifiedVault)
1668
+ const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
1669
+ const response = await app.request(
1670
+ `/v1/earn/vaults/${TestEarn.verifiedVault.vaultAddress}?chainId=${TestEarn.verifiedVault.chainId}&include=access,capabilities,zone`,
1671
+ )
1672
+
1673
+ expect(response.status).toBe(200)
1674
+ const vault = await TestApp.json(response, Earn.schema.getEarnVault.Response)
1675
+ // Registry labels name customers, so only the admin app serves them. `label` stays
1676
+ // present but empty because existing clients require it.
1677
+ for (const field of ['description', 'slug']) expect(vault).not.toHaveProperty(field)
1678
+ expect(vault.label).toBe('')
1679
+ expect(vault).not.toHaveProperty('gateway')
1680
+ // The rate and the valuation are include-gated, and neither was requested.
1681
+ expect(vault).not.toHaveProperty('apy')
1682
+ expect(vault).not.toHaveProperty('tvl')
1683
+ const capabilities = vault.capabilities
1684
+ expect(capabilities).toBeDefined()
1685
+ if (!capabilities) return
1686
+ expect({
1687
+ access: vault.access,
1688
+ assetTokenVerified: vault.assetToken.verified,
1689
+ engine: vault.engine,
1690
+ id: vault.id,
1691
+ privateRouting: capabilities.privateRouting,
1692
+ routerSwaps: capabilities.routerSwaps,
1693
+ shareTokenVerified: vault.shareToken.verified,
1694
+ vaultAddress: vault.vaultAddress,
1695
+ verified: vault.verified,
1696
+ zone: vault.zone,
1697
+ }).toMatchInlineSnapshot(`
1698
+ {
1699
+ "access": {
1700
+ "status": "allowlisted",
1701
+ },
1702
+ "assetTokenVerified": false,
1703
+ "engine": {
1704
+ "address": "0xd85fc943333a6cd7c0e3391acd54fc4e572f0baf",
1705
+ "type": "erc4626",
1706
+ "venue": "0xa8b4f0e69cd4b0e56b676343f02acd8c3b355322",
1707
+ },
1708
+ "id": "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
1709
+ "privateRouting": false,
1710
+ "routerSwaps": false,
1711
+ "shareTokenVerified": false,
1712
+ "vaultAddress": "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
1713
+ "verified": true,
1714
+ "zone": null,
1715
+ }
1716
+ `)
1717
+ },
1718
+ 60_000,
1719
+ )
1720
+
1721
+ test.runIf(Runtime.get().mode === 'testnet')(
1722
+ 'hides stale private fields without a configured router',
1723
+ async () => {
1724
+ const db = TestApp.database()
1725
+ await core_EarnVaults.upsert(db, {
1726
+ ...TestEarn.verifiedVault,
1727
+ privateInputTokens: [TestEarn.assetTokenAddress],
1728
+ privateOutputTokens: [TestEarn.assetTokenAddress],
1729
+ })
1730
+ const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
1731
+ const response = await app.request(
1732
+ `/v1/earn/vaults/${TestEarn.verifiedVault.vaultAddress}?chainId=${TestEarn.verifiedVault.chainId}&include=access,capabilities,zone`,
1733
+ )
1734
+
1735
+ expect(response.status).toBe(200)
1736
+ const vault = await TestApp.json(response, Earn.schema.getEarnVault.Response)
1737
+ expect(vault).toMatchObject({
1738
+ capabilities: { privateRouting: false, routerSwaps: false },
1739
+ verified: true,
1740
+ zone: null,
1741
+ })
1742
+ expect(vault).not.toHaveProperty('gateway')
1743
+ },
1744
+ 60_000,
1745
+ )
1876
1746
  test.runIf(Runtime.get().mode === 'testnet')(
1877
1747
  'resolves an unregistered vault directly from chain state',
1878
1748
  async () => {
@@ -1892,11 +1762,8 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
1892
1762
  const included = await TestApp.json(includedResponse, Earn.schema.getEarnVault.Response)
1893
1763
  expect({
1894
1764
  access: included.access,
1895
- description: included.description,
1896
1765
  engineType: included.engine.type,
1897
1766
  id: included.id,
1898
- label: included.label,
1899
- slug: included.slug,
1900
1767
  vaultAddress: included.vaultAddress,
1901
1768
  verified: included.verified,
1902
1769
  zone: included.zone,
@@ -1905,11 +1772,8 @@ describe('GET /v1/earn/vaults/:vaultId', () => {
1905
1772
  "access": {
1906
1773
  "status": "allowlisted",
1907
1774
  },
1908
- "description": null,
1909
1775
  "engineType": "erc4626",
1910
1776
  "id": "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
1911
- "label": "Tempo Earn Live Vault (Earn)",
1912
- "slug": null,
1913
1777
  "vaultAddress": "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
1914
1778
  "verified": false,
1915
1779
  "zone": null,
@@ -2474,12 +2338,10 @@ describe('GET /v1/earn/vaults/:vaultId/share-prices', () => {
2474
2338
  })
2475
2339
 
2476
2340
  describe('GET /v1/earn/vaults/:vaultId/positions/:address', () => {
2477
- const zoneKey = {
2478
- ...TestApp.key,
2479
- id: 'key_earn_zone_vault_position',
2480
- scopes: ['data:read', `zone:${TestEarn.zone.id}:read`],
2481
- token: 'secret_earn_zone_vault_position',
2482
- } satisfies TestApp.kvStore.Key
2341
+ const zoneKey = TestApp.zoneReader(
2342
+ { ...TestApp.key, id: 'key_earn_zone_vault_position', scopes: ['data:read'], token: 'secret_earn_zone_vault_position' }, // prettier-ignore
2343
+ [TestEarn.zone.id],
2344
+ )
2483
2345
 
2484
2346
  test('accepts and validates the wallet APY include', () => {
2485
2347
  expect(Earn.schema.getEarnVaultPosition.Query.safeParse({ include: ['apy'] }).success).toBe(
@@ -2533,9 +2395,12 @@ describe('GET /v1/earn/vaults/:vaultId/positions/:address', () => {
2533
2395
  test.runIf(Runtime.get().mode === 'testnet')(
2534
2396
  'returns not found for an incompatible public parent vault selected through a Zone',
2535
2397
  async () => {
2398
+ const db = TestApp.database()
2399
+ await TestApp.delegateZone(db, { chainIds: [TestEarn.zone.id] })
2536
2400
  const response = await TestApp.create({
2537
2401
  auth: { keys: [zoneKey] },
2538
2402
  cache,
2403
+ db,
2539
2404
  zones: [TestEarn.zone],
2540
2405
  }).request(
2541
2406
  `/v1/earn/vaults/${TestEarn.assetTokenAddress}/positions/${TestEarn.positionAddress}?chainId=${TestEarn.zone.id}`,
@@ -3390,168 +3255,6 @@ describe('GET /v1/earn/vaults/:vaultId/earnings/:address', () => {
3390
3255
  )
3391
3256
  })
3392
3257
 
3393
- describe('GET /v1/earn/vaults', () => {
3394
- test.runIf(Runtime.get().mode === 'testnet')(
3395
- 'extracts an indexed deployment and applies onchain filters',
3396
- async () => {
3397
- const db = TestApp.database()
3398
- const record = await core_EarnVaults.upsert(db, TestEarn.indexedVerifiedVault)
3399
- const app = TestApp.create({ auth: false, cache, db, zones: [TestEarn.zone] })
3400
- const query = new URLSearchParams({
3401
- asset: TestEarn.assetTokenAddress,
3402
- capability: 'deposit,exactWithdraw',
3403
- chainId: String(TestEarn.chain.id),
3404
- cursor: Cursor.encode([
3405
- TestEarn.indexedDeployment.blockNumber,
3406
- TestEarn.indexedDeployment.logIndex + 1,
3407
- ]),
3408
- 'engine.type': 'erc4626',
3409
- limit: '5',
3410
- })
3411
- const response = await app.request(`/v1/earn/vaults?${query}`)
3412
-
3413
- expect(response.status).toBe(200)
3414
- const timing = response.headers.get('server-timing') ?? ''
3415
- expect(timing).not.toContain('token_metadata')
3416
- expect(timing).not.toContain('token_logo')
3417
- // Neither the rate measurement nor the FX rate set is reached on a page
3418
- // that asked for neither.
3419
- expect(timing).not.toContain('earn_apy')
3420
- expect(timing).not.toContain('valuation_rates')
3421
- const body = await TestApp.json(response, Earn.schema.getEarnVaults.Response)
3422
- const vault = body.data.find(
3423
- (candidate) => candidate.vaultAddress === TestEarn.indexedDeployment.vaultAddress,
3424
- )
3425
- expect(vault).toBeDefined()
3426
- if (!vault) return
3427
- expect(vault.slug).toBe(record.slug)
3428
- expect(vault.assetToken).not.toHaveProperty('logoUri')
3429
- expect(vault.shareToken).not.toHaveProperty('logoUri')
3430
- expect(vault).not.toHaveProperty('gateway')
3431
- expect(vault).not.toHaveProperty('access')
3432
- expect(vault).not.toHaveProperty('apy')
3433
- expect(vault).not.toHaveProperty('capabilities')
3434
- expect(vault).not.toHaveProperty('tvl')
3435
- expect(vault).not.toHaveProperty('zone')
3436
-
3437
- query.set('include', 'access,apy,capabilities,token.logoUri,tvl,zone')
3438
- const includedResponse = await app.request(`/v1/earn/vaults?${query}`)
3439
- expect(includedResponse.status).toBe(200)
3440
- const includedTiming = includedResponse.headers.get('server-timing') ?? ''
3441
- expect(includedTiming).toContain('token_logo')
3442
- expect(includedTiming).toContain('earn_apy')
3443
- expect(includedTiming).toContain('valuation_rates')
3444
- const includedBody = await TestApp.json(includedResponse, Earn.schema.getEarnVaults.Response)
3445
- const included = includedBody.data.find(
3446
- (candidate) => candidate.vaultAddress === TestEarn.indexedDeployment.vaultAddress,
3447
- )
3448
- expect(included).toBeDefined()
3449
- if (!included) return
3450
- expect(['apy' in included, 'tvl' in included]).toStrictEqual([true, true])
3451
- expect({
3452
- access: included.access,
3453
- assetToken: {
3454
- address: included.assetToken.address,
3455
- decimals: included.assetToken.decimals,
3456
- name: included.assetToken.name,
3457
- symbol: included.assetToken.symbol,
3458
- },
3459
- capabilities: included.capabilities,
3460
- description: included.description,
3461
- engine: included.engine,
3462
- id: included.id,
3463
- label: included.label,
3464
- shareToken: {
3465
- address: included.shareToken.address,
3466
- decimals: included.shareToken.decimals,
3467
- name: included.shareToken.name,
3468
- symbol: included.shareToken.symbol,
3469
- },
3470
- vaultAddress: included.vaultAddress,
3471
- verified: included.verified,
3472
- }).toMatchInlineSnapshot(`
3473
- {
3474
- "access": {
3475
- "status": "allowlisted",
3476
- },
3477
- "assetToken": {
3478
- "address": "0x20c000000000000000000000ff04042ee92fd449",
3479
- "decimals": 6,
3480
- "name": "Bridge Test PATHUSD",
3481
- "symbol": "btPATHUSD",
3482
- },
3483
- "capabilities": {
3484
- "asyncRedeem": false,
3485
- "boundedRedeem": true,
3486
- "deposit": true,
3487
- "exactWithdraw": true,
3488
- "inKindDeposit": true,
3489
- "privateRouting": false,
3490
- "redeem": true,
3491
- "routerSwaps": false,
3492
- },
3493
- "description": "Indexed Bridge Test PATHUSD Earn deployment.",
3494
- "engine": {
3495
- "address": "0x3bba4aa05eee3c6e568e0e60185a4eb630927928",
3496
- "type": "erc4626",
3497
- "venue": "0xa8b4f0e69cd4b0e56b676343f02acd8c3b355322",
3498
- },
3499
- "id": "0xd4a673d20aeac2773d340ed595c497d460663ca2",
3500
- "label": "Indexed btPATHUSD Earn",
3501
- "shareToken": {
3502
- "address": "0x20c0000000000000000000006ee48bc223de1c5b",
3503
- "decimals": 6,
3504
- "name": "Tempo Earn Live Vault (Earn)",
3505
- "symbol": "teLIVEE",
3506
- },
3507
- "vaultAddress": "0xd4a673d20aeac2773d340ed595c497d460663ca2",
3508
- "verified": true,
3509
- }
3510
- `)
3511
- },
3512
- 60_000,
3513
- )
3514
-
3515
- test.runIf(Runtime.get().mode === 'testnet')(
3516
- 'traverses live indexed deployments from an opaque cursor',
3517
- async () => {
3518
- const app = TestApp.create({ auth: false, cache, zones: [TestEarn.zone] })
3519
- const cursor = Cursor.encode([
3520
- TestEarn.indexedDeployment.blockNumber,
3521
- TestEarn.indexedDeployment.logIndex,
3522
- ])
3523
- const response = await app.request(
3524
- `/v1/earn/vaults?chainId=${TestEarn.chain.id}&cursor=${encodeURIComponent(cursor)}&limit=5`,
3525
- )
3526
-
3527
- expect(response.status).toBe(200)
3528
- const body = await TestApp.json(response, Earn.schema.getEarnVaults.Response)
3529
- expect({
3530
- ids: body.data.map((vault) => vault.id),
3531
- nextCursor: body.nextCursor,
3532
- valid: body.data.every(
3533
- (vault) =>
3534
- vault.vaultAddress === vault.id &&
3535
- vault.assetToken.address.startsWith('0x20c0') &&
3536
- vault.engine.address.startsWith('0x') &&
3537
- vault.shareToken.address.startsWith('0x20c0') &&
3538
- vault.slug === null &&
3539
- !vault.verified,
3540
- ),
3541
- }).toMatchInlineSnapshot(`
3542
- {
3543
- "ids": [
3544
- "0xf4ae63687d6753a78e7f551d2eda1d0d31a5ea3a",
3545
- ],
3546
- "nextCursor": null,
3547
- "valid": true,
3548
- }
3549
- `)
3550
- },
3551
- 90_000,
3552
- )
3553
- })
3554
-
3555
3258
  describe('OpenAPI', () => {
3556
3259
  test('publishes stable Earn components', async () => {
3557
3260
  const app = TestApp.create({ auth: false, cache })
@@ -3589,14 +3292,6 @@ describe('OpenAPI', () => {
3589
3292
  "/v1/earn/vaults/{vaultId}/share-prices",
3590
3293
  "#/components/schemas/EarnVaultSharePriceList",
3591
3294
  ],
3592
- "getEarnVaults": [
3593
- "/v1/earn/vaults",
3594
- "#/components/schemas/EarnVaultList",
3595
- ],
3596
- "getVerifiedEarnVaults": [
3597
- "/v1/earn/vaults/verified",
3598
- "#/components/schemas/VerifiedEarnVaultList",
3599
- ],
3600
3295
  }
3601
3296
  `)
3602
3297
  expect(
@@ -3604,23 +3299,21 @@ describe('OpenAPI', () => {
3604
3299
  .filter((name) => name.startsWith('Earn') && !name.endsWith('Error'))
3605
3300
  .sort(),
3606
3301
  ).toMatchInlineSnapshot(`
3607
- [
3608
- "EarnAddressPosition",
3609
- "EarnAddressPositionList",
3610
- "EarnTransaction",
3611
- "EarnVault",
3612
- "EarnVaultDetail",
3613
- "EarnVaultEarnings",
3614
- "EarnVaultEngine",
3615
- "EarnVaultList",
3616
- "EarnVaultPosition",
3617
- "EarnVaultSharePriceList",
3618
- "EarnVaultZone",
3619
- "EarnVaultZoneRoute",
3620
- ]
3621
- `)
3622
- expect(spec.components?.schemas).toHaveProperty('VerifiedEarnVault')
3623
- expect(spec.components?.schemas).toHaveProperty('VerifiedEarnVaultList')
3302
+ [
3303
+ "EarnAddressPosition",
3304
+ "EarnAddressPositionList",
3305
+ "EarnTransaction",
3306
+ "EarnVaultDetail",
3307
+ "EarnVaultEarnings",
3308
+ "EarnVaultEngine",
3309
+ "EarnVaultPosition",
3310
+ "EarnVaultSharePriceList",
3311
+ "EarnVaultZone",
3312
+ "EarnVaultZoneRoute",
3313
+ ]
3314
+ `)
3315
+ expect(spec.paths).not.toHaveProperty('/v1/earn/vaults')
3316
+ expect(spec.paths).not.toHaveProperty('/v1/earn/vaults/verified')
3624
3317
  expect(JSON.stringify(spec.components?.schemas?.['EarnAddressPosition'])).toContain(
3625
3318
  'An account’s position in one earn vault.',
3626
3319
  )
@@ -3629,17 +3322,9 @@ describe('OpenAPI', () => {
3629
3322
  spec.paths['/v1/earn/vaults/{vaultId}']?.get?.responses?.['400']?.content?.[
3630
3323
  'application/json'
3631
3324
  ]?.schema?.$ref,
3632
- list: spec.paths['/v1/earn/vaults']?.get?.responses?.['400']?.content?.['application/json']
3633
- ?.schema?.$ref,
3634
- verified:
3635
- spec.paths['/v1/earn/vaults/verified']?.get?.responses?.['400']?.content?.[
3636
- 'application/json'
3637
- ]?.schema?.$ref,
3638
3325
  }).toMatchInlineSnapshot(`
3639
3326
  {
3640
3327
  "detail": "#/components/schemas/ApiKeyMalformedOrChainIdInvalidOrChainIdUnsupportedOrQueryInvalidOrVaultIdInvalidError",
3641
- "list": "#/components/schemas/ApiKeyMalformedOrChainIdInvalidOrChainIdUnsupportedOrQueryInvalidError",
3642
- "verified": "#/components/schemas/ApiKeyMalformedOrChainIdInvalidOrChainIdUnsupportedOrQueryInvalidError",
3643
3328
  }
3644
3329
  `)
3645
3330
  })
@@ -3647,15 +3332,13 @@ describe('OpenAPI', () => {
3647
3332
  test('publishes the flattened vault shape', async () => {
3648
3333
  const app = TestApp.create({ auth: false, cache })
3649
3334
  const spec = (await (await app.request('/openapi.json')).json()) as OpenApiDocument
3650
- const operation = spec.paths['/v1/earn/vaults']?.get
3335
+ const operation = spec.paths['/v1/earn/vaults/{vaultId}']?.get
3651
3336
  const parameters = operation?.parameters?.map((parameter) => parameter.name)
3652
3337
  const response = JSON.stringify(resolveSchema(spec, successSchema(operation)))
3653
3338
 
3654
3339
  expect(Object.keys(spec.paths)).toEqual(
3655
3340
  expect.arrayContaining([
3656
3341
  '/v1/earn/addresses/{address}/positions',
3657
- '/v1/earn/vaults',
3658
- '/v1/earn/vaults/verified',
3659
3342
  '/v1/earn/vaults/{vaultId}',
3660
3343
  '/v1/earn/vaults/{vaultId}/earnings/{address}',
3661
3344
  '/v1/earn/vaults/{vaultId}/positions/{address}',
@@ -3663,7 +3346,6 @@ describe('OpenAPI', () => {
3663
3346
  ]),
3664
3347
  )
3665
3348
  expect(parameters).toContain('apy.window')
3666
- expect(parameters).toContain('engine.type')
3667
3349
  expect(parameters).toContain('include')
3668
3350
  expect(parameters).not.toContain('engine.kind')
3669
3351
  expect(parameters).not.toContain('status')
@@ -3689,7 +3371,7 @@ describe('OpenAPI', () => {
3689
3371
  test('documents the rate window parameter', async () => {
3690
3372
  const app = TestApp.create({ auth: false, cache })
3691
3373
  const spec = (await (await app.request('/openapi.json')).json()) as OpenApiDocument
3692
- const window = spec.paths['/v1/earn/vaults']?.get?.parameters?.find(
3374
+ const window = spec.paths['/v1/earn/vaults/{vaultId}']?.get?.parameters?.find(
3693
3375
  (parameter) => parameter.name === 'apy.window',
3694
3376
  )
3695
3377
 
@@ -3701,7 +3383,7 @@ describe('OpenAPI', () => {
3701
3383
  test('documents the include-gated vault fields', async () => {
3702
3384
  const app = TestApp.create({ auth: false, cache })
3703
3385
  const spec = (await (await app.request('/openapi.json')).json()) as OpenApiDocument
3704
- const parameters = spec.paths['/v1/earn/vaults']?.get?.parameters ?? []
3386
+ const parameters = spec.paths['/v1/earn/vaults/{vaultId}']?.get?.parameters ?? []
3705
3387
  const include = parameters.find((parameter) => parameter.name === 'include')
3706
3388
 
3707
3389
  expect(include?.description).toContain('`apy,tvl`')