@oracle-agent/oracle 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/LICENSE +115 -201
  2. package/README.md +13 -516
  3. package/bin/oracle.mjs +19 -27
  4. package/package.json +15 -98
  5. package/CONTRIBUTING.md +0 -98
  6. package/SECURITY.md +0 -89
  7. package/SETUP.md +0 -381
  8. package/artifacts/inscription/oracle-was-here-preview.png +0 -0
  9. package/artifacts/inscription/oracle-was-here.svg +0 -1
  10. package/artifacts/specialist-packs/oracle-full-crypto.json +0 -295
  11. package/bin/desk-server.mjs +0 -440
  12. package/bin/oracle-data-mcp.mjs +0 -1019
  13. package/bin/oracle-init.mjs +0 -496
  14. package/bin/oracle-public-server.mjs +0 -36
  15. package/bin/oracle-route.mjs +0 -254
  16. package/bin/oracle-scan.mjs +0 -192
  17. package/bin/oracle-upgrade.mjs +0 -42
  18. package/docs/adding-a-chain.md +0 -229
  19. package/docs/architecture.md +0 -138
  20. package/docs/cli.md +0 -47
  21. package/docs/connectors.md +0 -13
  22. package/docs/oracle-pack-standard.md +0 -29
  23. package/docs/profiles.md +0 -151
  24. package/docs/public-surface.md +0 -133
  25. package/examples/add-a-chain.mjs +0 -65
  26. package/examples/oracle-pack-template.mjs +0 -38
  27. package/examples/research-a-token.mjs +0 -70
  28. package/plugins/oracle-owner-gate/__init__.py +0 -227
  29. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  30. package/profiles/_template/SOUL.md +0 -54
  31. package/profiles/_template/profile.json +0 -22
  32. package/profiles/bitcoin-agent/SOUL.md +0 -31
  33. package/profiles/bitcoin-agent/profile.json +0 -32
  34. package/profiles/hyperliquid-agent/SOUL.md +0 -34
  35. package/profiles/hyperliquid-agent/profile.json +0 -37
  36. package/profiles/oracle/SOUL.md +0 -107
  37. package/profiles/oracle/profile.json +0 -39
  38. package/profiles/polymarket-agent/SOUL.md +0 -35
  39. package/profiles/polymarket-agent/profile.json +0 -34
  40. package/profiles/profile.schema.json +0 -90
  41. package/profiles/protocol-builder/SOUL.md +0 -57
  42. package/profiles/protocol-builder/profile.json +0 -39
  43. package/profiles/robinhood-agent/SOUL.md +0 -53
  44. package/profiles/robinhood-agent/profile.json +0 -40
  45. package/profiles/solana-agent/SOUL.md +0 -37
  46. package/profiles/solana-agent/profile.json +0 -37
  47. package/profiles/stable-agent/SOUL.md +0 -43
  48. package/profiles/stable-agent/profile.json +0 -37
  49. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  50. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  51. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  52. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  53. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  54. package/public/agent-connect/app.js +0 -84
  55. package/public/agent-connect/index.html +0 -83
  56. package/public/agent-connect/styles.css +0 -70
  57. package/public/index.html +0 -12
  58. package/public/oracle-console/app.js +0 -272
  59. package/public/oracle-console/bitcoin-wallets.js +0 -206
  60. package/public/oracle-console/index.html +0 -91
  61. package/public/oracle-console/styles.css +0 -239
  62. package/public/oracle-splash/assets/cli-chain-hyperliquid.jpg +0 -0
  63. package/public/oracle-splash/assets/hero/orb.avif +0 -0
  64. package/public/oracle-splash/assets/hero/orb.webm +0 -0
  65. package/public/oracle-splash/assets/llms/claude.svg +0 -1
  66. package/public/oracle-splash/assets/llms/codex-icon.svg +0 -1
  67. package/public/oracle-splash/assets/llms/codex.svg +0 -1
  68. package/public/oracle-splash/assets/llms/cursor-icon.svg +0 -12
  69. package/public/oracle-splash/assets/llms/cursor.svg +0 -17
  70. package/public/oracle-splash/assets/llms/deepseek.svg +0 -1
  71. package/public/oracle-splash/assets/llms/gemini-icon.svg +0 -1
  72. package/public/oracle-splash/assets/llms/gemini.svg +0 -1
  73. package/public/oracle-splash/assets/llms/grok.svg +0 -8
  74. package/public/oracle-splash/assets/llms/hermes.png +0 -0
  75. package/public/oracle-splash/assets/llms/kimi-icon.svg +0 -1
  76. package/public/oracle-splash/assets/llms/kimi.svg +0 -1
  77. package/public/oracle-splash/assets/llms/manus.svg +0 -18
  78. package/public/oracle-splash/assets/llms/openclaw.svg +0 -22
  79. package/public/oracle-splash/assets/llms/perplexity.svg +0 -1
  80. package/public/oracle-splash/assets/llms/qwen.svg +0 -1
  81. package/public/oracle-splash/assets/llms/windsurf.svg +0 -1
  82. package/public/oracle-splash/assets/protocols/abcdex.png +0 -0
  83. package/public/oracle-splash/assets/protocols/across.png +0 -0
  84. package/public/oracle-splash/assets/protocols/aerodrome.png +0 -0
  85. package/public/oracle-splash/assets/protocols/balancer.png +0 -0
  86. package/public/oracle-splash/assets/protocols/cowswap.png +0 -0
  87. package/public/oracle-splash/assets/protocols/curve.png +0 -0
  88. package/public/oracle-splash/assets/protocols/dreamcash.png +0 -0
  89. package/public/oracle-splash/assets/protocols/felix.png +0 -0
  90. package/public/oracle-splash/assets/protocols/gmx.png +0 -0
  91. package/public/oracle-splash/assets/protocols/hyena.png +0 -0
  92. package/public/oracle-splash/assets/protocols/hyperbeat.png +0 -0
  93. package/public/oracle-splash/assets/protocols/hyperliquid.png +0 -0
  94. package/public/oracle-splash/assets/protocols/hyperswap.png +0 -0
  95. package/public/oracle-splash/assets/protocols/jupiter.png +0 -0
  96. package/public/oracle-splash/assets/protocols/kinetiq.png +0 -0
  97. package/public/oracle-splash/assets/protocols/lfj.png +0 -0
  98. package/public/oracle-splash/assets/protocols/lifi.png +0 -0
  99. package/public/oracle-splash/assets/protocols/magic-eden.png +0 -0
  100. package/public/oracle-splash/assets/protocols/morpho.png +0 -0
  101. package/public/oracle-splash/assets/protocols/odos.png +0 -0
  102. package/public/oracle-splash/assets/protocols/oneinch.png +0 -0
  103. package/public/oracle-splash/assets/protocols/opensea.png +0 -0
  104. package/public/oracle-splash/assets/protocols/pancakeswap.png +0 -0
  105. package/public/oracle-splash/assets/protocols/paragon.png +0 -0
  106. package/public/oracle-splash/assets/protocols/paraswap.png +0 -0
  107. package/public/oracle-splash/assets/protocols/pendle.png +0 -0
  108. package/public/oracle-splash/assets/protocols/polymarket.png +0 -0
  109. package/public/oracle-splash/assets/protocols/quickswap.png +0 -0
  110. package/public/oracle-splash/assets/protocols/relay.png +0 -0
  111. package/public/oracle-splash/assets/protocols/stargate.png +0 -0
  112. package/public/oracle-splash/assets/protocols/tradexyz.png +0 -0
  113. package/public/oracle-splash/assets/protocols/uniswap.png +0 -0
  114. package/public/oracle-splash/assets/protocols/velodrome.png +0 -0
  115. package/public/oracle-splash/assets/protocols/ventuals.png +0 -0
  116. package/public/oracle-splash/assets/wordmarks/across-icon.webp +0 -0
  117. package/public/oracle-splash/assets/wordmarks/across.svg +0 -4
  118. package/public/oracle-splash/assets/wordmarks/aerodrome.svg +0 -23
  119. package/public/oracle-splash/assets/wordmarks/balancer.svg +0 -3
  120. package/public/oracle-splash/assets/wordmarks/cowswap.svg +0 -1
  121. package/public/oracle-splash/assets/wordmarks/curve.png +0 -0
  122. package/public/oracle-splash/assets/wordmarks/gmx.svg +0 -13
  123. package/public/oracle-splash/assets/wordmarks/hop-icon.webp +0 -0
  124. package/public/oracle-splash/assets/wordmarks/hyena.svg +0 -7
  125. package/public/oracle-splash/assets/wordmarks/hyperliquid.svg +0 -21
  126. package/public/oracle-splash/assets/wordmarks/hyperswap.svg +0 -13
  127. package/public/oracle-splash/assets/wordmarks/jupiter.svg +0 -35
  128. package/public/oracle-splash/assets/wordmarks/kinetiq.svg +0 -1
  129. package/public/oracle-splash/assets/wordmarks/lfj.webp +0 -0
  130. package/public/oracle-splash/assets/wordmarks/lifi.png +0 -0
  131. package/public/oracle-splash/assets/wordmarks/magic-eden.svg +0 -1
  132. package/public/oracle-splash/assets/wordmarks/markets.svg +0 -1
  133. package/public/oracle-splash/assets/wordmarks/morpho.svg +0 -1
  134. package/public/oracle-splash/assets/wordmarks/odos.svg +0 -3
  135. package/public/oracle-splash/assets/wordmarks/oneinch-icon.webp +0 -0
  136. package/public/oracle-splash/assets/wordmarks/oneinch.svg +0 -6
  137. package/public/oracle-splash/assets/wordmarks/opensea-icon.svg +0 -17
  138. package/public/oracle-splash/assets/wordmarks/opensea.svg +0 -1
  139. package/public/oracle-splash/assets/wordmarks/outcome.svg +0 -16
  140. package/public/oracle-splash/assets/wordmarks/pancakeswap.svg +0 -18
  141. package/public/oracle-splash/assets/wordmarks/paragon.svg +0 -9
  142. package/public/oracle-splash/assets/wordmarks/paraswap.svg +0 -16
  143. package/public/oracle-splash/assets/wordmarks/pendle.png +0 -0
  144. package/public/oracle-splash/assets/wordmarks/polymarket.png +0 -0
  145. package/public/oracle-splash/assets/wordmarks/quickswap.png +0 -0
  146. package/public/oracle-splash/assets/wordmarks/relay.svg +0 -8
  147. package/public/oracle-splash/assets/wordmarks/satflow-icon.png +0 -0
  148. package/public/oracle-splash/assets/wordmarks/stargate-icon.webp +0 -0
  149. package/public/oracle-splash/assets/wordmarks/stargate.svg +0 -15
  150. package/public/oracle-splash/assets/wordmarks/uniswap.svg +0 -18
  151. package/public/oracle-splash/assets/wordmarks/velodrome.svg +0 -84
  152. package/public/oracle-splash/assets/wordmarks/xyz.svg +0 -12
  153. package/public/oracle-splash/assets/wordmarks/zerox-icon.webp +0 -0
  154. package/public/oracle-splash/brand/aave.webp +0 -0
  155. package/public/oracle-splash/brand/aavev2.webp +0 -0
  156. package/public/oracle-splash/brand/aborean.webp +0 -0
  157. package/public/oracle-splash/brand/across.webp +0 -0
  158. package/public/oracle-splash/brand/aerodrome.webp +0 -0
  159. package/public/oracle-splash/brand/afi.webp +0 -0
  160. package/public/oracle-splash/brand/arcus.webp +0 -0
  161. package/public/oracle-splash/brand/aster.webp +0 -0
  162. package/public/oracle-splash/brand/avant.webp +0 -0
  163. package/public/oracle-splash/brand/balancer.webp +0 -0
  164. package/public/oracle-splash/brand/beefy.webp +0 -0
  165. package/public/oracle-splash/brand/benqi.webp +0 -0
  166. package/public/oracle-splash/brand/bestinslot.ico +0 -0
  167. package/public/oracle-splash/brand/bitfi.webp +0 -0
  168. package/public/oracle-splash/brand/bonkswap.webp +0 -0
  169. package/public/oracle-splash/brand/bouncebit.webp +0 -0
  170. package/public/oracle-splash/brand/camelot.webp +0 -0
  171. package/public/oracle-splash/brand/compound.webp +0 -0
  172. package/public/oracle-splash/brand/concrete.webp +0 -0
  173. package/public/oracle-splash/brand/cow.webp +0 -0
  174. package/public/oracle-splash/brand/curve.webp +0 -0
  175. package/public/oracle-splash/brand/derive.webp +0 -0
  176. package/public/oracle-splash/brand/dolomite.webp +0 -0
  177. package/public/oracle-splash/brand/eigenlayer.webp +0 -0
  178. package/public/oracle-splash/brand/ekubo.webp +0 -0
  179. package/public/oracle-splash/brand/ethena.webp +0 -0
  180. package/public/oracle-splash/brand/etherfi.webp +0 -0
  181. package/public/oracle-splash/brand/etherfiborrow.webp +0 -0
  182. package/public/oracle-splash/brand/felix.webp +0 -0
  183. package/public/oracle-splash/brand/fluid.webp +0 -0
  184. package/public/oracle-splash/brand/fluxbeam.webp +0 -0
  185. package/public/oracle-splash/brand/folks.webp +0 -0
  186. package/public/oracle-splash/brand/fortyacres.webp +0 -0
  187. package/public/oracle-splash/brand/gainsnetwork.webp +0 -0
  188. package/public/oracle-splash/brand/gassss.webp +0 -0
  189. package/public/oracle-splash/brand/gmx.webp +0 -0
  190. package/public/oracle-splash/brand/harmonix.webp +0 -0
  191. package/public/oracle-splash/brand/hlorderbook.webp +0 -0
  192. package/public/oracle-splash/brand/hlp.webp +0 -0
  193. package/public/oracle-splash/brand/hop.webp +0 -0
  194. package/public/oracle-splash/brand/hyperbeat.webp +0 -0
  195. package/public/oracle-splash/brand/hyperlend.webp +0 -0
  196. package/public/oracle-splash/brand/hyperliquid.webp +0 -0
  197. package/public/oracle-splash/brand/hyperliquidhpl.webp +0 -0
  198. package/public/oracle-splash/brand/hyperliquidspot.webp +0 -0
  199. package/public/oracle-splash/brand/hyperswap.webp +0 -0
  200. package/public/oracle-splash/brand/hypha.webp +0 -0
  201. package/public/oracle-splash/brand/joedex.webp +0 -0
  202. package/public/oracle-splash/brand/jupiter.webp +0 -0
  203. package/public/oracle-splash/brand/kelp.webp +0 -0
  204. package/public/oracle-splash/brand/kinetiq.webp +0 -0
  205. package/public/oracle-splash/brand/kmhype.webp +0 -0
  206. package/public/oracle-splash/brand/kona.webp +0 -0
  207. package/public/oracle-splash/brand/konalend.webp +0 -0
  208. package/public/oracle-splash/brand/lfj.webp +0 -0
  209. package/public/oracle-splash/brand/lido.webp +0 -0
  210. package/public/oracle-splash/brand/lifi.webp +0 -0
  211. package/public/oracle-splash/brand/lighter.webp +0 -0
  212. package/public/oracle-splash/brand/lista.webp +0 -0
  213. package/public/oracle-splash/brand/loopedhype.webp +0 -0
  214. package/public/oracle-splash/brand/lorenzo.webp +0 -0
  215. package/public/oracle-splash/brand/magic-eden.webp +0 -0
  216. package/public/oracle-splash/brand/magiceden.webp +0 -0
  217. package/public/oracle-splash/brand/mempool.png +0 -0
  218. package/public/oracle-splash/brand/meteora.webp +0 -0
  219. package/public/oracle-splash/brand/morpho.webp +0 -0
  220. package/public/oracle-splash/brand/myriad.webp +0 -0
  221. package/public/oracle-splash/brand/noxa.webp +0 -0
  222. package/public/oracle-splash/brand/odos.webp +0 -0
  223. package/public/oracle-splash/brand/oneinch.webp +0 -0
  224. package/public/oracle-splash/brand/openbook.webp +0 -0
  225. package/public/oracle-splash/brand/opensea.webp +0 -0
  226. package/public/oracle-splash/brand/orca.webp +0 -0
  227. package/public/oracle-splash/brand/ordinals.png +0 -0
  228. package/public/oracle-splash/brand/ostium.webp +0 -0
  229. package/public/oracle-splash/brand/pancakeswap.webp +0 -0
  230. package/public/oracle-splash/brand/pendle.webp +0 -0
  231. package/public/oracle-splash/brand/perena.webp +0 -0
  232. package/public/oracle-splash/brand/pharaoh.webp +0 -0
  233. package/public/oracle-splash/brand/phoenix.webp +0 -0
  234. package/public/oracle-splash/brand/polymarket.webp +0 -0
  235. package/public/oracle-splash/brand/polynomial.webp +0 -0
  236. package/public/oracle-splash/brand/projectx.webp +0 -0
  237. package/public/oracle-splash/brand/pumpfun.webp +0 -0
  238. package/public/oracle-splash/brand/quickswap.webp +0 -0
  239. package/public/oracle-splash/brand/rain.webp +0 -0
  240. package/public/oracle-splash/brand/raydium.webp +0 -0
  241. package/public/oracle-splash/brand/relay.webp +0 -0
  242. package/public/oracle-splash/brand/rocketpool.webp +0 -0
  243. package/public/oracle-splash/brand/saber.webp +0 -0
  244. package/public/oracle-splash/brand/sakuraswap.webp +0 -0
  245. package/public/oracle-splash/brand/sanctum.webp +0 -0
  246. package/public/oracle-splash/brand/satflow.png +0 -0
  247. package/public/oracle-splash/brand/sierra.webp +0 -0
  248. package/public/oracle-splash/brand/sky.webp +0 -0
  249. package/public/oracle-splash/brand/solv.webp +0 -0
  250. package/public/oracle-splash/brand/spark.webp +0 -0
  251. package/public/oracle-splash/brand/sparksavings.webp +0 -0
  252. package/public/oracle-splash/brand/sphere.webp +0 -0
  253. package/public/oracle-splash/brand/ssv.webp +0 -0
  254. package/public/oracle-splash/brand/stabble.webp +0 -0
  255. package/public/oracle-splash/brand/stableswap.webp +0 -0
  256. package/public/oracle-splash/brand/stakewise.webp +0 -0
  257. package/public/oracle-splash/brand/stargate.webp +0 -0
  258. package/public/oracle-splash/brand/sthype.webp +0 -0
  259. package/public/oracle-splash/brand/sushiswap.webp +0 -0
  260. package/public/oracle-splash/brand/unisat.png +0 -0
  261. package/public/oracle-splash/brand/uniswap.webp +0 -0
  262. package/public/oracle-splash/brand/uniswapv2.webp +0 -0
  263. package/public/oracle-splash/brand/uniswapv4.webp +0 -0
  264. package/public/oracle-splash/brand/unit.webp +0 -0
  265. package/public/oracle-splash/brand/velodrome.webp +0 -0
  266. package/public/oracle-splash/brand/velora.webp +0 -0
  267. package/public/oracle-splash/brand/venus.webp +0 -0
  268. package/public/oracle-splash/brand/wbeth.webp +0 -0
  269. package/public/oracle-splash/brand/xsy.webp +0 -0
  270. package/public/oracle-splash/brand/yieldyak.webp +0 -0
  271. package/public/oracle-splash/brand/zerobase.webp +0 -0
  272. package/public/oracle-splash/brand/zerox.webp +0 -0
  273. package/public/oracle-splash/favicon.ico +0 -0
  274. package/public/oracle-splash/favicon.svg +0 -6
  275. package/public/oracle-splash/index.html +0 -1558
  276. package/public/oracle-splash/mesh-graph.png +0 -0
  277. package/public/oracle-splash/mesh-graph.svg +0 -216
  278. package/scripts/adversarial-bench.mjs +0 -114
  279. package/scripts/build-inscription.py +0 -230
  280. package/scripts/check-doc-drift.mjs +0 -123
  281. package/scripts/check-test-count.mjs +0 -105
  282. package/scripts/e2e-hl-markets.mjs +0 -21
  283. package/scripts/e2e-hl-perps.mjs +0 -48
  284. package/scripts/e2e-hypercore-staking.mjs +0 -128
  285. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  286. package/scripts/protocol-template-gate.mjs +0 -15
  287. package/scripts/public-api-scan.mjs +0 -23
  288. package/scripts/secret-scan.mjs +0 -181
  289. package/scripts/verify-v3-venues.mjs +0 -192
  290. package/skills/balance/SKILL.md +0 -176
  291. package/skills/oracle-action-semantics/SKILL.md +0 -40
  292. package/skills/oracle-best-execution/SKILL.md +0 -127
  293. package/skills/oracle-bitcoin/SKILL.md +0 -53
  294. package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
  295. package/skills/oracle-chat/SKILL.md +0 -61
  296. package/skills/oracle-chat/chain.SKILL.md +0 -31
  297. package/skills/oracle-chat/setup.SKILL.md +0 -37
  298. package/skills/oracle-circuit-breaker/SKILL.md +0 -51
  299. package/skills/oracle-contract-research/SKILL.md +0 -55
  300. package/skills/oracle-desk/SKILL.md +0 -58
  301. package/skills/oracle-dex-launch/SKILL.md +0 -38
  302. package/skills/oracle-grants/SKILL.md +0 -69
  303. package/skills/oracle-hypercore-staking/SKILL.md +0 -57
  304. package/skills/oracle-hyperliquid/SKILL.md +0 -56
  305. package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
  306. package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
  307. package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
  308. package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
  309. package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
  310. package/skills/oracle-polymarket/SKILL.md +0 -60
  311. package/skills/oracle-protocol-builder/SKILL.md +0 -59
  312. package/skills/oracle-protocol-security/SKILL.md +0 -60
  313. package/skills/oracle-public-product/SKILL.md +0 -44
  314. package/skills/oracle-receipts/SKILL.md +0 -52
  315. package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
  316. package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
  317. package/skills/oracle-solana/SKILL.md +0 -65
  318. package/skills/oracle-solana-nft/SKILL.md +0 -54
  319. package/skills/oracle-token-research/SKILL.md +0 -67
  320. package/skins/oracle.yaml +0 -56
  321. package/src/action-receipts.mjs +0 -265
  322. package/src/action-semantics.mjs +0 -62
  323. package/src/address-book.mjs +0 -208
  324. package/src/agent-auth.mjs +0 -206
  325. package/src/approval-guard.mjs +0 -282
  326. package/src/attestation-secret.mjs +0 -88
  327. package/src/audit-log.mjs +0 -196
  328. package/src/auth/oauth.mjs +0 -672
  329. package/src/auto-slippage.mjs +0 -378
  330. package/src/capability-posture.mjs +0 -125
  331. package/src/chains.mjs +0 -62
  332. package/src/cli/chain-catalog.mjs +0 -215
  333. package/src/cli/chain-state.mjs +0 -74
  334. package/src/cli/commands/auth.mjs +0 -193
  335. package/src/cli/commands/bootstrap.mjs +0 -87
  336. package/src/cli/commands/chain.mjs +0 -143
  337. package/src/cli/commands/chat.mjs +0 -434
  338. package/src/cli/commands/credential.mjs +0 -9
  339. package/src/cli/commands/data-mcp.mjs +0 -18
  340. package/src/cli/commands/data.mjs +0 -75
  341. package/src/cli/commands/doctor.mjs +0 -136
  342. package/src/cli/commands/help.mjs +0 -7
  343. package/src/cli/commands/init.mjs +0 -27
  344. package/src/cli/commands/mcp.mjs +0 -142
  345. package/src/cli/commands/model.mjs +0 -99
  346. package/src/cli/commands/prepare.mjs +0 -12
  347. package/src/cli/commands/public.mjs +0 -20
  348. package/src/cli/commands/route.mjs +0 -12
  349. package/src/cli/commands/runner.mjs +0 -9
  350. package/src/cli/commands/scan.mjs +0 -12
  351. package/src/cli/commands/setup.mjs +0 -275
  352. package/src/cli/commands/sign.mjs +0 -21
  353. package/src/cli/commands/signer.mjs +0 -9
  354. package/src/cli/commands/upgrade.mjs +0 -12
  355. package/src/cli/commands/vault.mjs +0 -9
  356. package/src/cli/commands/version.mjs +0 -22
  357. package/src/cli/first-run.mjs +0 -23
  358. package/src/cli/kernel.mjs +0 -239
  359. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  360. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  361. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  362. package/src/cli/mcp-targets/codex.mjs +0 -41
  363. package/src/cli/mcp-targets/shared.mjs +0 -61
  364. package/src/cli/messaging-platforms.mjs +0 -209
  365. package/src/cli/model-config.mjs +0 -70
  366. package/src/cli/operator-dispatch.mjs +0 -258
  367. package/src/cli/oracle-harness.py +0 -415
  368. package/src/cli/paths.mjs +0 -83
  369. package/src/cli/runtime.mjs +0 -351
  370. package/src/cli/setup-state.mjs +0 -168
  371. package/src/cli/spawn-child.mjs +0 -43
  372. package/src/data/catalog.mjs +0 -585
  373. package/src/data/desk-data.mjs +0 -695
  374. package/src/data/http.mjs +0 -253
  375. package/src/data/provider-endpoint.mjs +0 -94
  376. package/src/data/providers/aerodrome.mjs +0 -245
  377. package/src/data/providers/balancer.mjs +0 -209
  378. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  379. package/src/data/providers/bitcoin-meta.mjs +0 -378
  380. package/src/data/providers/blockscout.mjs +0 -14
  381. package/src/data/providers/bridges.mjs +0 -242
  382. package/src/data/providers/cowswap.mjs +0 -415
  383. package/src/data/providers/curve.mjs +0 -201
  384. package/src/data/providers/defillama.mjs +0 -88
  385. package/src/data/providers/dexscreener.mjs +0 -43
  386. package/src/data/providers/evm-rpc.mjs +0 -225
  387. package/src/data/providers/geckoterminal.mjs +0 -34
  388. package/src/data/providers/gmx.mjs +0 -496
  389. package/src/data/providers/hl-assets.mjs +0 -165
  390. package/src/data/providers/hl-info.mjs +0 -108
  391. package/src/data/providers/hl-markets.mjs +0 -210
  392. package/src/data/providers/hl-outcome.mjs +0 -61
  393. package/src/data/providers/hl-perps.mjs +0 -387
  394. package/src/data/providers/hl-staking.mjs +0 -353
  395. package/src/data/providers/hl-ws.mjs +0 -119
  396. package/src/data/providers/hyperevm-dex.mjs +0 -49
  397. package/src/data/providers/jupiter-venues.mjs +0 -119
  398. package/src/data/providers/jupiter.mjs +0 -315
  399. package/src/data/providers/lifi.mjs +0 -151
  400. package/src/data/providers/magiceden-sol.mjs +0 -406
  401. package/src/data/providers/morpho.mjs +0 -177
  402. package/src/data/providers/nft-gallery.mjs +0 -163
  403. package/src/data/providers/nft-portfolio.mjs +0 -494
  404. package/src/data/providers/odos.mjs +0 -156
  405. package/src/data/providers/oneinch.mjs +0 -174
  406. package/src/data/providers/opensea-multichain.mjs +0 -136
  407. package/src/data/providers/opensea-nft.mjs +0 -371
  408. package/src/data/providers/paraswap.mjs +0 -118
  409. package/src/data/providers/pendle.mjs +0 -188
  410. package/src/data/providers/poly-clob.mjs +0 -283
  411. package/src/data/providers/poly-public.mjs +0 -96
  412. package/src/data/providers/poly-ws.mjs +0 -103
  413. package/src/data/providers/portfolio-history.mjs +0 -394
  414. package/src/data/providers/portfolio.mjs +0 -594
  415. package/src/data/providers/rfq.mjs +0 -15
  416. package/src/data/providers/rh-agent.mjs +0 -59
  417. package/src/data/providers/satflow.mjs +0 -341
  418. package/src/data/providers/signed-material-guard.mjs +0 -108
  419. package/src/data/providers/solana-rpc.mjs +0 -197
  420. package/src/data/providers/uniswap-v3.mjs +0 -349
  421. package/src/data/providers/uniswap-v4.mjs +0 -414
  422. package/src/data/providers/zerox.mjs +0 -167
  423. package/src/data/public-api-scan.mjs +0 -61
  424. package/src/data/quote-placeholder.mjs +0 -31
  425. package/src/exact-integer.mjs +0 -72
  426. package/src/exec-policy.mjs +0 -455
  427. package/src/flags.mjs +0 -15
  428. package/src/fresh-window.mjs +0 -76
  429. package/src/gmx-attestation.mjs +0 -176
  430. package/src/index.mjs +0 -100
  431. package/src/nft-gas-war-guard.mjs +0 -139
  432. package/src/onboarding/agent-keys.mjs +0 -161
  433. package/src/onboarding/harness-configs.mjs +0 -102
  434. package/src/onboarding/index.mjs +0 -18
  435. package/src/onboarding/tiers.mjs +0 -139
  436. package/src/oracle-env.mjs +0 -47
  437. package/src/portfolio-risk.mjs +0 -170
  438. package/src/prepare-envelope.mjs +0 -204
  439. package/src/profile-upgrade.mjs +0 -277
  440. package/src/protocol-execution.mjs +0 -84
  441. package/src/protocol-templates/gate.mjs +0 -179
  442. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  443. package/src/public-api/buzz-integration.mjs +0 -256
  444. package/src/public-api/connect-agent.mjs +0 -416
  445. package/src/public-api/grants.mjs +0 -142
  446. package/src/public-api/http.mjs +0 -389
  447. package/src/public-control/aa-adapter.mjs +0 -402
  448. package/src/public-control/build-registry.mjs +0 -227
  449. package/src/public-control/bundler-client.mjs +0 -357
  450. package/src/public-control/grant-indexer.mjs +0 -296
  451. package/src/public-control/policy-render.mjs +0 -69
  452. package/src/public-control/policy-schema.mjs +0 -318
  453. package/src/public-control/runtime-config.mjs +0 -275
  454. package/src/public-control/session-key-model.mjs +0 -374
  455. package/src/public-control/session-orchestrator.mjs +0 -412
  456. package/src/rfq/intent.mjs +0 -180
  457. package/src/rfq/sources.mjs +0 -181
  458. package/src/route-attestation.mjs +0 -132
  459. package/src/router/best-execution.mjs +0 -326
  460. package/src/router/index.mjs +0 -226
  461. package/src/router/prepare-bridge.mjs +0 -289
  462. package/src/router/prepare-route.mjs +0 -398
  463. package/src/router/proposal.mjs +0 -311
  464. package/src/router/risk-classifier.mjs +0 -119
  465. package/src/router/route-sources.mjs +0 -364
  466. package/src/scanner/chains.config.mjs +0 -430
  467. package/src/scanner/contract.mjs +0 -270
  468. package/src/scanner/evm-scanner.mjs +0 -394
  469. package/src/scanner/index.mjs +0 -9
  470. package/src/scanner/v2-venue.mjs +0 -335
  471. package/src/scanner/v3-venue.mjs +0 -290
  472. package/src/scopes.mjs +0 -44
  473. package/src/sell-simulation.mjs +0 -167
  474. package/src/signals/engine.mjs +0 -146
  475. package/src/signals/index.mjs +0 -1
  476. package/src/token-transfer-guard.mjs +0 -188
  477. package/src/tui/app.mjs +0 -438
  478. package/src/tui/backend.mjs +0 -145
  479. package/src/tui/format.mjs +0 -272
  480. package/src/tui/gateway-client.mjs +0 -177
  481. package/src/tui/input.mjs +0 -501
  482. package/src/tui/renderer.mjs +0 -443
  483. package/src/tui/standalone-client.mjs +0 -666
  484. package/src/tui/theme.mjs +0 -81
  485. package/src/vault-attestation.mjs +0 -146
  486. package/src/venues.mjs +0 -206
  487. package/src/watch-preferences.mjs +0 -85
@@ -1,226 +0,0 @@
1
- // Public entry point: find the best swap or bridge route.
2
- //
3
- // Returns a ranked comparison, not just a winner. Showing the runners-up and the
4
- // spread is what lets a caller sanity-check the result instead of trusting it -- and
5
- // a one-source "best route" is not a comparison at all, so that case is labelled
6
- // rather than presented as if it beat something.
7
-
8
- import {
9
- gatherRoutes, rankRoutes, QUALITY, measurePriceImpact, applyImpactCeiling,
10
- } from "./best-execution.mjs";
11
- import { swapCandidates, bridgeCandidates, nativeUsd } from "./route-sources.mjs";
12
- import { llamaPrices } from "../data/providers/defillama.mjs";
13
-
14
- /** DefiLlama key for an ERC-20 on a given chain. */
15
- const LLAMA_CHAIN = {
16
- 1: "ethereum",
17
- 10: "optimism",
18
- 56: "bsc",
19
- 137: "polygon",
20
- 8453: "base",
21
- 42161: "arbitrum",
22
- 43114: "avax",
23
- };
24
-
25
- async function destPrice(chainId, token, opts) {
26
- const chain = LLAMA_CHAIN[Number(chainId)];
27
- if (!chain) return { priceUsd: null, decimals: null };
28
- const key = `${chain}:${token}`;
29
- try {
30
- const res = await llamaPrices([key], opts);
31
- const hit = res?.coins?.[key];
32
- const p = Number(hit?.price);
33
- const d = Number(hit?.decimals);
34
- return {
35
- priceUsd: Number.isFinite(p) ? p : null,
36
- decimals: Number.isFinite(d) ? d : null,
37
- };
38
- } catch {
39
- return { priceUsd: null, decimals: null };
40
- }
41
- }
42
-
43
- /**
44
- * Best same-chain swap route.
45
- *
46
- * @param {object} p
47
- * @param {number} p.chainId
48
- * @param {string} p.tokenIn
49
- * @param {string} p.tokenOut
50
- * @param {string|bigint} p.amountIn raw units of tokenIn
51
- * @param {string} [p.taker] address used for quoting only
52
- * @param {number} [p.decimalsIn] enables ParaSwap
53
- * @param {number} [p.decimalsOut] enables ParaSwap + net ranking
54
- */
55
- export async function bestSwapRoute(p, opts = {}) {
56
- const { chainId, tokenIn, tokenOut, amountIn } = p;
57
- if (chainId == null || !tokenIn || !tokenOut || amountIn == null) {
58
- throw new Error("bestSwapRoute requires chainId, tokenIn, tokenOut, amountIn");
59
- }
60
-
61
- // Prices and quotes run CONCURRENTLY, not one after the other.
62
- //
63
- // The obvious shape -- await the prices, then fan out the quotes -- adds the price
64
- // latency to every single comparison. Measured on Base: ~890ms of DefiLlama in
65
- // front of ~3.3s of quotes, for 4.7s total when the true floor is 3.3s.
66
- //
67
- // Neither price is needed to ASK for a quote:
68
- // * destPrice is only used at RANK time, after every quote has returned
69
- // * nativePriceUsd is only used by the 0x adapter to convert its native-wei gas
70
- // figure, so it is passed as a PROMISE and awaited inside that one adapter
71
- //
72
- // So the whole price fetch hides behind the slowest quote instead of preceding it.
73
- const nativePricePromise = nativeUsd(chainId, opts);
74
- const destPromise = destPrice(chainId, tokenOut, opts);
75
-
76
- const candidates = swapCandidates({
77
- ...p,
78
- nativePriceUsd: nativePricePromise,
79
- decimalsOut: p.decimalsOut,
80
- destDecimalsPromise: destPromise,
81
- opts,
82
- });
83
-
84
- const [routes, dest] = await Promise.all([
85
- gatherRoutes(candidates, { timeoutMs: opts.timeoutMs ?? 12_000 }),
86
- destPromise,
87
- ]);
88
-
89
- // Swallow an unused rejection so a failed price lookup cannot surface as an
90
- // unhandled rejection when no adapter happened to await it.
91
- nativePricePromise.catch(() => {});
92
-
93
- const ranked = rankRoutes(routes, {
94
- destPriceUsd: dest.priceUsd,
95
- destDecimals: p.decimalsOut ?? dest.decimals,
96
- });
97
-
98
- // Liquidity check. Ranking alone will happily crown a quote taken against a
99
- // drained pool, because a thin venue returns a well-formed number rather than
100
- // an error. Re-quote the winner at 1/1000th size and compare per-unit price:
101
- // real slippage decays smoothly, a dead pool falls off a cliff.
102
- //
103
- // Opt out with `maxImpactPct: null` for callers that genuinely want the raw
104
- // ranking (analytics, spread display) rather than an executable route.
105
- const maxImpactPct = opts.maxImpactPct === undefined ? 25 : opts.maxImpactPct;
106
- if (maxImpactPct != null && ranked.best) {
107
- const winner = ranked.best.source;
108
- const probe = async (amt) => {
109
- const sub = swapCandidates({
110
- ...p,
111
- amountIn: amt.toString(),
112
- nativePriceUsd: nativePricePromise,
113
- decimalsOut: p.decimalsOut,
114
- destDecimalsPromise: destPromise,
115
- opts,
116
- }).filter((c) => c.source === winner);
117
- if (!sub.length) return null;
118
- const got = await gatherRoutes(sub, { timeoutMs: opts.timeoutMs ?? 12_000 });
119
- return got?.[0]?.amountOut ?? null;
120
- };
121
-
122
- const impact = await measurePriceImpact(probe, amountIn);
123
- if (impact) {
124
- const guarded = applyImpactCeiling(ranked, { [winner]: impact }, { maxImpactPct });
125
- return {
126
- kind: "swap",
127
- chainId,
128
- tokenIn,
129
- tokenOut,
130
- amountIn: String(amountIn),
131
- ...guarded,
132
- priceImpact: { [winner]: Number(impact.impactPct.toFixed(2)) },
133
- };
134
- }
135
- }
136
-
137
- return {
138
- kind: "swap",
139
- chainId,
140
- tokenIn,
141
- tokenOut,
142
- amountIn: String(amountIn),
143
- ...ranked,
144
- sourcesTried: candidates.length,
145
- sourcesAnswered: routes.filter((r) => r.quality !== QUALITY.FAILED).length,
146
- note: describe(ranked, candidates.length),
147
- };
148
- }
149
-
150
- /**
151
- * Best cross-chain bridge route.
152
- *
153
- * Duration is reported, never folded into the score. A route that saves $2 and takes
154
- * 30 minutes is not strictly better than one costing $2 more that lands in 20
155
- * seconds -- that trade-off belongs to the caller, and burying it in a single number
156
- * would hide the only thing distinguishing two similar quotes.
157
- */
158
- export async function bestBridgeRoute(p, opts = {}) {
159
- const { fromChainId, toChainId, tokenIn, tokenOut, amountIn } = p;
160
- if (fromChainId == null || toChainId == null || !tokenIn || !tokenOut || amountIn == null) {
161
- throw new Error(
162
- "bestBridgeRoute requires fromChainId, toChainId, tokenIn, tokenOut, amountIn",
163
- );
164
- }
165
- if (Number(fromChainId) === Number(toChainId)) {
166
- throw new Error("bestBridgeRoute is for cross-chain; use bestSwapRoute for same-chain");
167
- }
168
-
169
- // Same concurrency rule as swaps: the destination price is only needed at RANK
170
- // time, so fetching it before the quotes would add its latency to every bridge
171
- // comparison for no reason.
172
- const destPromise = destPrice(toChainId, tokenOut, opts);
173
- const candidates = bridgeCandidates({ ...p, opts });
174
- const [routes, dest] = await Promise.all([
175
- gatherRoutes(candidates, { timeoutMs: opts.timeoutMs ?? 15_000 }),
176
- destPromise,
177
- ]);
178
- const ranked = rankRoutes(routes, {
179
- destPriceUsd: dest.priceUsd,
180
- destDecimals: p.decimalsOut ?? dest.decimals,
181
- });
182
-
183
- const durations = ranked.routes
184
- .map((r) => ({ source: r.source, seconds: r.meta?.durationSeconds ?? null }))
185
- .filter((d) => d.seconds != null);
186
-
187
- return {
188
- kind: "bridge",
189
- fromChainId,
190
- toChainId,
191
- tokenIn,
192
- tokenOut,
193
- amountIn: String(amountIn),
194
- ...ranked,
195
- durations,
196
- sourcesTried: candidates.length,
197
- sourcesAnswered: routes.filter((r) => r.quality !== QUALITY.FAILED).length,
198
- note: describe(ranked, candidates.length),
199
- };
200
- }
201
-
202
- function describe(ranked, tried) {
203
- if (!ranked.best) return "no source returned a usable route";
204
- const answered = ranked.routes.length;
205
- if (answered === 1) {
206
- return (
207
- `only 1 of ${tried} sources answered, so this is the ONLY route, not a proven ` +
208
- "best one. Treat it as unbenchmarked."
209
- );
210
- }
211
- if (ranked.improvementBps != null) {
212
- return (
213
- `best of ${answered} routes, ranked on ${ranked.rankedOn}: ` +
214
- `${(ranked.improvementBps / 100).toFixed(2)}% better than the runner-up ` +
215
- `(${ranked.spreadBasis})`
216
- );
217
- }
218
- // No spread claim when the top two are not measured the same way. Saying "X% better"
219
- // off a mismatched pair is worse than saying nothing.
220
- return (
221
- `best of ${answered} routes, ranked on ${ranked.rankedOn}. No spread quoted: the ` +
222
- "top routes report cost differently, so the margin is not comparable."
223
- );
224
- }
225
-
226
- export { QUALITY };
@@ -1,289 +0,0 @@
1
- // Prepare a cross-chain bridge route.
2
- //
3
- // Bridging differs from swapping in ways that matter for a signable artifact:
4
- //
5
- // 1. IT IS OFTEN MULTIPLE TRANSACTIONS. Relay can return an approval and a deposit
6
- // as separate items. A caller handed a bare "transaction" would sign the first
7
- // and believe they were done, leaving funds approved but not bridged. So the
8
- // artifact is always a LIST, and its length is stated.
9
- //
10
- // 2. THE DESTINATION CHAIN IS PART OF THE TRUST DECISION. Every transaction here
11
- // executes on the ORIGIN chain, but the value lands elsewhere. Signing an
12
- // origin-chain tx that credits the wrong destination is unrecoverable, so
13
- // toChainId is echoed alongside the destination address.
14
- //
15
- // 3. TIME IS A REAL COST. A bridge that saves $2 and takes 30 minutes is not
16
- // obviously better than one costing $2 more that lands in 20 seconds. Duration
17
- // is surfaced, never folded into a score.
18
- //
19
- // 4. FINALITY IS NOT ATOMIC. The origin transaction succeeding does NOT mean funds
20
- // arrived. That gap is where users panic, so it is stated explicitly rather than
21
- // left implied.
22
- //
23
- // Custody is unchanged: artifacts only. This module cannot sign or broadcast.
24
-
25
- import { bestBridgeRoute } from "./index.mjs";
26
- import { stampPrepared } from "../prepare-envelope.mjs";
27
-
28
- const ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
29
-
30
- /**
31
- * Placeholder addresses: fine for quoting, never for preparing.
32
- * Same reasoning as the swap path -- some venues catch this and some do not.
33
- */
34
- const NON_TAKER_ADDRESSES = new Set(
35
- [
36
- "0x0000000000000000000000000000000000000000",
37
- "0x000000000000000000000000000000000000dead",
38
- "0x0000000000000000000000000000000000000001",
39
- "0x00000000000000000000000000000000000a1ce5",
40
- ].map((a) => a.toLowerCase()),
41
- );
42
-
43
- const DEFAULT_DRIFT_TOLERANCE_BPS = 100;
44
-
45
- const PREPARERS = {
46
- relay: async ({ fromChainId, toChainId, tokenIn, tokenOut, amountIn, taker }, opts) => {
47
- const { relayPrepare } = await import("../data/providers/bridges.mjs");
48
- const p = await relayPrepare(
49
- {
50
- user: taker,
51
- originChainId: fromChainId,
52
- destinationChainId: toChainId,
53
- originCurrency: tokenIn,
54
- destinationCurrency: tokenOut,
55
- amount: String(amountIn),
56
- },
57
- opts,
58
- );
59
- return {
60
- transactions: p.transactions || [],
61
- amountOut: p.quote?.details?.currencyOut?.amount ?? null,
62
- minOut: p.quote?.details?.currencyOut?.minimumAmount ?? null,
63
- durationSeconds: p.quote?.details?.timeEstimate ?? null,
64
- };
65
- },
66
-
67
- lifi: async ({ fromChainId, toChainId, tokenIn, tokenOut, amountIn, taker }, opts) => {
68
- const { lifiPrepare } = await import("../data/providers/lifi.mjs");
69
- const p = await lifiPrepare(
70
- {
71
- fromChain: fromChainId,
72
- toChain: toChainId,
73
- fromToken: tokenIn,
74
- toToken: tokenOut,
75
- fromAmount: amountIn,
76
- fromAddress: taker,
77
- },
78
- opts,
79
- );
80
- // LI.FI returns a single transactionRequest. Normalized into a list so callers
81
- // handle one shape regardless of source -- a single-item list is honest, a bare
82
- // object next to Relay's list is a trap.
83
- return {
84
- transactions: p.transaction ? [p.transaction] : [],
85
- requiresApproval: p.requiresApproval ?? null,
86
- amountOut: p.quote?.estimate?.toAmount ?? null,
87
- minOut: p.quote?.estimate?.toAmountMin ?? null,
88
- durationSeconds: p.quote?.estimate?.executionDuration ?? null,
89
- };
90
- },
91
- };
92
-
93
- export function supportedBridgePreparers() {
94
- return Object.keys(PREPARERS);
95
- }
96
-
97
- /**
98
- * Compare bridge routes, then prepare the winner.
99
- *
100
- * @param {object} p same shape as bestBridgeRoute, plus:
101
- * @param {string} p.taker the real wallet that will sign
102
- * @param {string} [p.source] force a specific source
103
- * @param {number} [p.driftToleranceBps]
104
- */
105
- export async function prepareBestBridgeRoute(p, opts = {}) {
106
- const { taker, fromChainId, toChainId } = p;
107
-
108
- if (!taker) {
109
- throw new Error(
110
- "prepareBestBridgeRoute requires taker: bridge transactions are built FOR an " +
111
- "address, and the quote-only placeholder must never end up in one",
112
- );
113
- }
114
- if (!ADDRESS_RE.test(taker)) {
115
- throw new Error(`taker must be a valid 20-byte address, got "${taker}"`);
116
- }
117
- if (NON_TAKER_ADDRESSES.has(taker.toLowerCase())) {
118
- throw new Error(
119
- `taker "${taker}" is a placeholder/burn address. Bridging to it would send ` +
120
- "funds to an address nobody controls, on a chain where you cannot undo it.",
121
- );
122
- }
123
-
124
- const comparison = await bestBridgeRoute(p, opts);
125
- if (!comparison.best) {
126
- return { ok: false, reason: "no source returned a usable bridge route", comparison };
127
- }
128
-
129
- const chosenSource = p.source || comparison.best.source;
130
- const chosen = comparison.routes.find((r) => r.source === chosenSource);
131
- if (!chosen) {
132
- return { ok: false, reason: `source "${chosenSource}" returned no usable route`, comparison };
133
- }
134
-
135
- const prepare = PREPARERS[chosenSource];
136
- if (!prepare) {
137
- const alt = comparison.routes.find((r) => PREPARERS[r.source] && r.source !== chosenSource);
138
- return {
139
- ok: false,
140
- reason:
141
- `${chosenSource} won the comparison but has no bridge prepare path in this ` +
142
- `build. ` +
143
- (alt
144
- ? `Next preparable route is ${alt.source}; pass source:"${alt.source}".`
145
- : "No route in this comparison can be prepared."),
146
- // Machine-readable siblings of the message above. A caller should not have to
147
- // regex prose to find the fallback -- and the CLI/agent path reads these.
148
- failureKind: "no-prepare-path",
149
- ...(alt ? { alternative: alt.source } : {}),
150
- winner: chosenSource,
151
- comparison,
152
- };
153
- }
154
-
155
- let prepared;
156
- try {
157
- prepared = await prepare(p, opts);
158
- } catch (err) {
159
- const detail =
160
- typeof err?.body === "string" ? err.body : err?.body ? JSON.stringify(err.body) : "";
161
- const msg = [String(err?.message || err), detail].filter(Boolean).join(" :: ");
162
-
163
- const allowanceIssue = /allowance/i.test(msg);
164
- const balanceIssue = !allowanceIssue && /not enough|insufficient|balance/i.test(msg);
165
- const alt = comparison.routes.find((r) => PREPARERS[r.source] && r.source !== chosenSource);
166
-
167
- return {
168
- ok: false,
169
- reason: allowanceIssue
170
- ? `${chosenSource} will not build calldata until the token approval exists ` +
171
- `on-chain. Approve first, then prepare again. Underlying: ${msg}`
172
- : balanceIssue
173
- ? `${chosenSource} refused to build: ${msg}. Quoting works for any address; ` +
174
- `preparing needs the real funded wallet on chain ${fromChainId}.`
175
- : `${chosenSource} bridge prepare failed: ${msg}`,
176
- failureKind: allowanceIssue
177
- ? "approval-required-first"
178
- : balanceIssue
179
- ? "taker-not-funded"
180
- : "provider-error",
181
- ...(alt ? { alternative: alt.source } : {}),
182
- comparison,
183
- };
184
- }
185
-
186
- const txs = prepared.transactions || [];
187
- if (!txs.length) {
188
- return {
189
- ok: false,
190
- reason: `${chosenSource} returned no executable transaction for this route`,
191
- failureKind: "provider-error",
192
- comparison,
193
- };
194
- }
195
-
196
- // Every transaction must execute on the ORIGIN chain. A wrong chainId here means a
197
- // wallet could be prompted on the wrong network, and the user would be signing
198
- // something they cannot reason about.
199
- const wrongChain = txs.filter(
200
- (t) => t.chainId != null && Number(t.chainId) !== Number(fromChainId),
201
- );
202
- if (wrongChain.length) {
203
- return {
204
- ok: false,
205
- reason:
206
- `${chosenSource} returned a transaction for chain ${wrongChain[0].chainId} but ` +
207
- `the origin chain is ${fromChainId}. Refusing to hand over a mismatched ` +
208
- `artifact.`,
209
- failureKind: "chain-mismatch",
210
- comparison,
211
- };
212
- }
213
-
214
- // Drift against the comparison. Same reasoning as swaps: the comparison is stale.
215
- const tolerance = p.driftToleranceBps ?? DEFAULT_DRIFT_TOLERANCE_BPS;
216
- let driftBps = null;
217
- let driftWarning = null;
218
- if (prepared.amountOut != null && chosen.grossOut != null) {
219
- try {
220
- const then = BigInt(chosen.grossOut);
221
- const now = BigInt(prepared.amountOut);
222
- if (then > 0n) {
223
- driftBps = Number(((now - then) * 10_000n) / then);
224
- if (driftBps < -tolerance) {
225
- driftWarning =
226
- `route moved ${(driftBps / 100).toFixed(2)}% against you since the ` +
227
- `comparison (tolerance ${(tolerance / 100).toFixed(2)}%). Re-compare ` +
228
- `before signing.`;
229
- }
230
- }
231
- } catch {
232
- /* no fabricated drift */
233
- }
234
- }
235
-
236
- const warnings = [
237
- ...(driftWarning ? [driftWarning] : []),
238
- ...(comparison.warnings || []),
239
- // The single most common bridging surprise.
240
- `Bridging is NOT atomic: the origin transaction succeeding does not mean funds ` +
241
- `arrived on chain ${toChainId}. Expect ~${
242
- prepared.durationSeconds != null ? `${prepared.durationSeconds}s` : "minutes"
243
- } before the destination credits, and do not re-send if it is pending.`,
244
- ];
245
-
246
- if (txs.length > 1) {
247
- warnings.push(
248
- `This route needs ${txs.length} transactions signed IN ORDER. Signing only the ` +
249
- `first leaves funds approved but not bridged.`,
250
- );
251
- }
252
-
253
- return stampPrepared({
254
- ok: true,
255
- chosen: {
256
- source: chosenSource,
257
- wasWinner: chosenSource === comparison.best.source,
258
- netOut: chosen.netOut,
259
- grossOut: chosen.grossOut,
260
- gasUsd: chosen.gasUsd,
261
- },
262
- artifactKind: "unsigned-transaction-sequence",
263
- fromChainId: Number(fromChainId),
264
- toChainId: Number(toChainId),
265
- transactionCount: txs.length,
266
- transactions: txs,
267
- requiresApproval: prepared.requiresApproval ?? null,
268
- minOut: prepared.minOut ?? null,
269
- durationSeconds: prepared.durationSeconds ?? null,
270
- // Where value goes on the origin chain. The first destination is the bridge entry.
271
- destination: txs[0]?.to ?? null,
272
- unsigned: true,
273
- signedBy: "user-wallet",
274
- driftBps,
275
- warnings,
276
- runnersUp: comparison.routes
277
- .filter((r) => r.source !== chosenSource)
278
- .map((r) => ({ source: r.source, netOut: r.netOut, gasUsd: r.gasUsd })),
279
- comparison: {
280
- rankedOn: comparison.rankedOn,
281
- sourcesAnswered: comparison.sourcesAnswered,
282
- sourcesTried: comparison.sourcesTried,
283
- improvementBps: comparison.improvementBps,
284
- },
285
- note:
286
- `UNSIGNED. ${txs.length} transaction(s) on chain ${fromChainId}, crediting ` +
287
- `chain ${toChainId}. Verify every destination address before signing.`,
288
- }, { provider: "router", kind: "best-bridge" });
289
- }