@oracle-agent/oracle 0.11.0 → 0.12.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 (308) hide show
  1. package/LICENSE +115 -201
  2. package/README.md +66 -84
  3. package/SECURITY.md +37 -12
  4. package/SETUP.md +207 -272
  5. package/dist/action-receipts.mjs +1 -0
  6. package/dist/action-semantics.mjs +1 -0
  7. package/dist/address-book.mjs +2 -0
  8. package/dist/bin/desk-server.mjs +14 -0
  9. package/dist/bin/oracle-data-mcp.mjs +8 -0
  10. package/dist/bin/oracle-init.mjs +24 -0
  11. package/dist/bin/oracle-public-server.mjs +5 -0
  12. package/dist/bin/oracle-route.mjs +22 -0
  13. package/dist/bin/oracle-scan.mjs +18 -0
  14. package/dist/bin/oracle-upgrade.mjs +21 -0
  15. package/dist/bin/oracle.mjs +68 -0
  16. package/dist/chains.mjs +1 -0
  17. package/dist/cli/commands/auth.mjs +16 -0
  18. package/dist/cli/commands/bootstrap.mjs +18 -0
  19. package/dist/cli/commands/chain.mjs +21 -0
  20. package/dist/cli/commands/chat.mjs +35 -0
  21. package/dist/cli/commands/credential.mjs +1 -0
  22. package/dist/cli/commands/data-mcp.mjs +2 -0
  23. package/dist/cli/commands/data.mjs +12 -0
  24. package/dist/cli/commands/doctor.mjs +5 -0
  25. package/dist/cli/commands/gate.mjs +13 -0
  26. package/dist/cli/commands/help.mjs +1 -0
  27. package/dist/cli/commands/init.mjs +3 -0
  28. package/dist/cli/commands/mcp.mjs +33 -0
  29. package/dist/cli/commands/model.mjs +44 -0
  30. package/dist/cli/commands/prepare.mjs +2 -0
  31. package/dist/cli/commands/public.mjs +3 -0
  32. package/dist/cli/commands/route.mjs +2 -0
  33. package/dist/cli/commands/runner.mjs +1 -0
  34. package/dist/cli/commands/scan.mjs +2 -0
  35. package/dist/cli/commands/setup.mjs +34 -0
  36. package/dist/cli/commands/sign.mjs +4 -0
  37. package/dist/cli/commands/signer.mjs +1 -0
  38. package/dist/cli/commands/upgrade.mjs +2 -0
  39. package/dist/cli/commands/vault.mjs +1 -0
  40. package/dist/cli/commands/version.mjs +2 -0
  41. package/dist/data/desk-data.mjs +12 -0
  42. package/dist/index.mjs +17 -0
  43. package/dist/nft-gas-war-guard.mjs +1 -0
  44. package/dist/onboarding/harness-configs.mjs +4 -0
  45. package/dist/portfolio-risk.mjs +1 -0
  46. package/dist/prepare-envelope.mjs +1 -0
  47. package/dist/public-control/policy-schema.mjs +1 -0
  48. package/dist/router/index.mjs +2 -0
  49. package/dist/scanner/index.mjs +4 -0
  50. package/dist/signals/index.mjs +1 -0
  51. package/dist/watch-preferences.mjs +1 -0
  52. package/package.json +27 -65
  53. package/public/oracle-splash/index.html +11 -1
  54. package/CONTRIBUTING.md +0 -98
  55. package/bin/desk-server.mjs +0 -440
  56. package/bin/oracle-data-mcp.mjs +0 -1019
  57. package/bin/oracle-init.mjs +0 -496
  58. package/bin/oracle-public-server.mjs +0 -36
  59. package/bin/oracle-route.mjs +0 -254
  60. package/bin/oracle-scan.mjs +0 -192
  61. package/bin/oracle-upgrade.mjs +0 -42
  62. package/bin/oracle.mjs +0 -33
  63. package/docs/adding-a-chain.md +0 -229
  64. package/docs/architecture.md +0 -138
  65. package/docs/cli.md +0 -47
  66. package/docs/connectors.md +0 -13
  67. package/docs/oracle-pack-standard.md +0 -29
  68. package/docs/profiles.md +0 -151
  69. package/docs/public-surface.md +0 -133
  70. package/examples/add-a-chain.mjs +0 -65
  71. package/examples/oracle-pack-template.mjs +0 -38
  72. package/examples/research-a-token.mjs +0 -70
  73. package/plugins/oracle-owner-gate/__init__.py +0 -227
  74. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  75. package/profiles/_template/SOUL.md +0 -54
  76. package/profiles/_template/profile.json +0 -22
  77. package/profiles/bitcoin-agent/SOUL.md +0 -31
  78. package/profiles/bitcoin-agent/profile.json +0 -32
  79. package/profiles/hyperliquid-agent/SOUL.md +0 -34
  80. package/profiles/hyperliquid-agent/profile.json +0 -37
  81. package/profiles/oracle/SOUL.md +0 -107
  82. package/profiles/oracle/profile.json +0 -39
  83. package/profiles/polymarket-agent/SOUL.md +0 -35
  84. package/profiles/polymarket-agent/profile.json +0 -34
  85. package/profiles/profile.schema.json +0 -90
  86. package/profiles/protocol-builder/SOUL.md +0 -57
  87. package/profiles/protocol-builder/profile.json +0 -39
  88. package/profiles/robinhood-agent/SOUL.md +0 -53
  89. package/profiles/robinhood-agent/profile.json +0 -40
  90. package/profiles/solana-agent/SOUL.md +0 -37
  91. package/profiles/solana-agent/profile.json +0 -37
  92. package/profiles/stable-agent/SOUL.md +0 -43
  93. package/profiles/stable-agent/profile.json +0 -37
  94. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  95. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  96. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  97. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  98. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  99. package/scripts/adversarial-bench.mjs +0 -114
  100. package/scripts/build-inscription.py +0 -230
  101. package/scripts/check-doc-drift.mjs +0 -123
  102. package/scripts/check-test-count.mjs +0 -105
  103. package/scripts/e2e-hl-markets.mjs +0 -21
  104. package/scripts/e2e-hl-perps.mjs +0 -48
  105. package/scripts/e2e-hypercore-staking.mjs +0 -128
  106. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  107. package/scripts/protocol-template-gate.mjs +0 -15
  108. package/scripts/public-api-scan.mjs +0 -23
  109. package/scripts/secret-scan.mjs +0 -181
  110. package/scripts/verify-v3-venues.mjs +0 -192
  111. package/skills/balance/SKILL.md +0 -176
  112. package/skills/oracle-action-semantics/SKILL.md +0 -40
  113. package/skills/oracle-best-execution/SKILL.md +0 -127
  114. package/skills/oracle-bitcoin/SKILL.md +0 -53
  115. package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
  116. package/skills/oracle-chat/SKILL.md +0 -61
  117. package/skills/oracle-chat/chain.SKILL.md +0 -31
  118. package/skills/oracle-chat/setup.SKILL.md +0 -37
  119. package/skills/oracle-circuit-breaker/SKILL.md +0 -51
  120. package/skills/oracle-contract-research/SKILL.md +0 -55
  121. package/skills/oracle-desk/SKILL.md +0 -58
  122. package/skills/oracle-dex-launch/SKILL.md +0 -38
  123. package/skills/oracle-grants/SKILL.md +0 -69
  124. package/skills/oracle-hypercore-staking/SKILL.md +0 -57
  125. package/skills/oracle-hyperliquid/SKILL.md +0 -56
  126. package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
  127. package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
  128. package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
  129. package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
  130. package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
  131. package/skills/oracle-polymarket/SKILL.md +0 -60
  132. package/skills/oracle-protocol-builder/SKILL.md +0 -59
  133. package/skills/oracle-protocol-security/SKILL.md +0 -60
  134. package/skills/oracle-public-product/SKILL.md +0 -44
  135. package/skills/oracle-receipts/SKILL.md +0 -52
  136. package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
  137. package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
  138. package/skills/oracle-solana/SKILL.md +0 -65
  139. package/skills/oracle-solana-nft/SKILL.md +0 -54
  140. package/skills/oracle-token-research/SKILL.md +0 -67
  141. package/skins/oracle.yaml +0 -56
  142. package/src/action-receipts.mjs +0 -265
  143. package/src/action-semantics.mjs +0 -62
  144. package/src/address-book.mjs +0 -208
  145. package/src/agent-auth.mjs +0 -206
  146. package/src/approval-guard.mjs +0 -282
  147. package/src/attestation-secret.mjs +0 -88
  148. package/src/audit-log.mjs +0 -196
  149. package/src/auth/oauth.mjs +0 -672
  150. package/src/auto-slippage.mjs +0 -378
  151. package/src/capability-posture.mjs +0 -125
  152. package/src/chains.mjs +0 -62
  153. package/src/cli/chain-catalog.mjs +0 -215
  154. package/src/cli/chain-state.mjs +0 -74
  155. package/src/cli/commands/auth.mjs +0 -193
  156. package/src/cli/commands/bootstrap.mjs +0 -87
  157. package/src/cli/commands/chain.mjs +0 -143
  158. package/src/cli/commands/chat.mjs +0 -434
  159. package/src/cli/commands/credential.mjs +0 -9
  160. package/src/cli/commands/data-mcp.mjs +0 -18
  161. package/src/cli/commands/data.mjs +0 -75
  162. package/src/cli/commands/doctor.mjs +0 -136
  163. package/src/cli/commands/help.mjs +0 -7
  164. package/src/cli/commands/init.mjs +0 -27
  165. package/src/cli/commands/mcp.mjs +0 -142
  166. package/src/cli/commands/model.mjs +0 -99
  167. package/src/cli/commands/prepare.mjs +0 -12
  168. package/src/cli/commands/public.mjs +0 -20
  169. package/src/cli/commands/route.mjs +0 -12
  170. package/src/cli/commands/runner.mjs +0 -9
  171. package/src/cli/commands/scan.mjs +0 -12
  172. package/src/cli/commands/setup.mjs +0 -275
  173. package/src/cli/commands/sign.mjs +0 -21
  174. package/src/cli/commands/signer.mjs +0 -9
  175. package/src/cli/commands/upgrade.mjs +0 -12
  176. package/src/cli/commands/vault.mjs +0 -9
  177. package/src/cli/commands/version.mjs +0 -22
  178. package/src/cli/first-run.mjs +0 -23
  179. package/src/cli/kernel.mjs +0 -239
  180. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  181. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  182. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  183. package/src/cli/mcp-targets/codex.mjs +0 -41
  184. package/src/cli/mcp-targets/shared.mjs +0 -61
  185. package/src/cli/messaging-platforms.mjs +0 -209
  186. package/src/cli/model-config.mjs +0 -70
  187. package/src/cli/operator-dispatch.mjs +0 -258
  188. package/src/cli/oracle-harness.py +0 -415
  189. package/src/cli/paths.mjs +0 -83
  190. package/src/cli/runtime.mjs +0 -351
  191. package/src/cli/setup-state.mjs +0 -168
  192. package/src/cli/spawn-child.mjs +0 -43
  193. package/src/data/catalog.mjs +0 -585
  194. package/src/data/desk-data.mjs +0 -695
  195. package/src/data/http.mjs +0 -253
  196. package/src/data/provider-endpoint.mjs +0 -94
  197. package/src/data/providers/aerodrome.mjs +0 -245
  198. package/src/data/providers/balancer.mjs +0 -209
  199. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  200. package/src/data/providers/bitcoin-meta.mjs +0 -378
  201. package/src/data/providers/blockscout.mjs +0 -14
  202. package/src/data/providers/bridges.mjs +0 -242
  203. package/src/data/providers/cowswap.mjs +0 -415
  204. package/src/data/providers/curve.mjs +0 -201
  205. package/src/data/providers/defillama.mjs +0 -88
  206. package/src/data/providers/dexscreener.mjs +0 -43
  207. package/src/data/providers/evm-rpc.mjs +0 -225
  208. package/src/data/providers/geckoterminal.mjs +0 -34
  209. package/src/data/providers/gmx.mjs +0 -496
  210. package/src/data/providers/hl-assets.mjs +0 -165
  211. package/src/data/providers/hl-info.mjs +0 -108
  212. package/src/data/providers/hl-markets.mjs +0 -210
  213. package/src/data/providers/hl-outcome.mjs +0 -61
  214. package/src/data/providers/hl-perps.mjs +0 -387
  215. package/src/data/providers/hl-staking.mjs +0 -353
  216. package/src/data/providers/hl-ws.mjs +0 -119
  217. package/src/data/providers/hyperevm-dex.mjs +0 -49
  218. package/src/data/providers/jupiter-venues.mjs +0 -119
  219. package/src/data/providers/jupiter.mjs +0 -315
  220. package/src/data/providers/lifi.mjs +0 -151
  221. package/src/data/providers/magiceden-sol.mjs +0 -406
  222. package/src/data/providers/morpho.mjs +0 -177
  223. package/src/data/providers/nft-gallery.mjs +0 -163
  224. package/src/data/providers/nft-portfolio.mjs +0 -494
  225. package/src/data/providers/odos.mjs +0 -156
  226. package/src/data/providers/oneinch.mjs +0 -174
  227. package/src/data/providers/opensea-multichain.mjs +0 -136
  228. package/src/data/providers/opensea-nft.mjs +0 -371
  229. package/src/data/providers/paraswap.mjs +0 -118
  230. package/src/data/providers/pendle.mjs +0 -188
  231. package/src/data/providers/poly-clob.mjs +0 -283
  232. package/src/data/providers/poly-public.mjs +0 -96
  233. package/src/data/providers/poly-ws.mjs +0 -103
  234. package/src/data/providers/portfolio-history.mjs +0 -394
  235. package/src/data/providers/portfolio.mjs +0 -594
  236. package/src/data/providers/rfq.mjs +0 -15
  237. package/src/data/providers/rh-agent.mjs +0 -59
  238. package/src/data/providers/satflow.mjs +0 -341
  239. package/src/data/providers/signed-material-guard.mjs +0 -108
  240. package/src/data/providers/solana-rpc.mjs +0 -197
  241. package/src/data/providers/uniswap-v3.mjs +0 -349
  242. package/src/data/providers/uniswap-v4.mjs +0 -414
  243. package/src/data/providers/zerox.mjs +0 -167
  244. package/src/data/public-api-scan.mjs +0 -61
  245. package/src/data/quote-placeholder.mjs +0 -31
  246. package/src/exact-integer.mjs +0 -72
  247. package/src/exec-policy.mjs +0 -455
  248. package/src/flags.mjs +0 -15
  249. package/src/fresh-window.mjs +0 -76
  250. package/src/gmx-attestation.mjs +0 -176
  251. package/src/index.mjs +0 -100
  252. package/src/nft-gas-war-guard.mjs +0 -139
  253. package/src/onboarding/agent-keys.mjs +0 -161
  254. package/src/onboarding/harness-configs.mjs +0 -102
  255. package/src/onboarding/index.mjs +0 -18
  256. package/src/onboarding/tiers.mjs +0 -139
  257. package/src/oracle-env.mjs +0 -47
  258. package/src/portfolio-risk.mjs +0 -170
  259. package/src/prepare-envelope.mjs +0 -204
  260. package/src/profile-upgrade.mjs +0 -277
  261. package/src/protocol-execution.mjs +0 -84
  262. package/src/protocol-templates/gate.mjs +0 -179
  263. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  264. package/src/public-api/buzz-integration.mjs +0 -256
  265. package/src/public-api/connect-agent.mjs +0 -416
  266. package/src/public-api/grants.mjs +0 -142
  267. package/src/public-api/http.mjs +0 -389
  268. package/src/public-control/aa-adapter.mjs +0 -402
  269. package/src/public-control/build-registry.mjs +0 -227
  270. package/src/public-control/bundler-client.mjs +0 -357
  271. package/src/public-control/grant-indexer.mjs +0 -296
  272. package/src/public-control/policy-render.mjs +0 -69
  273. package/src/public-control/policy-schema.mjs +0 -318
  274. package/src/public-control/runtime-config.mjs +0 -275
  275. package/src/public-control/session-key-model.mjs +0 -374
  276. package/src/public-control/session-orchestrator.mjs +0 -412
  277. package/src/rfq/intent.mjs +0 -180
  278. package/src/rfq/sources.mjs +0 -181
  279. package/src/route-attestation.mjs +0 -132
  280. package/src/router/best-execution.mjs +0 -326
  281. package/src/router/index.mjs +0 -226
  282. package/src/router/prepare-bridge.mjs +0 -289
  283. package/src/router/prepare-route.mjs +0 -398
  284. package/src/router/proposal.mjs +0 -311
  285. package/src/router/risk-classifier.mjs +0 -119
  286. package/src/router/route-sources.mjs +0 -364
  287. package/src/scanner/chains.config.mjs +0 -430
  288. package/src/scanner/contract.mjs +0 -270
  289. package/src/scanner/evm-scanner.mjs +0 -394
  290. package/src/scanner/index.mjs +0 -9
  291. package/src/scanner/v2-venue.mjs +0 -335
  292. package/src/scanner/v3-venue.mjs +0 -290
  293. package/src/scopes.mjs +0 -44
  294. package/src/sell-simulation.mjs +0 -167
  295. package/src/signals/engine.mjs +0 -146
  296. package/src/signals/index.mjs +0 -1
  297. package/src/token-transfer-guard.mjs +0 -188
  298. package/src/tui/app.mjs +0 -438
  299. package/src/tui/backend.mjs +0 -145
  300. package/src/tui/format.mjs +0 -272
  301. package/src/tui/gateway-client.mjs +0 -177
  302. package/src/tui/input.mjs +0 -501
  303. package/src/tui/renderer.mjs +0 -443
  304. package/src/tui/standalone-client.mjs +0 -666
  305. package/src/tui/theme.mjs +0 -81
  306. package/src/vault-attestation.mjs +0 -146
  307. package/src/venues.mjs +0 -206
  308. package/src/watch-preferences.mjs +0 -85
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import{createServer as Io}from"node:http";import{readFileSync as gn,existsSync as ko}from"node:fs";import{dirname as No,join as Ge,normalize as Co,sep as Po}from"node:path";import{fileURLToPath as To}from"node:url";import{createHash as _n}from"node:crypto";var te=1,Xe=Object.freeze(["chainId","agentAddress","accountAddress","actions","targets","maxValueWei","maxGasWei","maxSlippageBps","expiresAt","nonce","revocationKey"]),In=Object.freeze(["read","simulate"]),Qe=1e4,Ze=1440*60,et=128,tt=256,nt=64,rt=256,ot=/^0x[0-9a-fA-F]{40}$/,kn=/^[a-z][a-z0-9_-]*:[a-z0-9._-]+$/,Nn=/^[a-z][a-z0-9_-]*:\*$/,Cn=/^[A-Za-z0-9._:-]+$/,Pn=/^[A-Za-z0-9._:-]+$/,st=/^(0|[1-9][0-9]*)$/,M=class extends Error{constructor(t){let r=t.map(n=>`${n.field}: ${n.message}`);super(`invalid grant (${t.length} error${t.length===1?"":"s"}): ${r.join("; ")}`),this.name="GrantValidationError",this.errors=t}};function at(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Tn(e){if(typeof e=="bigint")return e>=0n?e.toString(10):null;if(typeof e=="number")return!Number.isSafeInteger(e)||e<0?null:String(e);if(typeof e=="string"){let t=e.trim();return st.test(t)?t:null}return null}function F(e){if(typeof e=="bigint")return e<0n||e>BigInt(Number.MAX_SAFE_INTEGER)?null:Number(e);if(typeof e=="number")return!Number.isSafeInteger(e)||e<0?null:e;if(typeof e=="string"){let t=e.trim();if(!st.test(t))return null;let r=Number(t);return Number.isSafeInteger(r)?r:null}return null}function Se(e){let t=String(e).split(":")[0];return In.includes(t)}function ve(e,t={}){let r=[],n=(u,m)=>r.push({field:u,message:m});if(!at(e))return n("grant","grant must be a plain object"),{ok:!1,errors:r,grant:null};for(let u of Object.keys(e))Xe.includes(u)||n(u,"unknown field is not allowed");for(let u of Xe)(!(u in e)||e[u]==null)&&n(u,"required field is missing");if(r.length)return{ok:!1,errors:r,grant:null};let o={},s=F(e.chainId);s==null||s<=0?n("chainId","must be a positive integer chain id"):o.chainId=s;for(let u of["agentAddress","accountAddress"]){let m=e[u];typeof m!="string"||!ot.test(m.trim())?n(u,"must be a 0x-prefixed 20-byte hex address"):o[u]=m.trim().toLowerCase()}if(!Array.isArray(e.actions)||e.actions.length===0)n("actions","must be a non-empty array of action scopes");else if(e.actions.length>nt)n("actions",`too many actions (max ${nt})`);else{let u=[];for(let m of e.actions){let l=typeof m=="string"?m.trim():null;if(!l){n("actions","action entries must be non-empty strings");continue}if(l.includes("*")){t.allowWildcardActions===!0&&Nn.test(l)?u.push(l):n("actions",`broad wildcard action "${l}" is rejected (fail closed)`);continue}if(!kn.test(l)){n("actions",`malformed action "${l}" (expected verb:resource)`);continue}u.push(l)}o.actions=[...new Set(u)].sort()}if(!Array.isArray(e.targets))n("targets","must be an array of contract addresses");else if(e.targets.length>rt)n("targets",`too many targets (max ${rt})`);else{let u=[];for(let m of e.targets){let l=typeof m=="string"?m.trim():null;if(!l||!ot.test(l)){n("targets",`target "${m}" must be a 0x-prefixed 20-byte hex address (wildcards not allowed)`);continue}u.push(l.toLowerCase())}if(o.targets=[...new Set(u)].sort(),o.targets.length===0&&Array.isArray(o.actions)){let m=o.actions.filter(l=>!Se(l));(m.length>0||o.actions.length===0)&&n("targets",`empty targets are only allowed for read/simulate scopes (blocked by: ${m.join(", ")||"no valid actions"})`)}}for(let u of["maxValueWei","maxGasWei"]){let m=Tn(e[u]);m==null?n(u,"must be a non-negative integer wei amount"):o[u]=m}let a=F(e.maxSlippageBps);a==null||a>Qe?n("maxSlippageBps",`must be an integer between 0 and ${Qe}`):o.maxSlippageBps=a;let i=864e10,c=F(e.expiresAt);if(c==null||c<=0)n("expiresAt","must be a positive unix-seconds timestamp");else if(c>i)n("expiresAt","exceeds the max unix-seconds timestamp (pass seconds, not milliseconds)");else if(o.expiresAt=c,t.now!=null){let u=F(t.now);u==null?n("expiresAt","opts.now must be a unix-seconds integer"):c<=u?n("expiresAt",`grant is expired (expiresAt ${c} <= now ${u})`):c-u>Ze&&n("expiresAt",`grant exceeds the hard 24-hour TTL (${Ze} seconds)`)}let d=typeof e.nonce=="string"?e.nonce.trim():F(e.nonce)!=null?String(F(e.nonce)):null;!d||d.length>et||!Cn.test(d)?n("nonce",`must be a non-empty string (max ${et} chars, [A-Za-z0-9._:-])`):o.nonce=d;let h=typeof e.revocationKey=="string"?e.revocationKey.trim():null;return!h||h.length>tt||!Pn.test(h)?n("revocationKey",`must be a non-empty public identifier (max ${tt} chars, [A-Za-z0-9._:-])`):o.revocationKey=h,r.length?{ok:!1,errors:r,grant:null}:{ok:!0,errors:[],grant:o}}function ae(e,t={}){let{ok:r,errors:n,grant:o}=ve(e,t);if(!r)throw new M(n);return o}function Ae(e,t={}){let r=ae(e,t),o=Object.keys(r).sort().map(s=>`${JSON.stringify(s)}:${JSON.stringify(r[s])}`);return`{"version":${te},${o.join(",")}}`}function ie(e,t={}){return _n("sha256").update(Ae(e,t),"utf8").digest("hex")}function it(e,t){let r=F(t),n=F(at(e)?e.expiresAt:null);return r==null||n==null?!0:n<=r}var ct="oracle-connect-request",Rn="oracle-unsigned-grant",$n="oracle-grant-canonical-json-utf8-v1",O=class extends Error{constructor(t,r){super(`secret material must never appear in a public API object (at ${t}, rule: ${r})`),this.name="SecretLeakError",this.path=t,this.rule=r}},On=/(private[_-]?key|secret|bearer|keystore|mnemonic|seed[_-]?phrase|passphrase|password|api[_-]?key|access[_-]?token|auth[_-]?token|session[_-]?token|signer[_-]?url|signature)/i,Ln=Object.freeze(["privkey","wif","xprv","seed"]);function xe(e){let t=String(e),r=t.toLowerCase().replace(/[\s._-]+/g,"");return On.test(t)||Ln.includes(r)}var lt=Object.freeze([{rule:"raw-32-byte-hex-key",re:/^0x[0-9a-fA-F]{64}$/},{rule:"raw-32-byte-hex-bare",re:/^[0-9a-fA-F]{64}$/},{rule:"extended-private-key",re:/\b(?:xprv|tprv|yprv|zprv)[1-9A-HJ-NP-Za-km-z]{107}\b/},{rule:"bitcoin-wif",re:/\b[59KLc][1-9A-HJ-NP-Za-km-z]{50,51}\b/},{rule:"bip39-mnemonic",re:/\b(?:[a-z]{3,8}\s+){11,23}[a-z]{3,8}\b/},{rule:"bearer-token",re:/bearer\s+[A-Za-z0-9._~+/=-]+/i},{rule:"pem-private-key",re:/-----BEGIN[A-Z ]*PRIVATE KEY-----/},{rule:"keystore-path",re:/keystore/i},{rule:"signer-url",re:/https?:\/\/\S*sign/i},{rule:"authorization-header",re:/authorization\s*:/i}]),ut=Object.freeze(["grantid","id","hash","sha256","sha256hex","checksum","txhash","transactionhash","blockhash","digest","userophash","commithash","prevhash","intenthash","canonicalhash","payloadhash","requestid"]);function Un(e){return e.replace(/"([A-Za-z0-9_-]+)"\s*:\s*"(?:0x)?([0-9a-fA-F]{64})"/g,(t,r)=>ut.includes(String(r).toLowerCase().replace(/[_-]/g,""))?`"${r}":"<hex64>"`:t)}function dt(e){let t;try{t=JSON.stringify(e)}catch(o){throw new O("$",`unserializable-payload: ${String(o?.message||o)}`)}if(t===void 0)return"null";let r=Un(t);for(let{rule:o,re:s}of lt)if(s.test(r))throw new O("$<serialized>",o);if(/(?:^|[^0-9a-fA-Fx])0x[0-9a-fA-F]{64}(?![0-9a-fA-F])/.test(r))throw new O("$<serialized>","raw-32-byte-hex-embedded");return JSON.parse(t,(o,s)=>{if(o&&xe(o))throw new O(`$<serialized>.${o}`,"forbidden-key-name");return s}),t}function R(e,t="$",r=new Set,n=""){if(e==null)return e;if(typeof e=="string"){let o=ut.includes(String(n).toLowerCase().replace(/[_-]/g,""));for(let{rule:s,re:a}of lt)if(!(o&&s.startsWith("raw-32-byte-hex"))&&a.test(e))throw new O(t,s);return e}if(typeof e!="object"||r.has(e)||(r.add(e),ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e;if(e instanceof Map){for(let[o,s]of e.entries()){if(typeof o=="string"&&xe(o))throw new O(`${t}[${JSON.stringify(o)}]`,"forbidden-key-name");R(o,`${t}[key]`,r),R(s,`${t}[${String(o)}]`,r)}return e}if(e instanceof Set){let o=0;for(let s of e.values())R(s,`${t}[${o++}]`,r);return e}if(Array.isArray(e))return e.forEach((o,s)=>R(o,`${t}[${s}]`,r)),e;for(let[o,s]of Object.entries(e)){if(xe(o))throw new O(`${t}.${o}`,"forbidden-key-name");R(s,`${t}.${o}`,r,o)}return e}function ne(e){if(e&&typeof e=="object"&&!Object.isFrozen(e)){Object.freeze(e);for(let t of Object.values(e))ne(t)}return e}function pt(e,t){let r=Number(typeof e=="string"?e.trim():e);if(!Number.isSafeInteger(r)||r<=0)throw new M([{field:t,message:"must be a positive unix-seconds integer"}]);return r}function ft(e){if(e?.now==null)throw new M([{field:"opts.now",message:"explicit reference time is required for live grant construction"}]);return pt(e.now,"opts.now")}function Mn(e){return new Date(e*1e3).toISOString()}function Bn(e,t){let r=e.actions.every(n=>Se(n));return["ORACLE \u2014 CONNECT AGENT (unsigned grant, you sign it, we never do)","=================================================================",`Grant ID: ${t}`,`Version: ${te}`,`Chain: ${e.chainId}`,`Agent: ${e.agentAddress}`,`Your account: ${e.accountAddress}`,`Actions: ${e.actions.join(", ")}`,`Targets: ${e.targets.length?e.targets.join(", "):"(none \u2014 read/simulate only)"}`,`Max value: ${e.maxValueWei} wei`,`Max gas: ${e.maxGasWei} wei`,`Max slippage: ${e.maxSlippageBps} bps`,`Expires: ${Mn(e.expiresAt)} (unix ${e.expiresAt})`,`Nonce: ${e.nonce}`,`Revocation: ${e.revocationKey}`,"-----------------------------------------------------------------",r?"Scope: read/simulate only \u2014 this grant cannot move funds.":"Scope: includes state-changing actions bounded by the caps above.","Self-custodial: this payload is UNSIGNED and contains public data only.","Sign the bytes below with YOUR wallet; Oracle never holds your keys."].join(`
3
+ `)}function mt(e={},t={}){if(e==null||typeof e!="object"||Array.isArray(e))throw new M([{field:"request",message:"request must be a plain object"}]);let r=ft(t),{ttlSeconds:n,...o}=e,s={...o};if(n!=null){if(s.expiresAt!=null)throw new M([{field:"ttlSeconds",message:"pass either ttlSeconds or expiresAt, not both"}]);let c=pt(n,"ttlSeconds");s.expiresAt=r+c}let a=ae(s,{now:r,allowWildcardActions:t.allowWildcardActions===!0}),i=ne({kind:ct,version:te,grant:a});return R(i)}function ht(e={},t={}){let r=ft(t),n=e&&e.kind===ct?e.grant:e,o=ae(n,{now:r,allowWildcardActions:t.allowWildcardActions===!0}),s=Ae(o),a=ie(o),i=Buffer.from(s,"utf8"),c=ne({kind:Rn,unsigned:!0,payload:ne({version:te,grantId:a,grant:o,canonical:s}),signing:ne({scheme:$n,message:s,bytesHex:`0x${i.toString("hex")}`,byteLength:i.length,sha256:a}),render:Bn(o,a)});return R(c)}var G=Object.freeze({ACTIVE:"active",EXPIRED:"expired",REVOKED:"revoked",INVALID:"invalid"});function bt(e){if(e==null)return[];if(Array.isArray(e))return e;if(e instanceof Map)return[...e.values()];if(typeof e[Symbol.iterator]=="function")return[...e];throw new TypeError("grant store must be an array, Map, or iterable of grant records")}function qn(e){return e&&typeof e=="object"&&!Array.isArray(e)&&e.grant!=null?{grant:e.grant,revoked:e.revoked===!0||e.revokedAt!=null}:{grant:e,revoked:!1}}function Ee(e){let t=Number(typeof e=="string"?e.trim():e);if(!Number.isSafeInteger(t)||t<0)throw new TypeError("an explicit unix-seconds `now` is required (deterministic liveness, no wall-clock fallback)");return t}function Dn(e,t,r){if(e==null)return!1;if(typeof e=="function")return e(t,r)===!0;let n=[t,r.revocationKey];return e instanceof Set?n.some(o=>e.has(o)):Array.isArray(e)?n.some(o=>e.includes(o)):typeof e.has=="function"?n.some(o=>e.has(o)):!1}function yt(e,{now:t,revoked:r}={}){let n=Ee(t),{grant:o,revoked:s}=qn(e),{ok:a,grant:i}=ve(o);if(!a)return{status:G.INVALID,id:null,grant:null};let c=ie(i);return s||Dn(r,c,i)?{status:G.REVOKED,id:c,grant:i}:it(i,n)?{status:G.EXPIRED,id:c,grant:i}:{status:G.ACTIVE,id:c,grant:i}}function gt(e,{now:t,revoked:r,agentAddress:n,accountAddress:o,chainId:s}={}){let a=Ee(t),i=n!=null?String(n).trim().toLowerCase():null,c=o!=null?String(o).trim().toLowerCase():null,d=s!=null?Number(s):null,h=[];for(let u of bt(e)){let{status:m,id:l,grant:w}=yt(u,{now:a,revoked:r});m===G.ACTIVE&&(i!=null&&w.agentAddress!==i||c!=null&&w.accountAddress!==c||d!=null&&w.chainId!==d||h.push(Object.freeze({id:l,grant:w})))}return h.sort((u,m)=>u.id<m.id?-1:u.id>m.id?1:0),R(Object.freeze(h))}function wt(e,t,{now:r,revoked:n}={}){let o=Ee(r),s=String(t??"").trim().toLowerCase();if(!/^[0-9a-f]{64}$/.test(s))return null;for(let a of bt(e)){let i=yt(a,{now:o,revoked:n});if(i.status!==G.INVALID&&i.id===s)return R(Object.freeze({id:i.id,status:i.status,grant:i.grant}))}return null}import{Interface as Ot,getAddress as ar,id as Lt}from"ethers";import{createHash as Fn}from"node:crypto";var Hn=new Set([408,425,429,500,502,503,504]),St=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Vn=2,vt=4e3,xt=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],zn=new Set([301,302,303,307,308]),At=3;function jn(e){let t=String(e||"").toLowerCase();return xt.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function Kn(e){let t={};for(let[r,n]of Object.entries(e||{}))jn(r)||(t[r]=n);return t}function Gn(e,t){if(!e)throw new Error(`HTTP redirect from ${t} missing Location`);let r=new URL(String(e),String(t));if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`HTTP redirect from ${t} used unsupported protocol ${r.protocol}`);return r.toString()}function Wn(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}var _e=new Map;function Yn(e,t,r){let n={};for(let[c,d]of Object.entries(r||{}))n[c.toLowerCase()]=d;let o=Object.keys(n).filter(c=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(c)),a=[...new Set([...xt,...o])].sort().map(c=>`${c}=${n[c]??""}`).join(`
4
+ `),i=Fn("sha256").update(a).digest("hex").slice(0,32);return`${e} ${t} ${i}`}function Jn(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,vt):Math.min(250*2**e,vt)+Math.floor(Math.random()*100)}var Xn=e=>new Promise(t=>setTimeout(t,e));async function Qn(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:s}){let a=new AbortController,i=setTimeout(()=>a.abort(),s);try{let c=String(e),d={...n||{}};for(let h=0;h<=At;h+=1){let u=await t(c,{method:r,headers:d,body:o,signal:a.signal,redirect:"manual"}),m=await u.text(),l=null;if(m)try{l=JSON.parse(m)}catch{l=null}if(zn.has(u.status)){if(r!=="GET"&&r!=="HEAD"){let A=new Error(`HTTP ${u.status} ${r} ${c} redirected non-idempotent request`);throw A.status=u.status,A.body=l??m.slice(0,300),A}if(h===At)throw new Error(`HTTP redirect loop for ${e}`);let w=Gn(u.headers?.get?.("location"),c);Wn(w,c)||(d=Kn(d)),c=w;continue}if(!u.ok){let w=new Error(`HTTP ${u.status} ${r} ${c}`);throw w.status=u.status,w.retryAfter=u.headers?.get?.("retry-after")??null,w.body=l??m.slice(0,300),w}return l??m}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(i)}}async function N(e,t={}){let r=t.fetchImpl||globalThis.fetch;if(typeof r!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let n=t.timeoutMs??12e3,o=(t.method||"GET").toUpperCase(),s={Accept:"application/json",...t.headers||{}},a=t.body;a!=null&&typeof a!="string"&&(s["Content-Type"]=s["Content-Type"]||"application/json",a=JSON.stringify(a));let i=Number.isInteger(t.retries)?Math.max(t.retries,0):Vn,c=async()=>{let l;for(let w=0;w<=i;w++)try{return await Qn(e,{fetchImpl:r,method:o,headers:s,body:a,timeoutMs:n})}catch(A){l=A;let v=A?.status,_=A?.name==="AbortError",k=new Set([408,425,429]),q=v!=null?k.has(v)||Hn.has(v)&&St.has(o):!_&&St.has(o);if(w===i||!q)throw A;await Xn(Jn(w,A?.retryAfter))}throw l};if(!(t.dedupe!==!1&&o==="GET"&&a==null))return c();let h=Yn(o,e,s),u=_e.get(h);if(u)return u;let m=c().finally(()=>_e.delete(h));return _e.set(h,m),m}async function I(e){let t=Date.now();try{let r=await e();return{ok:!0,ms:Date.now()-t,data:r}}catch(r){return{ok:!1,ms:Date.now()-t,error:String(r.message||r),status:r.status??null}}}async function H(e,t,r){let n=Array.from(e),o=Math.max(1,Math.min(Number(t)||1,n.length||1)),s=new Array(n.length),a=0;return await Promise.all(Array.from({length:o},async()=>{for(;a<n.length;){let i=a++;s[i]=await r(n[i],i)}})),s}var Et={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},Zn=new Map(Object.values(Et).map(e=>[e.chainId,e]));function _t(e){return Zn.get(Number(e))||null}function It(e,t=process.env){let r=_t(e);if(!r)return null;for(let n of r.rpcEnv){let o=(t[n]||"").trim();if(o)return o}return null}import{Interface as er,getAddress as tr}from"ethers";var kt=new er(["function allowance(address owner,address spender) view returns (uint256)","function balanceOf(address account) view returns (uint256)"]);function Ie(e,t){try{return tr(e).toLowerCase()}catch{throw new Error(`${t} must be a valid EVM address`)}}var nr={1:"https://ethereum.publicnode.com",137:"https://polygon-bor-rpc.publicnode.com",42161:"https://arbitrum-one-rpc.publicnode.com",8453:"https://base-rpc.publicnode.com",10:"https://optimism-rpc.publicnode.com",988:"https://rpc.stable.xyz",56:"https://bsc-rpc.publicnode.com",43114:"https://avalanche-c-chain-rpc.publicnode.com",999:"https://rpc.hyperliquid.xyz/evm",2741:"https://api.mainnet.abs.xyz",4663:"https://rpc.mainnet.chain.robinhood.com"};function rr(e,{rpcUrl:t,env:r=process.env}={}){if(t)return t;let n=It(e,r);return n||nr[Number(e)]||null}var or=/^(?:eth_(?:call|blocknumber|chainid|get[a-z0-9]+|feehistory|gasprice|maxpriorityfeepergas|syncing|protocolversion|estimategas|createaccesslist)|net_(?:version|listening|peercount)|web3_(?:clientversion|sha3))$/;function sr(e){let t=String(e||""),r=t.toLowerCase();if(t!==t.trim()||!/^[a-zA-Z0-9_]+$/.test(t)||!or.test(r))throw new Error(`evm-rpc: ${t} refused \u2014 @oracle-agent/oracle is prepare-only (read RPC only; no broadcast/sign)`);return r}async function B(e,t,r=[],n={}){let o=String(t||"");sr(o);let s=rr(e,n);if(!s)throw new Error(`No RPC URL for chainId ${e} (set env from chain registry rpcEnv or pass rpcUrl)`);let i=await N(s,{method:"POST",body:{jsonrpc:"2.0",id:1,method:t,params:r},fetchImpl:n.fetchImpl,timeoutMs:n.timeoutMs??12e3});if(i?.error){let c=new Error(i.error.message||JSON.stringify(i.error));throw c.code=i.error.code,c}return i.result}async function ke(e,t={}){let r=await B(e,"eth_blockNumber",[],t);return parseInt(r,16)}async function Ne(e,t,r={}){if(!t)throw new Error("rpcGetBalance requires address");let n=await B(e,"eth_getBalance",[t,"latest"],r);return{chainId:Number(e),address:t,balanceWei:BigInt(n).toString(),balanceHex:n}}async function Nt(e={},t={}){let r=Number(e.chainId??t.chainId??1),n=Ie(e.token||e.tokenAddress,"token"),o=Ie(e.owner,"owner"),s=Ie(e.spender,"spender"),a=kt.encodeFunctionData("allowance",[o,s]),i=await B(r,"eth_call",[{to:n,data:a},e.blockTag||"latest"],t),c=kt.decodeFunctionResult("allowance",i),d=BigInt(c[0]);return{chainId:r,token:n,owner:o,spender:s,allowance:d.toString(),allowanceHex:`0x${d.toString(16)}`,blockTag:e.blockTag||"latest"}}var xs=Object.freeze(["blockNumber","nativeBalance","tokenBalance","resolveToken","resolvePools","scanBlocks","scoreRisk","quote","sellSimulation","prepareUnsignedTx"]),Ce=Object.freeze({LIVE:"LIVE",CACHED:"CACHED",STALE:"STALE",UNKNOWN:"UNKNOWN",UNAVAILABLE:"UNAVAILABLE"}),Pe=Object.freeze({PASS:"PASS",CAUTION:"CAUTION",FAIL:"FAIL",UNKNOWN:"UNKNOWN"});var ce=Object.freeze([{key:"ethereum",chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://etherscan.io",dexscreenerSlug:"ethereum",venueKind:"uniswap-v3",wrappedNative:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDC fee 500 quoted 1908.71 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:1}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:1}}]},{key:"optimism",chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://optimistic.etherscan.io",dexscreenerSlug:"optimism",venueKind:"uniswap-v3",wrappedNative:"0x4200000000000000000000000000000000000006",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDC fee 500 quoted 1905.23 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:10}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:10}}]},{key:"bsc",chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],nativeCurrency:{symbol:"BNB",decimals:18},explorer:"https://bscscan.com",dexscreenerSlug:"bsc",venueKind:"uniswap-v3",wrappedNative:"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",venues:[{kind:"quoter",address:"0x78D78E420Da98ad378D7799bE8f4AF69033EB077",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WBNB->USDC fee 500 quoted 413.86 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:56}},{kind:"router",address:"0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:56}}]},{key:"polygon",chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],nativeCurrency:{symbol:"POL",decimals:18},explorer:"https://polygonscan.com",dexscreenerSlug:"polygon",venueKind:"uniswap-v3",wrappedNative:"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WMATIC->USDC fee 500 quoted 0.0720 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:137}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:137}}]},{key:"stable",chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],nativeCurrency:{symbol:"USDT0",decimals:18},venues:[]},{key:"hyperevm",chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],nativeCurrency:{symbol:"HYPE",decimals:18},dexscreenerSlug:"hyperevm",venues:[]},{key:"abstract",chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},venues:[]},{key:"robinhood",chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC","ROBINHOOD_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},dexscreenerSlug:"robinhood",venueKind:"uniswap-v3",wrappedNative:"0x0bd7d308f8e1639fab988df18a8011f41eacad73",venues:[{kind:"quoter",address:"0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDG fee 100 quoted 1866.58 USDG, and USDG->CASHCAT fee 10000 quoted a live amount). A contract that correctly prices known pairs IS a working V3 quoter",source:"live eth_call against rpc.mainnet.chain.robinhood.com",date:"2026-07-31",chainId:4663}},{kind:"router",address:"0xcaf681a66d020601342297493863e78c959e5cb2",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode (24497 bytes) on this chain and the paired quoter at the same deployment passed a live functional quote",source:"live eth_getCode against rpc.mainnet.chain.robinhood.com",date:"2026-07-31",chainId:4663}},{kind:"factory",address:"0x1f7d7550b1b028f7571e69a784071f0205fd2efa",label:"Uniswap V3 Factory",verified:{method:"eth_getCode returned real bytecode (24535 bytes) and a PoolCreated log scan over this factory returned 76 pools in ~9000 recent blocks",source:"live eth_getLogs against rpc.mainnet.chain.robinhood.com",date:"2026-07-31",chainId:4663}}]},{key:"base",chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://basescan.org",dexscreenerSlug:"base",venueKind:"uniswap-v3",wrappedNative:"0x4200000000000000000000000000000000000006",venues:[{kind:"quoter",address:"0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",label:"Uniswap V3 QuoterV2 (Base)",verified:{method:"functional probe: quoteExactInputSingle returned WETH->USDC at fee 500 = 1908.44 USDC, a live sane price. The canonical mainnet quoter address also has bytecode on Base but does NOT price this pair, which is exactly the false positive a codesize-only check accepts",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:8453}},{kind:"router",address:"0x2626664c2603336E57B271c5C0b26F421741e481",label:"Uniswap V3 SwapRouter02 (Base)",verified:{method:"eth_getCode returned real bytecode and the paired Base quoter passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:8453}},{kind:"router-v2",address:"0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",label:"Uniswap V2 Router02 (Base)",verified:{method:"eth_getCode returned 17891 bytes; live getAmountsOut on WETH->USDC round-tripped to 98.75% (2x0.30% fee + impact)",source:"https://docs.uniswap.org/contracts/v2/reference/smart-contracts/v2-deployments",date:"2026-07-30",chainId:8453}}]},{key:"arbitrum",chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://arbiscan.io",dexscreenerSlug:"arbitrum",venueKind:"uniswap-v3",wrappedNative:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDC fee 500 quoted 1908.72 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:42161}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:42161}}]},{key:"avalanche",chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],nativeCurrency:{symbol:"AVAX",decimals:18},explorer:"https://snowtrace.io",dexscreenerSlug:"avalanche",venueKind:"uniswap-v3",wrappedNative:"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",venues:[{kind:"quoter",address:"0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WAVAX->USDC fee 500 quoted 6.48 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:43114}},{kind:"router",address:"0xbb00FF08d01D300023C629E8fFfFcb65A5a578cE",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:43114}}]}]);var Ct=new Ot(["function decimals() view returns (uint8)","function symbol() view returns (string)"]),Pt=new Ot(["function isApprovedForAll(address owner, address operator) view returns (bool)","function name() view returns (string)"]),ir=Lt("Approval(address,address,uint256)"),Js=Lt("ApprovalForAll(address,address,bool)"),cr=1e4,lr=2e5,ur=Object.freeze({"0x1111111254eeb25477b68fb85ed929f73a960582":"1inch v5 Router","0x111111125421ca6dc452d289314280a0f8842a65":"1inch v6 Router","0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45":"Uniswap Universal Router","0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad":"Uniswap Universal Router","0x000000000022d473030f116ddee9f6b43ac78ba3":"Permit2","0xe592427a0aece92de3edee1f18e0157c05861564":"Uniswap v3 Router","0x7a250d5630b4cf539739df2c5dacb4c659f2488d":"Uniswap v2 Router","0xdef1c0ded9bec7f1a1670819833240f027b25eff":"0x Exchange Proxy","0x2626664c2603336e57b271c5c0b26f421741e481":"Uniswap SwapRouter02 (Base)","0x6131b5fae19ea4f9d964eac0408e4408b66337b5":"KyberSwap Meta Aggregator","0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48":"USDC (token contract)"}),dr=Object.freeze([{address:"0x000000000022d473030f116ddee9f6b43ac78ba3",label:"Permit2"},{address:"0x1111111254eeb25477b68fb85ed929f73a960582",label:"1inch v5 Router"},{address:"0x111111125421ca6dc452d289314280a0f8842a65",label:"1inch v6 Router"},{address:"0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45",label:"Uniswap Universal Router"},{address:"0xe592427a0aece92de3edee1f18e0157c05861564",label:"Uniswap v3 Router"},{address:"0x7a250d5630b4cf539739df2c5dacb4c659f2488d",label:"Uniswap v2 Router"},{address:"0xdef1c0ded9bec7f1a1670819833240f027b25eff",label:"0x Exchange Proxy"},{address:"0x2626664c2603336e57b271c5c0b26f421741e481",label:"Uniswap SwapRouter02"}]),pr=Object.freeze([{address:"0x1e0049783f008a0085193e00003d00cd54003c71",label:"OpenSea Seaport Conduit"},{address:"0x00000000000000adc04c56bf30ac9d3c0aaf14dc",label:"Seaport 1.5"},{address:"0x0000000000000068f116a894984e2db1123eb395",label:"Seaport 1.6"},{address:"0x00000000000001ad428e4906ae43d8f9852d0dd6",label:"Seaport 1.4"},{address:"0x000000000000ad05ccc4f10045630fb830b95127",label:"Blur Marketplace"},{address:"0x00000000000000000000000000000000000000a5",label:"Blur Execution Delegate"},{address:"0xf42aa99f011a1fa7cda90e5e98b277e306bca83e",label:"Rarible Transfer Proxy"},{address:"0x000000000022d473030f116ddee9f6b43ac78ba3",label:"Permit2"}]),fr=Object.freeze({1:[{address:"0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",name:"Bored Ape Yacht Club"},{address:"0x60e4d786628fea6478f785a6d7e704777c86a7c6",name:"Mutant Ape Yacht Club"},{address:"0xed5af388653567af2f388e6224dc7c4b3241c544",name:"Azuki"},{address:"0x8a90cab2b38dba80c64b7734e58ee1db38b8992e",name:"Doodles"},{address:"0x49cf6f5d44e70224e2e23fdcdd2c053f30ada28b",name:"CloneX"},{address:"0x23581767a106ae21c074b2276d25e5c3e136a68b",name:"Moonbirds"}]}),mr=Object.freeze({1:[{address:"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",symbol:"USDC",decimals:6},{address:"0xdac17f958d2ee523a2206206994597c13d831ec7",symbol:"USDT",decimals:6},{address:"0x6b175474e89094c44da98b954eedeac495271d0f",symbol:"DAI",decimals:18},{address:"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",symbol:"WETH",decimals:18},{address:"0x2260fac5e5542a773aa44fbcfedf7c193bc2c599",symbol:"WBTC",decimals:8}],8453:[{address:"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",symbol:"USDC",decimals:6},{address:"0x4200000000000000000000000000000000000006",symbol:"WETH",decimals:18}],42161:[{address:"0xaf88d065e77c8cc2239327c5edb3a432268e5831",symbol:"USDC",decimals:6},{address:"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9",symbol:"USDT",decimals:6},{address:"0x82af49447d8a07e3bd95bd0d56f35241523fbab1",symbol:"WETH",decimals:18}],10:[{address:"0x0b2c639c533813f4aa9d7837caf62653d097ff85",symbol:"USDC",decimals:6},{address:"0x4200000000000000000000000000000000000006",symbol:"WETH",decimals:18}],137:[{address:"0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",symbol:"USDC",decimals:6},{address:"0xc2132d05d31c914a87c6611c10748aeb04b58e8f",symbol:"USDT",decimals:6}]}),hr=(1n<<256n)-1n,br=hr/2n,yr=4320*60*60*1e3,gr=360*60*1e3,wr=600*1e3,Sr=45*1e3,vr=512,Ar=128,Tt=new Map,Te=new Map,Rt=new Map;function W(e){return e?.cache===!1?!1:!e?.fetchImpl||e.cache===!0}function $e(e,t,r){let n=e.get(t);return n?Date.now()-n.at>r?(e.delete(t),null):n:null}function le(e,t,r,n){for(e.delete(t),e.set(t,{at:Date.now(),value:r});e.size>n;){let o=e.keys().next();if(o.done)break;e.delete(o.value)}}function xr(e,t){try{return ar(e).toLowerCase()}catch{throw new Error(`${t} must be a valid EVM address`)}}function Er(e){return`0x${e.slice(2).toLowerCase().padStart(64,"0")}`}function $t(e){return`0x${String(e).slice(-40).toLowerCase()}`}function _r({unlimited:e,spenderLabel:t,lastActivityAt:r}){if(e)return"unlimited";if(!t)return"unknown-spender";if(r){let n=Date.parse(r);if(Number.isFinite(n)&&Date.now()-n>yr)return"stale"}return"scoped"}function Ir(e,t,r){if(r)return"UNLIMITED";if(t==null)return e.toString();let n=10n**BigInt(t),o=e/n,s=e%n;if(s===0n)return o.toLocaleString("en-US");let a=s.toString().padStart(t,"0").replace(/0+$/,"").slice(0,6);return`${o.toLocaleString("en-US")}${a?`.${a}`:""}`}async function kr(e,t,r,n){let o=`${e}:${t}`,s=n?.get(o);if(s)return s;if(W(r)){let i=$e(Tt,o,gr);if(i)return i.value}let a=(async()=>{let i=async u=>{try{let m=Ct.encodeFunctionData(u,[]),l=await B(e,"eth_call",[{to:t,data:m},"latest"],r);return!l||l==="0x"?null:Ct.decodeFunctionResult(u,l)[0]}catch{return null}},[c,d]=await Promise.all([i("decimals"),i("symbol")]),h={decimals:c==null?null:Number(c),symbol:d==null?null:String(d).slice(0,24)};return W(r)&&le(Tt,o,h,vr),h})();return n?.set(o,a),a}async function Nr(e,t,r){let n=Math.min(Math.max(Number(r.lookbackBlocks)||cr,1),lr),o=await ke(e,r);if(!Number.isFinite(o))throw new Error("chain head unavailable");let s=Math.max(0,o-n),a=await B(e,"eth_getLogs",[{fromBlock:`0x${s.toString(16)}`,toBlock:"latest",topics:[ir,Er(t)]}],r);if(!Array.isArray(a))throw new Error("log scan returned no array");let i=new Map;for(let c of a){let d=String(c?.address||"").toLowerCase(),h=c?.topics?.[2];!d||!h||i.set(`${d}:${$t(h)}`,{token:d,spender:$t(h)})}return{pairs:[...i.values()],fromBlock:s,toBlock:o}}function Cr(e){return(mr[e]||[]).flatMap(r=>dr.map(n=>({token:r.address,spender:n.address,symbol:r.symbol,decimals:r.decimals})))}async function Pr(e,t,r={}){let n=[],o="direct-probe",s=null,a=Cr(e),i=Re(e),c=W(r)&&$e(Te,e,wr)?.value===!1;if(a.length===0&&i.length===0&&c)return{scan:{chainId:e,status:"unconfigured",method:o,error:"no Approval log access and no candidate token or collection set for this chain"},approvals:[]};try{let d=await Nr(e,t,r);n=d.pairs,o="log-scan",s={fromBlock:d.fromBlock,toBlock:d.toBlock},W(r)&&le(Te,e,!0,64)}catch{if(W(r)&&le(Te,e,!1,64),n=a,n.length===0&&i.length===0)return{scan:{chainId:e,status:"unconfigured",method:o,error:"no Approval log access and no candidate token or collection set for this chain"},approvals:[]}}try{let d=new Map,u=(await H(n,r.concurrency||4,async l=>{try{let w=await Nt({chainId:e,token:l.token,owner:t,spender:l.spender},r),A=BigInt(w.allowance);if(A<=0n)return null;let v=l.symbol?{symbol:l.symbol,decimals:l.decimals??null}:await kr(e,l.token,r,d),_=A>=br,k=ur[l.spender]||null;return{id:`${e}:${l.token}:${l.spender}`,chainId:e,standard:"erc20",token:l.token,tokenSymbol:v.symbol,decimals:v.decimals,spender:l.spender,spenderLabel:k,allowance:A.toString(),allowanceDisplay:Ir(A,v.decimals,_),unlimited:_,lastActivityAt:null,risk:_r({unlimited:_,spenderLabel:k,lastActivityAt:null})}}catch{return null}})).filter(Boolean),m=await Rr(e,t,r);return{scan:{chainId:e,status:"ok",method:o,pairsProbed:n.length,collectionsProbed:Re(e).length,...s||{}},approvals:[...u,...m]}}catch(d){return{scan:{chainId:e,status:"unavailable",method:o,error:String(d?.message||d).slice(0,200)},approvals:[]}}}async function Tr(e,t,r,n,o){try{let s=Pt.encodeFunctionData("isApprovedForAll",[r,n]),a=await B(e,"eth_call",[{to:t,data:s},"latest"],o);return!a||a==="0x"?null:!!Pt.decodeFunctionResult("isApprovedForAll",a)[0]}catch{return null}}function Re(e){return(fr[e]||[]).flatMap(r=>pr.map(n=>({collection:r.address,collectionName:r.name,operator:n.address,operatorLabel:n.label})))}async function Rr(e,t,r){let n=Re(e);return n.length===0?[]:(await H(n,r.concurrency||4,async s=>await Tr(e,s.collection,t,s.operator,r)!==!0?null:{id:`${e}:${s.collection}:${s.operator}:all`,chainId:e,standard:"erc721",token:s.collection,tokenSymbol:s.collectionName,decimals:null,spender:s.operator,spenderLabel:s.operatorLabel,allowance:null,allowanceDisplay:"ALL ITEMS",unlimited:!0,lastActivityAt:null,risk:"operator-all"})).filter(Boolean)}async function Ut(e={},t={}){let r=xr(e.owner||e.address,"owner"),n=new Map(ce.map(l=>[l.chainId,l])),o=Array.isArray(e.chainIds)&&e.chainIds.length?[...new Set(e.chainIds.map(Number))].filter(l=>n.has(l)):[...n.keys()],s=`${r}:${[...o].sort((l,w)=>l-w).join(",")}:${e.lookbackBlocks??""}`,a=W(t)&&!e.refresh;if(a){let l=$e(Rt,s,Sr);if(l)return{...l.value,cached:!0,cachedAgeMs:Date.now()-l.at}}let i=await H(o,e.concurrency||3,l=>Pr(l,r,{...t,lookbackBlocks:e.lookbackBlocks})),c=i.flatMap(l=>l.approvals),d=i.map(l=>l.scan),h=d.find(l=>l.method==="log-scan"&&l.toBlock),u=d.some(l=>l.method==="direct-probe"&&l.status==="ok"),m={provider:"approvals",operation:"scan",readOnly:!0,queriedAt:new Date().toISOString(),owner:r,scannedRange:h?`last ${h.toBlock-h.fromBlock} blocks`:u?"known routers, live allowance probe":null,approvals:c,scans:d,warnings:["Approval discovery is scoped. Log scanning is used where the endpoint permits it; otherwise a curated router set is probed directly. An empty result means nothing was found in that scope, not that the wallet is safe.","NFT operator approval (setApprovalForAll) is checked against a curated collection and marketplace set on supported chains only. A collection outside that set is not checked."]};return a&&le(Rt,s,m,Ar),{...m,cached:!1,cachedAgeMs:0}}import{getAddress as Qr}from"ethers";var Mt="mainnet-beta",$r="https://api.mainnet-beta.solana.com",Oe="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";function Or(e={}){return String(e.rpcUrl||process.env.SOLANA_RPC_URL||$r).trim()}function z(e,t="address"){let r=String(e||"").trim();if(!/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(r))throw new Error(`solana-rpc: ${t} must be a base58 public key`);return r}function Lr(e,t){return t?[...e,{commitment:t}]:e}async function Bt(e,t=[],r={}){let n=String(e||"");if(n==="sendTransaction"||n==="sendRawTransaction"||n==="requestAirdrop"||n==="requestAirDrop"||/airdrop/i.test(n)||/^send/i.test(n))throw new Error(`solana-rpc: ${n} refused \u2014 @oracle-agent/oracle is prepare-only (no broadcast/airdrop)`);let o=await N(Or(r),{method:"POST",body:{jsonrpc:"2.0",id:r.id||1,method:e,params:t},fetchImpl:r.fetchImpl,timeoutMs:r.timeoutMs??12e3});if(o?.error)throw new Error(`solana-rpc ${e}: ${o.error.message||JSON.stringify(o.error)}`);return o?.result}async function qt(e={},t={}){let r=z(e.address||e.owner,"address"),n=await Bt("getBalance",Lr([r],e.commitment),t);return{provider:"solana-rpc",cluster:Mt,address:r,lamports:String(n?.value??0),slot:n?.context?.slot??null,raw:n}}function Ur(e={}){let t=e.account?.data?.parsed?.info||{},r=t.tokenAmount||{};return{pubkey:e.pubkey,mint:t.mint||null,owner:t.owner||null,amount:String(r.amount??"0"),decimals:r.decimals??null,uiAmount:r.uiAmount??null,uiAmountString:r.uiAmountString??null,raw:e}}async function Le(e={},t={}){let r=z(e.owner||e.address,"owner"),n=e.mint?{mint:z(e.mint,"mint")}:{programId:z(e.programId||Oe,"token program")},o={encoding:"jsonParsed"};e.commitment&&(o.commitment=e.commitment);let s=await Bt("getTokenAccountsByOwner",[r,n,o],t),a=Array.isArray(s?.value)?s.value.map(Ur):[];return{provider:"solana-rpc",cluster:Mt,owner:r,filter:n,slot:s?.context?.slot??null,accounts:a,raw:s}}var Mr="mainnet",Br="https://mempool.space/api",qr="https://mempool.space/testnet/api";function Dt(e={}){return String(e.network||process.env.BTC_NETWORK||Mr).trim().toLowerCase()==="testnet"?"testnet":"mainnet"}function Dr(e={}){return e.baseUrl?String(e.baseUrl).replace(/\/$/,""):process.env.BTC_ESPLORA_URL?String(process.env.BTC_ESPLORA_URL).replace(/\/$/,""):Dt(e)==="testnet"?qr:Br}function V(e,t="address"){let r=String(e||"").trim();if(!/^(bc1|tb1|bcrt1)[a-z0-9]{20,90}$/i.test(r)&&!/^[13mn2][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(r))throw new Error(`bitcoin-esplora: ${t} must look like a Bitcoin address`);return r}async function Fr(e,t={}){let r=`${Dr(t)}${e.startsWith("/")?e:`/${e}`}`,o=await(t.fetchImpl||fetch)(r,{method:"GET",headers:{accept:"application/json,text/plain;q=0.9,*/*;q=0.8"},signal:AbortSignal.timeout(t.timeoutMs??12e3)}),s=await o.text();if(!o.ok)throw new Error(`bitcoin-esplora GET ${e}: HTTP ${o.status} ${s.slice(0,160)}`);return s}async function Hr(e,t={}){let r=await Fr(e,t);try{return JSON.parse(r)}catch{return r}}async function Ft(e={},t={}){let r=V(e.address||e.addr,"address"),n=await Hr(`/address/${r}`,t),o=n.chain_stats||{},s=n.mempool_stats||{},a=Number(o.funded_txo_sum||0)+Number(s.funded_txo_sum||0),i=Number(o.spent_txo_sum||0)+Number(s.spent_txo_sum||0);return{provider:"bitcoin-esplora",network:Dt(t),address:r,balanceSats:String(a-i),chainStats:o,mempoolStats:s,raw:n}}var Ht="ORACLE_ALLOW_CUSTOM_PROVIDER_URL";function Y({provider:e,defaultUrl:t,hosts:r=[],url:n,strict:o=!1}){let a=(String(n??"").trim()||String(t)).replace(/\/$/,"");if(a===String(t).replace(/\/$/,""))return{baseUrl:a,trusted:!0,host:Vt(t)};let i;try{i=new URL(a)}catch{throw new Error(`${e}: baseUrl must be an absolute http(s) URL`)}if(i.protocol!=="http:"&&i.protocol!=="https:")throw new Error(`${e}: baseUrl must be an absolute http(s) URL`);let c=i.host;if(!c)throw new Error(`${e}: baseUrl must be an absolute http(s) URL`);if(new Set([Vt(t),...r]).has(c)){let h=/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i.test(c);return i.protocol==="http:"&&!h?{baseUrl:a,trusted:!1,host:c,reason:"plaintext http downgrade"}:{baseUrl:a,trusted:!0,host:c}}if(String(process.env[Ht]||"")==="1")return{baseUrl:a,trusted:!1,host:c};if(o)throw new Error(`${e}: refusing to call non-allowlisted host ${c} (set ${Ht}=1 to permit it)`);return{baseUrl:a,trusted:!1,host:c}}function Vt(e){let t=new URL(String(e));if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error("unsupported protocol");return t.host}function j(e,t,r){let n={...e};if(!r)return n;for(let[o,s]of Object.entries(t||{}))s&&(n[o]=s);return n}function Ue(e={}){return String(e.baseUrl||process.env.BTC_META_API_URL||process.env.UNISAT_API_URL||"").trim().replace(/\/$/,"")}var Vr=["open-api.unisat.io","open-api-testnet.unisat.io","api.bestinslot.xyz","api.hiro.so"];function zr(e={}){let t=e.apiKey||process.env.UNISAT_API_KEY||process.env.BESTINSLOT_API_KEY||process.env.BTC_META_API_KEY||"",r=!1;try{let n=Ue(e);if(n){let o=new URL(n).host,s=new URL(n).protocol,a=/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i.test(o);r=Vr.includes(o)&&(s==="https:"||a)}}catch{r=!1}return j({accept:"application/json","user-agent":"oracle-btc-meta/0.1"},{authorization:t?`Bearer ${t}`:"","x-api-key":t},r)}async function zt(e,t={}){let n=await(t.fetchImpl||fetch)(e,{method:"GET",headers:zr(t),signal:AbortSignal.timeout(t.timeoutMs??12e3)}),o=await n.text(),s;try{s=JSON.parse(o)}catch{s=o}if(!n.ok)throw new Error(`bitcoin-meta GET ${e}: HTTP ${n.status} ${String(o).slice(0,160)}`);return s}async function jt(e={},t={}){let r=V(e.address||e.addr,"address"),n=Ue(t);if(!n)return{provider:"bitcoin-meta",address:r,ok:!1,balances:[],error:"no indexer configured (set BTC_META_API_URL or vendor API key env)"};let o=[`${n}/v1/indexer/address/${r}/runes/balance-list?start=0&limit=100`,`${n}/v1/runes/address/${r}`,`${n}/runes/balance/${r}`,`${n}/address/${r}/runes`],s=null;for(let a of o)try{let i=await zt(a,t),c=jr(i);return{provider:"bitcoin-meta",address:r,ok:!0,count:c.length,balances:c,source:a}}catch(i){s=i}return{provider:"bitcoin-meta",address:r,ok:!1,balances:[],error:String(s?.message||s||"all indexer paths failed")}}function jr(e){let t=e?.data?.detail||e?.data?.list||e?.data||e?.balances||e?.results||e?.runes||(Array.isArray(e)?e:[]);return(Array.isArray(t)?t:[]).map(n=>({rune:n.rune||n.runeid||n.runeId||n.spacedRune||n.name||n.ticker||null,runeId:n.runeid||n.runeId||n.id||null,amount:String(n.amount??n.balance??n.total??n.qty??"0"),symbol:n.symbol||null,divisibility:n.divisibility??n.div??null,raw:n}))}async function ue(e={},t={}){let r=V(e.address||e.addr,"address"),n=Ue(t);if(!n)return{provider:"bitcoin-meta",address:r,ok:!1,inscriptions:[],error:"no indexer configured \u2014 address-indexed lookups need a keyed indexer (BTC_META_API_URL + UNISAT_API_KEY / BESTINSLOT_API_KEY). ordinals.com recursive is keyless but has no address index.",unknownNotEmpty:!0,keylessAlternatives:["btc_inscription_info (by inscription id)","btc_meta_health"]};let o=Math.min(Number(e.limit||50),200),s=[`${n}/v1/indexer/address/${r}/inscription-data?cursor=0&size=${o}`,`${n}/v1/inscriptions/address/${r}?limit=${o}`,`${n}/address/${r}/inscriptions?limit=${o}`],a=null;for(let i of s)try{let c=await zt(i,t),d=Kr(c);return{provider:"bitcoin-meta",address:r,ok:!0,count:d.length,inscriptions:d,source:i}}catch(c){a=c}return{provider:"bitcoin-meta",address:r,ok:!1,inscriptions:[],error:String(a?.message||a||"all indexer paths failed")}}function Kr(e){let t=e?.data?.inscription||e?.data?.detail||e?.data?.list||e?.data||e?.inscriptions||e?.results||(Array.isArray(e)?e:[]);return(Array.isArray(t)?t:[]).map(n=>({id:n.inscriptionId||n.id||n.inscription_id||null,number:n.inscriptionNumber??n.number??null,sat:n.sat||n.satoshi||null,contentType:n.contentType||n.content_type||null,utxo:n.utxo||n.output||(n.txid!=null?`${n.txid}:${n.vout??n.n}`:null),raw:n}))}var Gr="https://api.hyperliquid.xyz/info",Wr="https://api.hyperliquid-testnet.xyz/info";function Yr({testnet:e,baseUrl:t}={}){if(t)return t.replace(/\/$/,"").endsWith("/info")?t:`${t.replace(/\/$/,"")}/info`;if(process.env.HL_INFO_URL)return process.env.HL_INFO_URL;if(process.env.HL_API_URL){let r=process.env.HL_API_URL.replace(/\/$/,"");return r.endsWith("/info")?r:`${r}/info`}return e||process.env.HL_TESTNET==="1"?Wr:Gr}async function Me(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Yr(t);return N(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function Kt(e={}){return Me({type:"allMids"},e)}async function Gt(e,t={}){if(!e)throw new Error("hlClearinghouse requires user address");return Me({type:"spotClearinghouseState",user:e},t)}async function Wt(e,t={}){if(!e)throw new Error("hlUserState requires user");return Me({type:"clearinghouseState",user:e},t)}var Jr="https://coins.llama.fi";function Xr(e={}){return(e.baseUrl||process.env.DEFILLAMA_COINS_URL||Jr).replace(/\/$/,"")}async function Yt(e,t={}){if(!Array.isArray(e)||!e.length)throw new Error("llamaPrices requires coins[]");let r=e.map(encodeURIComponent).join(",");return N(`${Xr(t)}/prices/current/${r}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}var Zr="TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",Xt=Object.freeze({ETH:"coingecko:ethereum",POL:"coingecko:polygon-ecosystem-token",BNB:"coingecko:binancecoin",AVAX:"coingecko:avalanche-2",HYPE:"coingecko:hyperliquid",USDT0:"coingecko:tether",SOL:"coingecko:solana",BTC:"coingecko:bitcoin"});function J(e={},t){return{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs,env:e.env,...e[t]||{}}}function de(e,...t){for(let r of t){let n=String(e?.[r]||"").trim();if(n)return n}return null}function Jt(e){if(!e)return null;try{return Qr(String(e).trim().toLowerCase())}catch{throw new Error("portfolio: EVM address must be a valid 20-byte address")}}function Fe(e={},t=process.env){let r=e.addresses||{},n=Jt(r.evm||e.evmAddress||de(t,"ORACLE_EVM_ADDRESS","ORACLE_DEFAULT_ADDRESS","MAD_OPERATOR_ADDRESS")),o=r.solana||e.solanaAddress||de(t,"ORACLE_SOLANA_ADDRESS"),s=r.bitcoin||e.bitcoinAddress||de(t,"ORACLE_BITCOIN_ADDRESS"),a=Jt(r.hyperliquid||e.hyperliquidAddress||de(t,"ORACLE_HYPERLIQUID_ADDRESS")||n);return{evm:n,solana:o?z(o,"portfolio Solana address"):null,bitcoin:s?V(s,"portfolio Bitcoin address"):null,hyperliquid:a}}function pe(e,t){let r=BigInt(String(e||"0")),n=Number(t);if(!Number.isInteger(n)||n<0||n>36)throw new Error("portfolio: decimals must be an integer from 0 to 36");if(n===0)return r.toString();let o=r<0n,s=o?-r:r,a=10n**BigInt(n),i=s/a,c=String(s%a).padStart(n,"0").replace(/0+$/,"");return`${o?"-":""}${i}${c?`.${c}`:""}`}function re(e){let t=Number(e);return Number.isFinite(t)?t:null}function De(e){return Number.isFinite(e)?Number(e.toFixed(2)):null}function X(e){let t=Number(e);return Number.isFinite(t)&&t!==0}function Qt(e,t){let r=Xt[t],n=r?e?.coins?.[r]:null,o=Number(n?.price);return{key:r||null,priceUsd:Number.isFinite(o)?o:null,timestamp:n?.timestamp??null,confidence:n?.confidence??null}}function eo(e){let t=new Map;for(let r of e)if(r?.ok)for(let n of r.data?.accounts||[]){let o=BigInt(String(n.amount||"0"));if(o===0n||!n.mint)continue;let s=`${n.mint}:${n.decimals??"unknown"}`,a=t.get(s)||{mint:n.mint,amountRaw:0n,decimals:n.decimals??null,programs:new Set,accounts:0};a.amountRaw+=o,a.accounts+=1,r.program&&a.programs.add(r.program),t.set(s,a)}return[...t.values()].map(r=>{let n=r.amountRaw.toString(),o=r.decimals==null?null:pe(n,r.decimals),s=r.decimals===0&&r.amountRaw===1n;return{mint:r.mint,amountRaw:n,amount:o,decimals:r.decimals,tokenPrograms:[...r.programs],accountCount:r.accounts,verification:"unverified",classification:s?"collectible-candidate":"fungible-or-unclassified",priceUsd:null,usdValue:null}})}function Be(e,t){return{family:e,status:"unsupported",reason:t}}function qe(e,t){if(!e||e.status!=="ok")return e;let r=Qt(t,e.symbol),n=re(e.amount),o=n!=null&&r.priceUsd!=null?De(n*r.priceUsd):null;return{...e,price:r,usdValue:o}}async function Zt(e={},t={}){let r=new Date().toISOString(),n=Fe(e,t.env||process.env),o=e.includePrices!==!1,s=e.includeTokens!==!1,a=e.includeCollectibles!==!1,i=new Map(ce.map(f=>[f.chainId,f])),c=Array.isArray(e.evmChainIds)&&e.evmChainIds.length?[...new Set(e.evmChainIds.map(Number))]:[...i.keys()],d=[...new Set(Object.values(Xt))],h=o?I(()=>Yt(d,J(t,"prices"))):Promise.resolve({ok:!1,ms:0,error:"price lookup disabled"}),u=H(c,e.concurrency||5,async f=>{let g=i.get(f);if(!g)return{family:"evm",chainId:f,name:null,address:n.evm,status:"unsupported",error:"chainId is not in Oracle's configured EVM registry"};if(!n.evm)return{family:"evm",chainId:f,name:g.name,address:null,status:"not-configured",error:"set ORACLE_EVM_ADDRESS or pass addresses.evm"};let S={...J(t,"evm"),rpcUrl:e.rpcUrls?.[f]||t.evm?.rpcUrls?.[f]},E=await I(()=>Ne(f,n.evm,S));if(!E.ok)return{family:"evm",chainId:f,name:g.name,address:n.evm,status:"unavailable",latencyMs:E.ms,error:E.error};let U=g.nativeCurrency?.decimals??18,$=g.nativeCurrency?.symbol||"NATIVE",b=E.data.balanceWei;return{family:"evm",chainId:f,name:g.name,address:n.evm,status:"ok",latencyMs:E.ms,native:{status:"ok",symbol:$,amountRaw:b,decimals:U,amount:pe(b,U)},fungibleTokens:{status:s?"unavailable":"not-requested",assets:[],reason:s?"EVM JSON-RPC cannot enumerate wallet tokens without an address indexer":"token discovery disabled"},collectibles:{status:a?"unavailable":"not-requested",assets:[],reason:a?"EVM JSON-RPC cannot enumerate wallet NFTs without an address indexer":"collectible discovery disabled"},source:"evm-rpc"}}),m=(async()=>{if(!n.solana)return{family:"solana",name:"Solana Mainnet",address:null,status:"not-configured",error:"set ORACLE_SOLANA_ADDRESS or pass addresses.solana"};let f=J(t,"solana"),g=await I(()=>qt({address:n.solana},f)),S=s||a?await Promise.all([I(()=>Le({owner:n.solana,programId:Oe},f)).then(T=>({...T,program:"spl-token"})),I(()=>Le({owner:n.solana,programId:Zr},f)).then(T=>({...T,program:"token-2022"}))]):[],E=eo(S),U=E.filter(T=>T.classification==="collectible-candidate"),$=E.filter(T=>T.classification!=="collectible-candidate"),b=S.filter(T=>!T.ok).map(T=>T.error);return{family:"solana",name:"Solana Mainnet",address:n.solana,status:g.ok||S.some(T=>T.ok)?"ok":"unavailable",native:g.ok?{status:"ok",symbol:"SOL",amountRaw:g.data.lamports,decimals:9,amount:pe(g.data.lamports,9),slot:g.data.slot}:{status:"unavailable",symbol:"SOL",error:g.error},fungibleTokens:{status:s?b.length===S.length?"unavailable":b.length?"partial":"ok":"not-requested",assets:s?$:[],errors:b,note:"SPL accounts are unverified until a metadata/indexer source confirms symbol and spam status"},collectibles:{status:a?b.length===S.length?"unavailable":"partial":"not-requested",assets:a?U:[],errors:b,note:"decimals=0 and amount=1 is only a collectible candidate, not verified NFT metadata"},source:"solana-rpc"}})(),l=(async()=>{if(!n.bitcoin)return{family:"bitcoin",name:"Bitcoin Mainnet",address:null,status:"not-configured",error:"set ORACLE_BITCOIN_ADDRESS or pass addresses.bitcoin"};let f=J(t,"bitcoin"),g=J(t,"bitcoinMeta"),[S,E,U]=await Promise.all([I(()=>Ft({address:n.bitcoin},f)),s?I(()=>jt({address:n.bitcoin},g)):Promise.resolve({ok:!1,ms:0,error:"token discovery disabled"}),a?I(()=>ue({address:n.bitcoin},g)):Promise.resolve({ok:!1,ms:0,error:"collectible discovery disabled"})]),$=E.ok?E.data:null,b=U.ok?U.data:null;return{family:"bitcoin",name:"Bitcoin Mainnet",address:n.bitcoin,status:S.ok||$?.ok||b?.ok?"ok":"unavailable",native:S.ok?{status:"ok",symbol:"BTC",amountRaw:S.data.balanceSats,decimals:8,amount:pe(S.data.balanceSats,8)}:{status:"unavailable",symbol:"BTC",error:S.error},fungibleTokens:{status:s?$?.ok?"ok":"unavailable":"not-requested",assets:$?.balances||[],error:$?.ok?null:$?.error||E.error,verification:"indexer-reported"},collectibles:{status:a?b?.ok?"ok":"unavailable":"not-requested",assets:b?.inscriptions||[],error:b?.ok?null:b?.error||U.error,unknownNotEmpty:!!b?.unknownNotEmpty,verification:"indexer-reported"},source:"bitcoin-esplora+bitcoin-meta"}})(),w=(async()=>{if(!n.hyperliquid)return{family:"hyperliquid",name:"Hyperliquid HyperCore",address:null,status:"not-configured",error:"set ORACLE_HYPERLIQUID_ADDRESS or pass addresses.hyperliquid"};let f=J(t,"hyperliquid"),[g,S,E]=await Promise.all([I(()=>Gt(n.hyperliquid,f)),I(()=>Wt(n.hyperliquid,f)),I(()=>Kt(f))]),U=(g.ok&&Array.isArray(g.data?.balances)?g.data.balances:[]).filter(b=>X(b.total)||X(b.hold)).map(b=>({coin:b.coin||null,total:String(b.total??"0"),hold:String(b.hold??"0"),priceUsd:null,usdValue:null})),$=(S.ok&&Array.isArray(S.data?.assetPositions)?S.data.assetPositions:[]).map(b=>b.position||b).filter(b=>X(b.szi)).map(b=>({coin:b.coin||null,size:String(b.szi??"0"),entryPrice:b.entryPx??null,positionValueUsd:b.positionValue??null,unrealizedPnlUsd:b.unrealizedPnl??null,liquidationPrice:b.liquidationPx??null}));return{family:"hyperliquid",name:"Hyperliquid HyperCore",address:n.hyperliquid,status:g.ok||S.ok?"ok":"unavailable",spot:{status:g.ok?"ok":"unavailable",balances:U,error:g.ok?null:g.error},perps:{status:S.ok?"ok":"unavailable",accountValueUsd:S.data?.marginSummary?.accountValue??null,withdrawableUsd:S.data?.withdrawable??null,positions:$,error:S.ok?null:S.error},mids:E.ok?E.data:{},source:"hyperliquid-info"}})(),[A,v,_,k,q]=await Promise.all([u,m,l,w,h]),p=q.ok?q.data:null,y=A.map(f=>f.native?{...f,native:qe(f.native,p)}:f);v.native&&(v.native=qe(v.native,p)),_.native&&(_.native=qe(_.native,p));let x=0,L=0,Z=0;for(let f of[...y,v,_])f.native?.status!=="ok"||!X(f.native.amount)||(f.native.usdValue!=null?(x+=f.native.usdValue,L+=1):Z+=1);let vn=Qt(p,"HYPE");for(let f of k.spot?.balances||[]){let g=String(f.coin||"").toUpperCase(),S=g==="USDC"||g==="USDT"||g==="USDT0"?1:g==="HYPE"?vn.priceUsd||re(k.mids?.HYPE):re(k.mids?.[f.coin]),E=re(f.total);f.priceUsd=S,f.usdValue=E!=null&&S!=null?De(E*S):null,X(f.total)&&(f.usdValue!=null?(x+=f.usdValue,L+=1):Z+=1)}let ye=re(k.perps?.accountValueUsd);ye!=null&&ye!==0&&(x+=ye,L+=1);let An=[...v.fungibleTokens?.assets||[],...v.collectibles?.assets||[]].filter(f=>X(f.amount)).length,xn=(_.fungibleTokens?.assets||[]).length+(_.collectibles?.assets||[]).length;Z+=An+xn;let ge=[...y,v,_,k],K=f=>ge.filter(g=>g.status===f).length,ee=[];y.some(f=>f.fungibleTokens?.status==="unavailable")&&ee.push("EVM token and NFT discovery is unavailable without a configured address indexer; native balances are still live."),(v.fungibleTokens?.assets?.length||v.collectibles?.assets?.length)&&ee.push("Solana token accounts are unverified and may include spam; collectible candidates are not confirmed NFTs."),_.collectibles?.unknownNotEmpty&&ee.push("Bitcoin inscription holdings are unknown, not zero, because no address indexer is configured."),q.ok||ee.push(`Price provider unavailable: ${q.error}`);let we=[Be("cosmos","requires a chain-specific bech32 address and LCD/RPC adapter"),Be("sui","Sui balance adapter is not installed"),Be("aptos","Aptos balance adapter is not installed")],En=ge.some(f=>["unavailable","partial","not-configured"].includes(f.fungibleTokens?.status)||["unavailable","partial","not-configured"].includes(f.collectibles?.status));return{provider:"portfolio",operation:"balances",readOnly:!0,queriedAt:r,addresses:n,coverage:{requestedSurfaces:ge.length,ok:K("ok"),unavailable:K("unavailable"),notConfigured:K("not-configured"),unsupported:K("unsupported")+we.length,evmChainsRequested:c.length,evmChainsOk:y.filter(f=>f.status==="ok").length},valuation:{knownUsd:De(x),label:"known priced value, not a complete portfolio total",pricedItems:L,unpricedNonzeroItems:Z,complete:Z===0&&!En&&K("unavailable")===0&&K("not-configured")===0&&we.length===0,priceSource:o?"DefiLlama":null,priceStatus:q.ok?"ok":"unavailable",priceQueriedAt:r},chains:[...y,v,_,k],unsupportedFamilies:we,warnings:ee}}import{readFileSync as to,existsSync as no}from"node:fs";import{getAddress as ro}from"ethers";var Sa=300*1e3,va=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})();var oo="https://api.opensea.io/api/v2",so=Object.freeze(["blast","base","ethereum","zora","arbitrum","sei","avalanche","polygon","optimism","ape_chain","flow","b3","soneium","ronin","bera_chain","solana","shape","unichain","gunzilla","abstract","animechain","hyperevm","somnia","monad","hyperliquid","megaeth","ink","robinhood","stablechain"]),ao=new Set(so),io=new Set(["solana","flow"]);function co(){let e=process.env.OPENSEA_ENV_FILE||`${process.env.HOME||""}/.config/locals-only/opensea.env`;if(!no(e))return"";try{for(let t of to(e,"utf8").split(`
5
+ `)){let r=t.match(/^\s*OPENSEA_API_KEY\s*=\s*(.+)\s*$/);if(r)return r[1].replace(/^["']|["']$/g,"").trim()}}catch{}return""}function He(e={}){return e.apiKey||process.env.OPENSEA_API_KEY||process.env.OPEN_SEA_API_KEY||co()}function nn(e={}){return Y({provider:"opensea",defaultUrl:oo,hosts:["api.opensea.io","testnets-api.opensea.io"],url:e.baseUrl||process.env.OPENSEA_API_URL})}function rn(e={}){return nn(e).baseUrl}function on(e={}){return j({accept:"application/json"},{"x-api-key":He(e)},nn(e).trusted)}function lo(e){let t=String(e||"ethereum").trim().toLowerCase();if(!ao.has(t))throw new Error(`opensea: unsupported account chain ${t}`);return t}function en(e,t="address"){try{return ro(String(e||"").trim().toLowerCase())}catch{throw new Error(`opensea: invalid ${t}`)}}function sn(e,t=null){let r=String(e||"").trim();if(!r)throw new Error("opensea: account address required");if(t&&!io.has(t)||!t&&/^0x[0-9a-fA-F]{40}$/.test(r))return en(r,"account address");if(!/^[1-9A-HJ-NP-Za-km-z]{32,64}$/.test(r))throw new Error("opensea: invalid account address");return r}function uo(e={},t,r){return{chain:t,owner:r,contract:e.contract||null,tokenId:e.identifier==null?null:String(e.identifier),tokenStandard:e.token_standard||null,collection:e.collection||null,name:e.name||null,description:e.description||null,imageUrl:e.display_image_url||e.image_url||e.original_image_url||null,originalImageUrl:e.original_image_url||e.image_url||null,animationUrl:e.display_animation_url||e.original_animation_url||null,metadataUrl:e.metadata_url||null,marketplaceUrl:e.opensea_url||null,estimatedValueUsd:e.estimated_value_usd!=null&&Number.isFinite(Number(e.estimated_value_usd))?Number(e.estimated_value_usd):null,spam:e.is_disabled===!0||e.is_nsfw===!0,disabled:e.is_disabled===!0,nsfw:e.is_nsfw===!0,traits:Array.isArray(e.traits)?e.traits:[],updatedAt:e.updated_at||null,acquisitionCost:null,itemPnl:{status:"unavailable",reason:"OpenSea account inventory does not expose trustworthy per-item acquisition cost"}}}async function Ve(e={},t={}){if(!He(t))throw new Error("OPENSEA_API_KEY required");let r=lo(e.chain),n=sn(e.address||e.owner,r),o=Math.min(Math.max(Number(e.pageSize??e.limit??200)||200,1),200),s=Math.min(Math.max(Number(e.maxPages??5)||5,1),25),a=[],i=e.next?String(e.next):null,c=0;do{let d=new URL(`${rn(t)}/chain/${encodeURIComponent(r)}/account/${encodeURIComponent(n)}/nfts`);d.searchParams.set("limit",String(o)),e.collection&&d.searchParams.set("collection",String(e.collection)),i&&d.searchParams.set("next",i);let h=await N(d.toString(),{headers:on(t),fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4});for(let u of Array.isArray(h?.nfts)?h.nfts:[])a.push(uo(u,r,n));i=h?.next?String(h.next):null,c+=1}while(i&&c<s);return{provider:"opensea-nft",source:"opensea-account-inventory",chain:r,owner:n,count:a.length,pages:c,complete:!i,next:i,nfts:a,exec:!1,readOnly:!0}}async function an(e={},t={}){if(!He(t))throw new Error("OPENSEA_API_KEY required");let r=sn(e.address||e.owner),n=await N(`${rn(t)}/account/${encodeURIComponent(r)}/pnl`,{headers:on(t),fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4});return{provider:"opensea-nft",source:"opensea-indexed-account-pnl",address:r,scope:"OpenSea-indexed account trading PnL across supported currencies, not per-item NFT cost basis",methodology:"provider-indexed",realizedPnlUsd:n?.realized_pnl_usd??null,unrealizedPnlUsd:n?.unrealized_pnl_usd??null,totalPnlUsd:n?.total_pnl_usd??null,netInvestedUsd:n?.net_invested_usd??null,currentValueUsd:n?.current_value_usd??null,returnPercentage:n?.return_percentage??null,itemLevelPnlAvailable:!1,raw:n,exec:!1,readOnly:!0}}var fo="https://api.satflow.com/v1";function cn(e={}){return Y({provider:"satflow",defaultUrl:fo,hosts:["api.satflow.com"],url:e.baseUrl||process.env.SATFLOW_API_URL})}function mo(e={}){return cn(e).baseUrl}function ln(e={}){return String(e.apiKey||process.env.SATFLOW_API_KEY||process.env.BTC_SATFLOW_API_KEY||"").trim()}function ho(e={}){return j({accept:"application/json","content-type":"application/json","user-agent":"oracle-btc-satflow/0.1"},{"x-api-key":ln(e)},cn(e).trusted)}async function bo(e,{method:t="GET",body:r,opts:n={}}={}){if(!ln(n))throw new Error("satflow: SATFLOW_API_KEY not set (request key via Satflow docs form)");let s=`${mo(n)}${e.startsWith("/")?e:`/${e}`}`,i=await(n.fetchImpl||fetch)(s,{method:t,headers:ho(n),body:r!=null?JSON.stringify(r):void 0,signal:AbortSignal.timeout(n.timeoutMs??2e4)}),c=await i.text(),d;try{d=JSON.parse(c)}catch{d=c}if(!i.ok)throw new Error(`satflow ${t} ${e}: HTTP ${i.status} ${String(c).slice(0,200)}`);return d}async function un(e={},t={}){let r=V(e.address||e.addr,"address"),n=new URLSearchParams({address:r});e.type&&n.set("type",e.type),e.limit!=null&&n.set("limit",String(e.limit)),e.offset!=null&&n.set("offset",String(e.offset));let o=await bo(`/address/wallet-contents?${n}`,{opts:t});return{provider:"satflow",address:r,contents:o}}var Ha=Object.freeze(["i.seadn.io","openseauserdata.com","arweave.net","ipfs.io","nftstorage.link","dweb.link","cloudflare-ipfs.com","ordinals.com","ordinals.g.com","cdn.helius-rpc.com","shdw-drive.genesysgo.net"]);var yo=Object.freeze([{chain:"ethereum",chainId:1,family:"evm"},{chain:"optimism",chainId:10,family:"evm"},{chain:"polygon",chainId:137,family:"evm"},{chain:"stablechain",chainId:988,family:"evm"},{chain:"hyperevm",chainId:999,family:"evm"},{chain:"abstract",chainId:2741,family:"evm"},{chain:"robinhood",chainId:4663,family:"evm"},{chain:"base",chainId:8453,family:"evm"},{chain:"arbitrum",chainId:42161,family:"evm"},{chain:"avalanche",chainId:43114,family:"evm"},{chain:"hyperliquid",chainId:null,family:"hyperliquid"}]),go=Object.freeze([{family:"evm",chain:"bsc",chainId:56,reason:"OpenSea account inventory does not support BSC"},{family:"cosmos",reason:"requires a chain-specific bech32 address and NFT indexer"},{family:"sui",reason:"owner inventory adapter not installed"},{family:"aptos",reason:"owner inventory adapter not installed"}]);function ze(e={},t){return{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs,...e[t]||{}}}async function oe(e,t){let r=await I(t);return r.ok?{ok:!0,data:r.data}:{ok:!1,error:`${e}: ${r.error}`.slice(0,300)}}function wo(e){if(Array.isArray(e))return e;for(let t of["items","results","ordinals","inscriptions","data"])if(Array.isArray(e?.[t]))return e[t];return[]}function So(e={},t){let r=e.inscription_id||e.inscriptionId||e.id||e.inscription||null;return{chain:"bitcoin",family:"bitcoin",owner:t,contract:null,tokenId:r==null?null:String(r),tokenStandard:"ordinal",collection:e.collection_slug||e.collectionSlug||e.collection?.slug||e.collection||null,name:e.name||e.meta?.name||(r?`Inscription ${r}`:"Bitcoin inscription"),description:e.description||e.meta?.description||null,imageUrl:e.image_url||e.imageUrl||e.content_url||e.contentUrl||e.thumbnail||null,originalImageUrl:e.content_url||e.contentUrl||e.image_url||e.imageUrl||null,animationUrl:null,metadataUrl:e.metadata_url||e.metadataUrl||null,marketplaceUrl:e.marketplace_url||e.marketplaceUrl||null,estimatedValueUsd:e.estimated_value_usd!=null&&Number.isFinite(Number(e.estimated_value_usd))?Number(e.estimated_value_usd):null,estimatedValueSats:(e.floor_price_sats??e.price_sats)!=null&&Number.isFinite(Number(e.floor_price_sats??e.price_sats))?Number(e.floor_price_sats??e.price_sats):null,spam:!1,disabled:!1,nsfw:!1,listed:e.listed===!0||e.is_listed===!0,listingId:e.listing_id||e.listingId||null,traits:Array.isArray(e.traits)?e.traits:[],updatedAt:e.updated_at||e.updatedAt||null,acquisitionCost:null,itemPnl:{status:"unavailable",reason:"Satflow wallet inventory does not expose trustworthy acquisition cost"},listingAdapter:"satflow",source:"satflow-wallet-contents"}}function vo(e,t){return{chain:"bitcoin",family:"bitcoin",owner:t,contract:null,tokenId:String(e),tokenStandard:"ordinal",collection:null,name:`Inscription ${e}`,description:null,imageUrl:null,originalImageUrl:null,animationUrl:null,metadataUrl:null,marketplaceUrl:null,estimatedValueUsd:null,spam:!1,disabled:!1,nsfw:!1,traits:[],updatedAt:null,acquisitionCost:null,itemPnl:{status:"unavailable",reason:"address indexer returned no acquisition or valuation data"},listingAdapter:"satflow",source:"bitcoin-meta-address-indexer"}}function dn(e={}){return[e.chain||"unknown",e.contract||"native",e.tokenId||"unknown"].join(":").toLowerCase()}function Ao(e){let t=new Map;if(Array.isArray(e)){for(let r of e)r?.assetKey&&t.set(String(r.assetKey).toLowerCase(),r);return t}if(e&&typeof e=="object")for(let[r,n]of Object.entries(e))t.set(r.toLowerCase(),n);return t}function xo(e,t){let r=dn(e),n=t.get(r),o=e.estimatedValueUsd==null?null:Number(e.estimatedValueUsd);if(!n)return{...e,assetKey:r};let s=Number(n.costUsd),a=Number(n.feesUsd??0);if(!Number.isFinite(s)||s<0||!Number.isFinite(a)||a<0)return{...e,assetKey:r,acquisitionCost:null,itemPnl:{status:"unavailable",reason:"invalid user-supplied cost basis"}};let i=Math.round((s+a)*100)/100;return Number.isFinite(o)?{...e,assetKey:r,acquisitionCost:{costUsd:s,feesUsd:a,totalCostUsd:i,acquiredAt:n.acquiredAt||null,source:n.source||"user-supplied"},itemPnl:{status:"estimated",methodology:"provider estimated current value minus supplied USD acquisition cost and fees",unrealizedUsd:Math.round((o-i)*100)/100,currentValueUsd:o,totalCostUsd:i,realizedUsd:null}}:{...e,assetKey:r,acquisitionCost:{costUsd:s,feesUsd:a,totalCostUsd:i,acquiredAt:n.acquiredAt||null,source:n.source||"user-supplied"},itemPnl:{status:"unavailable",reason:"current NFT valuation is unavailable"}}}function Eo(e){let t=new Map;for(let r of e){let n=dn(r);t.has(n)||t.set(n,r)}return[...t.values()]}function _o(e,t){let r=e.filter(s=>s.itemPnl?.status==="estimated"),n=e.length-r.length,o=Math.round(r.reduce((s,a)=>s+Number(a.itemPnl.unrealizedUsd||0),0)*100)/100;return{nftItemPnl:{status:n===0&&e.length?"estimated-complete-for-held-items":r.length?"partial":"unavailable",methodology:"Only items with explicit acquisition cost and provider estimated current value are included",knownUnrealizedUsd:o,knownItems:r.length,unknownItems:n,realizedUsd:null,warning:"Transfers, gifts, airdrops, mints, bridges, gas, royalties, and off-market sales can make cost basis unavailable or incomplete."},providerAccountPnl:t}}async function pn(e={},t={}){let r=new Date().toISOString(),n=Fe(e,t.env||process.env),o=Array.isArray(e.chains)&&e.chains.length?new Set(e.chains.map(p=>String(p).toLowerCase())):null,s=yo.filter(p=>!o||o.has(p.chain)),a=[],i=[],c=ze(t,"opensea"),d=n.evm?s.filter(p=>p.family!=="solana"):[],h=await H(d,4,async p=>({row:p,result:await oe(`opensea-${p.chain}`,()=>Ve({chain:p.chain,address:n.evm,pageSize:e.pageSize,maxPages:e.maxPages},c),t.timeoutMs??35e3)}));for(let{row:p,result:y}of h)if(y.ok){let x=y.data.nfts.map(L=>({...L,family:p.family,chainId:p.chainId,listingAdapter:"opensea",source:"opensea-account-inventory"}));i.push(...x),a.push({family:p.family,chain:p.chain,chainId:p.chainId,status:y.data.complete?"ok":"partial",count:x.length,complete:y.data.complete,next:y.data.next,source:"opensea"})}else a.push({family:p.family,chain:p.chain,chainId:p.chainId,status:"unavailable",error:y.error,source:"opensea"});if(!n.evm)for(let p of s.filter(y=>y.family!=="solana"))a.push({family:p.family,chain:p.chain,chainId:p.chainId,status:"not-configured",reason:"EVM address missing"});if(n.solana&&(!o||o.has("solana"))){let p=await oe("opensea-solana",()=>Ve({chain:"solana",address:n.solana,pageSize:e.pageSize,maxPages:e.maxPages},c),t.timeoutMs??35e3);if(p.ok){let y=p.data.nfts.map(x=>({...x,family:"solana",chainId:null,listingAdapter:null,source:"opensea-account-inventory"}));i.push(...y),a.push({family:"solana",chain:"solana",status:p.data.complete?"ok":"partial",count:y.length,complete:p.data.complete,next:p.data.next,source:"opensea"})}else a.push({family:"solana",chain:"solana",status:"unavailable",error:p.error,source:"opensea"})}else(!o||o.has("solana"))&&a.push({family:"solana",chain:"solana",status:"not-configured",reason:"Solana address missing"});if(n.bitcoin&&(!o||o.has("bitcoin"))){let p=await oe("satflow-wallet-contents",()=>un({address:n.bitcoin,type:"ordinals",limit:e.bitcoinLimit??100,offset:0},ze(t,"satflow")),t.timeoutMs??35e3);if(p.ok){let y=wo(p.data.contents).map(L=>So(L,n.bitcoin));i.push(...y);let x=y.length<Number(e.bitcoinLimit??100);a.push({family:"bitcoin",chain:"bitcoin",status:x?"ok":"partial",count:y.length,complete:x,source:"satflow"})}else{let y=await oe("bitcoin-meta-inscriptions",()=>ue({address:n.bitcoin},ze(t,"bitcoinMeta")),t.timeoutMs??35e3),x=y.ok&&y.data?.ok&&Array.isArray(y.data.inscriptions)?y.data.inscriptions:[];i.push(...x.map(L=>vo(L,n.bitcoin))),a.push({family:"bitcoin",chain:"bitcoin",status:x.length?"partial":"unavailable",count:x.length,complete:!1,source:x.length?"bitcoin-meta":"satflow",error:x.length?"Satflow unavailable; fallback has IDs only":p.error})}}else(!o||o.has("bitcoin"))&&a.push({family:"bitcoin",chain:"bitcoin",status:"not-configured",reason:"Bitcoin address missing"});let u=[];if(e.includePnl!==!1)for(let p of[...new Set([n.evm,n.solana].filter(Boolean))]){let y=await oe(`opensea-pnl-${p}`,()=>an({address:p},c),t.timeoutMs??35e3);u.push(y.ok?{status:"ok",...y.data}:{status:"unavailable",address:p,source:"opensea-indexed-account-pnl",error:y.error})}let m=Ao(e.costBasis),l=Eo(i).map(p=>xo(p,m)),w=l.filter(p=>!p.spam),A=l.filter(p=>p.spam),v=w.filter(p=>p.estimatedValueUsd!=null&&Number.isFinite(Number(p.estimatedValueUsd))),_=Math.round(v.reduce((p,y)=>p+Number(y.estimatedValueUsd),0)*100)/100,k=w.length-v.length,q=a.filter(p=>p.status!=="ok"||p.complete===!1);return{provider:"nft-portfolio",operation:"inventory",readOnly:!0,generatedAt:r,addresses:n,coverage:a,unsupported:go,inventory:{count:l.length,visibleCount:w.length,flaggedCount:A.length,items:l,visibleItems:w,flaggedItems:A},valuation:{estimatedCurrentValueUsd:_,valuedItems:v.length,unvaluedItems:k,complete:k===0&&q.length===0,methodology:"Sum of provider estimated_value_usd for non-flagged items. It is not an executable bid."},pnl:_o(w,u),listingCoverage:{opensea:"EVM listing actions available with OPENSEA_API_KEY, explicit price/currency/expiry, and user confirmation",satflow:"Bitcoin unsigned listing PSBT available with SATFLOW_API_KEY, explicit price/expiry, and user confirmation",solana:"Magic Eden unsigned list transaction available with MAGICEDEN_API_KEY, explicit SOL price/expiry, and user confirmation",unsupported:"Sui, Aptos, Cosmos, BSC, and unknown marketplaces fail closed"},metadataSafety:{imagesAreUntrusted:!0,animationAndHtmlNotRendered:!0,galleryRasterOnly:!0,missingImagesUsePlaceholders:!0}}}import{homedir as fn}from"node:os";import{join as mn}from"node:path";var oi=mn(fn(),".config","oracle"),si=mn(fn(),".config","mad-desk");function je(e,t,r=""){let n=process.env[e];if(n!=null&&String(n).trim()!=="")return n;let o=t?process.env[t]:void 0;return o!=null&&String(o).trim()!==""?o:r}var Ro=JSON.parse(gn(new URL("../../package.json",import.meta.url),"utf8")),Q="public",$o="127.0.0.1",Oo=8799,me=Ro.version,Lo=new Set(["127.0.0.1","localhost","::1"]),Uo=Ge(No(To(import.meta.url)),"../.."),Ke=Ge(Uo,"public","oracle-console"),hn=Object.freeze({"/":{file:"index.html",type:"text/html; charset=utf-8"},"/index.html":{file:"index.html",type:"text/html; charset=utf-8"},"/app.js":{file:"app.js",type:"application/javascript; charset=utf-8"},"/styles.css":{file:"styles.css",type:"text/css; charset=utf-8"},"/oracle-console":{file:"index.html",type:"text/html; charset=utf-8"},"/oracle-console/":{file:"index.html",type:"text/html; charset=utf-8"},"/oracle-console/index.html":{file:"index.html",type:"text/html; charset=utf-8"},"/oracle-console/app.js":{file:"app.js",type:"application/javascript; charset=utf-8"},"/oracle-console/styles.css":{file:"styles.css",type:"text/css; charset=utf-8"}}),Mo=1e6,P=class extends Error{constructor(t,r,n){super(n||r),this.status=t,this.code=r}};function D(e,t,r){let n=t,o;try{R(r),o=dt(r)}catch{n=500,o=JSON.stringify({error:"secret-leak-blocked"})}e.writeHead(n,{"content-type":"application/json; charset=utf-8","cache-control":"no-store","x-oracle-plane":Q,"x-oracle-unsigned":"true"}),e.end(o)}function Bo(e){return new Promise((t,r)=>{let n=[],o=0;e.on("data",s=>{if(o+=s.length,o>Mo){r(new P(413,"payload-too-large","request body too large")),e.destroy();return}n.push(s)}),e.on("end",()=>{let s=Buffer.concat(n).toString("utf8").trim();if(s==="")return t({});try{t(JSON.parse(s))}catch{r(new P(400,"invalid-json","request body must be valid JSON"))}}),e.on("error",()=>r(new P(400,"bad-request","request stream error")))})}function C(e,t){if(e==null)return{};if(typeof e!="object"||Array.isArray(e))throw new P(400,t,`${t} must be a JSON object`);return e}function qo(e){return String(e||"").trim().toLowerCase().replace(/^\[|\]$/g,"")}function Do(e){let t=qo(e);if(!Lo.has(t))throw new TypeError(`oracle-public only binds loopback hosts; got ${String(e)}`);return t==="::1"?"::1":String(e).trim()}function Fo(){return{status:200,body:{ok:!0,plane:Q,version:me}}}function he(e){return{...e,allowWildcardActions:!1,now:Math.floor(Date.now()/1e3)}}function Ho(e){let t=C(e,"body"),r=t.input!==void 0?C(t.input,"input"):t,n=he(C(t.opts,"opts")),o=r===t?(({opts:s,...a})=>a)(t):r;return{status:200,body:mt(o,n)}}function Vo(e){let t=C(e,"body"),r=t.request!==void 0?C(t.request,"request"):t.input!==void 0?C(t.input,"input"):t,n=he(C(t.opts,"opts")),o=r===t?(({opts:s,...a})=>a)(t):r;return{status:200,body:ht(o,n)}}function zo(e){let t=C(e,"body"),r=he(C(t.opts,"opts")),n=gt(t.store??[],r);return{status:200,body:{ok:!0,count:n.length,grants:n}}}function jo(e){let t=C(e,"body"),r=he(C(t.opts,"opts")),n=wt(t.store??[],t.id,r);return n==null?{status:404,body:{error:"grant-not-found"}}:{status:200,body:n}}function Ko(){let e=(process.env.ORACLE_PRIVY_APP_ID||process.env.PRIVY_APP_ID||"").trim(),t=e.length>0,r=!0,n=[];return t&&n.push("privy"),r&&n.push("injected"),{status:200,body:{ok:!0,plane:Q,version:me,custody:{selfCustodial:!0,signer:"user-wallet",privyEnabled:t,injectedEnabled:r,modes:n},privy:{appId:e||null}}}}var fe=12;async function Go(e){let t=C(e,"body"),r=typeof t.owner=="string"?t.owner:null;if(!r)throw new P(400,"owner-required","owner must be an EVM address");let n=Array.isArray(t.chainIds)?t.chainIds.map(Number).filter(Number.isFinite):void 0;if(n&&n.length>fe)throw new P(400,"too-many-chains",`at most ${fe} chainIds per request`);let s=await Ut({owner:r,chainIds:n},{});return{status:200,body:{ok:!0,owner:s.owner,scannedRange:s.scannedRange,approvals:s.approvals,scans:s.scans,warnings:s.warnings}}}function wn(e){if(typeof e=="string")return e.trim()===""?null:e;if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e.evm;if(typeof t=="string"&&t.trim()!=="")return t}return null}async function Wo(e){let t=C(e,"body"),r=wn(t.owner);if(!r)throw new P(400,"owner-required","owner must be an EVM address");let n=Array.isArray(t.chainIds)?t.chainIds.map(Number).filter(Number.isFinite):void 0;if(n&&n.length>fe)throw new P(400,"too-many-chains",`at most ${fe} chainIds per request`);let o=await Zt({addresses:{evm:r},evmChainIds:n,includePrices:!0,includeTokens:!0,includeCollectibles:!1},{env:{}}),s=[],a=[];for(let i of o.chains||[]){if(i.family!=="evm")continue;a.push({chainId:i.chainId,name:i.name,status:i.status,error:i.error??null,tokenDiscovery:i.fungibleTokens?.status??"unavailable",tokenDiscoveryReason:i.fungibleTokens?.reason??null});let c=i.native;i.status!=="ok"||!c||c.status!=="ok"||!c.amountRaw||c.amountRaw==="0"||c.amountRaw==="0x0"||s.push({chainId:i.chainId,chain:i.name,symbol:c.symbol,decimals:c.decimals,amount:String(c.amountRaw),amountRaw:String(c.amountRaw),amountFormatted:c.amount,kind:"native"})}return{status:200,body:{ok:!0,owner:o.addresses?.evm??r,queriedAt:o.queriedAt,portfolio:{rows:s,chains:a,coverage:o.coverage,complete:!1,incompleteReason:"EVM JSON-RPC returns native balances only; token enumeration requires an address indexer"},warnings:o.warnings}}}async function Yo(e){let t=C(e,"body"),r=wn(t.owner);if(!r)throw new P(400,"owner-required","owner must be an EVM address");let n=await pn({addresses:{evm:r}},{env:{}});return{status:200,body:{ok:!0,owner:r,queriedAt:n.queriedAt??new Date().toISOString(),nfts:{items:Array.isArray(n.items)?n.items:[],chains:n.chains??[],coverage:{operational:n.ok!==!1,complete:n.complete===!0,hasGaps:n.complete!==!0}},warnings:n.warnings}}}var Jo=6e4,Xo=120,Qo=10,bn=Object.freeze(new Set(["/public/approvals","/public/portfolio","/public/nfts"])),Zo=4096,se=new Map;function es(e){if(process.env.ORACLE_TRUST_PROXY==="1"){let t=e.headers["x-forwarded-for"];if(typeof t=="string"&&t.length>0){let r=t.split(",")[0].trim();if(r)return r.slice(0,64)}}return e.socket?.remoteAddress||"unknown"}function ts(e,t){let r=bn.has(t)?Qo:Xo,n=Date.now(),o=`${es(e)}:${bn.has(t)?"amp":"std"}`,s=se.get(o);if(!s||n>=s.resetAt){for(se.set(o,{count:1,resetAt:n+Jo});se.size>Zo;){let a=se.keys().next();if(a.done)break;se.delete(a.value)}return{allowed:!0,limit:r,remaining:r-1,retryAfterSec:0}}return s.count+=1,s.count>r?{allowed:!1,limit:r,remaining:0,retryAfterSec:Math.max(1,Math.ceil((s.resetAt-n)/1e3))}:{allowed:!0,limit:r,remaining:r-s.count,retryAfterSec:0}}var yn=Object.freeze({"GET /public/health":Fo,"GET /public/config":Ko,"POST /public/connect/request":Ho,"POST /public/connect/assemble":Vo,"POST /public/grants/active":zo,"POST /public/grants/get":jo,"POST /public/approvals":Go,"POST /public/portfolio":Wo,"POST /public/nfts":Yo});function We(e={}){return{"cache-control":"no-store","x-oracle-plane":Q,"x-oracle-unsigned":"true",...e}}function ns(e,t,r,n){e.writeHead(t,We({"content-type":r})),e.end(n)}function rs(e,t,r){if(e.method!=="GET"&&e.method!=="HEAD")return!1;let n=r===""?"/":r,o=hn[n]||hn[n.replace(/\/+$/,"")||"/"];if(!o)return!1;let s=Co(Ge(Ke,o.file));if(!s.startsWith(Ke+Po)&&s!==Ke)return D(t,404,{error:"not-found",message:"unknown static path"}),!0;if(!ko(s))return D(t,404,{error:"not-found",message:`missing static file ${o.file}`}),!0;let a=gn(s);return e.method==="HEAD"?(t.writeHead(200,We({"content-type":o.type,"content-length":String(a.length)})),t.end(),!0):(ns(t,200,o.type,a),!0)}async function os(e,t){let n=new URL(e.url,"http://localhost").pathname||"/";n.length>1&&n.endsWith("/")&&n!=="/oracle-console/"&&(n=n.replace(/\/+$/,"")),n===""&&(n="/");let o=n.replace(/\/+$/,"")||"/",s=`${e.method} ${o}`,a=yn[s];try{if(!a){if(rs(e,t,n))return;throw Object.keys(yn).some(u=>u.endsWith(` ${o}`))?new P(405,"method-not-allowed",`unsupported method for ${o}`):new P(404,"not-found",`unknown route ${o}`)}let i=ts(e,o);if(!i.allowed){t.writeHead(429,We({"content-type":"application/json","retry-after":String(i.retryAfterSec),"x-ratelimit-limit":String(i.limit),"x-ratelimit-remaining":"0"})),t.end(JSON.stringify({error:"rate-limited",message:`too many requests for ${o}; retry in ${i.retryAfterSec}s`}));return}let c=e.method==="GET"||e.method==="HEAD"?void 0:await Bo(e),d=await a(c);D(t,d.status,d.body)}catch(i){if(i instanceof O){D(t,500,{error:"secret-leak-blocked"});return}if(i instanceof M){D(t,400,{error:"invalid-grant",errors:i.errors.map(c=>({field:c.field,message:c.message}))});return}if(i instanceof P){D(t,i.status,{error:i.code,message:i.message});return}if(i instanceof TypeError){D(t,400,{error:"bad-request",message:i.message});return}D(t,500,{error:"internal-error"})}}function ss(){return Io((e,t)=>{os(e,t).catch(()=>{try{D(t,500,{error:"internal-error"})}catch{}})})}function Ye({host:e,port:t}={}){let r=Do(e??je("ORACLE_PUBLIC_HOST","MAD_PUBLIC_HOST",$o)),n=t??je("ORACLE_PUBLIC_PORT","MAD_PUBLIC_PORT",String(Oo)),o=Number(n);if(!Number.isInteger(o)||o<0||o>65535)throw new TypeError(`invalid public port: ${String(n)}`);return{host:r,port:o}}function Sn(e={}){let{host:t,port:r}=Ye(e),n=ss();return n.listen(r,t),n}var Je=Ye(),be=Sn(Je);be.on("listening",()=>{let e=be.address(),t=typeof e=="object"&&e?e.address:Je.host,r=typeof e=="object"&&e?e.port:Je.port;console.log(`oracle-public-server listening on http://${t}:${r} (plane=${Q}, version=${me}, unsigned-only)`)});be.on("error",e=>{console.error(`oracle-public-server failed to bind: ${e.code||e.message}`),process.exit(1)});for(let e of["SIGINT","SIGTERM"])process.on(e,()=>{be.close(()=>process.exit(0)),setTimeout(()=>process.exit(0),1e3).unref()});
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ var Yr=Object.defineProperty;var I=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var V=(e,t)=>{for(var r in t)Yr(e,r,{get:t[r],enumerable:!0})};import{createHash as en}from"node:crypto";function on(e){let t=String(e||"").toLowerCase();return Et.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function an(e){let t={};for(let[r,n]of Object.entries(e||{}))on(r)||(t[r]=n);return t}function sn(e,t){if(!e)throw new Error(`HTTP redirect from ${t} missing Location`);let r=new URL(String(e),String(t));if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`HTTP redirect from ${t} used unsupported protocol ${r.protocol}`);return r.toString()}function un(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function cn(e,t,r){let n={};for(let[u,c]of Object.entries(r||{}))n[u.toLowerCase()]=c;let o=Object.keys(n).filter(u=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(u)),s=[...new Set([...Et,...o])].sort().map(u=>`${u}=${n[u]??""}`).join(`
3
+ `),a=en("sha256").update(s).digest("hex").slice(0,32);return`${e} ${t} ${a}`}function ln(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,wt):Math.min(250*2**e,wt)+Math.floor(Math.random()*100)}async function pn(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:i}){let s=new AbortController,a=setTimeout(()=>s.abort(),i);try{let u=String(e),c={...n||{}};for(let p=0;p<=bt;p+=1){let d=await t(u,{method:r,headers:c,body:o,signal:s.signal,redirect:"manual"}),l=await d.text(),m=null;if(l)try{m=JSON.parse(l)}catch{m=null}if(nn.has(d.status)){if(r!=="GET"&&r!=="HEAD"){let g=new Error(`HTTP ${d.status} ${r} ${u} redirected non-idempotent request`);throw g.status=d.status,g.body=m??l.slice(0,300),g}if(p===bt)throw new Error(`HTTP redirect loop for ${e}`);let f=sn(d.headers?.get?.("location"),u);un(f,u)||(c=an(c)),u=f;continue}if(!d.ok){let f=new Error(`HTTP ${d.status} ${r} ${u}`);throw f.status=d.status,f.retryAfter=d.headers?.get?.("retry-after")??null,f.body=m??l.slice(0,300),f}return m??l}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(a)}}async function A(e,t={}){let r=t.fetchImpl||globalThis.fetch;if(typeof r!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let n=t.timeoutMs??12e3,o=(t.method||"GET").toUpperCase(),i={Accept:"application/json",...t.headers||{}},s=t.body;s!=null&&typeof s!="string"&&(i["Content-Type"]=i["Content-Type"]||"application/json",s=JSON.stringify(s));let a=Number.isInteger(t.retries)?Math.max(t.retries,0):rn,u=async()=>{let m;for(let f=0;f<=a;f++)try{return await pn(e,{fetchImpl:r,method:o,headers:i,body:s,timeoutMs:n})}catch(g){m=g;let h=g?.status,w=g?.name==="AbortError",v=new Set([408,425,429]),C=h!=null?v.has(h)||tn.has(h)&&gt.has(o):!w&&gt.has(o);if(f===a||!C)throw g;await dn(ln(f,g?.retryAfter))}throw m};if(!(t.dedupe!==!1&&o==="GET"&&s==null))return u();let p=cn(o,e,i),d=Be.get(p);if(d)return d;let l=u().finally(()=>Be.delete(p));return Be.set(p,l),l}var tn,gt,rn,wt,Et,nn,bt,Be,dn,B=I(()=>{tn=new Set([408,425,429,500,502,503,504]),gt=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),rn=2,wt=4e3,Et=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],nn=new Set([301,302,303,307,308]),bt=3;Be=new Map;dn=e=>new Promise(t=>setTimeout(t,e))});import{readFileSync as mn}from"node:fs";import{homedir as fn}from"node:os";import{join as yt}from"node:path";function hn(){if(process.env.ORACLE_TEST_ISOLATE_SECRETS==="1"){let r=(process.env.ORACLE_EXEC_ENV_FILE||"").trim();return r?[r]:[]}let e=(process.env.ORACLE_EXEC_ENV_FILE||process.env.MAD_EXEC_ENV_FILE||"").trim(),t=fn();return[e,yt(t,".config","oracle","exec.env"),yt(t,".config","mad-desk","exec.env")].filter(Boolean)}function At(e,t,r){let n=e??process.env[t]??process.env[r];if(!String(n||"").trim())for(let o of hn())try{let i=mn(o,"utf8"),s=i.match(new RegExp(`^${t}=(.*)$`,"m"))||i.match(new RegExp(`^${r}=(.*)$`,"m"));if(s&&(n=s[1].trim(),n))break}catch{}if(!String(n||"").trim())throw new Error(`${t} required for attestation. Set it in the environment, or place ${t}=<value> in ~/.config/oracle/exec.env`);return n}var vt=I(()=>{});var St=I(()=>{});import{createHash as gn,createHmac as wn,timingSafeEqual as ca}from"node:crypto";function Ue(e){return Array.isArray(e)?`[${e.map(Ue).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${Ue(e[t])}`).join(",")}}`:JSON.stringify(e??null)}function bn(e,{required:t=!1}={}){try{return At(e,"ORACLE_ROUTE_ATTESTATION_SECRET","MAD_ROUTE_ATTESTATION_SECRET")}catch(r){if(t)throw r;return null}}function Ct(e){let{signature:t,...r}=e;return r}function kt(e,{secret:t}={}){let r=bn(t);return r?{...e,signature:wn("sha256",r).update(Ue(Ct(e))).digest("hex")}:e}function En(e){let t=String(e||"").toLowerCase();if(!/^0x[0-9a-f]+$/.test(t)||t.length<10||t.length%2!==0)throw new Error("auto-slippage calldata must be even-length hex with a selector");return gn("sha256").update(Buffer.from(t.slice(2),"hex")).digest("hex")}function R(e,{chainId:t,venue:r,data:n,secret:o}={}){if(!e||e.mode!=="auto")throw new Error("bounded auto-slippage guard required");if(Number(e.chainId)!==Number(t))throw new Error("auto-slippage guard chain mismatch");if(String(e.venue).toLowerCase()!==String(r||"").toLowerCase())throw new Error("auto-slippage guard venue mismatch");return kt({...Ct(e),calldataHash:En(n)},{secret:o})}function $e(e,t=0){let r=Number(e);return Number.isFinite(r)?r:t}function yn(e){let t=e==null?xt:Number(e);if(!Number.isInteger(t)||t<0)throw new Error("auto-slippage cap must be a non-negative integer bps value");return Math.min(t,xt)}function U({liquidityUsd:e,priceChange5m:t=0,quoteAgeMs:r=0,crossChain:n=!1,requestedCapBps:o}={}){let i=$e(e,0),s=i>0?i>=25e4?5:i>=1e5?10:i>=5e4?20:i>=1e4?40:70:n?30:10,a=Math.min(60,Math.abs($e(t,0))*2),u=Math.min(40,Math.floor(Math.max(0,$e(r,0))/5e3)*5),c=Math.max(25,Math.ceil(20+s+a+u)),p=yn(o);return{mode:"auto",requiredBps:c,selectedBps:Math.min(c,p),capBps:p,executable:c<=p}}function An({chainId:e,venue:t,quoteAmountOut:r,liquidityUsd:n,priceChange5m:o=0,quoteAgeMs:i=0,crossChain:s=!1,requestedCapBps:a,quotedAtMs:u=Date.now(),ttlMs:c=It,secret:p}={}){let d=BigInt(r??0);if(d<=0n)throw new Error("auto-slippage guard requires positive quoteAmountOut");let l=U({liquidityUsd:n,priceChange5m:o,quoteAgeMs:i,crossChain:s,requestedCapBps:a});if(!l.executable)throw new Error(`auto-slippage requires ${l.requiredBps} bps above hard/requested cap ${l.capBps}; route blocked`);let m=Number(u);if(!Number.isFinite(m))throw new Error("auto-slippage: quotedAtMs must be a finite number");let f=Math.min(3e4,Math.max(1e3,Number(c)||It)),g=d*BigInt(1e4-l.selectedBps),h=g/10000n;if(g%10000n!==0n&&(h+=1n),h>d&&(h=d),d>0n&&h<=0n)throw new Error(`auto-slippage: quote ${d} is too small to express a ${l.selectedBps} bps floor without rounding to zero`);let w=Number((d-h)*10000n/(d===0n?1n:d));if(w>l.capBps)throw new Error(`auto-slippage: realised floor implies ${w} bps, above cap ${l.capBps} \u2014 refusing to issue a guard weaker than advertised`);return kt({mode:"auto",chainId:Number(e),venue:String(t||"unknown"),quoteAmountOut:d.toString(),minAmountOut:h.toString(),requiredBps:l.requiredBps,selectedBps:l.selectedBps,capBps:l.capBps,quotedAtMs:m,expiresAtMs:m+f},{secret:p})}function x(e,{chainId:t,venue:r,amountOut:n,liquidityUsd:o,priceChange5m:i,crossChain:s,requestedCapBps:a,quotedAtMs:u=Date.now(),ttlMs:c}={}){let p=An({chainId:t,venue:r,quoteAmountOut:n,liquidityUsd:o,priceChange5m:i,crossChain:s,requestedCapBps:a,quotedAtMs:u,ttlMs:c});return{...e,autoSlippage:p,amountOutMinimum:p.minAmountOut}}var xt,It,L=I(()=>{vt();St();xt=100,It=2e4});function Le(e){let t=String(e||"").trim();return/^0x[0-9a-fA-F]{40}$/.test(t)?t:P}var P,ce=I(()=>{P="0x000000000000000000000000000000000000dEaD"});import{createHash as vn,createHmac as Sn,timingSafeEqual as ha}from"node:crypto";function De(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(De).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${De(e[r])}`).join(",")}}`}function Ot(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Nt(e=process.env){return Ot(process.env)||Ot(e)}function Cn(e){let{oraclePrepared:t,prepareHash:r,prepareMac:n,note:o,...i}=e||{};return i}function kn(e){let t=Cn(e);return vn("sha256").update(De(t)).digest("hex")}function On(e,t=Nt()){return t?Sn("sha256",t).update(String(e)).digest("hex"):""}function S(e,{provider:t,kind:r,env:n=process.env}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let o={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1};if(!o.provider)throw new Error("stampPrepared: provider required");if(!o.kind)throw new Error("stampPrepared: kind required");let i=Date.now(),s=i+In,u={...o,preparedAt:i,expiresAt:s,prepareVersion:xn},c=kn(u),p=Nt(n),d=p?On(c,p):void 0,l={...u,oraclePrepared:!0,prepareHash:c};return d&&(l.prepareMac=d),l}var xn,In,ga,_=I(()=>{xn=2,In=300*1e3,ga=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});var qe={};V(qe,{LIFI_API:()=>_t,lifiChains:()=>Bn,lifiHealth:()=>_n,lifiPrepare:()=>Tn,lifiQuote:()=>J});function Fe(e={}){return(e.baseUrl||process.env.LIFI_API_URL||_t).replace(/\/$/,"")}function Rn(e){let t=String(e||Pe).toLowerCase();return t===Pe.toLowerCase()||t===Nn}function Rt(e,t){let r=String(e||"").trim();if(!/^0x[0-9a-fA-F]{40}$/.test(r))throw new Error(`lifi: ${t} must be a 20-byte address`);return r.toLowerCase()}async function _n(e={}){let t=await A(`${Fe(e)}/chains`,{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs??12e3}),r=Array.isArray(t)?t.length:t?.chains?.length||0;return{ok:r>0,chainCount:r}}async function J(e={},t={}){let{fromChain:r,toChain:n=r,fromToken:o=Pe,toToken:i,fromAmount:s,fromAddress:a=P}=e;if(r==null||!i||!s)throw new Error("lifiQuote requires fromChain, toToken, fromAmount");let u=new URLSearchParams({fromChain:String(r),toChain:String(n),fromToken:o,toToken:i,fromAmount:String(s),fromAddress:a}),c=U({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(r),requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!c.executable)throw new Error(`lifi: route requires ${c.requiredBps} bps above cap ${c.capBps}`);u.set("slippage",String(c.selectedBps/1e4));let p=await A(`${Fe(t)}/quote?${u}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),d=p?.estimate?.toAmount||p?.toAmount;if(!d)return{...p,autoSlippagePolicy:c};let l=p?.transactionRequest?.to||p?.estimate?.approvalAddress||"lifi",m=x(p,{chainId:Number(r),venue:l,amountOut:d,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(r),requestedCapBps:e.maxSlippageBps??e.slippageBps}),f=p?.estimate?.toAmountMin||p?.toAmountMin;if(f!=null&&BigInt(f)<BigInt(m.amountOutMinimum))throw new Error("lifi: provider transaction is under-protected versus bounded auto-slippage floor");return m}async function Tn(e={},t={}){let r=await J(e,t),n=r?.transactionRequest;if(!n?.to||!n?.data)throw new Error("lifi: quote did not return an executable transactionRequest");let o=Number(e.fromChain);if(n.chainId!=null&&Number(n.chainId)!==o)throw new Error("lifi: transaction chain mismatch");if(e.fromAddress&&n.from&&String(n.from).toLowerCase()!==String(e.fromAddress).toLowerCase())throw new Error("lifi: transaction sender mismatch");let i=null;if(!Rn(e.fromToken)){let s=r?.estimate?.approvalAddress||r?.approvalAddress;if(!s)throw new Error("lifi: ERC20 route missing approvalAddress");i={token:Rt(e.fromToken,"approval token"),spender:Rt(s,"approval spender"),amount:String(e.fromAmount)}}return S({provider:"lifi",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:o,quote:r,autoSlippage:r.autoSlippage,requiresApproval:i,transaction:{chainId:o,from:n.from||e.fromAddress,to:n.to,data:n.data,value:n.value??"0x0",...n.gasLimit!=null?{gasLimit:n.gasLimit}:{},slippageGuard:R(r.autoSlippage,{chainId:o,venue:n.to,data:n.data})}},{provider:"lifi",kind:"lifi-tx"})}async function Bn(e={}){return A(`${Fe(e)}/chains`,{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs??12e3})}var _t,Pe,Nn,le=I(()=>{B();L();ce();_();_t="https://li.quest/v1";Pe="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",Nn="0x0000000000000000000000000000000000000000"});var $t={};V($t,{PARASWAP_API:()=>Tt,paraswapHealth:()=>Un,paraswapPrepare:()=>$n,paraswapPrice:()=>de,paraswapTokens:()=>Bt});function K(e,t){let r=String(e||"");if(!/^0x[0-9a-fA-F]{40}$/.test(r))throw new Error(`${t} must be a 20-byte token address`);return r.toLowerCase()}async function Bt(e={},t={}){let r=Number(e.chainId||1);return A(`${Me(t)}/tokens/${r}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function de(e={},t={}){let r=Number(e.chainId||e.network||1);if(e.amount==null)throw new Error("amount required");let n=new URLSearchParams({srcToken:K(e.srcToken,"srcToken"),destToken:K(e.destToken,"destToken"),amount:String(e.amount),srcDecimals:String(Number(e.srcDecimals)),destDecimals:String(Number(e.destDecimals)),side:String(e.side||"SELL").toUpperCase(),network:String(r),version:String(e.version||"6.2")});e.includeDEXS&&n.set("includeDEXS",String(e.includeDEXS)),e.excludeDEXS&&n.set("excludeDEXS",String(e.excludeDEXS));let o=await A(`${Me(t)}/prices?${n}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),i=o?.priceRoute?.destAmount;return i?{...x(o,{chainId:r,venue:o?.priceRoute?.contractAddress||"paraswap-quote",amountOut:i,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,quoteAgeMs:0,requestedCapBps:e.maxSlippageBps??e.slippageBps}),executionReady:!1,executionBlocker:"call prepare to bind the price route to a validated transaction"}:{...o,executionReady:!1}}async function $n(e={},t={}){if(String(e.side||"SELL").toUpperCase()!=="SELL")throw new Error("paraswap: agentic prepare currently supports exact-input SELL only");let r=Number(e.chainId||e.network||1),n=K(e.userAddress,"userAddress"),o=await de(e,t),i=o?.priceRoute,s=String(i?.contractAddress||"").toLowerCase();if(!s)throw new Error("paraswap: price route missing contractAddress");let a={srcToken:K(e.srcToken,"srcToken"),destToken:K(e.destToken,"destToken"),srcAmount:String(i.srcAmount||e.amount),destAmount:String(o.amountOutMinimum),priceRoute:i,userAddress:n,ignoreChecks:!1,ignoreGasEstimate:!1};e.receiver&&(a.receiver=K(e.receiver,"receiver"));let u=await A(`${Me(t)}/transactions/${r}`,{method:"POST",body:a,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??25e3});if(Number(u.chainId??r)!==r)throw new Error("paraswap: transaction chain mismatch");if(String(u.to||"").toLowerCase()!==s)throw new Error("paraswap: transaction target mismatch");if(u.from&&String(u.from).toLowerCase()!==n)throw new Error("paraswap: transaction sender mismatch");return S({provider:"paraswap",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:r,quote:o,autoSlippage:o.autoSlippage,requiresApproval:a.srcToken!=="0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"?{token:a.srcToken,spender:i.tokenTransferProxy||s,amount:a.srcAmount}:null,transaction:{chainId:r,from:u.from||n,to:u.to,data:u.data,value:u.value??"0x0",...u.gas!=null?{gasLimit:u.gas}:{},slippageGuard:R(o.autoSlippage,{chainId:r,venue:u.to,data:u.data})}},{provider:"paraswap",kind:"paraswap-tx"})}async function Un(e={}){let t=await Bt({chainId:1},e),r=Array.isArray(t?.tokens)?t.tokens.length:Object.keys(t?.tokens||{}).length;return{ok:r>0,tokenSample:r}}var Tt,Me,Ve=I(()=>{B();L();_();Tt="https://api.paraswap.io",Me=(e={})=>(e.baseUrl||process.env.PARASWAP_API_URL||Tt).replace(/\/$/,"")});function pe({provider:e,defaultUrl:t,hosts:r=[],url:n,strict:o=!1}){let s=(String(n??"").trim()||String(t)).replace(/\/$/,"");if(s===String(t).replace(/\/$/,""))return{baseUrl:s,trusted:!0,host:Lt(t)};let a;try{a=new URL(s)}catch{throw new Error(`${e}: baseUrl must be an absolute http(s) URL`)}if(a.protocol!=="http:"&&a.protocol!=="https:")throw new Error(`${e}: baseUrl must be an absolute http(s) URL`);let u=a.host;if(!u)throw new Error(`${e}: baseUrl must be an absolute http(s) URL`);if(new Set([Lt(t),...r]).has(u)){let p=/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i.test(u);return a.protocol==="http:"&&!p?{baseUrl:s,trusted:!1,host:u,reason:"plaintext http downgrade"}:{baseUrl:s,trusted:!0,host:u}}if(String(process.env[Ut]||"")==="1")return{baseUrl:s,trusted:!1,host:u};if(o)throw new Error(`${e}: refusing to call non-allowlisted host ${u} (set ${Ut}=1 to permit it)`);return{baseUrl:s,trusted:!1,host:u}}function Lt(e){let t=new URL(String(e));if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error("unsupported protocol");return t.host}function me(e,t,r){let n={...e};if(!r)return n;for(let[o,i]of Object.entries(t||{}))i&&(n[o]=i);return n}var Ut,He=I(()=>{Ut="ORACLE_ALLOW_CUSTOM_PROVIDER_URL"});var Vt={};V(Vt,{ZEROX_API:()=>Dt,zeroxHealth:()=>Ln,zeroxPrepare:()=>Dn,zeroxPrice:()=>Mt,zeroxQuote:()=>he});function Pt(e={}){return pe({provider:"zerox",defaultUrl:Dt,hosts:["api.0x.org"],url:e.baseUrl||process.env.ZEROX_API_URL})}function Ft(e={}){return Pt(e).baseUrl}function fe(e={}){return e.apiKey||process.env.ZEROX_API_KEY||process.env.OX_API_KEY||process.env["0X_API_KEY"]||""}function qt(e={}){return me({"0x-version":"v2",accept:"application/json"},{"0x-api-key":fe(e)},Pt(e).trusted)}async function Ln(e={}){if(!fe(e))return{ok:!1,configured:!1,error:"ZEROX_API_KEY not set"};try{let t=await Mt({chainId:8453,sellToken:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",buyToken:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",sellAmount:"1000000000000000"},e);return{ok:!0,configured:!0,buyAmount:t.buyAmount||t.grossBuyAmount}}catch(t){return{ok:!1,configured:!0,error:String(t.message||t).slice(0,160)}}}async function Mt(e={},t={}){if(!fe(t))throw new Error("ZEROX_API_KEY required for 0x");let{chainId:r=8453,sellToken:n,buyToken:o,sellAmount:i,taker:s}=e;if(!n||!o||!i)throw new Error("zeroxPrice requires sellToken, buyToken, sellAmount");let a=new URLSearchParams({chainId:String(r),sellToken:n,buyToken:o,sellAmount:String(i)});return s&&a.set("taker",s),A(`${Ft(t)}/swap/allowance-holder/price?${a}`,{headers:qt(t),fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3})}async function he(e={},t={}){if(!fe(t))throw new Error("ZEROX_API_KEY required for 0x");let{chainId:r=8453,sellToken:n,buyToken:o,sellAmount:i,taker:s}=e;if(!n||!o||!i)throw new Error("zeroxQuote requires sellToken, buyToken, sellAmount");let a=U({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!a.executable)throw new Error(`0x: route requires ${a.requiredBps} bps above cap ${a.capBps}`);let u=new URLSearchParams({chainId:String(r),sellToken:n,buyToken:o,sellAmount:String(i),slippageBps:String(a.selectedBps)});s&&u.set("taker",s);let c=await A(`${Ft(t)}/swap/allowance-holder/quote?${u}`,{headers:qt(t),fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3}),p=c?.buyAmount||c?.grossBuyAmount;return p?x(c,{chainId:r,venue:c?.transaction?.to||c?.to||"0x",amountOut:p,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps}):{...c,autoSlippagePolicy:a}}async function Dn(e={},t={}){if(!e.taker)throw new Error("0x: taker required for executable prepare");let r=await he(e,t),n=r?.transaction;if(!n?.to||!n?.data)throw new Error("0x: firm quote returned no transaction");let o=Number(e.chainId??8453),i=r?.issues?.allowance?.spender||r?.allowanceTarget;return S({provider:"zerox",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:o,quote:r,autoSlippage:r.autoSlippage,requiresApproval:r?.issues?.allowance?.actual!=null&&BigInt(r.issues.allowance.actual)<BigInt(e.sellAmount)?{token:e.sellToken,spender:i,amount:String(e.sellAmount)}:null,transaction:{chainId:o,from:e.taker,to:n.to,data:n.data,value:n.value??"0x0",...n.gas!=null?{gasLimit:n.gas}:{},slippageGuard:R(r.autoSlippage,{chainId:o,venue:n.to,data:n.data})}},{provider:"zerox",kind:"zerox-tx"})}var Dt,je=I(()=>{B();L();He();_();Dt="https://api.0x.org"});var La,Da,zt=I(()=>{La=Object.freeze({READ:"read",PREPARE:"prepare",EXECUTE:"execute",AUTONOMOUS:"autonomous"}),Da=Object.freeze({"evm:prepare":["ORACLE_EVM_ADDRESS","EVM_KEYSTORE_FILE","ORACLE_SIGNER_ADDRESS"],"evm:execute":["EVM_KEYSTORE_FILE","ORACLE_KEYSTORE_FILE"],"btc:execute":["BTC_WIF_FILE","ORACLE_BTC_WIF_FILE"],"solana:execute":["SOLANA_KEYPAIR_FILE","ORACLE_SOLANA_KEYPAIR_FILE"],"nft:buy":[],"nft:mint":[],"cow:submit":[]})});var rr={};V(rr,{COW_CANCEL_TYPES:()=>Qt,COW_HOSTS:()=>ze,COW_ORDER_TYPES:()=>ge,COW_SETTLEMENT:()=>Gt,COW_VAULT_RELAYER:()=>Xt,cowCancelOrders:()=>Jn,cowChains:()=>to,cowHealth:()=>Kn,cowOrder:()=>tr,cowOrderStatus:()=>er,cowOrderUid:()=>Wn,cowPrepareCancel:()=>Yn,cowPrepareOrder:()=>zn,cowQuote:()=>ee,cowSignCancel:()=>Qn,cowSignOrder:()=>Gn,cowSubmitSignedOrder:()=>Xn,cowVerifyOrderFill:()=>eo});import{TypedDataEncoder as Wt,getAddress as Z,isAddress as Mn}from"ethers";function we(e,t={}){if(t.baseUrl)return t.baseUrl.replace(/\/$/,"");let r=ze[Number(e)];if(!r)throw new Error(`cowswap: unsupported chainId ${e}`);return r}function Vn(e,t="v1",r={}){let n=we(e,r);return t==="v1"?n:n.replace(/\/api\/v1$/,`/api/${t}`)}function F(e,t){let r=String(e||"").trim();if(!Mn(r))throw new Error(`cowswap: ${t} must be an address`);return Z(r).toLowerCase()}function z(e,t){try{let r=BigInt(String(e));if(r<0n)throw new Error("negative");return r.toString()}catch{throw new Error(`cowswap: ${t} must be a non-negative integer string`)}}function Jt(e,t){let r=String(e||"").trim();if(!/^0x[0-9a-fA-F]{64}$/.test(r))throw new Error(`cowswap: ${t} must be bytes32 hex`);return r.toLowerCase()}function Zt(e,t="uid"){let r=String(e||"").trim();if(!/^0x[0-9a-fA-F]{112}$/.test(r))throw new Error(`cowswap: ${t} must be 56-byte order UID hex`);return r.toLowerCase()}function Hn({digest:e,owner:t,validTo:r}={}){let n=Jt(e,"order digest").slice(2),o=F(t,"owner").slice(2).toLowerCase(),i=Number(r);if(!Number.isInteger(i)||i<0||i>4294967295)throw new Error("cowswap: validTo must fit uint32");return`0x${n}${o}${i.toString(16).padStart(8,"0")}`.toLowerCase()}function We(e){let t=Gt[Number(e)];if(!t)throw new Error(`cowswap: settlement contract not registered for chain ${e}`);return{name:"Gnosis Protocol",version:"v2",chainId:Number(e),verifyingContract:Z(t)}}function jn(e={},t,r){let n=F(e.sellToken,"sellToken"),o=F(e.buyToken,"buyToken"),i=F(e.receiver||r,"receiver"),s=Number(e.validTo);if(!Number.isInteger(s)||s<=0)throw new Error("cowswap: quote.validTo required");let a=Jt(e.appData||e.appDataHash||`0x${"0".repeat(64)}`,"appData");return{sellToken:n,buyToken:o,receiver:i,sellAmount:z(e.sellAmount,"sellAmount"),buyAmount:z(e.buyAmount,"buyAmount"),validTo:s,appData:a,feeAmount:z(e.feeAmount??"0","feeAmount"),kind:String(e.kind||"sell"),partiallyFillable:!!e.partiallyFillable,sellTokenBalance:String(e.sellTokenBalance||"erc20"),buyTokenBalance:String(e.buyTokenBalance||"erc20")}}async function Kn(e={}){try{let t=await ee({chainId:1,sellToken:Ke[1],buyToken:Yt[1],sellAmountBeforeFee:"1000000000000000",from:P},e);return{ok:!0,buyAmount:t.quote?.buyAmount||t.buyAmount}}catch(t){return{ok:!1,error:String(t.message||t).slice(0,160)}}}async function ee(e={},t={}){let r=Number(e.chainId??1),n=Le(e.from||e.owner),o=e.sellToken||Ke[r],i=e.buyToken||Yt[r],s=String(e.sellAmountBeforeFee||e.sellAmount||"0");if(!o||!i||s==="0")throw new Error("cowQuote requires sellToken, buyToken, sellAmountBeforeFee");if(/eeeeeeee|native|^eth$/i.test(o)&&(o=Ke[r],!o))throw new Error("no WETH mapping for chain");let a={sellToken:o,buyToken:i,from:n,receiver:e.receiver||n,sellAmountBeforeFee:s,kind:e.kind||"sell",signingScheme:e.signingScheme||"eip1271"},u=await A(`${we(r,t)}/quote`,{method:"POST",body:a,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3}),c=u?.quote?.buyAmount||u?.buyAmount;return c?x(u,{chainId:r,venue:"cowswap-order",amountOut:c,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps}):u}async function zn(e={},t={}){let r=Number(e.chainId??1),n=F(Le(e.from||e.owner||e.signer),"owner"),o=await ee({...e,chainId:r,from:n,signingScheme:e.signingScheme||"eip712"},t),i=jn(o?.quote||o,r,n),s=We(r),a={domain:s,types:ge,primaryType:"Order",message:i},u=Wt.hash(s,ge,i),c=Xt[r];if(!c)throw new Error(`cowswap: vault relayer not registered for chain ${r}`);return S({provider:"cowswap",orderReady:!0,executionReady:!1,chainId:r,owner:n,signingScheme:"eip712",settlement:s.verifyingContract.toLowerCase(),vaultRelayer:Z(c).toLowerCase(),quote:o,quoteId:o?.id??e.quoteId??null,typedData:a,cowGuard:{mode:"cow-order",version:1,provider:"cowswap",chainId:r,owner:n,settlement:s.verifyingContract.toLowerCase(),vaultRelayer:Z(c).toLowerCase(),sellToken:i.sellToken,buyToken:i.buyToken,sellAmount:i.sellAmount,buyAmount:i.buyAmount,validTo:i.validTo,quoteId:o?.id??e.quoteId??null,typedDataHash:u,issuedAtMs:Date.now(),expiresAtMs:Math.min(i.validTo*1e3,Date.now()+2e4)},requiresApproval:{token:i.sellToken,spender:Z(c).toLowerCase(),amount:i.sellAmount}},{provider:"cowswap",kind:"cow-order"})}async function er(e={},t={}){let r=Number(e.chainId??1),n=String(e.uid||e.orderUid||"").trim();if(!n)throw new Error("cowOrderStatus requires uid");return A(`${we(r,t)}/orders/${encodeURIComponent(n)}/status`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3})}async function tr(e={},t={}){let r=Number(e.chainId??1),n=String(e.uid||e.orderUid||"").trim();if(!n)throw new Error("cowOrder requires uid");return A(`${we(r,t)}/orders/${encodeURIComponent(n)}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3})}function Wn(e={}){let t=e.typedData||e,r=Number(e.chainId??t?.domain?.chainId),n=t?.message||e.order||e.message;if(!n)throw new Error("cowswap: typed order message required");let o=e.cowGuard?.typedDataHash||Wt.hash(We(r),ge,n),i=e.owner||e.from||e.signer||n.receiver;return Hn({digest:o,owner:i,validTo:n.validTo})}async function Gn(e={},t={}){throw new Error("cowswap.cowSignOrder refused: @oracle-agent/oracle is prepare-only. Sign with the user wallet; do not pass private keys here.")}async function Xn(e={},t={}){throw new Error("cowswap.cowSubmitSignedOrder refused: @oracle-agent/oracle is prepare-only. Submit signed orders from the user wallet or local operator.")}function Yn(e={}){let t=Number(e.chainId??1),r=F(e.owner||e.from||e.signer,"owner"),n=(e.orderUids||e.uids||[e.uid]).filter(Boolean).map((s,a)=>Zt(s,`orderUids[${a}]`));if(!n.length)throw new Error("cowswap: orderUids required");let o=We(t);return S({provider:"cowswap",chainId:t,owner:r,orderUids:n,signingScheme:"eip712",typedData:{domain:o,types:Qt,primaryType:"OrderCancellations",message:{orderUids:n}},cancelReady:!0,executableArtifact:!0},{provider:"cowswap",kind:"cow-cancel"})}async function Qn(e={},t={}){throw new Error("cowswap.cowSignCancel refused: @oracle-agent/oracle is prepare-only. Cancel-sign with the user wallet.")}async function Jn(e={},t={}){throw new Error("cowswap.cowCancelOrders refused: @oracle-agent/oracle is prepare-only. Cancel from the user wallet or local operator.")}function Zn(e={}){return z(e.buyAmount??e.executedBuyAmount??"0","trade.buyAmount")}async function eo(e={},t={}){let r=Number(e.chainId??1),n=Zt(e.uid||e.orderUid),o=t.order||await tr({chainId:r,uid:n},t),i=t.status||o.status||await er({chainId:r,uid:n},t).catch(()=>null),s=t.trades||await A(`${Vn(r,"v2",t)}/trades?orderUid=${encodeURIComponent(n)}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3}),a=Array.isArray(s)?s:[],u=e.expectedOwner?F(e.expectedOwner,"expectedOwner"):null;if(u&&F(o.owner||a[0]?.owner||u,"owner")!==u)return{ok:!1,provider:"cowswap",chainId:r,uid:n,reason:"owner mismatch",order:o,status:i,trades:a};let c=0n;for(let l of a.filter(m=>String(m.orderUid||"").toLowerCase()===n))c+=BigInt(Zn(l));c===0n&&o.executedBuyAmount!=null&&(c=BigInt(z(o.executedBuyAmount,"executedBuyAmount")));let p=e.minBuyAmount!=null?BigInt(z(e.minBuyAmount,"minBuyAmount")):0n,d=c>=p&&String(o.status||i?.status||"").toLowerCase()!=="expired";return{ok:d,provider:"cowswap",chainId:r,uid:n,status:o.status||i?.status||null,executedBuyAmount:c.toString(),minBuyAmount:e.minBuyAmount??null,trades:a,settlementTxs:[...new Set(a.map(l=>l.txHash).filter(Boolean))],order:o,orderStatus:i,reason:d?null:"insufficient fill or expired order"}}function to(){return Object.keys(ze).map(Number)}var ze,Gt,Xt,Ke,Yt,ge,Qt,Ge=I(()=>{B();L();zt();ce();_();ze={1:"https://api.cow.fi/mainnet/api/v1",100:"https://api.cow.fi/xdai/api/v1",42161:"https://api.cow.fi/arbitrum_one/api/v1",8453:"https://api.cow.fi/base/api/v1"},Gt=Object.freeze({1:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",100:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",42161:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",8453:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41"}),Xt=Object.freeze({1:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",100:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",42161:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",8453:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110"}),Ke={1:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",8453:"0x4200000000000000000000000000000000000006",42161:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"},Yt={1:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",8453:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",42161:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},ge=Object.freeze({Order:[{name:"sellToken",type:"address"},{name:"buyToken",type:"address"},{name:"receiver",type:"address"},{name:"sellAmount",type:"uint256"},{name:"buyAmount",type:"uint256"},{name:"validTo",type:"uint32"},{name:"appData",type:"bytes32"},{name:"feeAmount",type:"uint256"},{name:"kind",type:"string"},{name:"partiallyFillable",type:"bool"},{name:"sellTokenBalance",type:"string"},{name:"buyTokenBalance",type:"string"}]}),Qt=Object.freeze({OrderCancellations:[{name:"orderUids",type:"bytes[]"}]})});function or(e){return ro.get(Number(e))||null}function ar(e,t=process.env){let r=or(e);if(!r)return null;for(let n of r.rpcEnv){let o=(t[n]||"").trim();if(o)return o}return null}var nr,ro,ir=I(()=>{nr={robinhood:{chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC"],evm:!0},ethereum:{chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],evm:!0},polygon:{chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],evm:!0},arbitrum:{chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],evm:!0},base:{chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],evm:!0},hyperevm:{chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],evm:!0},bsc:{chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],evm:!0},avalanche:{chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],evm:!0},optimism:{chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],evm:!0},abstract:{chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],evm:!0},stable:{chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],evm:!0}},ro=new Map(Object.values(nr).map(e=>[e.chainId,e]))});import{Interface as no,getAddress as oo}from"ethers";function ur(e,t){try{return oo(e).toLowerCase()}catch{throw new Error(`${t} must be a valid EVM address`)}}function io(e,{rpcUrl:t,env:r=process.env}={}){if(t)return t;let n=ar(e,r);return n||ao[Number(e)]||null}function uo(e){let t=String(e||""),r=t.toLowerCase();if(t!==t.trim()||!/^[a-zA-Z0-9_]+$/.test(t)||!so.test(r))throw new Error(`evm-rpc: ${t} refused \u2014 @oracle-agent/oracle is prepare-only (read RPC only; no broadcast/sign)`);return r}async function k(e,t,r=[],n={}){let o=String(t||"");uo(o);let i=io(e,n);if(!i)throw new Error(`No RPC URL for chainId ${e} (set env from chain registry rpcEnv or pass rpcUrl)`);let a=await A(i,{method:"POST",body:{jsonrpc:"2.0",id:1,method:t,params:r},fetchImpl:n.fetchImpl,timeoutMs:n.timeoutMs??12e3});if(a?.error){let u=new Error(a.error.message||JSON.stringify(a.error));throw u.code=a.error.code,u}return a.result}async function cr(e,t={}){let r=await k(e,"eth_blockNumber",[],t);return parseInt(r,16)}async function lr(e,t,r={}){if(!t)throw new Error("rpcGetBalance requires address");let n=await k(e,"eth_getBalance",[t,"latest"],r);return{chainId:Number(e),address:t,balanceWei:BigInt(n).toString(),balanceHex:n}}async function dr(e={},t={}){let r=Number(e.chainId??t.chainId??1),n=ur(e.token||e.tokenAddress,"token"),o=ur(e.account||e.owner||e.address,"account"),i=sr.encodeFunctionData("balanceOf",[o]),s=await k(r,"eth_call",[{to:n,data:i},e.blockTag||"latest"],t),a=sr.decodeFunctionResult("balanceOf",s),u=BigInt(a[0]);return{chainId:r,token:n,account:o,balance:u.toString(),balanceHex:`0x${u.toString(16)}`,blockTag:e.blockTag||"latest"}}var sr,ao,so,W=I(()=>{B();ir();sr=new no(["function allowance(address owner,address spender) view returns (uint256)","function balanceOf(address account) view returns (uint256)"]);ao={1:"https://ethereum.publicnode.com",137:"https://polygon-bor-rpc.publicnode.com",42161:"https://arbitrum-one-rpc.publicnode.com",8453:"https://base-rpc.publicnode.com",10:"https://optimism-rpc.publicnode.com",988:"https://rpc.stable.xyz",56:"https://bsc-rpc.publicnode.com",43114:"https://avalanche-c-chain-rpc.publicnode.com",999:"https://rpc.hyperliquid.xyz/evm",2741:"https://api.mainnet.abs.xyz",4663:"https://rpc.mainnet.chain.robinhood.com"};so=/^(?:eth_(?:call|blocknumber|chainid|get[a-z0-9]+|feehistory|gasprice|maxpriorityfeepergas|syncing|protocolversion|estimategas|createaccesslist)|net_(?:version|listening|peercount)|web3_(?:clientversion|sha3))$/});var br={};V(br,{UNI_V3_CHAINS:()=>O,UNI_V3_FEE_TIERS:()=>fr,uniV3Chains:()=>ho,uniV3EthUsdc:()=>wr,uniV3Health:()=>fo,uniV3PrepareExactIn:()=>mo,uniV3QuoteExactIn:()=>re,uniV3QuoteExactInPath:()=>po});import{Interface as mr,getAddress as te,isAddress as co}from"ethers";function Ye(e){let t=Number(e),r=O[t];if(!r)throw new Error(`uniswap-v3: unsupported chainId ${e} (supported: ${Object.keys(O).join(", ")})`);return{chainId:t,...r}}function Xe(e,t){let r=O[Number(t)];if(!e||e===hr||e===gr||/^eth$/i.test(String(e)))return te(r.weth);let n=String(e);if(/^weth$/i.test(n))return te(r.weth);if(/^usdc$/i.test(n))return te(r.usdc);if(!co(n))throw new Error(`invalid token address: ${e}`);return te(n)}function lo(e,t){if(e.length!==t.length+1)throw new Error("path: fees.length must be tokens.length - 1");let r="0x";for(let n=0;n<t.length;n++)r+=e[n].slice(2).toLowerCase(),r+=Number(t[n]).toString(16).padStart(6,"0");return r+=e[e.length-1].slice(2).toLowerCase(),r}async function re(e={},t={}){let{chainId:r,quoter:n,router:o}=Ye(e.chainId??8453),i=Xe(e.tokenIn||"WETH",r),s=Xe(e.tokenOut||O[r].usdc,r),a=BigInt(e.amountIn??0);if(a<=0n)throw new Error("amountIn required (raw base units)");let u=e.fee!=null?[Number(e.fee)]:e.tryFees===!1?[3e3]:[...fr],c=[],p=null;for(let d of u){let l=be.encodeFunctionData("quoteExactInputSingle",[{tokenIn:i,tokenOut:s,amountIn:a,fee:d,sqrtPriceLimitX96:0n}]);try{let m=await k(r,"eth_call",[{to:n,data:l},"latest"],t);if(!m||m==="0x"){c.push({fee:d,ok:!1,error:"empty result"});continue}let f=be.decodeFunctionResult("quoteExactInputSingle",m),g={fee:d,ok:!0,amountOut:f[0].toString(),sqrtPriceX96After:f[1].toString(),initializedTicksCrossed:Number(f[2]),gasEstimate:f[3].toString()};c.push(g),(!p||BigInt(g.amountOut)>BigInt(p.amountOut))&&(p=g)}catch(m){c.push({fee:d,ok:!1,error:String(m.message||m).slice(0,160)})}}if(!p){let d=c.map(l=>`${l.fee}:${l.error||"fail"}`).join("; ");throw new Error(`uniswap-v3 quote failed chain=${r}: ${d}`)}return x({venue:"uniswap-v3",chainId:r,chain:O[r].name,quoter:n,tokenIn:i,tokenOut:s,amountIn:a.toString(),fee:p.fee,amountOut:p.amountOut,gasEstimate:p.gasEstimate,sqrtPriceX96After:p.sqrtPriceX96After,initializedTicksCrossed:p.initializedTicksCrossed,triedFees:c,best:!0},{chainId:r,venue:o,amountOut:p.amountOut,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps})}async function po(e={},t={}){let{chainId:r,quoter:n,router:o}=Ye(e.chainId??8453),i=(e.tokens||[]).map(l=>Xe(l,r)),s=(e.fees||[]).map(Number);if(i.length<2)throw new Error("tokens[] need at least 2 addresses");let a=BigInt(e.amountIn??0);if(a<=0n)throw new Error("amountIn required");let u=lo(i,s),c=be.encodeFunctionData("quoteExactInput",[u,a]),p=await k(r,"eth_call",[{to:n,data:c},"latest"],t),d=be.decodeFunctionResult("quoteExactInput",p);return x({venue:"uniswap-v3",chainId:r,chain:O[r].name,quoter:n,tokens:i,fees:s,path:u,amountIn:a.toString(),amountOut:d[0].toString(),gasEstimate:d[3].toString()},{chainId:r,venue:o,amountOut:d[0].toString(),liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps})}async function wr(e={},t={}){let r=Number(e.chainId??8453),n=e.amountIn??"1000000000000000",o=await re({chainId:r,tokenIn:O[r].weth,tokenOut:O[r].usdc,amountIn:n,fee:e.fee},t),i=Number(o.amountOut)/1e6;return{...o,amountOutUsdc:i,pair:"WETH/USDC"}}async function mo(e={},t={}){let r=Number(e.chainId??8453),n=Ye(r),o=te(e.recipient),i=String(e.tokenIn||"WETH"),s=!e.tokenIn||i===hr||i===gr||/^eth$/i.test(i),a=await re(e,t),u=pr.encodeFunctionData("exactInputSingle",[{tokenIn:a.tokenIn,tokenOut:a.tokenOut,fee:a.fee,recipient:o,amountIn:BigInt(a.amountIn),amountOutMinimum:BigInt(a.amountOutMinimum),sqrtPriceLimitX96:0n}]),c=Math.min(600,Math.max(30,Number(e.deadlineSeconds??300))),d=Number(t.nowSeconds??Math.floor(Date.now()/1e3))+c,l=pr.encodeFunctionData("multicall",[d,[u]]);return S({provider:"uniswap-v3",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:r,deadline:d,quote:a,autoSlippage:a.autoSlippage,requiresApproval:s?null:{token:a.tokenIn,spender:n.router,amount:a.amountIn},transaction:{chainId:r,from:o,to:n.router,data:l,value:s?a.amountIn:"0",slippageGuard:R(a.autoSlippage,{chainId:r,venue:n.router,data:l})}},{provider:"uniswap-v3",kind:"univ3-swap-tx"})}async function fo(e={}){let t=Number(e.chainId??8453);try{let r=await wr({chainId:t,amountIn:"1000000000000000"},e);return{ok:!0,chainId:t,fee:r.fee,amountOutUsdc:r.amountOutUsdc,midPxHint:r.amountOutUsdc/.001}}catch(r){return{ok:!1,chainId:t,error:String(r.message||r).slice(0,200)}}}async function ho(){return Object.entries(O).map(([e,t])=>({chainId:Number(e),name:t.name,quoter:t.quoter,weth:t.weth,usdc:t.usdc}))}var O,fr,be,pr,hr,gr,Qe=I(()=>{W();L();_();O={1:{name:"ethereum",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",usdc:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},8453:{name:"base",quoter:"0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",router:"0x2626664c2603336E57B271c5C0b26F421741e481",weth:"0x4200000000000000000000000000000000000006",usdc:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},42161:{name:"arbitrum",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",usdc:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},4663:{name:"robinhood",quoter:"0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",router:"0xcaf681a66d020601342297493863e78c959e5cb2",weth:"0x0bd7d308f8e1639fab988df18a8011f41eacad73",usdc:"0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"},10:{name:"optimism",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0x4200000000000000000000000000000000000006",usdc:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"},56:{name:"bsc",quoter:"0x78D78E420Da98ad378D7799bE8f4AF69033EB077",router:"0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2",weth:"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",usdc:"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"},137:{name:"polygon",quoter:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",router:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",weth:"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",usdc:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"},43114:{name:"avalanche",quoter:"0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F",router:"0xbb00FF08d01D300023C629E8fFfFcb65A5a578cE",weth:"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",usdc:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"}},fr=[100,500,3e3,1e4],be=new mr(["function quoteExactInputSingle((address tokenIn, address tokenOut, uint256 amountIn, uint24 fee, uint160 sqrtPriceLimitX96) params) returns (uint256 amountOut, uint160 sqrtPriceX96After, uint32 initializedTicksCrossed, uint256 gasEstimate)","function quoteExactInput(bytes path, uint256 amountIn) returns (uint256 amountOut, uint160[] sqrtPriceX96AfterList, uint32[] initializedTicksCrossedList, uint256 gasEstimate)"]),pr=new mr(["function exactInputSingle((address tokenIn,address tokenOut,uint24 fee,address recipient,uint256 amountIn,uint256 amountOutMinimum,uint160 sqrtPriceLimitX96) params) payable returns (uint256 amountOut)","function multicall(uint256 deadline,bytes[] data) payable returns (bytes[] results)"]),hr="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",gr="0x0000000000000000000000000000000000000000"});var Ir={};V(Ir,{UNI_V4_CHAINS:()=>D,UNI_V4_FEE_TIERS:()=>vr,computeV4PoolId:()=>xr,uniV4Chains:()=>xo,uniV4Health:()=>Io,uniV4PrepareExactIn:()=>So,uniV4QuoteExactIn:()=>ye});import{AbiCoder as go,Interface as Ar,getAddress as T,isAddress as Ee,keccak256 as wo}from"ethers";function Je(e){let t=Number(e),r=D[t];if(!r)throw new Error(`uniswap-v4: unsupported chainId ${e} (supported: ${Object.keys(D).join(", ")})`);return{chainId:t,...r}}function yr(e,t){let r=D[Number(t)];if(!e||e===Sr||e===H||/^eth$/i.test(String(e)))return T(r.weth);let n=String(e);if(/^weth$/i.test(n))return T(r.weth);if(/^usdc$/i.test(n)||/^usdg$/i.test(n))return T(r.usdc);if(!Ee(n))throw new Error(`invalid token address: ${e}`);return T(n)}function xr({currency0:e,currency1:t,fee:r,tickSpacing:n,hooks:o=H}){let i=T(e),s=T(t);if(i.toLowerCase()===s.toLowerCase())throw new Error("poolKey currencies must differ");let[a,u]=i.toLowerCase()<s.toLowerCase()?[i,s]:[s,i],c=o&&Ee(o)?T(o):H;return wo(ne.encode(["address","address","uint24","int24","address"],[a,u,Number(r),Number(n),c]))}function vo({tokenIn:e,tokenOut:t,fee:r,tickSpacing:n,hooks:o=H}){let i=T(e),s=T(t),[a,u]=i.toLowerCase()<s.toLowerCase()?[i,s]:[s,i],c=i.toLowerCase()===a.toLowerCase();return{poolKey:{currency0:a,currency1:u,fee:Number(r),tickSpacing:Number(n),hooks:o&&Ee(o)?T(o):H},zeroForOne:c}}async function ye(e={},t={}){let{chainId:r,quoter:n,poolManager:o,universalRouter:i}=Je(e.chainId??8453),s=yr(e.tokenIn||"WETH",r),a=yr(e.tokenOut||D[r].usdc,r),u=BigInt(e.amountIn??0);if(u<=0n)throw new Error("amountIn required (raw base units)");if(u>0xffffffffffffffffffffffffffffffffn)throw new Error("amountIn exceeds uint128");let c=e.fee!=null&&e.tickSpacing!=null?[{fee:Number(e.fee),tickSpacing:Number(e.tickSpacing)}]:e.tryTiers===!1?[{fee:500,tickSpacing:10}]:[...vr],p=e.hooks||H,d=[],l=null;for(let m of c){let{poolKey:f,zeroForOne:g}=vo({tokenIn:s,tokenOut:a,fee:m.fee,tickSpacing:m.tickSpacing,hooks:p}),h=Er.encodeFunctionData("quoteExactInputSingle",[{poolKey:f,zeroForOne:g,exactAmount:u,hookData:"0x"}]);try{let w=await k(r,"eth_call",[{to:n,data:h},"latest"],t);if(!w||w==="0x"){d.push({...m,ok:!1,error:"empty result"});continue}let v=Er.decodeFunctionResult("quoteExactInputSingle",w),C={fee:m.fee,tickSpacing:m.tickSpacing,ok:!0,amountOut:v[0].toString(),gasEstimate:v[1].toString(),poolKey:f,zeroForOne:g,poolId:xr({...f})};d.push(C),(!l||BigInt(C.amountOut)>BigInt(l.amountOut))&&(l=C)}catch(w){d.push({...m,ok:!1,error:String(w.message||w).slice(0,160)})}}if(!l){let m=d.map(f=>`${f.fee}/${f.tickSpacing}:${f.error||"fail"}`).join("; ");throw new Error(`uniswap-v4 quote failed chain=${r}: ${m}`)}return x({venue:"uniswap-v4",chainId:r,chain:D[r].name,poolManager:o,quoter:n,universalRouter:i||null,tokenIn:s,tokenOut:a,amountIn:u.toString(),fee:l.fee,tickSpacing:l.tickSpacing,hooks:l.poolKey.hooks,poolId:l.poolId,zeroForOne:l.zeroForOne,amountOut:l.amountOut,gasEstimate:l.gasEstimate,triedTiers:d,best:!0,executionReady:!1,prepareReady:typeof e.recipient=="string"&&Ee(e.recipient)&&e.slippageBps!=null},{chainId:r,venue:i||n,amountOut:l.amountOut,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps})}async function So(e={},t={}){let r=Number(e.chainId??8453),n=Je(r);if(!e.recipient)throw new Error("uniswap-v4 prepare requires recipient");let o=T(e.recipient);if(e.slippageBps==null)throw new Error("uniswap-v4 prepare requires explicit slippageBps");let i=Number(e.slippageBps);if(!Number.isInteger(i)||i<0||i>=1e4)throw new Error("slippageBps must be an integer from 0 through 9999");let s=String(e.tokenIn||"");if(!s||s===Sr||s===H||/^eth$/i.test(s))throw new Error("uniswap-v4 prepare currently requires an ERC-20 tokenIn; native input is not inferred");let a=await ye(e,t);if(!n.universalRouter)throw new Error(`uniswap-v4: no Universal Router on chain ${r}`);let u=BigInt(a.amountOut)*BigInt(1e4-i)/10000n,c={currency0:a.zeroForOne?a.tokenIn:a.tokenOut,currency1:a.zeroForOne?a.tokenOut:a.tokenIn,fee:a.fee,tickSpacing:a.tickSpacing,hooks:a.hooks},d=ne.encode(["tuple(tuple(address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks) poolKey,bool zeroForOne,uint128 amountIn,uint128 amountOutMinimum,uint256 minHopPriceX36,bytes hookData)"],[[c,a.zeroForOne,BigInt(a.amountIn),u,0n,"0x"]]),l=ne.encode(["address","uint256"],[a.tokenIn,BigInt(a.amountIn)]),m=ne.encode(["address","uint256"],[a.tokenOut,u]),f=ne.encode(["bytes","bytes[]"],[yo,[d,l,m]]),g=Math.min(600,Math.max(30,Number(e.deadlineSeconds??300))),w=Number(t.nowSeconds??Math.floor(Date.now()/1e3))+g,v=bo.encodeFunctionData("execute",[Eo,[f],w]);return S({provider:"uniswap-v4",prepareReady:!0,calldataReady:!0,executionReady:!1,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:r,deadline:w,quote:{...a,amountOutMinimum:u.toString(),slippageBps:i},requiresApproval:{token:a.tokenIn,spender:Ao,amount:a.amountIn,note:"Universal Router V4 settlement uses Permit2; Permit2 authorization for the Universal Router is also required"},transaction:{chainId:r,from:o,to:n.universalRouter,data:v,value:"0"}},{provider:"uniswap-v4",kind:"univ4-swap-tx"})}async function xo(){return Object.entries(D).map(([e,t])=>({chainId:Number(e),name:t.name,poolManager:t.poolManager,quoter:t.quoter,stateView:t.stateView||null,universalRouter:t.universalRouter||null,weth:t.weth,usdc:t.usdc}))}async function Io(e={}){let t=Je(e.chainId??8453),r=await k(t.chainId,"eth_getCode",[t.quoter,"latest"],e),n=typeof r=="string"&&r!=="0x"&&r.length>4;return{ok:n,chainId:t.chainId,quoter:t.quoter,poolManager:t.poolManager,codeBytes:n?(r.length-2)/2:0}}var ne,H,D,vr,Er,bo,Eo,yo,Ao,Sr,Ze=I(()=>{W();L();_();ne=go.defaultAbiCoder(),H="0x0000000000000000000000000000000000000000",D={1:{name:"ethereum",poolManager:"0x000000000004444c5dc75cB358380D2e3dE08A90",quoter:"0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203",stateView:"0x7ffe42c4a5deea5b0fec41c94c136cf115597227",universalRouter:"0x66a9893cc07d91d95644aedd05d03f95e1dba8af",weth:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",usdc:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},10:{name:"optimism",poolManager:"0x9a13f98cb987694c9f086b1f5eb990eea8264ec3",quoter:"0x1f3131a13296fb91c90870043742c3cdbff1a8d7",stateView:"0xc18a3169788f4f75a170290584eca6395c75ecdb",universalRouter:"0x851116d9223fabed8e56c0e6b8ad0c31d98b3507",weth:"0x4200000000000000000000000000000000000006",usdc:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"},56:{name:"bsc",poolManager:"0x28e2ea090877bf75740558f6bfb36a5ffee9e9df",quoter:"0x9f75dd27d6664c475b90e105573e550ff69437b0",stateView:"0xd13dd3d6e93f276fafc9db9e6bb47c1180aee0c4",universalRouter:"0x1906c1d672b88cd1b9ac7593301ca990f94eae07",weth:"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",usdc:"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"},137:{name:"polygon",poolManager:"0x67366782805870060151383f4bbff9dab53e5cd6",quoter:"0xb3d5c3dfc3a7aebff71895a7191796bffc2c81b9",stateView:"0x5ea1bd7974c8a611cbab0bdcafcb1d9cc9b3ba5a",universalRouter:"0x1095692a6237d83c6a72f3f5efedb9a670c49223",weth:"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",usdc:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"},8453:{name:"base",poolManager:"0x498581fF718922c3f8e6A244956aF099B2652b2b",quoter:"0x0d5e0f971ed27fbff6c2837bf31316121532048d",stateView:"0xa3c0c9b65bad0b08107aa264b0f3db444b867a71",universalRouter:"0x6ff5693b99212da76ad316178a184ab56d299b43",weth:"0x4200000000000000000000000000000000000006",usdc:"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"},42161:{name:"arbitrum",poolManager:"0x360e68faccca8ca495c1b759fd9eee466db9fb32",quoter:"0x3972c00f7ed4885e145823eb7c655375d275a1c5",stateView:"0x76fd297e2d437cd7f76d50f01afe6160f86e9990",universalRouter:"0xa51afafe0263b40edaef0df8781ea9aa03e381a3",weth:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",usdc:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831"},43114:{name:"avalanche",poolManager:"0x06380c0e0912312b5150364b9dc4542ba0dbbc85",quoter:"0xbe40675bb704506a3c2ccfb762dcfd1e979845c2",stateView:"0xc3c9e198c735a4b97e3e683f391ccbdd60b69286",universalRouter:"0x94b75331ae8d42c1b61065089b7d48fe14aa73b7",weth:"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",usdc:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"},4663:{name:"robinhood",poolManager:"0x8366a39cc670b4001a1121b8f6a443a643e40951",quoter:"0x8dc178efb8111bb0973dd9d722ebeff267c98f94",stateView:"0xf3334192d15450cdd385c8b70e03f9a6bd9e673b",universalRouter:"0x8876789976dEcBfCbBbe364623C63652db8C0904",weth:"0x0bd7d308f8e1639fab988df18a8011f41eacad73",usdc:"0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"}},vr=[{fee:100,tickSpacing:1},{fee:500,tickSpacing:10},{fee:3e3,tickSpacing:60},{fee:1e4,tickSpacing:200},{fee:25e3,tickSpacing:8}],Er=new Ar(["function quoteExactInputSingle(((address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks) poolKey,bool zeroForOne,uint128 exactAmount,bytes hookData) params) returns (uint256 amountOut, uint256 gasEstimate)"]),bo=new Ar(["function execute(bytes commands,bytes[] inputs,uint256 deadline) payable"]),Eo="0x10",yo="0x060c0f",Ao="0x000000000022D473030F116dDEE9F6B43aC78BA3",Sr="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"});var ve={};V(ve,{ACROSS_API:()=>Cr,HOP_API:()=>kr,RELAY_API:()=>Or,acrossHealth:()=>No,acrossSuggestedFees:()=>Nr,hopHealth:()=>Ro,hopQuote:()=>Rr,relayHealth:()=>_o,relayPrepare:()=>To,relayQuote:()=>et});async function No(e={}){try{return{ok:!0,estimatedFillTimeSec:(await Nr({token:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",destinationToken:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",originChainId:1,destinationChainId:42161,amount:"1000000000000000"},e)).estimatedFillTimeSec}}catch(t){return{ok:!1,error:String(t.message||t).slice(0,160)}}}async function Nr(e={},t={}){let{token:r,destinationToken:n=r,originChainId:o,destinationChainId:i,amount:s}=e;if(!r||o==null||i==null||!s)throw new Error("acrossSuggestedFees requires token, originChainId, destinationChainId, amount");let a=new URLSearchParams({token:r,destinationToken:n,originChainId:String(o),destinationChainId:String(i),amount:String(s)}),u=(t.baseUrl||process.env.ACROSS_API_URL||Cr).replace(/\/$/,"");return A(`${u}/suggested-fees?${a}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3})}async function Ro(e={}){try{let t=await Rr({amount:"1000000000000000",token:"ETH",fromChain:"ethereum",toChain:"arbitrum",slippage:.5},e);return{ok:!0,estimatedRecieved:t.estimatedRecieved||t.estimatedReceived}}catch(t){return{ok:!1,error:String(t.message||t).slice(0,160)}}}async function Rr(e={},t={}){let{amount:r,token:n="ETH",fromChain:o="ethereum",toChain:i="arbitrum"}=e;if(!r)throw new Error("hopQuote requires amount");let s=e.slippage==null?void 0:Math.round(Number(e.slippage)*100),a=U({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:o!==i,requestedCapBps:e.maxSlippageBps??e.slippageBps??s});if(!a.executable)throw new Error(`hop: route requires ${a.requiredBps} bps above cap ${a.capBps}`);let u=new URLSearchParams({amount:String(r),token:n,fromChain:o,toChain:i,slippage:String(a.selectedBps/100)}),c=(t.baseUrl||process.env.HOP_API_URL||kr).replace(/\/$/,""),p=await A(`${c}/quote?${u}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3}),d=p?.estimatedRecieved||p?.estimatedReceived;return d?x(p,{chainId:Number(e.originChainId||e.chainId||Oo[o]||0),venue:p?.tx?.to||"hop",amountOut:d,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:o!==i,requestedCapBps:e.maxSlippageBps??e.slippageBps??s}):{...p,autoSlippagePolicy:a}}async function _o(e={}){try{let t=await et({user:P,originChainId:1,destinationChainId:8453,originCurrency:"0x0000000000000000000000000000000000000000",destinationCurrency:"0x0000000000000000000000000000000000000000",amount:"1000000000000000",tradeType:"EXACT_INPUT"},e);return{ok:!0,hasSteps:Array.isArray(t.steps),stepCount:t.steps?.length||0}}catch(t){return{ok:!1,error:String(t.message||t).slice(0,160)}}}async function et(e={},t={}){let{user:r=P,originChainId:n,destinationChainId:o,originCurrency:i="0x0000000000000000000000000000000000000000",destinationCurrency:s="0x0000000000000000000000000000000000000000",amount:a,tradeType:u="EXACT_INPUT"}=e;if(n==null||o==null||!a)throw new Error("relayQuote requires originChainId, destinationChainId, amount");let c=U({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(o),requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!c.executable)throw new Error(`relay: route requires ${c.requiredBps} bps above cap ${c.capBps}`);let p=(t.baseUrl||process.env.RELAY_API_URL||Or).replace(/\/$/,""),d=await A(`${p}/quote`,{method:"POST",body:{user:r,originChainId:Number(n),destinationChainId:Number(o),originCurrency:i,destinationCurrency:s,amount:String(a),tradeType:u,slippageTolerance:String(c.selectedBps)},fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),l=d?.details?.currencyOut?.amount;return!l||!/^\d+$/.test(String(l))?{...d,autoSlippagePolicy:c}:x(d,{chainId:Number(n),venue:d?.steps?.[0]?.items?.[0]?.data?.to||"relay",amountOut:l,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(o),requestedCapBps:e.maxSlippageBps??e.slippageBps})}async function To(e={},t={}){let r=await et(e,t),n=Number(e.originChainId),o=(r.steps||[]).flatMap(a=>(a.items||[]).filter(u=>u?.data?.to&&u?.data?.data).map(u=>({stepId:a.id,...u.data})));if(!o.length)throw new Error("relay: quote returned no executable transaction items");let i=String(r?.autoSlippage?.venue||"").toLowerCase();if(o.some(a=>String(a.to).toLowerCase()!==i))throw new Error("relay: route includes a separate approval/transaction that is not yet safely bound");let s=o.map(a=>({chainId:n,from:a.from||e.user,to:a.to,data:a.data,value:a.value??"0x0",...a.gasLimit!=null||a.gas!=null?{gasLimit:a.gasLimit??a.gas}:{},slippageGuard:R(r.autoSlippage,{chainId:n,venue:a.to,data:a.data})}));return S({provider:"relay",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:n,quote:r,autoSlippage:r.autoSlippage,transactions:s},{provider:"relay",kind:"relay-tx"})}var Cr,kr,Or,Oo,Se=I(()=>{B();L();ce();_();Cr="https://across.to/api",kr="https://api.hop.exchange/v1",Or="https://api.relay.link",Oo={ethereum:1,optimism:10,bsc:56,polygon:137,arbitrum:42161,avalanche:43114,base:8453}});var ie=Object.freeze(["blockNumber","nativeBalance","tokenBalance","resolveToken","resolvePools","scanBlocks","scoreRisk","quote","sellSimulation","prepareUnsignedTx"]),E=Object.freeze({LIVE:"LIVE",CACHED:"CACHED",STALE:"STALE",UNKNOWN:"UNKNOWN",UNAVAILABLE:"UNAVAILABLE"}),b=Object.freeze({PASS:"PASS",CAUTION:"CAUTION",FAIL:"FAIL",UNKNOWN:"UNKNOWN"}),Qr=/^0x[0-9a-fA-F]{40}$/;function Jr(e={}){let t=[],r=[];if(!e||typeof e!="object")return{ok:!1,errors:["definition must be an object"],warnings:r};if((!Number.isInteger(e.chainId)||e.chainId<=0)&&t.push("chainId must be a positive integer"),(typeof e.key!="string"||!/^[a-z][a-z0-9-]*$/.test(e.key||""))&&t.push('key must be a lowercase slug (e.g. "base")'),(typeof e.name!="string"||!e.name.trim())&&t.push("name is required"),!Array.isArray(e.rpcEnv)||e.rpcEnv.length===0)t.push("rpcEnv must list at least one environment variable name");else for(let o of e.rpcEnv)(typeof o!="string"||!/^[A-Z][A-Z0-9_]*$/.test(o))&&t.push(`rpcEnv entry "${o}" should be an UPPER_SNAKE env var name`);if(e.nativeCurrency){let o=e.nativeCurrency;(typeof o.symbol!="string"||!o.symbol)&&t.push("nativeCurrency.symbol is required when nativeCurrency is set"),Number.isInteger(o.decimals)||t.push("nativeCurrency.decimals must be an integer")}for(let[o,i]of(e.venues||[]).entries()){let s=`venues[${o}]`;if(!i||typeof i!="object"){t.push(`${s} must be an object`);continue}Qr.test(i.address||"")||t.push(`${s}.address is not a valid 20-byte address`),/^0x0{40}$/.test(i.address||"")&&t.push(`${s}.address is the zero address -- placeholder left in place?`),i.kind||t.push(`${s}.kind is required (router|quoter|factory|...)`),i.verified?(i.verified.method||t.push(`${s}.verified.method is required`),i.verified.source||t.push(`${s}.verified.source is required`),i.verified.date||r.push(`${s}.verified.date missing -- add one so staleness is visible`)):t.push(`${s} must record verification: { verified: { method, source, date } }. An unverified venue stays blocked.`)}let n=e.capabilities||{};for(let o of Object.keys(n))ie.includes(o)?typeof n[o]!="function"&&t.push(`capability "${o}" must be a function`):t.push(`unknown capability "${o}"`);return Object.keys(n).length===0&&r.push("scanner implements no capabilities -- it can only be registered, not used"),n.prepareUnsignedTx&&!n.quote&&r.push("prepareUnsignedTx without quote: no priced expectation to validate the built tx against"),n.prepareUnsignedTx&&!n.sellSimulation&&r.push("prepareUnsignedTx without sellSimulation: cannot prove an asset is exitable before buying"),{ok:t.length===0,errors:t,warnings:r}}function Zr(e){let{ok:t,errors:r,warnings:n}=Jr(e);if(!t)throw new Error(`invalid scanner for ${e?.key??"<unknown>"}:
4
+ - ${r.join(`
5
+ - `)}`);let o=e.capabilities||{},i=ie.filter(a=>typeof o[a]=="function"),s={key:e.key,chainId:e.chainId,name:e.name,rpcEnv:[...e.rpcEnv],nativeCurrency:e.nativeCurrency?{...e.nativeCurrency}:null,explorer:e.explorer||null,venues:(e.venues||[]).map(a=>({...a})),warnings:n,capabilities(){return{chainId:e.chainId,key:e.key,supported:[...i],unsupported:ie.filter(a=>!i.includes(a))}},supports(a){return i.includes(a)}};for(let a of ie)i.includes(a)?s[a]=async(...u)=>o[a](...u,{scanner:s}):s[a]=async()=>{throw new Error(`${e.key} (chain ${e.chainId}) does not implement "${a}". Supported: ${i.join(", ")||"none"}. An unimplemented capability is absent, not assumed -- implement it or treat this chain as fail-closed for that operation.`)};return Object.freeze(s)}var Re=new Map;function dt(e){let t=Zr(e);return Re.set(t.chainId,t),t}function se(e){return Re.get(Number(e))||null}function _e(){return[...Re.values()]}var $=Object.freeze({FULL:"FULL",NO_GAS:"NO_GAS",FAILED:"FAILED"}),mt={1:"coingecko:ethereum",10:"coingecko:ethereum",56:"coingecko:binancecoin",137:"coingecko:matic-network",8453:"coingecko:ethereum",42161:"coingecko:ethereum",43114:"coingecko:avalanche-2",999:"coingecko:ethereum"},Q=e=>{try{return e==null||e===""?null:BigInt(String(e).split(".")[0])}catch{return null}};function pt(e){let{source:t,amountOut:r,minOut:n=null,gasUsd:o=null,feeUsd:i=null,estimatedGas:s=null,error:a=null,executionReady:u=!1,meta:c={}}=e||{};if(a||r==null)return{source:t,quality:$.FAILED,amountOut:null,error:a||"no amountOut returned"};let p=Q(r);return p==null||p<=0n?{source:t,quality:$.FAILED,amountOut:null,error:"non-positive amountOut"}:{source:t,quality:o==null?$.NO_GAS:$.FULL,amountOut:p.toString(),minOut:Q(n)?.toString()??null,gasUsd:o,feeUsd:i,estimatedGas:s==null?null:String(s),executionReady:u,meta:c}}async function ft(e,t,{divisor:r=1000n}={}){let n=Q(t);if(n==null||n<=0n)return null;let o=n/r>0n?n/r:1n;if(o>=n)return null;let i,s;try{[i,s]=await Promise.all([e(o),e(n)])}catch{return null}let a=Q(i),u=Q(s);if(a==null||u==null||a<=0n)return null;let c=Number(a)/Number(o),p=Number(u)/Number(n);return!Number.isFinite(c)||!Number.isFinite(p)||c<=0?null:{impactPct:(1-p/c)*100,probeAmountIn:o.toString(),probeAmountOut:a.toString(),fullAmountOut:u.toString()}}function ht(e,t,{maxImpactPct:r=25}={}){let n=[],o=[],i=(e.routes??[]).filter(a=>{let u=t?.[a.source];return u?u.impactPct>r?(n.push({source:a.source,impactPct:Number(u.impactPct.toFixed(2)),reason:`price impact ${u.impactPct.toFixed(1)}% exceeds ${r}% ceiling -- the venue cannot absorb this size near the quoted price`}),!1):!0:(o.push(a.source),!0)}),s=[...e.warnings??[]];return n.length&&s.push(`dropped ${n.length} route(s) on price impact: `+n.map(a=>`${a.source} (${a.impactPct}%)`).join(", ")),o.length&&s.push(`price impact NOT measured for: ${o.join(", ")}. These are unproven against thin liquidity, not proven safe.`),{...e,routes:i,best:i[0]??null,impactRejected:n,impactUnmeasured:o,warnings:s}}function Te(e,{destPriceUsd:t=null,destDecimals:r=null}={}){let n=e.filter(d=>d.quality!==$.FAILED),o=e.filter(d=>d.quality===$.FAILED),i=t!=null&&t>0&&r!=null&&r>=0,s=n.map(d=>{let l=BigInt(d.amountOut),m=0n,f=!1;if(i){let h=(d.gasUsd??0)+(d.feeUsd??0);if(h>0){let w=h/t*10**r;Number.isFinite(w)&&w>=0&&(m=BigInt(Math.floor(w)),f=!0)}else d.gasUsd===0&&(f=!0)}let g=l>m?l-m:0n;return{...d,grossOut:l.toString(),netOut:g.toString(),costInDest:m.toString(),costAccounted:f}});s.sort((d,l)=>BigInt(l.netOut)>BigInt(d.netOut)?1:-1);let a=s.filter(d=>!d.costAccounted).map(d=>d.source),u=[];i?a.length&&u.push(`gas not reported by: ${a.join(", ")}. These are ranked on gross output and may be overstated relative to gas-measured routes.`):u.push("destination price/decimals unavailable: ranked on GROSS output. Gas is not included, so a cheap-looking route may cost more to execute.");let c=null,p=null;if(s.length>=2&&s[0].costAccounted&&s[1].costAccounted){let d=BigInt(s[0].netOut),l=BigInt(s[1].netOut);l>0n&&(c=Number((d-l)*10000n/l),p=`${s[0].source} vs ${s[1].source}`)}return{best:s[0]??null,routes:s,failed:o,improvementBps:c,spreadBasis:p,rankedOn:i?"net-of-cost":"gross",warnings:u}}async function ue(e,{timeoutMs:t=12e3}={}){let r=(o,i)=>Promise.race([o,new Promise((s,a)=>setTimeout(()=>a(new Error(`${i}: timeout`)),t))]);return(await Promise.allSettled(e.map(o=>r(Promise.resolve().then(o.run),o.source)))).map((o,i)=>{let s=e[i].source;return o.status==="rejected"?pt({source:s,error:String(o.reason?.message||o.reason)}):pt({source:s,...o.value})})}le();Ve();je();B();L();He();_();var Pn="https://api.1inch.dev/swap/v6.0";function Ht(e={}){return pe({provider:"oneinch",defaultUrl:Pn,hosts:["api.1inch.dev"],url:e.baseUrl||process.env.ONEINCH_API_URL})}function Fn(e={}){return Ht(e).baseUrl}function jt(e={}){return e.apiKey||process.env.ONEINCH_API_KEY||process.env.ONE_INCH_API_KEY||""}function qn(e={}){let t=jt(e);return me({accept:"application/json"},{Authorization:t?`Bearer ${t}`:""},Ht(e).trusted)}async function Kt(e={},t={}){if(!jt(t))throw new Error("ONEINCH_API_KEY required for 1inch");let r=Number(e.chainId??1),{src:n,dst:o,amount:i}=e;if(!n||!o||!i)throw new Error("oneinchQuote requires src, dst, amount");let s=new URLSearchParams({src:n,dst:o,amount:String(i)}),a=await A(`${Fn(t)}/${r}/quote?${s}`,{headers:qn(t),fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3});return a?.dstAmount?x(a,{chainId:r,venue:"1inch-quote",amountOut:a.dstAmount,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,requestedCapBps:e.maxSlippageBps??e.slippageBps}):a}Ge();Qe();Ze();B();var Co="https://coins.llama.fi";function ko(e={}){return(e.baseUrl||process.env.DEFILLAMA_COINS_URL||Co).replace(/\/$/,"")}async function Ae(e,t={}){if(!Array.isArray(e)||!e.length)throw new Error("llamaPrices requires coins[]");let r=e.map(encodeURIComponent).join(",");return A(`${ko(t)}/prices/current/${r}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}var q=e=>{let t=Number(e);return Number.isFinite(t)?t:null};function xe(e){if(!Array.isArray(e))return null;let t=0,r=!1;for(let n of e){let o=q(n?.amountUSD);o!=null&&(t+=o,r=!0)}return r?t:null}async function _r(e,t={}){let r=mt[Number(e)];if(!r)return null;try{let n=await Ae([r],t);return q(n?.coins?.[r]?.price)}catch{return null}}function tt({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o,slippageBps:i,decimalsIn:s,decimalsOut:a,nativePriceUsd:u=null,destDecimalsPromise:c=null,opts:p={}}){let d=[];return d.push({source:"lifi",run:async()=>{let l=await J({fromChain:e,toChain:e,fromToken:t,toToken:r,fromAmount:n},p),m=l?.estimate??l?.[0]?.estimate;return{amountOut:m?.toAmount,minOut:m?.toAmountMin,gasUsd:xe(m?.gasCosts),feeUsd:xe(m?.feeCosts),meta:{tool:l?.tool??l?.toolDetails?.name}}}}),s!=null&&d.push({source:"paraswap",run:async()=>{let l=a??(await Promise.resolve(c))?.decimals;if(l==null)throw new Error("paraswap needs destination decimals; none supplied or resolvable");let f=(await de({chainId:e,srcToken:t,destToken:r,amount:n,srcDecimals:s,destDecimals:l},p))?.priceRoute;return{amountOut:f?.destAmount,gasUsd:q(f?.gasCostUSD),meta:{bestRoute:f?.bestRoute?.[0]?.swaps?.[0]?.swapExchanges?.[0]?.exchange}}}}),process.env.ZEROX_API_KEY&&d.push({source:"0x",run:async()=>{let l=await he({chainId:e,sellToken:t,buyToken:r,sellAmount:n,taker:o},p),m=null,f=l?.totalNetworkFee,g=await Promise.resolve(u);return f!=null&&g&&(m=Number(f)/1e18*g),{amountOut:l?.buyAmount,minOut:l?.minBuyAmount,gasUsd:m,meta:{source:l?.route?.fills?.[0]?.source}}}}),process.env.ONEINCH_API_KEY&&d.push({source:"1inch",run:async()=>{let l=await Kt({chainId:e,src:t,dst:r,amount:n},p),m=null;return l?.gas!=null&&u&&(m=null),{amountOut:l?.dstAmount,gasUsd:m,meta:{gasUnits:l?.gas}}}}),d.push({source:"cow",run:async()=>{let l=await ee({chainId:e,sellToken:t,buyToken:r,sellAmountBeforeFee:String(n),from:o},p),m=l?.quote??l,f=m?.feeAmount;return{amountOut:m?.buyAmount,gasUsd:0,meta:{intent:!0,feeAmountInSellToken:f,settlement:"solver-executed"}}}}),O[Number(e)]&&d.push({source:"uniswap-v3",run:async()=>{let l=await re({chainId:e,tokenIn:t,tokenOut:r,amountIn:n},p);return{amountOut:l?.amountOut,minOut:l?.minOut??l?.amountOutMinimum??null,gasUsd:null,meta:{onchain:!0,fee:l?.fee,gasUnits:l?.gasEstimate,quoter:l?.quoter}}}}),D[Number(e)]&&d.push({source:"uniswap-v4",run:async()=>{let l=await ye({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,recipient:o,slippageBps:i},p);return{amountOut:l?.amountOut,minOut:l?.minOut??l?.amountOutMinimum??null,gasUsd:null,meta:{onchain:!0,venue:"uniswap-v4",fee:l?.fee,tickSpacing:l?.tickSpacing,poolId:l?.poolId,hooks:l?.hooks,gasUnits:l?.gasEstimate,quoter:l?.quoter,poolManager:l?.poolManager,prepareReady:l?.prepareReady===!0,executionReady:!1}}}}),d}function Tr({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:o,taker:i,opts:s={}}){let a=[];return a.push({source:"lifi",run:async()=>{let u=await J({fromChain:e,toChain:t,fromToken:r,toToken:n,fromAmount:o},s),c=u?.estimate??u?.[0]?.estimate;return{amountOut:c?.toAmount,minOut:c?.toAmountMin,gasUsd:xe(c?.gasCosts),feeUsd:xe(c?.feeCosts),meta:{tool:u?.tool??u?.toolDetails?.name,durationSeconds:q(c?.executionDuration)}}}}),a.push({source:"relay",run:async()=>{let{relayQuote:u}=await Promise.resolve().then(()=>(Se(),ve)),p=(await u({user:i,originChainId:e,destinationChainId:t,originCurrency:r,destinationCurrency:n,amount:String(o)},s))?.details;return{amountOut:p?.currencyOut?.amount,minOut:p?.currencyOut?.minimumAmount,gasUsd:q(p?.totalImpact?.usd)!=null?Math.abs(q(p.totalImpact.usd)):null,meta:{durationSeconds:q(p?.timeEstimate),rate:p?.rate}}}}),a.push({source:"across",run:async()=>{let{acrossSuggestedFees:u}=await Promise.resolve().then(()=>(Se(),ve)),c=await u({token:r,destinationToken:n,originChainId:e,destinationChainId:t,amount:String(o)},s),p=c?.totalRelayFee?.total,d=null;if(p!=null)try{let l=BigInt(String(o))-BigInt(String(p));l>0n&&(d=l.toString())}catch{}return{amountOut:d,gasUsd:null,meta:{derivedFromFees:!0,durationSeconds:q(c?.estimatedFillTimeSec),limits:c?.limits?{min:c.limits.minDeposit,max:c.limits.maxDeposit}:void 0}}}}),a}var Bo={1:"ethereum",10:"optimism",56:"bsc",137:"polygon",8453:"base",42161:"arbitrum",43114:"avax"};async function Br(e,t,r){let n=Bo[Number(e)];if(!n)return{priceUsd:null,decimals:null};let o=`${n}:${t}`;try{let s=(await Ae([o],r))?.coins?.[o],a=Number(s?.price),u=Number(s?.decimals);return{priceUsd:Number.isFinite(a)?a:null,decimals:Number.isFinite(u)?u:null}}catch{return{priceUsd:null,decimals:null}}}async function Ie(e,t={}){let{chainId:r,tokenIn:n,tokenOut:o,amountIn:i}=e;if(r==null||!n||!o||i==null)throw new Error("bestSwapRoute requires chainId, tokenIn, tokenOut, amountIn");let s=_r(r,t),a=Br(r,o,t),u=tt({...e,nativePriceUsd:s,decimalsOut:e.decimalsOut,destDecimalsPromise:a,opts:t}),[c,p]=await Promise.all([ue(u,{timeoutMs:t.timeoutMs??12e3}),a]);s.catch(()=>{});let d=Te(c,{destPriceUsd:p.priceUsd,destDecimals:e.decimalsOut??p.decimals}),l=t.maxImpactPct===void 0?25:t.maxImpactPct;if(l!=null&&d.best){let m=d.best.source,g=await ft(async h=>{let w=tt({...e,amountIn:h.toString(),nativePriceUsd:s,decimalsOut:e.decimalsOut,destDecimalsPromise:a,opts:t}).filter(C=>C.source===m);return w.length?(await ue(w,{timeoutMs:t.timeoutMs??12e3}))?.[0]?.amountOut??null:null},i);if(g){let h=ht(d,{[m]:g},{maxImpactPct:l});return{kind:"swap",chainId:r,tokenIn:n,tokenOut:o,amountIn:String(i),...h,priceImpact:{[m]:Number(g.impactPct.toFixed(2))}}}}return{kind:"swap",chainId:r,tokenIn:n,tokenOut:o,amountIn:String(i),...d,sourcesTried:u.length,sourcesAnswered:c.filter(m=>m.quality!==$.FAILED).length,note:$r(d,u.length)}}async function Ce(e,t={}){let{fromChainId:r,toChainId:n,tokenIn:o,tokenOut:i,amountIn:s}=e;if(r==null||n==null||!o||!i||s==null)throw new Error("bestBridgeRoute requires fromChainId, toChainId, tokenIn, tokenOut, amountIn");if(Number(r)===Number(n))throw new Error("bestBridgeRoute is for cross-chain; use bestSwapRoute for same-chain");let a=Br(n,i,t),u=Tr({...e,opts:t}),[c,p]=await Promise.all([ue(u,{timeoutMs:t.timeoutMs??15e3}),a]),d=Te(c,{destPriceUsd:p.priceUsd,destDecimals:e.decimalsOut??p.decimals}),l=d.routes.map(m=>({source:m.source,seconds:m.meta?.durationSeconds??null})).filter(m=>m.seconds!=null);return{kind:"bridge",fromChainId:r,toChainId:n,tokenIn:o,tokenOut:i,amountIn:String(s),...d,durations:l,sourcesTried:u.length,sourcesAnswered:c.filter(m=>m.quality!==$.FAILED).length,note:$r(d,u.length)}}function $r(e,t){if(!e.best)return"no source returned a usable route";let r=e.routes.length;return r===1?`only 1 of ${t} sources answered, so this is the ONLY route, not a proven best one. Treat it as unbenchmarked.`:e.improvementBps!=null?`best of ${r} routes, ranked on ${e.rankedOn}: ${(e.improvementBps/100).toFixed(2)}% better than the runner-up (${e.spreadBasis})`:`best of ${r} routes, ranked on ${e.rankedOn}. No spread quoted: the top routes report cost differently, so the margin is not comparable.`}_();var M=Object.freeze({TRANSACTION:"unsigned-transaction",TYPED_DATA_ORDER:"typed-data-order"}),$o=100,rt={"uniswap-v3":async({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o},i)=>{let{uniV3PrepareExactIn:s}=await Promise.resolve().then(()=>(Qe(),br)),a=await s({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,recipient:o},i);return{artifactKind:M.TRANSACTION,transaction:a.transaction,requiresApproval:a.requiresApproval??null,amountOut:a.quote?.amountOut??null,minOut:a.quote?.amountOutMinimum??null}},"uniswap-v4":async({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o,slippageBps:i,fee:s,tickSpacing:a,hooks:u},c)=>{let{uniV4PrepareExactIn:p}=await Promise.resolve().then(()=>(Ze(),Ir)),d=await p({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,recipient:o,slippageBps:i,fee:s,tickSpacing:a,hooks:u},c);return{artifactKind:M.TRANSACTION,transaction:d.transaction,requiresApproval:d.requiresApproval,amountOut:d.quote?.amountOut??null,minOut:d.quote?.amountOutMinimum??null,prepareReady:!0,executionReady:!1}},lifi:async({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o},i)=>{let{lifiPrepare:s}=await Promise.resolve().then(()=>(le(),qe)),a=await s({fromChain:e,toChain:e,fromToken:t,toToken:r,fromAmount:n,fromAddress:o},i);return{artifactKind:M.TRANSACTION,transaction:a.transaction,requiresApproval:a.requiresApproval??null,amountOut:a.quote?.estimate?.toAmount??null,minOut:a.quote?.estimate?.toAmountMin??null}},paraswap:async({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o,decimalsIn:i,decimalsOut:s},a)=>{let{paraswapPrepare:u}=await Promise.resolve().then(()=>(Ve(),$t)),c=await u({chainId:e,srcToken:t,destToken:r,amount:n,srcDecimals:i,destDecimals:s,userAddress:o,side:"SELL"},a);return{artifactKind:M.TRANSACTION,transaction:c.transaction,requiresApproval:c.requiresApproval??null,amountOut:c.quote?.priceRoute?.destAmount??null,minOut:c.quote?.amountOutMinimum??null}},"0x":async({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o},i)=>{let{zeroxPrepare:s}=await Promise.resolve().then(()=>(je(),Vt)),a=await s({chainId:e,sellToken:t,buyToken:r,sellAmount:n,taker:o},i);return{artifactKind:M.TRANSACTION,transaction:a.transaction,requiresApproval:a.requiresApproval??null,amountOut:a.quote?.buyAmount??null,minOut:a.quote?.minBuyAmount??null}},cow:async({chainId:e,tokenIn:t,tokenOut:r,amountIn:n,taker:o},i)=>{let{cowPrepareOrder:s}=await Promise.resolve().then(()=>(Ge(),rr)),a=await s({chainId:e,sellToken:t,buyToken:r,sellAmountBeforeFee:String(n),from:o},i);return{artifactKind:M.TYPED_DATA_ORDER,typedData:a.typedData,requiresApproval:{token:t,spender:a.vaultRelayer,amount:String(n),note:"CoW pulls funds via the vault relayer, not the settlement contract"},settlement:a.settlement,amountOut:a.quote?.quote?.buyAmount??null,minOut:null,submission:"sign the typed data, then submit the order to the CoW API"}}};var Uo=new Set(["0x0000000000000000000000000000000000000000","0x000000000000000000000000000000000000dead","0x0000000000000000000000000000000000000001","0x00000000000000000000000000000000000a1ce5"].map(e=>e.toLowerCase())),Lo=/^0x[0-9a-fA-F]{40}$/;async function Ur(e,t={}){let{taker:r}=e;if(!r)throw new Error("prepareBestRoute requires taker: a prepared transaction is built FOR an address, and the quote-only placeholder must never end up in one");if(!Lo.test(r))throw new Error(`taker must be a valid 20-byte address, got "${r}"`);if(Uo.has(r.toLowerCase()))throw new Error(`taker "${r}" is a placeholder/burn address. It is valid for quoting but not for preparing -- that would build a transaction for an address nobody controls. Pass the real wallet that will sign.`);let n=await Ie(e,t);if(!n.best){let l=n.impactRejected??[];return{ok:!1,reason:l.length?l[0].reason:"no source returned a usable route",priceImpactBlocked:l.length>0,impactRejected:l,comparison:n}}let o=e.source||n.best.source,i=n.routes.find(l=>l.source===o);if(!i)return{ok:!1,reason:`source "${o}" did not return a usable route`,comparison:n};let s=rt[o];if(!s){let l=n.routes.find(m=>rt[m.source]&&m.source!==o);return{ok:!1,reason:`${o} won the comparison but has no prepare path in this build. `+(l?`Next preparable route is ${l.source}; pass source:"${l.source}" to use it.`:"No route in this comparison can be prepared."),comparison:n,winner:o}}let a;try{a=await s(e,t)}catch(l){let m=typeof l?.body=="string"?l.body:l?.body?JSON.stringify(l.body):"",f=[String(l?.message||l),m].filter(Boolean).join(" :: "),g=/allowance/i.test(f),h=!g&&/not enough|insufficient|balance/i.test(f),w,v;g?(v="approval-required-first",w=`${o} will not build swap calldata until the token approval exists on-chain. Approve the spender first, then prepare again. Underlying: ${f}`):h?(v="taker-not-funded",w=`${o} refused to build the transaction: ${f}. This venue verifies the taker holds the input token. Quoting works for any address; preparing needs the real funded wallet.`):(v="provider-error",w=`${o} prepare failed: ${f}`);let C=n.routes.find(Y=>rt[Y.source]&&Y.source!==o);return{ok:!1,reason:w,failureKind:v,...C?{alternative:C.source}:{},comparison:n}}let u=e.driftToleranceBps??$o,c=null,p=null;if(a.amountOut!=null&&i.grossOut!=null)try{let l=BigInt(i.grossOut),m=BigInt(a.amountOut);l>0n&&(c=Number((m-l)*10000n/l),c<-u&&(p=`route moved ${(c/100).toFixed(2)}% against you between the comparison and this prepare (tolerance ${(u/100).toFixed(2)}%). The ranking may no longer hold -- re-run the comparison before signing.`))}catch{}let d=n.routes.filter(l=>l.source!==o).map(l=>({source:l.source,netOut:l.netOut,gasUsd:l.gasUsd}));return S({ok:!0,chosen:{source:o,wasWinner:o===n.best.source,netOut:i.netOut,grossOut:i.grossOut,gasUsd:i.gasUsd},priceImpact:n.priceImpact??null,impactUnmeasured:n.impactUnmeasured??[],...a,unsigned:!0,signedBy:"user-wallet",destination:a.artifactKind===M.TRANSACTION?a.transaction?.to??null:a.settlement??null,driftBps:c,warnings:[...p?[p]:[],...n.warnings||[],...a.artifactKind===M.TYPED_DATA_ORDER?["This is an ORDER to sign, not a transaction to broadcast. Signing it authorizes a solver to settle on your behalf."]:[]],runnersUp:d,comparison:{rankedOn:n.rankedOn,sourcesAnswered:n.sourcesAnswered,sourcesTried:n.sourcesTried,improvementBps:n.improvementBps},note:"UNSIGNED. Verify the destination address and minOut against a fresh quote immediately before signing -- a quote-time minimum is not a minimum at broadcast time."},{provider:"router",kind:"best-route"})}_();var Do=/^0x[0-9a-fA-F]{40}$/,Po=new Set(["0x0000000000000000000000000000000000000000","0x000000000000000000000000000000000000dead","0x0000000000000000000000000000000000000001","0x00000000000000000000000000000000000a1ce5"].map(e=>e.toLowerCase())),Fo=100,nt={relay:async({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:o,taker:i},s)=>{let{relayPrepare:a}=await Promise.resolve().then(()=>(Se(),ve)),u=await a({user:i,originChainId:e,destinationChainId:t,originCurrency:r,destinationCurrency:n,amount:String(o)},s);return{transactions:u.transactions||[],amountOut:u.quote?.details?.currencyOut?.amount??null,minOut:u.quote?.details?.currencyOut?.minimumAmount??null,durationSeconds:u.quote?.details?.timeEstimate??null}},lifi:async({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:o,taker:i},s)=>{let{lifiPrepare:a}=await Promise.resolve().then(()=>(le(),qe)),u=await a({fromChain:e,toChain:t,fromToken:r,toToken:n,fromAmount:o,fromAddress:i},s);return{transactions:u.transaction?[u.transaction]:[],requiresApproval:u.requiresApproval??null,amountOut:u.quote?.estimate?.toAmount??null,minOut:u.quote?.estimate?.toAmountMin??null,durationSeconds:u.quote?.estimate?.executionDuration??null}}};async function Lr(e,t={}){let{taker:r,fromChainId:n,toChainId:o}=e;if(!r)throw new Error("prepareBestBridgeRoute requires taker: bridge transactions are built FOR an address, and the quote-only placeholder must never end up in one");if(!Do.test(r))throw new Error(`taker must be a valid 20-byte address, got "${r}"`);if(Po.has(r.toLowerCase()))throw new Error(`taker "${r}" is a placeholder/burn address. Bridging to it would send funds to an address nobody controls, on a chain where you cannot undo it.`);let i=await Ce(e,t);if(!i.best)return{ok:!1,reason:"no source returned a usable bridge route",comparison:i};let s=e.source||i.best.source,a=i.routes.find(h=>h.source===s);if(!a)return{ok:!1,reason:`source "${s}" returned no usable route`,comparison:i};let u=nt[s];if(!u){let h=i.routes.find(w=>nt[w.source]&&w.source!==s);return{ok:!1,reason:`${s} won the comparison but has no bridge prepare path in this build. `+(h?`Next preparable route is ${h.source}; pass source:"${h.source}".`:"No route in this comparison can be prepared."),failureKind:"no-prepare-path",...h?{alternative:h.source}:{},winner:s,comparison:i}}let c;try{c=await u(e,t)}catch(h){let w=typeof h?.body=="string"?h.body:h?.body?JSON.stringify(h.body):"",v=[String(h?.message||h),w].filter(Boolean).join(" :: "),C=/allowance/i.test(v),Y=!C&&/not enough|insufficient|balance/i.test(v),ct=i.routes.find(lt=>nt[lt.source]&&lt.source!==s);return{ok:!1,reason:C?`${s} will not build calldata until the token approval exists on-chain. Approve first, then prepare again. Underlying: ${v}`:Y?`${s} refused to build: ${v}. Quoting works for any address; preparing needs the real funded wallet on chain ${n}.`:`${s} bridge prepare failed: ${v}`,failureKind:C?"approval-required-first":Y?"taker-not-funded":"provider-error",...ct?{alternative:ct.source}:{},comparison:i}}let p=c.transactions||[];if(!p.length)return{ok:!1,reason:`${s} returned no executable transaction for this route`,failureKind:"provider-error",comparison:i};let d=p.filter(h=>h.chainId!=null&&Number(h.chainId)!==Number(n));if(d.length)return{ok:!1,reason:`${s} returned a transaction for chain ${d[0].chainId} but the origin chain is ${n}. Refusing to hand over a mismatched artifact.`,failureKind:"chain-mismatch",comparison:i};let l=e.driftToleranceBps??Fo,m=null,f=null;if(c.amountOut!=null&&a.grossOut!=null)try{let h=BigInt(a.grossOut),w=BigInt(c.amountOut);h>0n&&(m=Number((w-h)*10000n/h),m<-l&&(f=`route moved ${(m/100).toFixed(2)}% against you since the comparison (tolerance ${(l/100).toFixed(2)}%). Re-compare before signing.`))}catch{}let g=[...f?[f]:[],...i.warnings||[],`Bridging is NOT atomic: the origin transaction succeeding does not mean funds arrived on chain ${o}. Expect ~${c.durationSeconds!=null?`${c.durationSeconds}s`:"minutes"} before the destination credits, and do not re-send if it is pending.`];return p.length>1&&g.push(`This route needs ${p.length} transactions signed IN ORDER. Signing only the first leaves funds approved but not bridged.`),S({ok:!0,chosen:{source:s,wasWinner:s===i.best.source,netOut:a.netOut,grossOut:a.grossOut,gasUsd:a.gasUsd},artifactKind:"unsigned-transaction-sequence",fromChainId:Number(n),toChainId:Number(o),transactionCount:p.length,transactions:p,requiresApproval:c.requiresApproval??null,minOut:c.minOut??null,durationSeconds:c.durationSeconds??null,destination:p[0]?.to??null,unsigned:!0,signedBy:"user-wallet",driftBps:m,warnings:g,runnersUp:i.routes.filter(h=>h.source!==s).map(h=>({source:h.source,netOut:h.netOut,gasUsd:h.gasUsd})),comparison:{rankedOn:i.rankedOn,sourcesAnswered:i.sourcesAnswered,sourcesTried:i.sourcesTried,improvementBps:i.improvementBps},note:`UNSIGNED. ${p.length} transaction(s) on chain ${n}, crediting chain ${o}. Verify every destination address before signing.`},{provider:"router",kind:"best-bridge"})}W();B();var qo="https://api.dexscreener.com";function Mo(e={}){return(e.baseUrl||process.env.DEXSCREENER_API_URL||qo).replace(/\/$/,"")}async function Dr(e,t={}){if(!e)throw new Error("tokenAddress required");return A(`${Mo(t)}/latest/dex/tokens/${e}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??12e3})}W();var at={getAmountsOut:"d06ca61f",swapExactTokensForTokens:"38ed1739",swapExactETHForTokens:"7ff36ab5"},N=e=>BigInt(e).toString(16).padStart(64,"0"),oe=e=>e.slice(2).toLowerCase().padStart(64,"0");function Vo(e,t){return`0x${at.getAmountsOut}`+N(e)+N(64)+N(t.length)+t.map(oe).join("")}function Ho(e){if(!e||e==="0x")return null;let t=e.slice(2);if(t.length<128)return null;let r=Number(BigInt(`0x${t.slice(64,128)}`));if(!Number.isFinite(r)||r<1||r>16)return null;let n=[];for(let o=0;o<r;o++){let i=128+o*64;if(t.length<i+64)return null;n.push(BigInt(`0x${t.slice(i,i+64)}`))}return n}function ot(e,t="router"){return(e?.venues||[]).find(n=>n.kind===t)?.address??null}var it=100;function jo(e,t){let r=Number(t);if(!Number.isFinite(r)||r<0)throw new Error("slippageBps must be a non-negative number");if(r>it)throw new Error(`slippageBps ${r} exceeds the ${it} bps ceiling. Block and requote or split the order -- do not widen the guard to force a fill.`);return BigInt(e)*BigInt(1e4-Math.floor(r))/10000n}function Pr(e){let{chainId:t,wrappedNative:r}=e;async function n(o,i,s,a){let u=await k(t,"eth_call",[{to:o,data:Vo(i,s)},"latest"],a);return Ho(u?.result??u)}return{async quote({tokenIn:o,tokenOut:i,amountIn:s,path:a},u={}){let c=ot(u.scanner);if(!c)return{chainId:t,evidence:E.UNAVAILABLE,reason:"no verified router configured for this chain; quoting stays fail-closed rather than guessing a venue address"};let p=a||[o,i];if(p.some(l=>!/^0x[0-9a-fA-F]{40}$/.test(l||"")))throw new Error("quote requires valid 20-byte addresses");let d=await n(c,s,p,u);return d?{chainId:t,router:c,path:p,amountIn:String(s),amountOut:d[d.length-1].toString(),hops:p.length-1,evidence:E.LIVE,note:"exact-input quote at current reserves; not a guaranteed fill"}:{chainId:t,router:c,path:p,evidence:E.UNKNOWN,reason:"router returned no amounts -- no pool for this path, or the call reverted"}},async sellSimulation({token:o,amountIn:i,base:s},a={}){let u=ot(a.scanner),c=s||r;if(!u||!c)return{chainId:t,token:o,verdict:b.UNKNOWN,evidence:E.UNAVAILABLE,reason:u?"no wrappedNative configured for this chain, so no base asset to round-trip against":"no verified router configured for this chain"};let p=await n(u,i,[c,o],a);if(!p)return{chainId:t,token:o,verdict:b.FAIL,evidence:E.LIVE,leg:"buy",reason:"buy leg returned no amounts -- no route in"};let d=p[p.length-1];if(d===0n)return{chainId:t,token:o,verdict:b.FAIL,evidence:E.LIVE,leg:"buy",reason:"buy leg quotes zero output"};let l=await n(u,d,[o,c],a);if(!l)return{chainId:t,token:o,verdict:b.FAIL,evidence:E.LIVE,leg:"sell",bought:d.toString(),reason:"SELL LEG FAILED while the buy leg quoted fine. This is the honeypot signature: do not trade."};let m=l[l.length-1],f=Number(m*10000n/BigInt(i)),g=b.PASS,h="round trip completes with expected fee/impact loss";return f<5e3?(g=b.FAIL,h=`round trip returns only ${(f/100).toFixed(2)}% -- punitive tax or no real liquidity`):f<9e3&&(g=b.CAUTION,h=`round trip returns ${(f/100).toFixed(2)}% -- transfer tax or thin liquidity at this size`),{chainId:t,token:o,base:c,router:u,verdict:g,reason:h,amountIn:String(i),bought:d.toString(),returned:m.toString(),retentionBps:f,evidence:E.LIVE,note:"Quote-level round trip. It does not prove transfer hooks absent at execution time."}},async prepareUnsignedTx({tokenIn:o,tokenOut:i,amountIn:s,recipient:a,slippageBps:u=50,deadlineSeconds:c=900,path:p},d={}){let l=d.scanner,m=ot(l);if(!m)throw new Error(`chain ${t} has no verified router; preparing a swap stays fail-closed. Add a venue with recorded provenance first (see docs/adding-a-chain.md).`);if(!/^0x[0-9a-fA-F]{40}$/.test(a||""))throw new Error("prepareUnsignedTx requires a valid recipient address");let f=p||[o,i],g=await this.quote({tokenIn:o,tokenOut:i,amountIn:s,path:f},d);if(g.evidence!==E.LIVE)throw new Error(`cannot prepare without a live quote (${g.evidence}: ${g.reason??"no reason given"})`);let h=jo(g.amountOut,u);if(h<=0n)throw new Error("computed minOut is zero -- refusing to prepare");let w=BigInt(Math.floor(Date.now()/1e3)+Number(c)),v=r&&f[0].toLowerCase()===r.toLowerCase()&&d.useNative,C=v?`0x${at.swapExactETHForTokens}`+N(h)+N(128)+oe(a)+N(w)+N(f.length)+f.map(oe).join(""):`0x${at.swapExactTokensForTokens}`+N(s)+N(h)+N(160)+oe(a)+N(w)+N(f.length)+f.map(oe).join("");return{unsigned:!0,signedBy:"user-wallet",chainId:t,tx:{to:m,data:C,value:v?`0x${BigInt(s).toString(16)}`:"0x0"},guard:{quotedOut:g.amountOut,minOut:h.toString(),slippageBps:u,maxSlippageBps:it,deadline:w.toString()},requires:v?[]:[{step:"approve",token:f[0],spender:m,amount:String(s)}],note:"UNSIGNED. Re-verify the guard against a fresh quote immediately before signing -- a quote-time minimum is not a minimum at broadcast time."}}}}W();var Ko=[100,500,3e3,1e4],Fr={quoteExactInputSingle:"c6a5026a",exactInputSingle:"04e45aaf"},j=e=>BigInt(e).toString(16).padStart(64,"0"),ae=e=>e.slice(2).toLowerCase().padStart(64,"0"),qr=/^0x[0-9a-fA-F]{40}$/,ut=100;function zo(e,t){let r=Number(t);if(!Number.isFinite(r)||r<0)throw new Error("slippageBps must be a non-negative number");if(r>ut)throw new Error(`slippageBps ${r} exceeds the ${ut} bps ceiling. Block and requote or split the order -- do not widen the guard to force a fill.`);return BigInt(e)*BigInt(1e4-Math.floor(r))/10000n}function st(e,t){return(e?.venues||[]).find(r=>r.kind===t)?.address??null}function Mr(e){let{chainId:t,wrappedNative:r}=e;async function n({quoter:i,tokenIn:s,tokenOut:a,amountIn:u,fee:c},p){let d=`0x${Fr.quoteExactInputSingle}`+ae(s)+ae(a)+j(u)+j(c)+j(0),l=await k(t,"eth_call",[{to:i,data:d},"latest"],p).catch(()=>null),m=l?.result??l;if(!m||m==="0x"||m.length<66)return null;let f=BigInt(`0x${m.slice(2,66)}`);return f>0n?f:null}async function o({quoter:i,tokenIn:s,tokenOut:a,amountIn:u},c){let p=[],d=null;for(let l of Ko){let m=await n({quoter:i,tokenIn:s,tokenOut:a,amountIn:u,fee:l},c);p.push({fee:l,amountOut:m?m.toString():null}),m&&(!d||m>d.amountOut)&&(d={fee:l,amountOut:m})}return{best:d,tried:p}}return{async quote({tokenIn:i,tokenOut:s,amountIn:a},u={}){let c=st(u.scanner,"quoter");if(!c)return{chainId:t,evidence:E.UNAVAILABLE,reason:"no verified quoter configured for this chain; quoting stays fail-closed rather than guessing a venue address"};for(let l of[i,s])if(!qr.test(l||""))throw new Error("quote requires valid 20-byte addresses");let{best:p,tried:d}=await o({quoter:c,tokenIn:i,tokenOut:s,amountIn:a},u);return p?{chainId:t,venue:"uniswap-v3",quoter:c,tokenIn:i,tokenOut:s,amountIn:String(a),amountOut:p.amountOut.toString(),fee:p.fee,triedFeeTiers:d,evidence:E.LIVE,note:"exact-input single-hop quote at current tick; not a guaranteed fill"}:{chainId:t,quoter:c,tokenIn:i,tokenOut:s,triedFeeTiers:d,evidence:E.UNKNOWN,reason:"no fee tier returned a quote -- no V3 pool for this pair, or no liquidity"}},async sellSimulation({token:i,amountIn:s,base:a},u={}){let c=st(u.scanner,"quoter"),p=a||r;if(!c||!p)return{chainId:t,token:i,verdict:b.UNKNOWN,evidence:E.UNAVAILABLE,reason:c?"no wrappedNative configured, so there is no base asset to round-trip against":"no verified quoter configured for this chain"};let d=await o({quoter:c,tokenIn:p,tokenOut:i,amountIn:s},u);if(!d.best)return{chainId:t,token:i,verdict:b.FAIL,evidence:E.LIVE,leg:"buy",reason:"no V3 pool priced the buy leg on any fee tier"};let l=await o({quoter:c,tokenIn:i,tokenOut:p,amountIn:d.best.amountOut},u);if(!l.best)return{chainId:t,token:i,verdict:b.FAIL,evidence:E.LIVE,leg:"sell",bought:d.best.amountOut.toString(),reason:"SELL LEG FAILED while the buy leg quoted fine. This is the honeypot signature: do not trade."};let m=l.best.amountOut,f=Number(m*10000n/BigInt(s)),g=b.PASS,h="round trip completes with expected fee/impact loss";return f<5e3?(g=b.FAIL,h=`round trip returns only ${(f/100).toFixed(2)}% -- punitive tax or no real liquidity`):f<9e3&&(g=b.CAUTION,h=`round trip returns ${(f/100).toFixed(2)}% -- transfer tax or thin liquidity at this size`),{chainId:t,venue:"uniswap-v3",token:i,base:p,verdict:g,reason:h,amountIn:String(s),bought:d.best.amountOut.toString(),returned:m.toString(),retentionBps:f,buyFee:d.best.fee,sellFee:l.best.fee,evidence:E.LIVE,note:"Quote-level round trip. It does not prove transfer hooks absent at execution time."}},async prepareUnsignedTx({tokenIn:i,tokenOut:s,amountIn:a,recipient:u,slippageBps:c=50,fee:p},d={}){let l=st(d.scanner,"router");if(!l)throw new Error(`chain ${t} has no verified V3 router; preparing a swap stays fail-closed. Add a venue with recorded provenance first (see docs/adding-a-chain.md).`);if(!qr.test(u||""))throw new Error("prepareUnsignedTx requires a valid recipient address");let m=await this.quote({tokenIn:i,tokenOut:s,amountIn:a},d);if(m.evidence!==E.LIVE)throw new Error(`cannot prepare without a live quote (${m.evidence}: ${m.reason??"no reason given"})`);let f=p??m.fee,g=zo(m.amountOut,c);if(g<=0n)throw new Error("computed minOut is zero -- refusing to prepare");let h=`0x${Fr.exactInputSingle}`+ae(i)+ae(s)+j(f)+ae(u)+j(a)+j(g)+j(0);return{unsigned:!0,signedBy:"user-wallet",chainId:t,venue:"uniswap-v3",tx:{to:l,data:h,value:"0x0"},guard:{quotedOut:m.amountOut,minOut:g.toString(),slippageBps:c,maxSlippageBps:ut,fee:f},requires:[{step:"approve",token:i,spender:l,amount:String(a)}],note:"UNSIGNED. Re-verify the guard against a fresh quote immediately before signing -- a quote-time minimum is not a minimum at broadcast time."}}}}var ke={decimals:"0x313ce567",symbol:"0x95d89b41",name:"0x06fdde03",totalSupply:"0x18160ddd",owner:"0x8da5cb5b"};function Vr(e){if(!e||e==="0x")return null;try{return BigInt(e)}catch{return null}}function Hr(e){if(!e||e==="0x")return null;let t=e.slice(2);if(t.length>=128){let n=Number(BigInt(`0x${t.slice(64,128)}`));if(n>0&&n<=256&&t.length>=128+n*2){let o=t.slice(128,128+n*2),i=Buffer.from(o,"hex").toString("utf8").replace(/\0+$/,"");if(i)return i}}return Buffer.from(t.slice(0,64),"hex").toString("utf8").replace(/\0+$/,"")||null}function Wo(e){let{chainId:t}=e;async function r(n,o,i){return k(t,"eth_call",[{to:n,data:o},"latest"],i)}return{async blockNumber(n={}){let o=await cr(t,n);return{chainId:t,blockNumber:o?.blockNumber??o,evidence:E.LIVE}},async nativeBalance(n,o={}){let i=await lr(t,n,o);return{chainId:t,address:n,wei:i?.wei??i?.balance??null,symbol:e.nativeCurrency?.symbol??null,decimals:e.nativeCurrency?.decimals??18,evidence:E.LIVE}},async tokenBalance({token:n,owner:o},i={}){let s=await dr({chainId:t,token:n,owner:o},i);return{chainId:t,token:n,owner:o,raw:s?.balance??s,evidence:E.LIVE}},async resolveToken(n,o={}){if(!/^0x[0-9a-fA-F]{40}$/.test(n||""))return{chainId:t,token:n,evidence:E.UNKNOWN,error:"resolveToken needs a 20-byte address; symbol lookup is a market-data concern"};let[i,s,a,u]=await Promise.all([r(n,ke.decimals,o).catch(()=>null),r(n,ke.symbol,o).catch(()=>null),r(n,ke.name,o).catch(()=>null),r(n,ke.totalSupply,o).catch(()=>null)]),c=Vr(i?.result??i),p=c!==null||s?.result||a?.result;return{chainId:t,address:n,decimals:c===null?null:Number(c),symbol:Hr(s?.result??s),name:Hr(a?.result??a),totalSupply:(Vr(u?.result??u)??null)?.toString()??null,evidence:p?E.LIVE:E.UNKNOWN,warning:p?void 0:"no ERC-20 metadata returned -- may not be a token contract"}},async resolvePools(n,o={}){let i=e.dexscreenerSlug;if(!i)return{chainId:t,token:n,pools:[],evidence:E.UNAVAILABLE,reason:"no dexscreenerSlug configured for this chain; pool discovery is unavailable rather than guessed"};let s=await Dr(n,o).catch(()=>null),u=(s?.pairs||s?.data?.pairs||[]).filter(c=>String(c.chainId).toLowerCase()===String(i).toLowerCase()).map(c=>({pair:c.pairAddress,dex:c.dexId,base:c.baseToken?.address,quote:c.quoteToken?.address,liquidityUsd:c.liquidity?.usd??null,priceUsd:c.priceUsd??null,volume24hUsd:c.volume?.h24??null,createdAt:c.pairCreatedAt??null})).sort((c,p)=>(p.liquidityUsd??0)-(c.liquidityUsd??0));return{chainId:t,token:n,pools:u,evidence:u.length?E.LIVE:E.UNKNOWN}},async scanBlocks({fromBlock:n,toBlock:o,address:i,topics:s,chunkSize:a=2e3}={},u={}){if(!Number.isInteger(n)||!Number.isInteger(o))throw new Error("scanBlocks requires integer fromBlock and toBlock");if(o<n)throw new Error("toBlock must be >= fromBlock");let c=[],p=[];for(let d=n;d<=o;d+=a){let l=Math.min(d+a-1,o);p.push([d,l])}for(let[d,l]of p){let m={fromBlock:`0x${d.toString(16)}`,toBlock:`0x${l.toString(16)}`};i&&(m.address=i),s&&(m.topics=s);let f=await k(t,"eth_getLogs",[m],u).catch(g=>({error:String(g?.message||g)}));if(f?.error)return{chainId:t,fromBlock:n,toBlock:o,logs:c,complete:!1,failedAt:[d,l],error:f.error,evidence:E.UNKNOWN};for(let g of f?.result??f??[])c.push(g)}return{chainId:t,fromBlock:n,toBlock:o,logs:c,complete:!0,chunks:p.length,evidence:E.LIVE}},async scoreRisk(n,o={}){let i=[],s=b.PASS,a=p=>{let d={[b.PASS]:0,[b.CAUTION]:1,[b.UNKNOWN]:2,[b.FAIL]:3};d[p]>d[s]&&(s=p)},u=await this.resolveToken(n,o);u.evidence!==E.LIVE?(i.push({check:"erc20-metadata",result:b.UNKNOWN,detail:u.warning}),a(b.UNKNOWN)):i.push({check:"erc20-metadata",result:b.PASS,detail:`${u.symbol} / ${u.decimals}d`});let c=await this.resolvePools(n,o);if(c.evidence===E.UNAVAILABLE)i.push({check:"liquidity",result:b.UNKNOWN,detail:c.reason}),a(b.UNKNOWN);else if(!c.pools.length)i.push({check:"liquidity",result:b.FAIL,detail:"no pool with liquidity found"}),a(b.FAIL);else{let p=c.pools[0],d=p.liquidityUsd??0;d<5e3?(i.push({check:"liquidity",result:b.CAUTION,detail:`top pool only $${d}`}),a(b.CAUTION)):i.push({check:"liquidity",result:b.PASS,detail:`$${d} on ${p.dex}`}),p.createdAt&&Date.now()-p.createdAt<24*3600*1e3&&(i.push({check:"age",result:b.CAUTION,detail:"pool under 24h old"}),a(b.CAUTION))}if(typeof this.sellSimulation=="function"){let p=await this.sellSimulation({token:n,amountIn:(10n**16n).toString()},o).catch(d=>({verdict:b.UNKNOWN,reason:String(d?.message||d)}));i.push({check:"sellability",result:p.verdict,detail:p.retentionBps!=null?`round trip returns ${(p.retentionBps/100).toFixed(2)}% -- ${p.reason}`:p.reason}),a(p.verdict)}else i.push({check:"sellability",result:b.UNKNOWN,detail:"no verified router on this chain, so a round-trip sell simulation cannot run. Treat as unproven -- a buy path is not an exit path."}),a(b.UNKNOWN);return{chainId:t,token:n,verdict:s,checks:i,note:"Structural checks only. UNKNOWN is not PASS. A token is not tradeable until a sell simulation succeeds."}}}}function jr(e){let r={...Wo(e)},n=new Set((e.venues||[]).map(i=>i.kind));e.venueKind==="uniswap-v3"&&n.has("quoter")&&n.has("router")?Object.assign(r,Mr({chainId:e.chainId,wrappedNative:e.wrappedNative})):e.venueKind==="uniswap-v2"&&n.has("router")&&Object.assign(r,Pr({chainId:e.chainId,wrappedNative:e.wrappedNative}));let o={};for(let[i,s]of Object.entries(r))o[i]=s.bind(r);return{key:e.key,chainId:e.chainId,name:e.name,rpcEnv:e.rpcEnv,nativeCurrency:e.nativeCurrency,explorer:e.explorer,venues:e.venues||[],capabilities:o}}var Go=Object.freeze([{key:"ethereum",chainId:1,name:"Ethereum",rpcEnv:["ETH_RPC_URL","ETHEREUM_RPC_URL","MAINNET_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://etherscan.io",dexscreenerSlug:"ethereum",venueKind:"uniswap-v3",wrappedNative:"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDC fee 500 quoted 1908.71 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:1}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:1}}]},{key:"optimism",chainId:10,name:"OP Mainnet",rpcEnv:["OPTIMISM_RPC_URL","OP_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://optimistic.etherscan.io",dexscreenerSlug:"optimism",venueKind:"uniswap-v3",wrappedNative:"0x4200000000000000000000000000000000000006",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDC fee 500 quoted 1905.23 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:10}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:10}}]},{key:"bsc",chainId:56,name:"BNB Smart Chain",rpcEnv:["BSC_RPC_URL","BNB_RPC_URL"],nativeCurrency:{symbol:"BNB",decimals:18},explorer:"https://bscscan.com",dexscreenerSlug:"bsc",venueKind:"uniswap-v3",wrappedNative:"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",venues:[{kind:"quoter",address:"0x78D78E420Da98ad378D7799bE8f4AF69033EB077",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WBNB->USDC fee 500 quoted 413.86 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:56}},{kind:"router",address:"0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:56}}]},{key:"polygon",chainId:137,name:"Polygon",rpcEnv:["POLYGON_RPC_URL","POLYGON_RPC"],nativeCurrency:{symbol:"POL",decimals:18},explorer:"https://polygonscan.com",dexscreenerSlug:"polygon",venueKind:"uniswap-v3",wrappedNative:"0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WMATIC->USDC fee 500 quoted 0.0720 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:137}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:137}}]},{key:"stable",chainId:988,name:"Stable Mainnet",rpcEnv:["STABLE_RPC_URL","STABLE_RPC"],nativeCurrency:{symbol:"USDT0",decimals:18},venues:[]},{key:"hyperevm",chainId:999,name:"HyperEVM",rpcEnv:["HYPEREVM_RPC_URL","HYPER_EVM_RPC"],nativeCurrency:{symbol:"HYPE",decimals:18},dexscreenerSlug:"hyperevm",venues:[]},{key:"abstract",chainId:2741,name:"Abstract",rpcEnv:["ABSTRACT_RPC_URL","ABS_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},venues:[]},{key:"robinhood",chainId:4663,name:"Robinhood Chain",rpcEnv:["RH_CHAIN_RPC","ROBINHOOD_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},dexscreenerSlug:"robinhood",venueKind:"uniswap-v3",wrappedNative:"0x0bd7d308f8e1639fab988df18a8011f41eacad73",venues:[{kind:"quoter",address:"0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDG fee 100 quoted 1866.58 USDG, and USDG->CASHCAT fee 10000 quoted a live amount). A contract that correctly prices known pairs IS a working V3 quoter",source:"live eth_call against rpc.mainnet.chain.robinhood.com",date:"2026-07-31",chainId:4663}},{kind:"router",address:"0xcaf681a66d020601342297493863e78c959e5cb2",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode (24497 bytes) on this chain and the paired quoter at the same deployment passed a live functional quote",source:"live eth_getCode against rpc.mainnet.chain.robinhood.com",date:"2026-07-31",chainId:4663}},{kind:"factory",address:"0x1f7d7550b1b028f7571e69a784071f0205fd2efa",label:"Uniswap V3 Factory",verified:{method:"eth_getCode returned real bytecode (24535 bytes) and a PoolCreated log scan over this factory returned 76 pools in ~9000 recent blocks",source:"live eth_getLogs against rpc.mainnet.chain.robinhood.com",date:"2026-07-31",chainId:4663}}]},{key:"base",chainId:8453,name:"Base",rpcEnv:["BASE_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://basescan.org",dexscreenerSlug:"base",venueKind:"uniswap-v3",wrappedNative:"0x4200000000000000000000000000000000000006",venues:[{kind:"quoter",address:"0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a",label:"Uniswap V3 QuoterV2 (Base)",verified:{method:"functional probe: quoteExactInputSingle returned WETH->USDC at fee 500 = 1908.44 USDC, a live sane price. The canonical mainnet quoter address also has bytecode on Base but does NOT price this pair, which is exactly the false positive a codesize-only check accepts",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:8453}},{kind:"router",address:"0x2626664c2603336E57B271c5C0b26F421741e481",label:"Uniswap V3 SwapRouter02 (Base)",verified:{method:"eth_getCode returned real bytecode and the paired Base quoter passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:8453}},{kind:"router-v2",address:"0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",label:"Uniswap V2 Router02 (Base)",verified:{method:"eth_getCode returned 17891 bytes; live getAmountsOut on WETH->USDC round-tripped to 98.75% (2x0.30% fee + impact)",source:"https://docs.uniswap.org/contracts/v2/reference/smart-contracts/v2-deployments",date:"2026-07-30",chainId:8453}}]},{key:"arbitrum",chainId:42161,name:"Arbitrum One",rpcEnv:["ARBITRUM_RPC_URL","ARB_RPC_URL"],nativeCurrency:{symbol:"ETH",decimals:18},explorer:"https://arbiscan.io",dexscreenerSlug:"arbitrum",venueKind:"uniswap-v3",wrappedNative:"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",venues:[{kind:"quoter",address:"0x61fFE014bA17989E743c5F6cB21bF9697530B21e",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WETH->USDC fee 500 quoted 1908.72 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:42161}},{kind:"router",address:"0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:42161}}]},{key:"avalanche",chainId:43114,name:"Avalanche C-Chain",rpcEnv:["AVALANCHE_RPC_URL","AVAX_RPC_URL"],nativeCurrency:{symbol:"AVAX",decimals:18},explorer:"https://snowtrace.io",dexscreenerSlug:"avalanche",venueKind:"uniswap-v3",wrappedNative:"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",venues:[{kind:"quoter",address:"0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F",label:"Uniswap V3 QuoterV2",verified:{method:"functional probe, not a codesize check: quoteExactInputSingle returned a live sane price (WAVAX->USDC fee 500 quoted 6.48 USDC). A contract that correctly prices a known pair IS a working V3 quoter",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:43114}},{kind:"router",address:"0xbb00FF08d01D300023C629E8fFfFcb65A5a578cE",label:"Uniswap V3 SwapRouter02",verified:{method:"eth_getCode returned real bytecode on this chain and the paired quoter at the same deployment passed a live functional quote",source:"scripts/verify-v3-venues.mjs (re-runnable)",date:"2026-07-30",chainId:43114}}]}]);function Kr(){return Go.map(e=>dt(jr(e)))}Kr();var[zr,...Ne]=process.argv.slice(2),Oe=Ne.includes("--json"),y=Ne.filter(e=>e!=="--json"),Wr="0x0000000000000000000000000000000000000000";function G(e){e||X("missing <chain>");let t=Number(e);if(se(t))return t;let r=_e().find(n=>n.key===String(e).toLowerCase());if(r)return r.chainId;X(`unknown chain "${e}". Known: ${_e().map(n=>n.key).join(", ")}`)}function X(e){console.error(`error: ${e}`),process.exit(1)}function Gr(e,t){return(Number(e)/10**t).toLocaleString(void 0,{maximumFractionDigits:6})}function Xr(e,t){if(console.log(`sources: ${e.sourcesAnswered}/${e.sourcesTried} answered`),console.log(`ranked on: ${e.rankedOn}
6
+ `),!e.routes.length){console.log("no source returned a usable route.");for(let n of e.failed)console.log(` ${n.source}: ${n.error}`);return}let r=Math.max(...e.routes.map(n=>n.source.length),6);console.log(` ${"source".padEnd(r)} ${"net out".padStart(14)} ${"gross".padStart(14)} cost`);for(let[n,o]of e.routes.entries()){let i=n===0?"*":" ",s=o.gasUsd==null?"gas unknown":o.gasUsd===0?"gasless (solver)":`$${Number(o.gasUsd+(o.feeUsd??0)).toFixed(2)}`,a=o.meta?.durationSeconds!=null?` ~${o.meta.durationSeconds}s`:"";console.log(`${i} ${o.source.padEnd(r)} ${Gr(o.netOut,t).padStart(14)} ${Gr(o.grossOut,t).padStart(14)} ${s}${a}`)}for(let n of e.failed)console.log(` ${n.source.padEnd(r)} FAILED: ${String(n.error).slice(0,60)}`);console.log(`
7
+ ${e.note}`);for(let n of e.warnings)console.log(`
8
+ WARNING: ${n}`)}try{switch(zr){case"swap":{let e=G(y[0]);(!y[1]||!y[2])&&X("usage: oracle-route swap <chain> <tokenIn> <tokenOut> [amountIn]");let t=y[3]||(10n**18n).toString(),r=se(e),[n,o]=await Promise.all([r.resolveToken(y[1]).then(s=>s.decimals).catch(()=>null),r.resolveToken(y[2]).then(s=>s.decimals).catch(()=>null)]),i=await Ie({chainId:e,tokenIn:y[1],tokenOut:y[2],amountIn:t,taker:y[4]||"0x000000000000000000000000000000000000dEaD",decimalsIn:n,decimalsOut:o});Oe?process.stdout.write(`${JSON.stringify(i,null,2)}
9
+ `):Xr(i,o??18);break}case"bridge":{let e=G(y[0]),t=G(y[1]),r=y[2]||Wr,n=y[3]||(10n**18n).toString(),o=await Ce({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:r,amountIn:n,taker:y[4]||"0x000000000000000000000000000000000000dEaD",decimalsOut:18});Oe?process.stdout.write(`${JSON.stringify(o,null,2)}
10
+ `):Xr(o,18);break}case"prepare":{let e=G(y[0]);(!y[1]||!y[2]||!y[3])&&X("usage: oracle-route prepare <chain> <tokenIn> <tokenOut> <taker> [amountIn] [--source=X]");let t=y[3],r=y[4]||(10n**18n).toString(),n=Ne.find(u=>u.startsWith("--source=")),o=se(e),[i,s]=await Promise.all([o.resolveToken(y[1]).then(u=>u.decimals).catch(()=>null),o.resolveToken(y[2]).then(u=>u.decimals).catch(()=>null)]),a=await Ur({chainId:e,tokenIn:y[1],tokenOut:y[2],amountIn:r,taker:t,decimalsIn:i,decimalsOut:s,source:n?n.split("=")[1]:void 0});if(Oe){process.stdout.write(`${JSON.stringify(a,null,2)}
11
+ `);break}a.ok||(console.log(`could not prepare: ${a.reason}`),a.failureKind&&console.log(`kind: ${a.failureKind}`),a.alternative&&console.log(`try: --source=${a.alternative}`),process.exit(1)),console.log(`source: ${a.chosen.source}${a.chosen.wasWinner?" (winner)":" (override -- NOT the winner)"}`),console.log(`artifact: ${a.artifactKind}`),console.log(`destination: ${a.destination}`),a.minOut&&console.log(`minOut: ${a.minOut}`),a.driftBps!=null&&console.log(`drift: ${(a.driftBps/100).toFixed(3)}% vs comparison`),a.requiresApproval&&(console.log(`
12
+ approval required first:`),console.log(` token ${a.requiresApproval.token}`),console.log(` spender ${a.requiresApproval.spender}`),a.requiresApproval.note&&console.log(` note ${a.requiresApproval.note}`)),a.runnersUp?.length&&console.log(`
13
+ runners-up: ${a.runnersUp.map(u=>u.source).join(", ")}`);for(let u of a.warnings)console.log(`
14
+ WARNING: ${u}`);console.log(`
15
+ ${a.note}`);break}case"prepare-bridge":{let e=G(y[0]),t=G(y[1]);y[2]||X("usage: oracle-route prepare-bridge <fromChain> <toChain> <taker> [token] [amountIn] [--source=X]");let r=y[2],n=y[3]||Wr,o=y[4]||(10n**17n).toString(),i=Ne.find(a=>a.startsWith("--source=")),s=await Lr({fromChainId:e,toChainId:t,tokenIn:n,tokenOut:n,amountIn:o,taker:r,decimalsOut:18,source:i?i.split("=")[1]:void 0});if(Oe){process.stdout.write(`${JSON.stringify(s,null,2)}
16
+ `);break}s.ok||(console.log(`could not prepare: ${s.reason}`),s.failureKind&&console.log(`kind: ${s.failureKind}`),s.alternative&&console.log(`try: --source=${s.alternative}`),process.exit(1)),console.log(`source: ${s.chosen.source}${s.chosen.wasWinner?" (winner)":" (override -- NOT the winner)"}`),console.log(`artifact: ${s.artifactKind}`),console.log(`route: chain ${s.fromChainId} -> chain ${s.toChainId}`),console.log(`signs: ${s.transactionCount} transaction(s) on chain ${s.fromChainId}`),console.log(`destination: ${s.destination}`),s.minOut&&console.log(`minOut: ${s.minOut}`),s.durationSeconds!=null&&console.log(`eta: ~${s.durationSeconds}s to credit`),s.driftBps!=null&&console.log(`drift: ${(s.driftBps/100).toFixed(3)}% vs comparison`),s.requiresApproval&&(console.log(`
17
+ approval required first:`),console.log(` token ${s.requiresApproval.token}`),console.log(` spender ${s.requiresApproval.spender}`)),s.transactions.forEach((a,u)=>{console.log(`
18
+ tx ${u+1}/${s.transactionCount}: chain ${a.chainId} -> ${a.to}`)}),s.runnersUp?.length&&console.log(`
19
+ runners-up: ${s.runnersUp.map(a=>a.source).join(", ")}`);for(let a of s.warnings)console.log(`
20
+ WARNING: ${a}`);console.log(`
21
+ ${s.note}`);break}default:console.log(["oracle-route -- best-execution routing",""," oracle-route swap <chain> <tokenIn> <tokenOut> [amountIn] [taker]"," oracle-route bridge <fromChain> <toChain> [token] [amountIn] [taker]"," oracle-route prepare <chain> <tokenIn> <tokenOut> <taker> [amountIn] [--source=X]"," oracle-route prepare-bridge <fromChain> <toChain> <taker> [token] [amt] [--source=X]",""," Ranks by NET output (gross minus gas and fees), not headline quote."," A route quoting more but costing more gas can lose. --json for detail."].join(`
22
+ `)),process.exit(zr?1:0)}}catch(e){X(String(e?.message||e))}