tapimo 0.15.1 → 0.18.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 (709) hide show
  1. package/README.md +137 -0
  2. package/dist/ApiKey.d.ts +1 -0
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +4 -2
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +37 -11
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +163 -10
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +13085 -11974
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +46 -15
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +1 -1
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +1 -1
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/admin/App.d.ts +893 -191
  19. package/dist/admin/App.d.ts.map +1 -1
  20. package/dist/admin/App.js +5 -1
  21. package/dist/admin/App.js.map +1 -1
  22. package/dist/admin/apps/api-keys.d.ts +70 -70
  23. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.js +8 -3
  25. package/dist/admin/apps/api-keys.js.map +1 -1
  26. package/dist/admin/apps/earn-vaults.d.ts +66 -27
  27. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  28. package/dist/admin/apps/earn-vaults.js +36 -7
  29. package/dist/admin/apps/earn-vaults.js.map +1 -1
  30. package/dist/admin/apps/organizations.d.ts +25 -25
  31. package/dist/admin/apps/organizations.d.ts.map +1 -1
  32. package/dist/admin/apps/organizations.js +5 -4
  33. package/dist/admin/apps/organizations.js.map +1 -1
  34. package/dist/admin/apps/route-policies.d.ts +632 -0
  35. package/dist/admin/apps/route-policies.d.ts.map +1 -0
  36. package/dist/admin/apps/route-policies.js +257 -0
  37. package/dist/admin/apps/route-policies.js.map +1 -0
  38. package/dist/admin/apps/routes-support.js +39 -3
  39. package/dist/admin/apps/routes-support.js.map +1 -1
  40. package/dist/admin/apps/routes.d.ts +529 -76
  41. package/dist/admin/apps/routes.d.ts.map +1 -1
  42. package/dist/admin/apps/routes.js +82 -1
  43. package/dist/admin/apps/routes.js.map +1 -1
  44. package/dist/admin/apps/verified-tokens.d.ts +157 -157
  45. package/dist/admin/index.d.ts +0 -1
  46. package/dist/admin/index.d.ts.map +1 -1
  47. package/dist/admin/index.js +0 -1
  48. package/dist/admin/index.js.map +1 -1
  49. package/dist/admin/ui.generated.d.ts +1 -1
  50. package/dist/admin/ui.generated.d.ts.map +1 -1
  51. package/dist/admin/ui.generated.js +205 -201
  52. package/dist/admin/ui.generated.js.map +1 -1
  53. package/dist/analytics/Analytics.d.ts.map +1 -1
  54. package/dist/analytics/Analytics.js +65 -1
  55. package/dist/analytics/Analytics.js.map +1 -1
  56. package/dist/analytics/tables/requestEvents.d.ts +1 -1
  57. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  58. package/dist/analytics/tables/requestEvents.js +58 -59
  59. package/dist/analytics/tables/requestEvents.js.map +1 -1
  60. package/dist/apps/data/App.d.ts +2709 -2670
  61. package/dist/apps/data/App.d.ts.map +1 -1
  62. package/dist/apps/data/routes/activities.d.ts +357 -357
  63. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  64. package/dist/apps/data/routes/activities.js +50 -0
  65. package/dist/apps/data/routes/activities.js.map +1 -1
  66. package/dist/apps/data/routes/addresses.d.ts +248 -248
  67. package/dist/apps/data/routes/balances.d.ts +22 -22
  68. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  69. package/dist/apps/data/routes/balances.js +5 -7
  70. package/dist/apps/data/routes/balances.js.map +1 -1
  71. package/dist/apps/data/routes/blocks.d.ts +125 -125
  72. package/dist/apps/data/routes/coingecko.d.ts +54 -54
  73. package/dist/apps/data/routes/earn.d.ts +103 -12
  74. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  75. package/dist/apps/data/routes/earn.js +456 -220
  76. package/dist/apps/data/routes/earn.js.map +1 -1
  77. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  78. package/dist/apps/data/routes/exchanges.js +267 -97
  79. package/dist/apps/data/routes/exchanges.js.map +1 -1
  80. package/dist/apps/data/routes/fee-amm.d.ts +109 -127
  81. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  82. package/dist/apps/data/routes/fee-amm.js +83 -54
  83. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  84. package/dist/apps/data/routes/indexer.d.ts +43 -43
  85. package/dist/apps/data/routes/receipts.d.ts +235 -235
  86. package/dist/apps/data/routes/rpc.d.ts +30 -30
  87. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  88. package/dist/apps/data/routes/tokens.js +11 -6
  89. package/dist/apps/data/routes/tokens.js.map +1 -1
  90. package/dist/apps/data/routes/transactions.d.ts +2 -0
  91. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  92. package/dist/apps/data/routes/transactions.js +30 -22
  93. package/dist/apps/data/routes/transactions.js.map +1 -1
  94. package/dist/apps/data/routes/transfers.d.ts +77 -77
  95. package/dist/apps/data/routes/valuation.d.ts +32 -32
  96. package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
  97. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  98. package/dist/apps/data/routes/webhooks.js +1 -1
  99. package/dist/apps/data/routes/webhooks.js.map +1 -1
  100. package/dist/apps/data/routes/zones.d.ts +31 -31
  101. package/dist/apps/management/App.d.ts +2909 -2064
  102. package/dist/apps/management/App.d.ts.map +1 -1
  103. package/dist/apps/management/App.js +2 -0
  104. package/dist/apps/management/App.js.map +1 -1
  105. package/dist/apps/management/Billing.d.ts +2 -4
  106. package/dist/apps/management/Billing.d.ts.map +1 -1
  107. package/dist/apps/management/Billing.js +65 -26
  108. package/dist/apps/management/Billing.js.map +1 -1
  109. package/dist/apps/management/routes/api-keys.d.ts +257 -245
  110. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  111. package/dist/apps/management/routes/api-keys.js +70 -11
  112. package/dist/apps/management/routes/api-keys.js.map +1 -1
  113. package/dist/apps/management/routes/billing.d.ts +84 -84
  114. package/dist/apps/management/routes/cli.d.ts +912 -0
  115. package/dist/apps/management/routes/cli.d.ts.map +1 -0
  116. package/dist/apps/management/routes/cli.js +416 -0
  117. package/dist/apps/management/routes/cli.js.map +1 -0
  118. package/dist/apps/management/routes/faucet.d.ts +8 -8
  119. package/dist/apps/management/routes/invitations.d.ts +138 -138
  120. package/dist/apps/management/routes/invite-links.d.ts +172 -172
  121. package/dist/apps/management/routes/members.d.ts +16 -16
  122. package/dist/apps/management/routes/orgs.d.ts +104 -104
  123. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  124. package/dist/apps/management/routes/orgs.js +8 -2
  125. package/dist/apps/management/routes/orgs.js.map +1 -1
  126. package/dist/apps/management/routes/projects.d.ts +125 -125
  127. package/dist/apps/management/routes/usage.d.ts +8 -8
  128. package/dist/apps/management/routes/verified-token-requests.d.ts +86 -86
  129. package/dist/apps/management/routes/webhooks.d.ts +485 -485
  130. package/dist/apps/mpp/App.d.ts +44 -44
  131. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
  132. package/dist/apps/mpp/internal/Policy.js +4 -2
  133. package/dist/apps/mpp/internal/Policy.js.map +1 -1
  134. package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
  135. package/dist/apps/mpp/internal/Sponsorship.js +6 -4
  136. package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
  137. package/dist/apps/relay/App.d.ts +8 -0
  138. package/dist/apps/relay/App.d.ts.map +1 -1
  139. package/dist/apps/relay/App.js +16 -4
  140. package/dist/apps/relay/App.js.map +1 -1
  141. package/dist/apps/relay/Sponsorships.d.ts +4 -6
  142. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  143. package/dist/apps/relay/Sponsorships.js +71 -60
  144. package/dist/apps/relay/Sponsorships.js.map +1 -1
  145. package/dist/apps/routes/Access.d.ts +53 -0
  146. package/dist/apps/routes/Access.d.ts.map +1 -1
  147. package/dist/apps/routes/Access.js +121 -0
  148. package/dist/apps/routes/Access.js.map +1 -1
  149. package/dist/apps/routes/App.d.ts +397 -158
  150. package/dist/apps/routes/App.d.ts.map +1 -1
  151. package/dist/apps/routes/App.js.map +1 -1
  152. package/dist/apps/routes/routes/chains.d.ts +25 -25
  153. package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
  154. package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
  155. package/dist/apps/routes/routes/deposit-addresses.js +217 -32
  156. package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
  157. package/dist/apps/routes/routes/quotes.d.ts +171 -81
  158. package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
  159. package/dist/apps/routes/routes/quotes.js +101 -27
  160. package/dist/apps/routes/routes/quotes.js.map +1 -1
  161. package/dist/apps/routes/routes/transfers.d.ts +532 -480
  162. package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
  163. package/dist/apps/routes/routes/transfers.js +182 -37
  164. package/dist/apps/routes/routes/transfers.js.map +1 -1
  165. package/dist/cli/ApiKeys.d.ts +120 -0
  166. package/dist/cli/ApiKeys.d.ts.map +1 -0
  167. package/dist/cli/ApiKeys.js +138 -0
  168. package/dist/cli/ApiKeys.js.map +1 -0
  169. package/dist/cli/Cli.d.ts +92 -34
  170. package/dist/cli/Cli.d.ts.map +1 -1
  171. package/dist/cli/Cli.js +188 -11
  172. package/dist/cli/Cli.js.map +1 -1
  173. package/dist/cli/Credentials.d.ts +95 -0
  174. package/dist/cli/Credentials.d.ts.map +1 -0
  175. package/dist/cli/Credentials.js +110 -0
  176. package/dist/cli/Credentials.js.map +1 -0
  177. package/dist/cli/Spec.d.ts +59 -0
  178. package/dist/cli/Spec.d.ts.map +1 -0
  179. package/dist/cli/Spec.js +77 -0
  180. package/dist/cli/Spec.js.map +1 -0
  181. package/dist/cli/bin.js +5 -1
  182. package/dist/cli/bin.js.map +1 -1
  183. package/dist/cli/commands/admin.d.ts +5 -5
  184. package/dist/cli/commands/admin.d.ts.map +1 -1
  185. package/dist/cli/commands/auth.d.ts +73 -0
  186. package/dist/cli/commands/auth.d.ts.map +1 -0
  187. package/dist/cli/commands/auth.js +204 -0
  188. package/dist/cli/commands/auth.js.map +1 -0
  189. package/dist/cli/commands/keys.d.ts +17 -0
  190. package/dist/cli/commands/keys.d.ts.map +1 -0
  191. package/dist/cli/commands/keys.js +109 -0
  192. package/dist/cli/commands/keys.js.map +1 -0
  193. package/dist/cloudflare.d.ts +27 -2
  194. package/dist/cloudflare.d.ts.map +1 -1
  195. package/dist/cloudflare.js +144 -17
  196. package/dist/cloudflare.js.map +1 -1
  197. package/dist/db/Db.d.ts +23 -0
  198. package/dist/db/Db.d.ts.map +1 -1
  199. package/dist/db/Db.js +413 -1
  200. package/dist/db/Db.js.map +1 -1
  201. package/dist/db/Schema.d.ts +44 -1
  202. package/dist/db/Schema.d.ts.map +1 -1
  203. package/dist/db/Schema.js +56 -3
  204. package/dist/db/Schema.js.map +1 -1
  205. package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
  206. package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
  207. package/dist/db/tables/apiKeyAdmissions.js +65 -9
  208. package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
  209. package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
  210. package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
  211. package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
  212. package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
  213. package/dist/db/tables/authAccounts.d.ts.map +1 -1
  214. package/dist/db/tables/authAccounts.js +1 -0
  215. package/dist/db/tables/authAccounts.js.map +1 -1
  216. package/dist/db/tables/earnVaults.d.ts +5 -1
  217. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  218. package/dist/db/tables/earnVaults.js +12 -1
  219. package/dist/db/tables/earnVaults.js.map +1 -1
  220. package/dist/db/tables/organizations.d.ts +4 -2
  221. package/dist/db/tables/organizations.d.ts.map +1 -1
  222. package/dist/db/tables/organizations.js +8 -34
  223. package/dist/db/tables/organizations.js.map +1 -1
  224. package/dist/db/tables/requestUsage.d.ts +5 -1
  225. package/dist/db/tables/requestUsage.d.ts.map +1 -1
  226. package/dist/db/tables/requestUsage.js +10 -2
  227. package/dist/db/tables/requestUsage.js.map +1 -1
  228. package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
  229. package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
  230. package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
  231. package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
  232. package/dist/db/tables/rewardRuns.d.ts.map +1 -1
  233. package/dist/db/tables/rewardRuns.js +4 -0
  234. package/dist/db/tables/rewardRuns.js.map +1 -1
  235. package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
  236. package/dist/db/tables/rewardTransactionAttempts.js +2 -0
  237. package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
  238. package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
  239. package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
  240. package/dist/db/tables/routesDepositAddresses.js +84 -31
  241. package/dist/db/tables/routesDepositAddresses.js.map +1 -1
  242. package/dist/db/tables/routesDeposits.d.ts.map +1 -1
  243. package/dist/db/tables/routesDeposits.js +31 -21
  244. package/dist/db/tables/routesDeposits.js.map +1 -1
  245. package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
  246. package/dist/db/tables/routesIdempotency.js +2 -0
  247. package/dist/db/tables/routesIdempotency.js.map +1 -1
  248. package/dist/db/tables/routesPolicies.d.ts +58 -0
  249. package/dist/db/tables/routesPolicies.d.ts.map +1 -0
  250. package/dist/db/tables/routesPolicies.js +198 -0
  251. package/dist/db/tables/routesPolicies.js.map +1 -0
  252. package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
  253. package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
  254. package/dist/db/tables/routesTransferSubsidies.js +41 -0
  255. package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
  256. package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
  257. package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
  258. package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
  259. package/dist/db/tables/routesTransfers.d.ts +26 -1
  260. package/dist/db/tables/routesTransfers.d.ts.map +1 -1
  261. package/dist/db/tables/routesTransfers.js +36 -6
  262. package/dist/db/tables/routesTransfers.js.map +1 -1
  263. package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
  264. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  265. package/dist/db/tables/sponsoredTransactions.js +144 -33
  266. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  267. package/dist/db/tables/users.d.ts +2 -0
  268. package/dist/db/tables/users.d.ts.map +1 -1
  269. package/dist/db/tables/users.js +11 -0
  270. package/dist/db/tables/users.js.map +1 -1
  271. package/dist/handlers/internal/multisig.d.ts +1 -1
  272. package/dist/handlers/internal/multisig.d.ts.map +1 -1
  273. package/dist/handlers/internal/multisig.js +3 -2
  274. package/dist/handlers/internal/multisig.js.map +1 -1
  275. package/dist/handlers/relay.d.ts +2 -0
  276. package/dist/handlers/relay.d.ts.map +1 -1
  277. package/dist/handlers/relay.js +34 -15
  278. package/dist/handlers/relay.js.map +1 -1
  279. package/dist/internal/Auth.d.ts +57 -6
  280. package/dist/internal/Auth.d.ts.map +1 -1
  281. package/dist/internal/Auth.js +182 -78
  282. package/dist/internal/Auth.js.map +1 -1
  283. package/dist/internal/BetterAuth.d.ts +22 -0
  284. package/dist/internal/BetterAuth.d.ts.map +1 -1
  285. package/dist/internal/BetterAuth.js +17 -14
  286. package/dist/internal/BetterAuth.js.map +1 -1
  287. package/dist/internal/Cache.d.ts +5 -0
  288. package/dist/internal/Cache.d.ts.map +1 -1
  289. package/dist/internal/Cache.js +3 -1
  290. package/dist/internal/Cache.js.map +1 -1
  291. package/dist/internal/CliAuth.d.ts +243 -0
  292. package/dist/internal/CliAuth.d.ts.map +1 -0
  293. package/dist/internal/CliAuth.js +249 -0
  294. package/dist/internal/CliAuth.js.map +1 -0
  295. package/dist/internal/EarnSharePrices.d.ts +1 -1
  296. package/dist/internal/EarnSharePrices.d.ts.map +1 -1
  297. package/dist/internal/EarnSharePrices.js +7 -3
  298. package/dist/internal/EarnSharePrices.js.map +1 -1
  299. package/dist/internal/EarnVaults.d.ts +47 -0
  300. package/dist/internal/EarnVaults.d.ts.map +1 -1
  301. package/dist/internal/EarnVaults.js +188 -4
  302. package/dist/internal/EarnVaults.js.map +1 -1
  303. package/dist/internal/EarnWithdrawals.d.ts +73 -0
  304. package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
  305. package/dist/internal/EarnWithdrawals.js +189 -0
  306. package/dist/internal/EarnWithdrawals.js.map +1 -0
  307. package/dist/internal/ExecutionContext.d.ts +21 -0
  308. package/dist/internal/ExecutionContext.d.ts.map +1 -0
  309. package/dist/internal/ExecutionContext.js +16 -0
  310. package/dist/internal/ExecutionContext.js.map +1 -0
  311. package/dist/internal/Log.d.ts +7 -3
  312. package/dist/internal/Log.d.ts.map +1 -1
  313. package/dist/internal/Log.js +163 -130
  314. package/dist/internal/Log.js.map +1 -1
  315. package/dist/internal/MetricSink.d.ts.map +1 -1
  316. package/dist/internal/MetricSink.js +26 -1
  317. package/dist/internal/MetricSink.js.map +1 -1
  318. package/dist/internal/RateLimit.d.ts +67 -0
  319. package/dist/internal/RateLimit.d.ts.map +1 -1
  320. package/dist/internal/RateLimit.js +174 -27
  321. package/dist/internal/RateLimit.js.map +1 -1
  322. package/dist/internal/Store.d.ts +6 -0
  323. package/dist/internal/Store.d.ts.map +1 -1
  324. package/dist/internal/Store.js +4 -5
  325. package/dist/internal/Store.js.map +1 -1
  326. package/dist/internal/Timing.d.ts +6 -0
  327. package/dist/internal/Timing.d.ts.map +1 -1
  328. package/dist/internal/Timing.js +21 -1
  329. package/dist/internal/Timing.js.map +1 -1
  330. package/dist/internal/Tron.d.ts +124 -0
  331. package/dist/internal/Tron.d.ts.map +1 -0
  332. package/dist/internal/Tron.js +202 -0
  333. package/dist/internal/Tron.js.map +1 -0
  334. package/dist/internal/Viem.d.ts +4 -0
  335. package/dist/internal/Viem.d.ts.map +1 -1
  336. package/dist/internal/Viem.js +25 -6
  337. package/dist/internal/Viem.js.map +1 -1
  338. package/dist/internal/rewards/Read.d.ts +2 -2
  339. package/dist/internal/rewards/Read.d.ts.map +1 -1
  340. package/dist/internal/rewards/Read.js +11 -2
  341. package/dist/internal/rewards/Read.js.map +1 -1
  342. package/dist/internal/routes/Action.d.ts +27 -0
  343. package/dist/internal/routes/Action.d.ts.map +1 -1
  344. package/dist/internal/routes/Action.js +49 -1
  345. package/dist/internal/routes/Action.js.map +1 -1
  346. package/dist/internal/routes/Chain.d.ts +2 -0
  347. package/dist/internal/routes/Chain.d.ts.map +1 -1
  348. package/dist/internal/routes/Chain.js +4 -0
  349. package/dist/internal/routes/Chain.js.map +1 -1
  350. package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
  351. package/dist/internal/routes/DepositAddress.js +5 -0
  352. package/dist/internal/routes/DepositAddress.js.map +1 -1
  353. package/dist/internal/routes/Evidence.d.ts.map +1 -1
  354. package/dist/internal/routes/Evidence.js +6 -2
  355. package/dist/internal/routes/Evidence.js.map +1 -1
  356. package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
  357. package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
  358. package/dist/internal/routes/EvmTransferSettlement.js +196 -0
  359. package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
  360. package/dist/internal/routes/Policy.d.ts +161 -0
  361. package/dist/internal/routes/Policy.d.ts.map +1 -0
  362. package/dist/internal/routes/Policy.js +249 -0
  363. package/dist/internal/routes/Policy.js.map +1 -0
  364. package/dist/internal/routes/Provider.d.ts +66 -3
  365. package/dist/internal/routes/Provider.d.ts.map +1 -1
  366. package/dist/internal/routes/Provider.js +106 -27
  367. package/dist/internal/routes/Provider.js.map +1 -1
  368. package/dist/internal/routes/Quota.d.ts +57 -0
  369. package/dist/internal/routes/Quota.d.ts.map +1 -0
  370. package/dist/internal/routes/Quota.js +144 -0
  371. package/dist/internal/routes/Quota.js.map +1 -0
  372. package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
  373. package/dist/internal/routes/Reconciliation.js +163 -47
  374. package/dist/internal/routes/Reconciliation.js.map +1 -1
  375. package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
  376. package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
  377. package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
  378. package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
  379. package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
  380. package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
  381. package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
  382. package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
  383. package/dist/internal/routes/Subsidy.d.ts +2 -2
  384. package/dist/internal/routes/Subsidy.d.ts.map +1 -1
  385. package/dist/internal/routes/Subsidy.js +2 -2
  386. package/dist/internal/routes/Subsidy.js.map +1 -1
  387. package/dist/internal/routes/Transfer.d.ts +229 -1
  388. package/dist/internal/routes/Transfer.d.ts.map +1 -1
  389. package/dist/internal/routes/Transfer.js +644 -7
  390. package/dist/internal/routes/Transfer.js.map +1 -1
  391. package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
  392. package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
  393. package/dist/internal/routes/TransferReconciliation.js +83 -159
  394. package/dist/internal/routes/TransferReconciliation.js.map +1 -1
  395. package/dist/internal/routes/TransferSettlement.d.ts +45 -0
  396. package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
  397. package/dist/internal/routes/TransferSettlement.js +2 -0
  398. package/dist/internal/routes/TransferSettlement.js.map +1 -0
  399. package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
  400. package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
  401. package/dist/internal/routes/TransferSubsidy.js +64 -5
  402. package/dist/internal/routes/TransferSubsidy.js.map +1 -1
  403. package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
  404. package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
  405. package/dist/internal/routes/TronTransferSettlement.js +201 -0
  406. package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
  407. package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
  408. package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
  409. package/dist/internal/routes/TronTransferSubsidy.js +439 -0
  410. package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
  411. package/dist/internal/routes/index.d.ts +3 -0
  412. package/dist/internal/routes/index.d.ts.map +1 -1
  413. package/dist/internal/routes/index.js +3 -0
  414. package/dist/internal/routes/index.js.map +1 -1
  415. package/dist/internal/routes/providers/across.d.ts +3 -0
  416. package/dist/internal/routes/providers/across.d.ts.map +1 -1
  417. package/dist/internal/routes/providers/across.js +11 -0
  418. package/dist/internal/routes/providers/across.js.map +1 -1
  419. package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
  420. package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
  421. package/dist/internal/routes/providers/legacyMesh.js +474 -0
  422. package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
  423. package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
  424. package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
  425. package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
  426. package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
  427. package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
  428. package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
  429. package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
  430. package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
  431. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
  432. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
  433. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
  434. package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
  435. package/dist/internal/routes/providers/propAmm.d.ts +70 -0
  436. package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
  437. package/dist/internal/routes/providers/propAmm.js +524 -0
  438. package/dist/internal/routes/providers/propAmm.js.map +1 -0
  439. package/dist/internal/routes/providers/relay.d.ts +3 -0
  440. package/dist/internal/routes/providers/relay.d.ts.map +1 -1
  441. package/dist/internal/routes/providers/relay.js +352 -41
  442. package/dist/internal/routes/providers/relay.js.map +1 -1
  443. package/dist/internal/routes/providers/rhino.d.ts +3 -0
  444. package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
  445. package/dist/internal/routes/providers/rhino.js +11 -0
  446. package/dist/internal/routes/providers/rhino.js.map +1 -1
  447. package/dist/internal/routes/providers/squid.d.ts +3 -0
  448. package/dist/internal/routes/providers/squid.d.ts.map +1 -1
  449. package/dist/internal/routes/providers/squid.js +19 -0
  450. package/dist/internal/routes/providers/squid.js.map +1 -1
  451. package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
  452. package/dist/internal/routes/providers/stargate.js +22 -9
  453. package/dist/internal/routes/providers/stargate.js.map +1 -1
  454. package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
  455. package/dist/internal/routes/providers/symbiosis.js +13 -17
  456. package/dist/internal/routes/providers/symbiosis.js.map +1 -1
  457. package/dist/providers/index.d.ts +14 -0
  458. package/dist/providers/index.d.ts.map +1 -1
  459. package/dist/providers/index.js +6 -0
  460. package/dist/providers/index.js.map +1 -1
  461. package/package.json +16 -6
  462. package/src/ApiKey.ts +7 -3
  463. package/src/ApiKeys.test.ts +652 -8
  464. package/src/ApiKeys.ts +191 -11
  465. package/src/App.test.ts +405 -18
  466. package/src/App.ts +51 -15
  467. package/src/Client.test-d.ts +157 -10
  468. package/src/Client.test.ts +4 -4
  469. package/src/Scope.ts +1 -2
  470. package/src/admin/App.ts +11 -5
  471. package/src/admin/apps/api-keys.test.ts +98 -2
  472. package/src/admin/apps/api-keys.ts +21 -12
  473. package/src/admin/apps/earn-vaults.test.ts +76 -7
  474. package/src/admin/apps/earn-vaults.ts +47 -8
  475. package/src/admin/apps/organizations.test.ts +147 -31
  476. package/src/admin/apps/organizations.ts +5 -4
  477. package/src/admin/apps/route-policies.test.ts +220 -0
  478. package/src/admin/apps/route-policies.ts +322 -0
  479. package/src/admin/apps/routes-support.test.ts +107 -2
  480. package/src/admin/apps/routes-support.ts +43 -3
  481. package/src/admin/apps/routes.test.ts +150 -0
  482. package/src/admin/apps/routes.ts +97 -1
  483. package/src/admin/apps/scopes.test.ts +1 -1
  484. package/src/admin/index.ts +0 -1
  485. package/src/admin/ui/plugin.ts +2 -1
  486. package/src/admin/ui/src/components/Dialog.tsx +1 -1
  487. package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
  488. package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
  489. package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
  490. package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
  491. package/src/admin/ui/src/lib/route-policies.ts +232 -0
  492. package/src/admin/ui/src/lib/routes.ts +34 -0
  493. package/src/admin/ui/src/routeTree.gen.ts +21 -0
  494. package/src/admin/ui/src/routes/api-keys.tsx +21 -2
  495. package/src/admin/ui/src/routes/early-access.tsx +1 -0
  496. package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
  497. package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
  498. package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
  499. package/src/admin/ui/src/routes/organizations.tsx +1 -0
  500. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
  501. package/src/admin/ui/src/routes/route-policies.tsx +678 -0
  502. package/src/admin/ui/src/routes/routes.tsx +85 -2
  503. package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
  504. package/src/admin/ui/src/routes/subsidies.tsx +1 -0
  505. package/src/admin/ui/src/routes/verified-tokens.tsx +1 -0
  506. package/src/admin/ui.generated.ts +258 -202
  507. package/src/analytics/Analytics.test.ts +4 -50
  508. package/src/analytics/Analytics.ts +65 -1
  509. package/src/analytics/tables/requestEvents.test.ts +402 -1
  510. package/src/analytics/tables/requestEvents.ts +62 -93
  511. package/src/apps/data/routes/activities.test.ts +315 -14
  512. package/src/apps/data/routes/activities.ts +60 -0
  513. package/src/apps/data/routes/balances.ts +5 -7
  514. package/src/apps/data/routes/earn.bench.ts +18 -0
  515. package/src/apps/data/routes/earn.local.test.ts +507 -0
  516. package/src/apps/data/routes/earn.test.ts +405 -127
  517. package/src/apps/data/routes/earn.ts +660 -270
  518. package/src/apps/data/routes/exchanges.bench.ts +3 -1
  519. package/src/apps/data/routes/exchanges.test.ts +166 -2
  520. package/src/apps/data/routes/exchanges.ts +308 -101
  521. package/src/apps/data/routes/fee-amm.test.ts +134 -2
  522. package/src/apps/data/routes/fee-amm.ts +122 -60
  523. package/src/apps/data/routes/receipts.test.ts +21 -18
  524. package/src/apps/data/routes/rpc.test.ts +2 -2
  525. package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
  526. package/src/apps/data/routes/tokens.test.ts +4 -4
  527. package/src/apps/data/routes/tokens.ts +11 -6
  528. package/src/apps/data/routes/transactions.test.ts +29 -0
  529. package/src/apps/data/routes/transactions.ts +33 -22
  530. package/src/apps/data/routes/webhooks.test.ts +12 -3
  531. package/src/apps/data/routes/webhooks.ts +2 -1
  532. package/src/apps/management/App.ts +4 -0
  533. package/src/apps/management/Billing.test.ts +253 -27
  534. package/src/apps/management/Billing.ts +83 -29
  535. package/src/apps/management/routes/api-keys.test.ts +1 -1
  536. package/src/apps/management/routes/api-keys.ts +85 -11
  537. package/src/apps/management/routes/billing.test.ts +68 -4
  538. package/src/apps/management/routes/cli.test.ts +370 -0
  539. package/src/apps/management/routes/cli.ts +533 -0
  540. package/src/apps/management/routes/me.test.ts +14 -4
  541. package/src/apps/management/routes/orgs.test.ts +108 -4
  542. package/src/apps/management/routes/orgs.ts +7 -2
  543. package/src/apps/management/routes/usage.test.ts +2 -2
  544. package/src/apps/mpp/internal/Policy.test.ts +51 -4
  545. package/src/apps/mpp/internal/Policy.ts +6 -2
  546. package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
  547. package/src/apps/mpp/internal/Sponsorship.ts +6 -4
  548. package/src/apps/relay/App.test.ts +85 -1
  549. package/src/apps/relay/App.ts +28 -4
  550. package/src/apps/relay/Sponsorships.test.ts +97 -1
  551. package/src/apps/relay/Sponsorships.ts +77 -66
  552. package/src/apps/routes/Access.test.ts +319 -0
  553. package/src/apps/routes/Access.ts +147 -0
  554. package/src/apps/routes/App.ts +10 -0
  555. package/src/apps/routes/routes/chains.test.ts +3 -2
  556. package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
  557. package/src/apps/routes/routes/deposit-addresses.ts +243 -32
  558. package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
  559. package/src/apps/routes/routes/quotes.test.ts +81 -8
  560. package/src/apps/routes/routes/quotes.ts +109 -27
  561. package/src/apps/routes/routes/transfers.test.ts +252 -15
  562. package/src/apps/routes/routes/transfers.ts +212 -33
  563. package/src/cli/ApiKeys.test.ts +265 -0
  564. package/src/cli/ApiKeys.ts +189 -0
  565. package/src/cli/Cli.test.ts +188 -0
  566. package/src/cli/Cli.ts +280 -12
  567. package/src/cli/Credentials.test.ts +122 -0
  568. package/src/cli/Credentials.ts +144 -0
  569. package/src/cli/Spec.test.ts +133 -0
  570. package/src/cli/Spec.ts +132 -0
  571. package/src/cli/bin.test.ts +49 -0
  572. package/src/cli/bin.ts +5 -1
  573. package/src/cli/commands/auth.test.ts +138 -0
  574. package/src/cli/commands/auth.ts +254 -0
  575. package/src/cli/commands/keys.test.ts +68 -0
  576. package/src/cli/commands/keys.ts +125 -0
  577. package/src/cloudflare.ts +184 -36
  578. package/src/db/Db.test.ts +877 -0
  579. package/src/db/Db.ts +498 -1
  580. package/src/db/Schema.ts +75 -4
  581. package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
  582. package/src/db/tables/apiKeyAdmissions.ts +101 -11
  583. package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
  584. package/src/db/tables/authAccounts.test.ts +30 -0
  585. package/src/db/tables/authAccounts.ts +1 -0
  586. package/src/db/tables/earnVaults.test.ts +34 -0
  587. package/src/db/tables/earnVaults.ts +17 -2
  588. package/src/db/tables/organizations.test.ts +148 -84
  589. package/src/db/tables/organizations.ts +11 -43
  590. package/src/db/tables/requestUsage.ts +13 -2
  591. package/src/db/tables/rewardCampaigns.test.ts +163 -0
  592. package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
  593. package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
  594. package/src/db/tables/rewardRuns.ts +4 -0
  595. package/src/db/tables/rewardTransactionAttempts.ts +2 -0
  596. package/src/db/tables/routesDepositAddresses.test.ts +263 -0
  597. package/src/db/tables/routesDepositAddresses.ts +118 -34
  598. package/src/db/tables/routesDeposits.test.ts +66 -5
  599. package/src/db/tables/routesDeposits.ts +47 -26
  600. package/src/db/tables/routesIdempotency.test.ts +80 -0
  601. package/src/db/tables/routesIdempotency.ts +2 -0
  602. package/src/db/tables/routesPolicies.test.ts +143 -0
  603. package/src/db/tables/routesPolicies.ts +251 -0
  604. package/src/db/tables/routesTransferSubsidies.ts +64 -0
  605. package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
  606. package/src/db/tables/routesTransfers.test.ts +183 -2
  607. package/src/db/tables/routesTransfers.ts +65 -6
  608. package/src/db/tables/sponsoredTransactions.test.ts +351 -76
  609. package/src/db/tables/sponsoredTransactions.ts +182 -38
  610. package/src/db/tables/users.test.ts +51 -0
  611. package/src/db/tables/users.ts +12 -0
  612. package/src/handlers/internal/multisig.store.test.ts +120 -0
  613. package/src/handlers/internal/multisig.test.ts +389 -0
  614. package/src/handlers/internal/multisig.ts +13 -10
  615. package/src/handlers/relay.test.ts +259 -83
  616. package/src/handlers/relay.ts +36 -17
  617. package/src/internal/Auth.test.ts +291 -8
  618. package/src/internal/Auth.ts +227 -96
  619. package/src/internal/BetterAuth.test.ts +58 -22
  620. package/src/internal/BetterAuth.ts +23 -17
  621. package/src/internal/Cache.ts +3 -1
  622. package/src/internal/CliAuth.test.ts +279 -0
  623. package/src/internal/CliAuth.ts +319 -0
  624. package/src/internal/EarnSharePrices.test.ts +25 -0
  625. package/src/internal/EarnSharePrices.ts +9 -2
  626. package/src/internal/EarnVaults.test.ts +67 -0
  627. package/src/internal/EarnVaults.ts +299 -4
  628. package/src/internal/EarnWithdrawals.test.ts +315 -0
  629. package/src/internal/EarnWithdrawals.ts +266 -0
  630. package/src/internal/ExecutionContext.ts +31 -0
  631. package/src/internal/Log.test.ts +210 -0
  632. package/src/internal/Log.ts +180 -142
  633. package/src/internal/MetricSink.test.ts +190 -15
  634. package/src/internal/MetricSink.ts +27 -1
  635. package/src/internal/RateLimit.test.ts +144 -8
  636. package/src/internal/RateLimit.ts +254 -26
  637. package/src/internal/Store.ts +4 -5
  638. package/src/internal/Timing.test.ts +32 -0
  639. package/src/internal/Timing.ts +20 -1
  640. package/src/internal/Tron.test-d.ts +22 -0
  641. package/src/internal/Tron.test.ts +94 -0
  642. package/src/internal/Tron.ts +289 -0
  643. package/src/internal/Viem.rpc.test.ts +76 -0
  644. package/src/internal/Viem.ts +29 -6
  645. package/src/internal/rewards/Read.test.ts +109 -0
  646. package/src/internal/rewards/Read.ts +13 -4
  647. package/src/internal/routes/Action.test.ts +70 -0
  648. package/src/internal/routes/Action.ts +76 -1
  649. package/src/internal/routes/Chain.test.ts +18 -0
  650. package/src/internal/routes/Chain.ts +5 -0
  651. package/src/internal/routes/DepositAddress.ts +5 -0
  652. package/src/internal/routes/Evidence.test.ts +64 -0
  653. package/src/internal/routes/Evidence.ts +11 -3
  654. package/src/internal/routes/EvmTransferSettlement.ts +213 -0
  655. package/src/internal/routes/Policy.test.ts +316 -0
  656. package/src/internal/routes/Policy.ts +399 -0
  657. package/src/internal/routes/Provider.test.ts +103 -2
  658. package/src/internal/routes/Provider.ts +149 -27
  659. package/src/internal/routes/Quota.test.ts +149 -0
  660. package/src/internal/routes/Quota.ts +226 -0
  661. package/src/internal/routes/Reconciliation.local.test.ts +285 -0
  662. package/src/internal/routes/Reconciliation.test.ts +371 -13
  663. package/src/internal/routes/Reconciliation.ts +193 -42
  664. package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
  665. package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
  666. package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
  667. package/src/internal/routes/SourceObservation.test.ts +221 -0
  668. package/src/internal/routes/Subsidy.local.test.ts +46 -0
  669. package/src/internal/routes/Subsidy.ts +4 -2
  670. package/src/internal/routes/Transfer.solana.test.ts +389 -0
  671. package/src/internal/routes/Transfer.test.ts +130 -1
  672. package/src/internal/routes/Transfer.tron.test.ts +172 -0
  673. package/src/internal/routes/Transfer.ts +866 -8
  674. package/src/internal/routes/TransferReconciliation.test.ts +26 -4
  675. package/src/internal/routes/TransferReconciliation.ts +91 -166
  676. package/src/internal/routes/TransferSettlement.ts +48 -0
  677. package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
  678. package/src/internal/routes/TransferSubsidy.test.ts +34 -4
  679. package/src/internal/routes/TransferSubsidy.ts +87 -12
  680. package/src/internal/routes/TronTransferSettlement.ts +212 -0
  681. package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
  682. package/src/internal/routes/TronTransferSubsidy.ts +619 -0
  683. package/src/internal/routes/index.test.ts +3 -0
  684. package/src/internal/routes/index.ts +3 -0
  685. package/src/internal/routes/providers/across.ts +13 -0
  686. package/src/internal/routes/providers/index.test.ts +141 -0
  687. package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
  688. package/src/internal/routes/providers/legacyMesh.ts +633 -0
  689. package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
  690. package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
  691. package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
  692. package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
  693. package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
  694. package/src/internal/routes/providers/propAmm.ts +640 -0
  695. package/src/internal/routes/providers/relay.test.ts +1263 -41
  696. package/src/internal/routes/providers/relay.ts +423 -38
  697. package/src/internal/routes/providers/rhino.ts +14 -1
  698. package/src/internal/routes/providers/squid.ts +21 -0
  699. package/src/internal/routes/providers/stargate.test.ts +105 -1
  700. package/src/internal/routes/providers/stargate.ts +22 -9
  701. package/src/internal/routes/providers/symbiosis.ts +13 -47
  702. package/src/providers/index.test.ts +2 -0
  703. package/src/providers/index.ts +18 -0
  704. package/dist/admin/Access.d.ts +0 -39
  705. package/dist/admin/Access.d.ts.map +0 -1
  706. package/dist/admin/Access.js +0 -73
  707. package/dist/admin/Access.js.map +0 -1
  708. package/src/admin/Access.test.ts +0 -130
  709. package/src/admin/Access.ts +0 -85
@@ -18,7 +18,6 @@ import * as Scope from '../../../Scope.js'
18
18
  import * as Db from '../../../db/Db.js'
19
19
  import * as core_EarnVaults from '../../../db/tables/earnVaults.js'
20
20
  import * as RewardCampaignDistributors from '../../../db/tables/rewardCampaignDistributors.js'
21
- import * as RewardCampaigns from '../../../db/tables/rewardCampaigns.js'
22
21
  import * as RewardEligibilityAssociations from '../../../db/tables/rewardEligibilityAssociations.js'
23
22
  import * as Auth from '../../../internal/Auth.js'
24
23
  import * as Cache from '../../../internal/Cache.js'
@@ -26,6 +25,7 @@ import * as Cursor from '../../../internal/Cursor.js'
26
25
  import * as EarnRates from '../../../internal/EarnRates.js'
27
26
  import * as EarnSharePrices from '../../../internal/EarnSharePrices.js'
28
27
  import * as EarnVaults from '../../../internal/EarnVaults.js'
28
+ import * as EarnWithdrawals from '../../../internal/EarnWithdrawals.js'
29
29
  import type * as Log from '../../../internal/Log.js'
30
30
  import * as OpenApi from '../../../internal/OpenApi.js'
31
31
  import * as RewardRead from '../../../internal/rewards/Read.js'
@@ -663,11 +663,13 @@ export namespace schema {
663
663
  z.meta({ examples: ['0'] }),
664
664
  ),
665
665
  assetBalance: Schema.DecimalString.check(
666
- z.describe('Assets held by this account at the observation block, in asset base units.'),
666
+ z.describe(
667
+ 'Public vault assets held by this account at the observation block, in asset base units.',
668
+ ),
667
669
  z.meta({ examples: ['250000000'] }),
668
670
  ),
669
671
  assetToken: Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50').check(
670
- z.describe('TIP-20 asset token accepted by the vault or its selected Zone route.'),
672
+ z.describe('TIP-20 asset token accepted by the public parent vault.'),
671
673
  ),
672
674
  chainId: Schema.ChainId.check(
673
675
  z.describe('Chain containing the account position.'),
@@ -677,6 +679,17 @@ export namespace schema {
677
679
  z.describe('Stable resource ID for this vault position, equal to the account address.'),
678
680
  z.meta({ examples: ['0xbe058e1c4df8a4366a387bf595b284246a93039e'] }),
679
681
  ),
682
+ privateAssetBalance: z
683
+ .optional(Schema.DecimalString)
684
+ .check(
685
+ z.describe(
686
+ 'Private Zone assets held by this account at the observation block, in private asset base units.',
687
+ ),
688
+ z.meta({ examples: ['250000000'] }),
689
+ ),
690
+ privateAssetToken: z
691
+ .optional(Schema.tokenAddress('0x20c000000000000000000000b9537d11c60e8b50'))
692
+ .check(z.describe('TIP-20 private asset used by the validated Zone route.')),
680
693
  shareAllowance: Schema.DecimalString.check(
681
694
  z.describe(
682
695
  'Earn shares the vault may spend from a direct account, in share base units. Always zero for Zone-routed positions, which use Zone withdrawals instead of approvals.',
@@ -730,7 +743,9 @@ export namespace schema {
730
743
  ),
731
744
  })
732
745
  .check(
733
- z.describe('Vault asset amount receiving this annual rate.'),
746
+ z.describe(
747
+ 'Vault asset amount receiving this annual rate. Zero for an eligible boost with no currently qualified amount.',
748
+ ),
734
749
  z.meta({
735
750
  examples: [{ baseUnits: '25000000000', decimals: 6, formatted: '25000' }],
736
751
  }),
@@ -742,14 +757,16 @@ export namespace schema {
742
757
  type: z
743
758
  .enum(['base', 'boost'])
744
759
  .check(
745
- z.describe('Base vault yield or qualified depositor boost.'),
760
+ z.describe('Base vault yield or eligible depositor boost target.'),
746
761
  z.meta({ examples: ['boost'] }),
747
762
  ),
748
763
  })
749
764
  .check(z.describe('Position component receiving one annual rate.')),
750
765
  )
751
766
  .check(
752
- z.describe('Position amounts grouped by the annual rate they receive.'),
767
+ z.describe(
768
+ 'Position amounts grouped by annual rate. Eligible active boosts appear even with zero qualified amount and do not increase the balance-weighted net rate.',
769
+ ),
753
770
  z.meta({
754
771
  examples: [
755
772
  [
@@ -789,7 +806,9 @@ export namespace schema {
789
806
  z.describe('Assets deposited with this account as receiver over indexed vault history.'),
790
807
  ),
791
808
  totalWithdrawn: Schema.DecimalString.check(
792
- z.describe('Assets returned by completed withdrawals over indexed vault history.'),
809
+ z.describe(
810
+ 'Completed withdrawal proceeds plus other outgoing shares valued at their transfer blocks.',
811
+ ),
793
812
  ),
794
813
  }),
795
814
  z.strictObject({
@@ -863,7 +882,7 @@ export namespace schema {
863
882
  ),
864
883
  currentValue: Schema.DecimalString.check(
865
884
  z.describe(
866
- 'Asset value of the account’s active earn shares at the latest indexed block, in asset base units.',
885
+ 'Asset value of the account’s active earn shares at the ending indexed block, in asset base units.',
867
886
  ),
868
887
  z.meta({ examples: ['600000'] }),
869
888
  ),
@@ -874,14 +893,39 @@ export namespace schema {
874
893
  })
875
894
 
876
895
  const earningsPeriod = z
877
- .enum(['30d', 'active', 'lifetime'])
896
+ .enum(['7d', '30d', 'active', 'custom', 'lifetime'])
878
897
  .check(
879
898
  z.describe(
880
- 'Earnings period to calculate: trailing 30 days, shares still held, or lifetime history.',
899
+ 'Earnings period: trailing 7 or 30 days, shares still held, explicit timestamps, or lifetime history.',
881
900
  ),
882
901
  z.meta({ examples: ['lifetime'] }),
883
902
  )
884
903
 
904
+ const earningsWindow = z.extend(earningsBase, {
905
+ end: z.iso
906
+ .datetime()
907
+ .check(
908
+ z.describe(
909
+ 'UTC ending boundary. Includes activity through the latest indexed block at or before this timestamp.',
910
+ ),
911
+ z.meta({ examples: ['2026-09-18T00:00:00.000Z'] }),
912
+ ),
913
+ period: z
914
+ .enum(['7d', '30d', 'custom'])
915
+ .check(
916
+ z.describe('Rolling or explicitly bounded earnings window.'),
917
+ z.meta({ examples: ['7d'] }),
918
+ ),
919
+ start: z.iso
920
+ .datetime()
921
+ .check(
922
+ z.describe(
923
+ 'UTC opening boundary. Excludes activity through the latest indexed block at or before this timestamp.',
924
+ ),
925
+ z.meta({ examples: ['2026-09-11T00:00:00.000Z'] }),
926
+ ),
927
+ })
928
+
885
929
  const earnings = z.union([
886
930
  z.extend(earningsBase, {
887
931
  lifetimeEarnings: z
@@ -889,7 +933,7 @@ export namespace schema {
889
933
  .check(
890
934
  z.regex(/^-?\d+$/),
891
935
  z.describe(
892
- 'Current share value plus completed redemptions, exact withdrawals, and finalized async assets, minus asset deposits, at the latest indexed block.',
936
+ 'Current share value plus withdrawals, including outgoing shares valued when transferred, minus asset deposits, at the latest indexed block.',
893
937
  ),
894
938
  z.meta({ examples: ['0'] }),
895
939
  ),
@@ -901,7 +945,7 @@ export namespace schema {
901
945
  ),
902
946
  totalWithdrawn: Schema.DecimalString.check(
903
947
  z.describe(
904
- 'Assets returned by completed redemptions and exact withdrawals initiated by this account over complete indexed vault history.',
948
+ 'Completed vault withdrawal proceeds plus other outgoing shares valued at their transfer blocks, regardless of recipient or spender.',
905
949
  ),
906
950
  z.meta({ examples: ['1000000'] }),
907
951
  ),
@@ -941,13 +985,7 @@ export namespace schema {
941
985
  z.meta({ examples: ['complete'] }),
942
986
  ),
943
987
  }),
944
- z.extend(earningsBase, {
945
- period: z
946
- .literal('30d')
947
- .check(
948
- z.describe('Returns cash-flow-adjusted earnings over the trailing 30 days.'),
949
- z.meta({ examples: ['30d'] }),
950
- ),
988
+ z.extend(earningsWindow, {
951
989
  status: z
952
990
  .literal('complete')
953
991
  .check(
@@ -959,13 +997,18 @@ export namespace schema {
959
997
  .check(
960
998
  z.regex(/^-?\d+$/),
961
999
  z.describe(
962
- 'Ending share value plus realized assets, minus deposits and opening share value, over the trailing 30 days.',
1000
+ 'Ending share value plus withdrawals, including outgoing shares valued when transferred, minus deposits and opening share value, over the requested window.',
963
1001
  ),
964
1002
  z.meta({ examples: ['0'] }),
965
1003
  ),
966
1004
  }),
967
1005
  z.extend(earningsBase, {
968
- period: earningsPeriod,
1006
+ period: z
1007
+ .enum(['active', 'lifetime'])
1008
+ .check(
1009
+ z.describe('Earnings period with unavailable cost basis.'),
1010
+ z.meta({ examples: ['lifetime'] }),
1011
+ ),
969
1012
  status: z
970
1013
  .literal('incomplete_cost_basis')
971
1014
  .check(
@@ -975,13 +1018,17 @@ export namespace schema {
975
1018
  z.meta({ examples: ['incomplete_cost_basis'] }),
976
1019
  ),
977
1020
  }),
978
- z.extend(earningsBase, {
979
- period: z
980
- .literal('30d')
1021
+ z.extend(earningsWindow, {
1022
+ status: z
1023
+ .literal('incomplete_cost_basis')
981
1024
  .check(
982
- z.describe('Trailing period with an unresolved async redemption.'),
983
- z.meta({ examples: ['30d'] }),
1025
+ z.describe(
1026
+ 'Indexed activity cannot reconstruct the requested window’s asset cost basis.',
1027
+ ),
1028
+ z.meta({ examples: ['incomplete_cost_basis'] }),
984
1029
  ),
1030
+ }),
1031
+ z.extend(earningsWindow, {
985
1032
  status: z
986
1033
  .literal('pending_redemption')
987
1034
  .check(
@@ -1422,12 +1469,42 @@ export namespace schema {
1422
1469
  })
1423
1470
  .check(z.describe('Path parameters identifying an earn vault account.'))
1424
1471
 
1425
- /** Query parameters selecting the chain containing the vault. */
1472
+ /** Query parameters selecting the chain and earnings interval. */
1426
1473
  export const Query = z
1427
1474
  .strictObject({
1428
1475
  chainId: Schema.ChainIdQuery,
1476
+ end: z
1477
+ .optional(z.iso.datetime({ offset: true }))
1478
+ .check(
1479
+ z.describe(
1480
+ 'Required with period=custom. Inclusive ISO 8601 ending timestamp; indexed history must cover this time.',
1481
+ ),
1482
+ z.meta({ examples: ['2026-09-18T00:00:00.000Z'] }),
1483
+ ),
1429
1484
  period: z._default(earningsPeriod, 'lifetime'),
1485
+ start: z
1486
+ .optional(z.iso.datetime({ offset: true }))
1487
+ .check(
1488
+ z.describe(
1489
+ 'Required with period=custom. Exclusive ISO 8601 opening timestamp, earlier than end.',
1490
+ ),
1491
+ z.meta({ examples: ['2026-09-11T00:00:00.000Z'] }),
1492
+ ),
1430
1493
  })
1494
+ .check(
1495
+ z.refine(
1496
+ (value) =>
1497
+ value.period === 'custom'
1498
+ ? value.start !== undefined &&
1499
+ value.end !== undefined &&
1500
+ Date.parse(value.start) < Date.parse(value.end)
1501
+ : value.start === undefined && value.end === undefined,
1502
+ {
1503
+ message:
1504
+ 'Only period=custom accepts start and end; both are required and start must be earlier than end',
1505
+ },
1506
+ ),
1507
+ )
1431
1508
  .check(z.describe('Query parameters selecting an earn vault account.'))
1432
1509
 
1433
1510
  /** Earnings for one account and period in one Earn vault. */
@@ -1447,7 +1524,7 @@ export function earn(options: earn.Options = {}) {
1447
1524
  return new Hono<App.Environment>()
1448
1525
  .post(
1449
1526
  '/v1/earn/rewards/eligibility',
1450
- Auth.policy({ apiKey: { scopes: [Scope.wildcard] } }),
1527
+ Auth.policy({ apiKey: { scopes: ['rewards:write'] } }),
1451
1528
  OpenApi.validate('json', schema.registerRewardEligibility.Body, {
1452
1529
  code: 'body_invalid',
1453
1530
  message: 'Invalid reward eligibility registration',
@@ -1480,6 +1557,25 @@ export function earn(options: earn.Options = {}) {
1480
1557
  if (!c.get('supportedChainIds').has(body.chainId))
1481
1558
  return Response.unsupportedChainId(c, body.chainId, c.get('supportedChainIds'))
1482
1559
  c.set('chainId', body.chainId)
1560
+ if (c.get('zones').has(body.chainId))
1561
+ return Response.error(c, {
1562
+ code: 'chain_id_unsupported',
1563
+ message: `Zone chain ID ${body.chainId} is not supported for rewards registration.`,
1564
+ status: 400,
1565
+ })
1566
+
1567
+ const principal = Auth.getPrincipal(c)
1568
+ if (
1569
+ principal?.type === 'api_key' &&
1570
+ principal.environment === 'sandbox' &&
1571
+ Viem.isMainnet(body.chainId)
1572
+ )
1573
+ return Response.error(c, {
1574
+ code: 'api_key_forbidden',
1575
+ message: 'Sandbox API keys only support testnet.',
1576
+ status: 403,
1577
+ })
1578
+
1483
1579
  c.header('Cache-Control', Cache.policies.noStore)
1484
1580
  const result = await RewardEligibilityAssociations.upsert(Db.get(c.get('db')), {
1485
1581
  ...body,
@@ -1944,21 +2040,26 @@ export function earn(options: earn.Options = {}) {
1944
2040
  })
1945
2041
  if (c.get('zones').has(chainId)) Cache.setPolicy(c, Cache.policies.noStore)
1946
2042
  try {
1947
- const position = await getVaultPosition(c, {
1948
- account: address,
1949
- asOf: query.asOf,
1950
- chainId,
1951
- vault: vaultId,
1952
- })
1953
- const apy = query.include.includes('apy')
1954
- ? await resolvePositionApy(c, {
2043
+ const position_pending = Timing.time(c, 'earn_position', () =>
2044
+ getVaultPosition(c, {
2045
+ account: address,
2046
+ asOf: query.asOf,
2047
+ chainId,
2048
+ vault: vaultId,
2049
+ }),
2050
+ )
2051
+ // Rate and vault reads depend only on the vault, so they overlap the
2052
+ // position's chained RPC hops instead of queueing behind them.
2053
+ const apy_pending = query.include.includes('apy')
2054
+ ? resolvePositionApy(c, {
1955
2055
  chainId,
2056
+ position: position_pending,
1956
2057
  recipient: address,
1957
- shareBalance: position.shareBalance,
1958
- value: position.value,
1959
2058
  vault: vaultId,
1960
2059
  })
1961
2060
  : undefined
2061
+ const position = await position_pending
2062
+ const apy = await apy_pending
1962
2063
  const rewards = query.include.some((value) => value.startsWith('rewards'))
1963
2064
  ? await RewardRead.recipient({
1964
2065
  chainId,
@@ -1979,6 +2080,12 @@ export function earn(options: earn.Options = {}) {
1979
2080
  asOf: query.asOf,
1980
2081
  block: position.block,
1981
2082
  id: address,
2083
+ ...(position.privateAssetBalance === undefined
2084
+ ? {}
2085
+ : { privateAssetBalance: position.privateAssetBalance.toString() }),
2086
+ ...(position.privateAssetToken === undefined
2087
+ ? {}
2088
+ : { privateAssetToken: position.privateAssetToken }),
1982
2089
  ...(rewards
1983
2090
  ? {
1984
2091
  rewards: query.include.includes('rewards.proof')
@@ -2080,7 +2187,7 @@ export function earn(options: earn.Options = {}) {
2080
2187
  }),
2081
2188
  OpenApi.describeRoute({
2082
2189
  description:
2083
- 'Gets an account’s indexed asset value and earnings for lifetime history, the trailing 30 days, or shares still held.',
2190
+ 'Gets an account’s asset value and earnings for lifetime history, shares still held, or a rolling or custom time window.',
2084
2191
  operationId: 'getEarnVaultEarnings',
2085
2192
  responses: OpenApi.responses({
2086
2193
  errors: {
@@ -2109,7 +2216,7 @@ export function earn(options: earn.Options = {}) {
2109
2216
  Cache.response<App.Environment>({
2110
2217
  cacheControl: Cache.policies.state,
2111
2218
  key: (c) => Cache.urlKey(c, schema.getEarnVaultEarnings.Query),
2112
- name: 'tempo-api:earn-vault-earnings:v4',
2219
+ name: 'tempo-api:earn-vault-earnings:v5',
2113
2220
  }),
2114
2221
  async (c) => {
2115
2222
  if (Auth.narrowAccess) return Auth.paidAccessError(c)
@@ -2141,13 +2248,15 @@ export function earn(options: earn.Options = {}) {
2141
2248
  const chainId = query.chainId ?? c.get('chainId')
2142
2249
  try {
2143
2250
  const data = await getVaultEarnings(c, {
2251
+ ...query,
2144
2252
  account: address,
2145
2253
  chainId,
2146
- period: query.period,
2147
2254
  vault: vaultId,
2148
2255
  })
2149
2256
  return c.json(Response.validated(schema.getEarnVaultEarnings.Response, data), 200)
2150
2257
  } catch (cause) {
2258
+ if (cause instanceof IndexedBlockNotFoundError || cause instanceof IndexedCoverageError)
2259
+ return Response.error(c, { code: 'query_invalid', message: cause.message, status: 400 })
2151
2260
  try {
2152
2261
  await resolveVaultDiscovery(c, { chainId, include: [], vaultAddress: vaultId })
2153
2262
  } catch (vaultCause) {
@@ -2271,19 +2380,27 @@ export async function getVaultEarnings(
2271
2380
  ) {
2272
2381
  const client = c.get('getClient')(options.chainId)
2273
2382
  const tidx = c.get('getTidx')(options.chainId)
2274
- const [block, rewardTransfer] = await Promise.all([
2275
- getLatestIndexedBlock(tidx),
2276
- getRewardTransferPredicate(c, options),
2383
+ const [block, earnings] = await Promise.all([
2384
+ options.period === 'custom'
2385
+ ? getIndexedBlockAtOrBefore(tidx, options.end!)
2386
+ : getLatestIndexedBlock(tidx),
2387
+ getEarningsConfiguration(c, options),
2277
2388
  ])
2278
2389
  const blockNumber = block.number
2279
- if (options.period === '30d')
2390
+ if (options.period === '7d' || options.period === '30d' || options.period === 'custom')
2280
2391
  return getWindowVaultEarnings(c, {
2281
2392
  account: options.account,
2282
2393
  blockNumber,
2283
2394
  chainId: options.chainId,
2395
+ earnings,
2396
+ end: options.period === 'custom' ? new Date(options.end!).toISOString() : block.timestamp,
2284
2397
  period: options.period,
2285
- rewardTransfer,
2286
- timestamp: block.timestamp,
2398
+ start:
2399
+ options.period === 'custom'
2400
+ ? new Date(options.start!).toISOString()
2401
+ : new Date(
2402
+ Date.parse(block.timestamp) - Ttl.days(options.period === '7d' ? 7 : 30),
2403
+ ).toISOString(),
2287
2404
  vault: options.vault,
2288
2405
  })
2289
2406
  const position = client.earn.getPosition({
@@ -2303,7 +2420,7 @@ export async function getVaultEarnings(
2303
2420
  const activeCostBasis = await getActiveCostBasis(tidx, {
2304
2421
  account: options.account,
2305
2422
  blockNumber,
2306
- rewardTransfer,
2423
+ rewardTransfer: getRewardTransferPredicate(current.shareToken, earnings.rewardDistributors),
2307
2424
  shareBalance: current.shareBalance,
2308
2425
  shareToken: current.shareToken,
2309
2426
  vault: options.vault,
@@ -2324,10 +2441,11 @@ export async function getVaultEarnings(
2324
2441
  }),
2325
2442
  position,
2326
2443
  ])
2327
- const externalShareTransfer = await hasExternalShareTransfer(tidx, {
2444
+ const transfers = await getShareTransferState(tidx, {
2328
2445
  account: options.account,
2329
2446
  blockNumber,
2330
- rewardTransfer,
2447
+ client,
2448
+ rewardTransfer: getRewardTransferPredicate(current.shareToken, earnings.rewardDistributors),
2331
2449
  shareToken: current.shareToken,
2332
2450
  startBlockNumber: beforeFirstBlockNumber,
2333
2451
  vault: options.vault,
@@ -2339,9 +2457,10 @@ export async function getVaultEarnings(
2339
2457
  id: options.account,
2340
2458
  period: options.period,
2341
2459
  }
2342
- if (history.incompleteCostBasis || externalShareTransfer)
2460
+ if (history.incompleteCostBasis || transfers.external || transfers.withdrawn === undefined)
2343
2461
  return { ...base, status: 'incomplete_cost_basis' as const }
2344
- const totalWithdrawn = history.redeemed + history.withdrewExact + history.finalized
2462
+ const totalWithdrawn =
2463
+ history.redeemed + history.withdrewExact + history.finalized + transfers.withdrawn
2345
2464
  const cashFlows = {
2346
2465
  totalDeposited: history.deposited.toString(),
2347
2466
  totalWithdrawn: totalWithdrawn.toString(),
@@ -2357,7 +2476,7 @@ export async function getVaultEarnings(
2357
2476
  }
2358
2477
  }
2359
2478
 
2360
- /** Reads cash-flow-adjusted earnings over a trailing indexed window. */
2479
+ /** Reads cash-flow-adjusted earnings over an indexed time window. */
2361
2480
  async function getWindowVaultEarnings(
2362
2481
  c: Context<App.Environment>,
2363
2482
  options: getWindowVaultEarnings.Options,
@@ -2370,13 +2489,19 @@ async function getWindowVaultEarnings(
2370
2489
  blockNumber: BigInt(options.blockNumber),
2371
2490
  vault: options.vault,
2372
2491
  }),
2373
- getWindowStartBlockNumber(tidx, { days: 30, timestamp: options.timestamp }),
2492
+ options.period === 'custom'
2493
+ ? getIndexedBlockAtOrBefore(tidx, options.start).then((block) => block.number)
2494
+ : getWindowStartBlockNumber(tidx, { timestamp: options.start }),
2374
2495
  ])
2375
- const [externalShareTransfer, history, opening] = await Promise.all([
2376
- hasExternalShareTransfer(tidx, {
2496
+ const [transfers, history, opening] = await Promise.all([
2497
+ getShareTransferState(tidx, {
2377
2498
  account: options.account,
2378
2499
  blockNumber: options.blockNumber,
2379
- rewardTransfer: options.rewardTransfer,
2500
+ client,
2501
+ rewardTransfer: getRewardTransferPredicate(
2502
+ current.shareToken,
2503
+ options.earnings.rewardDistributors,
2504
+ ),
2380
2505
  shareToken: current.shareToken,
2381
2506
  startBlockNumber,
2382
2507
  vault: options.vault,
@@ -2399,12 +2524,15 @@ async function getWindowVaultEarnings(
2399
2524
  account: options.account,
2400
2525
  assetToken: current.assetToken,
2401
2526
  currentValue: current.value.toString(),
2527
+ end: options.end,
2402
2528
  id: options.account,
2403
2529
  period: options.period,
2530
+ start: options.start,
2404
2531
  }
2405
2532
  if (
2406
2533
  opening === undefined ||
2407
- externalShareTransfer ||
2534
+ transfers.external ||
2535
+ transfers.withdrawn === undefined ||
2408
2536
  history.incompleteCostBasis ||
2409
2537
  opening.crossBoundaryRedemption ||
2410
2538
  opening.endShares !== current.shareBalance
@@ -2425,7 +2553,7 @@ async function getWindowVaultEarnings(
2425
2553
  finalized: history.finalized,
2426
2554
  openingValue,
2427
2555
  redeemed: history.redeemed,
2428
- withdrewExact: history.withdrewExact,
2556
+ withdrewExact: history.withdrewExact + transfers.withdrawn,
2429
2557
  })
2430
2558
  return { ...base, status: 'complete' as const, windowEarnings: windowEarnings.toString() }
2431
2559
  }
@@ -2439,12 +2567,14 @@ declare namespace getWindowVaultEarnings {
2439
2567
  blockNumber: number
2440
2568
  /** Tempo chain containing the vault. */
2441
2569
  chainId: z.output<typeof Schema.ChainId>
2442
- /** Trailing earnings period. */
2443
- period: '30d'
2444
- /** SQL predicate recognizing paid rewards in the share-transfer history. */
2445
- rewardTransfer: string
2446
- /** Latest indexed block timestamp. */
2447
- timestamp: string
2570
+ /** Counterparties recognized for this vault's earnings. */
2571
+ earnings: z.output<typeof EarnVaults.schema.Earnings>
2572
+ /** Inclusive ending timestamp in UTC. */
2573
+ end: string
2574
+ /** Rolling or custom earnings period. */
2575
+ period: '7d' | '30d' | 'custom'
2576
+ /** Exclusive opening timestamp in UTC. */
2577
+ start: string
2448
2578
  /** Earn vault contract address. */
2449
2579
  vault: z.output<typeof Schema.Address>
2450
2580
  }
@@ -2482,10 +2612,9 @@ export declare namespace calculateWindowEarnings {
2482
2612
 
2483
2613
  export declare namespace getVaultEarnings {
2484
2614
  /** Inputs identifying the account and vault to calculate. */
2485
- type Options = {
2615
+ type Options = z.output<typeof schema.getEarnVaultEarnings.Query> & {
2486
2616
  account: z.output<typeof Schema.Address>
2487
2617
  chainId: z.output<typeof Schema.ChainId>
2488
- period: z.output<typeof schema.getEarnVaultEarnings.Query>['period']
2489
2618
  vault: z.output<typeof Schema.Address>
2490
2619
  }
2491
2620
  }
@@ -2559,12 +2688,12 @@ export declare namespace parseIndexedBlockAtOrBefore {
2559
2688
  }
2560
2689
  }
2561
2690
 
2562
- /** Resolves the last indexed block at or before a trailing-day boundary. */
2691
+ /** Resolves a rolling boundary, allowing windows that start before the chain existed. */
2563
2692
  async function getWindowStartBlockNumber(
2564
2693
  tidx: Tidx.Client,
2565
2694
  options: getWindowStartBlockNumber.Options,
2566
2695
  ) {
2567
- const cutoff = new Date(Date.parse(options.timestamp) - Ttl.days(options.days)).toISOString()
2696
+ const cutoff = options.timestamp
2568
2697
  const result = await tidx.fetch({
2569
2698
  query:
2570
2699
  `SELECT num FROM blocks WHERE timestamp <= '${cutoff}' ORDER BY num DESC LIMIT 1` as string,
@@ -2577,11 +2706,9 @@ async function getWindowStartBlockNumber(
2577
2706
  }
2578
2707
 
2579
2708
  declare namespace getWindowStartBlockNumber {
2580
- /** Inputs defining a trailing boundary from an indexed timestamp. */
2709
+ /** Inputs defining a rolling window's opening boundary. */
2581
2710
  type Options = {
2582
- /** Number of trailing days. */
2583
- days: number
2584
- /** Timestamp anchoring the end of the window. */
2711
+ /** Canonical UTC timestamp anchoring the start of the window. */
2585
2712
  timestamp: string
2586
2713
  }
2587
2714
  }
@@ -2824,31 +2951,44 @@ declare namespace getWindowShareState {
2824
2951
  }
2825
2952
  }
2826
2953
 
2827
- /** Builds a share-transfer predicate for the vault's verified reward distributors. */
2828
- async function getRewardTransferPredicate(
2954
+ /** Combines recorded campaign distributors with additional per-vault reward distributors. */
2955
+ async function getEarningsConfiguration(
2829
2956
  c: Context<App.Environment>,
2830
2957
  options: Pick<getVaultEarnings.Options, 'chainId' | 'vault'>,
2831
- ) {
2958
+ ): Promise<z.output<typeof EarnVaults.schema.Earnings>> {
2832
2959
  const db = Db.get(c.get('db'))
2833
- const campaign = await RewardCampaigns.get(db, {
2960
+ const record = await core_EarnVaults.get(db, {
2834
2961
  chainId: options.chainId,
2835
2962
  vaultAddress: options.vault,
2836
2963
  })
2837
- if (!campaign) return '0'
2838
2964
  const distributors = await RewardCampaignDistributors.list(db, {
2839
2965
  chainId: options.chainId,
2840
2966
  vaultAddress: options.vault,
2841
2967
  })
2968
+ return {
2969
+ rewardDistributors: [
2970
+ ...new Set([
2971
+ ...distributors.map(({ distributorAddress }) => distributorAddress),
2972
+ ...(record?.earnings?.rewardDistributors ?? []),
2973
+ ]),
2974
+ ],
2975
+ }
2976
+ }
2977
+
2978
+ /** Builds a share-transfer predicate scoped to this vault's share token and configured distributors. */
2979
+ function getRewardTransferPredicate(
2980
+ shareToken: z.output<typeof Schema.Address>,
2981
+ distributors: readonly z.output<typeof Schema.Address>[],
2982
+ ) {
2842
2983
  if (distributors.length === 0) return '0'
2843
2984
  const addresses = distributors
2844
- .map(({ distributorAddress }) => Schema.Address.parse(distributorAddress))
2985
+ .map((address) => Schema.Address.parse(address))
2845
2986
  .map((address) => `'${address}'`)
2846
2987
  .join(', ')
2847
- const shareToken = Schema.Address.parse(campaign.earnShareAddress)
2848
2988
 
2849
2989
  // Batch rewards have no per-recipient event; exclude treasury returns instead. Qualify the filter so TIDX does not apply it to other event CTEs.
2850
2990
  return `
2851
- token = '${shareToken}'
2991
+ token = '${shareToken.toLowerCase()}'
2852
2992
  AND "from" IN (${addresses})
2853
2993
  AND tx_hash NOT IN (
2854
2994
  SELECT returned.tx_hash FROM UnspentReturned AS returned
@@ -2857,12 +2997,10 @@ async function getRewardTransferPredicate(
2857
2997
  `
2858
2998
  }
2859
2999
 
2860
- /** Returns whether an account sent or received Earn shares outside known vault flows. */
2861
- async function hasExternalShareTransfer(
2862
- tidx: Tidx.Client,
2863
- options: hasExternalShareTransfer.Options,
2864
- ) {
2865
- // Vault exits pull shares into the vault before burning. Reconcile counts by transaction and amount so unmatched direct sends remain external.
3000
+ /** Reads unknown incoming shares and recipient-independent outgoing share values. */
3001
+ async function getShareTransferState(tidx: Tidx.Client, options: getShareTransferState.Options) {
3002
+ const withdrawals = await EarnWithdrawals.read(tidx, options)
3003
+ // Incoming rewards and cancelled requests are known; other receipts still lack deposit basis.
2866
3004
  const result = await tidx.fetch({
2867
3005
  engine: 'clickhouse',
2868
3006
  query: `
@@ -2874,56 +3012,11 @@ async function hasExternalShareTransfer(
2874
3012
  AND toUInt256(amount) > 0
2875
3013
  AND block_num > ${options.startBlockNumber}
2876
3014
  AND block_num <= ${options.blockNumber}
2877
- AND (
2878
- ("from" = '${options.account}' AND "to" != '${options.vault}')
2879
- OR (
2880
- "to" = '${options.account}'
2881
- AND "from" != '${zeroAddress}'
2882
- AND "from" != '${options.vault}'
2883
- AND NOT (${options.rewardTransfer})
2884
- )
2885
- )
2886
- ) + (
2887
- SELECT count()
2888
- FROM (
2889
- SELECT tx_hash, toUInt256(amount) AS amount, count() AS transfer_count
2890
- FROM token_transfers
2891
- WHERE token = '${options.shareToken.toLowerCase()}'
2892
- AND toUInt256(amount) > 0
2893
- AND "from" = '${options.account}'
2894
- AND "to" = '${options.vault}'
2895
- AND block_num > ${options.startBlockNumber}
2896
- AND block_num <= ${options.blockNumber}
2897
- GROUP BY tx_hash, amount
2898
- ) AS candidate
2899
- LEFT JOIN (
2900
- SELECT tx_hash, amount, count() AS exit_count
2901
- FROM (
2902
- SELECT tx_hash, toUInt256(earnShares) AS amount
2903
- FROM Redeemed
2904
- WHERE address = '${options.vault}'
2905
- AND caller = '${options.account}'
2906
- AND block_num > ${options.startBlockNumber}
2907
- AND block_num <= ${options.blockNumber}
2908
- UNION ALL
2909
- SELECT tx_hash, toUInt256(earnShares) AS amount
2910
- FROM RedeemRequested
2911
- WHERE address = '${options.vault}'
2912
- AND requester = '${options.account}'
2913
- AND block_num > ${options.startBlockNumber}
2914
- AND block_num <= ${options.blockNumber}
2915
- UNION ALL
2916
- SELECT tx_hash, toUInt256(earnSharesBurned) AS amount
2917
- FROM WithdrewExact
2918
- WHERE address = '${options.vault}'
2919
- AND caller = '${options.account}'
2920
- AND block_num > ${options.startBlockNumber}
2921
- AND block_num <= ${options.blockNumber}
2922
- ) AS protocol_exit
2923
- GROUP BY tx_hash, amount
2924
- ) AS matched
2925
- ON matched.tx_hash = candidate.tx_hash AND matched.amount = candidate.amount
2926
- WHERE candidate.transfer_count > coalesce(matched.exit_count, 0)
3015
+ AND "to" = '${options.account}'
3016
+ AND "from" != '${options.account}'
3017
+ AND "from" != '${zeroAddress}'
3018
+ AND "from" != '${options.vault}'
3019
+ AND NOT (${options.rewardTransfer})
2927
3020
  ) + (
2928
3021
  SELECT count()
2929
3022
  FROM (
@@ -2960,13 +3053,20 @@ async function hasExternalShareTransfer(
2960
3053
  })
2961
3054
  const count = Value.toNumber(result.rows[0]?.['count'])
2962
3055
  if (count === undefined) throw new Error('TIDX returned an invalid Earn-share transfer count.')
2963
- return count > 0
3056
+ return {
3057
+ external: count > 0,
3058
+ withdrawn:
3059
+ count > 0
3060
+ ? undefined
3061
+ : await EarnWithdrawals.value(options.client, { vault: options.vault, withdrawals }),
3062
+ }
2964
3063
  }
2965
3064
 
2966
- declare namespace hasExternalShareTransfer {
3065
+ declare namespace getShareTransferState {
2967
3066
  type Options = {
2968
3067
  account: z.output<typeof Schema.Address>
2969
3068
  blockNumber: number
3069
+ client: Viem.getClient.ReturnType
2970
3070
  rewardTransfer: string
2971
3071
  shareToken: z.output<typeof Schema.Address>
2972
3072
  startBlockNumber: number
@@ -3073,6 +3173,14 @@ export declare namespace calculateActiveCostBasis {
3073
3173
 
3074
3174
  /** Reads the active asset cost basis for shares held at one indexed block. */
3075
3175
  async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis.Options) {
3176
+ const withdrawals = await EarnWithdrawals.read(tidx, {
3177
+ ...options,
3178
+ startBlockNumber: beforeFirstBlockNumber,
3179
+ })
3180
+ const outgoing =
3181
+ withdrawals.length === 0
3182
+ ? '0'
3183
+ : `(tx_hash, log_idx) IN (${withdrawals.map(({ transactionHash, logIndex }) => `('${transactionHash}', ${logIndex})`).join(', ')})`
3076
3184
  const result = await tidx.fetch({
3077
3185
  engine: 'clickhouse',
3078
3186
  query: `
@@ -3168,6 +3276,7 @@ async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis
3168
3276
  AND "to" = '${options.account}'
3169
3277
  AND "from" != '${zeroAddress}'
3170
3278
  AND "from" != '${options.vault}'
3279
+ AND "from" != '${options.account}'
3171
3280
  AND block_num <= ${options.blockNumber}
3172
3281
  UNION ALL
3173
3282
  SELECT
@@ -3181,7 +3290,7 @@ async function getActiveCostBasis(tidx: Tidx.Client, options: getActiveCostBasis
3181
3290
  WHERE token = '${options.shareToken.toLowerCase()}'
3182
3291
  AND toUInt256(amount) > 0
3183
3292
  AND "from" = '${options.account}'
3184
- AND "to" != '${options.vault}'
3293
+ AND (${outgoing})
3185
3294
  AND block_num <= ${options.blockNumber}
3186
3295
  ) AS actions
3187
3296
  ORDER BY block_num, log_idx
@@ -3630,21 +3739,63 @@ export async function getVaultPosition(
3630
3739
  ): Promise<getVaultPosition.ReturnType> {
3631
3740
  const zone = c.get('zones').get(options.chainId)
3632
3741
  if (!zone) {
3633
- const block =
3634
- options.asOf === undefined
3635
- ? undefined
3636
- : await getIndexedBlockAtOrBefore(c.get('getTidx')(options.chainId), options.asOf)
3742
+ if (options.asOf === undefined) return readLivePosition(c, options)
3743
+ const block = await getIndexedBlockAtOrBefore(c.get('getTidx')(options.chainId), options.asOf)
3637
3744
  const position = await c
3638
3745
  .get('getClient')(options.chainId)
3639
3746
  .earn.getPosition({
3640
3747
  account: options.account,
3641
- ...(block ? { blockNumber: BigInt(block.number) } : {}),
3748
+ blockNumber: BigInt(block.number),
3642
3749
  vault: options.vault,
3643
3750
  })
3644
3751
  return { ...position, block, valueToken: position.assetToken }
3645
3752
  }
3646
3753
 
3647
- const route = await resolveZonePositionRoute(c, {
3754
+ const { blockNumber, discovery, position, sourceBlock } = await getZoneVaultPositionCore(
3755
+ c,
3756
+ options,
3757
+ )
3758
+ const privateAsset = await resolveZonePositionPrivateAsset(c, {
3759
+ chainId: options.chainId,
3760
+ discovery,
3761
+ vault: options.vault,
3762
+ }).catch((cause) => {
3763
+ recordZonePositionEnrichmentFailure(c, {
3764
+ cause,
3765
+ chainId: discovery.chainId,
3766
+ operation: 'resolvePrivateAsset',
3767
+ })
3768
+ return undefined
3769
+ })
3770
+ const privateAssetBalance =
3771
+ privateAsset && sourceBlock >= privateAsset.deploymentBlock
3772
+ ? await readZoneBalance(c.get('getClient')(options.chainId), {
3773
+ account: options.account,
3774
+ blockNumber,
3775
+ token: privateAsset.token,
3776
+ }).catch((cause) => {
3777
+ recordZonePositionEnrichmentFailure(c, {
3778
+ cause,
3779
+ chainId: options.chainId,
3780
+ operation: 'eth_call',
3781
+ })
3782
+ return undefined
3783
+ })
3784
+ : undefined
3785
+ return {
3786
+ ...position,
3787
+ ...(privateAssetBalance === undefined || privateAsset === undefined
3788
+ ? {}
3789
+ : { privateAssetBalance, privateAssetToken: privateAsset.token }),
3790
+ }
3791
+ }
3792
+
3793
+ /** Reads the on-chain Zone position without optional private-route enrichment. */
3794
+ async function getZoneVaultPositionCore(
3795
+ c: Context<App.Environment>,
3796
+ options: getVaultPosition.Options,
3797
+ ) {
3798
+ const core = await resolveZonePositionCore(c, {
3648
3799
  chainId: options.chainId,
3649
3800
  vault: options.vault,
3650
3801
  })
@@ -3658,44 +3809,168 @@ export async function getVaultPosition(
3658
3809
  readZoneBalance(zoneClient, {
3659
3810
  account: options.account,
3660
3811
  blockNumber,
3661
- token: route.privateAsset,
3812
+ token: core.vaultAsset,
3813
+ }).catch(async (cause) => {
3814
+ // The public vault asset may not be deployed on the private Zone.
3815
+ if (
3816
+ cause instanceof ContractFunctionExecutionError &&
3817
+ cause.walk((error) => error instanceof ContractFunctionZeroDataError)
3818
+ )
3819
+ return 0n
3820
+ const code = await zoneClient.getCode({ address: core.vaultAsset, blockNumber })
3821
+ if (!code || code === '0x') return 0n
3822
+ throw cause
3662
3823
  }),
3663
3824
  readZoneBalance(zoneClient, {
3664
3825
  account: options.account,
3665
3826
  blockNumber,
3666
- token: route.shareToken,
3827
+ token: core.shareToken,
3828
+ }).catch(async (cause) => {
3829
+ if (
3830
+ cause instanceof ContractFunctionExecutionError &&
3831
+ cause.walk((error) => error instanceof ContractFunctionZeroDataError)
3832
+ )
3833
+ throw new EarnVaults.NotFoundError()
3834
+ const code = await zoneClient.getCode({ address: core.shareToken, blockNumber })
3835
+ if (!code || code === '0x') throw new EarnVaults.NotFoundError()
3836
+ throw cause
3667
3837
  }),
3668
3838
  readZoneSourceBlock(c, {
3669
3839
  blockNumber,
3670
3840
  historical: block !== undefined,
3671
- portal: route.portal,
3672
- sourceChainId: route.sourceChainId,
3841
+ portal: core.portal,
3842
+ sourceChainId: core.sourceChainId,
3673
3843
  zoneClient,
3674
3844
  }),
3675
3845
  ])
3676
3846
  const sourceBlock = Value.toNumber(importedParentBlockNumber)
3677
- if (sourceBlock === undefined || sourceBlock < route.deploymentBlock)
3678
- throw new EarnVaults.NotFoundError()
3679
- const value = await c
3680
- .get('getClient')(route.sourceChainId)
3681
- .earn.getRedeemQuote({
3682
- blockNumber: BigInt(sourceBlock),
3683
- shareAmount: shareBalance,
3684
- vault: options.vault,
3685
- })
3847
+ if (sourceBlock === undefined) throw new EarnVaults.NotFoundError()
3848
+ const value = await quoteZonePosition(c.get('getClient')(core.sourceChainId), {
3849
+ blockNumber: BigInt(sourceBlock),
3850
+ shareAmount: shareBalance,
3851
+ vault: options.vault,
3852
+ })
3853
+ return {
3854
+ blockNumber,
3855
+ discovery: core.discovery,
3856
+ position: {
3857
+ assetAllowance: 0n,
3858
+ assetBalance,
3859
+ assetToken: core.vaultAsset,
3860
+ block,
3861
+ shareAllowance: 0n,
3862
+ shareBalance,
3863
+ shareToken: core.shareToken,
3864
+ value,
3865
+ valueToken: core.vaultAsset,
3866
+ },
3867
+ sourceBlock,
3868
+ }
3869
+ }
3870
+
3871
+ /** Quotes Zone shares only after the verified parent block contains the vault. */
3872
+ export async function quoteZonePosition(
3873
+ client: ReturnType<App.Environment['Variables']['getClient']>,
3874
+ options: quoteZonePosition.Options,
3875
+ ) {
3876
+ const code = await client.getCode({ address: options.vault, blockNumber: options.blockNumber })
3877
+ if (!code || code === '0x') throw new EarnVaults.NotFoundError()
3878
+ return client.earn.getRedeemQuote(options)
3879
+ }
3880
+
3881
+ export declare namespace quoteZonePosition {
3882
+ /** Aligned parent observation used to value Zone shares. */
3883
+ type Options = {
3884
+ /** Verified parent block imported by the Zone. */
3885
+ blockNumber: bigint
3886
+ /** Zone shares to quote. */
3887
+ shareAmount: bigint
3888
+ /** Public parent vault to quote. */
3889
+ vault: z.output<typeof Schema.Address>
3890
+ }
3891
+ }
3892
+
3893
+ /**
3894
+ * Reads a live direct-chain position in two RPC hops by caching the vault's
3895
+ * immutable token bindings, which otherwise cost a hop on every request.
3896
+ */
3897
+ async function readLivePosition(
3898
+ c: Context<App.Environment>,
3899
+ options: readLivePosition.Options,
3900
+ ): Promise<getVaultPosition.ReturnType> {
3901
+ const client = c.get('getClient')(options.chainId)
3902
+ const { asset, shareToken } = await resolveVaultBindings(c, options)
3903
+ const [assetAllowance, assetBalance, shareAllowance, shareBalance] = await client.multicall({
3904
+ allowFailure: false,
3905
+ contracts: [
3906
+ {
3907
+ abi: Abis.tip20,
3908
+ address: asset,
3909
+ args: [options.account, options.vault],
3910
+ functionName: 'allowance',
3911
+ },
3912
+ { abi: Abis.tip20, address: asset, args: [options.account], functionName: 'balanceOf' },
3913
+ {
3914
+ abi: Abis.tip20,
3915
+ address: shareToken,
3916
+ args: [options.account, options.vault],
3917
+ functionName: 'allowance',
3918
+ },
3919
+ { abi: Abis.tip20, address: shareToken, args: [options.account], functionName: 'balanceOf' },
3920
+ ],
3921
+ })
3922
+ const value = await client.earn.getRedeemQuote({
3923
+ shareAmount: shareBalance,
3924
+ vault: options.vault,
3925
+ })
3686
3926
  return {
3687
- assetAllowance: 0n,
3927
+ assetAllowance,
3688
3928
  assetBalance,
3689
- assetToken: route.privateAsset,
3690
- block,
3691
- shareAllowance: 0n,
3929
+ assetToken: asset,
3930
+ shareAllowance,
3692
3931
  shareBalance,
3693
- shareToken: route.shareToken,
3932
+ shareToken,
3694
3933
  value,
3695
- valueToken: route.vaultAsset,
3934
+ valueToken: asset,
3696
3935
  }
3697
3936
  }
3698
3937
 
3938
+ declare namespace readLivePosition {
3939
+ /** Account and direct-chain vault whose live position is read. */
3940
+ type Options = Pick<getVaultPosition.Options, 'account' | 'chainId' | 'vault'>
3941
+ }
3942
+
3943
+ /** Resolves a vault's asset and EarnShare addresses, cached because they never change after deployment. */
3944
+ async function resolveVaultBindings(
3945
+ c: Context<App.Environment>,
3946
+ options: resolveVaultBindings.Options,
3947
+ ) {
3948
+ return Store.memoize(
3949
+ async () => {
3950
+ const [asset, shareToken] = await c
3951
+ .get('getClient')(options.chainId)
3952
+ .multicall({
3953
+ allowFailure: false,
3954
+ contracts: [
3955
+ { abi: Abis.earnVault, address: options.vault, functionName: 'asset' },
3956
+ { abi: Abis.earnVault, address: options.vault, functionName: 'earnShare' },
3957
+ ],
3958
+ })
3959
+ return { asset, shareToken }
3960
+ },
3961
+ {
3962
+ key: `earn-vault-bindings:v1:${options.chainId}:${options.vault.toLowerCase()}`,
3963
+ store: c.get('store'),
3964
+ ttl: Ttl.hours(1),
3965
+ },
3966
+ )
3967
+ }
3968
+
3969
+ declare namespace resolveVaultBindings {
3970
+ /** Vault whose immutable token bindings are resolved. */
3971
+ type Options = Pick<getVaultPosition.Options, 'chainId' | 'vault'>
3972
+ }
3973
+
3699
3974
  export declare namespace getVaultPosition {
3700
3975
  /** Inputs selecting one direct or Zone-routed account position. */
3701
3976
  type Options = {
@@ -3708,6 +3983,10 @@ export declare namespace getVaultPosition {
3708
3983
  /** Normalized position state across a direct chain or private Zone. */
3709
3984
  type ReturnType = Actions.earn.getPosition.ReturnValue & {
3710
3985
  block?: { number: number; timestamp: string } | undefined
3986
+ /** Private route token balance, when Zone enrichment succeeds. */
3987
+ privateAssetBalance?: bigint | undefined
3988
+ /** Private route token address, when Zone enrichment succeeds. */
3989
+ privateAssetToken?: z.output<typeof Schema.Address> | undefined
3711
3990
  valueToken: z.output<typeof Schema.Address>
3712
3991
  }
3713
3992
  }
@@ -3797,60 +4076,47 @@ export declare namespace alignZoneSourceBlock {
3797
4076
  }
3798
4077
  }
3799
4078
 
3800
- /** Resolves the verified parent vault and token pair for one Zone route. */
3801
- async function resolveZonePositionRoute(
4079
+ /** Resolves the public parent vault and Zone checkpoint boundary. */
4080
+ async function resolveZonePositionCore(
3802
4081
  c: Context<App.Environment>,
3803
- options: resolveZonePositionRoute.Options,
3804
- ): Promise<resolveZonePositionRoute.ReturnType> {
4082
+ options: resolveZonePositionCore.Options,
4083
+ ): Promise<resolveZonePositionCore.ReturnType> {
3805
4084
  const zone = c.get('zones').get(options.chainId)
3806
4085
  if (!zone?.sourceId) throw new EarnVaults.NotFoundError()
3807
- const db = Db.get(c.get('dbCached'))
3808
- const record = await core_EarnVaults.get(db, {
3809
- chainId: zone.sourceId,
3810
- vaultAddress: options.vault,
3811
- })
3812
- const configured = record?.zones.find((route) => route.chainId === options.chainId)
3813
- if (!record || !configured) throw new EarnVaults.NotFoundError()
3814
4086
  const discovery = await resolveVaultDiscovery(c, {
3815
4087
  chainId: zone.sourceId,
3816
4088
  include: [],
3817
4089
  vaultAddress: options.vault,
4090
+ }).catch((cause) => {
4091
+ if (isIncompatible(cause)) throw new EarnVaults.NotFoundError()
4092
+ throw cause
3818
4093
  })
3819
- const [route] = await EarnVaults.resolveZoneRoutes({
3820
- discovery,
3821
- getClient: c.get('getClient'),
3822
- routes: [configured],
3823
- zones: [...c.get('zones').values()],
3824
- })
3825
- const privateAsset = route?.inputTokens[0]
3826
4094
  const portalContract = zone.contracts?.['portal']
3827
4095
  const portal = Schema.Address.safeParse(
3828
4096
  portalContract && 'address' in portalContract
3829
4097
  ? portalContract.address
3830
4098
  : portalContract?.[zone.sourceId]?.address,
3831
4099
  )
3832
- if (!route || !privateAsset || !portal.success) throw new EarnVaults.NotFoundError()
4100
+ if (!portal.success) throw new EarnVaults.NotFoundError()
3833
4101
  return {
3834
- deploymentBlock: route.deploymentBlock,
4102
+ discovery,
3835
4103
  portal: portal.data,
3836
- privateAsset,
3837
4104
  shareToken: discovery.shareToken.address,
3838
4105
  sourceChainId: zone.sourceId,
3839
4106
  vaultAsset: discovery.assetToken.address,
3840
4107
  }
3841
4108
  }
3842
4109
 
3843
- declare namespace resolveZonePositionRoute {
3844
- /** Zone and parent vault selecting one curated route. */
4110
+ declare namespace resolveZonePositionCore {
4111
+ /** Zone and public parent vault selecting one position. */
3845
4112
  type Options = {
3846
4113
  chainId: z.output<typeof Schema.ChainId>
3847
4114
  vault: z.output<typeof Schema.Address>
3848
4115
  }
3849
4116
 
3850
- /** Verified addresses needed to read and value a Zone position. */
4117
+ /** Public addresses and checkpoint boundary needed to read and value a Zone position. */
3851
4118
  type ReturnType = {
3852
- deploymentBlock: number
3853
- privateAsset: z.output<typeof Schema.Address>
4119
+ discovery: EarnVaults.Discovery
3854
4120
  portal: z.output<typeof Schema.Address>
3855
4121
  shareToken: z.output<typeof Schema.Address>
3856
4122
  sourceChainId: number
@@ -3858,6 +4124,69 @@ declare namespace resolveZonePositionRoute {
3858
4124
  }
3859
4125
  }
3860
4126
 
4127
+ /** Resolves an optional validated private asset from the Admin Zone route. */
4128
+ async function resolveZonePositionPrivateAsset(
4129
+ c: Context<App.Environment>,
4130
+ options: resolveZonePositionPrivateAsset.Options,
4131
+ ) {
4132
+ const record = await core_EarnVaults.get(Db.get(c.get('dbCached')), {
4133
+ chainId: options.discovery.chainId,
4134
+ vaultAddress: options.vault,
4135
+ })
4136
+ const configured = record?.zones.find((route) => route.chainId === options.chainId)
4137
+ if (!configured) return undefined
4138
+ const [route] = await EarnVaults.resolveZoneRoutes({
4139
+ discovery: options.discovery,
4140
+ getClient: c.get('getClient'),
4141
+ routes: [configured],
4142
+ zones: [...c.get('zones').values()],
4143
+ })
4144
+ const token = route?.inputTokens[0]
4145
+ return token ? { deploymentBlock: route.deploymentBlock, token } : undefined
4146
+ }
4147
+
4148
+ declare namespace resolveZonePositionPrivateAsset {
4149
+ /** Curated route to validate for optional Zone enrichment. */
4150
+ type Options = {
4151
+ /** Private Zone containing the route. */
4152
+ chainId: z.output<typeof Schema.ChainId>
4153
+ /** Public vault bindings used to validate the route. */
4154
+ discovery: EarnVaults.Discovery
4155
+ /** Public parent vault address. */
4156
+ vault: z.output<typeof Schema.Address>
4157
+ }
4158
+ }
4159
+
4160
+ /** Records a bounded dependency signal without failing the core Zone position. */
4161
+ function recordZonePositionEnrichmentFailure(
4162
+ c: Context<App.Environment>,
4163
+ options: recordZonePositionEnrichmentFailure.Options,
4164
+ ) {
4165
+ Cache.setPolicy(c, Cache.policies.noStore)
4166
+ const rpc = Viem.requestFailure(options.cause)
4167
+ const failure: Log.ProviderFailure = rpc
4168
+ ? { ...rpc, chainId: options.chainId, id: 'rpc', operation: options.operation }
4169
+ : {
4170
+ chainId: options.chainId,
4171
+ failure: 'unknown',
4172
+ id: 'earn-zone-position',
4173
+ operation: options.operation,
4174
+ }
4175
+ c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure])
4176
+ }
4177
+
4178
+ declare namespace recordZonePositionEnrichmentFailure {
4179
+ /** Dependency failure and bounded operation label for request logging. */
4180
+ type Options = {
4181
+ /** Dependency error to classify and redact. */
4182
+ cause: unknown
4183
+ /** Chain associated with the failed dependency. */
4184
+ chainId: number
4185
+ /** Logical operation that failed. */
4186
+ operation: 'eth_call' | 'resolvePrivateAsset'
4187
+ }
4188
+ }
4189
+
3861
4190
  /** Lists every vault where an account holds earn shares, ordered by vault address. */
3862
4191
  export async function listPositions(c: Context<App.Environment>, options: listPositions.Options) {
3863
4192
  const denomination = options['valuation.currency']
@@ -3866,15 +4195,7 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
3866
4195
  const sourceChainId = zone ? zone.sourceId : options.chainId
3867
4196
  if (sourceChainId === undefined) throw new EarnVaults.NotFoundError()
3868
4197
  const db = Db.get(c.get('dbCached'))
3869
- const recordsPromise = core_EarnVaults
3870
- .list(db, { chainId: sourceChainId })
3871
- .then((records) =>
3872
- zone
3873
- ? records.filter((record) =>
3874
- record.zones.some((route) => route.chainId === options.chainId),
3875
- )
3876
- : records,
3877
- )
4198
+ const recordsPromise = core_EarnVaults.list(db, { chainId: sourceChainId })
3878
4199
  // The verified page needs no index: the registry is the candidate set.
3879
4200
  const heldPromise =
3880
4201
  options.verified || zone
@@ -3918,11 +4239,14 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
3918
4239
  batch.map(async (vault) => {
3919
4240
  const record = registry.get(vault)
3920
4241
  try {
3921
- const position = await getVaultPosition(c, {
4242
+ const input = {
3922
4243
  account: options.address,
3923
4244
  chainId: options.chainId,
3924
4245
  vault: Schema.Address.parse(vault),
3925
- })
4246
+ }
4247
+ const position = zone
4248
+ ? (await getZoneVaultPositionCore(c, input)).position
4249
+ : await getVaultPosition(c, input)
3926
4250
  return { position, record, vaultAddress: vault }
3927
4251
  } catch (cause) {
3928
4252
  if (cause instanceof EarnVaults.NotFoundError) return undefined
@@ -3945,15 +4269,48 @@ export async function listPositions(c: Context<App.Environment>, options: listPo
3945
4269
  : undefined
3946
4270
  const [cashFlows, tokens, valueTokens, snapshot] = await Promise.all([
3947
4271
  indexedBlock
3948
- ? getVaultLifetimeCashFlows(c.get('getTidx')(options.chainId), {
3949
- account: options.address,
3950
- blockNumber: indexedBlock.number,
3951
- vaults: page.map(({ vaultAddress }) => Schema.Address.parse(vaultAddress)),
3952
- })
4272
+ ? (async () => {
4273
+ const tidx = c.get('getTidx')(options.chainId)
4274
+ const flows = await getVaultLifetimeCashFlows(tidx, {
4275
+ account: options.address,
4276
+ blockNumber: indexedBlock.number,
4277
+ vaults: page.map(({ vaultAddress }) => Schema.Address.parse(vaultAddress)),
4278
+ })
4279
+ for (const { position, vaultAddress } of page) {
4280
+ const flow = flows.get(vaultAddress)
4281
+ if (flow?.status !== 'complete') continue
4282
+ const vault = Schema.Address.parse(vaultAddress)
4283
+ const withdrawals = await EarnWithdrawals.read(tidx, {
4284
+ account: options.address,
4285
+ blockNumber: indexedBlock.number,
4286
+ shareToken: position.shareToken,
4287
+ startBlockNumber: beforeFirstBlockNumber,
4288
+ vault,
4289
+ })
4290
+ const withdrawn = await EarnWithdrawals.value(c.get('getClient')(options.chainId), {
4291
+ vault,
4292
+ withdrawals,
4293
+ })
4294
+ flows.set(
4295
+ vaultAddress,
4296
+ withdrawn === undefined
4297
+ ? { status: 'incomplete_history' }
4298
+ : {
4299
+ ...flow,
4300
+ totalWithdrawn: (BigInt(flow.totalWithdrawn) + withdrawn).toString(),
4301
+ },
4302
+ )
4303
+ }
4304
+ return flows
4305
+ })()
3953
4306
  : undefined,
3954
4307
  (async () => {
3955
4308
  const addresses = [
3956
- ...new Set(page.flatMap(({ position }) => [position.assetToken, position.shareToken])),
4309
+ ...new Set(
4310
+ page.flatMap(({ position }) =>
4311
+ zone ? [position.shareToken] : [position.assetToken, position.shareToken],
4312
+ ),
4313
+ ),
3957
4314
  ]
3958
4315
  const groups: Tokens.resolveTokens.ReturnType[] = []
3959
4316
  for (let index = 0; index < addresses.length; index += tokenReadChunkSize)
@@ -4088,7 +4445,7 @@ declare namespace queryHeldVaults {
4088
4445
  /** Serializes one live position into the address-scoped row contract. */
4089
4446
  function serializePosition(options: serializePosition.Options) {
4090
4447
  const { position, tokens } = options
4091
- const assetToken = getToken(tokens, position.assetToken)
4448
+ const assetToken = getToken(options.valueTokens ?? tokens, position.assetToken)
4092
4449
  const shareToken = getToken(tokens, position.shareToken)
4093
4450
  const valueToken = getToken(options.valueTokens ?? tokens, position.valueToken)
4094
4451
  const vaultAddress = Schema.Address.parse(options.vaultAddress.toLowerCase())
@@ -4437,6 +4794,7 @@ async function readVaultDiscovery(
4437
4794
  return Timing.time(c, 'earn_vault_discovery', () =>
4438
4795
  EarnVaults.resolve({
4439
4796
  getClient: c.get('getClient'),
4797
+ hints: c.get('store'),
4440
4798
  include: options.include,
4441
4799
  input: {
4442
4800
  chainId: options.chainId,
@@ -4523,80 +4881,78 @@ async function resolvePositionApy(
4523
4881
  c.set('providerFailures', [...(c.get('providerFailures') ?? []), failure])
4524
4882
  }
4525
4883
  const rateFailures: Log.ProviderFailure[] = []
4526
- const [rates, discovery] = await Promise.all([
4527
- Timing.time(c, 'earn_apy', () =>
4528
- EarnRates.resolve({
4529
- chainId: sourceChainId,
4530
- getClient: c.get('getClient'),
4531
- getTidx: c.get('getTidx'),
4532
- onFailure: (failure) => {
4533
- rateFailures.push({ ...failure, chainId: sourceChainId })
4534
- },
4535
- store: c.get('store'),
4536
- vaults: [options.vault],
4537
- }),
4538
- ).catch(() => {
4539
- rateFailures.push({
4540
- chainId: sourceChainId,
4541
- failure: 'unknown',
4542
- id: 'earn-apy',
4543
- operation: 'resolve',
4544
- })
4545
- return undefined
4546
- }),
4547
- resolveVaultDiscovery(c, {
4884
+ const rates_pending = Timing.time(c, 'earn_apy', () =>
4885
+ EarnRates.resolve({
4548
4886
  chainId: sourceChainId,
4549
- include: [],
4550
- vaultAddress: options.vault,
4551
- }).catch((cause) => {
4552
- const failure = Viem.requestFailure(cause)
4553
- recordFailure(
4554
- failure
4555
- ? { ...failure, chainId: sourceChainId, id: 'rpc', operation: 'eth_call' }
4556
- : {
4557
- chainId: sourceChainId,
4558
- failure: 'unknown',
4559
- id: 'earn-vaults',
4560
- operation: 'getVault',
4561
- },
4562
- )
4563
- return undefined
4887
+ getClient: c.get('getClient'),
4888
+ getTidx: c.get('getTidx'),
4889
+ onFailure: (failure) => {
4890
+ rateFailures.push({ ...failure, chainId: sourceChainId })
4891
+ },
4892
+ store: c.get('store'),
4893
+ vaults: [options.vault],
4564
4894
  }),
4565
- ])
4566
- const base = rates?.get(options.vault.toLowerCase())
4567
- const rateFailure = rateFailures[0]
4568
- if (rateFailure) recordFailure(rateFailure)
4569
- if (!base || !discovery) return null
4570
- return await Timing.time(c, 'earn_rewards_apy', async () => {
4571
- const [earnFees, record] = await Promise.all([
4572
- c.get('getClient')(sourceChainId).readContract({
4573
- abi: Abis.earnVault,
4574
- address: options.vault,
4575
- functionName: 'earnFees',
4576
- }),
4577
- core_EarnVaults.get(Db.get(c.get('db')), {
4895
+ ).catch(() => {
4896
+ rateFailures.push({
4897
+ chainId: sourceChainId,
4898
+ failure: 'unknown',
4899
+ id: 'earn-apy',
4900
+ operation: 'resolve',
4901
+ })
4902
+ return undefined
4903
+ })
4904
+ // Vault facts and the registry row depend only on the vault, so they load
4905
+ // alongside the rate read rather than after it.
4906
+ const vault_pending = Timing.time(c, 'earn_vault_facts', () =>
4907
+ Promise.all([
4908
+ resolveVaultApyFacts(c, { chainId: sourceChainId, vault: options.vault }),
4909
+ core_EarnVaults.get(Db.get(c.get('dbCached')), {
4578
4910
  chainId: options.chainId,
4579
4911
  vaultAddress: options.vault,
4580
4912
  }),
4581
- ])
4913
+ ]),
4914
+ ).catch((cause: unknown) => {
4915
+ const failure = Viem.requestFailure(cause)
4916
+ recordFailure(
4917
+ failure
4918
+ ? { ...failure, chainId: sourceChainId, id: 'rpc', operation: 'eth_call' }
4919
+ : (sharePriceProviderFailure({ cause, chainId: sourceChainId }) ?? {
4920
+ chainId: options.chainId,
4921
+ failure: 'unknown',
4922
+ id: 'earn-rewards',
4923
+ operation: 'getPositionApy',
4924
+ }),
4925
+ )
4926
+ return undefined
4927
+ })
4928
+ // The handler surfaces a failed position read; here it only ends enrichment.
4929
+ const position = await options.position.catch(() => undefined)
4930
+ const [rates, vault] = await Promise.all([rates_pending, vault_pending])
4931
+ const base = rates?.get(options.vault.toLowerCase())
4932
+ const rateFailure = rateFailures[0]
4933
+ if (rateFailure) recordFailure(rateFailure)
4934
+ if (!base || !vault || !position) return null
4935
+ const [facts, record] = vault
4936
+ return await Timing.time(c, 'earn_rewards_apy', () => {
4582
4937
  // Accounting retains qualified shares for excluded infrastructure, so apply its current exclusions here too.
4583
4938
  const zoneContracts = [...c.get('zones').values()]
4584
4939
  .filter((zone) => zone.sourceId === options.chainId)
4585
4940
  .flatMap((zone) => positionApyContractAddresses(zone.contracts))
4941
+ // Registration must show on the next read, so reward rows stay on the primary.
4586
4942
  return RewardRead.positionApy({
4587
- assetDecimals: discovery.assetToken.decimals,
4943
+ assetDecimals: facts.assetDecimals,
4588
4944
  baseNet: base.net,
4589
4945
  chainId: options.chainId,
4590
4946
  db: c.get('db'),
4591
4947
  excludedAddresses: [
4592
- discovery.engine.address,
4593
- earnFees,
4948
+ facts.engine,
4949
+ facts.earnFees,
4594
4950
  ...(record?.zones.map((zone) => zone.earnRouter) ?? []),
4595
4951
  ...zoneContracts,
4596
4952
  ],
4597
4953
  recipient: options.recipient,
4598
- shareBalance: options.shareBalance.toString(),
4599
- value: options.value.toString(),
4954
+ shareBalance: position.shareBalance.toString(),
4955
+ value: position.value.toString(),
4600
4956
  vaultAddress: options.vault,
4601
4957
  })
4602
4958
  }).catch((cause) => {
@@ -4612,17 +4968,51 @@ async function resolvePositionApy(
4612
4968
  })
4613
4969
  }
4614
4970
 
4971
+ /**
4972
+ * Resolves the vault facts wallet APY needs (engine, fee sink, asset decimals)
4973
+ * in one cached hop; full discovery costs several and serves no other field.
4974
+ */
4975
+ async function resolveVaultApyFacts(
4976
+ c: Context<App.Environment>,
4977
+ options: resolveVaultApyFacts.Options,
4978
+ ) {
4979
+ return Store.memoize(
4980
+ async () => {
4981
+ const client = c.get('getClient')(options.chainId)
4982
+ const { asset } = await resolveVaultBindings(c, options)
4983
+ const [assetDecimals, earnFees, engine] = await client.multicall({
4984
+ allowFailure: false,
4985
+ contracts: [
4986
+ { abi: Abis.tip20, address: asset, functionName: 'decimals' },
4987
+ { abi: Abis.earnVault, address: options.vault, functionName: 'earnFees' },
4988
+ { abi: Abis.earnVault, address: options.vault, functionName: 'engine' },
4989
+ ],
4990
+ })
4991
+ return { assetDecimals, earnFees, engine }
4992
+ },
4993
+ {
4994
+ key: `earn-vault-apy-facts:v1:${options.chainId}:${options.vault.toLowerCase()}`,
4995
+ store: c.get('store'),
4996
+ // Matches the rate bucket so a migrated engine reappears with the reset rate.
4997
+ ttl: Ttl.minutes(15),
4998
+ },
4999
+ )
5000
+ }
5001
+
5002
+ declare namespace resolveVaultApyFacts {
5003
+ /** Vault whose engine, fee sink, and asset decimals are resolved. */
5004
+ type Options = Pick<getVaultPosition.Options, 'chainId' | 'vault'>
5005
+ }
5006
+
4615
5007
  declare namespace resolvePositionApy {
4616
- /** Current wallet position used to resolve its effective APY. */
5008
+ /** Wallet and vault whose effective APY is resolved alongside a live position read. */
4617
5009
  type Options = {
4618
5010
  /** Chain containing the vault position. */
4619
5011
  chainId: z.output<typeof Schema.ChainId>
5012
+ /** In-flight live position supplying the EarnShare balance and asset value. */
5013
+ position: Promise<getVaultPosition.ReturnType>
4620
5014
  /** Wallet receiving the position yield. */
4621
5015
  recipient: z.output<typeof Schema.Address>
4622
- /** Current EarnShare balance. */
4623
- shareBalance: bigint
4624
- /** Current asset value of the position. */
4625
- value: bigint
4626
5016
  /** EarnVault containing the position. */
4627
5017
  vault: z.output<typeof Schema.Address>
4628
5018
  }