tapimo 0.15.1 → 0.18.1

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
package/src/db/Db.test.ts CHANGED
@@ -4,16 +4,26 @@ import * as pg from 'pg'
4
4
 
5
5
  import * as Runtime from '../../test/runtime.js'
6
6
  import * as TestRoutes from '../../test/Routes.js'
7
+ import * as ManagementWebhooks from '../apps/management/routes/webhooks.js'
8
+ import type * as Campaigns from '../internal/rewards/Campaigns.js'
9
+ import * as DepositAddress from '../internal/routes/DepositAddress.js'
7
10
  import * as Transfer from '../internal/routes/Transfer.js'
11
+ import * as EarnVaults from './tables/earnVaults.js'
12
+ import * as RewardAccounts from './tables/rewardAccounts.js'
13
+ import * as RewardCampaigns from './tables/rewardCampaigns.js'
14
+ import * as RewardRuns from './tables/rewardRuns.js'
15
+ import * as RoutesDepositAddresses from './tables/routesDepositAddresses.js'
8
16
  import * as RoutesTransferTransactions from './tables/routesTransferTransactions.js'
9
17
  import * as RoutesTransfers from './tables/routesTransfers.js'
10
18
  import * as RoutesTransferSubsidies from './tables/routesTransferSubsidies.js'
11
19
  import * as Db from './Db.js'
20
+ import * as VerifiedTokens from './tables/verifiedTokens.js'
12
21
  import * as Webhooks from '../internal/Webhooks.js'
13
22
  import * as Invitations from './tables/invitations.js'
14
23
  import * as ApiKeyOwnerTombstones from './tables/apiKeyOwnerTombstones.js'
15
24
  import * as Organizations from './tables/organizations.js'
16
25
  import * as Projects from './tables/projects.js'
26
+ import * as RoutesPolicies from './tables/routesPolicies.js'
17
27
  import * as WebhookSubscriptions from './tables/webhookSubscriptions.js'
18
28
 
19
29
  const create = () => Db.postgres({ connectionString: Runtime.postgresUrl, schema: `t_${nanoid()}` })
@@ -27,6 +37,599 @@ describe('postgres', () => {
27
37
  await db.close()
28
38
  })
29
39
 
40
+ test.each(['targetYield', 'boostRewards', 'both'] as const)(
41
+ 'behavior: extends d730 %s rewards without resetting accounting',
42
+ async (capability) => {
43
+ const db = create()
44
+ try {
45
+ await db.migrate()
46
+ const config = rewardExtensionConfig()
47
+ if (capability === 'targetYield') delete config.boostRewards
48
+ if (capability === 'boostRewards') delete config.targetYield
49
+ const campaign = await seedRewardExtension(db, { config })
50
+ const controls = [
51
+ await seedRewardExtension(db, { chainId: 42431, config }),
52
+ await seedRewardExtension(db, { config, vaultAddress: `0x${'ab'.repeat(20)}` }),
53
+ ]
54
+ const schedule = config.targetYield ?? config.boostRewards!
55
+ const run = await RewardRuns.ensure(db, {
56
+ ...campaign,
57
+ endsAt: schedule.endTimestamp,
58
+ startsAfter: schedule.startTimestamp,
59
+ })
60
+ await RewardRuns.transition(db, {
61
+ fence: run.fence,
62
+ id: run.id,
63
+ patch: {},
64
+ phase: 'delivered',
65
+ })
66
+ await RewardCampaigns.advance(db, {
67
+ ...campaign,
68
+ deliveredThrough: schedule.endTimestamp,
69
+ eventCursor: { blockNumber: 1234, logIndex: 7, transactionIndex: 2 },
70
+ expectedDeliveredThrough: schedule.startTimestamp,
71
+ })
72
+ await RewardAccounts.replace(db, {
73
+ ...campaign,
74
+ accounts: [
75
+ {
76
+ accrualRemainder: '17',
77
+ allocatedPrincipalAssets: '25000000',
78
+ cumulativeEntitlement: '900',
79
+ cumulativePaid: '700',
80
+ deferral: 'below minimum',
81
+ eligibilityRegisteredAt: '2026-09-01T00:00:00.000Z',
82
+ lots: [],
83
+ pendingRewardAssets: '23',
84
+ publicEarnShares: '30000000000000000000',
85
+ qualifiedEarnShares: '25000000000000000000',
86
+ recipient: `0x${'cd'.repeat(20)}`,
87
+ registrationOrder: '3',
88
+ updatedAt: '2026-09-30T12:00:00.000Z',
89
+ },
90
+ ],
91
+ })
92
+ const before = await RewardCampaigns.get(db, campaign)
93
+ const accounts = await RewardAccounts.list(db, campaign)
94
+ const runs = await db.kysely.selectFrom('reward_runs').selectAll().execute()
95
+ const through = Date.parse('2026-10-01T17:00:00Z') / 1_000
96
+ expect(
97
+ (await RewardCampaigns.listDue(db, { limit: 10, through })).some(
98
+ (entry) =>
99
+ entry.chainId === campaign.chainId && entry.vaultAddress === campaign.vaultAddress,
100
+ ),
101
+ ).toBe(false)
102
+
103
+ await replayRewardExtension(db)
104
+ const updated = await RewardCampaigns.get(db, campaign)
105
+ const endTimestamp = Date.parse('2026-12-17T12:00:00-05:00') / 1_000
106
+ expect(updated).toEqual({
107
+ ...before,
108
+ config: {
109
+ ...(config.boostRewards
110
+ ? { boostRewards: { ...config.boostRewards, endTimestamp } }
111
+ : {}),
112
+ ...(config.targetYield ? { targetYield: { ...config.targetYield, endTimestamp } } : {}),
113
+ },
114
+ updatedAt: expect.any(String),
115
+ })
116
+ expect(await RewardAccounts.list(db, campaign)).toEqual(accounts)
117
+ expect(await db.kysely.selectFrom('reward_runs').selectAll().execute()).toEqual(runs)
118
+ for (const control of controls)
119
+ expect(await RewardCampaigns.get(db, control)).toEqual(control)
120
+ expect(await RewardCampaigns.listDue(db, { limit: 10, through })).toContainEqual(updated)
121
+
122
+ await replayRewardExtension(db)
123
+ await db.migrate()
124
+ expect(await RewardCampaigns.get(db, campaign)).toEqual(updated)
125
+ } finally {
126
+ await db.close()
127
+ }
128
+ },
129
+ )
130
+
131
+ test.each(['pending', 'indexing', 'paying', 'failed', 'delivered'] as const)(
132
+ 'behavior: refuses d730 extension with unresolved %s work',
133
+ async (state) => {
134
+ const db = create()
135
+ try {
136
+ await db.migrate()
137
+ const campaign = await seedRewardExtension(db, { config: rewardExtensionConfig() })
138
+ const schedule = campaign.config.boostRewards!
139
+ if (state === 'pending')
140
+ await RewardCampaigns.upsert(db, {
141
+ ...campaign,
142
+ config: { boostRewards: { ...schedule, targetAnnualRateBps: 800 } },
143
+ now: schedule.startTimestamp + 1,
144
+ })
145
+ else {
146
+ const run = await RewardRuns.ensure(db, {
147
+ ...campaign,
148
+ endsAt: schedule.endTimestamp,
149
+ startsAfter: schedule.startTimestamp,
150
+ })
151
+ await RewardRuns.transition(db, { fence: run.fence, id: run.id, patch: {}, phase: state })
152
+ }
153
+ const before = await RewardCampaigns.get(db, campaign)
154
+ await expect(replayRewardExtension(db)).rejects.toThrow(
155
+ state === 'pending'
156
+ ? 'resolve the pending configuration'
157
+ : 'finish outstanding reward runs',
158
+ )
159
+ expect(await RewardCampaigns.get(db, campaign)).toEqual(before)
160
+ expect(
161
+ await db.kysely
162
+ .selectFrom('migrations')
163
+ .select('name')
164
+ .where('name', '=', '0302_extend_d730_reward_campaign')
165
+ .execute(),
166
+ ).toEqual([])
167
+ } finally {
168
+ await db.close()
169
+ }
170
+ },
171
+ )
172
+
173
+ test('behavior: d730 extension preserves later end dates and operational pause', async () => {
174
+ const db = create()
175
+ try {
176
+ await db.migrate()
177
+ const config = rewardExtensionConfig()
178
+ config.targetYield!.endTimestamp = Date.parse('2027-01-01T00:00:00Z') / 1_000
179
+ const campaign = await seedRewardExtension(db, { config })
180
+ await RewardCampaigns.setPaused(db, { ...campaign, paused: true })
181
+ await replayRewardExtension(db)
182
+ expect(await RewardCampaigns.get(db, campaign)).toEqual({
183
+ ...campaign,
184
+ config: {
185
+ ...config,
186
+ boostRewards: {
187
+ ...config.boostRewards,
188
+ endTimestamp: Date.parse('2026-12-17T17:00:00Z') / 1_000,
189
+ },
190
+ },
191
+ paused: true,
192
+ updatedAt: expect.any(String),
193
+ })
194
+ expect(await RewardCampaigns.listDue(db, { limit: 10, through: 1_800_000_000 })).toEqual([])
195
+ } finally {
196
+ await db.close()
197
+ }
198
+ })
199
+
200
+ test('behavior: each preview schema receives the subsidy status constraint', async () => {
201
+ const schemas = [`t_${nanoid()}`, `t_${nanoid()}`]
202
+ const dbs = schemas.map((schema) =>
203
+ Db.postgres({ connectionString: Runtime.postgresUrl, schema }),
204
+ )
205
+ try {
206
+ for (const db of dbs) await db.migrate()
207
+ for (const schema of schemas) {
208
+ const result = await sql<{ exists: boolean }>`
209
+ SELECT EXISTS (
210
+ SELECT 1 FROM pg_constraint AS c
211
+ JOIN pg_class AS t ON t.oid = c.conrelid
212
+ JOIN pg_namespace AS n ON n.oid = t.relnamespace
213
+ WHERE c.conname = 'routes_transfer_subsidies_status_check'
214
+ AND t.relname = 'routes_transfer_subsidies'
215
+ AND n.nspname = ${schema}
216
+ ) AS exists
217
+ `.execute(dbs[0]!.kysely)
218
+ expect(result.rows[0]?.exists).toBe(true)
219
+ }
220
+ } finally {
221
+ for (const db of dbs) await db.close()
222
+ }
223
+ })
224
+
225
+ test.each([
226
+ { chainId: 4217, migration: '0299_verified_tokens_ousd', version: 'existing_0299_ousd' },
227
+ {
228
+ chainId: 42431,
229
+ migration: '0301_verified_tokens_ousd_testnet',
230
+ version: 'existing_0301_ousd',
231
+ },
232
+ ])('behavior: publishes OUSD into an existing $chainId verified-token list', async (options) => {
233
+ const db = create()
234
+ try {
235
+ await db.migrate()
236
+ await db.kysely
237
+ .insertInto('verified_token_lists')
238
+ .values({
239
+ chainId: options.chainId,
240
+ updatedAt: '2026-09-22T00:00:00.000Z',
241
+ version: 'existing',
242
+ })
243
+ .execute()
244
+ await db.kysely
245
+ .insertInto('verified_tokens')
246
+ .values({
247
+ address: '0x20c0000000000000000000000000000000000000',
248
+ chainId: options.chainId,
249
+ currency: 'USD',
250
+ decimals: 6,
251
+ logoUri: null,
252
+ name: 'PathUSD',
253
+ position: 0,
254
+ symbol: 'pathUSD',
255
+ })
256
+ .execute()
257
+
258
+ const migration = Db.migrations.find((candidate) => candidate.name === options.migration)!
259
+ const startedAt = await sql<{ value: Date }>`SELECT clock_timestamp() AS value`.execute(
260
+ db.kysely,
261
+ )
262
+ await migration.up(db.kysely).execute()
263
+ const list = await db.kysely
264
+ .selectFrom('verified_token_lists')
265
+ .selectAll()
266
+ .where('chainId', '=', String(options.chainId))
267
+ .executeTakeFirstOrThrow()
268
+ await migration.up(db.kysely).execute()
269
+
270
+ expect(
271
+ await db.kysely
272
+ .selectFrom('verified_tokens')
273
+ .selectAll()
274
+ .where('chainId', '=', String(options.chainId))
275
+ .orderBy('position')
276
+ .execute(),
277
+ ).toMatchObject([
278
+ { address: '0x20c0000000000000000000000000000000000000', position: 0 },
279
+ {
280
+ address: '0x20c0000000000000000000006a37da5c996874be',
281
+ currency: 'USD',
282
+ decimals: 6,
283
+ name: 'OpenUSD',
284
+ position: 1,
285
+ symbol: 'OUSD',
286
+ },
287
+ ])
288
+ const replayed = await db.kysely
289
+ .selectFrom('verified_token_lists')
290
+ .selectAll()
291
+ .where('chainId', '=', String(options.chainId))
292
+ .executeTakeFirstOrThrow()
293
+ const finishedAt = await sql<{ value: Date }>`SELECT clock_timestamp() AS value`.execute(
294
+ db.kysely,
295
+ )
296
+ expect(replayed).toEqual(list)
297
+ expect(new Date(list.updatedAt).getTime()).toBeGreaterThanOrEqual(
298
+ startedAt.rows[0]!.value.getTime(),
299
+ )
300
+ expect(new Date(list.updatedAt).getTime()).toBeLessThanOrEqual(
301
+ finishedAt.rows[0]!.value.getTime(),
302
+ )
303
+ await expect(
304
+ db.kysely
305
+ .selectFrom('verified_token_lists')
306
+ .select('version')
307
+ .where('chainId', '=', String(options.chainId))
308
+ .executeTakeFirstOrThrow(),
309
+ ).resolves.toEqual({ version: options.version })
310
+ } finally {
311
+ await db.close()
312
+ }
313
+ })
314
+
315
+ test('behavior: serializes the OUSD migration with verified-token publishers', async () => {
316
+ const schema = `t_${nanoid()}`
317
+ const database = () => Db.postgres({ connectionString: Runtime.postgresUrl, schema })
318
+ const db = database()
319
+ const migrationDb = database()
320
+ const observerDb = database()
321
+ try {
322
+ await db.migrate()
323
+ const locked = Promise.withResolvers<void>()
324
+ const release = Promise.withResolvers<void>()
325
+ const publication = db.transaction(async (tx) => {
326
+ await sql`SELECT pg_advisory_xact_lock(1987342187, 4217)`.execute(tx.kysely)
327
+ locked.resolve()
328
+ await release.promise
329
+ await VerifiedTokens.publish(tx, 4217, {
330
+ tokens: [
331
+ {
332
+ address: '0x20c0000000000000000000000000000000000001',
333
+ currency: 'USD',
334
+ decimals: 6,
335
+ name: 'Published USD',
336
+ symbol: 'pUSD',
337
+ },
338
+ ],
339
+ updatedAt: '2026-09-27T00:00:00.000Z',
340
+ version: 'published',
341
+ })
342
+ })
343
+ await locked.promise
344
+
345
+ const migration = Db.migrations.find(
346
+ (candidate) => candidate.name === '0299_verified_tokens_ousd',
347
+ )!
348
+ const migrated = migrationDb.transaction(async (tx) => {
349
+ await sql`SELECT set_config('search_path', quote_ident(${schema}), true)`.execute(tx.kysely)
350
+ await migration.up(tx.kysely).execute()
351
+ })
352
+ try {
353
+ await expect
354
+ .poll(async () => {
355
+ const { rows } = await sql<{ waiting: boolean }>`SELECT EXISTS (
356
+ SELECT 1 FROM pg_locks
357
+ WHERE locktype = 'advisory'
358
+ AND classid = 1987342187
359
+ AND objid = 4217
360
+ AND NOT granted
361
+ ) AS waiting`.execute(observerDb.kysely)
362
+ return rows[0]!.waiting
363
+ })
364
+ .toBe(true)
365
+ } finally {
366
+ release.resolve()
367
+ }
368
+ await publication
369
+ await migrated
370
+
371
+ await expect(VerifiedTokens.list(db, 4217)).resolves.toMatchObject([
372
+ { symbol: 'pUSD' },
373
+ { address: '0x20c0000000000000000000006a37da5c996874be', symbol: 'OUSD' },
374
+ ])
375
+ } finally {
376
+ await db.close()
377
+ await migrationDb.close()
378
+ await observerDb.close()
379
+ }
380
+ })
381
+
382
+ test('behavior: migrates legacy funding webhook event types without changing subscription state', async () => {
383
+ const db = create()
384
+ try {
385
+ await db.migrate()
386
+ const owner = { orgId: 'org_legacy_webhooks', type: 'api_key' } as const
387
+ for (const eventType of ['routes:deposit.updated', 'routes:transfer.updated'] as const) {
388
+ for (const status of ['active', 'paused', 'disabled'] as const) {
389
+ const subscription = await Webhooks.createSubscription(
390
+ db,
391
+ {
392
+ chainId: 4217,
393
+ context: { title: 'Legacy subscription' },
394
+ destination: { type: 'url', url: 'https://hooks.example.com/endpoint' },
395
+ environment: 'production',
396
+ eventType,
397
+ filters: { status: ['completed'] },
398
+ owner,
399
+ projectId: 'prj_legacy',
400
+ },
401
+ { now: () => new Date('2026-08-24T17:30:13.847Z'), startBlockNumber: 123 },
402
+ )
403
+ // Seed the persisted pre-rename value without widening the current event type contract.
404
+ await sql`
405
+ UPDATE webhook_subscriptions
406
+ SET event_type = ${eventType.replace('routes:', 'funding:')},
407
+ status = ${status}, failure_count = 10,
408
+ last_delivery_at = '2026-08-24T19:21:13.478Z'
409
+ WHERE id = ${subscription.id}
410
+ `.execute(db.kysely)
411
+ }
412
+ }
413
+ for (const eventType of ['routes:deposit.updated', 'token:transfer'] as const)
414
+ await Webhooks.createSubscription(db, {
415
+ chainId: 4217,
416
+ destination: { type: 'url', url: 'https://hooks.example.com/current' },
417
+ eventType,
418
+ owner,
419
+ })
420
+
421
+ const records = () =>
422
+ db.kysely.selectFrom('webhook_subscriptions').selectAll().orderBy('id').execute()
423
+ const before = await records()
424
+ const list = () => Webhooks.listSubscriptions(db, owner)
425
+ expect(ManagementWebhooks.schema.ListResponse.safeParse({ data: await list() }).success).toBe(
426
+ false,
427
+ )
428
+ const name = '0282_webhook_subscription_routes_event_types'
429
+ await db.kysely.deleteFrom('migrations').where('name', '=', name).execute()
430
+ await db.migrate()
431
+
432
+ const expected = before.map((record) => ({
433
+ ...record,
434
+ eventType: record.eventType.replace('funding:', 'routes:'),
435
+ }))
436
+ expect(await records()).toEqual(expected)
437
+ expect(ManagementWebhooks.schema.ListResponse.safeParse({ data: await list() }).success).toBe(
438
+ true,
439
+ )
440
+ expect(await list()).toHaveLength(8)
441
+
442
+ // Exercise statement replay as well as the migration ledger's normal no-op path.
443
+ const migration = Db.migrations.find((migration) => migration.name === name)!
444
+ await migration.up(db.kysely).execute()
445
+ await db.migrate()
446
+ expect(await records()).toEqual(expected)
447
+ } finally {
448
+ await db.close()
449
+ }
450
+ })
451
+
452
+ test('behavior: combined policy migration preserves previously migrated data', async () => {
453
+ const db = create()
454
+ try {
455
+ await db.migrate()
456
+ const org = await Organizations.create(db, { name: 'Existing policy owner' })
457
+ const scope = { orgId: org.id, environment: 'production' } as const
458
+ const policy = await RoutesPolicies.save(db, { scope, version: 0, policy: { access: [] } })
459
+ await db.kysely
460
+ .insertInto('api_key_admissions')
461
+ .values({
462
+ id: 'key_existing',
463
+ orgId: org.id,
464
+ projectId: null,
465
+ expiresAt: null,
466
+ pendingScopes: JSON.stringify(['routes:read']),
467
+ })
468
+ .execute()
469
+ // Existing previews have the DDL but only the former migration names in their ledger.
470
+ const combined = await db.kysely
471
+ .deleteFrom('migrations')
472
+ .where('name', '=', '0280_routes_policies')
473
+ .returningAll()
474
+ .executeTakeFirstOrThrow()
475
+ const historical = [
476
+ { ...combined, name: '0267_routes_policies' },
477
+ { ...combined, name: '0270_api_key_pending_scopes' },
478
+ { ...combined, name: '0270_routes_policies' },
479
+ ]
480
+ await db.kysely.insertInto('migrations').values(historical).execute()
481
+
482
+ await db.migrate()
483
+ await db.migrate()
484
+ expect(await RoutesPolicies.get(db, scope)).toEqual(policy)
485
+ expect(
486
+ await db.kysely
487
+ .selectFrom('api_key_admissions')
488
+ .select('pendingScopes')
489
+ .where('id', '=', 'key_existing')
490
+ .executeTakeFirst(),
491
+ ).toEqual({ pendingScopes: ['routes:read'] })
492
+ expect(
493
+ await db.kysely
494
+ .selectFrom('migrations')
495
+ .selectAll()
496
+ .where(
497
+ 'name',
498
+ 'in',
499
+ historical.map(({ name }) => name),
500
+ )
501
+ .orderBy('name')
502
+ .execute(),
503
+ ).toEqual(historical)
504
+ } finally {
505
+ await db.close()
506
+ }
507
+ })
508
+
509
+ test('behavior: staged policy upgrades preserve legacy rows and allow distinct commitments only after compatible workers', async () => {
510
+ const schema = `t_${nanoid()}`
511
+ const db = Db.postgres({ connectionString: Runtime.postgresUrl })
512
+ try {
513
+ await db.kysely.executeQuery(
514
+ CompiledQuery.raw(`CREATE SCHEMA ${pg.escapeIdentifier(schema)}`),
515
+ )
516
+ await db.transaction(async (tx) => {
517
+ await sql`SELECT set_config('search_path', quote_ident(${schema}), true)`.execute(tx.kysely)
518
+ const boundary = Db.migrations.findIndex(({ name }) => name === '0280_routes_policies')
519
+ expect(boundary).toBeGreaterThan(0)
520
+ for (const migration of Db.migrations.slice(0, boundary))
521
+ await migration.up(tx.kysely).execute()
522
+ const org = await Organizations.create(tx, { name: 'Legacy route customer' })
523
+ const first = await DepositAddress.create(tx, {
524
+ environment: 'production',
525
+ orgId: org.id,
526
+ deliveryStrategy: 'provider',
527
+ providerOutputToken: TestRoutes.providerOutputToken(),
528
+ snapshot: TestRoutes.depositAddressSnapshot({ subsidize: true }),
529
+ })
530
+ const before = await RoutesDepositAddresses.get(tx, first.id)
531
+ const replacement = Db.migrations.findIndex(
532
+ ({ name }) => name === '0281_routes_deposit_address_policy_identity',
533
+ )
534
+ expect(replacement).toBeGreaterThan(boundary)
535
+ for (const migration of Db.migrations.slice(boundary, replacement))
536
+ await migration.up(tx.kysely).execute()
537
+ expect(await RoutesDepositAddresses.get(tx, first.id)).toEqual(before)
538
+ // Exact pre-policy worker ON CONFLICT target, executed against the upgraded schema.
539
+ const oldInsert = (record: RoutesDepositAddresses.Record) =>
540
+ tx.kysely
541
+ .insertInto('routes_deposit_addresses')
542
+ .values({ ...record, providerRequestIds: JSON.stringify(record.providerRequestIds) })
543
+ .onConflict((oc) =>
544
+ oc
545
+ .columns([
546
+ 'orgId',
547
+ 'environment',
548
+ 'projectId',
549
+ 'sourceChainId',
550
+ 'sourceTokenKey',
551
+ 'destinationTokenKey',
552
+ 'recipient',
553
+ 'refundAddress',
554
+ 'subsidize',
555
+ ])
556
+ .doNothing(),
557
+ )
558
+ .returningAll()
559
+ .executeTakeFirst()
560
+ const record = {
561
+ ...first,
562
+ id: DepositAddress.generateId(),
563
+ address: `0x${'83'.repeat(20)}`,
564
+ recipient: `0x${'84'.repeat(20)}`,
565
+ }
566
+ expect(await oldInsert(record)).toMatchObject({ id: record.id })
567
+ expect(await oldInsert({ ...record, id: DepositAddress.generateId() })).toBeUndefined()
568
+ const match = {
569
+ destinationTokenKey: record.destinationTokenKey,
570
+ environment: record.environment,
571
+ orgId: record.orgId,
572
+ recipient: record.recipient,
573
+ refundAddress: record.refundAddress,
574
+ sourceChainId: record.sourceChainId,
575
+ sourceTokenKey: record.sourceTokenKey,
576
+ subsidize: record.subsidize,
577
+ }
578
+ expect(
579
+ await RoutesDepositAddresses.insertOrGet(tx, {
580
+ match,
581
+ record: { ...record, id: DepositAddress.generateId() },
582
+ }),
583
+ ).toMatchObject({ id: record.id })
584
+ await expect(
585
+ RoutesDepositAddresses.insertOrGet(tx, {
586
+ match: { ...match, policyKey: '["tempo","0.050000"]', providerId: record.providerId },
587
+ record: {
588
+ ...record,
589
+ id: DepositAddress.generateId(),
590
+ address: `0x${'85'.repeat(20)}`,
591
+ providerState: { routePolicyKey: '["tempo","0.050000"]' },
592
+ },
593
+ }),
594
+ ).rejects.toThrow(RoutesDepositAddresses.IdentityConflictError)
595
+ // Targetless DO NOTHING keeps the transaction usable after a uniqueness conflict.
596
+ expect(await RoutesDepositAddresses.countByOrganization(tx, org.id)).toBe(2)
597
+
598
+ // Only policy-aware workers can run after the financial identity upgrade; their inserts are targetless.
599
+ for (let attempt = 0; attempt < 2; attempt++)
600
+ await Db.migrations[replacement]!.up(tx.kysely).execute()
601
+ const commitment = {
602
+ ...record,
603
+ address: `0x${'85'.repeat(20)}`,
604
+ id: DepositAddress.generateId(),
605
+ providerState: { routePolicyKey: '["tempo","0.050000"]' },
606
+ }
607
+ const policyMatch = {
608
+ ...match,
609
+ policyKey: '["tempo","0.050000"]',
610
+ providerId: record.providerId,
611
+ }
612
+ expect(
613
+ await RoutesDepositAddresses.insertOrGet(tx, { match: policyMatch, record: commitment }),
614
+ ).toEqual(commitment)
615
+ expect(
616
+ await RoutesDepositAddresses.insertOrGet(tx, {
617
+ match: policyMatch,
618
+ record: { ...commitment, id: DepositAddress.generateId() },
619
+ }),
620
+ ).toEqual(commitment)
621
+ expect(await RoutesDepositAddresses.getMatching(tx, match)).toEqual(record)
622
+ expect(await RoutesDepositAddresses.get(tx, first.id)).toEqual(before)
623
+ expect(await RoutesDepositAddresses.countByOrganization(tx, org.id)).toBe(3)
624
+ })
625
+ } finally {
626
+ await db.kysely.executeQuery(
627
+ CompiledQuery.raw(`DROP SCHEMA IF EXISTS ${pg.escapeIdentifier(schema)} CASCADE`),
628
+ )
629
+ await db.close()
630
+ }
631
+ })
632
+
30
633
  test('behavior: raw owner deletes fence API keys for older application code', async () => {
31
634
  const db = create()
32
635
  await db.migrate()
@@ -262,6 +865,154 @@ describe('postgres', () => {
262
865
  }
263
866
  })
264
867
 
868
+ test('behavior: archives an expired Solana settlement and preserves its billing owner', async () => {
869
+ const db = create()
870
+ await db.migrate()
871
+ try {
872
+ const chainId = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
873
+ const token = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
874
+ const recipient = '82RrXaHHzCuSYG7oiQgHyEDRiYHKmrNTTka3D2QtUnTL'
875
+ const snapshot = TestRoutes.transferSnapshot({
876
+ destinationChain: { addressFormat: 'base58', id: chainId, kind: 'solana', name: 'Solana' },
877
+ destinationToken: {
878
+ address: token,
879
+ currency: 'USD',
880
+ decimals: 6,
881
+ name: 'USD Coin',
882
+ standard: 'SPL',
883
+ symbol: 'USDC',
884
+ tokenKey: `${chainId}/spl:${token}`,
885
+ verified: true,
886
+ },
887
+ recipient,
888
+ sourceTransactionHashes: [`0x${'ab'.repeat(32)}`],
889
+ })
890
+ const amount = { baseUnits: '1', currency: 'USD', decimals: 6, formatted: '0.000001' }
891
+ const account = 'EhsfgAGLqLuBysRpXFNHmgDQc81zzPvypY4eNjgZV97X'
892
+ const signed = {
893
+ account,
894
+ amount: '1',
895
+ chainId,
896
+ hash: '3UBy3CJGU8pWLWpuXaa9dtNjdSJdvrng8gyKSyUGifxEqBDzjmJukP7Fg5GdtsJjYKMXMv14SszGUrEyNgKoQaMB',
897
+ transaction:
898
+ 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA==',
899
+ }
900
+ const replacement = {
901
+ ...signed,
902
+ hash: '2ApX6qqMYmcC2k1PVnZ7zKjx1ewGTvds9urXMcSP3owqvrUBjXpVrnxSqmsG6J4xv29VCNMBVurBepLhu2PTEyNx',
903
+ }
904
+ const owner = await Transfer.create(db, {
905
+ apiKeyId: 'key_owner',
906
+ environment: 'production',
907
+ orgId: 'org_owner',
908
+ snapshot,
909
+ })
910
+ const initial = await Transfer.transition(db, {
911
+ expectedVersion: owner.version,
912
+ id: owner.id,
913
+ providerState: { transferSubsidy: JSON.stringify(signed) },
914
+ status: 'processing',
915
+ subsidyAccount: account,
916
+ subsidyAmount: amount,
917
+ subsidyChainId: chainId,
918
+ subsidyTokenAddress: token,
919
+ subsidyTransactionHash: signed.hash,
920
+ })
921
+ expect(initial.type).toBe('applied')
922
+ const key = {
923
+ sourceChainId: snapshot.sourceChain.id,
924
+ transactionRef: snapshot.sourceTransactionHashes![0]!,
925
+ }
926
+ const marked = await db.transaction((tx) =>
927
+ RoutesTransferSubsidies.markExpiredIn(tx, {
928
+ ...key,
929
+ signedHash: signed.hash,
930
+ signedTransaction: JSON.stringify(signed),
931
+ transferId: owner.id,
932
+ }),
933
+ )
934
+ expect(marked).toMatchObject({ type: 'expired', settlement: { transferId: owner.id } })
935
+ expect(
936
+ await db.transaction((tx) =>
937
+ RoutesTransferSubsidies.markExpiredIn(tx, {
938
+ ...key,
939
+ signedHash: signed.hash,
940
+ signedTransaction: JSON.stringify(signed),
941
+ transferId: owner.id,
942
+ }),
943
+ ),
944
+ ).toMatchObject({ type: 'stale' })
945
+ const archived = await db.kysely
946
+ .selectFrom('routes_transfer_subsidy_expired_attempts')
947
+ .selectAll()
948
+ .execute()
949
+ expect(archived).toMatchObject([
950
+ { transaction: JSON.stringify(signed), transactionHash: signed.hash, transferId: owner.id },
951
+ ])
952
+ const foreign = await Transfer.create(db, {
953
+ apiKeyId: 'key_foreign',
954
+ environment: 'production',
955
+ orgId: 'org_foreign',
956
+ snapshot,
957
+ })
958
+ await expect(
959
+ Transfer.transition(db, {
960
+ expectedVersion: foreign.version,
961
+ id: foreign.id,
962
+ providerState: { transferSubsidy: JSON.stringify(replacement) },
963
+ status: 'processing',
964
+ subsidyAccount: account,
965
+ subsidyAmount: amount,
966
+ subsidyChainId: chainId,
967
+ subsidyTokenAddress: token,
968
+ subsidyTransactionHash: replacement.hash,
969
+ }),
970
+ ).rejects.toThrow('Only the subsidy owner may replace an expired settlement')
971
+ const staleShared = await Transfer.transition(db, {
972
+ expectedVersion: foreign.version,
973
+ id: foreign.id,
974
+ providerState: { transferSubsidy: JSON.stringify(signed) },
975
+ status: 'processing',
976
+ subsidyAccount: account,
977
+ subsidyAmount: amount,
978
+ subsidyChainId: chainId,
979
+ subsidyTokenAddress: token,
980
+ subsidyTransactionHash: signed.hash,
981
+ })
982
+ expect(staleShared.type).toBe('applied')
983
+ expect(staleShared.type === 'applied' && staleShared.record.subsidyAmount).toBeNull()
984
+ expect(
985
+ await db.transaction((tx) => RoutesTransferSubsidies.getForUpdateIn(tx, key)),
986
+ ).toMatchObject({ status: 'expired', transaction: JSON.stringify(signed) })
987
+ await expect(
988
+ Transfer.transition(db, {
989
+ expectedVersion: initial.type === 'applied' ? initial.record.version : 2,
990
+ id: owner.id,
991
+ providerState: {
992
+ transferSubsidy: JSON.stringify({ ...replacement, amount: '2' }),
993
+ },
994
+ subsidyTransactionHash: replacement.hash,
995
+ }),
996
+ ).rejects.toThrow('Expired subsidy replacement changed settlement terms')
997
+ const next = await Transfer.transition(db, {
998
+ expectedVersion: initial.type === 'applied' ? initial.record.version : 2,
999
+ id: owner.id,
1000
+ providerState: { transferSubsidy: JSON.stringify(replacement) },
1001
+ subsidyTransactionHash: replacement.hash,
1002
+ })
1003
+ expect(next.type).toBe('applied')
1004
+ expect(
1005
+ await db.transaction((tx) => RoutesTransferSubsidies.getForUpdateIn(tx, key)),
1006
+ ).toMatchObject({
1007
+ status: 'active',
1008
+ transaction: JSON.stringify(replacement),
1009
+ transferId: owner.id,
1010
+ })
1011
+ } finally {
1012
+ await db.close()
1013
+ }
1014
+ })
1015
+
265
1016
  test('behavior: legacy invitation inserts do not grant early access', async () => {
266
1017
  const db = create()
267
1018
  await db.migrate()
@@ -415,3 +1166,129 @@ describe('postgres', () => {
415
1166
  await db.close()
416
1167
  })
417
1168
  })
1169
+
1170
+ describe('observe', () => {
1171
+ test('separates connection waits from query execution', async () => {
1172
+ const db = create()
1173
+ await db.migrate()
1174
+ try {
1175
+ const durations: number[] = []
1176
+ const timings: Db.observe.Timing[] = []
1177
+ const observed = Db.observe(db, {
1178
+ onQuery: (duration, timing) => {
1179
+ durations.push(duration)
1180
+ timings.push(timing)
1181
+ },
1182
+ })
1183
+ await Promise.all([
1184
+ sql`SELECT pg_sleep(0.04)`.execute(observed.kysely),
1185
+ sql`SELECT 1`.execute(observed.kysely),
1186
+ ])
1187
+
1188
+ expect(timings).toHaveLength(2)
1189
+ expect(timings.some((timing) => timing.acquire >= 30)).toBe(true)
1190
+ expect(timings.some((timing) => timing.query >= 30)).toBe(true)
1191
+ expect(durations).toEqual(timings.map((timing) => timing.acquire + timing.query))
1192
+ } finally {
1193
+ await db.close()
1194
+ }
1195
+ })
1196
+
1197
+ test('reports one duration per query and leaves results intact', async () => {
1198
+ const db = create()
1199
+ await db.migrate()
1200
+ try {
1201
+ const durations: number[] = []
1202
+ const observed = Db.observe(db, { onQuery: (ms) => durations.push(ms) })
1203
+ expect(await Organizations.get(observed, 'missing')).toBeUndefined()
1204
+ expect(await Organizations.get(observed, 'missing')).toBeUndefined()
1205
+
1206
+ expect(durations).toHaveLength(2)
1207
+ expect(durations.every((ms) => ms > 0)).toBe(true)
1208
+ } finally {
1209
+ await db.close()
1210
+ }
1211
+ })
1212
+
1213
+ test('reports rejected queries and leaves unobserved handles silent', async () => {
1214
+ const db = create()
1215
+ await db.migrate()
1216
+ try {
1217
+ const durations: number[] = []
1218
+ const observed = Db.observe(db, { onQuery: (ms) => durations.push(ms) })
1219
+ await expect(
1220
+ sql`SELECT * FROM missing_table_for_observe`.execute(observed.kysely),
1221
+ ).rejects.toThrow()
1222
+ expect(await Organizations.get(db, 'missing')).toBeUndefined()
1223
+
1224
+ expect(durations).toHaveLength(1)
1225
+ expect(durations[0]).toBeGreaterThan(0)
1226
+ } finally {
1227
+ await db.close()
1228
+ }
1229
+ })
1230
+ })
1231
+
1232
+ function rewardExtensionConfig(): Campaigns.Config {
1233
+ const schedule = {
1234
+ endTimestamp: Date.parse('2026-09-30T12:00:00Z') / 1_000,
1235
+ intervalSeconds: 300,
1236
+ startTimestamp: Date.parse('2026-09-01T00:00:00Z') / 1_000,
1237
+ }
1238
+ return {
1239
+ boostRewards: {
1240
+ ...schedule,
1241
+ excludedAddresses: [],
1242
+ funding: { wallet: `0x${'12'.repeat(20)}` },
1243
+ perUserPrincipalCapAssets: '25000000000',
1244
+ targetAnnualRateBps: 700,
1245
+ totalPrincipalCapAssets: '10000000000000',
1246
+ treasury: `0x${'34'.repeat(20)}`,
1247
+ },
1248
+ targetYield: {
1249
+ ...schedule,
1250
+ annualRate: { bps: 500 },
1251
+ funding: [{ remainder: true, wallet: `0x${'56'.repeat(20)}` }],
1252
+ },
1253
+ }
1254
+ }
1255
+
1256
+ async function seedRewardExtension(db: Db.Db, options: seedRewardExtension.Options) {
1257
+ const chainId = options.chainId ?? 4217
1258
+ const vaultAddress = options.vaultAddress ?? '0xd730394f3bb85a4828e35fc5e361dcc9f894fa4f'
1259
+ await EarnVaults.upsert(db, {
1260
+ chainId,
1261
+ description: null,
1262
+ label: 'Reward extension fixture',
1263
+ privateInputTokens: [],
1264
+ privateOutputTokens: [],
1265
+ vaultAddress,
1266
+ zones: [],
1267
+ })
1268
+ return RewardCampaigns.upsert(db, {
1269
+ assetAddress: `0x${'78'.repeat(20)}`,
1270
+ assetDecimals: 6,
1271
+ chainId,
1272
+ config: options.config,
1273
+ earnShareAddress: `0x${'90'.repeat(20)}`,
1274
+ earnShareDecimals: 18,
1275
+ now: Date.parse('2026-08-31T00:00:00Z') / 1_000,
1276
+ vaultAddress,
1277
+ })
1278
+ }
1279
+
1280
+ declare namespace seedRewardExtension {
1281
+ type Options = {
1282
+ chainId?: number
1283
+ config: Campaigns.Config
1284
+ vaultAddress?: `0x${string}`
1285
+ }
1286
+ }
1287
+
1288
+ async function replayRewardExtension(db: Db.Db) {
1289
+ await db.kysely
1290
+ .deleteFrom('migrations')
1291
+ .where('name', '=', '0302_extend_d730_reward_campaign')
1292
+ .execute()
1293
+ await db.migrate()
1294
+ }