@eco-incorp/sauce 0.99.5 → 0.99.7

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 (1197) hide show
  1. package/README.md +58 -16
  2. package/actions/action-program.schema.json +480 -379
  3. package/actions/dist/abis.d.ts +19 -18
  4. package/actions/dist/abis.d.ts.map +1 -1
  5. package/actions/dist/abis.js +29 -29
  6. package/actions/dist/compile.d.ts +4 -4
  7. package/actions/dist/compile.d.ts.map +1 -1
  8. package/actions/dist/compile.js +3 -1
  9. package/actions/dist/compose.d.ts +63 -6
  10. package/actions/dist/compose.d.ts.map +1 -1
  11. package/actions/dist/compose.js +100 -16
  12. package/actions/dist/index.d.ts +1 -1
  13. package/actions/dist/index.d.ts.map +1 -1
  14. package/actions/dist/names.d.ts +88 -0
  15. package/actions/dist/names.d.ts.map +1 -0
  16. package/actions/dist/names.js +324 -0
  17. package/actions/dist/program.d.ts.map +1 -1
  18. package/actions/dist/program.js +115 -5
  19. package/actions/dist/registry.d.ts +10 -8
  20. package/actions/dist/registry.d.ts.map +1 -1
  21. package/actions/dist/registry.js +10 -8
  22. package/actions/dist/schema.d.ts.map +1 -1
  23. package/actions/dist/schema.js +99 -12
  24. package/actions/dist/semantics.d.ts +12 -2
  25. package/actions/dist/semantics.d.ts.map +1 -1
  26. package/actions/dist/semantics.js +78 -8
  27. package/actions/dist/spec.d.ts +30 -0
  28. package/actions/dist/spec.d.ts.map +1 -1
  29. package/actions/dist/spec.js +151 -138
  30. package/actions/dist/split-swap.d.ts +10 -5
  31. package/actions/dist/split-swap.d.ts.map +1 -1
  32. package/actions/dist/split-swap.js +48 -7
  33. package/actions/dist/to-quote.d.ts +14 -5
  34. package/actions/dist/to-quote.d.ts.map +1 -1
  35. package/actions/dist/to-quote.js +210 -244
  36. package/actions/dist/to-sauce.d.ts +18 -4
  37. package/actions/dist/to-sauce.d.ts.map +1 -1
  38. package/actions/dist/to-sauce.js +232 -205
  39. package/actions/dist/types.d.ts +245 -147
  40. package/actions/dist/types.d.ts.map +1 -1
  41. package/actions/dist/types.js +4 -0
  42. package/docs/README.md +38 -0
  43. package/docs/api/README.md +37 -23
  44. package/docs/api/compiler.md +53 -12
  45. package/docs/api/contracts.md +105 -0
  46. package/docs/api/coverage.md +80 -57
  47. package/docs/api/router.md +238 -0
  48. package/docs/api/routes.md +31 -22
  49. package/docs/concepts/architecture.md +30 -5
  50. package/docs/concepts/saucescript.md +53 -56
  51. package/docs/examples/README.md +21 -14
  52. package/docs/examples/action-program.ts +51 -35
  53. package/docs/examples/cross-chain-cascade.sauce.ts +4 -0
  54. package/docs/examples/cross-chain-intent.sauce.ts +2 -1
  55. package/docs/examples/evm-execution.ts +2 -4
  56. package/docs/examples/first-intent.ts +7 -2
  57. package/docs/examples/pot-router.ts +19 -0
  58. package/docs/examples/registry-names.ts +52 -0
  59. package/docs/examples/router-route.sauce.ts +31 -0
  60. package/docs/examples/router-route.ts +72 -0
  61. package/docs/examples/router-swap.sauce.ts +16 -0
  62. package/docs/examples/router-swap.ts +47 -0
  63. package/docs/examples/venue-where-deployed.sauce.ts +14 -0
  64. package/docs/guides/actions.md +230 -120
  65. package/docs/guides/builders-and-actions.md +24 -15
  66. package/docs/guides/cli.md +1442 -0
  67. package/docs/guides/compiling.md +24 -10
  68. package/docs/guides/intents.md +260 -17
  69. package/docs/guides/mcp.md +539 -0
  70. package/docs/guides/nested-intents.md +21 -6
  71. package/docs/guides/protocols-and-tokens.md +235 -36
  72. package/docs/guides/quick-start.md +5 -0
  73. package/docs/guides/solana.md +199 -52
  74. package/docs/guides/verification.md +2 -2
  75. package/mcp/dist/config.js +78 -0
  76. package/mcp/dist/config.js.map +1 -0
  77. package/mcp/dist/entry.js +112 -0
  78. package/mcp/dist/entry.js.map +1 -0
  79. package/mcp/dist/files.js +64 -0
  80. package/mcp/dist/files.js.map +1 -0
  81. package/mcp/dist/guard.js +262 -0
  82. package/mcp/dist/guard.js.map +1 -0
  83. package/mcp/dist/http.js +111 -0
  84. package/mcp/dist/http.js.map +1 -0
  85. package/mcp/dist/intents.js +579 -0
  86. package/mcp/dist/intents.js.map +1 -0
  87. package/mcp/dist/prompts.js +153 -0
  88. package/mcp/dist/prompts.js.map +1 -0
  89. package/mcp/dist/reach.js +98 -0
  90. package/mcp/dist/reach.js.map +1 -0
  91. package/mcp/dist/resources.js +154 -0
  92. package/mcp/dist/resources.js.map +1 -0
  93. package/mcp/dist/sdk.js +34 -0
  94. package/mcp/dist/sdk.js.map +1 -0
  95. package/mcp/dist/server.js +119 -0
  96. package/mcp/dist/server.js.map +1 -0
  97. package/mcp/dist/setup.js +189 -0
  98. package/mcp/dist/setup.js.map +1 -0
  99. package/mcp/dist/skilltools.js +520 -0
  100. package/mcp/dist/skilltools.js.map +1 -0
  101. package/mcp/dist/terms.js +93 -0
  102. package/mcp/dist/terms.js.map +1 -0
  103. package/mcp/dist/tools.js +1497 -0
  104. package/mcp/dist/tools.js.map +1 -0
  105. package/mcp/dist/wallets.js +168 -0
  106. package/mcp/dist/wallets.js.map +1 -0
  107. package/package.json +18 -13
  108. package/sdk/dist/artifacts/V12Deployments.json +3 -1
  109. package/sdk/dist/artifacts/V12EngineGate.json +1 -2
  110. package/sdk/dist/artifacts/V12KitchenProxy.json +1 -0
  111. package/sdk/dist/chains/canonical.d.ts +15 -24
  112. package/sdk/dist/chains/canonical.d.ts.map +1 -1
  113. package/sdk/dist/chains/canonical.js +18 -29
  114. package/sdk/dist/chains/canonical.js.map +1 -1
  115. package/sdk/dist/cli/actions.d.ts +29 -0
  116. package/sdk/dist/cli/actions.d.ts.map +1 -0
  117. package/sdk/dist/cli/actions.js +122 -0
  118. package/sdk/dist/cli/actions.js.map +1 -0
  119. package/sdk/dist/cli/args.d.ts +118 -0
  120. package/sdk/dist/cli/args.d.ts.map +1 -0
  121. package/sdk/dist/cli/args.js +354 -0
  122. package/sdk/dist/cli/args.js.map +1 -0
  123. package/sdk/dist/cli/assume.d.ts +51 -0
  124. package/sdk/dist/cli/assume.d.ts.map +1 -0
  125. package/sdk/dist/cli/assume.js +207 -0
  126. package/sdk/dist/cli/assume.js.map +1 -0
  127. package/sdk/dist/cli/chain.d.ts +170 -0
  128. package/sdk/dist/cli/chain.d.ts.map +1 -0
  129. package/sdk/dist/cli/chain.js +457 -0
  130. package/sdk/dist/cli/chain.js.map +1 -0
  131. package/sdk/dist/cli/commands.d.ts +226 -0
  132. package/sdk/dist/cli/commands.d.ts.map +1 -0
  133. package/sdk/dist/cli/commands.js +637 -0
  134. package/sdk/dist/cli/commands.js.map +1 -0
  135. package/sdk/dist/cli/create.d.ts +70 -0
  136. package/sdk/dist/cli/create.d.ts.map +1 -0
  137. package/sdk/dist/cli/create.js +483 -0
  138. package/sdk/dist/cli/create.js.map +1 -0
  139. package/sdk/dist/cli/diagnostics.d.ts +12 -0
  140. package/sdk/dist/cli/diagnostics.d.ts.map +1 -0
  141. package/sdk/dist/cli/diagnostics.js +200 -0
  142. package/sdk/dist/cli/diagnostics.js.map +1 -0
  143. package/sdk/dist/cli/effects.d.ts +71 -0
  144. package/sdk/dist/cli/effects.d.ts.map +1 -0
  145. package/sdk/dist/cli/effects.js +279 -0
  146. package/sdk/dist/cli/effects.js.map +1 -0
  147. package/sdk/dist/cli/fill.d.ts +83 -0
  148. package/sdk/dist/cli/fill.d.ts.map +1 -0
  149. package/sdk/dist/cli/fill.js +734 -0
  150. package/sdk/dist/cli/fill.js.map +1 -0
  151. package/sdk/dist/cli/funding.d.ts +126 -0
  152. package/sdk/dist/cli/funding.d.ts.map +1 -0
  153. package/sdk/dist/cli/funding.js +514 -0
  154. package/sdk/dist/cli/funding.js.map +1 -0
  155. package/sdk/dist/cli/globals.d.ts +16 -0
  156. package/sdk/dist/cli/globals.d.ts.map +1 -0
  157. package/sdk/dist/cli/globals.js +197 -0
  158. package/sdk/dist/cli/globals.js.map +1 -0
  159. package/sdk/dist/cli/init.d.ts +34 -0
  160. package/sdk/dist/cli/init.d.ts.map +1 -0
  161. package/sdk/dist/cli/init.js +181 -0
  162. package/sdk/dist/cli/init.js.map +1 -0
  163. package/sdk/dist/cli/inputs.d.ts +72 -0
  164. package/sdk/dist/cli/inputs.d.ts.map +1 -0
  165. package/sdk/dist/cli/inputs.js +152 -0
  166. package/sdk/dist/cli/inputs.js.map +1 -0
  167. package/sdk/dist/cli/inspect.d.ts +48 -0
  168. package/sdk/dist/cli/inspect.d.ts.map +1 -0
  169. package/sdk/dist/cli/inspect.js +536 -0
  170. package/sdk/dist/cli/inspect.js.map +1 -0
  171. package/sdk/dist/cli/intent-commands.d.ts +71 -0
  172. package/sdk/dist/cli/intent-commands.d.ts.map +1 -0
  173. package/sdk/dist/cli/intent-commands.js +698 -0
  174. package/sdk/dist/cli/intent-commands.js.map +1 -0
  175. package/sdk/dist/cli/intent-svm.d.ts +15 -0
  176. package/sdk/dist/cli/intent-svm.d.ts.map +1 -0
  177. package/sdk/dist/cli/intent-svm.js +222 -0
  178. package/sdk/dist/cli/intent-svm.js.map +1 -0
  179. package/sdk/dist/cli/intents.d.ts +43 -0
  180. package/sdk/dist/cli/intents.d.ts.map +1 -0
  181. package/sdk/dist/cli/intents.js +89 -0
  182. package/sdk/dist/cli/intents.js.map +1 -0
  183. package/sdk/dist/cli/interactive.d.ts +11 -0
  184. package/sdk/dist/cli/interactive.d.ts.map +1 -0
  185. package/sdk/dist/cli/interactive.js +161 -0
  186. package/sdk/dist/cli/interactive.js.map +1 -0
  187. package/sdk/dist/cli/lifecycle-svm.d.ts +109 -0
  188. package/sdk/dist/cli/lifecycle-svm.d.ts.map +1 -0
  189. package/sdk/dist/cli/lifecycle-svm.js +299 -0
  190. package/sdk/dist/cli/lifecycle-svm.js.map +1 -0
  191. package/sdk/dist/cli/lifecycle.d.ts +439 -0
  192. package/sdk/dist/cli/lifecycle.d.ts.map +1 -0
  193. package/sdk/dist/cli/lifecycle.js +1721 -0
  194. package/sdk/dist/cli/lifecycle.js.map +1 -0
  195. package/sdk/dist/cli/main.d.ts +3 -0
  196. package/sdk/dist/cli/main.d.ts.map +1 -0
  197. package/sdk/dist/cli/main.js +8 -0
  198. package/sdk/dist/cli/main.js.map +1 -0
  199. package/sdk/dist/cli/mcp.d.ts +66 -0
  200. package/sdk/dist/cli/mcp.d.ts.map +1 -0
  201. package/sdk/dist/cli/mcp.js +169 -0
  202. package/sdk/dist/cli/mcp.js.map +1 -0
  203. package/sdk/dist/cli/password.d.ts +54 -0
  204. package/sdk/dist/cli/password.d.ts.map +1 -0
  205. package/sdk/dist/cli/password.js +148 -0
  206. package/sdk/dist/cli/password.js.map +1 -0
  207. package/sdk/dist/cli/policy.d.ts +130 -0
  208. package/sdk/dist/cli/policy.d.ts.map +1 -0
  209. package/sdk/dist/cli/policy.js +702 -0
  210. package/sdk/dist/cli/policy.js.map +1 -0
  211. package/sdk/dist/cli/pools.d.ts +140 -0
  212. package/sdk/dist/cli/pools.d.ts.map +1 -0
  213. package/sdk/dist/cli/pools.js +658 -0
  214. package/sdk/dist/cli/pools.js.map +1 -0
  215. package/sdk/dist/cli/price.d.ts +74 -0
  216. package/sdk/dist/cli/price.d.ts.map +1 -0
  217. package/sdk/dist/cli/price.js +321 -0
  218. package/sdk/dist/cli/price.js.map +1 -0
  219. package/sdk/dist/cli/prompt.d.ts +30 -0
  220. package/sdk/dist/cli/prompt.d.ts.map +1 -0
  221. package/sdk/dist/cli/prompt.js +53 -0
  222. package/sdk/dist/cli/prompt.js.map +1 -0
  223. package/sdk/dist/cli/publish.d.ts +48 -0
  224. package/sdk/dist/cli/publish.d.ts.map +1 -0
  225. package/sdk/dist/cli/publish.js +480 -0
  226. package/sdk/dist/cli/publish.js.map +1 -0
  227. package/sdk/dist/cli/receipt.d.ts +35 -0
  228. package/sdk/dist/cli/receipt.d.ts.map +1 -0
  229. package/sdk/dist/cli/receipt.js +63 -0
  230. package/sdk/dist/cli/receipt.js.map +1 -0
  231. package/sdk/dist/cli/rehearse.d.ts +80 -0
  232. package/sdk/dist/cli/rehearse.d.ts.map +1 -0
  233. package/sdk/dist/cli/rehearse.js +265 -0
  234. package/sdk/dist/cli/rehearse.js.map +1 -0
  235. package/sdk/dist/cli/report.d.ts +69 -0
  236. package/sdk/dist/cli/report.d.ts.map +1 -0
  237. package/sdk/dist/cli/report.js +206 -0
  238. package/sdk/dist/cli/report.js.map +1 -0
  239. package/sdk/dist/cli/returned.d.ts +16 -0
  240. package/sdk/dist/cli/returned.d.ts.map +1 -0
  241. package/sdk/dist/cli/returned.js +111 -0
  242. package/sdk/dist/cli/returned.js.map +1 -0
  243. package/sdk/dist/cli/run.d.ts +40 -0
  244. package/sdk/dist/cli/run.d.ts.map +1 -0
  245. package/sdk/dist/cli/run.js +3162 -0
  246. package/sdk/dist/cli/run.js.map +1 -0
  247. package/sdk/dist/cli/signer.d.ts +72 -0
  248. package/sdk/dist/cli/signer.d.ts.map +1 -0
  249. package/sdk/dist/cli/signer.js +243 -0
  250. package/sdk/dist/cli/signer.js.map +1 -0
  251. package/sdk/dist/cli/simulate.d.ts +11 -0
  252. package/sdk/dist/cli/simulate.d.ts.map +1 -0
  253. package/sdk/dist/cli/simulate.js +246 -0
  254. package/sdk/dist/cli/simulate.js.map +1 -0
  255. package/sdk/dist/cli/skills.d.ts +77 -0
  256. package/sdk/dist/cli/skills.d.ts.map +1 -0
  257. package/sdk/dist/cli/skills.js +527 -0
  258. package/sdk/dist/cli/skills.js.map +1 -0
  259. package/sdk/dist/cli/solana.d.ts +183 -0
  260. package/sdk/dist/cli/solana.d.ts.map +1 -0
  261. package/sdk/dist/cli/solana.js +1360 -0
  262. package/sdk/dist/cli/solana.js.map +1 -0
  263. package/sdk/dist/cli/store.d.ts +60 -0
  264. package/sdk/dist/cli/store.d.ts.map +1 -0
  265. package/sdk/dist/cli/store.js +196 -0
  266. package/sdk/dist/cli/store.js.map +1 -0
  267. package/sdk/dist/cli/support.d.ts +144 -0
  268. package/sdk/dist/cli/support.d.ts.map +1 -0
  269. package/sdk/dist/cli/support.js +217 -0
  270. package/sdk/dist/cli/support.js.map +1 -0
  271. package/sdk/dist/cli/svm-effects.d.ts +50 -0
  272. package/sdk/dist/cli/svm-effects.d.ts.map +1 -0
  273. package/sdk/dist/cli/svm-effects.js +196 -0
  274. package/sdk/dist/cli/svm-effects.js.map +1 -0
  275. package/sdk/dist/cli/terminal.d.ts +42 -0
  276. package/sdk/dist/cli/terminal.d.ts.map +1 -0
  277. package/sdk/dist/cli/terminal.js +136 -0
  278. package/sdk/dist/cli/terminal.js.map +1 -0
  279. package/sdk/dist/cli/verify.d.ts +32 -0
  280. package/sdk/dist/cli/verify.d.ts.map +1 -0
  281. package/sdk/dist/cli/verify.js +185 -0
  282. package/sdk/dist/cli/verify.js.map +1 -0
  283. package/sdk/dist/cli/wallet-commands.d.ts +59 -0
  284. package/sdk/dist/cli/wallet-commands.d.ts.map +1 -0
  285. package/sdk/dist/cli/wallet-commands.js +222 -0
  286. package/sdk/dist/cli/wallet-commands.js.map +1 -0
  287. package/sdk/dist/cli/wallet-send.d.ts +38 -0
  288. package/sdk/dist/cli/wallet-send.d.ts.map +1 -0
  289. package/sdk/dist/cli/wallet-send.js +303 -0
  290. package/sdk/dist/cli/wallet-send.js.map +1 -0
  291. package/sdk/dist/cli/wallets.d.ts +79 -0
  292. package/sdk/dist/cli/wallets.d.ts.map +1 -0
  293. package/sdk/dist/cli/wallets.js +297 -0
  294. package/sdk/dist/cli/wallets.js.map +1 -0
  295. package/sdk/dist/deployments/index.d.ts +4 -62
  296. package/sdk/dist/deployments/index.d.ts.map +1 -1
  297. package/sdk/dist/deployments/index.js +4 -84
  298. package/sdk/dist/deployments/index.js.map +1 -1
  299. package/sdk/dist/deployments/pot.d.ts +17 -7
  300. package/sdk/dist/deployments/pot.d.ts.map +1 -1
  301. package/sdk/dist/deployments/pot.js +25 -10
  302. package/sdk/dist/deployments/pot.js.map +1 -1
  303. package/sdk/dist/deployments/releases.d.ts +36 -0
  304. package/sdk/dist/deployments/releases.d.ts.map +1 -0
  305. package/sdk/dist/deployments/releases.js +61 -0
  306. package/sdk/dist/deployments/releases.js.map +1 -0
  307. package/sdk/dist/deployments/releases.json +76 -0
  308. package/sdk/dist/deployments/v12-addresses.d.ts +13 -0
  309. package/sdk/dist/deployments/v12-addresses.d.ts.map +1 -1
  310. package/sdk/dist/deployments/v12-addresses.js +16 -3
  311. package/sdk/dist/deployments/v12-addresses.js.map +1 -1
  312. package/sdk/dist/deposit/index.d.ts +6 -6
  313. package/sdk/dist/deposit/index.d.ts.map +1 -1
  314. package/sdk/dist/deposit/index.js +1 -1
  315. package/sdk/dist/deposit/index.js.map +1 -1
  316. package/sdk/dist/deposit/params.d.ts +4 -4
  317. package/sdk/dist/deposit/params.d.ts.map +1 -1
  318. package/sdk/dist/deposit/params.js +7 -4
  319. package/sdk/dist/deposit/params.js.map +1 -1
  320. package/sdk/dist/deposit/source.d.ts +3 -30
  321. package/sdk/dist/deposit/source.d.ts.map +1 -1
  322. package/sdk/dist/deposit/source.js +7 -83
  323. package/sdk/dist/deposit/source.js.map +1 -1
  324. package/sdk/dist/deposit/templates.d.ts +1 -2
  325. package/sdk/dist/deposit/templates.d.ts.map +1 -1
  326. package/sdk/dist/deposit/templates.js +10 -2
  327. package/sdk/dist/deposit/templates.js.map +1 -1
  328. package/sdk/dist/deposit/types.d.ts +14 -12
  329. package/sdk/dist/deposit/types.d.ts.map +1 -1
  330. package/sdk/dist/deposit/types.js +6 -0
  331. package/sdk/dist/deposit/types.js.map +1 -1
  332. package/sdk/dist/descriptors/accessors.d.ts +38 -35
  333. package/sdk/dist/descriptors/accessors.d.ts.map +1 -1
  334. package/sdk/dist/descriptors/accessors.js +16 -0
  335. package/sdk/dist/descriptors/accessors.js.map +1 -1
  336. package/sdk/dist/descriptors/call.d.ts +66 -14
  337. package/sdk/dist/descriptors/call.d.ts.map +1 -1
  338. package/sdk/dist/descriptors/call.js +94 -13
  339. package/sdk/dist/descriptors/call.js.map +1 -1
  340. package/sdk/dist/descriptors/contracts.generated.d.ts +3393 -0
  341. package/sdk/dist/descriptors/contracts.generated.d.ts.map +1 -0
  342. package/sdk/dist/descriptors/contracts.generated.js +728 -0
  343. package/sdk/dist/descriptors/contracts.generated.js.map +1 -0
  344. package/sdk/dist/descriptors/derive.d.ts +20 -11
  345. package/sdk/dist/descriptors/derive.d.ts.map +1 -1
  346. package/sdk/dist/descriptors/derive.js +68 -30
  347. package/sdk/dist/descriptors/derive.js.map +1 -1
  348. package/sdk/dist/descriptors/index.d.ts +6 -7
  349. package/sdk/dist/descriptors/index.d.ts.map +1 -1
  350. package/sdk/dist/descriptors/index.js +2 -2
  351. package/sdk/dist/descriptors/index.js.map +1 -1
  352. package/sdk/dist/descriptors/links.d.ts +23 -214
  353. package/sdk/dist/descriptors/links.d.ts.map +1 -1
  354. package/sdk/dist/descriptors/links.js +1 -232
  355. package/sdk/dist/descriptors/links.js.map +1 -1
  356. package/sdk/dist/descriptors/query.d.ts +1 -1
  357. package/sdk/dist/descriptors/query.d.ts.map +1 -1
  358. package/sdk/dist/descriptors/query.js +1 -1
  359. package/sdk/dist/descriptors/query.js.map +1 -1
  360. package/sdk/dist/descriptors/registry.d.ts +2 -5
  361. package/sdk/dist/descriptors/registry.d.ts.map +1 -1
  362. package/sdk/dist/descriptors/registry.js +11 -66
  363. package/sdk/dist/descriptors/registry.js.map +1 -1
  364. package/sdk/dist/embedded/resolve.d.ts +4 -4
  365. package/sdk/dist/embedded/resolve.d.ts.map +1 -1
  366. package/sdk/dist/embedded/resolve.js +12 -8
  367. package/sdk/dist/embedded/resolve.js.map +1 -1
  368. package/sdk/dist/embedded/skills.generated.d.ts +1 -1
  369. package/sdk/dist/embedded/skills.generated.d.ts.map +1 -1
  370. package/sdk/dist/embedded/skills.generated.js +137 -136
  371. package/sdk/dist/embedded/skills.generated.js.map +1 -1
  372. package/sdk/dist/embedded/sources.generated.d.ts.map +1 -1
  373. package/sdk/dist/embedded/sources.generated.js +40 -6
  374. package/sdk/dist/embedded/sources.generated.js.map +1 -1
  375. package/sdk/dist/evm/engine.d.ts +813 -10
  376. package/sdk/dist/evm/engine.d.ts.map +1 -1
  377. package/sdk/dist/evm/engine.js +127 -8
  378. package/sdk/dist/evm/engine.js.map +1 -1
  379. package/sdk/dist/index.d.ts +3 -2
  380. package/sdk/dist/index.d.ts.map +1 -1
  381. package/sdk/dist/index.js +6 -2
  382. package/sdk/dist/index.js.map +1 -1
  383. package/sdk/dist/plugin/index.d.ts +3 -2
  384. package/sdk/dist/plugin/index.d.ts.map +1 -1
  385. package/sdk/dist/plugin/index.js.map +1 -1
  386. package/sdk/dist/price.d.ts +40 -0
  387. package/sdk/dist/price.d.ts.map +1 -0
  388. package/sdk/dist/price.js +101 -0
  389. package/sdk/dist/price.js.map +1 -0
  390. package/sdk/dist/protocols/aerodrome/abis.d.ts +76 -0
  391. package/sdk/dist/protocols/aerodrome/abis.d.ts.map +1 -1
  392. package/sdk/dist/protocols/aerodrome/abis.js +61 -0
  393. package/sdk/dist/protocols/aerodrome/abis.js.map +1 -1
  394. package/sdk/dist/protocols/aerodrome-slipstream/abis.d.ts +70 -0
  395. package/sdk/dist/protocols/aerodrome-slipstream/abis.d.ts.map +1 -1
  396. package/sdk/dist/protocols/aerodrome-slipstream/abis.js +54 -0
  397. package/sdk/dist/protocols/aerodrome-slipstream/abis.js.map +1 -1
  398. package/sdk/dist/protocols/camelot/abis.d.ts +178 -0
  399. package/sdk/dist/protocols/camelot/abis.d.ts.map +1 -1
  400. package/sdk/dist/protocols/camelot/abis.js +139 -0
  401. package/sdk/dist/protocols/camelot/abis.js.map +1 -1
  402. package/sdk/dist/protocols/cbeth/functions.d.ts +2 -2
  403. package/sdk/dist/protocols/cbeth/functions.d.ts.map +1 -1
  404. package/sdk/dist/protocols/cbeth/functions.js +4 -6
  405. package/sdk/dist/protocols/cbeth/functions.js.map +1 -1
  406. package/sdk/dist/protocols/crvusd/functions.d.ts +2 -2
  407. package/sdk/dist/protocols/crvusd/functions.d.ts.map +1 -1
  408. package/sdk/dist/protocols/crvusd/functions.js +6 -6
  409. package/sdk/dist/protocols/eco-routes/abis.d.ts +792 -50
  410. package/sdk/dist/protocols/eco-routes/abis.d.ts.map +1 -1
  411. package/sdk/dist/protocols/eco-routes/abis.js +1058 -49
  412. package/sdk/dist/protocols/eco-routes/abis.js.map +1 -1
  413. package/sdk/dist/protocols/eco-routes/addresses.generated.d.ts +44 -61
  414. package/sdk/dist/protocols/eco-routes/addresses.generated.d.ts.map +1 -1
  415. package/sdk/dist/protocols/eco-routes/addresses.generated.js +45 -62
  416. package/sdk/dist/protocols/eco-routes/addresses.generated.js.map +1 -1
  417. package/sdk/dist/protocols/eco-routes/lookup.d.ts +10 -0
  418. package/sdk/dist/protocols/eco-routes/lookup.d.ts.map +1 -1
  419. package/sdk/dist/protocols/eco-routes/lookup.js +16 -0
  420. package/sdk/dist/protocols/eco-routes/lookup.js.map +1 -1
  421. package/sdk/dist/protocols/erc20/functions.d.ts +3 -3
  422. package/sdk/dist/protocols/erc20/functions.d.ts.map +1 -1
  423. package/sdk/dist/protocols/erc20/functions.js +6 -9
  424. package/sdk/dist/protocols/erc20/functions.js.map +1 -1
  425. package/sdk/dist/protocols/frax/functions.d.ts +2 -2
  426. package/sdk/dist/protocols/frax/functions.d.ts.map +1 -1
  427. package/sdk/dist/protocols/frax/functions.js +6 -6
  428. package/sdk/dist/protocols/gho/functions.d.ts +2 -2
  429. package/sdk/dist/protocols/gho/functions.d.ts.map +1 -1
  430. package/sdk/dist/protocols/gho/functions.js +4 -6
  431. package/sdk/dist/protocols/gho/functions.js.map +1 -1
  432. package/sdk/dist/protocols/liquity-v2/functions.d.ts +2 -2
  433. package/sdk/dist/protocols/liquity-v2/functions.d.ts.map +1 -1
  434. package/sdk/dist/protocols/liquity-v2/functions.js +4 -6
  435. package/sdk/dist/protocols/liquity-v2/functions.js.map +1 -1
  436. package/sdk/dist/protocols/maverick/abis.d.ts +77 -0
  437. package/sdk/dist/protocols/maverick/abis.d.ts.map +1 -1
  438. package/sdk/dist/protocols/maverick/abis.js +58 -0
  439. package/sdk/dist/protocols/maverick/abis.js.map +1 -1
  440. package/sdk/dist/protocols/maverick/addresses.d.ts.map +1 -1
  441. package/sdk/dist/protocols/maverick/addresses.js +4 -0
  442. package/sdk/dist/protocols/maverick/addresses.js.map +1 -1
  443. package/sdk/dist/protocols/pancakeswap-v2/abis.d.ts +52 -0
  444. package/sdk/dist/protocols/pancakeswap-v2/abis.d.ts.map +1 -1
  445. package/sdk/dist/protocols/pancakeswap-v2/abis.js +43 -0
  446. package/sdk/dist/protocols/pancakeswap-v2/abis.js.map +1 -1
  447. package/sdk/dist/protocols/pancakeswap-v3/abis.d.ts +73 -0
  448. package/sdk/dist/protocols/pancakeswap-v3/abis.d.ts.map +1 -1
  449. package/sdk/dist/protocols/pancakeswap-v3/abis.js +56 -0
  450. package/sdk/dist/protocols/pancakeswap-v3/abis.js.map +1 -1
  451. package/sdk/dist/protocols/permit2/abis.d.ts +113 -0
  452. package/sdk/dist/protocols/permit2/abis.d.ts.map +1 -1
  453. package/sdk/dist/protocols/permit2/abis.js +63 -0
  454. package/sdk/dist/protocols/permit2/abis.js.map +1 -1
  455. package/sdk/dist/protocols/quickswap/abis.d.ts +148 -0
  456. package/sdk/dist/protocols/quickswap/abis.d.ts.map +1 -1
  457. package/sdk/dist/protocols/quickswap/abis.js +119 -0
  458. package/sdk/dist/protocols/quickswap/abis.js.map +1 -1
  459. package/sdk/dist/protocols/sushiswap-v2/abis.d.ts +52 -0
  460. package/sdk/dist/protocols/sushiswap-v2/abis.d.ts.map +1 -1
  461. package/sdk/dist/protocols/sushiswap-v2/abis.js +42 -0
  462. package/sdk/dist/protocols/sushiswap-v2/abis.js.map +1 -1
  463. package/sdk/dist/protocols/synthra-v3/abis.d.ts +73 -0
  464. package/sdk/dist/protocols/synthra-v3/abis.d.ts.map +1 -1
  465. package/sdk/dist/protocols/synthra-v3/abis.js +55 -0
  466. package/sdk/dist/protocols/synthra-v3/abis.js.map +1 -1
  467. package/sdk/dist/protocols/trader-joe/abis.d.ts +133 -0
  468. package/sdk/dist/protocols/trader-joe/abis.d.ts.map +1 -1
  469. package/sdk/dist/protocols/trader-joe/abis.js +101 -0
  470. package/sdk/dist/protocols/trader-joe/abis.js.map +1 -1
  471. package/sdk/dist/protocols/trader-joe/addresses.d.ts.map +1 -1
  472. package/sdk/dist/protocols/trader-joe/addresses.js +5 -0
  473. package/sdk/dist/protocols/trader-joe/addresses.js.map +1 -1
  474. package/sdk/dist/protocols/uniswap-v2/abis.d.ts +52 -0
  475. package/sdk/dist/protocols/uniswap-v2/abis.d.ts.map +1 -1
  476. package/sdk/dist/protocols/uniswap-v2/abis.js +44 -0
  477. package/sdk/dist/protocols/uniswap-v2/abis.js.map +1 -1
  478. package/sdk/dist/protocols/uniswap-v3/abis.d.ts +73 -0
  479. package/sdk/dist/protocols/uniswap-v3/abis.d.ts.map +1 -1
  480. package/sdk/dist/protocols/uniswap-v3/abis.js +55 -0
  481. package/sdk/dist/protocols/uniswap-v3/abis.js.map +1 -1
  482. package/sdk/dist/protocols/uniswap-v4/abis.d.ts +247 -0
  483. package/sdk/dist/protocols/uniswap-v4/abis.d.ts.map +1 -1
  484. package/sdk/dist/protocols/uniswap-v4/abis.js +167 -0
  485. package/sdk/dist/protocols/uniswap-v4/abis.js.map +1 -1
  486. package/sdk/dist/protocols/uniswap-v4/addresses.d.ts.map +1 -1
  487. package/sdk/dist/protocols/uniswap-v4/addresses.js +50 -0
  488. package/sdk/dist/protocols/uniswap-v4/addresses.js.map +1 -1
  489. package/sdk/dist/protocols/unitflow-v3/abis.d.ts +73 -0
  490. package/sdk/dist/protocols/unitflow-v3/abis.d.ts.map +1 -1
  491. package/sdk/dist/protocols/unitflow-v3/abis.js +56 -0
  492. package/sdk/dist/protocols/unitflow-v3/abis.js.map +1 -1
  493. package/sdk/dist/protocols/velodrome/abis.d.ts +76 -0
  494. package/sdk/dist/protocols/velodrome/abis.d.ts.map +1 -1
  495. package/sdk/dist/protocols/velodrome/abis.js +61 -0
  496. package/sdk/dist/protocols/velodrome/abis.js.map +1 -1
  497. package/sdk/dist/recipes/cctp-split.sauce.ts +5 -3
  498. package/sdk/dist/recipes/plain-transfer.sauce.ts +5 -2
  499. package/sdk/dist/routes/accessor-index.d.ts +2 -2
  500. package/sdk/dist/routes/accessor-index.d.ts.map +1 -1
  501. package/sdk/dist/routes/accessor-index.js +4 -3
  502. package/sdk/dist/routes/accessor-index.js.map +1 -1
  503. package/sdk/dist/routes/ambient.d.ts +5 -0
  504. package/sdk/dist/routes/ambient.d.ts.map +1 -1
  505. package/sdk/dist/routes/ambient.js +20 -0
  506. package/sdk/dist/routes/ambient.js.map +1 -1
  507. package/sdk/dist/routes/ast-walk.d.ts +21 -3
  508. package/sdk/dist/routes/ast-walk.d.ts.map +1 -1
  509. package/sdk/dist/routes/ast-walk.js +33 -4
  510. package/sdk/dist/routes/ast-walk.js.map +1 -1
  511. package/sdk/dist/routes/available.d.ts +43 -0
  512. package/sdk/dist/routes/available.d.ts.map +1 -0
  513. package/sdk/dist/routes/available.js +230 -0
  514. package/sdk/dist/routes/available.js.map +1 -0
  515. package/sdk/dist/routes/builtins.generated.d.ts +180 -0
  516. package/sdk/dist/routes/builtins.generated.d.ts.map +1 -0
  517. package/sdk/dist/routes/builtins.generated.js +2 -0
  518. package/sdk/dist/routes/builtins.generated.js.map +1 -0
  519. package/sdk/dist/routes/chain-exports.generated.d.ts +13 -8
  520. package/sdk/dist/routes/chain-exports.generated.d.ts.map +1 -1
  521. package/sdk/dist/routes/chain-exports.generated.js.map +1 -1
  522. package/sdk/dist/routes/closure.d.ts.map +1 -1
  523. package/sdk/dist/routes/closure.js +13 -26
  524. package/sdk/dist/routes/closure.js.map +1 -1
  525. package/sdk/dist/routes/composed.d.ts.map +1 -1
  526. package/sdk/dist/routes/composed.js +20 -8
  527. package/sdk/dist/routes/composed.js.map +1 -1
  528. package/sdk/dist/routes/encode.d.ts +17 -0
  529. package/sdk/dist/routes/encode.d.ts.map +1 -1
  530. package/sdk/dist/routes/encode.js +14 -11
  531. package/sdk/dist/routes/encode.js.map +1 -1
  532. package/sdk/dist/routes/entry.d.ts +76 -0
  533. package/sdk/dist/routes/entry.d.ts.map +1 -0
  534. package/sdk/dist/routes/entry.js +478 -0
  535. package/sdk/dist/routes/entry.js.map +1 -0
  536. package/sdk/dist/routes/index.d.ts +21 -14
  537. package/sdk/dist/routes/index.d.ts.map +1 -1
  538. package/sdk/dist/routes/index.js +12 -9
  539. package/sdk/dist/routes/index.js.map +1 -1
  540. package/sdk/dist/routes/intent-body.d.ts +97 -0
  541. package/sdk/dist/routes/intent-body.d.ts.map +1 -0
  542. package/sdk/dist/routes/intent-body.js +441 -0
  543. package/sdk/dist/routes/intent-body.js.map +1 -0
  544. package/sdk/dist/routes/intent-dsl.d.ts +21 -6
  545. package/sdk/dist/routes/intent-dsl.d.ts.map +1 -1
  546. package/sdk/dist/routes/intent-dsl.js +34 -17
  547. package/sdk/dist/routes/intent-dsl.js.map +1 -1
  548. package/sdk/dist/routes/intent-sugar.d.ts +77 -4
  549. package/sdk/dist/routes/intent-sugar.d.ts.map +1 -1
  550. package/sdk/dist/routes/intent-sugar.js +358 -152
  551. package/sdk/dist/routes/intent-sugar.js.map +1 -1
  552. package/sdk/dist/routes/intent.d.ts +13 -1
  553. package/sdk/dist/routes/intent.d.ts.map +1 -1
  554. package/sdk/dist/routes/intent.js +37 -1
  555. package/sdk/dist/routes/intent.js.map +1 -1
  556. package/sdk/dist/routes/nest.d.ts +3 -2
  557. package/sdk/dist/routes/nest.d.ts.map +1 -1
  558. package/sdk/dist/routes/nest.js +5 -3
  559. package/sdk/dist/routes/nest.js.map +1 -1
  560. package/sdk/dist/routes/parse.d.ts +6 -0
  561. package/sdk/dist/routes/parse.d.ts.map +1 -0
  562. package/sdk/dist/routes/parse.js +39 -0
  563. package/sdk/dist/routes/parse.js.map +1 -0
  564. package/sdk/dist/routes/portal.d.ts +258 -4
  565. package/sdk/dist/routes/portal.d.ts.map +1 -1
  566. package/sdk/dist/routes/portal.js +588 -9
  567. package/sdk/dist/routes/portal.js.map +1 -1
  568. package/sdk/dist/routes/protocol-rewrite.d.ts +71 -1
  569. package/sdk/dist/routes/protocol-rewrite.d.ts.map +1 -1
  570. package/sdk/dist/routes/protocol-rewrite.js +178 -54
  571. package/sdk/dist/routes/protocol-rewrite.js.map +1 -1
  572. package/sdk/dist/routes/rs-compile.d.ts +25 -22
  573. package/sdk/dist/routes/rs-compile.d.ts.map +1 -1
  574. package/sdk/dist/routes/rs-compile.js +55 -49
  575. package/sdk/dist/routes/rs-compile.js.map +1 -1
  576. package/sdk/dist/routes/sauce-calls.d.ts +26 -12
  577. package/sdk/dist/routes/sauce-calls.d.ts.map +1 -1
  578. package/sdk/dist/routes/sauce-calls.js +16 -23
  579. package/sdk/dist/routes/sauce-calls.js.map +1 -1
  580. package/sdk/dist/routes/sauce-route.d.ts +74 -7
  581. package/sdk/dist/routes/sauce-route.d.ts.map +1 -1
  582. package/sdk/dist/routes/sauce-route.js +249 -96
  583. package/sdk/dist/routes/sauce-route.js.map +1 -1
  584. package/sdk/dist/routes/source-globals.d.ts +107 -0
  585. package/sdk/dist/routes/source-globals.d.ts.map +1 -0
  586. package/sdk/dist/routes/source-globals.generated.d.ts +5530 -936
  587. package/sdk/dist/routes/source-globals.generated.d.ts.map +1 -1
  588. package/sdk/dist/routes/source-globals.generated.js +3 -4
  589. package/sdk/dist/routes/source-globals.generated.js.map +1 -1
  590. package/sdk/dist/routes/source-globals.js +174 -0
  591. package/sdk/dist/routes/source-globals.js.map +1 -0
  592. package/sdk/dist/routes/stock-tokens.d.ts +69 -0
  593. package/sdk/dist/routes/stock-tokens.d.ts.map +1 -0
  594. package/sdk/dist/routes/stock-tokens.generated.d.ts +4 -0
  595. package/sdk/dist/routes/stock-tokens.generated.d.ts.map +1 -0
  596. package/sdk/dist/routes/stock-tokens.generated.js +1836 -0
  597. package/sdk/dist/routes/stock-tokens.generated.js.map +1 -0
  598. package/sdk/dist/routes/stock-tokens.js +65 -0
  599. package/sdk/dist/routes/stock-tokens.js.map +1 -0
  600. package/sdk/dist/routes/token-registry.d.ts +64 -8
  601. package/sdk/dist/routes/token-registry.d.ts.map +1 -1
  602. package/sdk/dist/routes/token-registry.js +208 -33
  603. package/sdk/dist/routes/token-registry.js.map +1 -1
  604. package/sdk/dist/routes/token-rewrite.d.ts +63 -28
  605. package/sdk/dist/routes/token-rewrite.d.ts.map +1 -1
  606. package/sdk/dist/routes/token-rewrite.js +387 -123
  607. package/sdk/dist/routes/token-rewrite.js.map +1 -1
  608. package/sdk/dist/routes/unknown-global.d.ts +32 -0
  609. package/sdk/dist/routes/unknown-global.d.ts.map +1 -0
  610. package/sdk/dist/routes/unknown-global.js +106 -0
  611. package/sdk/dist/routes/unknown-global.js.map +1 -0
  612. package/sdk/dist/routes/vault.d.ts +38 -8
  613. package/sdk/dist/routes/vault.d.ts.map +1 -1
  614. package/sdk/dist/routes/vault.js +47 -8
  615. package/sdk/dist/routes/vault.js.map +1 -1
  616. package/sdk/dist/sauce-script/builtins.d.ts +309 -0
  617. package/sdk/dist/sauce-script/declarations.d.ts +3 -0
  618. package/sdk/dist/sauce-script/declarations.d.ts.map +1 -0
  619. package/sdk/dist/sauce-script/declarations.js +229 -0
  620. package/sdk/dist/sauce-script/declarations.js.map +1 -0
  621. package/sdk/dist/sauce-script/index.d.ts +2714 -0
  622. package/sdk/dist/sauce-script/ts-plugin.cjs +85 -0
  623. package/sdk/dist/skills/loader.d.ts.map +1 -1
  624. package/sdk/dist/skills/loader.js +4 -3
  625. package/sdk/dist/skills/loader.js.map +1 -1
  626. package/sdk/dist/std/router/balancer-v2-vault.abi.json +78 -0
  627. package/sdk/dist/std/router/curve-cryptoswap.abi.json +29 -0
  628. package/sdk/dist/std/router/curve-stableswap.abi.json +29 -0
  629. package/sdk/dist/std/router/dodo-v2-pool.abi.json +39 -0
  630. package/sdk/dist/std/router/lb-pair.abi.json +55 -0
  631. package/sdk/dist/std/router/package.json +7 -0
  632. package/sdk/dist/std/router/router.evm.js +567 -0
  633. package/sdk/dist/std/router/sauce-router.abi.json +202 -0
  634. package/sdk/dist/std/router/uniswap-v2-pair.abi.json +49 -0
  635. package/sdk/dist/std/router/woo-pp-v2.abi.json +42 -0
  636. package/sdk/dist/std/token/permit2.abi.json +226 -0
  637. package/sdk/dist/std/token/token.evm.js +73 -0
  638. package/sdk/dist/std/token/token.svm.js +194 -41
  639. package/sdk/dist/svm/client.d.ts +62 -15
  640. package/sdk/dist/svm/client.d.ts.map +1 -1
  641. package/sdk/dist/svm/client.js +103 -42
  642. package/sdk/dist/svm/client.js.map +1 -1
  643. package/sdk/dist/svm/engine.d.ts +66 -5
  644. package/sdk/dist/svm/engine.d.ts.map +1 -1
  645. package/sdk/dist/svm/engine.js +73 -5
  646. package/sdk/dist/svm/engine.js.map +1 -1
  647. package/sdk/dist/svm/index.d.ts +2 -0
  648. package/sdk/dist/svm/index.d.ts.map +1 -1
  649. package/sdk/dist/svm/index.js +2 -0
  650. package/sdk/dist/svm/index.js.map +1 -1
  651. package/sdk/dist/svm/instructions.d.ts +72 -1
  652. package/sdk/dist/svm/instructions.d.ts.map +1 -1
  653. package/sdk/dist/svm/instructions.js +81 -2
  654. package/sdk/dist/svm/instructions.js.map +1 -1
  655. package/sdk/dist/svm/kitchen.d.ts +20 -1
  656. package/sdk/dist/svm/kitchen.d.ts.map +1 -1
  657. package/sdk/dist/svm/kitchen.js +47 -1
  658. package/sdk/dist/svm/kitchen.js.map +1 -1
  659. package/sdk/dist/svm/portal.d.ts +250 -0
  660. package/sdk/dist/svm/portal.d.ts.map +1 -0
  661. package/sdk/dist/svm/portal.js +462 -0
  662. package/sdk/dist/svm/portal.js.map +1 -0
  663. package/sdk/dist/svm/send.d.ts +18 -2
  664. package/sdk/dist/svm/send.d.ts.map +1 -1
  665. package/sdk/dist/svm/send.js +28 -3
  666. package/sdk/dist/svm/send.js.map +1 -1
  667. package/sdk/dist/svm/token-accounts.d.ts +49 -0
  668. package/sdk/dist/svm/token-accounts.d.ts.map +1 -0
  669. package/sdk/dist/svm/token-accounts.js +58 -0
  670. package/sdk/dist/svm/token-accounts.js.map +1 -0
  671. package/sdk/dist/svm/token-extensions.d.ts +18 -7
  672. package/sdk/dist/svm/token-extensions.d.ts.map +1 -1
  673. package/sdk/dist/svm/token-extensions.js +58 -5
  674. package/sdk/dist/svm/token-extensions.js.map +1 -1
  675. package/sdk/dist/token/api.d.ts +7 -4
  676. package/sdk/dist/token/api.d.ts.map +1 -1
  677. package/sdk/dist/token/api.js.map +1 -1
  678. package/sdk/dist/token/evm.js +2 -2
  679. package/sdk/dist/token/index.d.ts +4 -4
  680. package/sdk/dist/token/index.js +4 -4
  681. package/sdk/dist/token/params.js +1 -1
  682. package/sdk/dist/token/source.js +3 -3
  683. package/sdk/dist/token/source.js.map +1 -1
  684. package/sdk/dist/token/types.d.ts +2 -2
  685. package/sdk/dist/token/types.js +2 -2
  686. package/sdk/src/protocols/aerodrome/AerodromePoolABI.json +105 -0
  687. package/sdk/src/protocols/aerodrome/abis.ts +62 -0
  688. package/sdk/src/protocols/aerodrome-slipstream/AerodromeSlipstreamPoolABI.json +96 -0
  689. package/sdk/src/protocols/aerodrome-slipstream/abis.ts +55 -0
  690. package/sdk/src/protocols/camelot/CamelotV2FactoryABI.json +25 -0
  691. package/sdk/src/protocols/camelot/CamelotV2PairABI.json +109 -0
  692. package/sdk/src/protocols/camelot/CamelotV3FactoryABI.json +25 -0
  693. package/sdk/src/protocols/camelot/CamelotV3PoolABI.json +92 -0
  694. package/sdk/src/protocols/camelot/abis.ts +143 -0
  695. package/sdk/src/protocols/cbeth/functions.ts +4 -6
  696. package/sdk/src/protocols/crvusd/functions.ts +6 -6
  697. package/sdk/src/protocols/eco-routes/PortalABI.json +1448 -0
  698. package/sdk/src/protocols/eco-routes/ProverABI.json +162 -0
  699. package/sdk/src/protocols/eco-routes/abis.ts +1060 -51
  700. package/sdk/src/protocols/eco-routes/addresses.generated.ts +45 -62
  701. package/sdk/src/protocols/eco-routes/lookup.ts +18 -0
  702. package/sdk/src/protocols/erc20/functions.ts +6 -9
  703. package/sdk/src/protocols/frax/functions.ts +6 -6
  704. package/sdk/src/protocols/gho/functions.ts +4 -6
  705. package/sdk/src/protocols/liquity-v2/functions.ts +4 -6
  706. package/sdk/src/protocols/maverick/MaverickV2PoolABI.json +107 -0
  707. package/sdk/src/protocols/maverick/abis.ts +59 -0
  708. package/sdk/src/protocols/maverick/addresses.ts +4 -0
  709. package/sdk/src/protocols/pancakeswap-v2/PancakeSwapV2PairABI.json +72 -0
  710. package/sdk/src/protocols/pancakeswap-v2/abis.ts +44 -0
  711. package/sdk/src/protocols/pancakeswap-v3/PancakeSwapV3PoolABI.json +100 -0
  712. package/sdk/src/protocols/pancakeswap-v3/abis.ts +57 -0
  713. package/sdk/src/protocols/permit2/Permit2ABI.json +154 -0
  714. package/sdk/src/protocols/permit2/abis.ts +63 -0
  715. package/sdk/src/protocols/quickswap/QuickSwapV2FactoryABI.json +25 -0
  716. package/sdk/src/protocols/quickswap/QuickSwapV2PairABI.json +72 -0
  717. package/sdk/src/protocols/quickswap/QuickSwapV3FactoryABI.json +25 -0
  718. package/sdk/src/protocols/quickswap/QuickSwapV3PoolABI.json +88 -0
  719. package/sdk/src/protocols/quickswap/abis.ts +123 -0
  720. package/sdk/src/protocols/sushiswap-v2/SushiSwapV2PairABI.json +72 -0
  721. package/sdk/src/protocols/sushiswap-v2/abis.ts +43 -0
  722. package/sdk/src/protocols/synthra-v3/SynthraV3PoolABI.json +100 -0
  723. package/sdk/src/protocols/synthra-v3/abis.ts +56 -0
  724. package/sdk/src/protocols/trader-joe/LBPairABI.json +185 -0
  725. package/sdk/src/protocols/trader-joe/abis.ts +102 -0
  726. package/sdk/src/protocols/trader-joe/addresses.ts +5 -0
  727. package/sdk/src/protocols/uniswap-v2/UniswapV2PairABI.json +72 -0
  728. package/sdk/src/protocols/uniswap-v2/abis.ts +45 -0
  729. package/sdk/src/protocols/uniswap-v3/UniswapV3PoolABI.json +100 -0
  730. package/sdk/src/protocols/uniswap-v3/abis.ts +56 -0
  731. package/sdk/src/protocols/uniswap-v4/UniswapV4PoolManagerABI.json +38 -0
  732. package/sdk/src/protocols/uniswap-v4/UniswapV4StateViewABI.json +307 -0
  733. package/sdk/src/protocols/uniswap-v4/abis.ts +168 -0
  734. package/sdk/src/protocols/uniswap-v4/addresses.ts +50 -0
  735. package/sdk/src/protocols/unitflow-v3/UnitFlowV3PoolABI.json +100 -0
  736. package/sdk/src/protocols/unitflow-v3/abis.ts +57 -0
  737. package/sdk/src/protocols/velodrome/VelodromePoolABI.json +105 -0
  738. package/sdk/src/protocols/velodrome/abis.ts +62 -0
  739. package/skills/sauce-actions/SKILL.md +166 -0
  740. package/skills/sauce-actions/examples/swap-and-supply.json +24 -0
  741. package/skills/sauce-actions/examples/swap-by-key.json +15 -0
  742. package/skills/sauce-actions/references/actions.md +731 -0
  743. package/skills/sauce-chains/SKILL.md +137 -0
  744. package/skills/sauce-chains/examples/chains.sauce.ts +25 -0
  745. package/skills/sauce-chains/references/arbitrum.md +158 -0
  746. package/skills/sauce-chains/references/arc.md +107 -0
  747. package/skills/sauce-chains/references/aurora.md +33 -0
  748. package/skills/sauce-chains/references/avalanche.md +106 -0
  749. package/skills/sauce-chains/references/base-stocks.md +77 -0
  750. package/skills/sauce-chains/references/base.md +141 -0
  751. package/skills/sauce-chains/references/berachain.md +33 -0
  752. package/skills/sauce-chains/references/blast.md +60 -0
  753. package/skills/sauce-chains/references/boba.md +33 -0
  754. package/skills/sauce-chains/references/bsc.md +97 -0
  755. package/skills/sauce-chains/references/celo.md +57 -0
  756. package/skills/sauce-chains/references/core.md +33 -0
  757. package/skills/sauce-chains/references/cronos.md +33 -0
  758. package/skills/sauce-chains/references/ethereum-stocks.md +1741 -0
  759. package/skills/sauce-chains/references/ethereum.md +255 -0
  760. package/skills/sauce-chains/references/evmos.md +33 -0
  761. package/skills/sauce-chains/references/fantom.md +61 -0
  762. package/skills/sauce-chains/references/fuse.md +33 -0
  763. package/skills/sauce-chains/references/gnosis.md +57 -0
  764. package/skills/sauce-chains/references/index.md +58 -0
  765. package/skills/sauce-chains/references/ink.md +55 -0
  766. package/skills/sauce-chains/references/kava.md +33 -0
  767. package/skills/sauce-chains/references/klaytn.md +33 -0
  768. package/skills/sauce-chains/references/linea.md +65 -0
  769. package/skills/sauce-chains/references/manta.md +33 -0
  770. package/skills/sauce-chains/references/mantle.md +33 -0
  771. package/skills/sauce-chains/references/metis.md +54 -0
  772. package/skills/sauce-chains/references/mode.md +55 -0
  773. package/skills/sauce-chains/references/monad.md +79 -0
  774. package/skills/sauce-chains/references/moonbeam.md +33 -0
  775. package/skills/sauce-chains/references/opbnb.md +55 -0
  776. package/skills/sauce-chains/references/optimism.md +123 -0
  777. package/skills/sauce-chains/references/plasma.md +35 -0
  778. package/skills/sauce-chains/references/polygon.md +123 -0
  779. package/skills/sauce-chains/references/pulsechain.md +33 -0
  780. package/skills/sauce-chains/references/ronin.md +35 -0
  781. package/skills/sauce-chains/references/scroll.md +62 -0
  782. package/skills/sauce-chains/references/sei.md +55 -0
  783. package/skills/sauce-chains/references/solana.md +53 -0
  784. package/skills/sauce-chains/references/sonic.md +57 -0
  785. package/skills/sauce-chains/references/unichain.md +61 -0
  786. package/skills/sauce-chains/references/zetachain.md +33 -0
  787. package/skills/sauce-chains/references/zksync.md +59 -0
  788. package/skills/sauce-chains/references/zora.md +57 -0
  789. package/skills/sauce-cli/SKILL.md +366 -0
  790. package/skills/sauce-cli/examples/pay.sauce.ts +23 -0
  791. package/skills/sauce-cli/examples/split.sauce.ts +30 -0
  792. package/skills/sauce-distributed-swap/SKILL.md +392 -0
  793. package/skills/sauce-distributed-swap/examples/distributed-swap.mts +251 -0
  794. package/skills/sauce-distributed-swap/examples/distributed-swap.sauce.ts +115 -0
  795. package/skills/sauce-examples/SKILL.md +96 -0
  796. package/skills/sauce-globals/SKILL.md +175 -0
  797. package/skills/sauce-globals/examples/globals.mts +111 -0
  798. package/skills/sauce-globals/examples/globals.sauce.ts +47 -0
  799. package/skills/sauce-globals/references/chains.md +53 -0
  800. package/skills/sauce-globals/references/protocols.md +405 -0
  801. package/skills/sauce-globals/references/stocks.md +1824 -0
  802. package/skills/sauce-globals/references/tokens.md +53 -0
  803. package/skills/sauce-intents/SKILL.md +505 -0
  804. package/skills/sauce-intents/examples/cross-chain.sauce.ts +37 -0
  805. package/skills/sauce-intents/examples/fund-by-transfer.sauce.ts +54 -0
  806. package/skills/sauce-intents/examples/intents.mts +343 -0
  807. package/skills/sauce-intents/examples/swap-on-base.sauce.ts +135 -0
  808. package/skills/sauce-intents/references/portal.md +77 -0
  809. package/skills/sauce-overview/SKILL.md +161 -0
  810. package/skills/sauce-protocols/SKILL.md +118 -0
  811. package/skills/sauce-protocols/examples/protocols.mts +77 -0
  812. package/skills/sauce-protocols/examples/protocols.sauce.ts +27 -0
  813. package/{sdk/src/skills → skills/sauce-protocols/references}/aave-v2.md +35 -17
  814. package/skills/sauce-protocols/references/aave-v3.md +144 -0
  815. package/skills/sauce-protocols/references/aave-v4.md +50 -0
  816. package/skills/sauce-protocols/references/abracadabra.md +72 -0
  817. package/skills/sauce-protocols/references/across.md +73 -0
  818. package/skills/sauce-protocols/references/aerodrome-slipstream.md +50 -0
  819. package/{sdk/src/skills → skills/sauce-protocols/references}/aerodrome.md +43 -24
  820. package/skills/sauce-protocols/references/aevo.md +49 -0
  821. package/{sdk/src/skills → skills/sauce-protocols/references}/alchemix.md +10 -25
  822. package/{sdk/src/skills → skills/sauce-protocols/references}/ambient.md +14 -21
  823. package/{sdk/src/skills → skills/sauce-protocols/references}/arbitrum-bridge.md +11 -14
  824. package/{sdk/src/skills → skills/sauce-protocols/references}/arrakis.md +10 -26
  825. package/skills/sauce-protocols/references/axelar.md +56 -0
  826. package/{sdk/src/skills → skills/sauce-protocols/references}/balancer-v2.md +13 -29
  827. package/{sdk/src/skills → skills/sauce-protocols/references}/base-bridge.md +11 -16
  828. package/{sdk/src/skills → skills/sauce-protocols/references}/baseswap.md +12 -19
  829. package/{sdk/src/skills → skills/sauce-protocols/references}/beefy.md +10 -30
  830. package/{sdk/src/skills → skills/sauce-protocols/references}/benqi.md +11 -21
  831. package/{sdk/src/skills → skills/sauce-protocols/references}/camelot.md +13 -27
  832. package/skills/sauce-protocols/references/cbeth.md +48 -0
  833. package/skills/sauce-protocols/references/cctp.md +47 -0
  834. package/{sdk/src/skills → skills/sauce-protocols/references}/celer.md +11 -18
  835. package/{sdk/src/skills → skills/sauce-protocols/references}/chainlink-ccip.md +11 -21
  836. package/skills/sauce-protocols/references/chainlink.md +47 -0
  837. package/{sdk/src/skills → skills/sauce-protocols/references}/circle-gateway.md +12 -38
  838. package/{sdk/src/skills → skills/sauce-protocols/references}/compound-v2.md +11 -25
  839. package/{sdk/src/skills → skills/sauce-protocols/references}/compound-v3.md +43 -27
  840. package/{sdk/src/skills → skills/sauce-protocols/references}/connext.md +11 -15
  841. package/{sdk/src/skills → skills/sauce-protocols/references}/convex.md +10 -28
  842. package/{sdk/src/skills → skills/sauce-protocols/references}/cowswap.md +12 -19
  843. package/skills/sauce-protocols/references/crvusd.md +49 -0
  844. package/skills/sauce-protocols/references/curve.md +98 -0
  845. package/{sdk/src/skills → skills/sauce-protocols/references}/debridge.md +11 -33
  846. package/{sdk/src/skills → skills/sauce-protocols/references}/dodo.md +13 -18
  847. package/skills/sauce-protocols/references/eigenlayer.md +48 -0
  848. package/{sdk/src/skills → skills/sauce-protocols/references}/ens.md +10 -26
  849. package/{sdk/src/skills → skills/sauce-protocols/references}/erc20.md +18 -34
  850. package/{sdk/src/skills → skills/sauce-protocols/references}/erc3156.md +10 -13
  851. package/{sdk/src/skills → skills/sauce-protocols/references}/erc4626.md +11 -27
  852. package/{sdk/src/skills → skills/sauce-protocols/references}/ethena.md +10 -27
  853. package/{sdk/src/skills → skills/sauce-protocols/references}/etherfi.md +10 -32
  854. package/{sdk/src/skills → skills/sauce-protocols/references}/euler-v2.md +11 -21
  855. package/{sdk/src/skills → skills/sauce-protocols/references}/fenix.md +12 -18
  856. package/{sdk/src/skills → skills/sauce-protocols/references}/fluid.md +11 -20
  857. package/{sdk/src/skills → skills/sauce-protocols/references}/frax-ether.md +10 -26
  858. package/skills/sauce-protocols/references/frax.md +48 -0
  859. package/{sdk/src/skills → skills/sauce-protocols/references}/gains-network.md +11 -28
  860. package/skills/sauce-protocols/references/gamma.md +57 -0
  861. package/{sdk/src/skills → skills/sauce-protocols/references}/gelato.md +12 -20
  862. package/skills/sauce-protocols/references/gho.md +50 -0
  863. package/{sdk/src/skills → skills/sauce-protocols/references}/gmx-v1.md +12 -34
  864. package/{sdk/src/skills → skills/sauce-protocols/references}/gmx-v2.md +15 -28
  865. package/skills/sauce-protocols/references/harvest.md +41 -0
  866. package/{sdk/src/skills → skills/sauce-protocols/references}/hegic.md +10 -18
  867. package/{sdk/src/skills → skills/sauce-protocols/references}/hop.md +11 -21
  868. package/{sdk/src/skills → skills/sauce-protocols/references}/hyperlane.md +11 -21
  869. package/skills/sauce-protocols/references/index.md +355 -0
  870. package/{sdk/src/skills → skills/sauce-protocols/references}/instadapp.md +10 -18
  871. package/skills/sauce-protocols/references/kelp.md +46 -0
  872. package/{sdk/src/skills → skills/sauce-protocols/references}/kim.md +12 -18
  873. package/{sdk/src/skills → skills/sauce-protocols/references}/kyberswap-aggregator.md +12 -35
  874. package/skills/sauce-protocols/references/kyberswap.md +72 -0
  875. package/{sdk/src/skills → skills/sauce-protocols/references}/layerbank.md +11 -26
  876. package/{sdk/src/skills → skills/sauce-protocols/references}/layerzero.md +11 -25
  877. package/{sdk/src/skills → skills/sauce-protocols/references}/level-finance.md +10 -24
  878. package/{sdk/src/skills → skills/sauce-protocols/references}/lido.md +10 -28
  879. package/{sdk/src/skills → skills/sauce-protocols/references}/lifi.md +11 -25
  880. package/{sdk/src/skills → skills/sauce-protocols/references}/linea-bridge.md +11 -14
  881. package/{sdk/src/skills → skills/sauce-protocols/references}/liquity-v1.md +10 -21
  882. package/skills/sauce-protocols/references/liquity-v2.md +48 -0
  883. package/{sdk/src/skills → skills/sauce-protocols/references}/lynex.md +12 -18
  884. package/skills/sauce-protocols/references/maker.md +57 -0
  885. package/skills/sauce-protocols/references/mantle-meth.md +43 -0
  886. package/{sdk/src/skills → skills/sauce-protocols/references}/maverick.md +13 -25
  887. package/{sdk/src/skills → skills/sauce-protocols/references}/moonwell.md +11 -21
  888. package/{sdk/src/skills → skills/sauce-protocols/references}/morpho-blue.md +44 -21
  889. package/{sdk/src/skills → skills/sauce-protocols/references}/mux-protocol.md +10 -30
  890. package/skills/sauce-protocols/references/olympus.md +39 -0
  891. package/skills/sauce-protocols/references/oneinch.md +81 -0
  892. package/skills/sauce-protocols/references/openocean.md +69 -0
  893. package/{sdk/src/skills → skills/sauce-protocols/references}/optimism-bridge.md +11 -16
  894. package/{sdk/src/skills → skills/sauce-protocols/references}/opyn.md +10 -21
  895. package/{sdk/src/skills → skills/sauce-protocols/references}/pancakeswap-v2.md +39 -41
  896. package/skills/sauce-protocols/references/pancakeswap-v3.md +72 -0
  897. package/skills/sauce-protocols/references/paraswap.md +39 -0
  898. package/{sdk/src/skills → skills/sauce-protocols/references}/pendle.md +47 -29
  899. package/skills/sauce-protocols/references/permit2.md +101 -0
  900. package/skills/sauce-protocols/references/perpetual-protocol.md +53 -0
  901. package/{sdk/src/skills → skills/sauce-protocols/references}/polygon-bridge.md +11 -17
  902. package/{sdk/src/skills → skills/sauce-protocols/references}/premia.md +10 -19
  903. package/{sdk/src/skills → skills/sauce-protocols/references}/puffer.md +10 -21
  904. package/skills/sauce-protocols/references/pyth.md +45 -0
  905. package/{sdk/src/skills → skills/sauce-protocols/references}/quickswap.md +13 -27
  906. package/{sdk/src/skills → skills/sauce-protocols/references}/radiant.md +11 -15
  907. package/{sdk/src/skills → skills/sauce-protocols/references}/ramses.md +12 -18
  908. package/skills/sauce-protocols/references/reflexer.md +52 -0
  909. package/skills/sauce-protocols/references/registry/aave-v2.md +43 -0
  910. package/skills/sauce-protocols/references/registry/aave-v3.md +62 -0
  911. package/skills/sauce-protocols/references/registry/aave-v4.md +80 -0
  912. package/skills/sauce-protocols/references/registry/abracadabra.md +54 -0
  913. package/skills/sauce-protocols/references/registry/across.md +57 -0
  914. package/skills/sauce-protocols/references/registry/aerodrome-slipstream.md +72 -0
  915. package/skills/sauce-protocols/references/registry/aerodrome.md +58 -0
  916. package/skills/sauce-protocols/references/registry/aevo.md +39 -0
  917. package/skills/sauce-protocols/references/registry/alchemix.md +46 -0
  918. package/skills/sauce-protocols/references/registry/ambient.md +40 -0
  919. package/skills/sauce-protocols/references/registry/arbitrum-bridge.md +40 -0
  920. package/skills/sauce-protocols/references/registry/arrakis.md +49 -0
  921. package/skills/sauce-protocols/references/registry/axelar.md +65 -0
  922. package/skills/sauce-protocols/references/registry/balancer-v2.md +50 -0
  923. package/skills/sauce-protocols/references/registry/base-bridge.md +42 -0
  924. package/skills/sauce-protocols/references/registry/baseswap.md +40 -0
  925. package/skills/sauce-protocols/references/registry/beefy.md +51 -0
  926. package/skills/sauce-protocols/references/registry/benqi.md +49 -0
  927. package/skills/sauce-protocols/references/registry/camelot.md +82 -0
  928. package/skills/sauce-protocols/references/registry/cbeth.md +43 -0
  929. package/skills/sauce-protocols/references/registry/cctp.md +48 -0
  930. package/skills/sauce-protocols/references/registry/celer.md +44 -0
  931. package/skills/sauce-protocols/references/registry/chainlink-ccip.md +45 -0
  932. package/skills/sauce-protocols/references/registry/chainlink.md +49 -0
  933. package/skills/sauce-protocols/references/registry/circle-gateway.md +70 -0
  934. package/skills/sauce-protocols/references/registry/compound-v2.md +53 -0
  935. package/skills/sauce-protocols/references/registry/compound-v3.md +52 -0
  936. package/skills/sauce-protocols/references/registry/connext.md +41 -0
  937. package/skills/sauce-protocols/references/registry/convex.md +51 -0
  938. package/skills/sauce-protocols/references/registry/cowswap.md +40 -0
  939. package/skills/sauce-protocols/references/registry/crvusd.md +40 -0
  940. package/skills/sauce-protocols/references/registry/curve.md +81 -0
  941. package/skills/sauce-protocols/references/registry/debridge.md +59 -0
  942. package/skills/sauce-protocols/references/registry/dodo.md +39 -0
  943. package/skills/sauce-protocols/references/registry/eco-routes.md +65 -0
  944. package/skills/sauce-protocols/references/registry/eigenlayer.md +58 -0
  945. package/skills/sauce-protocols/references/registry/ens.md +49 -0
  946. package/skills/sauce-protocols/references/registry/erc20.md +44 -0
  947. package/skills/sauce-protocols/references/registry/erc3156.md +38 -0
  948. package/skills/sauce-protocols/references/registry/erc4626.md +51 -0
  949. package/skills/sauce-protocols/references/registry/ethena.md +50 -0
  950. package/skills/sauce-protocols/references/registry/etherfi.md +57 -0
  951. package/skills/sauce-protocols/references/registry/euler-v2.md +49 -0
  952. package/skills/sauce-protocols/references/registry/fenix.md +39 -0
  953. package/skills/sauce-protocols/references/registry/fluid.md +48 -0
  954. package/skills/sauce-protocols/references/registry/frax-ether.md +49 -0
  955. package/skills/sauce-protocols/references/registry/frax.md +40 -0
  956. package/skills/sauce-protocols/references/registry/gains-network.md +43 -0
  957. package/skills/sauce-protocols/references/registry/gamma.md +56 -0
  958. package/skills/sauce-protocols/references/registry/gelato.md +45 -0
  959. package/skills/sauce-protocols/references/registry/gho.md +40 -0
  960. package/skills/sauce-protocols/references/registry/gmx-v1.md +59 -0
  961. package/skills/sauce-protocols/references/registry/gmx-v2.md +41 -0
  962. package/skills/sauce-protocols/references/registry/harvest.md +44 -0
  963. package/skills/sauce-protocols/references/registry/hegic.md +39 -0
  964. package/skills/sauce-protocols/references/registry/hop.md +49 -0
  965. package/skills/sauce-protocols/references/registry/hyperlane.md +48 -0
  966. package/skills/sauce-protocols/references/registry/instadapp.md +39 -0
  967. package/skills/sauce-protocols/references/registry/kelp.md +47 -0
  968. package/skills/sauce-protocols/references/registry/kim.md +39 -0
  969. package/skills/sauce-protocols/references/registry/kyberswap-aggregator.md +49 -0
  970. package/skills/sauce-protocols/references/registry/kyberswap.md +63 -0
  971. package/skills/sauce-protocols/references/registry/layerbank.md +54 -0
  972. package/skills/sauce-protocols/references/registry/layerzero.md +49 -0
  973. package/skills/sauce-protocols/references/registry/level-finance.md +41 -0
  974. package/skills/sauce-protocols/references/registry/lido.md +51 -0
  975. package/skills/sauce-protocols/references/registry/lifi.md +48 -0
  976. package/skills/sauce-protocols/references/registry/linea-bridge.md +40 -0
  977. package/skills/sauce-protocols/references/registry/liquity-v1.md +42 -0
  978. package/skills/sauce-protocols/references/registry/liquity-v2.md +40 -0
  979. package/skills/sauce-protocols/references/registry/lynex.md +39 -0
  980. package/skills/sauce-protocols/references/registry/maker.md +55 -0
  981. package/skills/sauce-protocols/references/registry/mantle-meth.md +48 -0
  982. package/skills/sauce-protocols/references/registry/maverick.md +60 -0
  983. package/skills/sauce-protocols/references/registry/moonwell.md +49 -0
  984. package/skills/sauce-protocols/references/registry/morpho-blue.md +47 -0
  985. package/skills/sauce-protocols/references/registry/mux-protocol.md +49 -0
  986. package/skills/sauce-protocols/references/registry/olympus.md +42 -0
  987. package/skills/sauce-protocols/references/registry/oneinch.md +45 -0
  988. package/skills/sauce-protocols/references/registry/openocean.md +44 -0
  989. package/skills/sauce-protocols/references/registry/optimism-bridge.md +42 -0
  990. package/skills/sauce-protocols/references/registry/opyn.md +42 -0
  991. package/skills/sauce-protocols/references/registry/pancakeswap-v2.md +71 -0
  992. package/skills/sauce-protocols/references/registry/pancakeswap-v3.md +76 -0
  993. package/skills/sauce-protocols/references/registry/paraswap.md +51 -0
  994. package/skills/sauce-protocols/references/registry/pendle.md +43 -0
  995. package/skills/sauce-protocols/references/registry/permit2.md +50 -0
  996. package/skills/sauce-protocols/references/registry/perpetual-protocol.md +49 -0
  997. package/skills/sauce-protocols/references/registry/polygon-bridge.md +43 -0
  998. package/skills/sauce-protocols/references/registry/premia.md +40 -0
  999. package/skills/sauce-protocols/references/registry/puffer.md +43 -0
  1000. package/skills/sauce-protocols/references/registry/pyth.md +40 -0
  1001. package/skills/sauce-protocols/references/registry/quickswap.md +80 -0
  1002. package/skills/sauce-protocols/references/registry/radiant.md +41 -0
  1003. package/skills/sauce-protocols/references/registry/ramses.md +39 -0
  1004. package/skills/sauce-protocols/references/registry/reflexer.md +56 -0
  1005. package/skills/sauce-protocols/references/registry/renzo.md +47 -0
  1006. package/skills/sauce-protocols/references/registry/rocket-pool.md +49 -0
  1007. package/skills/sauce-protocols/references/registry/sablier.md +40 -0
  1008. package/skills/sauce-protocols/references/registry/safe.md +47 -0
  1009. package/skills/sauce-protocols/references/registry/scroll-bridge.md +48 -0
  1010. package/skills/sauce-protocols/references/registry/seamless.md +42 -0
  1011. package/skills/sauce-protocols/references/registry/seaport.md +44 -0
  1012. package/skills/sauce-protocols/references/registry/silo.md +48 -0
  1013. package/skills/sauce-protocols/references/registry/socket.md +44 -0
  1014. package/skills/sauce-protocols/references/registry/sommelier.md +43 -0
  1015. package/skills/sauce-protocols/references/registry/spark.md +42 -0
  1016. package/skills/sauce-protocols/references/registry/spookyswap.md +40 -0
  1017. package/skills/sauce-protocols/references/registry/squid.md +45 -0
  1018. package/skills/sauce-protocols/references/registry/stader.md +47 -0
  1019. package/skills/sauce-protocols/references/registry/stargate.md +45 -0
  1020. package/skills/sauce-protocols/references/registry/superfluid.md +49 -0
  1021. package/skills/sauce-protocols/references/registry/sushiswap-v2.md +71 -0
  1022. package/skills/sauce-protocols/references/registry/swell.md +49 -0
  1023. package/skills/sauce-protocols/references/registry/synapse.md +46 -0
  1024. package/skills/sauce-protocols/references/registry/syncswap.md +38 -0
  1025. package/skills/sauce-protocols/references/registry/synthetix-v3.md +48 -0
  1026. package/skills/sauce-protocols/references/registry/synthra-v3.md +77 -0
  1027. package/skills/sauce-protocols/references/registry/thales.md +51 -0
  1028. package/skills/sauce-protocols/references/registry/thena.md +39 -0
  1029. package/skills/sauce-protocols/references/registry/thruster.md +38 -0
  1030. package/skills/sauce-protocols/references/registry/tokemak.md +45 -0
  1031. package/skills/sauce-protocols/references/registry/trader-joe.md +66 -0
  1032. package/skills/sauce-protocols/references/registry/uniswap-v2.md +77 -0
  1033. package/skills/sauce-protocols/references/registry/uniswap-v3.md +113 -0
  1034. package/skills/sauce-protocols/references/registry/uniswap-v4.md +117 -0
  1035. package/skills/sauce-protocols/references/registry/unitflow-v3.md +65 -0
  1036. package/skills/sauce-protocols/references/registry/velodrome.md +58 -0
  1037. package/skills/sauce-protocols/references/registry/venus.md +62 -0
  1038. package/skills/sauce-protocols/references/registry/vertex.md +46 -0
  1039. package/skills/sauce-protocols/references/registry/wormhole.md +59 -0
  1040. package/skills/sauce-protocols/references/registry/yearn-v3.md +46 -0
  1041. package/skills/sauce-protocols/references/registry/zerolend.md +41 -0
  1042. package/skills/sauce-protocols/references/registry/zerox.md +44 -0
  1043. package/skills/sauce-protocols/references/registry/zksync-bridge.md +40 -0
  1044. package/{sdk/src/skills → skills/sauce-protocols/references}/renzo.md +10 -24
  1045. package/{sdk/src/skills → skills/sauce-protocols/references}/rocket-pool.md +10 -26
  1046. package/{sdk/src/skills → skills/sauce-protocols/references}/sablier.md +10 -27
  1047. package/skills/sauce-protocols/references/safe.md +42 -0
  1048. package/{sdk/src/skills → skills/sauce-protocols/references}/scroll-bridge.md +11 -20
  1049. package/{sdk/src/skills → skills/sauce-protocols/references}/seamless.md +11 -16
  1050. package/skills/sauce-protocols/references/seaport.md +38 -0
  1051. package/{sdk/src/skills → skills/sauce-protocols/references}/silo.md +11 -20
  1052. package/{sdk/src/skills → skills/sauce-protocols/references}/socket.md +11 -18
  1053. package/skills/sauce-protocols/references/sommelier.md +40 -0
  1054. package/{sdk/src/skills → skills/sauce-protocols/references}/spark.md +11 -16
  1055. package/{sdk/src/skills → skills/sauce-protocols/references}/spookyswap.md +12 -19
  1056. package/{sdk/src/skills → skills/sauce-protocols/references}/squid.md +11 -21
  1057. package/skills/sauce-protocols/references/stader.md +39 -0
  1058. package/{sdk/src/skills → skills/sauce-protocols/references}/stargate.md +11 -22
  1059. package/{sdk/src/skills → skills/sauce-protocols/references}/superfluid.md +10 -28
  1060. package/{sdk/src/skills → skills/sauce-protocols/references}/sushiswap-v2.md +38 -43
  1061. package/skills/sauce-protocols/references/swell.md +49 -0
  1062. package/skills/sauce-protocols/references/synapse.md +54 -0
  1063. package/{sdk/src/skills → skills/sauce-protocols/references}/syncswap.md +12 -17
  1064. package/{sdk/src/skills → skills/sauce-protocols/references}/synthetix-v3.md +10 -29
  1065. package/skills/sauce-protocols/references/synthra-v3.md +63 -0
  1066. package/skills/sauce-protocols/references/thales.md +58 -0
  1067. package/{sdk/src/skills → skills/sauce-protocols/references}/thena.md +12 -18
  1068. package/{sdk/src/skills → skills/sauce-protocols/references}/thruster.md +13 -18
  1069. package/skills/sauce-protocols/references/tokemak.md +40 -0
  1070. package/{sdk/src/skills → skills/sauce-protocols/references}/trader-joe.md +13 -26
  1071. package/{sdk/src/skills → skills/sauce-protocols/references}/uniswap-v2.md +46 -44
  1072. package/skills/sauce-protocols/references/uniswap-v3.md +188 -0
  1073. package/skills/sauce-protocols/references/uniswap-v4.md +155 -0
  1074. package/skills/sauce-protocols/references/unitflow-v3.md +63 -0
  1075. package/{sdk/src/skills → skills/sauce-protocols/references}/velodrome.md +12 -24
  1076. package/{sdk/src/skills → skills/sauce-protocols/references}/venus.md +12 -31
  1077. package/skills/sauce-protocols/references/vertex.md +42 -0
  1078. package/skills/sauce-protocols/references/wormhole.md +57 -0
  1079. package/{sdk/src/skills → skills/sauce-protocols/references}/yearn-v3.md +10 -25
  1080. package/{sdk/src/skills → skills/sauce-protocols/references}/zerolend.md +11 -15
  1081. package/skills/sauce-protocols/references/zerox.md +39 -0
  1082. package/{sdk/src/skills → skills/sauce-protocols/references}/zksync-bridge.md +11 -14
  1083. package/skills/sauce-script/SKILL.md +407 -0
  1084. package/skills/sauce-script/examples/IOracle.json +12 -0
  1085. package/skills/sauce-script/examples/saucescript.mts +167 -0
  1086. package/skills/sauce-script/examples/twap.sauce.ts +29 -0
  1087. package/skills/sauce-script/references/builtins.json +823 -0
  1088. package/skills/sauce-script/references/builtins.md +674 -0
  1089. package/skills/sauce-solana/SKILL.md +322 -0
  1090. package/skills/sauce-solana/examples/solana.mts +166 -0
  1091. package/skills/sauce-solana/examples/solana.sauce.ts +45 -0
  1092. package/skills/sauce-solana/examples/token-2022.sauce.ts +38 -0
  1093. package/skills/sauce-swaps/SKILL.md +200 -0
  1094. package/skills/sauce-swaps/examples/swap-leg.sauce.ts +50 -0
  1095. package/skills/sauce-swaps/examples/swaps.mts +124 -0
  1096. package/skills/sauce-typescript/SKILL.md +178 -0
  1097. package/skills/sauce-typescript/examples/actions.mts +100 -0
  1098. package/skills/sauce-typescript/examples/compiler.mts +69 -0
  1099. package/skills/sauce-typescript/examples/cook.mts +65 -0
  1100. package/skills/sauce-typescript/examples/verify.mts +104 -0
  1101. package/dev-tools/README.md +0 -16
  1102. package/dev-tools/artifacts/IERC20.json +0 -1
  1103. package/dev-tools/artifacts/ISauceRouter.json +0 -1
  1104. package/dev-tools/artifacts/IUniswapV3Pool.json +0 -1
  1105. package/dev-tools/artifacts/Router.json +0 -1
  1106. package/dev-tools/hardhat.config.cjs +0 -18
  1107. package/dev-tools/sauce/js/add.js +0 -4
  1108. package/dev-tools/sauce/js/call.js +0 -8
  1109. package/dev-tools/sauce/js/erc20.js +0 -18
  1110. package/dev-tools/sauce/js/example.js +0 -6
  1111. package/dev-tools/sauce/js/fibonacci.js +0 -13
  1112. package/dev-tools/sauce/ts/add.ts +0 -4
  1113. package/dev-tools/sauce/ts/call.ts +0 -8
  1114. package/dev-tools/sauce/ts/erc20.ts +0 -18
  1115. package/dev-tools/sauce/ts/example.ts +0 -6
  1116. package/dev-tools/sauce/ts/fibonacci.ts +0 -13
  1117. package/dev-tools/sauce/ts/saucescript.d.ts +0 -1
  1118. package/dev-tools/sauce/ts/tsconfig.json +0 -12
  1119. package/dev-tools/scripts/deploy.ts +0 -107
  1120. package/dev-tools/scripts/init.js +0 -132
  1121. package/dev-tools/scripts/run.ts +0 -67
  1122. package/dev-tools/scripts/start-fork.sh +0 -92
  1123. package/dev-tools/scripts/start-local.sh +0 -120
  1124. package/dev-tools/scripts/stop-local.sh +0 -40
  1125. package/dev-tools/scripts/sync-artifacts.js +0 -46
  1126. package/dev-tools/scripts/sync-price.ts +0 -58
  1127. package/dev-tools/src/contracts.ts +0 -59
  1128. package/dev-tools/src/runner.ts +0 -355
  1129. package/dev-tools/src/svm-local.ts +0 -305
  1130. package/dev-tools/src/sync-price.ts +0 -217
  1131. package/sdk/dist/deployments/v12.generated.d.ts +0 -95
  1132. package/sdk/dist/deployments/v12.generated.d.ts.map +0 -1
  1133. package/sdk/dist/deployments/v12.generated.js +0 -50
  1134. package/sdk/dist/deployments/v12.generated.js.map +0 -1
  1135. package/sdk/dist/swap/index.d.ts +0 -29
  1136. package/sdk/dist/swap/index.d.ts.map +0 -1
  1137. package/sdk/dist/swap/index.js +0 -27
  1138. package/sdk/dist/swap/index.js.map +0 -1
  1139. package/sdk/dist/swap/params.d.ts +0 -29
  1140. package/sdk/dist/swap/params.d.ts.map +0 -1
  1141. package/sdk/dist/swap/params.js +0 -123
  1142. package/sdk/dist/swap/params.js.map +0 -1
  1143. package/sdk/dist/swap/source.d.ts +0 -30
  1144. package/sdk/dist/swap/source.d.ts.map +0 -1
  1145. package/sdk/dist/swap/source.js +0 -101
  1146. package/sdk/dist/swap/source.js.map +0 -1
  1147. package/sdk/dist/swap/types.d.ts +0 -160
  1148. package/sdk/dist/swap/types.d.ts.map +0 -1
  1149. package/sdk/dist/swap/types.js +0 -106
  1150. package/sdk/dist/swap/types.js.map +0 -1
  1151. package/sdk/src/skills/aave-v3.md +0 -134
  1152. package/sdk/src/skills/aave-v4.md +0 -91
  1153. package/sdk/src/skills/abracadabra.md +0 -93
  1154. package/sdk/src/skills/across.md +0 -90
  1155. package/sdk/src/skills/aerodrome-slipstream.md +0 -57
  1156. package/sdk/src/skills/aevo.md +0 -58
  1157. package/sdk/src/skills/axelar.md +0 -80
  1158. package/sdk/src/skills/cbeth.md +0 -62
  1159. package/sdk/src/skills/chainlink.md +0 -62
  1160. package/sdk/src/skills/crvusd.md +0 -58
  1161. package/sdk/src/skills/curve.md +0 -141
  1162. package/sdk/src/skills/eigenlayer.md +0 -71
  1163. package/sdk/src/skills/frax.md +0 -57
  1164. package/sdk/src/skills/gamma.md +0 -79
  1165. package/sdk/src/skills/gho.md +0 -61
  1166. package/sdk/src/skills/harvest.md +0 -49
  1167. package/sdk/src/skills/index.md +0 -299
  1168. package/sdk/src/skills/kelp.md +0 -60
  1169. package/sdk/src/skills/kyberswap.md +0 -100
  1170. package/sdk/src/skills/liquity-v2.md +0 -59
  1171. package/sdk/src/skills/loader.ts +0 -46
  1172. package/sdk/src/skills/maker.md +0 -79
  1173. package/sdk/src/skills/mantle-meth.md +0 -60
  1174. package/sdk/src/skills/olympus.md +0 -46
  1175. package/sdk/src/skills/oneinch.md +0 -64
  1176. package/sdk/src/skills/openocean.md +0 -86
  1177. package/sdk/src/skills/pancakeswap-v3.md +0 -104
  1178. package/sdk/src/skills/paraswap.md +0 -67
  1179. package/sdk/src/skills/permit2.md +0 -73
  1180. package/sdk/src/skills/perpetual-protocol.md +0 -73
  1181. package/sdk/src/skills/pyth.md +0 -58
  1182. package/sdk/src/skills/reflexer.md +0 -73
  1183. package/sdk/src/skills/safe.md +0 -56
  1184. package/sdk/src/skills/seaport.md +0 -65
  1185. package/sdk/src/skills/sommelier.md +0 -47
  1186. package/sdk/src/skills/stader.md +0 -53
  1187. package/sdk/src/skills/swell.md +0 -65
  1188. package/sdk/src/skills/synapse.md +0 -63
  1189. package/sdk/src/skills/synthra-v3.md +0 -57
  1190. package/sdk/src/skills/thales.md +0 -74
  1191. package/sdk/src/skills/tokemak.md +0 -48
  1192. package/sdk/src/skills/uniswap-v3.md +0 -202
  1193. package/sdk/src/skills/uniswap-v4.md +0 -125
  1194. package/sdk/src/skills/unitflow-v3.md +0 -62
  1195. package/sdk/src/skills/vertex.md +0 -55
  1196. package/sdk/src/skills/wormhole.md +0 -76
  1197. package/sdk/src/skills/zerox.md +0 -51
@@ -0,0 +1,1721 @@
1
+ /**
2
+ * An eco-routes intent's lifecycle after it is published, as PLAIN VALUES: where it stands, and
3
+ * every transaction that moves it on, built UNSIGNED — the fill (the approvals, then `fulfill` or
4
+ * `fulfillAndProve` with the prover's fee in its value), the proof, the claim (`withdraw` or
5
+ * `batchWithdraw`), the refund and the cancellation (`cancel` or `cancelAndProve`) — plus the
6
+ * import of intents someone published, from the transaction that published them.
7
+ *
8
+ * The `sauce` command's `fill --send`, `prove`, `claim`, `refund`, `cancel` and `intents` are a
9
+ * layer over these, adding the signer, the prompts and the store under `~/.sauce`; `sauce mcp`
10
+ * calls them as they are. So nothing here signs, prompts, reads a file or the environment, or
11
+ * keeps state: each function takes the intent (an {@link IntentRecord}, the JSON the store keeps
12
+ * and an MCP tool passes) and an endpoint per chain ({@link Endpoints}), reads what it needs, and
13
+ * returns JSON-serialisable values — amounts as decimal strings — with `notes` saying what a person
14
+ * should know. A thing that cannot happen yet is `ready: false` with the reason, never an error.
15
+ *
16
+ * What each transaction does on chain is in `routes/portal.ts`, which builds the calldata and cites
17
+ * the eco-routes source it follows. What this module adds is the reading: which prover proves the
18
+ * intent, and with what fee; what the destination Portal recorded; what the source's prover has
19
+ * proven; the vault's balances; and whether each Portal can cancel (`cancel` in the destination's
20
+ * code) and refuses to pay a cancellation (`CancelledIntent` in the source's, without which a
21
+ * proven cancellation would pay the reward to an address nobody controls).
22
+ */
23
+ import { decodeEventLog, decodeFunctionResult, encodeFunctionData, getAbiItem, getAddress, hexToBytes, isAddressEqual, parseAbi, toEventSelector, toFunctionSelector, zeroAddress, } from "viem";
24
+ import { requireChain, resolveChain } from "../chains/canonical.js";
25
+ import { v12PotAbi } from "../evm/engine.js";
26
+ import { SAUCE_INTENT_POT_SALT, v12PredictPot } from "../deployments/pot.js";
27
+ import { PortalABI } from "../protocols/eco-routes/abis.js";
28
+ import { ECO_ROUTES_ADDRESSES } from "../protocols/eco-routes/addresses.generated.js";
29
+ import { denormalizeToEvm, hashIntent, kindOf } from "../routes/encode.js";
30
+ import { toUniversalAddress } from "../routes/normalize.js";
31
+ import { CANCELLED_CLAIMANT, CANCELLED_CLAIMANT_BYTES32, batchWithdrawTx, cancelAndProveTx, cancelTx, fulfillAndProveTx, fulfillApprovalTxs, fulfillTx, fulfillmentCall, hyperlaneProverData, intentFromPublished, intentHashCall, intentVaultAddressCall, isIntentFundedCall, provenIntentCall, proverFeeCall, proveTx, refundTx, rewardStatusCall, withdrawTx, } from "../routes/portal.js";
32
+ import { sauceEvmDeployPotCall } from "../routes/sauce-calls.js";
33
+ import { CliError, UsageError } from "./args.js";
34
+ import { connect, kitchenFee, potState } from "./chain.js";
35
+ import { kitchenAddress } from "./commands.js";
36
+ import { formatAmount, tokenInfo } from "./effects.js";
37
+ import { requireSupported } from "./support.js";
38
+ import { planSvmFill, readSvmDestination, rehearseSvm, svmCancelTransaction, svmFinalizedSlot, svmProgramExists, svmProveTransaction, svmRpc, svmSpend, } from "./lifecycle-svm.js";
39
+ import { svmHyperDispatcherPda, svmKeyOf, universalOfSvmKey } from "../svm/portal.js";
40
+ import { address as svmAddress } from "@solana/kit";
41
+ /** The current record schema. A reader refuses any other, by name. */
42
+ export const INTENT_SCHEMA = "sauce.intent/1";
43
+ /** A universal (32-byte) address as the record writes it: 20 bytes, checksummed, on an EVM chain. */
44
+ function shown(address, chain) {
45
+ return chain.kind === "evm" ? getAddress(denormalizeToEvm(address)) : address;
46
+ }
47
+ /** An EVM chain the record names, refusing one this SDK does not know. */
48
+ function chainOf(id, what) {
49
+ const chain = resolveChain(Number(id));
50
+ if (chain === undefined)
51
+ throw new CliError(`the intent's ${what}, chain ${id}, is not one Sauce knows`);
52
+ return chain;
53
+ }
54
+ /** The record of `intent`, published through `sourcePortal`. */
55
+ export function intentRecord(intent, options) {
56
+ const source = chainOf(intent.sourceChainId, "source");
57
+ const destination = chainOf(intent.destination, "destination");
58
+ const hashes = hashIntent(intent);
59
+ const tokens = (list, chain) => list.map((entry) => ({ token: shown(entry.token, chain), amount: entry.amount.toString() }));
60
+ return {
61
+ schema: INTENT_SCHEMA,
62
+ ...hashes,
63
+ source: { chainId: source.id, chain: source.slug, portal: getAddress(options.sourcePortal) },
64
+ destination: {
65
+ chainId: destination.id,
66
+ chain: destination.slug,
67
+ portal: shown(intent.route.portal, destination),
68
+ },
69
+ ...(options.vault === undefined ? {} : { vault: getAddress(options.vault) }),
70
+ route: {
71
+ salt: intent.route.salt,
72
+ deadline: intent.route.deadline.toString(),
73
+ portal: shown(intent.route.portal, destination),
74
+ nativeAmount: intent.route.nativeAmount.toString(),
75
+ tokens: tokens(intent.route.tokens, destination),
76
+ calls: intent.route.calls.map((call) => ({
77
+ target: shown(call.target, destination),
78
+ data: call.data,
79
+ value: call.value.toString(),
80
+ })),
81
+ },
82
+ reward: {
83
+ deadline: intent.reward.deadline.toString(),
84
+ creator: shown(intent.reward.creator, source),
85
+ prover: shown(intent.reward.prover, source),
86
+ nativeAmount: intent.reward.nativeAmount.toString(),
87
+ tokens: tokens(intent.reward.tokens, source),
88
+ },
89
+ };
90
+ }
91
+ const integer = (value, what) => {
92
+ if (typeof value !== "string" || !/^\d+$/.test(value)) {
93
+ throw new CliError(`the intent's ${what} is not a decimal integer string`);
94
+ }
95
+ return BigInt(value);
96
+ };
97
+ /**
98
+ * The SDK's `Intent` from its record, checked: the schema is this one, and the route and reward
99
+ * hash to the hashes the record states — so a record edited by hand, or written by something
100
+ * else, is refused rather than acted on.
101
+ */
102
+ export function intentOf(record) {
103
+ if (record.schema !== INTENT_SCHEMA) {
104
+ throw new CliError(`the intent record's schema is ${JSON.stringify(record.schema)}, ` +
105
+ `not ${INTENT_SCHEMA}`);
106
+ }
107
+ const address = (value, what) => {
108
+ try {
109
+ return toUniversalAddress(value);
110
+ }
111
+ catch {
112
+ throw new CliError(`the intent's ${what} is not an address`);
113
+ }
114
+ };
115
+ const intent = {
116
+ sourceChainId: BigInt(record.source.chainId),
117
+ destination: BigInt(record.destination.chainId),
118
+ route: {
119
+ salt: record.route.salt,
120
+ deadline: integer(record.route.deadline, "route deadline"),
121
+ portal: address(record.route.portal, "route portal"),
122
+ nativeAmount: integer(record.route.nativeAmount, "route native amount"),
123
+ tokens: record.route.tokens.map((entry) => ({
124
+ token: address(entry.token, "route token"),
125
+ amount: integer(entry.amount, "route token amount"),
126
+ })),
127
+ calls: record.route.calls.map((call) => ({
128
+ target: address(call.target, "route call target"),
129
+ data: call.data,
130
+ value: integer(call.value, "route call value"),
131
+ })),
132
+ },
133
+ reward: {
134
+ deadline: integer(record.reward.deadline, "reward deadline"),
135
+ creator: address(record.reward.creator, "creator"),
136
+ prover: address(record.reward.prover, "prover"),
137
+ nativeAmount: integer(record.reward.nativeAmount, "reward native amount"),
138
+ tokens: record.reward.tokens.map((entry) => ({
139
+ token: address(entry.token, "reward token"),
140
+ amount: integer(entry.amount, "reward token amount"),
141
+ })),
142
+ },
143
+ };
144
+ const hashes = hashIntent(intent);
145
+ if (hashes.intentHash !== record.intentHash.toLowerCase()) {
146
+ throw new CliError(`the intent record says ${record.intentHash}, but its route and reward hash to ` +
147
+ `${hashes.intentHash}: it was changed after it was written`);
148
+ }
149
+ return intent;
150
+ }
151
+ const txJson = (chain, tx, what) => ({
152
+ chainId: chain.id,
153
+ chain: chain.slug,
154
+ to: getAddress(tx.to),
155
+ data: tx.data,
156
+ value: tx.value.toString(),
157
+ what,
158
+ });
159
+ /** A {@link TxJson} as a transaction to send. */
160
+ export const txRequest = (tx) => ({
161
+ to: tx.to,
162
+ data: tx.data,
163
+ value: BigInt(tx.value),
164
+ });
165
+ // ---------------------------------------------------------------------------------------------
166
+ // Reading chains
167
+ // ---------------------------------------------------------------------------------------------
168
+ /** Clients for the chains a call needs, connected once and checked to serve their chain. */
169
+ class Chains {
170
+ endpoints;
171
+ clients = new Map();
172
+ constructor(endpoints) {
173
+ this.endpoints = endpoints;
174
+ }
175
+ has(chain) {
176
+ return this.endpoints[String(chain.id)] !== undefined;
177
+ }
178
+ /** The client for `chain`; `why` says what it is needed for, when there is no endpoint. */
179
+ get(chain, why) {
180
+ const url = this.endpoints[String(chain.id)];
181
+ if (url === undefined) {
182
+ throw new UsageError(`${why} needs ${chain.slug}'s endpoint (chain id ${chain.id})`);
183
+ }
184
+ let client = this.clients.get(chain.id);
185
+ if (client === undefined) {
186
+ client = connect(url, chain);
187
+ this.clients.set(chain.id, client);
188
+ }
189
+ return client;
190
+ }
191
+ async maybe(chain) {
192
+ return this.has(chain) ? this.get(chain, "") : undefined;
193
+ }
194
+ /** A Solana client for `chain`; `why` says what it is needed for, when there is no endpoint. */
195
+ svm(chain, why) {
196
+ const url = this.endpoints[String(chain.id)];
197
+ if (url === undefined) {
198
+ throw new UsageError(`${why} needs ${chain.slug}'s endpoint (chain id ${chain.id})`);
199
+ }
200
+ return svmRpc(url);
201
+ }
202
+ }
203
+ const reasonOf = (error) => error.shortMessage ?? "the call reverted";
204
+ /** `call` against `client`, decoded; reading failures become a CliError naming `what`. */
205
+ async function readCall(client, call, what) {
206
+ let data;
207
+ try {
208
+ ({ data } = await client.call({ to: call.to, data: call.data }));
209
+ }
210
+ catch (error) {
211
+ throw new CliError(`reading ${what} failed: ${reasonOf(error)}`);
212
+ }
213
+ if (data === undefined || data === "0x") {
214
+ throw new CliError(`reading ${what} returned nothing: the contract has no code, or no such function`);
215
+ }
216
+ return call.decode(data);
217
+ }
218
+ /** `fn` read from `client`, or `undefined` when it reverts or the contract has no such function. */
219
+ async function tryRead(client, call) {
220
+ try {
221
+ const { data } = await client.call({ to: call.to, data: call.data });
222
+ return data === undefined || data === "0x" ? undefined : call.decode(data);
223
+ }
224
+ catch {
225
+ return undefined;
226
+ }
227
+ }
228
+ /** The latest block's timestamp: the clock a deadline is checked against on that chain. */
229
+ async function chainTime(client) {
230
+ try {
231
+ return (await client.getBlock({ blockTag: "latest" })).timestamp;
232
+ }
233
+ catch (error) {
234
+ throw new CliError(`reading the latest block failed: ${reasonOf(error)}`);
235
+ }
236
+ }
237
+ /** Whether `code` dispatches `selector`: a PUSH4 of it, outside push data. */
238
+ function dispatches(code, selector) {
239
+ return pushes(code).four.has(selector.slice(2).toLowerCase());
240
+ }
241
+ /** Whether `code` can revert with the custom error `selector`: a PUSH4 of it, or the left-aligned
242
+ * PUSH32 the optimizer (via-IR) emits for an error's selector. */
243
+ function carriesError(code, selector) {
244
+ const { four, left } = pushes(code);
245
+ const bare = selector.slice(2).toLowerCase();
246
+ return four.has(bare) || left.has(bare);
247
+ }
248
+ /** The scans of the last `PUSH_CACHE_SIZE` codes read, least recently used first (a `Map` keeps
249
+ * insertion order, and a hit is moved to the end), so a long-running caller such as the MCP
250
+ * server neither grows it without bound nor loses every entry at once. */
251
+ const pushCache = new Map();
252
+ const PUSH_CACHE_SIZE = 64;
253
+ function pushes(code) {
254
+ const cached = pushCache.get(code);
255
+ if (cached !== undefined) {
256
+ pushCache.delete(code);
257
+ pushCache.set(code, cached);
258
+ return cached;
259
+ }
260
+ const four = new Set();
261
+ const left = new Set();
262
+ const hex = code.slice(2).toLowerCase();
263
+ for (let i = 0; i < hex.length; i += 2) {
264
+ const op = Number.parseInt(hex.slice(i, i + 2), 16);
265
+ if (op === 0x63)
266
+ four.add(hex.slice(i + 2, i + 10));
267
+ if (op === 0x7f && /^0{56}$/.test(hex.slice(i + 10, i + 66)))
268
+ left.add(hex.slice(i + 2, i + 10));
269
+ if (op >= 0x60 && op <= 0x7f)
270
+ i += (op - 0x5f) * 2;
271
+ }
272
+ const found = { four, left };
273
+ pushCache.set(code, found);
274
+ if (pushCache.size > PUSH_CACHE_SIZE)
275
+ pushCache.delete(pushCache.keys().next().value);
276
+ return found;
277
+ }
278
+ async function codeAt(client, address, what) {
279
+ try {
280
+ const code = await client.getCode({ address });
281
+ return code === undefined || code === "0x" ? undefined : code;
282
+ }
283
+ catch (error) {
284
+ throw new CliError(`reading ${what}'s code failed: ${reasonOf(error)}`);
285
+ }
286
+ }
287
+ const CANCEL = toFunctionSelector(getAbiItem({ abi: PortalABI, name: "cancel" }));
288
+ const CANCEL_AND_PROVE = toFunctionSelector(getAbiItem({ abi: PortalABI, name: "cancelAndProve" }));
289
+ const CANCELLED_INTENT = toFunctionSelector("CancelledIntent(bytes32)");
290
+ const COOK = toFunctionSelector(getAbiItem({ abi: v12PotAbi, name: "cook" }));
291
+ const PROVER = parseAbi([
292
+ "function PORTAL() view returns (address)",
293
+ "function getProofType() view returns (string)",
294
+ "function isWhitelisted(bytes32) view returns (bool)",
295
+ ]);
296
+ const ERC20 = parseAbi([
297
+ "function balanceOf(address) view returns (uint256)",
298
+ "function allowance(address, address) view returns (uint256)",
299
+ "function approve(address, uint256) returns (bool)",
300
+ ]);
301
+ /** `fn(args)` on `address`, as a read call. */
302
+ const proverRead = (address, functionName, args = []) => ({
303
+ to: address,
304
+ data: encodeFunctionData({ abi: PROVER, functionName, args }),
305
+ decode: (result) => decodeFunctionResult({ abi: PROVER, functionName, data: result }),
306
+ });
307
+ /** The registry role (and generation, environment) whose address is `prover` on `source`. */
308
+ function registryRole(source, prover) {
309
+ for (const [generation, record] of Object.entries(ECO_ROUTES_ADDRESSES)) {
310
+ const environments = record.chains[String(source.id)];
311
+ for (const [environment, roles] of Object.entries(environments ?? {})) {
312
+ for (const [role, address] of Object.entries(roles)) {
313
+ if (/Prover$/.test(role) && isAddressEqual(address, prover)) {
314
+ return { generation, environment, role };
315
+ }
316
+ }
317
+ }
318
+ }
319
+ return undefined;
320
+ }
321
+ function registryAddress(chain, where) {
322
+ const table = ECO_ROUTES_ADDRESSES[where.generation]?.chains[String(chain.id)]?.[where.environment]?.[where.role];
323
+ return table === undefined ? undefined : getAddress(table);
324
+ }
325
+ /**
326
+ * Which prover on the destination proves `intent`, and whether this module can drive it.
327
+ *
328
+ * The reward names the SOURCE chain's prover. Its counterpart on the destination is the registry's
329
+ * address for the same role (the same generation and environment), else the same address; it must
330
+ * answer `PORTAL()` with the destination Portal (a prover takes `prove` only from its own), and,
331
+ * when the source is readable, the source prover must whitelist it (or the proof is refused on
332
+ * arrival). Hyperlane is driven here — its data `abi.encode((sourceChainProver, metadata, hook))`,
333
+ * its domain for an EVM source its chain id, as eco's solver sends (`hyper.prover.ts:40-45`).
334
+ * Polymer's proof is fetched from Polymer's prover API and submitted to the source by a relayer,
335
+ * and LayerZero's and Metalayer's need their own endpoint ids: refused here, saying so.
336
+ */
337
+ export async function proverPlan(intent, destination, source) {
338
+ const sourceChain = requireChain(Number(intent.sourceChainId));
339
+ const destinationChain = requireChain(Number(intent.destination));
340
+ const sourceProver = getAddress(denormalizeToEvm(intent.reward.prover));
341
+ const portal = getAddress(denormalizeToEvm(intent.route.portal));
342
+ const role = registryRole(sourceChain, sourceProver);
343
+ const counterpart = role === undefined ? undefined : registryAddress(destinationChain, role);
344
+ const candidates = [...new Set([counterpart, sourceProver].filter((a) => a !== undefined))];
345
+ let found;
346
+ const refused = [];
347
+ for (const candidate of candidates) {
348
+ if ((await codeAt(destination, candidate, "a prover")) === undefined) {
349
+ refused.push(`${candidate} has no code on ${destinationChain.slug}`);
350
+ continue;
351
+ }
352
+ const itsPortal = await tryRead(destination, proverRead(candidate, "PORTAL"));
353
+ if (itsPortal === undefined || !isAddressEqual(itsPortal, portal)) {
354
+ refused.push(`${candidate} on ${destinationChain.slug} serves ${itsPortal ?? "no Portal"}, not the ` +
355
+ `route's Portal ${portal}`);
356
+ continue;
357
+ }
358
+ const kind = await tryRead(destination, proverRead(candidate, "getProofType"));
359
+ found = { address: candidate, ...(kind === undefined ? {} : { kind }) };
360
+ break;
361
+ }
362
+ const base = { sourceProver };
363
+ if (found === undefined) {
364
+ return {
365
+ ...base,
366
+ supported: false,
367
+ why: `no prover on ${destinationChain.slug} proves to the reward's prover ${sourceProver}` +
368
+ (refused.length === 0 ? "" : ` (${refused.join("; ")})`),
369
+ };
370
+ }
371
+ const plan = {
372
+ ...base,
373
+ destinationProver: found.address,
374
+ ...(found.kind === undefined ? {} : { kind: found.kind }),
375
+ };
376
+ if (found.kind !== "Hyperlane") {
377
+ const why = found.kind === "Polymer"
378
+ ? "a Polymer proof is fetched from Polymer's prover API and submitted to the source " +
379
+ "chain's prover by a relayer, which this command does not do"
380
+ : `this command proves through Hyperlane provers, and ${found.address} is ` +
381
+ `${found.kind === undefined ? "of no proof type it reports" : `a ${found.kind} prover`}`;
382
+ return { ...plan, supported: false, why };
383
+ }
384
+ if (source !== undefined) {
385
+ const trusted = await tryRead(source, proverRead(sourceProver, "isWhitelisted", [toUniversalAddress(found.address)]));
386
+ if (trusted === false) {
387
+ return {
388
+ ...plan,
389
+ supported: false,
390
+ why: `the reward's prover ${sourceProver} on ${sourceChain.slug} does not whitelist ` +
391
+ `${found.address}, so it would refuse the proof`,
392
+ };
393
+ }
394
+ }
395
+ return {
396
+ ...plan,
397
+ supported: true,
398
+ sourceDomain: BigInt(sourceChain.id),
399
+ data: hyperlaneProverData({ sourceProver }),
400
+ };
401
+ }
402
+ /** The registry's Solana key (32-byte hex) for `where`, as a program id. */
403
+ function registrySvmKey(chain, where) {
404
+ const table = ECO_ROUTES_ADDRESSES[where.generation]?.chains[String(chain.id)]?.[where.environment]?.[where.role];
405
+ return table === undefined ? undefined : svmKeyOf(table);
406
+ }
407
+ /**
408
+ * Which program on Solana proves `intent` to its EVM source, and whether this module can drive it:
409
+ * the registry's Solana address for the reward prover's role. Only the HyperProver: its message
410
+ * goes through Hyperlane's Mailbox with the gas paid to the IGP in the same transaction
411
+ * (`svm/portal.ts`), its sender the HyperProver's dispatcher, which the source prover must
412
+ * whitelist (checked when the source is readable).
413
+ */
414
+ async function svmProverPlan(intent, destination, source) {
415
+ const sourceChain = requireChain(Number(intent.sourceChainId));
416
+ const destinationChain = requireChain(Number(intent.destination));
417
+ const sourceProver = getAddress(denormalizeToEvm(intent.reward.prover));
418
+ const role = registryRole(sourceChain, sourceProver);
419
+ const program = role === undefined ? undefined : registrySvmKey(destinationChain, role);
420
+ const base = { sourceProver };
421
+ if (role === undefined || program === undefined) {
422
+ return {
423
+ ...base,
424
+ supported: false,
425
+ why: `the reward's prover ${sourceProver} is no registry prover with a ${destinationChain.slug} counterpart`,
426
+ };
427
+ }
428
+ const kind = role.role.replace(/Prover$/, "");
429
+ const plan = { ...base, destinationProver: program, kind: kind === "Hyper" ? "Hyperlane" : kind };
430
+ if (role.role !== "HyperProver") {
431
+ return {
432
+ ...plan,
433
+ supported: false,
434
+ why: role.role === "PolymerProver"
435
+ ? "a Polymer proof is fetched from Polymer's prover API and submitted to the source " +
436
+ "chain's prover by a relayer, which this command does not do"
437
+ : `this command proves from Solana through the HyperProver, and ${program} is a ${role.role}`,
438
+ };
439
+ }
440
+ if (!(await svmProgramExists(destination, svmAddress(program)))) {
441
+ return {
442
+ ...plan,
443
+ supported: false,
444
+ why: `the HyperProver ${program} is not a program on Solana`,
445
+ };
446
+ }
447
+ if (source !== undefined) {
448
+ const sender = await svmHyperDispatcherPda(svmAddress(program));
449
+ const trusted = await tryRead(source, proverRead(sourceProver, "isWhitelisted", [universalOfSvmKey(sender)]));
450
+ if (trusted === false) {
451
+ return {
452
+ ...plan,
453
+ supported: false,
454
+ why: `the reward's prover ${sourceProver} on ${sourceChain.slug} does not whitelist Solana's ` +
455
+ `HyperProver dispatcher ${sender}, so it would refuse the proof`,
456
+ };
457
+ }
458
+ }
459
+ return {
460
+ ...plan,
461
+ supported: true,
462
+ sourceDomain: BigInt(sourceChain.id),
463
+ hyper: {
464
+ hyperProver: svmAddress(program),
465
+ sourceChainId: intent.sourceChainId,
466
+ sourceProver,
467
+ },
468
+ };
469
+ }
470
+ /** The bridge fee for proving these (intent, claimant) pairs through `plan`'s prover. */
471
+ async function proofFee(destination, plan, destinationChainId, pairs) {
472
+ return readCall(destination, proverFeeCall({
473
+ prover: plan.destinationProver,
474
+ sourceDomain: plan.sourceDomain,
475
+ destinationChainId,
476
+ pairs,
477
+ data: plan.data,
478
+ }), `the prover's fee (${plan.destinationProver}.fetchFee)`);
479
+ }
480
+ const proverJson = (plan) => ({
481
+ sourceProver: plan.sourceProver,
482
+ ...(plan.destinationProver === undefined ? {} : { destinationProver: plan.destinationProver }),
483
+ ...(plan.kind === undefined ? {} : { kind: plan.kind }),
484
+ supported: plan.supported,
485
+ ...(plan.why === undefined ? {} : { why: plan.why }),
486
+ ...(plan.sourceDomain === undefined ? {} : { sourceDomain: plan.sourceDomain.toString() }),
487
+ });
488
+ async function read(what, call) {
489
+ try {
490
+ return await call();
491
+ }
492
+ catch (error) {
493
+ throw new CliError(`reading ${what} failed: ${reasonOf(error)}`);
494
+ }
495
+ }
496
+ /**
497
+ * The transactions a solver sends to fill `intent` on its destination, as `client` reads it:
498
+ *
499
+ * 1. `Kitchen.deployPot(executor, 0)`, when the route cooks on the destination's shared intent Pot
500
+ * and it is not deployed yet (any account may send it; the Pot is the Executor's either way);
501
+ * 2. the solver's approval of the Portal for each route token, reset to zero first where a smaller
502
+ * allowance stands (USDT refuses to move a nonzero allowance to another);
503
+ * 3. `Portal.fulfillAndProve` with `route.nativeAmount` plus the prover's fee as its value — or
504
+ * `Portal.fulfill` with the native amount alone, when `prove` is false or (left unset) when the
505
+ * reward's prover is not one this module drives, which `notes` then says.
506
+ *
507
+ * It checks what the Portal would refuse first and says so in `notes`: a Portal that hashes the
508
+ * intent differently, a cook on an undeployed Pot that is not the shared one, a Kitchen fee the
509
+ * route underpays.
510
+ */
511
+ export async function planFill(client, intent, options) {
512
+ const chain = requireChain(Number(intent.destination));
513
+ if (chain.kind !== "evm") {
514
+ throw new CliError(`the intent to ${chain.slug} is fulfilled through Solana's Portal program, which this does ` +
515
+ "not drive: it fills an EVM destination's Portal");
516
+ }
517
+ const portal = getAddress(denormalizeToEvm(intent.route.portal));
518
+ if ((await codeAt(client, portal, "the Portal")) === undefined) {
519
+ throw new CliError(`the Portal the route records, ${portal}, has no code on ${chain.slug}`);
520
+ }
521
+ const executor = await read("the Portal's executor()", () => client.readContract({ address: portal, abi: PortalABI, functionName: "executor" }));
522
+ const notes = [];
523
+ const hashes = hashIntent(intent);
524
+ if (kindOf(Number(intent.sourceChainId)) === "evm") {
525
+ const check = intentHashCall(intent, { portal });
526
+ const answer = await read("the Portal's getIntentHash", () => client.call({ to: check.to, data: check.data }));
527
+ if (answer.data !== undefined && check.decode(answer.data).intentHash !== hashes.intentHash) {
528
+ notes.push(`the Portal on ${chain.slug} hashes this intent to ${check.decode(answer.data).intentHash}, ` +
529
+ `not ${hashes.intentHash}: its fulfill refuses the route as InvalidHash`);
530
+ }
531
+ }
532
+ // The shared intent Pot: the one a route cooks on unless it names another.
533
+ const pot = getAddress(v12PredictPot(executor, SAUCE_INTENT_POT_SALT));
534
+ const cookTargets = intent.route.calls
535
+ .filter((call) => call.data.startsWith(COOK))
536
+ .map((call) => getAddress(denormalizeToEvm(call.target)));
537
+ const cooks = cookTargets.includes(pot);
538
+ const { deployed } = await potState(client, pot);
539
+ for (const other of new Set(cookTargets.filter((target) => target !== pot))) {
540
+ if (!(await potState(client, other)).deployed) {
541
+ notes.push(`the route cooks on Pot ${other}, which is not deployed on ${chain.slug} and is not the ` +
542
+ "shared intent Pot, so the fill cannot deploy it: deploy it first");
543
+ }
544
+ }
545
+ if (cooks && !deployed) {
546
+ notes.push(`warning: the shared intent Pot ${pot} is not deployed on ${chain.slug}. The fill ` +
547
+ "deploys it first, as the first solver to fill an intent there must. Any account may " +
548
+ `deploy it: \`sauce pot --owner ${executor} --chain ${chain.slug}\` prints the ` +
549
+ "transaction, and with --deploy and a signer sends it.");
550
+ }
551
+ let kitchen = 0n;
552
+ if (cookTargets.length > 0) {
553
+ const fee = await kitchenFee(client, chain);
554
+ intent.route.calls.forEach((call, index) => {
555
+ if (!call.data.startsWith(COOK))
556
+ return;
557
+ kitchen += call.value;
558
+ if (call.value < fee) {
559
+ notes.push(`route call ${index + 1} pays the Kitchen ${call.value} wei, and ${chain.slug}'s ` +
560
+ `Kitchen charges ${fee}: its cook reverts with FeeNotPaid. Build the intent with ` +
561
+ `--intent-execution-fee ${fee}.`);
562
+ }
563
+ });
564
+ }
565
+ const solver = getAddress(options.solver);
566
+ const claimant = (options.claimant ?? solver);
567
+ const steps = [];
568
+ if (cooks && !deployed) {
569
+ const kitchenAt = kitchenAddress();
570
+ steps.push({
571
+ kind: "deploy",
572
+ what: `Kitchen.deployPot(${executor}, ${SAUCE_INTENT_POT_SALT})`,
573
+ to: kitchenAt,
574
+ data: sauceEvmDeployPotCall({
575
+ kitchen: kitchenAt,
576
+ owner: executor,
577
+ salt: SAUCE_INTENT_POT_SALT,
578
+ }).data,
579
+ value: 0n,
580
+ });
581
+ }
582
+ // Every route token at once: its name, what the solver holds and has approved.
583
+ const tokens = await Promise.all(fulfillApprovalTxs(intent).map(async (approval) => {
584
+ const token = getAddress(approval.to);
585
+ const amount = intent.route.tokens
586
+ .filter((entry) => getAddress(denormalizeToEvm(entry.token)) === token)
587
+ .reduce((sum, entry) => sum + entry.amount, 0n);
588
+ const [info, held, standing] = await Promise.all([
589
+ tokenInfo(client, chain, token),
590
+ read(`the solver's ${token} balance`, () => client.readContract({
591
+ address: token,
592
+ abi: ERC20,
593
+ functionName: "balanceOf",
594
+ args: [solver],
595
+ })),
596
+ read(`the solver's ${token} allowance to the Portal`, () => client.readContract({
597
+ address: token,
598
+ abi: ERC20,
599
+ functionName: "allowance",
600
+ args: [solver, portal],
601
+ })),
602
+ ]);
603
+ return { approval, token, amount, held, standing, info };
604
+ }));
605
+ // The approvals are planned from the allowance read now. Another transaction of the solver's
606
+ // that moves it before these land (a concurrent fill of a USDT-like token) can make the approve
607
+ // revert: the CLI re-plans after a person approves, and rehearses each transaction just before
608
+ // sending it, so such a race is refused unsent rather than reverting on chain.
609
+ for (const { approval, token, amount, standing, info } of tokens) {
610
+ if (standing >= amount)
611
+ continue;
612
+ const symbol = info.symbol ?? token;
613
+ const amountText = formatAmount({ tokens: new Map([[token, info]]) }, token, amount);
614
+ if (standing > 0n) {
615
+ steps.push({
616
+ kind: "approve",
617
+ what: `reset the solver's ${symbol} allowance to the Portal`,
618
+ to: token,
619
+ data: encodeFunctionData({ abi: ERC20, functionName: "approve", args: [portal, 0n] }),
620
+ value: 0n,
621
+ });
622
+ }
623
+ steps.push({
624
+ kind: "approve",
625
+ what: `approve the Portal for ${amountText}`,
626
+ ...approval,
627
+ to: token,
628
+ });
629
+ }
630
+ const prover = await proverPlan(intent, client, options.source);
631
+ if (options.prove === true && !prover.supported) {
632
+ throw new CliError(`the fill cannot prove itself: ${prover.why}`);
633
+ }
634
+ const proves = options.prove !== false && prover.supported;
635
+ if (options.prove === undefined && !prover.supported) {
636
+ notes.push(`the fill does not prove itself, so prove it separately once filled: ${prover.why}`);
637
+ }
638
+ const fee = proves
639
+ ? await proofFee(client, prover, intent.destination, [
640
+ { intentHash: hashes.intentHash, claimant },
641
+ ])
642
+ : 0n;
643
+ const fill = proves
644
+ ? fulfillAndProveTx(intent, {
645
+ claimant,
646
+ prover: prover.destinationProver,
647
+ sourceDomain: prover.sourceDomain,
648
+ data: prover.data,
649
+ fee,
650
+ })
651
+ : fulfillTx(intent, { claimant });
652
+ const native = `the route's nativeAmount` + (cookTargets.length > 0 ? ", the Kitchen's fee for its cook" : "");
653
+ steps.push({
654
+ kind: "fulfill",
655
+ what: proves
656
+ ? `Portal.fulfillAndProve(${hashes.intentHash}, route, ${hashes.rewardHash}, ${claimant}, ` +
657
+ `${prover.destinationProver}, ${prover.sourceDomain}, data) with ${fill.value} wei: ` +
658
+ `${intent.route.nativeAmount} for ${native}, and ${fee} for the ${prover.kind} proof`
659
+ : `Portal.fulfill(${hashes.intentHash}, route, ${hashes.rewardHash}, ${claimant}) with ` +
660
+ `${fill.value} wei: ${native}`,
661
+ to: getAddress(fill.to),
662
+ data: fill.data,
663
+ value: fill.value,
664
+ });
665
+ return {
666
+ chain,
667
+ hashes,
668
+ portal,
669
+ executor,
670
+ pot,
671
+ cooks,
672
+ deployed,
673
+ solver,
674
+ claimant,
675
+ tokens: tokens.map(({ token, amount, held, standing, info }) => ({
676
+ token,
677
+ amount,
678
+ held,
679
+ standing,
680
+ info,
681
+ })),
682
+ steps,
683
+ value: fill.value,
684
+ proves,
685
+ prover,
686
+ fee: { prover: fee, kitchen },
687
+ notes,
688
+ };
689
+ }
690
+ /** {@link planFill} for an MCP tool: the unsigned transactions, in order, as JSON. */
691
+ export async function buildFill(record, endpoints, options) {
692
+ const intent = intentOf(record);
693
+ const chains = new Chains(endpoints);
694
+ const destination = requireChain(Number(intent.destination));
695
+ requireSupported("building a fill", [destination]);
696
+ if (destination.kind === "svm")
697
+ return buildSvmFill(intent, chains, options);
698
+ const client = await chains.get(destination, "a fill");
699
+ const plan = await planFill(client, intent, {
700
+ solver: getAddress(options.from),
701
+ ...(options.claimant === undefined ? {} : { claimant: options.claimant }),
702
+ ...(options.prove === undefined ? {} : { prove: options.prove }),
703
+ ...(chains.has(requireChain(Number(intent.sourceChainId)))
704
+ ? { source: await chains.get(requireChain(Number(intent.sourceChainId)), "") }
705
+ : {}),
706
+ });
707
+ const notes = [...plan.notes];
708
+ for (const token of plan.tokens) {
709
+ if (token.held < token.amount) {
710
+ notes.push(`${plan.solver} holds ${formatAmount({ tokens: new Map([[token.token, token.info]]) }, token.token, token.held)}, ` +
711
+ `and the fill delivers ${formatAmount({ tokens: new Map([[token.token, token.info]]) }, token.token, token.amount)}: the fulfill reverts until it holds enough`);
712
+ }
713
+ }
714
+ return {
715
+ from: plan.solver,
716
+ transactions: plan.steps.map((step) => txJson(plan.chain, step, step.what)),
717
+ proves: plan.proves,
718
+ fee: { prover: plan.fee.prover.toString(), kitchen: plan.fee.kitchen.toString() },
719
+ prover: proverJson(plan.prover),
720
+ delivers: plan.tokens.map((token) => ({
721
+ token: token.token,
722
+ ...(token.info.symbol === undefined ? {} : { symbol: token.info.symbol }),
723
+ amount: token.amount.toString(),
724
+ held: token.held.toString(),
725
+ })),
726
+ notes,
727
+ };
728
+ }
729
+ const iso = (seconds) => new Date(Number(seconds) * 1000).toISOString();
730
+ const yes = (why, at) => ({
731
+ ok: true,
732
+ why,
733
+ ...(at === undefined ? {} : { at: at.toString() }),
734
+ });
735
+ const no = (why, at) => ({
736
+ ok: false,
737
+ why,
738
+ ...(at === undefined ? {} : { at: at.toString() }),
739
+ });
740
+ async function readSource(client, intent, portal) {
741
+ const chain = requireChain(Number(intent.sourceChainId));
742
+ const code = await codeAt(client, portal, "the source Portal");
743
+ if (code === undefined) {
744
+ throw new CliError(`the source Portal ${portal} has no code on ${chain.slug}`);
745
+ }
746
+ const target = { portal };
747
+ const [vault, status, time] = await Promise.all([
748
+ readCall(client, intentVaultAddressCall(intent, target), "the intent's vault"),
749
+ readCall(client, rewardStatusCall(intent, target), "the reward's status"),
750
+ chainTime(client),
751
+ ]);
752
+ const vaultAddress = getAddress(vault);
753
+ const holds = await Promise.all([
754
+ ...(intent.reward.nativeAmount > 0n
755
+ ? [
756
+ read("the vault's balance", () => client.getBalance({ address: vaultAddress })).then((holds) => ({
757
+ token: "native",
758
+ holds,
759
+ reward: intent.reward.nativeAmount,
760
+ })),
761
+ ]
762
+ : []),
763
+ ...intent.reward.tokens.map(async (entry) => {
764
+ const token = getAddress(denormalizeToEvm(entry.token));
765
+ const [info, holds] = await Promise.all([
766
+ tokenInfo(client, chain, token),
767
+ read(`the vault's ${token} balance`, () => client.readContract({
768
+ address: token,
769
+ abi: ERC20,
770
+ functionName: "balanceOf",
771
+ args: [vaultAddress],
772
+ })),
773
+ ]);
774
+ return { token, info, holds, reward: entry.amount };
775
+ }),
776
+ ]);
777
+ // Funded two ways: `publishAndFund` (or `fund`) records the status Funded, and a transfer into
778
+ // the vault leaves it Initial with the vault holding the reward, which the Portal's own
779
+ // `isIntentFunded` (what solvers check) counts as funded. Asked of the Portal where it answers;
780
+ // else the vault's balances against the reward.
781
+ const funded = status === "Funded" ||
782
+ (status === "Initial" &&
783
+ ((await tryRead(client, isIntentFundedCall(intent, target))) ??
784
+ holds.every((entry) => entry.holds >= entry.reward)));
785
+ // A prover with no code holds no proof: the Portal itself treats it so (`_validateRefund`).
786
+ const prover = getAddress(denormalizeToEvm(intent.reward.prover));
787
+ const proverCode = await codeAt(client, prover, "the reward's prover");
788
+ const proof = proverCode === undefined
789
+ ? null
790
+ : await readCall(client, provenIntentCall(intent), "the prover's provenIntents");
791
+ return {
792
+ client,
793
+ portal,
794
+ vault: vaultAddress,
795
+ status,
796
+ funded,
797
+ holds,
798
+ proof: proof === null || proof.claimant === zeroAddress ? null : proof,
799
+ // Necessary, not sufficient: code that can revert `CancelledIntent` is eco-routes 2.12's
800
+ // `withdraw`, which refuses a cancellation's sentinel claimant, and a Portal predating 2.12
801
+ // cannot revert it at all. A different contract carrying the selector would pass; the Portal
802
+ // here is the one the intent itself names, whose source this does not re-verify.
803
+ refusesCancelledClaimant: carriesError(code, CANCELLED_INTENT),
804
+ time,
805
+ };
806
+ }
807
+ async function readDestination(client, intent) {
808
+ const chain = requireChain(Number(intent.destination));
809
+ const portal = getAddress(denormalizeToEvm(intent.route.portal));
810
+ const code = await codeAt(client, portal, "the destination Portal");
811
+ if (code === undefined) {
812
+ throw new CliError(`the Portal the route records, ${portal}, has no code on ${chain.slug}`);
813
+ }
814
+ const [recorded, time] = await Promise.all([
815
+ readCall(client, fulfillmentCall(intent), "what the destination Portal recorded"),
816
+ chainTime(client),
817
+ ]);
818
+ return {
819
+ portal,
820
+ claimant: /^0x0{64}$/.test(recorded) ? null : recorded,
821
+ canCancel: dispatches(code, CANCEL) && dispatches(code, CANCEL_AND_PROVE),
822
+ time,
823
+ };
824
+ }
825
+ const isCancelled = (claimant) => claimant !== null && claimant.toLowerCase() === CANCELLED_CLAIMANT_BYTES32;
826
+ /**
827
+ * Where `record` stands, read from its source chain (the reward's status, the vault, the prover's
828
+ * proof) and its destination (what the Portal recorded) — each only where `endpoints` has the
829
+ * chain — with what can be done next and why not. The state is the furthest one read: refunded or
830
+ * claimed, then a proof (of a fill, or of a cancellation), then the destination's record (filled,
831
+ * cancelled), then the funding.
832
+ */
833
+ export async function intentStatus(record, endpoints) {
834
+ const intent = intentOf(record);
835
+ const chains = new Chains(endpoints);
836
+ const sourceChain = requireChain(Number(intent.sourceChainId));
837
+ const destinationChain = requireChain(Number(intent.destination));
838
+ const notes = [];
839
+ if (sourceChain.kind !== "evm") {
840
+ throw new CliError(`this reads intents an EVM chain published; one ${sourceChain.slug} published lives in ` +
841
+ "Solana's Portal program, whose reward side it does not read");
842
+ }
843
+ const onSolana = destinationChain.kind === "svm";
844
+ const sourceClient = await chains.maybe(sourceChain);
845
+ const destinationRpc = onSolana && chains.has(destinationChain) ? chains.svm(destinationChain, "") : undefined;
846
+ const destinationClient = onSolana ? undefined : await chains.maybe(destinationChain);
847
+ if (sourceClient === undefined) {
848
+ notes.push(`no ${sourceChain.slug} endpoint: the funding, the proof and the claim are not read`);
849
+ }
850
+ if (destinationClient === undefined && destinationRpc === undefined) {
851
+ notes.push(`no ${destinationChain.slug} endpoint: the fill and the cancellation are not read`);
852
+ }
853
+ const [source, destination] = await Promise.all([
854
+ sourceClient === undefined
855
+ ? undefined
856
+ : readSource(sourceClient, intent, getAddress(record.source.portal)),
857
+ destinationRpc !== undefined
858
+ ? readSvmDestination(destinationRpc, intent)
859
+ : destinationClient === undefined
860
+ ? undefined
861
+ : readDestination(destinationClient, intent),
862
+ ]);
863
+ const prover = destinationRpc !== undefined
864
+ ? await svmProverPlan(intent, destinationRpc, sourceClient)
865
+ : destinationClient === undefined
866
+ ? undefined
867
+ : await proverPlan(intent, destinationClient, sourceClient);
868
+ const routeDeadline = intent.route.deadline;
869
+ const rewardDeadline = intent.reward.deadline;
870
+ const proof = source?.proof ?? null;
871
+ const proofHere = proof !== null && proof.destination === intent.destination;
872
+ const cancelProven = proofHere && isAddressEqual(proof.claimant, CANCELLED_CLAIMANT);
873
+ const recorded = destination?.claimant ?? null;
874
+ const state = source?.status === "Refunded"
875
+ ? "refunded"
876
+ : source?.status === "Withdrawn"
877
+ ? "claimed"
878
+ : cancelProven
879
+ ? "cancelProven"
880
+ : proofHere
881
+ ? "proven"
882
+ : isCancelled(recorded)
883
+ ? "cancelled"
884
+ : recorded !== null
885
+ ? "filled"
886
+ : source?.funded === true
887
+ ? "funded"
888
+ : "unfunded";
889
+ if (proof !== null && !proofHere) {
890
+ notes.push(`the reward's prover records a proof of this intent from chain ${proof.destination}, not ` +
891
+ `${destinationChain.slug}: a claim challenges (deletes) it rather than paying`);
892
+ }
893
+ const fill = destination === undefined
894
+ ? no(`needs ${destinationChain.slug}'s endpoint`)
895
+ : recorded !== null
896
+ ? no(isCancelled(recorded) ? "it was cancelled" : `it was filled, for claimant ${recorded}`)
897
+ : destination.time > routeDeadline
898
+ ? no(`the route's deadline, ${iso(routeDeadline)}, has passed`)
899
+ : source !== undefined && !source.funded
900
+ ? no("the reward is not funded: a solver would fill it for nothing")
901
+ : yes(`until ${iso(routeDeadline)}`, routeDeadline);
902
+ const prove = destination === undefined
903
+ ? no(`needs ${destinationChain.slug}'s endpoint`)
904
+ : recorded === null
905
+ ? no("it is neither filled nor cancelled on the destination yet")
906
+ : proofHere
907
+ ? no("the source has the proof already")
908
+ : prover !== undefined && !prover.supported
909
+ ? no(prover.why)
910
+ : yes(isCancelled(recorded) ? "prove the cancellation" : "prove the fill");
911
+ const claim = source === undefined
912
+ ? no(`needs ${sourceChain.slug}'s endpoint`)
913
+ : source.status === "Withdrawn"
914
+ ? no("the reward was claimed")
915
+ : source.status === "Refunded"
916
+ ? no("the reward was refunded")
917
+ : cancelProven
918
+ ? no("a proven cancellation pays no claimant: refund it")
919
+ : !proofHere
920
+ ? no(recorded !== null && !isCancelled(recorded)
921
+ ? "filled, but the source's prover has no proof yet"
922
+ : "the source's prover has no proof of a fill")
923
+ : yes(`pays ${proof.claimant}`);
924
+ const refund = source === undefined
925
+ ? no(`needs ${sourceChain.slug}'s endpoint`)
926
+ : cancelProven
927
+ ? yes("the cancellation is proven: refundable now")
928
+ : proofHere
929
+ ? source.status === "Withdrawn" && source.holds.some((entry) => entry.holds > 0n)
930
+ ? yes("claimed: the vault's leftovers go back to the creator")
931
+ : no(source.status === "Withdrawn"
932
+ ? "claimed: the vault holds nothing to refund"
933
+ : "proven: the reward is the claimant's")
934
+ : source.status === "Refunded" && source.holds.every((entry) => entry.holds === 0n)
935
+ ? no("the reward was refunded")
936
+ : source.time < rewardDeadline
937
+ ? no(`not before the reward's deadline, ${iso(rewardDeadline)}`, rewardDeadline)
938
+ : yes(`the reward's deadline, ${iso(rewardDeadline)}, has passed`);
939
+ const cancel = destination === undefined
940
+ ? no(`needs ${destinationChain.slug}'s endpoint`)
941
+ : !destination.canCancel
942
+ ? no(`the destination Portal ${destination.portal} has no cancel (it predates eco-routes ` +
943
+ `2.12): refund after the reward's deadline, ${iso(rewardDeadline)}`)
944
+ : source === undefined
945
+ ? no(`needs ${sourceChain.slug}'s endpoint, to check its Portal refuses to pay a cancellation`)
946
+ : !source.refusesCancelledClaimant
947
+ ? no(`the source Portal ${source.portal} would pay a proven cancellation to an address ` +
948
+ `nobody controls (it predates eco-routes 2.12): refund after ${iso(rewardDeadline)}`)
949
+ : isCancelled(recorded)
950
+ ? no("it is cancelled already: prove the cancellation")
951
+ : recorded !== null
952
+ ? no("it was filled")
953
+ : destination.time <= routeDeadline
954
+ ? no(`not before the route's deadline, ${iso(routeDeadline)}, has passed`, routeDeadline + 1n)
955
+ : yes(`the route's deadline, ${iso(routeDeadline)}, has passed`);
956
+ return {
957
+ intentHash: record.intentHash,
958
+ state,
959
+ ...(source === undefined
960
+ ? {}
961
+ : {
962
+ source: {
963
+ chain: sourceChain.slug,
964
+ portal: source.portal,
965
+ vault: source.vault,
966
+ rewardStatus: source.status,
967
+ funded: source.funded,
968
+ vaultHolds: source.holds.map((entry) => ({
969
+ token: entry.token,
970
+ ...(entry.info?.symbol === undefined ? {} : { symbol: entry.info.symbol }),
971
+ ...(entry.token === "native"
972
+ ? { decimals: 18 }
973
+ : entry.info?.decimals === undefined
974
+ ? {}
975
+ : { decimals: entry.info.decimals }),
976
+ holds: entry.holds.toString(),
977
+ reward: entry.reward.toString(),
978
+ })),
979
+ proof: proof === null
980
+ ? null
981
+ : { claimant: proof.claimant, destination: proof.destination.toString() },
982
+ refusesCancelledClaimant: source.refusesCancelledClaimant,
983
+ time: source.time.toString(),
984
+ },
985
+ }),
986
+ ...(destination === undefined
987
+ ? {}
988
+ : {
989
+ destination: {
990
+ chain: destinationChain.slug,
991
+ portal: destination.portal,
992
+ claimant: recorded,
993
+ cancelled: isCancelled(recorded),
994
+ canCancel: destination.canCancel,
995
+ time: destination.time.toString(),
996
+ },
997
+ }),
998
+ deadlines: { route: routeDeadline.toString(), reward: rewardDeadline.toString() },
999
+ ...(prover === undefined ? {} : { prover: proverJson(prover) }),
1000
+ can: { fill, prove, claim, refund, cancel },
1001
+ notes,
1002
+ };
1003
+ }
1004
+ /**
1005
+ * The proof of `records` — fills or cancellations recorded on their (one) destination — from the
1006
+ * destination's prover to the source's: `Portal.prove(prover, sourceDomain, intentHashes, data)`
1007
+ * with the bridge fee as its value. An intent the destination has no record of is refused, and
1008
+ * one the source has proven already (where the source is readable) is left out, saying so.
1009
+ */
1010
+ export async function buildProve(records, endpoints, options = {}) {
1011
+ if (records.length === 0)
1012
+ throw new UsageError("no intent to prove");
1013
+ const intents = records.map(intentOf);
1014
+ const chains = new Chains(endpoints);
1015
+ const destinationChain = requireChain(Number(intents[0].destination));
1016
+ const sourceChain = requireChain(Number(intents[0].sourceChainId));
1017
+ requireSupported("building a proof", intents.map((intent) => requireChain(Number(intent.destination))));
1018
+ for (const intent of intents) {
1019
+ if (intent.destination !== intents[0].destination ||
1020
+ intent.sourceChainId !== intents[0].sourceChainId ||
1021
+ intent.reward.prover !== intents[0].reward.prover) {
1022
+ throw new UsageError("one proof carries intents from one destination to one source through one prover: " +
1023
+ "prove the others separately");
1024
+ }
1025
+ }
1026
+ if (destinationChain.kind === "svm")
1027
+ return buildSvmProve(intents, chains, options);
1028
+ const destination = await chains.get(destinationChain, "a proof");
1029
+ const source = await chains.maybe(sourceChain);
1030
+ const notes = [];
1031
+ const pairs = [];
1032
+ for (const intent of intents) {
1033
+ const { intentHash } = hashIntent(intent);
1034
+ const recorded = await readCall(destination, fulfillmentCall(intent), "what the destination Portal recorded");
1035
+ if (/^0x0{64}$/.test(recorded)) {
1036
+ return {
1037
+ ready: false,
1038
+ why: `${intentHash} is neither filled nor cancelled on ${destinationChain.slug}: there is nothing to prove`,
1039
+ transactions: [],
1040
+ notes,
1041
+ };
1042
+ }
1043
+ if (source !== undefined) {
1044
+ const proof = await tryRead(source, provenIntentCall(intent));
1045
+ if (proof !== undefined &&
1046
+ proof.claimant !== zeroAddress &&
1047
+ proof.destination === intent.destination) {
1048
+ notes.push(`${intentHash} is proven on ${sourceChain.slug} already, for ${proof.claimant}: left out`);
1049
+ continue;
1050
+ }
1051
+ }
1052
+ if (isCancelled(recorded)) {
1053
+ // A cancellation is proven once the destination block that recorded it is final: a reorg
1054
+ // past the deadline that let a fill in first would leave that solver unpaid (eco-routes'
1055
+ // proven-cancellation design, §1).
1056
+ const block = options.cancelledIn?.[intentHash];
1057
+ if (block === undefined) {
1058
+ notes.push(`${intentHash} was cancelled in a block this does not know: prove it once that block ` +
1059
+ `is final on ${destinationChain.slug}`);
1060
+ }
1061
+ else {
1062
+ const finalized = await destination
1063
+ .getBlock({ blockTag: "finalized" })
1064
+ .then((final) => final.number)
1065
+ .catch(() => undefined);
1066
+ if (finalized === undefined) {
1067
+ notes.push(`${destinationChain.slug}'s endpoint reports no finalized block: make sure block ` +
1068
+ `${block}, which cancelled ${intentHash}, is final`);
1069
+ }
1070
+ else if (finalized < BigInt(block)) {
1071
+ return {
1072
+ ready: false,
1073
+ why: `${intentHash} was cancelled in block ${block} on ${destinationChain.slug}, which is ` +
1074
+ `not final yet (the finalized block is ${finalized}): prove it once it is`,
1075
+ transactions: [],
1076
+ notes,
1077
+ };
1078
+ }
1079
+ }
1080
+ }
1081
+ pairs.push({ intent, intentHash, claimant: recorded });
1082
+ }
1083
+ if (pairs.length === 0) {
1084
+ return { ready: false, why: "every intent is proven already", transactions: [], notes };
1085
+ }
1086
+ const plan = await proverPlan(pairs[0].intent, destination, source);
1087
+ if (!plan.supported) {
1088
+ return { ready: false, why: plan.why, transactions: [], notes, prover: proverJson(plan) };
1089
+ }
1090
+ const fee = await proofFee(destination, plan, intents[0].destination, pairs);
1091
+ const tx = proveTx(pairs.map((pair) => pair.intent), {
1092
+ prover: plan.destinationProver,
1093
+ sourceDomain: plan.sourceDomain,
1094
+ data: plan.data,
1095
+ fee,
1096
+ });
1097
+ const cancelled = pairs.filter((pair) => isCancelled(pair.claimant)).length;
1098
+ return {
1099
+ ready: true,
1100
+ transactions: [
1101
+ txJson(destinationChain, { ...tx, to: getAddress(tx.to) }, `Portal.prove(${plan.destinationProver}, ${plan.sourceDomain}, [${pairs.map((p) => p.intentHash).join(", ")}], data) ` +
1102
+ `with ${fee} wei, the ${plan.kind} fee: carries ${pairs.length - cancelled} fill(s)` +
1103
+ (cancelled === 0 ? "" : ` and ${cancelled} cancellation(s)`) +
1104
+ ` to ${sourceChain.slug}`),
1105
+ ],
1106
+ fee: fee.toString(),
1107
+ prover: proverJson(plan),
1108
+ notes,
1109
+ };
1110
+ }
1111
+ /** The vault's balances of the reward, read once for a claim's or a refund's report. */
1112
+ async function vaultMoves(source, intent, to, all) {
1113
+ return source.holds
1114
+ .map((entry) => ({
1115
+ entry,
1116
+ // `Vault.withdraw` pays at most the reward's amount of each; `Vault.refund` everything.
1117
+ amount: all ? entry.holds : entry.holds < entry.reward ? entry.holds : entry.reward,
1118
+ }))
1119
+ .filter(({ amount }) => amount > 0n)
1120
+ .map(({ entry, amount }) => ({
1121
+ token: entry.token,
1122
+ ...(entry.info?.symbol === undefined ? {} : { symbol: entry.info.symbol }),
1123
+ ...(entry.token === "native"
1124
+ ? { decimals: 18 }
1125
+ : entry.info?.decimals === undefined
1126
+ ? {}
1127
+ : { decimals: entry.info.decimals }),
1128
+ amount: amount.toString(),
1129
+ to,
1130
+ }));
1131
+ }
1132
+ /**
1133
+ * The claim of `records`' rewards on their (one) source: `withdraw`, or `batchWithdraw` for
1134
+ * several, paying each the claimant its prover recorded. An intent that cannot be claimed is left
1135
+ * out with the reason in `notes`; with none left, `ready` is false and `why` is the first reason.
1136
+ */
1137
+ export async function buildClaim(records, endpoints) {
1138
+ if (records.length === 0)
1139
+ throw new UsageError("no intent to claim");
1140
+ const intents = records.map(intentOf);
1141
+ const sourceChain = requireChain(Number(intents[0].sourceChainId));
1142
+ requireSupported("building a claim", intents.map((intent) => requireChain(Number(intent.sourceChainId))));
1143
+ const portal = getAddress(records[0].source.portal);
1144
+ if (records.some((record) => !isAddressEqual(record.source.portal, portal) || record.source.chainId !== sourceChain.id)) {
1145
+ throw new UsageError("one claim withdraws from one source Portal: claim the others separately");
1146
+ }
1147
+ const chains = new Chains(endpoints);
1148
+ const client = await chains.get(sourceChain, "a claim");
1149
+ const notes = [];
1150
+ const claims = [];
1151
+ const sources = await Promise.all(intents.map((intent) => readSource(client, intent, portal)));
1152
+ for (const [index, intent] of intents.entries()) {
1153
+ const { intentHash } = hashIntent(intent);
1154
+ const source = sources[index];
1155
+ const proof = source.proof;
1156
+ const reason = source.status === "Withdrawn"
1157
+ ? "its reward was claimed already"
1158
+ : source.status === "Refunded"
1159
+ ? "its reward was refunded"
1160
+ : proof === null
1161
+ ? `the reward's prover ${getAddress(denormalizeToEvm(intent.reward.prover))} has no proof of it yet`
1162
+ : proof.destination !== intent.destination
1163
+ ? `its proof is from chain ${proof.destination}, not ${intent.destination}: a withdraw would challenge it, not pay`
1164
+ : isAddressEqual(proof.claimant, CANCELLED_CLAIMANT)
1165
+ ? "its cancellation is proven, which pays no claimant: refund it"
1166
+ : undefined;
1167
+ if (reason !== undefined) {
1168
+ notes.push(`${intentHash}: ${reason}`);
1169
+ continue;
1170
+ }
1171
+ claims.push({
1172
+ intent,
1173
+ intentHash,
1174
+ claimant: proof.claimant,
1175
+ vault: source.vault,
1176
+ moves: await vaultMoves(source, intent, proof.claimant, false),
1177
+ });
1178
+ }
1179
+ if (claims.length === 0) {
1180
+ return { ready: false, why: notes[0], transactions: [], notes, claims: [] };
1181
+ }
1182
+ const tx = claims.length === 1
1183
+ ? withdrawTx(claims[0].intent, { portal })
1184
+ : batchWithdrawTx(claims.map((claim) => claim.intent), { portal });
1185
+ return {
1186
+ ready: true,
1187
+ transactions: [
1188
+ txJson(sourceChain, { ...tx, to: getAddress(tx.to) }, claims.length === 1
1189
+ ? `Portal.withdraw(${claims[0].intent.destination}, routeHash, reward): pays ${claims[0].claimant}`
1190
+ : `Portal.batchWithdraw(${claims.length} intents): pays each its claimant`),
1191
+ ],
1192
+ claims: claims.map(({ intentHash, claimant, vault, moves }) => ({
1193
+ intentHash,
1194
+ claimant,
1195
+ vault,
1196
+ moves,
1197
+ })),
1198
+ notes,
1199
+ };
1200
+ }
1201
+ /**
1202
+ * The refund of `record`'s reward to its creator, on the source: `refund`, which anyone may send,
1203
+ * once the Portal allows it — at once after a proven cancellation, from the reward's deadline for
1204
+ * an intent no one proved, and for a claimed one only its leftovers.
1205
+ */
1206
+ export async function buildRefund(record, endpoints) {
1207
+ const intent = intentOf(record);
1208
+ const sourceChain = requireChain(Number(intent.sourceChainId));
1209
+ requireSupported("building a refund", [sourceChain]);
1210
+ const chains = new Chains(endpoints);
1211
+ const client = await chains.get(sourceChain, "a refund");
1212
+ const portal = getAddress(record.source.portal);
1213
+ const source = await readSource(client, intent, portal);
1214
+ const creator = getAddress(denormalizeToEvm(intent.reward.creator));
1215
+ const proof = source.proof;
1216
+ const proofHere = proof !== null && proof.destination === intent.destination;
1217
+ const cancelProven = proofHere && isAddressEqual(proof.claimant, CANCELLED_CLAIMANT);
1218
+ const moves = await vaultMoves(source, intent, creator, true);
1219
+ const deadline = intent.reward.deadline;
1220
+ const why = proofHere && !cancelProven && source.status !== "Withdrawn"
1221
+ ? `it is proven, for ${proof.claimant}: the reward is the claimant's to claim, not the creator's`
1222
+ : !proofHere && source.time < deadline
1223
+ ? `not before the reward's deadline, ${iso(deadline)} (${deadline - source.time}s from ` +
1224
+ `${sourceChain.slug}'s latest block)` +
1225
+ (requireChain(Number(intent.destination)).kind === "evm"
1226
+ ? "; a 2.12+ destination can cancel it sooner, once the route's deadline has passed"
1227
+ : "")
1228
+ : moves.length === 0
1229
+ ? source.status === "Refunded"
1230
+ ? "it was refunded already, and the vault holds nothing more"
1231
+ : "the vault holds nothing to refund"
1232
+ : undefined;
1233
+ if (why !== undefined)
1234
+ return {
1235
+ ready: false,
1236
+ why,
1237
+ transactions: [],
1238
+ notes: [],
1239
+ refundee: creator,
1240
+ vault: source.vault,
1241
+ moves,
1242
+ };
1243
+ const tx = refundTx(intent, { portal });
1244
+ return {
1245
+ ready: true,
1246
+ transactions: [
1247
+ txJson(sourceChain, { ...tx, to: getAddress(tx.to) }, `Portal.refund(${intent.destination}, routeHash, reward): returns the vault's ${source.vault} holdings to the creator ${creator}`),
1248
+ ],
1249
+ refundee: creator,
1250
+ vault: source.vault,
1251
+ moves,
1252
+ notes: cancelProven
1253
+ ? ["the cancellation is proven: refundable before the reward's deadline"]
1254
+ : [],
1255
+ };
1256
+ }
1257
+ /**
1258
+ * The cancellation of `record` on its destination, after the route's deadline: `cancel`, or
1259
+ * `cancelAndProve` with `prove` (its fee in the value). Refused where the destination Portal has no
1260
+ * `cancel`, and where the SOURCE Portal would pay a proven cancellation — the sentinel claimant —
1261
+ * instead of refusing it, since that would burn the reward.
1262
+ */
1263
+ export async function buildCancel(record, endpoints, options = {}) {
1264
+ const intent = intentOf(record);
1265
+ const sourceChain = requireChain(Number(intent.sourceChainId));
1266
+ const destinationChain = requireChain(Number(intent.destination));
1267
+ requireSupported("building a cancellation", [destinationChain]);
1268
+ const chains = new Chains(endpoints);
1269
+ if (destinationChain.kind === "svm")
1270
+ return buildSvmCancel(record, intent, chains, options);
1271
+ const destination = await chains.get(destinationChain, "a cancellation");
1272
+ const sourceClient = await chains.get(sourceChain, "a cancellation (to check the source Portal refuses to pay a cancellation)");
1273
+ const [there, here] = await Promise.all([
1274
+ readDestination(destination, intent),
1275
+ readSource(sourceClient, intent, getAddress(record.source.portal)),
1276
+ ]);
1277
+ const deadline = intent.route.deadline;
1278
+ const notReady = (why) => ({ ready: false, why, transactions: [], notes: [] });
1279
+ if (!there.canCancel) {
1280
+ return notReady(`the destination Portal ${there.portal} on ${destinationChain.slug} has no cancel (it ` +
1281
+ `predates eco-routes 2.12): refund after the reward's deadline, ${iso(intent.reward.deadline)}`);
1282
+ }
1283
+ if (!here.refusesCancelledClaimant) {
1284
+ return notReady(`the source Portal ${here.portal} on ${sourceChain.slug} would pay a proven cancellation to ` +
1285
+ `${CANCELLED_CLAIMANT}, an address nobody controls (it predates eco-routes 2.12), so it ` +
1286
+ `is not cancelled: refund after the reward's deadline, ${iso(intent.reward.deadline)}`);
1287
+ }
1288
+ if (isCancelled(there.claimant)) {
1289
+ return notReady("it is cancelled already: prove the cancellation, then refund");
1290
+ }
1291
+ if (there.claimant !== null)
1292
+ return notReady(`it was filled, for claimant ${there.claimant}`);
1293
+ if (there.time <= deadline) {
1294
+ return notReady(`not before the route's deadline, ${iso(deadline)}, has passed (${deadline + 1n - there.time}s ` +
1295
+ `from ${destinationChain.slug}'s latest block)`);
1296
+ }
1297
+ if (here.status === "Refunded" || here.status === "Withdrawn") {
1298
+ return notReady(`its reward was ${here.status === "Refunded" ? "refunded" : "claimed"} already`);
1299
+ }
1300
+ if (options.prove !== true) {
1301
+ const tx = cancelTx(intent);
1302
+ return {
1303
+ ready: true,
1304
+ transactions: [
1305
+ txJson(destinationChain, { ...tx, to: getAddress(tx.to) }, `Portal.cancel(${hashIntent(intent).intentHash}, route, rewardHash): records the intent cancelled`),
1306
+ ],
1307
+ notes: [
1308
+ "Once the cancel is final on the destination, prove it (`sauce intent prove`), then refund " +
1309
+ "(`sauce intent refund`): eco-routes asks for the proof to wait for finality.",
1310
+ ],
1311
+ };
1312
+ }
1313
+ const plan = await proverPlan(intent, destination, sourceClient);
1314
+ if (!plan.supported)
1315
+ return { ...notReady(plan.why), prover: proverJson(plan) };
1316
+ const fee = await proofFee(destination, plan, intent.destination, [
1317
+ { intentHash: hashIntent(intent).intentHash, claimant: CANCELLED_CLAIMANT_BYTES32 },
1318
+ ]);
1319
+ const tx = cancelAndProveTx(intent, {
1320
+ prover: plan.destinationProver,
1321
+ sourceDomain: plan.sourceDomain,
1322
+ data: plan.data,
1323
+ fee,
1324
+ });
1325
+ return {
1326
+ ready: true,
1327
+ transactions: [
1328
+ txJson(destinationChain, { ...tx, to: getAddress(tx.to) }, `Portal.cancelAndProve(${hashIntent(intent).intentHash}, route, rewardHash, ${plan.destinationProver}, ` +
1329
+ `${plan.sourceDomain}, data) with ${fee} wei, the ${plan.kind} fee`),
1330
+ ],
1331
+ fee: fee.toString(),
1332
+ prover: proverJson(plan),
1333
+ notes: [
1334
+ "warning: this proves the cancellation before the destination is final. eco-routes asks a " +
1335
+ "refund service to cancel, wait for finality, then prove: a reorg past the deadline that " +
1336
+ "re-includes a fill would leave that solver unpaid.",
1337
+ ],
1338
+ };
1339
+ }
1340
+ // ---------------------------------------------------------------------------------------------
1341
+ // An intent to Solana
1342
+ // ---------------------------------------------------------------------------------------------
1343
+ /** A claimant on the source chain as the 32 bytes Solana's Portal records: an EVM address, padded. */
1344
+ function claimant32(claimant, chain) {
1345
+ if (claimant === undefined) {
1346
+ throw new UsageError(`a fill on ${chain.slug} needs the claimant, an address on the intent's source chain that the ` +
1347
+ "reward pays (--claimant <address>): the Solana key that fills it is not one");
1348
+ }
1349
+ const bytes = hexToBytes(claimant);
1350
+ if (bytes.length !== 20 && bytes.length !== 32) {
1351
+ throw new UsageError(`the claimant ${claimant} is neither an address nor 32 bytes`);
1352
+ }
1353
+ return toUniversalAddress(claimant);
1354
+ }
1355
+ /** The Solana fee payer a step is sent from: `from`, a Solana key. */
1356
+ function svmPayer(from, what) {
1357
+ if (from === undefined) {
1358
+ throw new UsageError(`${what} on Solana needs the account that pays its fee (--keypair <path>)`);
1359
+ }
1360
+ try {
1361
+ return svmAddress(from);
1362
+ }
1363
+ catch {
1364
+ throw new UsageError(`${from} is not a Solana key: ${what} on Solana is paid by a Solana account`);
1365
+ }
1366
+ }
1367
+ async function buildSvmFill(intent, chains, options) {
1368
+ const destination = requireChain(Number(intent.destination));
1369
+ const sourceChain = requireChain(Number(intent.sourceChainId));
1370
+ const rpc = chains.svm(destination, "a fill");
1371
+ const solver = svmPayer(options.from, "a fill");
1372
+ const claimant = claimant32(options.claimant, destination);
1373
+ const source = await chains.maybe(sourceChain);
1374
+ const [there, prover] = await Promise.all([
1375
+ readSvmDestination(rpc, intent),
1376
+ svmProverPlan(intent, rpc, source),
1377
+ ]);
1378
+ if (options.prove === true && !prover.supported) {
1379
+ throw new CliError(`the fill cannot prove itself: ${prover.why}`);
1380
+ }
1381
+ const proves = options.prove !== false && prover.supported;
1382
+ const plan = await planSvmFill(rpc, destination, intent, { solver, claimant });
1383
+ const notes = [...plan.notes];
1384
+ if (there.claimant !== null) {
1385
+ notes.push(isCancelled(there.claimant)
1386
+ ? "it is cancelled on Solana: the fulfill fails"
1387
+ : `it is filled already on Solana, for claimant ${there.claimant}: the fulfill fails`);
1388
+ }
1389
+ if (options.prove === undefined && !prover.supported) {
1390
+ notes.push(`it is filled without its proof: ${prover.why}`);
1391
+ }
1392
+ const { intentHash } = hashIntent(intent);
1393
+ const transactions = [plan.transaction];
1394
+ if (proves) {
1395
+ transactions.push(await svmProveTransaction(rpc, destination, svmAddress(there.portal), [intentHash], prover.hyper, solver, `Portal.prove(${prover.destinationProver}, ${sourceChain.id}, [${intentHash}]) through ` +
1396
+ `Hyperlane to ${sourceChain.slug}, the IGP's gas paid`));
1397
+ notes.push("The second transaction proves the fill, so send it once the first has landed. It shares " +
1398
+ "the first's blockhash, which lasts about a minute; past that, build the proof again " +
1399
+ "(`sauce intent prove`).");
1400
+ }
1401
+ return {
1402
+ from: solver,
1403
+ transactions,
1404
+ proves,
1405
+ fee: { prover: "0", kitchen: "0" },
1406
+ prover: proverJson(prover),
1407
+ delivers: plan.tokens.map((token) => ({
1408
+ token: token.mint,
1409
+ amount: token.amount.toString(),
1410
+ held: token.held.toString(),
1411
+ })),
1412
+ notes,
1413
+ };
1414
+ }
1415
+ async function buildSvmProve(intents, chains, options) {
1416
+ const destinationChain = requireChain(Number(intents[0].destination));
1417
+ const sourceChain = requireChain(Number(intents[0].sourceChainId));
1418
+ const rpc = chains.svm(destinationChain, "a proof");
1419
+ const source = await chains.maybe(sourceChain);
1420
+ const payer = svmPayer(options.from, "a proof");
1421
+ const notes = [];
1422
+ const pairs = [];
1423
+ let portal;
1424
+ // What the destination recorded for every intent, read at once.
1425
+ const recorded = await Promise.all(intents.map((intent) => readSvmDestination(rpc, intent)));
1426
+ for (const [index, intent] of intents.entries()) {
1427
+ const { intentHash } = hashIntent(intent);
1428
+ const there = recorded[index];
1429
+ portal = there.portal;
1430
+ if (there.claimant === null) {
1431
+ return {
1432
+ ready: false,
1433
+ why: `${intentHash} is neither filled nor cancelled on ${destinationChain.slug}: there is nothing to prove`,
1434
+ transactions: [],
1435
+ notes,
1436
+ };
1437
+ }
1438
+ if (source !== undefined) {
1439
+ const proof = await tryRead(source, provenIntentCall(intent));
1440
+ if (proof !== undefined &&
1441
+ proof.claimant !== zeroAddress &&
1442
+ proof.destination === intent.destination) {
1443
+ notes.push(`${intentHash} is proven on ${sourceChain.slug} already, for ${proof.claimant}: left out`);
1444
+ continue;
1445
+ }
1446
+ }
1447
+ if (isCancelled(there.claimant)) {
1448
+ // As on an EVM destination: the cancellation is proven once the slot that recorded it is
1449
+ // final (eco-routes' proven-cancellation design, §1).
1450
+ const slot = options.cancelledIn?.[intentHash];
1451
+ if (slot === undefined) {
1452
+ notes.push(`${intentHash} was cancelled in a slot this does not know: prove it once that slot is ` +
1453
+ `final on ${destinationChain.slug}`);
1454
+ }
1455
+ else {
1456
+ const finalized = await svmFinalizedSlot(rpc);
1457
+ if (finalized < BigInt(slot)) {
1458
+ return {
1459
+ ready: false,
1460
+ why: `${intentHash} was cancelled in slot ${slot} on ${destinationChain.slug}, which is ` +
1461
+ `not final yet (the finalized slot is ${finalized}): prove it once it is`,
1462
+ transactions: [],
1463
+ notes,
1464
+ };
1465
+ }
1466
+ }
1467
+ }
1468
+ pairs.push({ intent, intentHash, claimant: there.claimant });
1469
+ }
1470
+ if (pairs.length === 0) {
1471
+ return { ready: false, why: "every intent is proven already", transactions: [], notes };
1472
+ }
1473
+ const plan = await svmProverPlan(pairs[0].intent, rpc, source);
1474
+ if (!plan.supported) {
1475
+ return { ready: false, why: plan.why, transactions: [], notes, prover: proverJson(plan) };
1476
+ }
1477
+ const cancelled = pairs.filter((pair) => isCancelled(pair.claimant)).length;
1478
+ const tx = await svmProveTransaction(rpc, destinationChain, svmAddress(portal), pairs.map((pair) => pair.intentHash), plan.hyper, payer, `Portal.prove(${plan.destinationProver}, ${sourceChain.id}, [${pairs.map((pair) => pair.intentHash).join(", ")}]) ` +
1479
+ `through Hyperlane, the IGP's gas paid: carries ${pairs.length - cancelled} fill(s)` +
1480
+ (cancelled === 0 ? "" : ` and ${cancelled} cancellation(s)`) +
1481
+ ` to ${sourceChain.slug}`);
1482
+ const rehearsal = await rehearseSvm(rpc, tx, [payer]);
1483
+ if (!rehearsal.ok) {
1484
+ return {
1485
+ ready: false,
1486
+ why: `the proof fails on ${destinationChain.slug}: ${rehearsal.reason}`,
1487
+ transactions: [],
1488
+ notes,
1489
+ prover: proverJson(plan),
1490
+ };
1491
+ }
1492
+ const spend = await svmSpend(rpc, payer, tx, rehearsal);
1493
+ return {
1494
+ ready: true,
1495
+ transactions: [{ ...tx, value: spend.toString() }],
1496
+ fee: spend.toString(),
1497
+ prover: proverJson(plan),
1498
+ notes,
1499
+ };
1500
+ }
1501
+ async function buildSvmCancel(record, intent, chains, options) {
1502
+ const sourceChain = requireChain(Number(intent.sourceChainId));
1503
+ const destinationChain = requireChain(Number(intent.destination));
1504
+ const rpc = chains.svm(destinationChain, "a cancellation");
1505
+ const sourceClient = await chains.get(sourceChain, "a cancellation (to check the source Portal refuses to pay a cancellation)");
1506
+ const payer = svmPayer(options.from, "a cancellation");
1507
+ const [there, here] = await Promise.all([
1508
+ readSvmDestination(rpc, intent),
1509
+ readSource(sourceClient, intent, getAddress(record.source.portal)),
1510
+ ]);
1511
+ const deadline = intent.route.deadline;
1512
+ const notReady = (why) => ({ ready: false, why, transactions: [], notes: [] });
1513
+ if (!there.canCancel) {
1514
+ return notReady(`the destination Portal ${there.portal} on ${destinationChain.slug} has no cancel: refund ` +
1515
+ `after the reward's deadline, ${iso(intent.reward.deadline)}`);
1516
+ }
1517
+ if (!here.refusesCancelledClaimant) {
1518
+ return notReady(`the source Portal ${here.portal} on ${sourceChain.slug} would pay a proven cancellation to ` +
1519
+ `${CANCELLED_CLAIMANT}, an address nobody controls (it predates eco-routes 2.12), so it ` +
1520
+ `is not cancelled: refund after the reward's deadline, ${iso(intent.reward.deadline)}`);
1521
+ }
1522
+ if (isCancelled(there.claimant)) {
1523
+ return notReady("it is cancelled already: prove the cancellation, then refund");
1524
+ }
1525
+ if (there.claimant !== null)
1526
+ return notReady(`it was filled, for claimant ${there.claimant}`);
1527
+ if (there.time <= deadline) {
1528
+ return notReady(`not before the route's deadline, ${iso(deadline)}, has passed (${deadline + 1n - there.time}s ` +
1529
+ `by ${destinationChain.slug}'s clock)`);
1530
+ }
1531
+ if (here.status === "Refunded" || here.status === "Withdrawn") {
1532
+ return notReady(`its reward was ${here.status === "Refunded" ? "refunded" : "claimed"} already`);
1533
+ }
1534
+ const { intentHash } = hashIntent(intent);
1535
+ const plan = options.prove === true ? await svmProverPlan(intent, rpc, sourceClient) : undefined;
1536
+ if (plan !== undefined && !plan.supported) {
1537
+ return { ...notReady(plan.why), prover: proverJson(plan) };
1538
+ }
1539
+ const tx = await svmCancelTransaction(rpc, destinationChain, intent, payer, plan?.hyper, plan === undefined
1540
+ ? `Portal.cancel(${intentHash}, route, rewardHash) on ${destinationChain.slug}: records the intent cancelled`
1541
+ : `Portal.cancel(${intentHash}, route, rewardHash), then Portal.prove(${plan.destinationProver}, ` +
1542
+ `${sourceChain.id}, [${intentHash}]) through Hyperlane, the IGP's gas paid`);
1543
+ const rehearsal = await rehearseSvm(rpc, tx, [payer]);
1544
+ if (!rehearsal.ok) {
1545
+ return notReady(`the cancellation fails on ${destinationChain.slug}: ${rehearsal.reason}`);
1546
+ }
1547
+ const spend = await svmSpend(rpc, payer, tx, rehearsal);
1548
+ return {
1549
+ ready: true,
1550
+ transactions: [{ ...tx, value: plan === undefined ? "0" : spend.toString() }],
1551
+ ...(plan === undefined ? {} : { fee: spend.toString(), prover: proverJson(plan) }),
1552
+ notes: plan === undefined
1553
+ ? [
1554
+ "Once the cancel is final on the destination, prove it (`sauce intent prove`), then " +
1555
+ "refund (`sauce intent refund`): eco-routes asks for the proof to wait for finality.",
1556
+ ]
1557
+ : [
1558
+ "warning: this proves the cancellation before the destination is final. eco-routes " +
1559
+ "asks a refund service to cancel, wait for finality, then prove: a rollback past the " +
1560
+ "deadline that re-includes a fill would leave that solver unpaid.",
1561
+ ],
1562
+ };
1563
+ }
1564
+ /** `DispatchId(bytes32 indexed messageId)`: a Hyperlane Mailbox's record of a message it sent. */
1565
+ const DISPATCH_ID = toEventSelector("DispatchId(bytes32)");
1566
+ /** The Hyperlane messages a transaction dispatched, from its receipt's logs: what a proof travels
1567
+ * as, and what the Hyperlane explorer finds it by. */
1568
+ export function dispatchedMessages(logs) {
1569
+ return logs
1570
+ .filter((log) => log.topics[0]?.toLowerCase() === DISPATCH_ID && log.topics[1] !== undefined)
1571
+ .map((log) => ({ mailbox: getAddress(log.address), id: log.topics[1] }));
1572
+ }
1573
+ /**
1574
+ * The gateway's status of `intentHash` from `GET <api>/v1/intents/status?intentHash=…` — an
1575
+ * OPTIONAL second source, at a URL the caller gives (none is built in), beside the on-chain reads
1576
+ * that are the truth. `apiKey`, when given, goes in `x-api-key`. `undefined` when the gateway has no
1577
+ * entry for the intent; a failure is an error naming the status, never the URL or the key.
1578
+ */
1579
+ export async function gatewayStatus(api, intentHash, apiKey) {
1580
+ const url = `${api.replace(/\/+$/, "")}/v1/intents/status?${new URLSearchParams({ intentHash })}`;
1581
+ let response;
1582
+ try {
1583
+ response = await fetch(url, {
1584
+ headers: {
1585
+ accept: "application/json",
1586
+ ...(apiKey === undefined ? {} : { "x-api-key": apiKey }),
1587
+ },
1588
+ });
1589
+ }
1590
+ catch {
1591
+ throw new CliError("the gateway (--api) could not be reached");
1592
+ }
1593
+ if (!response.ok) {
1594
+ throw new CliError(`the gateway (--api) answered ${response.status}` +
1595
+ (response.status === 401 || response.status === 403
1596
+ ? ": it needs an API key (--api-key-file)"
1597
+ : ""));
1598
+ }
1599
+ const page = (await response.json().catch(() => ({})));
1600
+ const wanted = intentHash.toLowerCase();
1601
+ const entry = (page.results ?? []).find((result) => (result.intentHashes ?? []).some((hash) => hash.toLowerCase() === wanted));
1602
+ if (entry?.status === undefined)
1603
+ return undefined;
1604
+ return {
1605
+ status: entry.status,
1606
+ ...(entry.destinationTx?.txHash === undefined
1607
+ ? {}
1608
+ : { destinationTx: entry.destinationTx.txHash }),
1609
+ ...(entry.updatedAt === undefined ? {} : { updatedAt: String(entry.updatedAt) }),
1610
+ };
1611
+ }
1612
+ const INTENT_FUNDED_TOPIC = toEventSelector(PortalABI.find((item) => item.type === "event" && item.name === "IntentFunded"));
1613
+ /**
1614
+ * The intents `logs` record funded completely, as `portal:intentHash` keys: each
1615
+ * `IntentFunded(intentHash, funder, complete)` decoded strictly with the registry's declaration,
1616
+ * and keyed by the contract that emitted it, so another contract's log of the same shape funds
1617
+ * nothing. A log that does not decode is not a funding.
1618
+ */
1619
+ export function fundedIntents(logs) {
1620
+ const funded = new Set();
1621
+ for (const log of logs) {
1622
+ if (log.topics[0]?.toLowerCase() !== INTENT_FUNDED_TOPIC)
1623
+ continue;
1624
+ let decoded;
1625
+ try {
1626
+ decoded = decodeEventLog({
1627
+ abi: PortalABI,
1628
+ eventName: "IntentFunded",
1629
+ topics: log.topics,
1630
+ data: log.data,
1631
+ strict: true,
1632
+ });
1633
+ }
1634
+ catch {
1635
+ continue;
1636
+ }
1637
+ if (decoded.eventName !== "IntentFunded" || !decoded.args.complete)
1638
+ continue;
1639
+ funded.add(`${getAddress(log.address)}:${decoded.args.intentHash.toLowerCase()}`);
1640
+ }
1641
+ return funded;
1642
+ }
1643
+ /**
1644
+ * The intents `logs` — a transaction's, mined in `at.blockNumber` on `chain` — announce with
1645
+ * `IntentPublished`, rebuilt and recorded with the vault each one's Portal derives, and whether the
1646
+ * same transaction funded each completely. None is an empty list, not an error.
1647
+ */
1648
+ export async function publishedIntents(client, chain, logs, at) {
1649
+ const indexed = logs.map((log, index) => ({ log, index }));
1650
+ const published = indexed.flatMap(({ log, index }) => {
1651
+ const intent = intentFromPublished({ topics: log.topics, data: log.data }, BigInt(chain.id));
1652
+ return intent === undefined ? [] : [{ ...intent, portal: getAddress(log.address), index }];
1653
+ });
1654
+ if (published.length === 0)
1655
+ return [];
1656
+ const block = await read("its block", () => client.getBlock({ blockNumber: at.blockNumber }));
1657
+ const funded = fundedIntents(logs);
1658
+ return Promise.all(published.map(async ({ intent, intentHash, portal, index }) => {
1659
+ const vault = await tryRead(client, intentVaultAddressCall(intent, { portal }));
1660
+ // Funded by a transfer into the vault before `publish`: no `IntentFunded`, so asked of the
1661
+ // Portal as of the block that published it.
1662
+ const logged = funded.has(`${portal}:${intentHash.toLowerCase()}`);
1663
+ const query = isIntentFundedCall(intent, { portal });
1664
+ const held = logged ||
1665
+ (await client
1666
+ .call({ to: query.to, data: query.data, blockNumber: at.blockNumber })
1667
+ .then(({ data }) => (data === undefined || data === "0x" ? false : query.decode(data)))
1668
+ .catch(() => false));
1669
+ return {
1670
+ record: intentRecord(intent, {
1671
+ sourcePortal: portal,
1672
+ ...(vault === undefined ? {} : { vault }),
1673
+ }),
1674
+ txHash: at.txHash,
1675
+ block: at.blockNumber.toString(),
1676
+ time: block.timestamp.toString(),
1677
+ logIndex: index,
1678
+ funded: held,
1679
+ };
1680
+ }));
1681
+ }
1682
+ /**
1683
+ * The intents the transaction `txHash` on `chain` published, rebuilt from its `IntentPublished`
1684
+ * logs (`routes/portal.ts#intentFromPublished`, which checks each one's hash), with the vault each
1685
+ * one's Portal derives. `index` picks one of several. The Portal is the log's emitter: an intent
1686
+ * is claimed and refunded where it was published.
1687
+ */
1688
+ export async function importIntents(ref, endpoints) {
1689
+ const chain = requireChain(ref.chain);
1690
+ if (chain.kind !== "evm") {
1691
+ throw new CliError(`${chain.slug} is not an EVM chain: intents are imported from an EVM Portal's logs`);
1692
+ }
1693
+ const client = await new Chains(endpoints).get(chain, "an import");
1694
+ let receipt;
1695
+ try {
1696
+ receipt = await client.getTransactionReceipt({ hash: ref.txHash });
1697
+ }
1698
+ catch (error) {
1699
+ throw new CliError(`reading the receipt of ${ref.txHash} on ${chain.slug} failed: ${reasonOf(error)}`);
1700
+ }
1701
+ if (receipt.status !== "success") {
1702
+ throw new CliError(`${ref.txHash} reverted on ${chain.slug}: it published nothing`);
1703
+ }
1704
+ const found = await publishedIntents(client, chain, receipt.logs.map((log) => ({
1705
+ address: getAddress(log.address),
1706
+ topics: log.topics,
1707
+ data: log.data,
1708
+ })), { txHash: ref.txHash, blockNumber: receipt.blockNumber });
1709
+ if (found.length === 0) {
1710
+ throw new CliError(`${ref.txHash} on ${chain.slug} logged no IntentPublished: it published no intent`);
1711
+ }
1712
+ if (ref.index !== undefined) {
1713
+ const one = found[ref.index];
1714
+ if (one === undefined) {
1715
+ throw new UsageError(`${ref.txHash} published ${found.length} intent(s): index ${ref.index} is not one`);
1716
+ }
1717
+ return { intents: [one], notes: [] };
1718
+ }
1719
+ return { intents: found, notes: [] };
1720
+ }
1721
+ //# sourceMappingURL=lifecycle.js.map