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
@@ -0,0 +1,951 @@
1
+ /** @module-tag localnet */
2
+
3
+ import { Address, Hex } from 'ox'
4
+ import { decodeFunctionData, encodeFunctionData, erc20Abi } from 'viem'
5
+ import { getBlock, sendTransactionSync, writeContractSync } from 'viem/actions'
6
+ import { Abis, Actions } from 'viem/tempo'
7
+
8
+ import * as TestApp from '../../../../test/App.js'
9
+ import * as Contracts from '../../../../test/contracts/propAmm.js'
10
+ import * as TestPropAmm from '../../../../test/PropAmm.js'
11
+ import * as TestRoutes from '../../../../test/Routes.js'
12
+ import * as Runtime from '../../../../test/runtime.js'
13
+ import * as Tempo from '../../../../test/Tempo.js'
14
+ import * as Organizations from '../../../db/tables/organizations.js'
15
+ import * as Policies from '../../../db/tables/routesPolicies.js'
16
+ import * as TransferTransactions from '../../../db/tables/routesTransferTransactions.js'
17
+ import * as Transfer from '../../../internal/routes/Transfer.js'
18
+ import * as Reconciliation from '../../../internal/routes/TransferReconciliation.js'
19
+ import * as TransfersTable from '../../../db/tables/routesTransfers.js'
20
+ import * as Transfers from './transfers.js'
21
+ import * as Catalog from '../../../internal/routes/Catalog.js'
22
+ import * as Provider from '../../../internal/routes/Provider.js'
23
+ import * as Schema from '../../../internal/Schema.js'
24
+ import * as PropAmm from '../../../internal/routes/providers/propAmm.js'
25
+ import * as Quotes from './quotes.js'
26
+
27
+ const db = TestApp.database()
28
+ const client = Tempo.getClient({ account: Tempo.accounts[6] })
29
+ const recipient = Tempo.accounts[7].address
30
+ const sender = client.account.address
31
+ const denied = Tempo.accounts[8].address
32
+ const provider = PropAmm.propAmm()
33
+ const app = TestApp.create({ auth: false, db, providers: [provider] })
34
+ const writer = {
35
+ id: 'key_propamm_writer',
36
+ orgId: 'org_propamm_writer',
37
+ scopes: ['routes:read', 'routes:write'],
38
+ token: 'secret_propamm_writer',
39
+ } satisfies TestApp.kvStore.Key
40
+ const queued: Reconciliation.Message[] = []
41
+ const transfersApp = TestApp.create({
42
+ auth: { keys: [writer] },
43
+ db,
44
+ providers: [provider],
45
+ routes: {
46
+ async dispatchTransferReconciliation(message) {
47
+ queued.push(message)
48
+ },
49
+ },
50
+ })
51
+ let pool: Awaited<ReturnType<typeof TestPropAmm.deploy>>
52
+ let catalog: Catalog.Snapshot
53
+
54
+ beforeAll(async () => {
55
+ if (Runtime.get().mode !== 'localnet') return
56
+ await Actions.faucet.fundSync(client, { account: client.account })
57
+ pool = await TestPropAmm.deploy({ client, recipient })
58
+ const chainId = `eip155:${pool.chainId}`
59
+ const data = Catalog.schema.Data.parse({
60
+ chains: [
61
+ {
62
+ aliases: [],
63
+ id: chainId,
64
+ name: 'Tempo',
65
+ parentChainId: null,
66
+ rpcUrls: [Tempo.rpcUrl],
67
+ slug: 'tempo',
68
+ },
69
+ ],
70
+ chainTokens: [
71
+ { address: pool.base, chainId, decimals: 6, name: null, standard: 'TIP-20', tokenId: 'usdy' },
72
+ {
73
+ address: pool.quote,
74
+ chainId,
75
+ decimals: 6,
76
+ name: null,
77
+ standard: 'TIP-20',
78
+ tokenId: 'usdce',
79
+ },
80
+ ],
81
+ routes: TestRoutes.data.routes
82
+ .filter(
83
+ (route) =>
84
+ route.providerId === 'propamm' &&
85
+ ['usdy', 'usdce'].includes(route.sourceTokenId) &&
86
+ ['usdy', 'usdce'].includes(route.destinationTokenId),
87
+ )
88
+ .map((route) => ({
89
+ ...route,
90
+ configuration: { poolAddress: pool.pool },
91
+ destinationChainId: chainId,
92
+ sourceChainId: chainId,
93
+ })),
94
+ tokens: TestRoutes.data.tokens.filter((token) => ['usdy', 'usdce'].includes(token.id)),
95
+ })
96
+ await Catalog.publish(db, data)
97
+ catalog = await Catalog.read(db)
98
+ await Organizations.upsert(db, { id: writer.orgId, name: writer.orgId })
99
+ await Policies.save(db, {
100
+ policy: { access: null },
101
+ scope: { environment: 'production', orgId: writer.orgId },
102
+ version: 0,
103
+ })
104
+ })
105
+
106
+ describe.skipIf(Runtime.get().mode !== 'localnet')('prepareTransfer', () => {
107
+ test.each(['tempo', `eip155:${client.chain.id}`, undefined])(
108
+ 'defaults sourceChain to destinationChain (%s)',
109
+ async (destinationChain) => {
110
+ const response = await transfersApp.request('/v1/routes/transfers', {
111
+ body: JSON.stringify({
112
+ amount: '1000000',
113
+ destinationChain,
114
+ destinationToken: 'usdce',
115
+ mode: 'exactSource',
116
+ recipient,
117
+ sender,
118
+ sourceToken: 'usdy',
119
+ }),
120
+ headers: {
121
+ 'content-type': 'application/json',
122
+ 'idempotency-key': `propamm_default_source_${destinationChain}`,
123
+ 'tempo-api-key': writer.token,
124
+ },
125
+ method: 'POST',
126
+ })
127
+ expect(response.status).toBe(200)
128
+ const transfer = await TestApp.json(response, Transfers.schema.createRoutesTransfer.Response)
129
+ expect(transfer.sourceChain.id).toBe(`eip155:${pool.chainId}`)
130
+ expect(transfer.destinationChain.id).toBe(`eip155:${pool.chainId}`)
131
+ expect(transfer.action.calls[1]!.to.toLowerCase()).toBe(pool.pool.toLowerCase())
132
+ },
133
+ )
134
+
135
+ test.each([
136
+ {
137
+ baseToQuote: true,
138
+ destinationToken: 'usdce',
139
+ expected: 2_500_000n,
140
+ sourceAmount: '2000000',
141
+ sourceToken: 'usdy',
142
+ },
143
+ {
144
+ baseToQuote: false,
145
+ destinationToken: 'usdy',
146
+ expected: 2_000_000n,
147
+ sourceAmount: '2500000',
148
+ sourceToken: 'usdce',
149
+ },
150
+ ])(
151
+ 'prepares and executes $sourceToken to $destinationToken atomically',
152
+ async ({ baseToQuote, destinationToken, expected, sourceAmount, sourceToken }) => {
153
+ const response = await transfersApp.request('/v1/routes/transfers', {
154
+ body: JSON.stringify({
155
+ amount: sourceAmount,
156
+ destinationChain: 'tempo',
157
+ destinationToken,
158
+ mode: 'exactSource',
159
+ recipient,
160
+ sender,
161
+ slippageBps: 100,
162
+ sourceChain: 'tempo',
163
+ sourceToken,
164
+ }),
165
+ headers: {
166
+ 'content-type': 'application/json',
167
+ 'idempotency-key': `propamm_${sourceToken}`,
168
+ 'tempo-api-key': writer.token,
169
+ },
170
+ method: 'POST',
171
+ })
172
+ expect(response.status).toBe(200)
173
+ const transfer = await TestApp.json(response, Transfers.schema.createRoutesTransfer.Response)
174
+ expect(transfer.action.type).toBe('evm:calls')
175
+ expect(transfer.action.calls).toHaveLength(2)
176
+ const [approval, swap] = transfer.action.calls
177
+ const decodedApproval = decodeFunctionData({ abi: erc20Abi, data: approval!.data as Hex.Hex })
178
+ expect(decodedApproval.functionName).toBe('approve')
179
+ expect(decodedApproval.args).toEqual([Address.checksum(pool.pool), BigInt(sourceAmount)])
180
+ const decoded = decodeFunctionData({ abi: Abis.directPropAmm, data: swap!.data as Hex.Hex })
181
+ if (decoded.functionName !== 'swapExactInput')
182
+ throw new Error('Expected an exact-input swap.')
183
+ const [
184
+ direction,
185
+ amountIn,
186
+ minimum,
187
+ beneficiary,
188
+ customerId,
189
+ tradeId,
190
+ deadline,
191
+ price,
192
+ tolerance,
193
+ updatedAt,
194
+ ] = decoded.args
195
+ expect([
196
+ direction,
197
+ amountIn,
198
+ minimum,
199
+ beneficiary.toLowerCase(),
200
+ customerId,
201
+ price,
202
+ tolerance,
203
+ ]).toEqual([
204
+ baseToQuote,
205
+ BigInt(sourceAmount),
206
+ (expected * 99n) / 100n,
207
+ recipient.toLowerCase(),
208
+ Hex.padLeft(sender, 32).toLowerCase(),
209
+ pool.price,
210
+ 0n,
211
+ ])
212
+ expect(Number(deadline) * 1000).toBe(Date.parse(transfer.quote.expiresAt!))
213
+ expect(deadline).toBeLessThanOrEqual(updatedAt + pool.maxOracleAge)
214
+ const stored = await TransfersTable.get(db, transfer.id)
215
+ expect(stored?.providerState).toMatchObject({
216
+ propAmm: {
217
+ amountIn: sourceAmount,
218
+ baseToQuote,
219
+ customerId: Hex.padLeft(Address.checksum(sender), 32),
220
+ deadline: deadline.toString(),
221
+ expectedOraclePrice: price.toString(),
222
+ minAmountOut: minimum.toString(),
223
+ minimumOracleUpdatedAt: updatedAt.toString(),
224
+ oraclePriceToleranceBps: '0',
225
+ pool: pool.pool,
226
+ recipient: Address.checksum(recipient),
227
+ sender: Address.checksum(sender),
228
+ tradeId,
229
+ },
230
+ })
231
+
232
+ const token = baseToQuote ? pool.quote : pool.base
233
+ const before = await Actions.token.getBalance(client, { account: recipient, token })
234
+ const receipt = await sendTransactionSync(client, {
235
+ calls: transfer.action.calls.map((call) => ({
236
+ data: call.data as Hex.Hex,
237
+ to: call.to as Hex.Hex,
238
+ value: BigInt(call.value),
239
+ })),
240
+ })
241
+ expect(receipt.status).toBe('success')
242
+ const sourceChain = catalog.chainsByKey.get(`eip155:${pool.chainId}`)!
243
+ const verification = {
244
+ destinationChain: sourceChain,
245
+ providerState: stored!.providerState!,
246
+ sourceChain,
247
+ transactionHash: receipt.transactionHash,
248
+ transfer: stored!.snapshot,
249
+ }
250
+ await expect
251
+ .poll(
252
+ async () =>
253
+ (await provider.verifySourceTransaction!(verification, new AbortController().signal))
254
+ .type,
255
+ { timeout: 30_000 },
256
+ )
257
+ .toBe('verified')
258
+ for (const changed of [
259
+ { tradeId: Hex.random(32) },
260
+ { pool: denied },
261
+ { sender: denied },
262
+ { recipient: denied },
263
+ { amountIn: '1' },
264
+ { minAmountOut: '1' },
265
+ { expectedOraclePrice: '1' },
266
+ { minimumOracleUpdatedAt: '1' },
267
+ { oraclePriceToleranceBps: '1' },
268
+ { baseToQuote: !baseToQuote },
269
+ ])
270
+ expect(
271
+ await provider.verifySourceTransaction!(
272
+ {
273
+ ...verification,
274
+ providerState: {
275
+ ...stored!.providerState,
276
+ propAmm: {
277
+ ...PropAmm.schema.ProviderState.parse(stored!.providerState).propAmm,
278
+ ...changed,
279
+ },
280
+ },
281
+ },
282
+ new AbortController().signal,
283
+ ),
284
+ ).toEqual({ type: 'invalid' })
285
+
286
+ const registration = {
287
+ body: JSON.stringify({ transactionHash: receipt.transactionHash }),
288
+ headers: { 'content-type': 'application/json', 'tempo-api-key': writer.token },
289
+ method: 'POST',
290
+ }
291
+ const registered = await transfersApp.request(
292
+ `/v1/routes/transfers/${transfer.id}/source-transactions`,
293
+ registration,
294
+ )
295
+ expect(registered.status).toBe(200)
296
+ expect((await registered.json()).status).toBe('processing')
297
+ expect(queued.some((message) => message.transferId === transfer.id)).toBe(true)
298
+
299
+ // A fresh tracker loads all evidence from storage, as it would after a worker restart.
300
+ const tracker = Reconciliation.createTracker({ db, providers: [PropAmm.propAmm()] })
301
+ expect(
302
+ await tracker.reconcile({ transferId: transfer.id, type: 'routes:transfer:reconcile' }),
303
+ ).toEqual({ type: 'completed' })
304
+ expect(
305
+ await tracker.reconcile({ transferId: transfer.id, type: 'routes:transfer:reconcile' }),
306
+ ).toEqual({ type: 'ignored' })
307
+ const completed = await TransfersTable.get(db, transfer.id)
308
+ expect(completed?.snapshot).toMatchObject({
309
+ destinationTransactionHashes: [receipt.transactionHash],
310
+ sourceTransactionHashes: [receipt.transactionHash],
311
+ })
312
+ expect(completed?.status).toBe('completed')
313
+ expect(
314
+ (await TransferTransactions.listByTransfer(db, transfer.id)).map(
315
+ ({ role, transactionRef }) => ({ role, transactionRef }),
316
+ ),
317
+ ).toEqual([
318
+ { role: 'source', transactionRef: receipt.transactionHash },
319
+ { role: 'destination', transactionRef: receipt.transactionHash },
320
+ ])
321
+ const replay = await transfersApp.request(
322
+ `/v1/routes/transfers/${transfer.id}/source-transactions`,
323
+ registration,
324
+ )
325
+ expect(replay.status).toBe(200)
326
+ const duplicate = await Transfer.create(db, {
327
+ apiKeyId: writer.id,
328
+ environment: 'production',
329
+ orgId: writer.orgId,
330
+ providerState: stored!.providerState!,
331
+ snapshot: stored!.snapshot,
332
+ })
333
+ const conflict = await transfersApp.request(
334
+ `/v1/routes/transfers/${duplicate.id}/source-transactions`,
335
+ registration,
336
+ )
337
+ expect(conflict.status).toBe(409)
338
+ expect((await conflict.json()).error.code).toBe('source_transaction_conflict')
339
+
340
+ expect(
341
+ Actions.propAmm.swap.extractEvent(receipt.logs, { pool: pool.pool, tradeId }).args.tradeId,
342
+ ).toBe(tradeId)
343
+ const after = await Actions.token.getBalance(client, { account: recipient, token })
344
+ expect(after.amount - before.amount).toBe(expected)
345
+ expect(
346
+ (
347
+ await Actions.token.getAllowance(client, {
348
+ account: sender,
349
+ spender: pool.pool,
350
+ token: baseToQuote ? pool.base : pool.quote,
351
+ })
352
+ ).amount,
353
+ ).toBe(0n)
354
+ },
355
+ )
356
+
357
+ test('rejects altered batches before persistence', async () => {
358
+ const selected = (await prepareTransfer())!
359
+ const parameters = {
360
+ candidate: selected.candidate,
361
+ destinationAmountMin: selected.result.destinationAmountMin,
362
+ method: 'transaction' as const,
363
+ mode: 'exactSource' as const,
364
+ recipient,
365
+ sender,
366
+ }
367
+ const action = selected.result.action
368
+ expect(provider.validateTransferAction!({ ...parameters, action })).toEqual({})
369
+ const [approval, swap] = action.calls
370
+ for (const calls of [
371
+ [approval!, swap!, swap!],
372
+ [swap!, approval!],
373
+ [{ ...approval!, value: '0x1' }, swap!],
374
+ [{ ...approval!, to: denied }, swap!],
375
+ [approval!, { ...swap!, to: denied }],
376
+ [approval!, { ...swap!, data: swap!.data + '00' }],
377
+ [approval!],
378
+ ])
379
+ expect(() =>
380
+ provider.validateTransferAction!({ ...parameters, action: { calls, type: 'evm:calls' } }),
381
+ ).toThrow(Provider.ProviderPayloadError)
382
+ expect(() =>
383
+ provider.validateTransferAction!({ ...parameters, action, recipient: denied }),
384
+ ).toThrow(Provider.ProviderPayloadError)
385
+ expect(() =>
386
+ provider.validateTransferAction!({ ...parameters, action, destinationAmountMin: '1' }),
387
+ ).toThrow(Provider.ProviderPayloadError)
388
+ })
389
+
390
+ test('rejects extra calls, standalone approvals, and reverted swaps', async () => {
391
+ const selected = (await prepareTransfer())!
392
+ const snapshot = TestRoutes.transferSnapshot({
393
+ destinationAmount: { baseUnits: '1250000', currency: 'USD', decimals: 6, formatted: '1.25' },
394
+ destinationAmountMin: {
395
+ baseUnits: '1250000',
396
+ currency: 'USD',
397
+ decimals: 6,
398
+ formatted: '1.25',
399
+ },
400
+ destinationChain: selected.candidate.destinationChain,
401
+ destinationToken: selected.candidate.destinationToken,
402
+ provider: selected.candidate.provider,
403
+ quote: { expiresAt: selected.result.expiresAt, sampledAt: selected.result.sampledAt },
404
+ recipient,
405
+ sender,
406
+ sourceAmount: { baseUnits: '1000000', currency: 'USDY', decimals: 6, formatted: '1' },
407
+ sourceChain: selected.candidate.sourceChain,
408
+ sourceToken: selected.candidate.sourceToken,
409
+ })
410
+ const chain = catalog.chainsByKey.get(`eip155:${pool.chainId}`)!
411
+ const calls = selected.result.action.calls.map((call) => ({
412
+ data: call.data as Hex.Hex,
413
+ to: call.to as Address.Address,
414
+ value: BigInt(call.value),
415
+ }))
416
+ for (const batch of [[calls[0]!], [...calls, calls[0]!]]) {
417
+ const receipt = await sendTransactionSync(client, { calls: batch })
418
+ expect(receipt.status).toBe('success')
419
+ await expect
420
+ .poll(
421
+ async () =>
422
+ (
423
+ await provider.verifySourceTransaction!(
424
+ {
425
+ destinationChain: chain,
426
+ providerState: selected.result.providerState,
427
+ sourceChain: chain,
428
+ transactionHash: receipt.transactionHash,
429
+ transfer: snapshot,
430
+ },
431
+ new AbortController().signal,
432
+ )
433
+ ).type,
434
+ { timeout: 30_000 },
435
+ )
436
+ .toBe('invalid')
437
+ }
438
+ await Actions.token.approveSync(client, { amount: 0n, spender: pool.pool, token: pool.base })
439
+ const decoded = decodeFunctionData({ abi: Abis.directPropAmm, data: calls[1]!.data })
440
+ if (decoded.functionName !== 'swapExactInput') throw new Error('Expected an exact-input swap.')
441
+ const args = decoded.args
442
+ const expired = encodeFunctionData({
443
+ abi: Abis.directPropAmm,
444
+ functionName: 'swapExactInput',
445
+ args: [args[0], args[1], args[2], args[3], args[4], args[5], 1n, args[7], args[8], args[9]],
446
+ })
447
+ const reverted = await sendTransactionSync(client, {
448
+ calls: [calls[0]!, { ...calls[1]!, data: expired }],
449
+ throwOnReceiptRevert: false,
450
+ gas: 500_000n,
451
+ maxFeePerGas: 10_000_000_000n,
452
+ maxPriorityFeePerGas: 0n,
453
+ })
454
+ expect(reverted.status).toBe('reverted')
455
+ expect(
456
+ (
457
+ await Actions.token.getAllowance(client, {
458
+ account: sender,
459
+ spender: pool.pool,
460
+ token: pool.base,
461
+ })
462
+ ).amount,
463
+ ).toBe(0n)
464
+ await expect
465
+ .poll(
466
+ async () =>
467
+ (
468
+ await provider.verifySourceTransaction!(
469
+ {
470
+ destinationChain: chain,
471
+ providerState: selected.result.providerState,
472
+ sourceChain: chain,
473
+ transactionHash: reverted.transactionHash,
474
+ transfer: snapshot,
475
+ },
476
+ new AbortController().signal,
477
+ )
478
+ ).type,
479
+ { timeout: 30_000 },
480
+ )
481
+ .toBe('invalid')
482
+ })
483
+
484
+ test('reopens orphaned source evidence without losing prepared terms', async () => {
485
+ const request = {
486
+ body: JSON.stringify({
487
+ amount: '1000000',
488
+ destinationChain: 'tempo',
489
+ destinationToken: 'usdce',
490
+ mode: 'exactSource',
491
+ recipient,
492
+ sender,
493
+ sourceChain: 'tempo',
494
+ sourceToken: 'usdy',
495
+ }),
496
+ headers: {
497
+ 'content-type': 'application/json',
498
+ 'idempotency-key': 'propamm_reorg',
499
+ 'tempo-api-key': writer.token,
500
+ },
501
+ method: 'POST',
502
+ }
503
+ const response = await transfersApp.request('/v1/routes/transfers', request)
504
+ expect(response.status).toBe(200)
505
+ const created = await TestApp.json(response, Transfers.schema.createRoutesTransfer.Response)
506
+ const stored = (await TransfersTable.get(db, created.id))!
507
+ const transactionHash = Hex.random(32)
508
+ const chain = catalog.chainsByKey.get(`eip155:${pool.chainId}`)!
509
+ expect(
510
+ await provider.verifySourceTransaction!(
511
+ {
512
+ destinationChain: chain,
513
+ providerState: stored.providerState!,
514
+ sourceChain: chain,
515
+ transactionHash,
516
+ transfer: stored.snapshot,
517
+ },
518
+ new AbortController().signal,
519
+ ),
520
+ ).toEqual({ type: 'pending' })
521
+ const state = {
522
+ ...stored.providerState,
523
+ propAmmEvidence: {
524
+ amountOut: created.destinationAmount!.baseUnits,
525
+ blockHash: `0x${'aa'.repeat(32)}`,
526
+ blockNumber: '0',
527
+ transactionHash,
528
+ },
529
+ }
530
+ const registered = await Transfer.registerSourceTransactions(db, {
531
+ chainId: chain.id,
532
+ id: stored.id,
533
+ providerState: state,
534
+ transactionHashes: [transactionHash],
535
+ })
536
+ expect(registered.type).toBe('registered')
537
+ const tracker = Reconciliation.createTracker({ db, providers: [provider] })
538
+ expect(
539
+ await tracker.reconcile({ transferId: stored.id, type: 'routes:transfer:reconcile' }),
540
+ ).toEqual({ type: 'reopened' })
541
+ const reopened = (await TransfersTable.get(db, stored.id))!
542
+ expect(reopened.status).toBe('awaiting-source')
543
+ expect(reopened.providerState).toEqual(stored.providerState)
544
+ expect(reopened.snapshot.sourceTransactionHashes).toBeUndefined()
545
+ expect(await TransferTransactions.listByTransfer(db, stored.id)).toEqual([])
546
+ })
547
+
548
+ test('replays persisted preparation without requoting or generating another trade ID', async () => {
549
+ const request = {
550
+ body: JSON.stringify({
551
+ amount: '1000000',
552
+ destinationChain: 'tempo',
553
+ destinationToken: 'usdce',
554
+ mode: 'exactSource',
555
+ recipient,
556
+ sender,
557
+ sourceChain: 'tempo',
558
+ sourceToken: 'usdy',
559
+ }),
560
+ headers: {
561
+ 'content-type': 'application/json',
562
+ 'idempotency-key': 'propamm_replay',
563
+ 'tempo-api-key': writer.token,
564
+ },
565
+ method: 'POST',
566
+ }
567
+ const first = await transfersApp.request('/v1/routes/transfers', request)
568
+ expect(first.status).toBe(200)
569
+ const expected = await first.json()
570
+ await writeContractSync(client, {
571
+ abi: Abis.directPropAmm,
572
+ address: pool.pool,
573
+ functionName: 'pause',
574
+ })
575
+ try {
576
+ const replay = await transfersApp.request('/v1/routes/transfers', request)
577
+ expect(replay.status).toBe(200)
578
+ expect(await replay.json()).toEqual(expected)
579
+ } finally {
580
+ await writeContractSync(client, {
581
+ abi: Abis.directPropAmm,
582
+ address: pool.pool,
583
+ functionName: 'unpause',
584
+ })
585
+ }
586
+ })
587
+
588
+ test('requotes changed oracle prices at preparation', async () => {
589
+ const previous = await getQuotes()
590
+ expect(previous[0]?.destinationAmount.baseUnits).toBe('1250000')
591
+ const timestamp = (await getBlock(client)).timestamp
592
+ await writeContractSync(client, {
593
+ abi: Contracts.pushPriceOracle.abi,
594
+ address: pool.oracle,
595
+ args: [1_255_000_000_000_000_000n, timestamp],
596
+ functionName: 'pushPrice',
597
+ })
598
+ try {
599
+ const selected = await prepareTransfer()
600
+ expect(selected?.result.destinationAmount).toBe('1255000')
601
+ expect(selected?.result.providerState).toMatchObject({
602
+ propAmm: { expectedOraclePrice: '1255000000000000000' },
603
+ })
604
+ } finally {
605
+ await expect.poll(async () => (await getBlock(client)).timestamp).toBeGreaterThan(timestamp)
606
+ await writeContractSync(client, {
607
+ abi: Contracts.pushPriceOracle.abi,
608
+ address: pool.oracle,
609
+ args: [pool.price, (await getBlock(client)).timestamp],
610
+ functionName: 'pushPrice',
611
+ })
612
+ }
613
+ })
614
+
615
+ test.each([{ sender: denied }, { recipient: denied }])(
616
+ 'rejects ineligible preparation identities: %j',
617
+ async (identity) => {
618
+ const attempts: Provider.ProviderAttempt[] = []
619
+ expect(
620
+ await prepareTransfer({ ...identity, onAttempt: (attempt) => attempts.push(attempt) }),
621
+ ).toBeUndefined()
622
+ expect(attempts.map(({ operation, outcome }) => ({ operation, outcome }))).toEqual([
623
+ { operation: 'prepareTransfer', outcome: 'unavailable' },
624
+ ])
625
+ },
626
+ )
627
+
628
+ test('uses one RPC call for warm quotes and preparation', async () => {
629
+ const requests: string[] = []
630
+ const provider = PropAmm.propAmm({
631
+ async fetch(input, init) {
632
+ const { method } = JSON.parse(init!.body as string)
633
+ requests.push(method)
634
+ return fetch(input, init)
635
+ },
636
+ })
637
+ expect(await getQuotes({ providers: [provider] })).toHaveLength(1)
638
+ expect(requests).toMatchInlineSnapshot(`
639
+ [
640
+ "eth_call",
641
+ "eth_call",
642
+ ]
643
+ `)
644
+ requests.length = 0
645
+ expect(await getQuotes({ providers: [provider] })).toHaveLength(1)
646
+ expect(requests).toMatchInlineSnapshot(`
647
+ [
648
+ "eth_call",
649
+ ]
650
+ `)
651
+ requests.length = 0
652
+ expect(await prepareTransfer({ providers: [provider] })).toBeDefined()
653
+ expect(requests).toMatchInlineSnapshot(`
654
+ [
655
+ "eth_call",
656
+ ]
657
+ `)
658
+ requests.length = 0
659
+ expect(
660
+ await prepareTransfer({
661
+ destinationToken: 'usdy',
662
+ providers: [provider],
663
+ sourceToken: 'usdce',
664
+ }),
665
+ ).toBeDefined()
666
+ expect(requests).toMatchInlineSnapshot(`
667
+ [
668
+ "eth_call",
669
+ ]
670
+ `)
671
+ })
672
+
673
+ test.each([0, 10_000])('bounds minimum output at %i bps slippage', async (slippageBps) => {
674
+ const selected = await prepareTransfer({ slippageBps })
675
+ expect(selected?.result.destinationAmountMin).toBe(slippageBps === 0 ? '1250000' : '1')
676
+ })
677
+ })
678
+
679
+ describe.skipIf(Runtime.get().mode !== 'localnet')('quoteRoutes', () => {
680
+ test.each([
681
+ {
682
+ destinationToken: 'usdce',
683
+ expected: '2500000',
684
+ sourceAmount: '2000000',
685
+ sourceToken: 'usdy',
686
+ },
687
+ {
688
+ destinationToken: 'usdy',
689
+ expected: '2000000',
690
+ sourceAmount: '2500000',
691
+ sourceToken: 'usdce',
692
+ },
693
+ ])(
694
+ 'quotes $sourceToken to $destinationToken with the supplied identities',
695
+ async ({ expected, ...query }) => {
696
+ const response = await app.request(
697
+ `/v1/routes/quotes?${new URLSearchParams({ ...query, recipient, sender, sourceChain: 'tempo' })}`,
698
+ )
699
+ expect(response.status).toBe(200)
700
+ expect(response.headers.get('cache-control')).toBe('no-store')
701
+ const { data } = Quotes.schema.quoteRoutes.Response.parse(await response.json())
702
+ expect(data).toHaveLength(1)
703
+ expect(data[0]!.destinationAmount.baseUnits).toBe(expected)
704
+ expect(data[0]!.provider).toMatchInlineSnapshot(`
705
+ {
706
+ "id": "propamm",
707
+ "name": "PropAMM",
708
+ }
709
+ `)
710
+ expect(Date.parse(data[0]!.quote.expiresAt!)).toBeGreaterThan(Date.now())
711
+ },
712
+ )
713
+
714
+ test.each([
715
+ {
716
+ identity: { recipient, sender: '' },
717
+ detail: {
718
+ message: 'Sender and recipient addresses are required. Provide both addresses and retry.',
719
+ },
720
+ },
721
+ {
722
+ identity: { recipient: '', sender },
723
+ detail: {
724
+ message: 'Sender and recipient addresses are required. Provide both addresses and retry.',
725
+ },
726
+ },
727
+ {
728
+ identity: { recipient, sender: denied },
729
+ detail: {
730
+ message:
731
+ 'The sender is not authorized for this route. Use an approved sender address or request access before retrying.',
732
+ path: ['sender'],
733
+ },
734
+ },
735
+ {
736
+ identity: { recipient: denied, sender },
737
+ detail: {
738
+ message:
739
+ 'The recipient is not authorized for this route. Use an approved recipient address or request access before retrying.',
740
+ path: ['recipient'],
741
+ },
742
+ },
743
+ {
744
+ identity: { recipient, sender: 'invalid' },
745
+ detail: {
746
+ message:
747
+ 'A sender or recipient address is invalid. Check both addresses for the selected chains and retry.',
748
+ },
749
+ },
750
+ ])('returns an actionable error: $detail.message', async ({ identity, detail }) => {
751
+ const query = new URLSearchParams({
752
+ destinationToken: 'usdce',
753
+ sourceAmount: '1000000',
754
+ sourceChain: 'tempo',
755
+ sourceToken: 'usdy',
756
+ })
757
+ for (const [key, value] of Object.entries(identity)) if (value) query.set(key, value)
758
+ const response = await app.request(`/v1/routes/quotes?${query}`)
759
+ expect(response.status).toBe(400)
760
+ const body = await TestApp.json(response, Schema.ErrorResponse)
761
+ expect(body.error).toEqual({
762
+ code: 'route_unavailable',
763
+ details: [detail],
764
+ message: 'No route is available for this request. Review the details and retry.',
765
+ })
766
+ })
767
+
768
+ test('does not advertise unavailable pool inventory', async () => {
769
+ expect(
770
+ await Provider.getQuotes({
771
+ catalog,
772
+ destinationToken: 'usdce',
773
+ providers: [provider],
774
+ recipient,
775
+ sender,
776
+ sourceAmount: '1000000000',
777
+ sourceAmountUnits: 'baseUnits',
778
+ sourceChain: 'tempo',
779
+ sourceToken: 'usdy',
780
+ }),
781
+ ).toEqual([])
782
+ })
783
+
784
+ test('does not advertise a paused pool', async () => {
785
+ await writeContractSync(client, {
786
+ abi: Abis.directPropAmm,
787
+ address: pool.pool,
788
+ functionName: 'pause',
789
+ })
790
+ try {
791
+ expect(await getQuotes()).toEqual([])
792
+ } finally {
793
+ await writeContractSync(client, {
794
+ abi: Abis.directPropAmm,
795
+ address: pool.pool,
796
+ functionName: 'unpause',
797
+ })
798
+ }
799
+ })
800
+
801
+ test('records unexpected RPC failures through existing provider observability', async () => {
802
+ const attempts: Provider.ProviderAttempt[] = []
803
+ await expect(
804
+ Provider.getQuotes({
805
+ catalog,
806
+ destinationToken: 'usdce',
807
+ onAttempt: (attempt) => attempts.push(attempt),
808
+ providers: [PropAmm.propAmm({ resolveRpcUrls: () => ['http://127.0.0.1:1'] })],
809
+ recipient,
810
+ sender,
811
+ sourceAmount: '1000000',
812
+ sourceAmountUnits: 'baseUnits',
813
+ sourceChain: 'tempo',
814
+ sourceToken: 'usdy',
815
+ }),
816
+ ).rejects.toBeInstanceOf(Provider.ProviderQuoteError)
817
+ expect(
818
+ attempts.map(({ operation, outcome, provider }) => ({ id: provider.id, operation, outcome })),
819
+ ).toMatchInlineSnapshot(`
820
+ [
821
+ {
822
+ "id": "propamm",
823
+ "operation": "getQuote",
824
+ "outcome": "failed",
825
+ },
826
+ ]
827
+ `)
828
+ })
829
+
830
+ test('omits stale oracle quotes without treating them as RPC failures', async () => {
831
+ await writeContractSync(client, {
832
+ abi: Abis.directPropAmm,
833
+ address: pool.pool,
834
+ functionName: 'pause',
835
+ })
836
+ await writeContractSync(client, {
837
+ abi: Abis.directPropAmm,
838
+ address: pool.pool,
839
+ args: [10n],
840
+ functionName: 'setMaxOracleAge',
841
+ })
842
+ // Keep the oracle fresh while reopening the pool, then let it expire onchain.
843
+ const timestamp = (await getBlock(client)).timestamp
844
+ await writeContractSync(client, {
845
+ abi: Contracts.pushPriceOracle.abi,
846
+ address: pool.oracle,
847
+ args: [pool.price, timestamp],
848
+ functionName: 'pushPrice',
849
+ })
850
+ await writeContractSync(client, {
851
+ abi: Abis.directPropAmm,
852
+ address: pool.pool,
853
+ functionName: 'unpause',
854
+ // Explicit fees and gas avoid pending-block estimation beyond the short oracle lifetime.
855
+ gas: 500_000n,
856
+ maxFeePerGas: 10_000_000_000n,
857
+ maxPriorityFeePerGas: 0n,
858
+ })
859
+ await expect
860
+ .poll(async () => (await getBlock(client)).timestamp, { timeout: 15_000 })
861
+ .toBeGreaterThan(timestamp + 10n)
862
+ const attempts: Provider.ProviderAttempt[] = []
863
+ expect(await getQuotes({ onAttempt: (attempt) => attempts.push(attempt) })).toEqual([])
864
+ expect(attempts.map(({ outcome }) => outcome)).toEqual(['unavailable'])
865
+ })
866
+ })
867
+
868
+ describe.skipIf(Runtime.get().mode !== 'localnet')('getRoutesProviders', () => {
869
+ test('discovers PropAMM and its same-chain tokens', async () => {
870
+ const response = await app.request('/v1/routes/providers')
871
+ expect(await response.json()).toMatchInlineSnapshot(`
872
+ {
873
+ "data": [
874
+ {
875
+ "id": "propamm",
876
+ "name": "PropAMM",
877
+ },
878
+ ],
879
+ }
880
+ `)
881
+ expect(
882
+ TestRoutes.data.routes.filter(
883
+ (route) =>
884
+ route.providerId === 'propamm' &&
885
+ ['usdy', 'usdce'].includes(route.sourceTokenId) &&
886
+ ['usdy', 'usdce'].includes(route.destinationTokenId),
887
+ ),
888
+ ).toHaveLength(2)
889
+ expect(
890
+ TestRoutes.data.routes
891
+ .filter(
892
+ (route) =>
893
+ route.providerId === 'propamm' &&
894
+ ['usdy', 'usdce'].includes(route.sourceTokenId) &&
895
+ ['usdy', 'usdce'].includes(route.destinationTokenId),
896
+ )
897
+ .every((route) => route.capabilities?.transfer?.modes.join() === 'exactSource'),
898
+ ).toBe(true)
899
+ const chains = await app.request('/v1/routes/chains')
900
+ expect(chains.status).toBe(200)
901
+ expect(JSON.stringify(await chains.json())).toContain('USDY')
902
+ })
903
+ })
904
+
905
+ describe.skipIf(Runtime.get().mode !== 'localnet')('getOpenApi', () => {
906
+ test('documents optional quote identities with examples', async () => {
907
+ const response = await app.request('/openapi.json')
908
+ const spec = await response.json()
909
+ const parameters = spec.paths['/v1/routes/quotes'].get.parameters
910
+ for (const name of ['sender', 'recipient']) {
911
+ const parameter = parameters.find((parameter: { name: string }) => parameter.name === name)
912
+ expect(parameter).toMatchObject({ in: 'query', name })
913
+ expect(parameter.required ?? false).toBe(false)
914
+ expect(parameter.schema.examples).toHaveLength(1)
915
+ }
916
+ })
917
+ })
918
+
919
+ async function getQuotes(
920
+ options: Partial<Pick<Provider.getQuotes.Options, 'onAttempt' | 'providers'>> = {},
921
+ ) {
922
+ return Provider.getQuotes({
923
+ catalog,
924
+ destinationToken: 'usdce',
925
+ providers: [provider],
926
+ recipient,
927
+ sender,
928
+ sourceAmount: '1000000',
929
+ sourceAmountUnits: 'baseUnits',
930
+ sourceChain: 'tempo',
931
+ sourceToken: 'usdy',
932
+ ...options,
933
+ })
934
+ }
935
+
936
+ async function prepareTransfer(options: Partial<Provider.prepareTransfer.Options> = {}) {
937
+ return Provider.prepareTransfer({
938
+ catalog,
939
+ destinationChain: 'tempo',
940
+ destinationToken: 'usdce',
941
+ method: 'transaction',
942
+ mode: 'exactSource',
943
+ providers: [provider],
944
+ recipient,
945
+ sender,
946
+ sourceAmount: '1000000',
947
+ sourceChain: 'tempo',
948
+ sourceToken: 'usdy',
949
+ ...options,
950
+ })
951
+ }