@oracle-agent/oracle 0.28.28 → 0.28.30

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 (61) hide show
  1. package/README.md +10 -3
  2. package/SETUP.md +3 -0
  3. package/dist/assets/skills/bankrbot/SKILL.md +24 -0
  4. package/dist/assets/skills/oracle-agentic-crypto/SKILL.md +39 -0
  5. package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
  6. package/dist/assets/skills/oracle-uniswap-v4-hooks/SKILL.md +31 -0
  7. package/dist/assets/skills/oracle-x402/SKILL.md +30 -0
  8. package/dist/bin/desk-server.mjs +28 -26
  9. package/dist/bin/oracle-data-mcp.mjs +26 -12
  10. package/dist/bin/oracle-gateway.mjs +39 -27
  11. package/dist/bin/oracle-mev-arb-shadow.mjs +5 -5
  12. package/dist/bin/oracle-mev-shadow.mjs +5 -5
  13. package/dist/bin/oracle-public-server.mjs +4 -4
  14. package/dist/bin/oracle-route.mjs +15 -15
  15. package/dist/bin/oracle-scan.mjs +11 -11
  16. package/dist/bin/oracle.mjs +4 -3
  17. package/dist/cli/commands/auth.mjs +6 -6
  18. package/dist/cli/commands/chat.mjs +161 -161
  19. package/dist/cli/commands/doctor.mjs +1 -1
  20. package/dist/cli/commands/eval.mjs +138 -139
  21. package/dist/cli/commands/farm.mjs +22 -22
  22. package/dist/cli/commands/follow.mjs +14 -14
  23. package/dist/cli/commands/harness.mjs +4 -4
  24. package/dist/cli/commands/model.mjs +163 -163
  25. package/dist/cli/commands/receipt.mjs +1 -1
  26. package/dist/cli/commands/resolve.mjs +6 -6
  27. package/dist/cli/commands/setup.mjs +23 -23
  28. package/dist/cli/commands/snipe.mjs +24 -0
  29. package/dist/cli/commands/strategy.mjs +3 -3
  30. package/dist/cli/commands/swap.mjs +25 -25
  31. package/dist/cli/commands/venues.mjs +1 -1
  32. package/dist/control/approval-binding.mjs +1 -0
  33. package/dist/control/finality.mjs +1 -0
  34. package/dist/control-plane/index.mjs +6 -0
  35. package/dist/data/desk-data.mjs +27 -25
  36. package/dist/data/names.mjs +2 -2
  37. package/dist/data/providers/farming.mjs +2 -2
  38. package/dist/governance-prepare.mjs +2 -0
  39. package/dist/index.mjs +44 -31
  40. package/dist/local-marketplace.mjs +3 -0
  41. package/dist/local-pack-registry.mjs +3 -0
  42. package/dist/local-signer/runtime.mjs +7 -7
  43. package/dist/local-x402.mjs +3 -0
  44. package/dist/nft/universal-mint-router.mjs +3 -3
  45. package/dist/notifications/index.mjs +3 -0
  46. package/dist/position-health.mjs +2 -0
  47. package/dist/router/index.mjs +2 -2
  48. package/dist/router/prepare-bridge.mjs +2 -2
  49. package/dist/safety-intelligence.mjs +1 -0
  50. package/dist/scanner/index.mjs +3 -3
  51. package/dist/strategy/index.mjs +3 -3
  52. package/dist/task.d.mts +130 -0
  53. package/dist/task.mjs +2 -0
  54. package/dist/tax-lots.mjs +5 -0
  55. package/dist/tenant-rbac.mjs +1 -0
  56. package/dist/workflow-telemetry.mjs +1 -0
  57. package/package.json +17 -2
  58. package/public/agent-connect/index.html +2 -2
  59. package/public/install.sh +2 -2
  60. package/public/oracle-splash/index.html +2 -2
  61. package/public/oracle-splash/install.sh +2 -2
@@ -1,2 +1,2 @@
1
- var bt=Object.defineProperty;var B=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var ve=(e,t)=>{for(var r in t)bt(e,r,{get:t[r],enumerable:!0})};import H from"node:net";import Et from"node:dns";function X(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=d=>{if(!d)return[];let c=d.split(":"),u=c.at(-1);if(u?.includes(".")){let p=u.split(".").map(Number);if(p.length!==4||p.some(m=>!Number.isInteger(m)||m<0||m>255))return null;c.splice(c.length-1,1,(p[0]<<8|p[1]).toString(16),(p[2]<<8|p[3]).toString(16))}return c.some(p=>!/^[0-9a-f]{1,4}$/.test(p))?null:c.map(p=>Number.parseInt(p,16))},[n,i]=t.split("::"),o=r(n),a=r(i);if(!o||!a)return null;let s=t.includes("::"),f=8-o.length-a.length;if(!s&&f!==0||s&&f<1)return null;let l=[...o,...Array(Math.max(0,f)).fill(0),...a];return l.length!==8?null:Uint8Array.from(l.flatMap(d=>[d>>8,d&255]))}function ie(e,t,r){let n=Math.floor(r/8),i=r%8;for(let a=0;a<n;a+=1)if(e[a]!==t[a])return!1;if(!i)return!0;let o=255<<8-i;return(e[n]&o)===(t[n]&o)}function ae(e){if(H.isIPv4(e)){let t=e.split(".").map(Number);return!(t[0]===0||t[0]===10||t[0]===127||t[0]>=224||t[0]===100&&t[1]>=64&&t[1]<=127||t[0]===169&&t[1]===254||t[0]===172&&t[1]>=16&&t[1]<=31||t[0]===192&&(t[1]===0||t[1]===2||t[1]===168)||t[0]===192&&t[1]===88&&t[2]===99||t[0]===198&&(t[1]===18||t[1]===19||t[1]===51)||t[0]===203&&t[1]===0&&t[2]===113)}if(H.isIPv6(e)){let t=X(e);if(!t)return!1;let r=X("::ffff:0:0");return ie(t,r,96)?ae([...t.slice(12)].join(".")):ie(t,X("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([i,o])=>ie(t,X(i),o)):!1}return!1}function At(e){let t;try{t=new URL(String(e))}catch{return{ok:!1,error:`not a valid URL: ${String(e).slice(0,120)}`}}if(t.protocol!=="http:"&&t.protocol!=="https:")return{ok:!1,error:`refused protocol ${t.protocol} (only http/https)`};let r=t.hostname.toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,"");if(yt.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=H.isIP(r);return n!==0&&!ae(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function se(e,{lookupFn:t=Et.promises.lookup}={}){let r=At(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:H.isIPv6(r.host)?6:4}]};let n;try{n=await t(r.host,{all:!0,verbatim:!0})}catch{return{ok:!1,error:`refused: ${r.host} did not resolve`}}return!Array.isArray(n)||n.length===0||n.some(i=>!ae(i.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function ce({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let i=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),o=new Map,a=c=>(Array.isArray(c)?c:[c]).map(u=>typeof u=="string"?{address:u}:u).filter(u=>u&&u.address).map(u=>({address:u.address,family:u.family||(H.isIPv6(u.address)?6:4)})),s=(c,u,p)=>{o.set(i(c),a(typeof u=="string"?[{address:u,family:p}]:u))},f=c=>{let u=i(c);if(H.isIP(u))return[{address:u,family:H.isIPv6(u)?6:4}];let p=o.get(u);if(!p||!p.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return p},l=new r({connect:{lookup(c,u,p){let m;try{m=f(c)}catch(E){return p(E)}return u?.all?p(null,m):p(null,m[0].address,m[0].family)}}}),d=xt((c,u={})=>n(c,{...u,dispatcher:l}),s);return{dispatcher:l,fetch:d,pin:s,resolve:f,async close(){try{await l.destroy()}catch{}}}}function xt(e,t){if(typeof e!="function")throw new Error("markPinCapableFetch: fetchImpl must be a function");if(typeof t!="function")throw new Error("markPinCapableFetch: pin must be a function");return e[ue]=Object.freeze({pin:t}),e}function le(e){return typeof e=="function"&&typeof e[ue]?.pin=="function"}function Ne(e,t,r){if(!le(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[ue].pin(t,r)}var yt,ue,Te=B(()=>{yt=new Set(["localhost","metadata.google.internal","metadata.goog"]);ue=Symbol.for("oracle.egressGuard.pinCapableFetch")});import{createHash as St}from"node:crypto";function Ot(e){let t=String(e||"").toLowerCase();return Le.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function _t(e){let t={};for(let[r,n]of Object.entries(e||{}))Ot(r)||(t[r]=n);return t}function Bt(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 Nt(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function Tt(e,t,r,n={}){let i={};for(let[d,c]of Object.entries(r||{}))i[d.toLowerCase()]=c;let o=Object.keys(i).filter(d=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(d)),s=[...new Set([...Le,...o])].sort().map(d=>`${d}=${i[d]??""}`).join(`
2
- `),f=St("sha256").update(s).digest("hex").slice(0,32),l=`${n.untrustedUrl?"untrusted":"trusted"}:${n.maxResponseBytes??"unbounded"}`;return`${e} ${t} ${l} ${f}`}function Rt(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,$e):Math.min(250*2**e,$e)+Math.floor(Math.random()*100)}function z(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function pe(e,t,r){return z(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function G(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function Pt(e){return e?e.byteLength??e.length??0:0}async function Ue(e,t,{url:r,truncate:n=!1,onOversize:i}={}){if(t==null)return await e.text();let o=Number(e.headers?.get?.("content-length"));if(Number.isFinite(o)&&o>t&&(G(e),!n))throw pe(r,`content-length ${o}`,t);let a=e.body?.getReader?.();if(!a){let c=await e.text(),u=Buffer.byteLength(c,"utf8");if(u>t){if(!n)throw pe(r,`body ${u} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let s=[],f=0,l=!1;try{for(;;){let{value:c,done:u}=await a.read();if(u)break;if(c&&(s.push(Buffer.from(c)),f+=Pt(c),f>t)){l=!0;break}}}finally{if(l)try{await a.cancel()}catch{}try{a.releaseLock?.()}catch{}}if(l&&(typeof i=="function"&&i(),!n))throw pe(r,`streamed ${f} bytes`,t);let d=Buffer.concat(s);return(l?d.subarray(0,t):d).toString("utf8")}function Fe(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Ut(e,{fetchImpl:t,method:r,headers:n,body:i,timeoutMs:o,lookupFn:a,realFetch:s,untrustedUrl:f=!1,maxResponseBytes:l=null,importUndici:d,validateResponse:c}){let u=new AbortController,p=setTimeout(()=>u.abort(),o),m=null,E=t,h=a?{lookupFn:a}:{};if(f&&!s&&!le(E))throw z(`HTTP refused ${e}: untrustedUrl requires a pin-capable fetchImpl (see markPinCapableFetch in egress-guard.mjs) or no fetchImpl override so Oracle can pin the connection itself`);let A=async(w,{status:I=null}={})=>{let x=await se(w,h);if(!x.ok)throw z(I==null?`HTTP refused ${w}: ${x.error}`:`HTTP redirect to ${w} ${x.error}`,I==null?{}:{status:I});let b=new URL(w).hostname;if(s){if(m&&(await m.close(),m=null),!m)try{m=await ce({requireUndici:!0,...d?{importUndici:d}:{}})}catch(S){throw z(I==null?`HTTP refused ${w}: ${S?.message||S}`:`HTTP redirect to ${w} refused: ${S?.message||S}`,I==null?{}:{status:I})}m.pin(b,x.addresses),E=m.fetch}else Ne(E,b,x.addresses);return x};try{let w=String(e),I={...n||{}};f&&await A(w);for(let x=0;x<=Pe;x+=1){let b=await E(w,{method:r,headers:I,body:i,signal:u.signal,redirect:"manual"});if(vt.has(b.status)){if(r!=="GET"&&r!=="HEAD"){let v=await Ue(b,l??kt,{url:w,truncate:!0}),k=new Error(`HTTP ${b.status} ${r} ${w} redirected non-idempotent request`);throw k.status=b.status,k.body=Fe(v)??v.slice(0,300),k}if(x===Pe)throw G(b),new Error(`HTTP redirect loop for ${e}`);let g=b.headers?.get?.("location"),y;try{y=Bt(g,w)}catch(v){throw G(b),v}let _=!Nt(y,w);if(G(b),_&&(I=_t(I)),f)await A(y,{status:b.status});else if(_){let v=await se(y,h);if(!v.ok){let k=new Error(`HTTP redirect from ${w} ${v.error}`);throw k.status=b.status,k.retryable=!1,k}s&&v.addresses?.length&&(m||(m=await ce(d?{importUndici:d}:{})),m&&(m.pin(new URL(y).hostname,v.addresses),E=m.fetch))}w=y;continue}if(typeof c=="function")try{await c(b,{url:w})}catch(g){throw G(b),z(g?.message||String(g))}let S=await Ue(b,l,{url:w,onOversize:()=>u.abort()}),$=Fe(S);if(!b.ok){let g=new Error(`HTTP ${b.status} ${r} ${w}`);throw g.status=b.status,g.retryAfter=b.headers?.get?.("retry-after")??null,g.body=$??S.slice(0,300),g}return $??S}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(p),m&&await m.close()}}async function C(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,i=(t.method||"GET").toUpperCase(),o={Accept:"application/json",...t.headers||{}},a=t.body;a!=null&&typeof a!="string"&&(o["Content-Type"]=o["Content-Type"]||"application/json",a=JSON.stringify(a));let s=Number.isInteger(t.retries)?Math.max(t.retries,0):Ct,f=t.lookupFn,l=!t.fetchImpl,d=t.untrustedUrl===!0,c=t.importUndici,u=t.validateResponse,p=Number(t.maxResponseBytes),m=Number.isFinite(p)&&p>0?Math.floor(p):null,E=async()=>{let x;for(let b=0;b<=s;b++)try{return await Ut(e,{fetchImpl:r,method:i,headers:o,body:a,timeoutMs:n,lookupFn:f,realFetch:l,untrustedUrl:d,maxResponseBytes:m,importUndici:c,validateResponse:u})}catch(S){x=S;let $=S?.status,g=S?.name==="AbortError",y=new Set([408,425,429]),_=S?.retryable===!1?!1:$!=null?y.has($)||It.has($)&&Re.has(i):!g&&Re.has(i);if(b===s||!_)throw S;await $t(Rt(b,S?.retryAfter))}throw x};if(!(t.dedupe!==!1&&i==="GET"&&a==null))return E();let A=Tt(i,e,o,{untrustedUrl:d,maxResponseBytes:m}),w=de.get(A);if(w)return w;let I=E().finally(()=>de.delete(A));return de.set(A,I),I}var It,Re,Ct,$e,Le,vt,Pe,kt,de,$t,T=B(()=>{Te();It=new Set([408,425,429,500,502,503,504]),Re=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Ct=2,$e=4e3,Le=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],vt=new Set([301,302,303,307,308]),Pe=3,kt=64*1024;de=new Map;$t=e=>new Promise(t=>setTimeout(t,e))});import{readFileSync as Ft}from"node:fs";import{homedir as Lt}from"node:os";import{join as Y}from"node:path";function Dt(){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=Lt();if(process.env.ORACLE_PUBLIC_DESKTOP==="1"){let r=(process.env.ORACLE_CONFIG_DIR||Y(t,".config","oracle")).trim();return[e,Y(r,"exec.env")].filter(Boolean)}return[e,Y(t,".config","oracle","exec.env"),Y(t,".config","mad-desk","exec.env")].filter(Boolean)}function De(e,t,r){let n=e??process.env[t]??process.env[r];if(!String(n||"").trim())for(let i of Dt())try{let o=Ft(i,"utf8"),a=o.match(new RegExp(`^${t}=(.*)$`,"m"))||o.match(new RegExp(`^${r}=(.*)$`,"m"));if(a&&(n=a[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 Me=B(()=>{});var qe=B(()=>{});import{createHash as Mt,createHmac as je,timingSafeEqual as qt}from"node:crypto";function W(e){return Array.isArray(e)?`[${e.map(W).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${W(e[t])}`).join(",")}}`:JSON.stringify(e??null)}function Ve(e,{required:t=!1}={}){try{return De(e,"ORACLE_ROUTE_ATTESTATION_SECRET","MAD_ROUTE_ATTESTATION_SECRET")}catch(r){if(t)throw r;return null}}function me(e){let{signature:t,...r}=e;return r}function ze(e,{secret:t}={}){let r=Ve(t);return r?{...e,signature:je("sha256",r).update(W(me(e))).digest("hex")}:e}function Ht(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 Mt("sha256").update(Buffer.from(t.slice(2),"hex")).digest("hex")}function F(e,{chainId:t,venue:r,data:n,secret:i}={}){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");let o=Ve(i);if(o){let p=je("sha256",o).update(W(me(e))).digest("hex");if(!jt(e.signature,p))throw new Error("auto-slippage guard signature mismatch \u2014 refusing to bind a guard this Oracle did not issue")}let a=Number(e.selectedBps),s=Number(e.capBps);if(!Number.isInteger(a)||a<0||a>Q||!Number.isInteger(s)||s<0||s>Q||a>s)throw new Error("auto-slippage guard bounds are invalid");let f=BigInt(e.quoteAmountOut??0),l=BigInt(e.minAmountOut??0);if(f<=0n||l<=0n)throw new Error("auto-slippage guard amounts must be positive");let d=f*BigInt(1e4-a),c=d/10000n;if(d%10000n!==0n&&(c+=1n),l<c)throw new Error("auto-slippage guard is under-protected relative to its quote");let u=Gt(n);if(u!=null&&u!==l)throw new Error(`auto-slippage: calldata encodes floor ${u}, not the guard floor ${l} \u2014 refusing to bind`);return ze({...me(e),calldataHash:Ht(n)},{secret:i})}function jt(e,t){let r=Buffer.from(String(e??""),"utf8"),n=Buffer.from(String(t??""),"utf8");return r.length!==n.length||r.length===0?!1:qt(r,n)}function fe(e,t=0){let r=Number(e);return Number.isFinite(r)?r:t}function Vt(e){let t=e==null?Q: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,Q)}function L({liquidityUsd:e,priceChange5m:t=0,quoteAgeMs:r=0,crossChain:n=!1,requestedCapBps:i}={}){let o=fe(e,0),a=o>0?o>=25e4?5:o>=1e5?10:o>=5e4?20:o>=1e4?40:70:n?30:10,s=Math.min(60,Math.abs(fe(t,0))*2),f=Math.min(40,Math.floor(Math.max(0,fe(r,0))/5e3)*5),l=Math.max(25,Math.ceil(20+a+s+f)),d=Vt(i);return{mode:"auto",requiredBps:l,selectedBps:Math.min(l,d),capBps:d,executable:l<=d}}function zt({chainId:e,venue:t,quoteAmountOut:r,liquidityUsd:n,priceChange5m:i=0,quoteAgeMs:o=0,crossChain:a=!1,requestedCapBps:s,quotedAtMs:f=Date.now(),ttlMs:l=He,secret:d}={}){let c=BigInt(r??0);if(c<=0n)throw new Error("auto-slippage guard requires positive quoteAmountOut");let u=L({liquidityUsd:n,priceChange5m:i,quoteAgeMs:o,crossChain:a,requestedCapBps:s});if(!u.executable)throw new Error(`auto-slippage requires ${u.requiredBps} bps above hard/requested cap ${u.capBps}; route blocked`);let p=Number(f);if(!Number.isFinite(p))throw new Error("auto-slippage: quotedAtMs must be a finite number");let m=Math.min(3e4,Math.max(1e3,Number(l)||He)),E=c*BigInt(1e4-u.selectedBps),h=E/10000n;if(E%10000n!==0n&&(h+=1n),h>c&&(h=c),c>0n&&h<=0n)throw new Error(`auto-slippage: quote ${c} is too small to express a ${u.selectedBps} bps floor without rounding to zero`);let A=Number((c-h)*10000n/(c===0n?1n:c));if(A>u.capBps)throw new Error(`auto-slippage: realised floor implies ${A} bps, above cap ${u.capBps} \u2014 refusing to issue a guard weaker than advertised`);return ze({mode:"auto",chainId:Number(e),venue:String(t||"unknown"),quoteAmountOut:c.toString(),minAmountOut:h.toString(),requiredBps:u.requiredBps,selectedBps:u.selectedBps,capBps:u.capBps,quotedAtMs:p,expiresAtMs:p+m},{secret:d})}function Gt(e){let t=String(e||"");if(!/^0x[0-9a-fA-F]+$/.test(t)||t.length<10||t.length%2!==0)return null;let r=t.slice(0,10).toLowerCase(),n=[];for(let o=10;o+64<=t.length;o+=64)n.push(t.slice(o,o+64));let i=o=>n[o]==null?null:BigInt("0x"+n[o]);switch(r){case"0x414bf389":return i(6);case"0x04e45aaf":return i(5);case"0xc04b8d59":{let o=i(0);if(o==null)return null;let a=Number(o)/32;return!Number.isInteger(a)||a<0?null:i(a+4)}case"0xb858183f":{let o=i(0);if(o==null)return null;let a=Number(o)/32;return!Number.isInteger(a)||a<0?null:i(a+3)}case"0xa026383e":return i(6);case"0x38ed1739":case"0x5c11d795":return i(1);case"0x7ff36ab5":case"0xb6f9de95":return i(0);case"0x18cbafe5":case"0x791ac947":return i(1);default:return null}}function N(e,{chainId:t,venue:r,amountOut:n,liquidityUsd:i,priceChange5m:o,crossChain:a,requestedCapBps:s,quotedAtMs:f=Date.now(),ttlMs:l}={}){let d=zt({chainId:t,venue:r,quoteAmountOut:n,liquidityUsd:i,priceChange5m:o,crossChain:a,requestedCapBps:s,quotedAtMs:f,ttlMs:l});return{...e,autoSlippage:d,amountOutMinimum:d.minAmountOut}}var Q,He,P=B(()=>{Me();qe();Q=100,He=2e4});var j,J=B(()=>{j="0x000000000000000000000000000000000000dEaD"});import{createHash as Kt,createHmac as Xt,timingSafeEqual as vn}from"node:crypto";function he(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(he).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${he(e[r])}`).join(",")}}`}function Ge(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Ke(e=process.env){return Ge(process.env)||Ge(e)}function Jt(e){let{prepareHash:t,prepareMac:r,note:n,...i}=e||{};return i}function Zt(e){let t=Jt(e);return Kt("sha256").update(he(t)).digest("hex")}function er(e,t=Ke()){return t?Xt("sha256",t).update(String(e)).digest("hex"):""}function O(e,{provider:t,kind:r,env:n=process.env,nowMs:i=Date.now(),expiresAtMs:o}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let a=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(a&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let s={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:a?e.oraclePrepared:!0};if(!s.provider)throw new Error("stampPrepared: provider required");if(!s.kind)throw new Error("stampPrepared: kind required");let f=Number(i),l=o==null?f+Qt:Number(o),d=l-f;if(!Number.isSafeInteger(f)||!Number.isSafeInteger(l)||d<=0||d>Wt)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let u={...s,preparedAt:f,expiresAt:l,prepareVersion:Yt},p=Zt(u),m=Ke(n),E=m?er(p,m):void 0,h={...u,prepareHash:p};return E&&(h.prepareMac=E),h}var Yt,Qt,Wt,R=B(()=>{Yt=2,Qt=300*1e3,Wt=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});import{Contract as tr,JsonRpcProvider as rr}from"ethers";function cr(e){return sr.test(String(e||""))}async function Xe(e,{contract:t=nr,rpc:r=ir,chainId:n=or,balanceOf:i}={}){if(!cr(e))throw new Error("invalid-address");if(i)return BigInt(await i(e));let o=new rr(r,n,{staticNetwork:!0}),a=new tr(t,ar,o);return BigInt(await a.balanceOf(e))}var nr,or,ir,ar,sr,Ye=B(()=>{nr="0x62FCFAf7573AD8B41a0FBF347AfEb85e06599A75",or=999,ir="https://rpc.hyperliquid.xyz/evm",ar=["function balanceOf(address owner) view returns (uint256)"],sr=/^0x[a-fA-F0-9]{40}$/});import{existsSync as ur,readFileSync as lr,lstatSync as dr}from"node:fs";import{homedir as Qe}from"node:os";import{join as ge}from"node:path";function mr(e){let t=String(e||"swap").toLowerCase();return Object.prototype.hasOwnProperty.call(We,t)?We[t]:fr}function Er(e=process.env){if(process.env.ORACLE_TEST_ISOLATE_SECRETS==="1"){if(e[Je])return String(e[Je]);let t=e.ORACLE_CONFIG_DIR||ge(Qe(),".config","oracle");return ge(t,"fee-recipient")}return ge(Qe(),".config","oracle","fee-recipient")}function yr(e=process.env){try{let t=Er(e);if(!ur(t)||dr(t).isSymbolicLink())return"";let r=lr(t,"utf8").trim().toLowerCase();return/^0x[a-f0-9]{40}$/.test(r)?r:""}catch{return""}}function Ar(e,{fallback:t=0}={}){if(e==null)return t;if(String(e).trim()==="")return 0;let r=Number(e);return!Number.isFinite(r)||r<=0?0:Math.min(Math.floor(r),pr)}function xr({env:e=process.env,action:t="swap",admin:r=!1}={}){let n=String(e[gr]||"").trim(),i=String(e[wr]||br).trim();if(r===!0)return{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"admin-oracle"};let o=mr(t),a=Ar(e[hr],{fallback:n?o:0}),s=Math.min(a,o);if(!s)return{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"not-configured"};if(!/^0x[a-fA-F0-9]{40}$/.test(n))return{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"no-recipient"};let f=yr(e);return!f||f!==n.toLowerCase()?{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"recipient-not-pinned"}:{bps:s,recipient:n,integrator:i,action:t,applies:!0,reason:"configured"}}async function we({wallet:e,env:t=process.env,action:r="swap",holderCheck:n={},admin:i=!1}={}){let o=xr({env:t,action:r,admin:i});if(i===!0)return{...o,holderVerificationStatus:"admin-oracle"};let a=String(e||"").trim().toLowerCase();if(!/^0x[a-f0-9]{40}$/.test(a))return{...o,holderVerificationStatus:"wallet-required"};try{return BigInt(await Xe(a,n))>0n?{...o,bps:0,applies:!1,reason:"locals-only-holder",holderVerificationStatus:"holder"}:{...o,holderVerificationStatus:"non-holder"}}catch{return{...o,holderVerificationStatus:"unavailable"}}}function Ze(e){return e?.applies?`Oracle routing fee ${e.bps} bps (${(e.bps/100).toFixed(2)}%) to ${e.recipient}.`:e?.reason==="admin-oracle"?"No Oracle fee (admin Oracle).":e?.reason==="locals-only-holder"?"No Oracle fee (Locals Only holder).":"No Oracle fee."}function et(e){return e?.applies?{integrator:e.integrator,fee:String(e.bps/1e4)}:{}}var pr,fr,We,hr,gr,wr,Je,br,Z=B(()=>{Ye();pr=100,fr=5,We=Object.freeze({swap:5,bridge:5,perps:0,nft:0});hr="ORACLE_INTEGRATOR_FEE_BPS",gr="ORACLE_INTEGRATOR_FEE_RECIPIENT",wr="ORACLE_INTEGRATOR_ID",Je="ORACLE_INTEGRATOR_FEE_RECIPIENT_PIN",br="oracle"});var nt={};ve(nt,{LIFI_API:()=>rt,lifiChains:()=>kr,lifiHealth:()=>Cr,lifiPrepare:()=>vr,lifiQuote:()=>ee});function Ee(e={}){return(e.baseUrl||process.env.LIFI_API_URL||rt).replace(/\/$/,"")}function Ir(e){let t=String(e||be).toLowerCase();return t===be.toLowerCase()||t===Sr}function tt(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 Cr(e={}){let t=await C(`${Ee(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 ee(e={},t={}){let{fromChain:r,toChain:n=r,fromToken:i=be,toToken:o,fromAmount:a,fromAddress:s=j}=e;if(r==null||!o||!a)throw new Error("lifiQuote requires fromChain, toToken, fromAmount");let f=new URLSearchParams({fromChain:String(r),toChain:String(n),fromToken:i,toToken:o,fromAmount:String(a),fromAddress:s}),l=L({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(r),requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!l.executable)throw new Error(`lifi: route requires ${l.requiredBps} bps above cap ${l.capBps}`);f.set("slippage",String(l.selectedBps/1e4));let d=await we({wallet:e.fromAddress,env:t.env,action:e.feeAction||"swap",holderCheck:t.holderCheck});for(let[h,A]of Object.entries(et(d)))f.set(h,A);let c=await C(`${Ee(t)}/quote?${f}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),u=c?.estimate?.toAmount||c?.toAmount;if(!u)return{...c,autoSlippagePolicy:l,oracleFee:d};let p=c?.transactionRequest?.to||c?.estimate?.approvalAddress||"lifi",m=N(c,{chainId:Number(r),venue:p,amountOut:u,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(r),requestedCapBps:e.maxSlippageBps??e.slippageBps}),E=c?.estimate?.toAmountMin||c?.toAmountMin;if(E!=null&&BigInt(E)<BigInt(m.amountOutMinimum))throw new Error("lifi: provider transaction is under-protected versus bounded auto-slippage floor");return{...m,oracleFee:d}}async function vr(e={},t={}){let r=await ee(e,t),n=r?.transactionRequest;if(!n?.to||!n?.data)throw new Error("lifi: quote did not return an executable transactionRequest");let i=Number(e.fromChain);if(n.chainId!=null&&Number(n.chainId)!==i)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 o=null;if(!Ir(e.fromToken)){let a=r?.estimate?.approvalAddress||r?.approvalAddress;if(!a)throw new Error("lifi: ERC20 route missing approvalAddress");let s=r?.action?.fromToken?.address||r?.estimate?.fromToken?.address||e.fromToken;o={token:tt(s,"approval token"),spender:tt(a,"approval spender"),amount:String(e.fromAmount)}}return O({provider:"lifi",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:i,quote:r,autoSlippage:r.autoSlippage,requiresApproval:o,transaction:{chainId:i,from:n.from||e.fromAddress,to:n.to,data:n.data,value:n.value??"0x0",...n.gasLimit!=null?{gasLimit:n.gasLimit}:{},slippageGuard:F(r.autoSlippage,{chainId:i,venue:n.to,data:n.data})}},{provider:"lifi",kind:"lifi-tx"})}async function kr(e={}){return C(`${Ee(e)}/chains`,{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs??12e3})}var rt,be,Sr,ye=B(()=>{T();P();J();R();Z();rt="https://li.quest/v1";be="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",Sr="0x0000000000000000000000000000000000000000"});var te={};ve(te,{ACROSS_API:()=>ct,HOP_API:()=>ut,RELAY_API:()=>lt,acrossHealth:()=>Dr,acrossSuggestedFees:()=>dt,hopHealth:()=>Mr,hopQuote:()=>pt,relayHealth:()=>qr,relayPrepare:()=>Hr,relayQuote:()=>xe});async function Dr(e={}){try{return{ok:!0,estimatedFillTimeSec:(await dt({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 dt(e={},t={}){let{token:r,destinationToken:n=r,originChainId:i,destinationChainId:o,amount:a}=e;if(!r||i==null||o==null||!a)throw new Error("acrossSuggestedFees requires token, originChainId, destinationChainId, amount");let s=new URLSearchParams({token:r,destinationToken:n,originChainId:String(i),destinationChainId:String(o),amount:String(a)}),f=(t.baseUrl||process.env.ACROSS_API_URL||ct).replace(/\/$/,"");return C(`${f}/suggested-fees?${s}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3})}async function Mr(e={}){try{let t=await pt({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 pt(e={},t={}){let{amount:r,token:n="ETH",fromChain:i="ethereum",toChain:o="arbitrum"}=e;if(!r)throw new Error("hopQuote requires amount");let a=e.slippage==null?void 0:Math.round(Number(e.slippage)*100),s=L({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:i!==o,requestedCapBps:e.maxSlippageBps??e.slippageBps??a});if(!s.executable)throw new Error(`hop: route requires ${s.requiredBps} bps above cap ${s.capBps}`);let f=new URLSearchParams({amount:String(r),token:n,fromChain:i,toChain:o,slippage:String(s.selectedBps/100)}),l=(t.baseUrl||process.env.HOP_API_URL||ut).replace(/\/$/,""),d=await C(`${l}/quote?${f}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3}),c=d?.estimatedRecieved||d?.estimatedReceived;return c?N(d,{chainId:Number(e.originChainId||e.chainId||Lr[i]||0),venue:d?.tx?.to||"hop",amountOut:c,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:i!==o,requestedCapBps:e.maxSlippageBps??e.slippageBps??a}):{...d,autoSlippagePolicy:s}}async function qr(e={}){try{let t=await xe({user:j,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 xe(e={},t={}){let{user:r=j,originChainId:n,destinationChainId:i,originCurrency:o="0x0000000000000000000000000000000000000000",destinationCurrency:a="0x0000000000000000000000000000000000000000",amount:s,tradeType:f="EXACT_INPUT"}=e;if(n==null||i==null||!s)throw new Error("relayQuote requires originChainId, destinationChainId, amount");let l=L({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(i),requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!l.executable)throw new Error(`relay: route requires ${l.requiredBps} bps above cap ${l.capBps}`);let d=(t.baseUrl||process.env.RELAY_API_URL||lt).replace(/\/$/,""),c=await C(`${d}/quote`,{method:"POST",body:{user:r,originChainId:Number(n),destinationChainId:Number(i),originCurrency:o,destinationCurrency:a,amount:String(s),tradeType:f,slippageTolerance:String(l.selectedBps)},fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),u=c?.details?.currencyOut?.amount;return!u||!/^\d+$/.test(String(u))?{...c,autoSlippagePolicy:l}:N(c,{chainId:Number(n),venue:c?.steps?.[0]?.items?.[0]?.data?.to||"relay",amountOut:u,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(i),requestedCapBps:e.maxSlippageBps??e.slippageBps})}async function Hr(e={},t={}){let r=await xe(e,t),n=Number(e.originChainId),i=(r.steps||[]).flatMap(s=>(s.items||[]).filter(f=>f?.data?.to&&f?.data?.data).map(f=>({stepId:s.id,...f.data})));if(!i.length)throw new Error("relay: quote returned no executable transaction items");let o=String(r?.autoSlippage?.venue||"").toLowerCase();if(i.some(s=>String(s.to).toLowerCase()!==o))throw new Error("relay: route includes a separate approval/transaction that is not yet safely bound");let a=i.map(s=>({chainId:n,from:s.from||e.user,to:s.to,data:s.data,value:s.value??"0x0",...s.gasLimit!=null||s.gas!=null?{gasLimit:s.gasLimit??s.gas}:{},slippageGuard:F(r.autoSlippage,{chainId:n,venue:s.to,data:s.data})}));return O({provider:"relay",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:n,quote:r,autoSlippage:r.autoSlippage,transactions:a},{provider:"relay",kind:"relay-tx"})}var ct,ut,lt,Lr,re=B(()=>{T();P();J();R();ct="https://across.to/api",ut="https://api.hop.exchange/v1",lt="https://api.relay.link",Lr={ethereum:1,optimism:10,bsc:56,polygon:137,arbitrum:42161,avalanche:43114,base:8453}});var en=Object.freeze(["blockNumber","nativeBalance","tokenBalance","resolveToken","resolvePools","scanBlocks","scoreRisk","quote","sellSimulation","prepareUnsignedTx"]),tn=Object.freeze({LIVE:"LIVE",CACHED:"CACHED",STALE:"STALE",UNKNOWN:"UNKNOWN",UNAVAILABLE:"UNAVAILABLE"}),rn=Object.freeze({PASS:"PASS",CAUTION:"CAUTION",FAIL:"FAIL",UNKNOWN:"UNKNOWN"});var U=Object.freeze({FULL:"FULL",NO_GAS:"NO_GAS",FAILED:"FAILED"});var ke=e=>{try{return e==null||e===""?null:BigInt(String(e).split(".")[0])}catch{return null}};function Oe(e){let{source:t,amountOut:r,minOut:n=null,gasUsd:i=null,feeUsd:o=null,oracleFeeBps:a=0,estimatedGas:s=null,liquidityUsd:f=null,error:l=null,executionReady:d=!1,meta:c={}}=e||{};if(l||r==null)return{source:t,quality:U.FAILED,amountOut:null,error:l||"no amountOut returned"};let u=ke(r);if(u==null||u<=0n)return{source:t,quality:U.FAILED,amountOut:null,error:"non-positive amountOut"};let p=Number(a);return{source:t,quality:i==null?U.NO_GAS:U.FULL,amountOut:u.toString(),minOut:ke(n)?.toString()??null,gasUsd:i,feeUsd:o,oracleFeeBps:Number.isFinite(p)&&p>0?Math.floor(p):0,estimatedGas:s==null?null:String(s),liquidityUsd:f==null?null:Number(f),executionReady:d,meta:c}}function _e(e,{destPriceUsd:t=null,destDecimals:r=null,liquidityFirst:n=!0,liquidityBandBps:i=50,gasPriceWei:o=null,nativePriceUsd:a=null}={}){let s=e.filter(g=>g.quality!==U.FAILED),f=e.filter(g=>g.quality===U.FAILED),l=t!=null&&t>0&&r!=null&&r>=0,d=Number(o),c=Number(a),u=Number.isFinite(d)&&d>0&&Number.isFinite(c)&&c>0,p=s.map(g=>{let y=BigInt(g.amountOut),_=0n,v=!1,k=!1,V=BigInt(g.oracleFeeBps??0),Se=V>0n?y*V/10000n:0n;if(l){let K=g.gasUsd,oe=Number(g.meta?.gasUnits??g.estimatedGas);if(K==null&&u&&Number.isFinite(oe)&&oe>0){let q=oe*d/1e18*c;Number.isFinite(q)&&q>=0&&(K=q,k=!0)}let Ce=(K??0)+(g.feeUsd??0);if(Ce>0){let q=Ce/t*10**r;Number.isFinite(q)&&q>=0&&(_=BigInt(Math.floor(q)),v=!0)}else K===0&&(v=!0)}let Ie=_+Se,wt=y>Ie?y-Ie:0n;return{...g,grossOut:y.toString(),netOut:wt.toString(),costInDest:_.toString(),oracleFeeInDest:Se.toString(),costAccounted:v,gasEstimated:k}}),m=Number(i)>0?Number(i):0,E=p.reduce((g,y)=>BigInt(y.netOut)>g?BigInt(y.netOut):g,0n),h=g=>E>0n?Number((E-BigInt(g))*10000n/E):0,A=[],w=p.slice().sort((g,y)=>BigInt(y.netOut)>BigInt(g.netOut)?1:-1)[0]??null;p.sort((g,y)=>{let _=h(g.netOut)<=m?0:1,v=h(y.netOut)<=m?0:1;if(n&&m>0&&_!==v)return _-v;if(n&&m>0){let k=g.liquidityUsd??-1,V=y.liquidityUsd??-1;if(k!==V)return V-k}return BigInt(y.netOut)>BigInt(g.netOut)?1:-1}),n&&m>0&&w&&p[0]&&p[0].source!==w.source&&A.push(`liquidity-first: chose ${p[0].source} (liquidity $${p[0].liquidityUsd??"unknown"}) over best-price ${w.source} within ${m} bps`);let I=p.filter(g=>!g.costAccounted).map(g=>g.source);l?I.length&&A.push(`gas not reported by: ${I.join(", ")}. These are ranked on gross output and may be overstated relative to gas-measured routes.`):A.push("destination price/decimals unavailable: ranked on GROSS output. Gas is not included, so a cheap-looking route may cost more to execute.");let x=p[0];if(l&&x&&x.costAccounted===!1){let g=p.find(y=>y.costAccounted&&h(y.netOut)<=m);g&&A.push(`winner ${x.source} has UNMEASURED gas; gas-measured ${g.source} is within ${m} bps and may net more once ${x.source}'s real gas is paid \u2014 prefer it if unsure.`)}let b=p.filter(g=>g.gasEstimated).map(g=>g.source);b.length&&A.push(`gas ESTIMATED (from gas units x current gas price, not measured) for: ${b.join(", ")}. Net includes this estimate so the ranking is gas-inclusive, but the on-chain gas may differ.`);let S=null,$=null;if(p.length>=2&&p[0].costAccounted&&p[1].costAccounted){let g=BigInt(p[0].netOut),y=BigInt(p[1].netOut);y>0n&&(S=Number((g-y)*10000n/y),$=`${p[0].source} vs ${p[1].source}`)}return{best:p[0]??null,routes:p,failed:f,improvementBps:S,spreadBasis:$,rankedOn:l?"net-of-cost":"gross",warnings:A}}async function Be(e,{timeoutMs:t=12e3}={}){let r=(i,o)=>Promise.race([i,new Promise((a,s)=>setTimeout(()=>s(new Error(`${o}: timeout`)),t))]);return(await Promise.allSettled(e.map(i=>r(Promise.resolve().then(i.run),i.source)))).map((i,o)=>{let a=e[o].source;return i.status==="rejected"?Oe({source:a,error:String(i.reason?.message||i.reason)}):Oe({source:a,...i.value})})}ye();T();P();R();Z();T();P();R();T();P();R();T();P();import{TypedDataEncoder as uo,getAddress as lo,isAddress as po}from"ethers";var oo=Object.freeze({READ:"read",PREPARE:"prepare",EXECUTE:"execute",AUTONOMOUS:"autonomous"});J();R();var Eo=Object.freeze({1:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",100:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",42161:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",8453:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41"}),yo=Object.freeze({1:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",100:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",42161:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",8453:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110"});var Ao=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"}]}),xo=Object.freeze({OrderCancellations:[{name:"orderUids",type:"bytes[]"}]});import{Interface as it,getAddress as Do,isAddress as Mo}from"ethers";T();var ot={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}},Io=new Map(Object.values(ot).map(e=>[e.chainId,e]));import{Interface as Br,getAddress as To}from"ethers";var Ro=new Br(["function allowance(address owner,address spender) view returns (uint256)","function balanceOf(address account) view returns (uint256)"]);T();var Uo=Object.freeze({1:"ethereum",10:"optimism",56:"bsc",137:"polygon",8453:"base",42161:"arbitrum",43114:"avalanche",999:"hyperevm",4663:"robinhood"});P();R();var zo=new it(["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)"]),Go=new it(["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)"]);import{AbiCoder as Rr,Interface as at,getAddress as Qo,isAddress as Wo,keccak256 as Jo}from"ethers";P();R();var ni=Rr.defaultAbiCoder();var oi=new at(["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)","function quoteExactOutputSingle(((address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks) poolKey,bool zeroForOne,uint128 exactAmount,bytes hookData) params) returns (uint256 amountIn, uint256 gasEstimate)"]),ii=new at(["function execute(bytes commands,bytes[] inputs,uint256 deadline) payable"]);T();var $r="https://coins.llama.fi",Pr="https://api.llama.fi";function Ur(e={}){return(e.baseUrl||process.env.DEFILLAMA_COINS_URL||$r).replace(/\/$/,"")}function Fr(e={}){return(e.baseUrl||process.env.DEFILLAMA_API_URL||Pr).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 C(`${Ur(t)}/prices/current/${r}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function st(e={}){return C(`${Fr(e)}/protocols`,{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs??2e4})}var M=e=>{let t=Number(e);return Number.isFinite(t)?t:null};function ft(e){if(!Array.isArray(e))return null;let t=0,r=!1;for(let n of e){let i=M(n?.amountUSD);i!=null&&(t+=i,r=!0)}return r?t:null}var D=e=>String(e??"").toLowerCase().replace(/[^a-z0-9]/g,""),mt=Object.freeze({across:["across"],relay:["relaychain","relay"],lifi:["jumper-(li.fi-powered)","lifi"],stargate:["stargate-v2","stargate-v1","stargate"],hop:["hop-protocol","hop"],debridge:["debridge"],synapse:["synapse"],connext:["connext"],cbridge:["celer-bridge","celer-cbridge","cbridge"],celer:["celer-bridge","celer-cbridge","cbridge"],squid:["squid"],symbiosis:["symbiosis"],wormhole:["wormhole"],mayan:["mayan"],allbridge:["allbridge"],thorchain:["thorchain"]});async function jr(e={}){try{let t=await st({...e,baseUrl:e.defillamaApiBaseUrl,timeoutMs:e.defillamaTimeoutMs??Math.min(Number(e.timeoutMs??5e3),5e3)});return Array.isArray(t)?t:[]}catch{return[]}}function Vr(e,t={}){let r=D(t.tool||t.provider||t.bridge||t.protocol),n=[];return e==="lifi"&&r&&r!=="lifi"&&n.push(...mt[r]||[r]),n.push(...mt[D(e)]||[e]),n}function zr(e,t,r={}){let n=Array.isArray(e)?e:[],i=Vr(t,r).map(D).filter(Boolean);for(let o of i){let a=n.find(f=>D(f?.slug)===o||D(f?.name)===o),s=M(a?.tvl);if(s!=null)return{liquidityUsd:s,protocol:a?.name??a?.slug??o}}for(let o of i){let a=n.find(f=>{let l=D(f?.category);return!l.includes("bridge")&&!l.includes("crosschain")?!1:D(f?.slug).includes(o)||D(f?.name).includes(o)}),s=M(a?.tvl);if(s!=null)return{liquidityUsd:s,protocol:a?.name??a?.slug??o}}return null}function ht({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:i,taker:o,opts:a={}}){let s=[],f=null,l=async(d,c={})=>(f||=jr(a),zr(await f,d,c));return s.push({source:"lifi",run:async()=>{let d=await ee({fromChain:e,toChain:t,fromToken:r,toToken:n,fromAmount:i},a),c=d?.estimate??d?.[0]?.estimate,u={tool:d?.tool??d?.toolDetails?.name,durationSeconds:M(c?.executionDuration)},p=await l("lifi",u);return{amountOut:c?.toAmount,minOut:c?.toAmountMin,gasUsd:ft(c?.gasCosts),feeUsd:ft(c?.feeCosts),oracleFeeBps:d?.oracleFee?.applies?d.oracleFee.bps:0,liquidityUsd:p?.liquidityUsd??null,meta:{...u,liquidityProtocol:p?.protocol,oracleFee:d?.oracleFee??null}}}}),s.push({source:"relay",run:async()=>{let{relayQuote:d}=await Promise.resolve().then(()=>(re(),te)),u=(await d({user:o,originChainId:e,destinationChainId:t,originCurrency:r,destinationCurrency:n,amount:String(i)},a))?.details,p={durationSeconds:M(u?.timeEstimate),rate:u?.rate},m=await l("relay",p);return{amountOut:u?.currencyOut?.amount,minOut:u?.currencyOut?.minimumAmount,gasUsd:M(u?.totalImpact?.usd)!=null?Math.abs(M(u.totalImpact.usd)):null,liquidityUsd:m?.liquidityUsd??null,meta:{...p,liquidityProtocol:m?.protocol}}}}),s.push({source:"across",run:async()=>{let{acrossSuggestedFees:d}=await Promise.resolve().then(()=>(re(),te)),c=await d({token:r,destinationToken:n,originChainId:e,destinationChainId:t,amount:String(i)},a),u=c?.totalRelayFee?.total,p=null;if(u!=null)try{let E=BigInt(String(i))-BigInt(String(u));E>0n&&(p=E.toString())}catch{}let m=await l("across");return{amountOut:p,gasUsd:null,liquidityUsd:m?.liquidityUsd??null,meta:{derivedFromFees:!0,durationSeconds:M(c?.estimatedFillTimeSec),limits:c?.limits?{min:c.limits.minDeposit,max:c.limits.maxDeposit}:void 0,liquidityProtocol:m?.protocol}}}}),s}Z();var Gr={1:"ethereum",10:"optimism",56:"bsc",137:"polygon",8453:"base",42161:"arbitrum",43114:"avax"};async function Kr(e,t,r){let n=Gr[Number(e)];if(!n)return{priceUsd:null,decimals:null};let i=`${n}:${t}`;try{let a=(await Ae([i],r))?.coins?.[i],s=Number(a?.price),f=Number(a?.decimals);return{priceUsd:Number.isFinite(s)?s:null,decimals:Number.isFinite(f)?f:null}}catch{return{priceUsd:null,decimals:null}}}async function gt(e,t={}){let{fromChainId:r,toChainId:n,tokenIn:i,tokenOut:o,amountIn:a}=e;if(r==null||n==null||!i||!o||a==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 s=Kr(n,o,t),f=ht({...e,opts:t}),[l,d]=await Promise.all([Be(f,{timeoutMs:t.timeoutMs??15e3}),s]),c=_e(l,{destPriceUsd:d.priceUsd,destDecimals:e.decimalsOut??d.decimals,liquidityBandBps:t.liquidityBandBps??50}),u=c.routes.map(p=>({source:p.source,seconds:p.meta?.durationSeconds??null})).filter(p=>p.seconds!=null);return{kind:"bridge",fromChainId:r,toChainId:n,tokenIn:i,tokenOut:o,amountIn:String(a),...c,durations:u,sourcesTried:f.length,sourcesAnswered:l.filter(p=>p.quality!==U.FAILED).length,note:Yr(c,f.length)}}function Xr(e){let t=e?.meta?.oracleFee;return t?.applies?` \xB7 ${Ze(t)}`:""}function Yr(e,t){if(!e.best)return"no source returned a usable route";let r=e.routes.length,n=Xr(e.best);if(r===1)return`only 1 of ${t} sources answered, so this is the ONLY route, not a proven best one. Treat it as unbenchmarked.`+n;if(e.improvementBps!=null){let i=e.improvementBps,o=i/100;if(i<.01)return`best of ${r} routes, ranked on ${e.rankedOn}: effectively tied with the runner-up (${e.spreadBasis}), inside quote noise. Re-quote before you size up.`+n;let a=o>=.01?`${o.toFixed(2)}%`:`${i.toFixed(2)}bps`;return`best of ${r} routes, ranked on ${e.rankedOn}: ${a} better than the runner-up (${e.spreadBasis})`+n}return`best of ${r} routes, ranked on ${e.rankedOn}. No spread quoted: the top routes report cost differently, so the margin is not comparable.`+n}R();var Qr=/^0x[0-9a-fA-F]{40}$/,Wr=new Set(["0x0000000000000000000000000000000000000000","0x000000000000000000000000000000000000dead","0x0000000000000000000000000000000000000001","0x00000000000000000000000000000000000a1ce5"].map(e=>e.toLowerCase())),Jr=100,ne={relay:async({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:i,taker:o},a)=>{let{relayPrepare:s}=await Promise.resolve().then(()=>(re(),te)),f=await s({user:o,originChainId:e,destinationChainId:t,originCurrency:r,destinationCurrency:n,amount:String(i)},a);return{transactions:f.transactions||[],amountOut:f.quote?.details?.currencyOut?.amount??null,minOut:f.quote?.details?.currencyOut?.minimumAmount??null,durationSeconds:f.quote?.details?.timeEstimate??null}},lifi:async({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:i,taker:o,isHolder:a},s)=>{let{lifiPrepare:f}=await Promise.resolve().then(()=>(ye(),nt)),l=await f({fromChain:e,toChain:t,fromToken:r,toToken:n,fromAmount:i,fromAddress:o,isHolder:a,feeAction:"bridge"},s);return{transactions:l.transaction?[l.transaction]:[],requiresApproval:l.requiresApproval??null,amountOut:l.quote?.estimate?.toAmount??null,minOut:l.quote?.estimate?.toAmountMin??null,durationSeconds:l.quote?.estimate?.executionDuration??null}}};function Gi(){return Object.keys(ne)}async function Ki(e,t={}){let{taker:r,fromChainId:n,toChainId:i}=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(!Qr.test(r))throw new Error(`taker must be a valid 20-byte address, got "${r}"`);if(Wr.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 o=await gt(e,t);if(!o.best)return{ok:!1,reason:"no source returned a usable bridge route",comparison:o};let a=e.source||o.best.source,s=o.routes.find(h=>h.source===a);if(!s)return{ok:!1,reason:`source "${a}" returned no usable route`,comparison:o};let f=ne[a];if(!f){let h=o.routes.find(A=>ne[A.source]&&A.source!==a);return{ok:!1,reason:`${a} 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:a,comparison:o}}let l;try{l=await f(e,t)}catch(h){let A=typeof h?.body=="string"?h.body:h?.body?JSON.stringify(h.body):"",w=[String(h?.message||h),A].filter(Boolean).join(" :: "),I=/allowance/i.test(w),x=!I&&/not enough|insufficient|balance/i.test(w),b=o.routes.find(S=>ne[S.source]&&S.source!==a);return{ok:!1,reason:I?`${a} will not build calldata until the token approval exists on-chain. Approve first, then prepare again. Underlying: ${w}`:x?`${a} refused to build: ${w}. Quoting works for any address; preparing needs the real funded wallet on chain ${n}.`:`${a} bridge prepare failed: ${w}`,failureKind:I?"approval-required-first":x?"taker-not-funded":"provider-error",...b?{alternative:b.source}:{},comparison:o}}let d=l.transactions||[];if(!d.length)return{ok:!1,reason:`${a} returned no executable transaction for this route`,failureKind:"provider-error",comparison:o};let c=d.filter(h=>h.chainId!=null&&Number(h.chainId)!==Number(n));if(c.length)return{ok:!1,reason:`${a} returned a transaction for chain ${c[0].chainId} but the origin chain is ${n}. Refusing to hand over a mismatched artifact.`,failureKind:"chain-mismatch",comparison:o};let u=e.driftToleranceBps??Jr,p=null,m=null;if(l.amountOut!=null&&s.grossOut!=null)try{let h=BigInt(s.grossOut),A=BigInt(l.amountOut);h>0n&&(p=Number((A-h)*10000n/h),p<-u&&(m=`route moved ${(p/100).toFixed(2)}% against you since the comparison (tolerance ${(u/100).toFixed(2)}%). Re-compare before signing.`))}catch{}let E=[...m?[m]:[],...o.warnings||[],`Bridging is NOT atomic: the origin transaction succeeding does not mean funds arrived on chain ${i}. Expect ~${l.durationSeconds!=null?`${l.durationSeconds}s`:"minutes"} before the destination credits, and do not re-send if it is pending.`];return d.length>1&&E.push(`This route needs ${d.length} transactions signed IN ORDER. Signing only the first leaves funds approved but not bridged.`),O({ok:!0,chosen:{source:a,wasWinner:a===o.best.source,netOut:s.netOut,grossOut:s.grossOut,gasUsd:s.gasUsd},artifactKind:"unsigned-transaction-sequence",fromChainId:Number(n),toChainId:Number(i),transactionCount:d.length,transactions:d,requiresApproval:l.requiresApproval??null,minOut:l.minOut??null,durationSeconds:l.durationSeconds??null,destination:d[0]?.to??null,unsigned:!0,signedBy:"user-wallet",driftBps:p,warnings:E,runnersUp:o.routes.filter(h=>h.source!==a).map(h=>({source:h.source,netOut:h.netOut,gasUsd:h.gasUsd})),comparison:{rankedOn:o.rankedOn,sourcesAnswered:o.sourcesAnswered,sourcesTried:o.sourcesTried,improvementBps:o.improvementBps},note:`UNSIGNED. ${d.length} transaction(s) on chain ${n}, crediting chain ${i}. Verify every destination address before signing.`},{provider:"router",kind:"best-bridge"})}export{Ki as prepareBestBridgeRoute,Gi as supportedBridgePreparers};
1
+ var bt=Object.defineProperty;var R=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var ve=(e,t)=>{for(var r in t)bt(e,r,{get:t[r],enumerable:!0})};import V from"node:net";import yt from"node:dns";function W(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=p=>{if(!p)return[];let c=p.split(":"),l=c.at(-1);if(l?.includes(".")){let u=l.split(".").map(Number);if(u.length!==4||u.some(w=>!Number.isInteger(w)||w<0||w>255))return null;c.splice(c.length-1,1,(u[0]<<8|u[1]).toString(16),(u[2]<<8|u[3]).toString(16))}return c.some(u=>!/^[0-9a-f]{1,4}$/.test(u))?null:c.map(u=>Number.parseInt(u,16))},[n,i]=t.split("::"),o=r(n),s=r(i);if(!o||!s)return null;let a=t.includes("::"),f=8-o.length-s.length;if(!a&&f!==0||a&&f<1)return null;let d=[...o,...Array(Math.max(0,f)).fill(0),...s];return d.length!==8?null:Uint8Array.from(d.flatMap(p=>[p>>8,p&255]))}function ae(e,t,r){let n=Math.floor(r/8),i=r%8;for(let s=0;s<n;s+=1)if(e[s]!==t[s])return!1;if(!i)return!0;let o=255<<8-i;return(e[n]&o)===(t[n]&o)}function ce(e){if(V.isIPv4(e)){let t=e.split(".").map(Number);return!(t[0]===0||t[0]===10||t[0]===127||t[0]>=224||t[0]===100&&t[1]>=64&&t[1]<=127||t[0]===169&&t[1]===254||t[0]===172&&t[1]>=16&&t[1]<=31||t[0]===192&&(t[1]===0||t[1]===2||t[1]===168)||t[0]===192&&t[1]===88&&t[2]===99||t[0]===198&&(t[1]===18||t[1]===19||t[1]===51)||t[0]===203&&t[1]===0&&t[2]===113)}if(V.isIPv6(e)){let t=W(e);if(!t)return!1;let r=W("::ffff:0:0");return ae(t,r,96)?ce([...t.slice(12)].join(".")):ae(t,W("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([i,o])=>ae(t,W(i),o)):!1}return!1}function At(e){let t;try{t=new URL(String(e))}catch{return{ok:!1,error:`not a valid URL: ${String(e).slice(0,120)}`}}if(t.protocol!=="http:"&&t.protocol!=="https:")return{ok:!1,error:`refused protocol ${t.protocol} (only http/https)`};let r=t.hostname.toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,"");if(Et.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=V.isIP(r);return n!==0&&!ce(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function ue(e,{lookupFn:t=yt.promises.lookup}={}){let r=At(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:V.isIPv6(r.host)?6:4}]};let n;try{n=await t(r.host,{all:!0,verbatim:!0})}catch{return{ok:!1,error:`refused: ${r.host} did not resolve`}}return!Array.isArray(n)||n.length===0||n.some(i=>!ce(i.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function le({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let i=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),o=new Map,s=c=>(Array.isArray(c)?c:[c]).map(l=>typeof l=="string"?{address:l}:l).filter(l=>l&&l.address).map(l=>({address:l.address,family:l.family||(V.isIPv6(l.address)?6:4)})),a=(c,l,u)=>{o.set(i(c),s(typeof l=="string"?[{address:l,family:u}]:l))},f=c=>{let l=i(c);if(V.isIP(l))return[{address:l,family:V.isIPv6(l)?6:4}];let u=o.get(l);if(!u||!u.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return u},d=new r({connect:{lookup(c,l,u){let w;try{w=f(c)}catch(y){return u(y)}return l?.all?u(null,w):u(null,w[0].address,w[0].family)}}}),p=xt((c,l={})=>n(c,{...l,dispatcher:d}),a);return{dispatcher:d,fetch:p,pin:a,resolve:f,async close(){try{await d.destroy()}catch{}}}}function xt(e,t){if(typeof e!="function")throw new Error("markPinCapableFetch: fetchImpl must be a function");if(typeof t!="function")throw new Error("markPinCapableFetch: pin must be a function");return e[de]=Object.freeze({pin:t}),e}function pe(e){return typeof e=="function"&&typeof e[de]?.pin=="function"}function Be(e,t,r){if(!pe(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[de].pin(t,r)}var Et,de,Re=R(()=>{Et=new Set(["localhost","metadata.google.internal","metadata.goog"]);de=Symbol.for("oracle.egressGuard.pinCapableFetch")});import{createHash as St}from"node:crypto";function Ot(e){let t=String(e||"").toLowerCase();return De.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function Nt(e){let t={};for(let[r,n]of Object.entries(e||{}))Ot(r)||(t[r]=n);return t}function Tt(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 _t(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function Bt(e,t,r,n={}){let i={};for(let[p,c]of Object.entries(r||{}))i[p.toLowerCase()]=c;let o=Object.keys(i).filter(p=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(p)),a=[...new Set([...De,...o])].sort().map(p=>`${p}=${i[p]??""}`).join(`
2
+ `),f=St("sha256").update(a).digest("hex").slice(0,32),d=`${n.untrustedUrl?"untrusted":"trusted"}:${n.maxResponseBytes??"unbounded"}`;return`${e} ${t} ${d} ${f}`}function Rt(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,$e):Math.min(250*2**e,$e)+Math.floor(Math.random()*100)}function G(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function me(e,t,r){return G(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function K(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function $t(e){return e?e.byteLength??e.length??0:0}async function Ue(e,t,{url:r,truncate:n=!1,onOversize:i}={}){if(t==null)return await e.text();let o=Number(e.headers?.get?.("content-length"));if(Number.isFinite(o)&&o>t&&(K(e),!n))throw me(r,`content-length ${o}`,t);let s=e.body?.getReader?.();if(!s){let c=await e.text(),l=Buffer.byteLength(c,"utf8");if(l>t){if(!n)throw me(r,`body ${l} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let a=[],f=0,d=!1;try{for(;;){let{value:c,done:l}=await s.read();if(l)break;if(c&&(a.push(Buffer.from(c)),f+=$t(c),f>t)){d=!0;break}}}finally{if(d)try{await s.cancel()}catch{}try{s.releaseLock?.()}catch{}}if(d&&(typeof i=="function"&&i(),!n))throw me(r,`streamed ${f} bytes`,t);let p=Buffer.concat(a);return(d?p.subarray(0,t):p).toString("utf8")}function Fe(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Lt(e,{fetchImpl:t,method:r,headers:n,body:i,timeoutMs:o,lookupFn:s,realFetch:a,untrustedUrl:f=!1,maxResponseBytes:d=null,importUndici:p,validateResponse:c,signal:l}){let u=new AbortController,w=setTimeout(()=>u.abort(),o),y=l?typeof AbortSignal.any=="function"?AbortSignal.any([l,u.signal]):l:u.signal,m=null,E=t,v=s?{lookupFn:s}:{};if(f&&!a&&!pe(E))throw G(`HTTP refused ${e}: untrustedUrl requires a pin-capable fetchImpl (see markPinCapableFetch in egress-guard.mjs) or no fetchImpl override so Oracle can pin the connection itself`);let N=async(b,{status:S=null}={})=>{let x=await ue(b,v);if(!x.ok)throw G(S==null?`HTTP refused ${b}: ${x.error}`:`HTTP redirect to ${b} ${x.error}`,S==null?{}:{status:S});let g=new URL(b).hostname;if(a){if(m&&(await m.close(),m=null),!m)try{m=await le({requireUndici:!0,...p?{importUndici:p}:{}})}catch(h){throw G(S==null?`HTTP refused ${b}: ${h?.message||h}`:`HTTP redirect to ${b} refused: ${h?.message||h}`,S==null?{}:{status:S})}m.pin(g,x.addresses),E=m.fetch}else Be(E,g,x.addresses);return x};try{let b=String(e),S={...n||{}};f&&await N(b);for(let x=0;x<=Le;x+=1){let g=await E(b,{method:r,headers:S,body:i,signal:y,redirect:"manual"});if(kt.has(g.status)){if(r!=="GET"&&r!=="HEAD"){let C=await Ue(g,d??vt,{url:b,truncate:!0}),T=new Error(`HTTP ${g.status} ${r} ${b} redirected non-idempotent request`);throw T.status=g.status,T.body=Fe(C)??C.slice(0,300),T}if(x===Le)throw K(g),new Error(`HTTP redirect loop for ${e}`);let I=g.headers?.get?.("location"),O;try{O=Tt(I,b)}catch(C){throw K(g),C}let B=!_t(O,b);if(K(g),B&&(S=Nt(S)),f)await N(O,{status:g.status});else if(B){let C=await ue(O,v);if(!C.ok){let T=new Error(`HTTP redirect from ${b} ${C.error}`);throw T.status=g.status,T.retryable=!1,T}a&&C.addresses?.length&&(m||(m=await le(p?{importUndici:p}:{})),m&&(m.pin(new URL(O).hostname,C.addresses),E=m.fetch))}b=O;continue}if(typeof c=="function")try{await c(g,{url:b})}catch(I){throw K(g),G(I?.message||String(I))}let h=await Ue(g,d,{url:b,onOversize:()=>u.abort()}),A=Fe(h);if(!g.ok){let I=new Error(`HTTP ${g.status} ${r} ${b}`);throw I.status=g.status,I.retryAfter=g.headers?.get?.("retry-after")??null,I.body=A??h.slice(0,300),I}return A??h}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(w),m&&await m.close()}}async function k(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,i=(t.method||"GET").toUpperCase(),o={Accept:"application/json",...t.headers||{}},s=t.body;s!=null&&typeof s!="string"&&(o["Content-Type"]=o["Content-Type"]||"application/json",s=JSON.stringify(s));let a=Number.isInteger(t.retries)?Math.max(t.retries,0):Ct,f=t.lookupFn,d=!t.fetchImpl,p=t.untrustedUrl===!0,c=t.importUndici,l=t.validateResponse,u=t.signal,w=Number(t.maxResponseBytes),y=Number.isFinite(w)&&w>0?Math.floor(w):null,m=async()=>{let S;for(let x=0;x<=a;x++){u?.throwIfAborted?.();try{return await Lt(e,{fetchImpl:r,method:i,headers:o,body:s,timeoutMs:n,lookupFn:f,realFetch:d,untrustedUrl:p,maxResponseBytes:y,importUndici:c,validateResponse:l,signal:u})}catch(g){S=g;let h=g?.status,A=g?.name==="AbortError"||g?.name==="TimeoutError"||u?.aborted,I=new Set([408,425,429]),O=g?.retryable===!1?!1:h!=null?I.has(h)||It.has(h)&&Pe.has(i):!A&&Pe.has(i);if(x===a||!O)throw g;let B=Rt(x,g?.retryAfter);u?await new Promise((C,T)=>{let X=setTimeout(C,B);u.addEventListener("abort",()=>{clearTimeout(X),T(u.reason||new DOMException("Aborted","AbortError"))},{once:!0})}):await Pt(B)}}throw S};if(!(t.dedupe!==!1&&!u&&i==="GET"&&s==null))return m();let v=Bt(i,e,o,{untrustedUrl:p,maxResponseBytes:y}),N=fe.get(v);if(N)return N;let b=m().finally(()=>fe.delete(v));return fe.set(v,b),b}var It,Pe,Ct,$e,De,kt,Le,vt,fe,Pt,$=R(()=>{Re();It=new Set([408,425,429,500,502,503,504]),Pe=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Ct=2,$e=4e3,De=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],kt=new Set([301,302,303,307,308]),Le=3,vt=64*1024;fe=new Map;Pt=e=>new Promise(t=>setTimeout(t,e))});import{readFileSync as Ut}from"node:fs";import{homedir as Ft}from"node:os";import{join as Q}from"node:path";function Dt(){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=Ft();if(process.env.ORACLE_PUBLIC_DESKTOP==="1"){let r=(process.env.ORACLE_CONFIG_DIR||Q(t,".config","oracle")).trim();return[e,Q(r,"exec.env")].filter(Boolean)}return[e,Q(t,".config","oracle","exec.env"),Q(t,".config","mad-desk","exec.env")].filter(Boolean)}function Me(e,t,r){let n=e??process.env[t]??process.env[r];if(!String(n||"").trim())for(let i of Dt())try{let o=Ut(i,"utf8"),s=o.match(new RegExp(`^${t}=(.*)$`,"m"))||o.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 qe=R(()=>{});var He=R(()=>{});import{createHash as Mt,createHmac as Ve,timingSafeEqual as qt}from"node:crypto";function Z(e){return Array.isArray(e)?`[${e.map(Z).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${Z(e[t])}`).join(",")}}`:JSON.stringify(e??null)}function ze(e,{required:t=!1}={}){try{return Me(e,"ORACLE_ROUTE_ATTESTATION_SECRET","MAD_ROUTE_ATTESTATION_SECRET")}catch(r){if(t)throw r;return null}}function we(e){let{signature:t,...r}=e;return r}function Ge(e,{secret:t}={}){let r=ze(t);return r?{...e,signature:Ve("sha256",r).update(Z(we(e))).digest("hex")}:e}function Ht(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 Mt("sha256").update(Buffer.from(t.slice(2),"hex")).digest("hex")}function D(e,{chainId:t,venue:r,data:n,secret:i}={}){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");let o=ze(i);if(o){let u=Ve("sha256",o).update(Z(we(e))).digest("hex");if(!jt(e.signature,u))throw new Error("auto-slippage guard signature mismatch \u2014 refusing to bind a guard this Oracle did not issue")}let s=Number(e.selectedBps),a=Number(e.capBps);if(!Number.isInteger(s)||s<0||s>J||!Number.isInteger(a)||a<0||a>J||s>a)throw new Error("auto-slippage guard bounds are invalid");let f=BigInt(e.quoteAmountOut??0),d=BigInt(e.minAmountOut??0);if(f<=0n||d<=0n)throw new Error("auto-slippage guard amounts must be positive");let p=f*BigInt(1e4-s),c=p/10000n;if(p%10000n!==0n&&(c+=1n),d<c)throw new Error("auto-slippage guard is under-protected relative to its quote");let l=Gt(n);if(l!=null&&l!==d)throw new Error(`auto-slippage: calldata encodes floor ${l}, not the guard floor ${d} \u2014 refusing to bind`);return Ge({...we(e),calldataHash:Ht(n)},{secret:i})}function jt(e,t){let r=Buffer.from(String(e??""),"utf8"),n=Buffer.from(String(t??""),"utf8");return r.length!==n.length||r.length===0?!1:qt(r,n)}function he(e,t=0){let r=Number(e);return Number.isFinite(r)?r:t}function Vt(e){let t=e==null?J: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,J)}function M({liquidityUsd:e,priceChange5m:t=0,quoteAgeMs:r=0,crossChain:n=!1,requestedCapBps:i}={}){let o=he(e,0),s=o>0?o>=25e4?5:o>=1e5?10:o>=5e4?20:o>=1e4?40:70:n?30:10,a=Math.min(60,Math.abs(he(t,0))*2),f=Math.min(40,Math.floor(Math.max(0,he(r,0))/5e3)*5),d=Math.max(25,Math.ceil(20+s+a+f)),p=Vt(i);return{mode:"auto",requiredBps:d,selectedBps:Math.min(d,p),capBps:p,executable:d<=p}}function zt({chainId:e,venue:t,quoteAmountOut:r,liquidityUsd:n,priceChange5m:i=0,quoteAgeMs:o=0,crossChain:s=!1,requestedCapBps:a,quotedAtMs:f=Date.now(),ttlMs:d=je,secret:p}={}){let c=BigInt(r??0);if(c<=0n)throw new Error("auto-slippage guard requires positive quoteAmountOut");let l=M({liquidityUsd:n,priceChange5m:i,quoteAgeMs:o,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 u=Number(f);if(!Number.isFinite(u))throw new Error("auto-slippage: quotedAtMs must be a finite number");let w=Math.min(3e4,Math.max(1e3,Number(d)||je)),y=c*BigInt(1e4-l.selectedBps),m=y/10000n;if(y%10000n!==0n&&(m+=1n),m>c&&(m=c),c>0n&&m<=0n)throw new Error(`auto-slippage: quote ${c} is too small to express a ${l.selectedBps} bps floor without rounding to zero`);let E=Number((c-m)*10000n/(c===0n?1n:c));if(E>l.capBps)throw new Error(`auto-slippage: realised floor implies ${E} bps, above cap ${l.capBps} \u2014 refusing to issue a guard weaker than advertised`);return Ge({mode:"auto",chainId:Number(e),venue:String(t||"unknown"),quoteAmountOut:c.toString(),minAmountOut:m.toString(),requiredBps:l.requiredBps,selectedBps:l.selectedBps,capBps:l.capBps,quotedAtMs:u,expiresAtMs:u+w},{secret:p})}function Gt(e){let t=String(e||"");if(!/^0x[0-9a-fA-F]+$/.test(t)||t.length<10||t.length%2!==0)return null;let r=t.slice(0,10).toLowerCase(),n=[];for(let o=10;o+64<=t.length;o+=64)n.push(t.slice(o,o+64));let i=o=>n[o]==null?null:BigInt("0x"+n[o]);switch(r){case"0x414bf389":return i(6);case"0x04e45aaf":return i(5);case"0xc04b8d59":{let o=i(0);if(o==null)return null;let s=Number(o)/32;return!Number.isInteger(s)||s<0?null:i(s+4)}case"0xb858183f":{let o=i(0);if(o==null)return null;let s=Number(o)/32;return!Number.isInteger(s)||s<0?null:i(s+3)}case"0xa026383e":return i(6);case"0x38ed1739":case"0x5c11d795":return i(1);case"0x7ff36ab5":case"0xb6f9de95":return i(0);case"0x18cbafe5":case"0x791ac947":return i(1);default:return null}}function P(e,{chainId:t,venue:r,amountOut:n,liquidityUsd:i,priceChange5m:o,crossChain:s,requestedCapBps:a,quotedAtMs:f=Date.now(),ttlMs:d}={}){let p=zt({chainId:t,venue:r,quoteAmountOut:n,liquidityUsd:i,priceChange5m:o,crossChain:s,requestedCapBps:a,quotedAtMs:f,ttlMs:d});return{...e,autoSlippage:p,amountOutMinimum:p.minAmountOut}}var J,je,U=R(()=>{qe();He();J=100,je=2e4});var z,ee=R(()=>{z="0x000000000000000000000000000000000000dEaD"});import{createHash as Kt,createHmac as Xt,timingSafeEqual as kn}from"node:crypto";function ge(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(ge).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${ge(e[r])}`).join(",")}}`}function Ke(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Xe(e=process.env){return Ke(process.env)||Ke(e)}function Jt(e){let{prepareHash:t,prepareMac:r,note:n,...i}=e||{};return i}function Zt(e){let t=Jt(e);return Kt("sha256").update(ge(t)).digest("hex")}function er(e,t=Xe()){return t?Xt("sha256",t).update(String(e)).digest("hex"):""}function _(e,{provider:t,kind:r,env:n=process.env,nowMs:i=Date.now(),expiresAtMs:o}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let s=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(s&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let a={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:s?e.oraclePrepared:!0};if(!a.provider)throw new Error("stampPrepared: provider required");if(!a.kind)throw new Error("stampPrepared: kind required");let f=Number(i),d=o==null?f+Wt:Number(o),p=d-f;if(!Number.isSafeInteger(f)||!Number.isSafeInteger(d)||p<=0||p>Qt)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let l={...a,preparedAt:f,expiresAt:d,prepareVersion:Yt},u=Zt(l),w=Xe(n),y=w?er(u,w):void 0,m={...l,prepareHash:u};return y&&(m.prepareMac=y),m}var Yt,Wt,Qt,L=R(()=>{Yt=2,Wt=300*1e3,Qt=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});import{Contract as tr,JsonRpcProvider as rr}from"ethers";function cr(e){return ar.test(String(e||""))}async function Ye(e,{contract:t=nr,rpc:r=ir,chainId:n=or,balanceOf:i}={}){if(!cr(e))throw new Error("invalid-address");if(i)return BigInt(await i(e));let o=new rr(r,n,{staticNetwork:!0}),s=new tr(t,sr,o);return BigInt(await s.balanceOf(e))}var nr,or,ir,sr,ar,We=R(()=>{nr="0x62FCFAf7573AD8B41a0FBF347AfEb85e06599A75",or=999,ir="https://rpc.hyperliquid.xyz/evm",sr=["function balanceOf(address owner) view returns (uint256)"],ar=/^0x[a-fA-F0-9]{40}$/});import{existsSync as ur,readFileSync as lr,lstatSync as dr}from"node:fs";import{homedir as Qe}from"node:os";import{join as be}from"node:path";function mr(e){let t=String(e||"swap").toLowerCase();return Object.prototype.hasOwnProperty.call(Je,t)?Je[t]:fr}function yr(e=process.env){if(process.env.ORACLE_TEST_ISOLATE_SECRETS==="1"){if(e[Ze])return String(e[Ze]);let t=e.ORACLE_CONFIG_DIR||be(Qe(),".config","oracle");return be(t,"fee-recipient")}return be(Qe(),".config","oracle","fee-recipient")}function Er(e=process.env){try{let t=yr(e);if(!ur(t)||dr(t).isSymbolicLink())return"";let r=lr(t,"utf8").trim().toLowerCase();return/^0x[a-f0-9]{40}$/.test(r)?r:""}catch{return""}}function Ar(e,{fallback:t=0}={}){if(e==null)return t;if(String(e).trim()==="")return 0;let r=Number(e);return!Number.isFinite(r)||r<=0?0:Math.min(Math.floor(r),pr)}function xr({env:e=process.env,action:t="swap",admin:r=!1}={}){let n=String(e[wr]||"").trim(),i=String(e[gr]||br).trim();if(r===!0)return{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"admin-oracle"};let o=mr(t),s=Ar(e[hr],{fallback:n?o:0}),a=Math.min(s,o);if(!a)return{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"not-configured"};if(!/^0x[a-fA-F0-9]{40}$/.test(n))return{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"no-recipient"};let f=Er(e);return!f||f!==n.toLowerCase()?{bps:0,recipient:"",integrator:i,action:t,applies:!1,reason:"recipient-not-pinned"}:{bps:a,recipient:n,integrator:i,action:t,applies:!0,reason:"configured"}}async function ye({wallet:e,env:t=process.env,action:r="swap",holderCheck:n={},admin:i=!1}={}){let o=xr({env:t,action:r,admin:i});if(i===!0)return{...o,holderVerificationStatus:"admin-oracle"};let s=String(e||"").trim().toLowerCase();if(!/^0x[a-f0-9]{40}$/.test(s))return{...o,holderVerificationStatus:"wallet-required"};try{return BigInt(await Ye(s,n))>0n?{...o,bps:0,applies:!1,reason:"locals-only-holder",holderVerificationStatus:"holder"}:{...o,holderVerificationStatus:"non-holder"}}catch{return{...o,holderVerificationStatus:"unavailable"}}}function et(e){return e?.applies?`Oracle routing fee ${e.bps} bps (${(e.bps/100).toFixed(2)}%) to ${e.recipient}.`:e?.reason==="admin-oracle"?"No Oracle fee (admin Oracle).":e?.reason==="locals-only-holder"?"No Oracle fee (Locals Only holder).":"No Oracle fee."}function tt(e){return e?.applies?{integrator:e.integrator,fee:String(e.bps/1e4)}:{}}var pr,fr,Je,hr,wr,gr,Ze,br,te=R(()=>{We();pr=100,fr=5,Je=Object.freeze({swap:5,bridge:5,perps:0,nft:0});hr="ORACLE_INTEGRATOR_FEE_BPS",wr="ORACLE_INTEGRATOR_FEE_RECIPIENT",gr="ORACLE_INTEGRATOR_ID",Ze="ORACLE_INTEGRATOR_FEE_RECIPIENT_PIN",br="oracle"});var ot={};ve(ot,{LIFI_API:()=>nt,lifiChains:()=>vr,lifiHealth:()=>Cr,lifiPrepare:()=>kr,lifiQuote:()=>re});function Ae(e={}){return(e.baseUrl||process.env.LIFI_API_URL||nt).replace(/\/$/,"")}function Ir(e){let t=String(e||Ee).toLowerCase();return t===Ee.toLowerCase()||t===Sr}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 Cr(e={}){let t=await k(`${Ae(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 re(e={},t={}){let{fromChain:r,toChain:n=r,fromToken:i=Ee,toToken:o,fromAmount:s,fromAddress:a=z}=e;if(r==null||!o||!s)throw new Error("lifiQuote requires fromChain, toToken, fromAmount");let f=new URLSearchParams({fromChain:String(r),toChain:String(n),fromToken:i,toToken:o,fromAmount:String(s),fromAddress:a}),d=M({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(r),requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!d.executable)throw new Error(`lifi: route requires ${d.requiredBps} bps above cap ${d.capBps}`);f.set("slippage",String(d.selectedBps/1e4));let p=await ye({wallet:e.fromAddress,env:t.env,action:e.feeAction||"swap",holderCheck:t.holderCheck});for(let[m,E]of Object.entries(tt(p)))f.set(m,E);let c=await k(`${Ae(t)}/quote?${f}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),l=c?.estimate?.toAmount||c?.toAmount;if(!l)return{...c,autoSlippagePolicy:d,oracleFee:p};let u=c?.transactionRequest?.to||c?.estimate?.approvalAddress||"lifi",w=P(c,{chainId:Number(r),venue:u,amountOut:l,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(r),requestedCapBps:e.maxSlippageBps??e.slippageBps}),y=c?.estimate?.toAmountMin||c?.toAmountMin;if(y!=null&&BigInt(y)<BigInt(w.amountOutMinimum))throw new Error("lifi: provider transaction is under-protected versus bounded auto-slippage floor");return{...w,oracleFee:p}}async function kr(e={},t={}){let r=await re(e,t),n=r?.transactionRequest;if(!n?.to||!n?.data)throw new Error("lifi: quote did not return an executable transactionRequest");let i=Number(e.fromChain);if(n.chainId!=null&&Number(n.chainId)!==i)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 o=null;if(!Ir(e.fromToken)){let s=r?.estimate?.approvalAddress||r?.approvalAddress;if(!s)throw new Error("lifi: ERC20 route missing approvalAddress");let a=r?.action?.fromToken?.address||r?.estimate?.fromToken?.address||e.fromToken;o={token:rt(a,"approval token"),spender:rt(s,"approval spender"),amount:String(e.fromAmount)}}return _({provider:"lifi",calldataReady:!0,requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,chainId:i,quote:r,autoSlippage:r.autoSlippage,requiresApproval:o,transaction:{chainId:i,from:n.from||e.fromAddress,to:n.to,data:n.data,value:n.value??"0x0",...n.gasLimit!=null?{gasLimit:n.gasLimit}:{},slippageGuard:D(r.autoSlippage,{chainId:i,venue:n.to,data:n.data})}},{provider:"lifi",kind:"lifi-tx"})}async function vr(e={}){return k(`${Ae(e)}/chains`,{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs??12e3})}var nt,Ee,Sr,xe=R(()=>{$();U();ee();L();te();nt="https://li.quest/v1";Ee="0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",Sr="0x0000000000000000000000000000000000000000"});var ne={};ve(ne,{ACROSS_API:()=>ct,HOP_API:()=>ut,RELAY_API:()=>lt,acrossHealth:()=>Dr,acrossSuggestedFees:()=>dt,hopHealth:()=>Mr,hopQuote:()=>pt,relayHealth:()=>qr,relayPrepare:()=>Hr,relayQuote:()=>Ce});async function Dr(e={}){try{return{ok:!0,estimatedFillTimeSec:(await dt({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 dt(e={},t={}){let{token:r,destinationToken:n=r,originChainId:i,destinationChainId:o,amount:s}=e;if(!r||i==null||o==null||!s)throw new Error("acrossSuggestedFees requires token, originChainId, destinationChainId, amount");let a=new URLSearchParams({token:r,destinationToken:n,originChainId:String(i),destinationChainId:String(o),amount:String(s)}),f=(t.baseUrl||process.env.ACROSS_API_URL||ct).replace(/\/$/,"");return k(`${f}/suggested-fees?${a}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3})}async function Mr(e={}){try{let t=await pt({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 pt(e={},t={}){let{amount:r,token:n="ETH",fromChain:i="ethereum",toChain:o="arbitrum"}=e;if(!r)throw new Error("hopQuote requires amount");let s=e.slippage==null?void 0:Math.round(Number(e.slippage)*100),a=M({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:i!==o,requestedCapBps:e.maxSlippageBps??e.slippageBps??s});if(!a.executable)throw new Error(`hop: route requires ${a.requiredBps} bps above cap ${a.capBps}`);let f=new URLSearchParams({amount:String(r),token:n,fromChain:i,toChain:o,slippage:String(a.selectedBps/100)}),d=(t.baseUrl||process.env.HOP_API_URL||ut).replace(/\/$/,""),p=await k(`${d}/quote?${f}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??15e3}),c=p?.estimatedRecieved||p?.estimatedReceived;return c?P(p,{chainId:Number(e.originChainId||e.chainId||Fr[i]||0),venue:p?.tx?.to||"hop",amountOut:c,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:i!==o,requestedCapBps:e.maxSlippageBps??e.slippageBps??s}):{...p,autoSlippagePolicy:a}}async function qr(e={}){try{let t=await Ce({user:z,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 Ce(e={},t={}){let{user:r=z,originChainId:n,destinationChainId:i,originCurrency:o="0x0000000000000000000000000000000000000000",destinationCurrency:s="0x0000000000000000000000000000000000000000",amount:a,tradeType:f="EXACT_INPUT"}=e;if(n==null||i==null||!a)throw new Error("relayQuote requires originChainId, destinationChainId, amount");let d=M({liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(i),requestedCapBps:e.maxSlippageBps??e.slippageBps});if(!d.executable)throw new Error(`relay: route requires ${d.requiredBps} bps above cap ${d.capBps}`);let p=(t.baseUrl||process.env.RELAY_API_URL||lt).replace(/\/$/,""),c=await k(`${p}/quote`,{method:"POST",body:{user:r,originChainId:Number(n),destinationChainId:Number(i),originCurrency:o,destinationCurrency:s,amount:String(a),tradeType:f,slippageTolerance:String(d.selectedBps)},fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs??2e4}),l=c?.details?.currencyOut?.amount;return!l||!/^\d+$/.test(String(l))?{...c,autoSlippagePolicy:d}:P(c,{chainId:Number(n),venue:c?.steps?.[0]?.items?.[0]?.data?.to||"relay",amountOut:l,liquidityUsd:e.liquidityUsd,priceChange5m:e.priceChange5m,crossChain:Number(n)!==Number(i),requestedCapBps:e.maxSlippageBps??e.slippageBps})}async function Hr(e={},t={}){let r=await Ce(e,t),n=Number(e.originChainId),i=(r.steps||[]).flatMap(a=>(a.items||[]).filter(f=>f?.data?.to&&f?.data?.data).map(f=>({stepId:a.id,...f.data})));if(!i.length)throw new Error("relay: quote returned no executable transaction items");let o=String(r?.autoSlippage?.venue||"").toLowerCase();if(i.some(a=>String(a.to).toLowerCase()!==o))throw new Error("relay: route includes a separate approval/transaction that is not yet safely bound");let s=i.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:D(r.autoSlippage,{chainId:n,venue:a.to,data:a.data})}));return _({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 ct,ut,lt,Fr,oe=R(()=>{$();U();ee();L();ct="https://across.to/api",ut="https://api.hop.exchange/v1",lt="https://api.relay.link",Fr={ethereum:1,optimism:10,bsc:56,polygon:137,arbitrum:42161,avalanche:43114,base:8453}});var en=Object.freeze(["blockNumber","nativeBalance","tokenBalance","resolveToken","resolvePools","scanBlocks","scoreRisk","quote","sellSimulation","prepareUnsignedTx"]),tn=Object.freeze({LIVE:"LIVE",CACHED:"CACHED",STALE:"STALE",UNKNOWN:"UNKNOWN",UNAVAILABLE:"UNAVAILABLE"}),rn=Object.freeze({PASS:"PASS",CAUTION:"CAUTION",FAIL:"FAIL",UNKNOWN:"UNKNOWN"});var F=Object.freeze({FULL:"FULL",NO_GAS:"NO_GAS",FAILED:"FAILED"});var Oe=e=>{try{return e==null||e===""?null:BigInt(String(e).split(".")[0])}catch{return null}};function Ne(e){let{source:t,amountOut:r,minOut:n=null,gasUsd:i=null,feeUsd:o=null,oracleFeeBps:s=0,estimatedGas:a=null,liquidityUsd:f=null,error:d=null,executionReady:p=!1,meta:c={}}=e||{};if(d||r==null)return{source:t,quality:F.FAILED,amountOut:null,error:d||"no amountOut returned"};let l=Oe(r);if(l==null||l<=0n)return{source:t,quality:F.FAILED,amountOut:null,error:"non-positive amountOut"};let u=Number(s);return{source:t,quality:i==null?F.NO_GAS:F.FULL,amountOut:l.toString(),minOut:Oe(n)?.toString()??null,gasUsd:i,feeUsd:o,oracleFeeBps:Number.isFinite(u)&&u>0?Math.floor(u):0,estimatedGas:a==null?null:String(a),liquidityUsd:f==null?null:Number(f),executionReady:p,meta:c}}function Te(e,{destPriceUsd:t=null,destDecimals:r=null,liquidityFirst:n=!0,liquidityBandBps:i=50,gasPriceWei:o=null,nativePriceUsd:s=null}={}){let a=e.filter(h=>h.quality!==F.FAILED),f=e.filter(h=>h.quality===F.FAILED),d=t!=null&&t>0&&r!=null&&r>=0,p=Number(o),c=Number(s),l=Number.isFinite(p)&&p>0&&Number.isFinite(c)&&c>0,u=a.map(h=>{let A=BigInt(h.amountOut),I=0n,O=!1,B=!1,C=BigInt(h.oracleFeeBps??0),T=C>0n?A*C/10000n:0n;if(d){let Y=h.gasUsd,se=Number(h.meta?.gasUnits??h.estimatedGas);if(Y==null&&l&&Number.isFinite(se)&&se>0){let j=se*p/1e18*c;Number.isFinite(j)&&j>=0&&(Y=j,B=!0)}let ke=(Y??0)+(h.feeUsd??0);if(ke>0){let j=ke/t*10**r;Number.isFinite(j)&&j>=0&&(I=BigInt(Math.floor(j)),O=!0)}else Y===0&&(O=!0)}let X=I+T,gt=A>X?A-X:0n;return{...h,grossOut:A.toString(),netOut:gt.toString(),costInDest:I.toString(),oracleFeeInDest:T.toString(),costAccounted:O,gasEstimated:B}}),w=Number(i)>0?Number(i):0,y=u.reduce((h,A)=>BigInt(A.netOut)>h?BigInt(A.netOut):h,0n),m=h=>y>0n?Number((y-BigInt(h))*10000n/y):0,E=[],v=u.slice().sort((h,A)=>BigInt(A.netOut)>BigInt(h.netOut)?1:-1)[0]??null;u.sort((h,A)=>{let I=m(h.netOut)<=w?0:1,O=m(A.netOut)<=w?0:1;if(n&&w>0&&I!==O)return I-O;if(n&&w>0){let B=h.liquidityUsd??-1,C=A.liquidityUsd??-1;if(B!==C)return C-B}return BigInt(A.netOut)>BigInt(h.netOut)?1:-1}),n&&w>0&&v&&u[0]&&u[0].source!==v.source&&E.push(`liquidity-first: chose ${u[0].source} (liquidity $${u[0].liquidityUsd??"unknown"}) over best-price ${v.source} within ${w} bps`);let N=u.filter(h=>!h.costAccounted).map(h=>h.source);d?N.length&&E.push(`gas not reported by: ${N.join(", ")}. These are ranked on gross output and may be overstated relative to gas-measured routes.`):E.push("destination price/decimals unavailable: ranked on GROSS output. Gas is not included, so a cheap-looking route may cost more to execute.");let b=u[0];if(d&&b&&b.costAccounted===!1){let h=u.find(A=>A.costAccounted&&m(A.netOut)<=w);h&&E.push(`winner ${b.source} has UNMEASURED gas; gas-measured ${h.source} is within ${w} bps and may net more once ${b.source}'s real gas is paid \u2014 prefer it if unsure.`)}let S=u.filter(h=>h.gasEstimated).map(h=>h.source);S.length&&E.push(`gas ESTIMATED (from gas units x current gas price, not measured) for: ${S.join(", ")}. Net includes this estimate so the ranking is gas-inclusive, but the on-chain gas may differ.`);let x=null,g=null;if(u.length>=2&&u[0].costAccounted&&u[1].costAccounted){let h=BigInt(u[0].netOut),A=BigInt(u[1].netOut);A>0n&&(x=Number((h-A)*10000n/A),g=`${u[0].source} vs ${u[1].source}`)}return{best:u[0]??null,routes:u,failed:f,improvementBps:x,spreadBasis:g,rankedOn:d?"net-of-cost":"gross",warnings:E}}async function _e(e,{timeoutMs:t=12e3}={}){let r=(i,o)=>Promise.race([i,new Promise((s,a)=>setTimeout(()=>a(new Error(`${o}: timeout`)),t))]);return(await Promise.allSettled(e.map(i=>r(Promise.resolve().then(i.run),i.source)))).map((i,o)=>{let s=e[o].source;return i.status==="rejected"?Ne({source:s,error:String(i.reason?.message||i.reason)}):Ne({source:s,...i.value})})}xe();$();U();L();te();$();U();L();$();U();L();$();U();import{TypedDataEncoder as uo,getAddress as lo,isAddress as po}from"ethers";var oo=Object.freeze({READ:"read",PREPARE:"prepare",EXECUTE:"execute",AUTONOMOUS:"autonomous"});ee();L();var yo=Object.freeze({1:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",100:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",42161:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41",8453:"0x9008D19f58AAbD9eD0D60971565AA8510560ab41"}),Eo=Object.freeze({1:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",100:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",42161:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110",8453:"0xC92E8bdf79f0507f65a392b0ab4667716BFE0110"});var Ao=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"}]}),xo=Object.freeze({OrderCancellations:[{name:"orderUids",type:"bytes[]"}]});import{Interface as st,getAddress as Ho,isAddress as jo}from"ethers";$();var it={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}},Io=new Map(Object.values(it).map(e=>[e.chainId,e]));import{Interface as Tr,getAddress as Bo}from"ethers";var Ro=new Tr(["function allowance(address owner,address spender) view returns (uint256)","function balanceOf(address account) view returns (uint256)"]);$();var Do=Object.freeze({1:"ethereum",10:"optimism",56:"bsc",137:"polygon",8453:"base",42161:"arbitrum",43114:"avalanche",999:"hyperevm",4663:"robinhood"});U();L();var Xo=new st(["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)"]),Yo=new st(["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)"]);import{AbiCoder as Rr,Interface as Se,getAddress as Zo,isAddress as ei,keccak256 as ti}from"ethers";U();L();var si=Rr.defaultAbiCoder();var ai=new Se(["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)","function quoteExactOutputSingle(((address currency0,address currency1,uint24 fee,int24 tickSpacing,address hooks) poolKey,bool zeroForOne,uint128 exactAmount,bytes hookData) params) returns (uint256 amountIn, uint256 gasEstimate)"]),ci=new Se(["function execute(bytes commands,bytes[] inputs,uint256 deadline) payable"]),ui=new Se(["function getSlot0(bytes32 poolId) view returns (uint160 sqrtPriceX96,int24 tick,uint24 protocolFee,uint24 lpFee)","function getLiquidity(bytes32 poolId) view returns (uint128 liquidity)"]),li=Object.freeze([[13,"beforeInitialize"],[12,"afterInitialize"],[11,"beforeAddLiquidity"],[10,"afterAddLiquidity"],[9,"beforeRemoveLiquidity"],[8,"afterRemoveLiquidity"],[7,"beforeSwap"],[6,"afterSwap"],[5,"beforeDonate"],[4,"afterDonate"],[3,"beforeSwapReturnsDelta"],[2,"afterSwapReturnsDelta"],[1,"afterAddLiquidityReturnsDelta"],[0,"afterRemoveLiquidityReturnsDelta"]]),di=(1n<<14n)-1n;$();var Pr="https://coins.llama.fi",$r="https://api.llama.fi";function Lr(e={}){return(e.baseUrl||process.env.DEFILLAMA_COINS_URL||Pr).replace(/\/$/,"")}function Ur(e={}){return(e.baseUrl||process.env.DEFILLAMA_API_URL||$r).replace(/\/$/,"")}async function Ie(e,t={}){if(!Array.isArray(e)||!e.length)throw new Error("llamaPrices requires coins[]");let r=e.map(encodeURIComponent).join(",");return k(`${Lr(t)}/prices/current/${r}`,{fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function at(e={}){return k(`${Ur(e)}/protocols`,{fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs??2e4})}var H=e=>{let t=Number(e);return Number.isFinite(t)?t:null};function ft(e){if(!Array.isArray(e))return null;let t=0,r=!1;for(let n of e){let i=H(n?.amountUSD);i!=null&&(t+=i,r=!0)}return r?t:null}var q=e=>String(e??"").toLowerCase().replace(/[^a-z0-9]/g,""),mt=Object.freeze({across:["across"],relay:["relaychain","relay"],lifi:["jumper-(li.fi-powered)","lifi"],stargate:["stargate-v2","stargate-v1","stargate"],hop:["hop-protocol","hop"],debridge:["debridge"],synapse:["synapse"],connext:["connext"],cbridge:["celer-bridge","celer-cbridge","cbridge"],celer:["celer-bridge","celer-cbridge","cbridge"],squid:["squid"],symbiosis:["symbiosis"],wormhole:["wormhole"],mayan:["mayan"],allbridge:["allbridge"],thorchain:["thorchain"]});async function jr(e={}){try{let t=await at({...e,baseUrl:e.defillamaApiBaseUrl,timeoutMs:e.defillamaTimeoutMs??Math.min(Number(e.timeoutMs??5e3),5e3)});return Array.isArray(t)?t:[]}catch{return[]}}function Vr(e,t={}){let r=q(t.tool||t.provider||t.bridge||t.protocol),n=[];return e==="lifi"&&r&&r!=="lifi"&&n.push(...mt[r]||[r]),n.push(...mt[q(e)]||[e]),n}function zr(e,t,r={}){let n=Array.isArray(e)?e:[],i=Vr(t,r).map(q).filter(Boolean);for(let o of i){let s=n.find(f=>q(f?.slug)===o||q(f?.name)===o),a=H(s?.tvl);if(a!=null)return{liquidityUsd:a,protocol:s?.name??s?.slug??o}}for(let o of i){let s=n.find(f=>{let d=q(f?.category);return!d.includes("bridge")&&!d.includes("crosschain")?!1:q(f?.slug).includes(o)||q(f?.name).includes(o)}),a=H(s?.tvl);if(a!=null)return{liquidityUsd:a,protocol:s?.name??s?.slug??o}}return null}function ht({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:i,taker:o,opts:s={}}){let a=[],f=null,d=async(p,c={})=>(f||=jr(s),zr(await f,p,c));return a.push({source:"lifi",run:async()=>{let p=await re({fromChain:e,toChain:t,fromToken:r,toToken:n,fromAmount:i},s),c=p?.estimate??p?.[0]?.estimate,l={tool:p?.tool??p?.toolDetails?.name,durationSeconds:H(c?.executionDuration)},u=await d("lifi",l);return{amountOut:c?.toAmount,minOut:c?.toAmountMin,gasUsd:ft(c?.gasCosts),feeUsd:ft(c?.feeCosts),oracleFeeBps:p?.oracleFee?.applies?p.oracleFee.bps:0,liquidityUsd:u?.liquidityUsd??null,meta:{...l,liquidityProtocol:u?.protocol,oracleFee:p?.oracleFee??null}}}}),a.push({source:"relay",run:async()=>{let{relayQuote:p}=await Promise.resolve().then(()=>(oe(),ne)),l=(await p({user:o,originChainId:e,destinationChainId:t,originCurrency:r,destinationCurrency:n,amount:String(i)},s))?.details,u={durationSeconds:H(l?.timeEstimate),rate:l?.rate},w=await d("relay",u);return{amountOut:l?.currencyOut?.amount,minOut:l?.currencyOut?.minimumAmount,gasUsd:H(l?.totalImpact?.usd)!=null?Math.abs(H(l.totalImpact.usd)):null,liquidityUsd:w?.liquidityUsd??null,meta:{...u,liquidityProtocol:w?.protocol}}}}),a.push({source:"across",run:async()=>{let{acrossSuggestedFees:p}=await Promise.resolve().then(()=>(oe(),ne)),c=await p({token:r,destinationToken:n,originChainId:e,destinationChainId:t,amount:String(i)},s),l=c?.totalRelayFee?.total,u=null;if(l!=null)try{let y=BigInt(String(i))-BigInt(String(l));y>0n&&(u=y.toString())}catch{}let w=await d("across");return{amountOut:u,gasUsd:null,liquidityUsd:w?.liquidityUsd??null,meta:{derivedFromFees:!0,durationSeconds:H(c?.estimatedFillTimeSec),limits:c?.limits?{min:c.limits.minDeposit,max:c.limits.maxDeposit}:void 0,liquidityProtocol:w?.protocol}}}}),a}te();var Gr={1:"ethereum",10:"optimism",56:"bsc",137:"polygon",8453:"base",42161:"arbitrum",43114:"avax"};async function Kr(e,t,r){let n=Gr[Number(e)];if(!n)return{priceUsd:null,decimals:null};let i=`${n}:${t}`;try{let s=(await Ie([i],r))?.coins?.[i],a=Number(s?.price),f=Number(s?.decimals);return{priceUsd:Number.isFinite(a)?a:null,decimals:Number.isFinite(f)?f:null}}catch{return{priceUsd:null,decimals:null}}}async function wt(e,t={}){let{fromChainId:r,toChainId:n,tokenIn:i,tokenOut:o,amountIn:s}=e;if(r==null||n==null||!i||!o||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=Kr(n,o,t),f=ht({...e,opts:t}),[d,p]=await Promise.all([_e(f,{timeoutMs:t.timeoutMs??15e3}),a]),c=Te(d,{destPriceUsd:p.priceUsd,destDecimals:e.decimalsOut??p.decimals,liquidityBandBps:t.liquidityBandBps??50}),l=c.routes.map(u=>({source:u.source,seconds:u.meta?.durationSeconds??null})).filter(u=>u.seconds!=null);return{kind:"bridge",fromChainId:r,toChainId:n,tokenIn:i,tokenOut:o,amountIn:String(s),...c,durations:l,sourcesTried:f.length,sourcesAnswered:d.filter(u=>u.quality!==F.FAILED).length,note:Yr(c,f.length)}}function Xr(e){let t=e?.meta?.oracleFee;return t?.applies?` \xB7 ${et(t)}`:""}function Yr(e,t){if(!e.best)return"no source returned a usable route";let r=e.routes.length,n=Xr(e.best);if(r===1)return`only 1 of ${t} sources answered, so this is the ONLY route, not a proven best one. Treat it as unbenchmarked.`+n;if(e.improvementBps!=null){let i=e.improvementBps,o=i/100;if(i<.01)return`best of ${r} routes, ranked on ${e.rankedOn}: effectively tied with the runner-up (${e.spreadBasis}), inside quote noise. Re-quote before you size up.`+n;let s=o>=.01?`${o.toFixed(2)}%`:`${i.toFixed(2)}bps`;return`best of ${r} routes, ranked on ${e.rankedOn}: ${s} better than the runner-up (${e.spreadBasis})`+n}return`best of ${r} routes, ranked on ${e.rankedOn}. No spread quoted: the top routes report cost differently, so the margin is not comparable.`+n}L();var Wr=/^0x[0-9a-fA-F]{40}$/,Qr=new Set(["0x0000000000000000000000000000000000000000","0x000000000000000000000000000000000000dead","0x0000000000000000000000000000000000000001","0x00000000000000000000000000000000000a1ce5"].map(e=>e.toLowerCase())),Jr=100,ie={relay:async({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:i,taker:o},s)=>{let{relayPrepare:a}=await Promise.resolve().then(()=>(oe(),ne)),f=await a({user:o,originChainId:e,destinationChainId:t,originCurrency:r,destinationCurrency:n,amount:String(i)},s);return{transactions:f.transactions||[],amountOut:f.quote?.details?.currencyOut?.amount??null,minOut:f.quote?.details?.currencyOut?.minimumAmount??null,durationSeconds:f.quote?.details?.timeEstimate??null}},lifi:async({fromChainId:e,toChainId:t,tokenIn:r,tokenOut:n,amountIn:i,taker:o,isHolder:s},a)=>{let{lifiPrepare:f}=await Promise.resolve().then(()=>(xe(),ot)),d=await f({fromChain:e,toChain:t,fromToken:r,toToken:n,fromAmount:i,fromAddress:o,isHolder:s,feeAction:"bridge"},a);return{transactions:d.transaction?[d.transaction]:[],requiresApproval:d.requiresApproval??null,amountOut:d.quote?.estimate?.toAmount??null,minOut:d.quote?.estimate?.toAmountMin??null,durationSeconds:d.quote?.estimate?.executionDuration??null}}};function Ji(){return Object.keys(ie)}async function Zi(e,t={}){let{taker:r,fromChainId:n,toChainId:i}=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(!Wr.test(r))throw new Error(`taker must be a valid 20-byte address, got "${r}"`);if(Qr.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 o=await wt(e,t);if(!o.best)return{ok:!1,reason:"no source returned a usable bridge route",comparison:o};let s=e.source||o.best.source,a=o.routes.find(m=>m.source===s);if(!a)return{ok:!1,reason:`source "${s}" returned no usable route`,comparison:o};let f=ie[s];if(!f){let m=o.routes.find(E=>ie[E.source]&&E.source!==s);return{ok:!1,reason:`${s} won the comparison but has no bridge prepare path in this build. `+(m?`Next preparable route is ${m.source}; pass source:"${m.source}".`:"No route in this comparison can be prepared."),failureKind:"no-prepare-path",...m?{alternative:m.source}:{},winner:s,comparison:o}}let d;try{d=await f(e,t)}catch(m){let E=typeof m?.body=="string"?m.body:m?.body?JSON.stringify(m.body):"",v=[String(m?.message||m),E].filter(Boolean).join(" :: "),N=/allowance/i.test(v),b=!N&&/not enough|insufficient|balance/i.test(v),S=o.routes.find(x=>ie[x.source]&&x.source!==s);return{ok:!1,reason:N?`${s} will not build calldata until the token approval exists on-chain. Approve first, then prepare again. Underlying: ${v}`:b?`${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:N?"approval-required-first":b?"taker-not-funded":"provider-error",...S?{alternative:S.source}:{},comparison:o}}let p=d.transactions||[];if(!p.length)return{ok:!1,reason:`${s} returned no executable transaction for this route`,failureKind:"provider-error",comparison:o};let c=p.filter(m=>m.chainId!=null&&Number(m.chainId)!==Number(n));if(c.length)return{ok:!1,reason:`${s} returned a transaction for chain ${c[0].chainId} but the origin chain is ${n}. Refusing to hand over a mismatched artifact.`,failureKind:"chain-mismatch",comparison:o};let l=e.driftToleranceBps??Jr,u=null,w=null;if(d.amountOut!=null&&a.grossOut!=null)try{let m=BigInt(a.grossOut),E=BigInt(d.amountOut);m>0n&&(u=Number((E-m)*10000n/m),u<-l&&(w=`route moved ${(u/100).toFixed(2)}% against you since the comparison (tolerance ${(l/100).toFixed(2)}%). Re-compare before signing.`))}catch{}let y=[...w?[w]:[],...o.warnings||[],`Bridging is NOT atomic: the origin transaction succeeding does not mean funds arrived on chain ${i}. Expect ~${d.durationSeconds!=null?`${d.durationSeconds}s`:"minutes"} before the destination credits, and do not re-send if it is pending.`];return p.length>1&&y.push(`This route needs ${p.length} transactions signed IN ORDER. Signing only the first leaves funds approved but not bridged.`),_({ok:!0,chosen:{source:s,wasWinner:s===o.best.source,netOut:a.netOut,grossOut:a.grossOut,gasUsd:a.gasUsd},artifactKind:"unsigned-transaction-sequence",fromChainId:Number(n),toChainId:Number(i),transactionCount:p.length,transactions:p,requiresApproval:d.requiresApproval??null,minOut:d.minOut??null,durationSeconds:d.durationSeconds??null,destination:p[0]?.to??null,unsigned:!0,signedBy:"user-wallet",driftBps:u,warnings:y,runnersUp:o.routes.filter(m=>m.source!==s).map(m=>({source:m.source,netOut:m.netOut,gasUsd:m.gasUsd})),comparison:{rankedOn:o.rankedOn,sourcesAnswered:o.sourcesAnswered,sourcesTried:o.sourcesTried,improvementBps:o.improvementBps},note:`UNSIGNED. ${p.length} transaction(s) on chain ${n}, crediting chain ${i}. Verify every destination address before signing.`},{provider:"router",kind:"best-bridge"})}export{Zi as prepareBestBridgeRoute,Ji as supportedBridgePreparers};
@@ -0,0 +1 @@
1
+ import{createHash as X}from"node:crypto";import{getAddress as G,wordlists as Y}from"ethers";import{address as J}from"@solana/addresses";import{base58check as Z,bech32 as K,bech32m as Q}from"@scure/base";import{sha256 as ee}from"@noble/hashes/sha2.js";var j=1,Pe=Object.freeze({CLEAR:"CLEAR",UNKNOWN:"UNKNOWN",REVIEW:"REVIEW",BLOCK:"BLOCK"}),te=Object.freeze(["sanctions","phishing","scam","address-poisoning"]),re=Object.freeze(["sanctions","phishing","scam"]),ne=new Set(te),se=128,ie=256,O=512,oe=4096,ae=8,ce=2048,D=366*24*60*60*1e3,de=6e4,le=Z(ee),fe=["privatekey","privkey","secretkey","secret","seedphrase","seed","mnemonic","passphrase","password","keystore","keymaterial","wif","xprv","xpriv","apikey","bearer","authorization","credential"],ye=/\b[5KL][1-9A-HJ-NP-Za-km-z]{50,51}\b/,he=/\bxprv[0-9A-Za-z]{50,}\b/,ge=/^\s*(?:0x)?[0-9a-fA-F]{64}\s*$/,me=new Set([12,15,18,21,24]),we=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,Ee=/^\d+$/,ue=String(Number.MAX_SAFE_INTEGER).length,Ce=new Set(["txhash","transactionhash","recordid","hash","digest","evidenceid","sourcerecordid","blockhash","receipthash","commithash","payloadhash","sha256","sha256hex","id"]),be=Object.freeze({CLEAR:"CLEAR",NO_MATCH:"CLEAR",NOT_LISTED:"CLEAR",ABSENT:"CLEAR",REVIEW:"REVIEW",SUSPECTED:"REVIEW",POSSIBLE_MATCH:"REVIEW",INCONCLUSIVE:"REVIEW",BLOCK:"BLOCK",MATCH:"BLOCK",LISTED:"BLOCK",MALICIOUS:"BLOCK",PHISHING:"BLOCK",SCAM:"BLOCK",UNKNOWN:"UNKNOWN",UNAVAILABLE:"UNKNOWN",ERROR:"UNKNOWN"}),W=Object.freeze({BLOCK:0,REVIEW:1,UNKNOWN:2,INFO:3});function M(e){return String(e).replace(/[^a-z0-9]/gi,"").toLowerCase()}function Te(e){let t=M(e);return fe.some(r=>t.includes(r))}function Ie(e){return Ce.has(M(e))}function ke(e){let t=String(e).trim().toLowerCase().split(/\s+/).filter(Boolean);return me.has(t.length)&&t.every(r=>Y.en.getWordIndex(r)>=0)}function T(e){let t=new WeakSet,r=0;function s(n,i,a,y=""){if(r+=1,r>oe)throw new RangeError("safety-intelligence: input is too large");if(a>ae)throw new RangeError("safety-intelligence: input is too deep");if(n==null||typeof n=="boolean")return;if(typeof n=="string"){if(n.length>ce)throw new RangeError(`safety-intelligence: string too long at ${i}`);if(ye.test(n)||he.test(n)||ke(n))throw new TypeError(`safety-intelligence: key material refused at ${i}`);if(ge.test(n)&&!Ie(y))throw new TypeError(`safety-intelligence: key material refused at ${i}`);return}if(typeof n=="number"){if(!Number.isFinite(n))throw new TypeError(`safety-intelligence: finite number required at ${i}`);return}if(typeof n=="bigint")return;if(typeof n!="object")throw new TypeError(`safety-intelligence: JSON-like input required at ${i}`);if(ArrayBuffer.isView(n)||n instanceof ArrayBuffer)throw new TypeError(`safety-intelligence: binary key material refused at ${i}`);if(t.has(n))throw new TypeError(`safety-intelligence: cyclic input refused at ${i}`);if(t.add(n),Array.isArray(n)){if(n.length>O)throw new RangeError(`safety-intelligence: array too large at ${i}`);if(n.length===64&&n.every(c=>Number.isInteger(c)&&c>=0&&c<=255))throw new TypeError(`safety-intelligence: key material refused at ${i}`);n.forEach((c,l)=>s(c,`${i}[${l}]`,a+1,y)),t.delete(n);return}if(Object.getPrototypeOf(n)!==Object.prototype)throw new TypeError(`safety-intelligence: plain object required at ${i}`);let f=Reflect.ownKeys(n).filter(c=>typeof c=="string");if(f.length>64)throw new RangeError(`safety-intelligence: too many fields at ${i}`);for(let c of f){if(Te(c))throw new TypeError(`safety-intelligence: secret-bearing field refused at ${i}.${c}`);let l=Object.getOwnPropertyDescriptor(n,c),m=l&&"get"in l&&typeof l.get=="function"?l.get.call(n):n[c];m!==void 0&&s(m,`${i}.${c}`,a+1,c)}t.delete(n)}return s(e,"$",0),e}function w(e,t,r){for(let s of Object.keys(e||{}))if(!t.has(s))throw new TypeError(`safety-intelligence: unknown ${r} field ${s}`)}function k(e,t,r,{required:s=!1}={}){if(e==null||e===""){if(s)throw new TypeError(`safety-intelligence: ${t} required`);return null}let n=String(e).trim();if(!n&&s)throw new TypeError(`safety-intelligence: ${t} required`);if(n.length>r)throw new RangeError(`safety-intelligence: ${t} exceeds ${r} characters`);if(/[\u0000-\u001f\u007f\u200b-\u200f\u202a-\u202e\u2060-\u2064\ufeff]/i.test(n))throw new TypeError(`safety-intelligence: control or invisible characters refused in ${t}`);return n||null}function p(e,t){if(e==null||e==="")throw new TypeError(`safety-intelligence: ${t} required`);let r;if(typeof e=="number"){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`safety-intelligence: ${t} must be a safe integer millisecond timestamp`);r=e}else if(typeof e=="string"){let s=e.trim();if(Ee.test(s)&&s.length<=ue){if(r=Number(s),!Number.isSafeInteger(r))throw new TypeError(`safety-intelligence: ${t} must be a safe integer millisecond timestamp`)}else if(we.test(s)){if(r=Date.parse(s),!Number.isFinite(r)||new Date(r).toISOString().replace(/\.000Z$/,"Z")!==s&&new Date(r).toISOString()!==s)throw new TypeError(`safety-intelligence: ${t} must be a canonical ISO timestamp`)}else throw new TypeError(`safety-intelligence: ${t} must be a canonical ISO timestamp or integer milliseconds`)}else throw new TypeError(`safety-intelligence: ${t} must be a timestamp`);if(!Number.isFinite(r))throw new TypeError(`safety-intelligence: ${t} must be a valid timestamp`);return{ms:r,iso:new Date(r).toISOString()}}function z(e,t){return e==null||e===""?null:p(e,t)}function V(e){let t=String(e||"").trim().toLowerCase();if(t==="evm"||t==="eip155")return"evm";if(t==="solana")return"solana";if(t==="bitcoin"||t==="bip122"||t==="btc")return"bitcoin";throw new TypeError("safety-intelligence: chain family must be evm, solana, or bitcoin")}function F(e){T(e);let t,r;if(Number.isInteger(e))t="evm",r=e;else if(typeof e=="string"){let i=e.trim();if(/^\d+$/.test(i))t="evm",r=Number(i);else{let a=/^(eip155|evm|solana|bitcoin|bip122|btc):([^:]+)$/i.exec(i);if(!a)throw new TypeError("safety-intelligence: chain must include a supported family");t=V(a[1]),r=a[2]}}else if(e&&typeof e=="object"&&!Array.isArray(e))w(e,new Set(["family","namespace","chainId","reference","network","key"]),"chain"),t=V(e.family??e.namespace??(e.chainId!=null?"evm":"")),r=t==="evm"?e.chainId??e.reference:e.network??e.reference;else throw new TypeError("safety-intelligence: chain required");if(t==="evm"){let i=typeof r=="string"&&/^\d+$/.test(r)?Number(r):r;if(!Number.isSafeInteger(i)||i<=0)throw new TypeError("safety-intelligence: EVM chainId must be a positive safe integer");return g({family:t,namespace:"eip155",reference:String(i),chainId:i,key:`eip155:${i}`})}let s=k(r,`${t} network`,80,{required:!0}).toLowerCase();if(!/^[a-z0-9][a-z0-9._-]*$/.test(s))throw new TypeError(`safety-intelligence: invalid ${t} network`);let n=t==="bitcoin"?"bip122":"solana";return g({family:t,namespace:n,reference:s,network:s,key:`${n}:${s}`})}function ve(e){let t=String(e).toLowerCase();return["mainnet","main","bitcoin"].includes(t)?"mainnet":["testnet","testnet3","test","signet"].includes(t)?"testnet":t==="regtest"?"regtest":"unknown"}function Ae(e,t){let r=k(e,"bitcoin address",100,{required:!0}),s=ve(t.reference);if(/^(bc1|tb1|bcrt1)/i.test(r)){if(r!==r.toLowerCase()&&r!==r.toUpperCase())throw new TypeError("safety-intelligence: mixed-case Bitcoin bech32 address refused");let a=r.toLowerCase(),y,f;try{y=K.decode(a,100),f="bech32"}catch{try{y=Q.decode(a,100),f="bech32m"}catch{throw new TypeError("safety-intelligence: invalid Bitcoin bech32 checksum")}}let c=y.words[0],l;try{l=K.fromWords(y.words.slice(1))}catch{throw new TypeError("safety-intelligence: invalid Bitcoin witness program")}if(!Number.isInteger(c)||c<0||c>16||l.length<2||l.length>40)throw new TypeError("safety-intelligence: invalid Bitcoin witness program");if(c===0&&(f!=="bech32"||![20,32].includes(l.length)))throw new TypeError("safety-intelligence: invalid v0 Bitcoin witness address");if(c>0&&f!=="bech32m")throw new TypeError("safety-intelligence: v1+ Bitcoin witness address must use bech32m");let m=s==="mainnet"?"bc":s==="testnet"?"tb":s==="regtest"?"bcrt":null;if(m&&y.prefix!==m)throw new TypeError(`safety-intelligence: Bitcoin address does not match ${t.reference}`);return{canonical:a,display:a}}let n;try{n=le.decode(r)}catch{throw new TypeError("safety-intelligence: invalid Bitcoin base58check address")}if(n.length!==21)throw new TypeError("safety-intelligence: invalid Bitcoin address payload");let i=n[0];if(s==="mainnet"&&![0,5].includes(i))throw new TypeError("safety-intelligence: Bitcoin address does not match mainnet");if((s==="testnet"||s==="regtest")&&![111,196].includes(i))throw new TypeError(`safety-intelligence: Bitcoin address does not match ${t.reference}`);return{canonical:r,display:r}}function Ne(e,t){let r=F(t);T(e);let s=k(e,`${r.family} address`,128,{required:!0});if(r.family==="evm"){let n=s.startsWith("0X")?`0x${s.slice(2)}`:s,i;try{i=G(n)}catch{throw new TypeError("safety-intelligence: invalid EVM address or mixed-case checksum")}return g({canonical:i.toLowerCase(),display:i})}if(r.family==="solana"){let n;try{n=String(J(s))}catch{throw new TypeError("safety-intelligence: invalid Solana address")}return g({canonical:n,display:n})}return g(Ae(s,r))}function v(e={}){if(T(e),!e||typeof e!="object"||Array.isArray(e))throw new TypeError("safety-intelligence: target object required");w(e,new Set(["chain","chainId","family","network","address","displayAddress","key"]),"target");let t=e.chain??(e.chainId!=null?{family:e.family??"evm",chainId:e.chainId}:{family:e.family,network:e.network}),r=F(t),s=Ne(e.address,r);return g({chain:r,address:s.canonical,displayAddress:s.display,key:`${r.key}:${s.canonical}`})}function b(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(b).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${b(e[t])}`).join(",")}}`}function He(e){return T(e),b(e)}function $(e){return X("sha256").update(e).digest("hex")}function g(e){if(!e||typeof e!="object"||Object.isFrozen(e))return e;for(let t of Object.values(e))g(t);return Object.freeze(e)}function _(e){let t=String(e||"").trim().toLowerCase().replace(/_/g,"-"),s={sanction:"sanctions",sanctions:"sanctions",phishing:"phishing",scam:"scam",fraud:"scam",poisoning:"address-poisoning","address-poisoning":"address-poisoning"}[t];if(!s||!ne.has(s))throw new TypeError(`safety-intelligence: unsupported evidence kind ${String(e||"<missing>")}`);return s}function Se(e){let t=e.verdict??e.disposition??e.result??e.status;if(t==null){for(let n of["match","listed","malicious"])if(typeof e[n]=="boolean"){t=e[n]?"MATCH":"NO_MATCH";break}}let r=String(t||"").trim().toUpperCase().replace(/[ -]+/g,"_"),s=be[r];if(!s)throw new TypeError(`safety-intelligence: unsupported evidence verdict ${String(t||"<missing>")}`);return s}function Oe(e,t){let r=e.target??(e.address!=null?{address:e.address,chain:e.chain,chainId:e.chainId,family:e.family,network:e.network}:null);if(!r){if(!t)throw new TypeError("safety-intelligence: evidence target required");return t}return v(r)}function pe(e={},t={}){if(T({input:e,options:t}),!e||typeof e!="object"||Array.isArray(e))throw new TypeError("safety-intelligence: evidence object required");w(e,new Set(["kind","type","category","source","sourceRecordId","recordId","reference","verdict","disposition","result","status","match","listed","malicious","confidence","fetchedAt","expiresAt","expiry","ttlMs","summary","target","address","chain","chainId","family","network"]),"evidence"),w(t,new Set(["target","asOf"]),"evidence option");let r=Oe(e,t.target?v(t.target):null),s=_(e.kind??e.type??e.category),n=Se(e),i=e.source&&typeof e.source=="object"?e.source.name??e.source.id:e.source,a=k(i,"evidence source",120,{required:!0}),y=Number(e.confidence);if(!Number.isFinite(y)||y<0||y>1)throw new TypeError("safety-intelligence: evidence confidence must be between 0 and 1");let f=p(e.fetchedAt,"evidence fetchedAt"),c=z(e.expiresAt??e.expiry,"evidence expiresAt");if(!c&&e.ttlMs!=null){let o=Number(e.ttlMs);if(!Number.isSafeInteger(o)||o<=0||o>D)throw new RangeError(`safety-intelligence: evidence ttlMs must be 1..${D}`);c={ms:f.ms+o,iso:new Date(f.ms+o).toISOString()}}if(!c)throw new TypeError("safety-intelligence: evidence expiresAt or ttlMs required");if(c.ms<=f.ms)throw new TypeError("safety-intelligence: evidence expiry must be after fetchedAt");if(t.asOf==null)throw new TypeError("safety-intelligence: explicit asOf required for deterministic freshness");let l=p(t.asOf,"asOf").ms,m=f.ms>l+de?"FUTURE":c.ms<=l?"STALE":"CURRENT",u=k(e.sourceRecordId??e.recordId??e.reference,"source record id",160),d=k(e.summary,"evidence summary",500),h={kind:s,verdict:n,source:a,...u?{sourceRecordId:u}:{},fetchedAt:f.iso,expiresAt:c.iso,confidence:y,freshness:m,target:r.key,...d?{summary:d}:{}},A=`safety-evidence:${$(b(h))}`;return g({id:A,...h})}function Re(e=[],t={}){if(T({records:e,options:t}),!Array.isArray(e))throw new TypeError("safety-intelligence: evidence must be an array");let r=t.maxEvidence??se;if(!Number.isSafeInteger(r)||r<=0||r>O)throw new RangeError("safety-intelligence: invalid maxEvidence");if(e.length>r)throw new RangeError(`safety-intelligence: evidence exceeds ${r} records`);w(t,new Set(["target","asOf","maxEvidence"]),"evidence-set option");let s={target:t.target,asOf:t.asOf},n=new Map(e.map(i=>{let a=pe(i,s);return[a.id,a]}));return g([...n.values()].sort((i,a)=>i.id.localeCompare(a.id)))}function xe(e,t,r){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError(`safety-intelligence: knownContacts[${r}] must be an object`);w(e,new Set(["id","label","address","chain","chainId","family","network"]),"contact");let s=v({address:e.address,chain:e.chain??(e.chainId!=null?{family:e.family??"evm",chainId:e.chainId}:e.family||e.network?{family:e.family,network:e.network}:t)}),n=k(e.id,"contact id",120),i=k(e.label,"contact label",120);return g({...n?{id:n}:{},...i?{label:i}:{},target:s})}function R(e,t){if(typeof e=="number"&&(!Number.isSafeInteger(e)||e<0))throw new TypeError(`safety-intelligence: ${t} must be an exact non-negative integer`);let r=typeof e=="bigint"?e.toString():String(e??"").trim();if(!/^\d+$/.test(r)||r.length>100)throw new TypeError(`safety-intelligence: ${t} must be a bounded base-unit integer`);return BigInt(r).toString()}function _e(e,t,r){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError(`safety-intelligence: observations[${r}] must be an object`);w(e,new Set(["address","counterparty","from","direction","amountBaseUnits","chain","chainId","family","network","observedAt"]),"observation");let s=e.counterparty??e.address??e.from,n=v({address:s,chain:e.chain??(e.chainId!=null?{family:e.family??"evm",chainId:e.chainId}:e.family||e.network?{family:e.family,network:e.network}:t)}),i=String(e.direction??(e.from!=null?"inbound":"unknown")).toLowerCase(),a=["inbound","received","receive"].includes(i)?"inbound":["outbound","sent","send"].includes(i)?"outbound":"unknown",y=R(e.amountBaseUnits,`observations[${r}].amountBaseUnits`),f=z(e.observedAt,`observations[${r}].observedAt`)?.iso??null;return g({target:n,direction:a,amountBaseUnits:y,...f?{observedAt:f}:{}})}function Le(e,t){let r=0;for(;r<e.length&&r<t.length&&e[r]===t[r];)r+=1;return r}function $e(e,t){let r=0;for(;r<e.length&&r<t.length&&e[e.length-1-r]===t[t.length-1-r];)r+=1;return r}function q(e){return e.chain.family==="evm"?e.address.slice(2):e.address}function I(e){return g({code:e.code,severity:e.severity,category:e.category,basis:e.basis,message:e.message,...e.evidenceIds?.length?{evidenceIds:[...e.evidenceIds].sort()}:{},...e.relatedTargets?.length?{relatedTargets:[...e.relatedTargets].sort()}:{}})}function L(e){let t=new Map;for(let r of e){let s=b(r);t.set(s,r)}return[...t.values()].sort((r,s)=>(W[r.severity]??9)-(W[s.severity]??9)||r.category.localeCompare(s.category)||r.code.localeCompare(s.code)||b(r).localeCompare(b(s)))}function Be(e={},t={}){if(T({input:e,options:t}),!e||typeof e!="object"||Array.isArray(e))throw new TypeError("safety-intelligence: poisoning input object required");w(e,new Set(["target","address","chain","chainId","family","network","knownContacts","expectedContact","observations","dustThresholdBaseUnits","lookalikeEdgeChars"]),"poisoning input"),w(t,new Set(["maxContacts","maxObservations"]),"poisoning option");let r=v(e.target??{address:e.address,chain:e.chain,chainId:e.chainId,family:e.family,network:e.network}),s=e.knownContacts??[],n=e.observations??[];if(!Array.isArray(s))throw new TypeError("safety-intelligence: knownContacts must be an array");if(!Array.isArray(n))throw new TypeError("safety-intelligence: observations must be an array");let i=t.maxContacts??ie,a=t.maxObservations??O;if(!Number.isSafeInteger(i)||i<=0||i>O)throw new RangeError("safety-intelligence: invalid maxContacts");if(!Number.isSafeInteger(a)||a<=0||a>O)throw new RangeError("safety-intelligence: invalid maxObservations");if(s.length>i)throw new RangeError(`safety-intelligence: knownContacts exceeds ${i}`);if(n.length>a)throw new RangeError(`safety-intelligence: observations exceeds ${a}`);let y=s.map((d,h)=>xe(d,r.chain,h)).sort((d,h)=>d.target.key.localeCompare(h.target.key)||String(d.id||d.label||"").localeCompare(String(h.id||h.label||""))),f=n.map((d,h)=>_e(d,r.chain,h)).sort((d,h)=>b(d).localeCompare(b(h))),c=y.filter(d=>d.target.chain.key===r.chain.key),l=c.filter(d=>d.target.address===r.address),m=[],u=null;if(e.expectedContact!=null){if(typeof e.expectedContact=="string")u=v({chain:r.chain,address:e.expectedContact});else if(typeof e.expectedContact=="object"&&!Array.isArray(e.expectedContact))w(e.expectedContact,new Set(["address","chain","chainId","family","network"]),"expectedContact"),u=v({address:e.expectedContact.address,chain:e.expectedContact.chain??(e.expectedContact.chainId!=null?{family:e.expectedContact.family??"evm",chainId:e.expectedContact.chainId}:e.expectedContact.family||e.expectedContact.network?{family:e.expectedContact.family,network:e.expectedContact.network}:r.chain)});else throw new TypeError("safety-intelligence: expectedContact must be an address or target object");u.key!==r.key&&m.push(I({code:"EXPECTED_CONTACT_MISMATCH",severity:"REVIEW",category:"address-poisoning",basis:"contact-match",message:"Destination does not exactly match the caller-supplied expected contact.",relatedTargets:[u.key,r.key]}))}if(l.length===0){let d=Number(e.lookalikeEdgeChars??4);if(!Number.isSafeInteger(d)||d<3||d>12)throw new RangeError("safety-intelligence: lookalikeEdgeChars must be 3..12");let h=q(r);for(let A of c){let o=q(A.target),E=Le(h,o),S=$e(h,o);E>=d&&S>=d&&h!==o&&m.push(I({code:"ADDRESS_LOOKALIKE",severity:"REVIEW",category:"address-poisoning",basis:"heuristic",message:`Destination shares at least ${d} leading and trailing characters with a different known contact.`,relatedTargets:[A.target.key,r.key]}))}if(e.dustThresholdBaseUnits!=null){let A=BigInt(R(e.dustThresholdBaseUnits,"dustThresholdBaseUnits"));f.filter(E=>E.target.key===r.key&&E.direction==="inbound"&&BigInt(E.amountBaseUnits)<=A).length>0&&m.push(I({code:"PRIOR_DUST_CONTACT",severity:"REVIEW",category:"address-poisoning",basis:"heuristic",message:"Destination appeared as an inbound counterparty at or below the caller-supplied base-unit dust threshold.",relatedTargets:[r.key]}))}}return g({target:r,exactKnownContact:l.length>0,exactContacts:l,findings:L(m),dustThresholdBaseUnits:e.dustThresholdBaseUnits==null?null:R(e.dustThresholdBaseUnits,"dustThresholdBaseUnits")})}function Ue(e){let t=e??re;if(!Array.isArray(t)||t.length===0||t.length>32)throw new TypeError("safety-intelligence: requiredChecks must be a non-empty bounded array");let r=t.map((n,i)=>{if(typeof n=="string")return{kind:_(n),source:null};if(!n||typeof n!="object"||Array.isArray(n))throw new TypeError(`safety-intelligence: requiredChecks[${i}] must be a kind or object`);return w(n,new Set(["kind","source"]),"required check"),{kind:_(n.kind),source:k(n.source,"required check source",120,{required:!0})}}),s=new Map(r.map(n=>[`${n.kind}:${n.source||"*"}`,n]));return g([...s.values()].sort((n,i)=>`${n.kind}:${n.source||"*"}`.localeCompare(`${i.kind}:${i.source||"*"}`)))}function Ke(e,t){return e.filter(r=>r.kind===t.kind&&(!t.source||r.source===t.source))}function je(e){return e.some(t=>t.severity==="BLOCK")?"BLOCK":e.some(t=>t.severity==="REVIEW")?"REVIEW":e.some(t=>t.severity==="UNKNOWN")?"UNKNOWN":"CLEAR"}function P(e){return T(e),`sha256:${$(b(e))}`}function De(e={},t={}){if(T({input:e,options:t}),!e||typeof e!="object"||Array.isArray(e))throw new TypeError("safety-intelligence: evaluation input object required");if(w(e,new Set(["target","address","chain","chainId","family","network","evidence","requiredChecks","knownContacts","expectedContact","observations","dustThresholdBaseUnits","lookalikeEdgeChars"]),"evaluation input"),w(t,new Set(["asOf","minClearConfidence","minBlockConfidence","maxEvidence","maxContacts","maxObservations"]),"evaluation option"),t.asOf==null)throw new TypeError("safety-intelligence: explicit asOf required for deterministic evaluation");let r=p(t.asOf,"asOf").iso,s=e.target??{address:e.address,chain:e.chain,chainId:e.chainId,family:e.family,network:e.network},n=v(s),i=Number(t.minClearConfidence??.8),a=Number(t.minBlockConfidence??.8);for(let[o,E]of[["minClearConfidence",i],["minBlockConfidence",a]])if(!Number.isFinite(E)||E<0||E>1)throw new TypeError(`safety-intelligence: ${o} must be between 0 and 1`);let y=Re(e.evidence??[],{target:n,asOf:r,maxEvidence:t.maxEvidence}),f=y.filter(o=>o.target===n.key),c=Ue(e.requiredChecks),l=[];for(let o of f)o.freshness==="CURRENT"&&o.verdict==="BLOCK"?l.push(I({code:o.confidence>=a?"CURRENT_EXPLICIT_BLOCK":"LOW_CONFIDENCE_BLOCK_SIGNAL",severity:o.confidence>=a?"BLOCK":"REVIEW",category:o.kind,basis:"explicit-evidence",message:o.confidence>=a?"A current injected source returned an explicit BLOCK disposition.":"A current injected source returned BLOCK below the configured block-confidence threshold.",evidenceIds:[o.id]})):o.freshness==="CURRENT"&&o.verdict==="REVIEW"?l.push(I({code:"CURRENT_EXPLICIT_REVIEW",severity:"REVIEW",category:o.kind,basis:"explicit-evidence",message:"A current injected source returned an explicit REVIEW disposition.",evidenceIds:[o.id]})):o.freshness!=="CURRENT"&&["BLOCK","REVIEW"].includes(o.verdict)?l.push(I({code:o.freshness==="FUTURE"?"FUTURE_POSITIVE_EVIDENCE":"STALE_POSITIVE_EVIDENCE",severity:"REVIEW",category:o.kind,basis:"explicit-evidence",message:"Non-current injected adverse evidence requires human review; it is not treated as a current fact.",evidenceIds:[o.id]})):o.freshness==="CURRENT"&&o.verdict==="UNKNOWN"&&l.push(I({code:"SOURCE_UNKNOWN",severity:"UNKNOWN",category:o.kind,basis:"explicit-evidence",message:"A current injected source could not determine a disposition.",evidenceIds:[o.id]}));for(let o of c){let E=Ke(f,o),S=E.filter(C=>C.freshness==="CURRENT"),x=S.filter(C=>C.verdict==="CLEAR"&&C.confidence>=i),B=S.filter(C=>C.verdict==="BLOCK");if(x.length>0&&B.length>0&&l.push(I({code:"CONTRADICTORY_EVIDENCE",severity:"REVIEW",category:o.kind,basis:"explicit-evidence",message:"Current injected sources conflict for a required check.",evidenceIds:[...x,...B].map(C=>C.id)})),x.length===0){let C=S.filter(N=>N.verdict==="CLEAR"),U=E.filter(N=>N.verdict==="CLEAR"&&N.freshness!=="CURRENT"),H=o.source?`${o.kind} from ${o.source}`:o.kind;l.push(I({code:C.length>0?"CLEAR_CONFIDENCE_TOO_LOW":U.length>0?"STALE_CLEAR_EVIDENCE":"MISSING_CURRENT_EVIDENCE",severity:"UNKNOWN",category:o.kind,basis:"coverage",message:`Required check ${H} lacks current explicit CLEAR evidence at the configured confidence threshold.`,evidenceIds:[...C,...U].map(N=>N.id)}))}}let m=Be({target:n,knownContacts:e.knownContacts??[],expectedContact:e.expectedContact,observations:e.observations??[],dustThresholdBaseUnits:e.dustThresholdBaseUnits,lookalikeEdgeChars:e.lookalikeEdgeChars},{maxContacts:t.maxContacts,maxObservations:t.maxObservations});l.push(...m.findings);let u=L(l),d=je(u);d==="CLEAR"&&(u=L([I({code:"REQUIRED_EVIDENCE_CURRENT_CLEAR",severity:"INFO",category:"coverage",basis:"explicit-evidence",message:"Every required injected check supplied current explicit CLEAR evidence; this is source-scoped and not a safety guarantee.",evidenceIds:f.filter(o=>o.freshness==="CURRENT"&&o.verdict==="CLEAR").map(o=>o.id)})]),d="CLEAR");let h={version:j,target:n.key,evaluatedAt:r,decision:d,gate:d==="CLEAR"?"CONTINUE":d==="BLOCK"?"BLOCK":"HOLD",requiredChecks:c,evidenceIds:f.map(o=>o.id).sort(),findings:u},A=g({...h,hash:P(h)});return g({version:j,target:n,evaluatedAt:r,status:d,evidence:y,requiredChecks:c,poisoning:m,policy:A})}function We(e={}){if(T(e),!e||typeof e!="object"||Array.isArray(e))throw new TypeError("safety-intelligence: transaction object required");w(e,new Set(["target","to","destination","address","chain","chainId","family","network","amountBaseUnits","valueBaseUnits"]),"transaction");let t=v(e.target??{address:e.to??e.destination??e.address,chain:e.chain,chainId:e.chainId,family:e.family,network:e.network}),r=e.amountBaseUnits??e.valueBaseUnits,s=r==null?null:R(r,"transaction amountBaseUnits"),n={target:t,amountBaseUnits:s};return g({id:`safety-transaction:${$(b(n))}`,...n})}function Xe(e={},t={}){if(T({input:e,options:t}),!e||typeof e!="object"||Array.isArray(e))throw new TypeError("safety-intelligence: transaction evaluation input object required");w(e,new Set(["transaction","evidence","requiredChecks","knownContacts","expectedContact","observations","dustThresholdBaseUnits","lookalikeEdgeChars"]),"transaction evaluation input");let r=We(e.transaction),s=De({target:r.target,evidence:e.evidence??[],requiredChecks:e.requiredChecks,knownContacts:e.knownContacts??[],expectedContact:e.expectedContact,observations:e.observations??[],dustThresholdBaseUnits:e.dustThresholdBaseUnits,lookalikeEdgeChars:e.lookalikeEdgeChars},t),{hash:n,...i}=s.policy,a={...i,transactionId:r.id},y=g({...a,hash:P(a)});return g({...s,transaction:r,policy:y})}export{re as DEFAULT_REQUIRED_SAFETY_CHECKS,te as SAFETY_EVIDENCE_KINDS,j as SAFETY_INTELLIGENCE_VERSION,Pe as SAFETY_STATUS,T as assertPublicSafetyInput,He as canonicalSafetyJson,Ne as canonicalizeSafetyAddress,F as canonicalizeSafetyChain,v as canonicalizeSafetyTarget,Be as detectAddressPoisoning,De as evaluateAddressSafety,Xe as evaluateTransactionSafety,P as hashSafetyPolicy,pe as normalizeSafetyEvidence,Re as normalizeSafetyEvidenceSet,We as normalizeSafetyTransaction};