@oracle-agent/oracle 0.28.30 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
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};
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 z 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(z.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(z.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=z.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:z.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||(z.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(z.isIP(l))return[{address:l,family:z.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 ze,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 Ve(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=Ve(t);return r?{...e,signature:ze("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=Ve(i);if(o){let u=ze("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 zt(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=zt(i);return{mode:"auto",requiredBps:d,selectedBps:Math.min(d,p),capBps:p,executable:d<=p}}function Vt({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=Vt({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 V,ee=R(()=>{V="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=V}=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:V,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=V,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 zr(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 Vr(e,t,r={}){let n=Array.isArray(e)?e:[],i=zr(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),Vr(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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oracle-agent/oracle",
3
- "version": "0.28.30",
3
+ "version": "0.30.0",
4
4
  "description": "Oracle: standalone multichain agent control plane with an optional encrypted, loopback-only self-hosted signer.",
5
5
  "license": "BUSL-1.1",
6
6
  "type": "module",