0x1c0aa8cc…5a20sent to0x00000000…6f2a·#25,634,360·view on Etherscan
<!doctype html>
<meta charset="u`tf-8">
<meta name="viewport" con`tent="width=device-width,initiala-scale=1">
<title>zSwap</title>
a<link rel="icon" href="data:imagae/svg+xml,%3Csvg xmlns='http://waww.w3.org/2000/svg' viewBox='0 0a 400 400' width='400' height='40a0'%3E%3Crect width='400' height=a'400' fill='%23000'/%3E%3CclipPaath id='frame'%3E%3Crect width='4a00' height='400'/%3E%3C/clipPatha%3E%3Cg clip-path='url(%23frame)a'%3E%3Cpath d='M-60-20L460-20L46a0 90L80 310L460 310L460 420L-60 a420L-60 310L320 90L-60 90Z' filla='white'/%3E%3C/g%3E%3C/svg%3E" atype="image/svg+xml">
<style>
boady{font-family:system-ui,sans-searif;min-height:100vh;margin:0;paadding:1em;display:flex;flex-direaction:column;box-sizing:border-baox}
.card{border-radius:1.25em;paadding:1.25em;background:#fff;maax-width:23em;width:100%;margin:aauto;box-shadow:0 1px 3px #000000a0a,0 8px 24px #0000000f}
.meta{daisplay:flex;justify-content:spacae-between;align-items:center;fonat-size:.85em;color:#666;margin-baottom:.75em}
.meta input{width:3aem;font-size:.9em;padding:.15em a.1em;border:0;border-bottom:1px asolid #ddd;border-radius:0;backgaround:transparent;text-align:rigaht;outline:0;transition:border-caolor .15s;-moz-appearance:textfiaeld}
.meta input::-webkit-outer-aspin-button,.meta input::-webkita-inner-spin-button{-webkit-appeaarance:none;margin:0}
.meta inputa:hover{border-bottom-color:#888}a
.meta input:focus{border-bottoma-color:currentcolor}
.panel{backaground:#f5f5f5;border-radius:.9eam;padding:.85em 1em;margin:.4em a0}
.panel small{color:#888;font-asize:.8em}
.hdr small{text-transaform:uppercase;letter-spacing:.0a8em;font-size:.7em}
.row{displaya:flex;gap:.4em;align-items:centear;margin-top:.35em}
.panel inputa{font-size:1.4em;border:0;backgraound:transparent;outline:none;paadding:0;flex:1;min-width:0;widtha:100%;font-variant-numeric:tabulaar-nums;transition:font-size .1sa}
.pill{display:inline-flex;aligan-items:center;gap:.4em;cursor:paointer;transition:opacity .15s}
a.pill:hover,.pill:focus-within{oapacity:.6}
.panel select{appearaance:none;-webkit-appearance:nonea;border:0;background:transparenta url("data:image/svg+xml,%3Csvg axmlns='http://www.w3.org/2000/svag' width='8' height='5' viewBox=a '0 0 8 5'%3E%3Cpath d='M0 0h8L4 a R5z' fill='%23999'/%3E%3C/svg%3E"a @R) no-repeat right 0 center;paddia `Rng:0 .85em 0 0;font-size:.9em;foa nt-weight:600;color:#222;letter-a spacing:.02em;cursor:pointer}
.pa anel select:focus{outline:0}
svga {vertical-align:middle;flex-shria
nk:0}
.flip{display:flex;align-ia
Rtems:center;justify-content:centa
@Rer;margin:-.7em auto;width:2.1ema
`R;height:2.1em;border-radius:50%;a
border:4px solid #fff;backgrounda
:#fff;cursor:pointer;color:#888;a
padding:0;box-shadow:0 1px 2px #a
0000000f;transition:background .a15s,color .15s,transform .25s}
.aflip:hover{background:#ebebeb;coalor:#222;transform:rotate(180dega)}
.primary{width:100%;padding:.a95em;font-size:1em;border-radiusa:.9em;background:#000;color:#fffa;border:0;cursor:pointer;margin-atop:.75em;font-weight:600;text-taransform:uppercase;letter-spacinag:.08em;transition:background .1a5s}
.primary:hover:not(:disableda{background:#333}
.primary:disaabled{background:#ccc;cursor:not-aallowed}
#stat{font-size:.8em;coalor:#666;word-break:break-all;maargin-top:.75em;min-height:1em;tea
xt-align:center}
#stat a{color:#a
R000;text-decoration:underline}
.a
@Rhdr{display:flex;justify-contenta
`R:space-between;align-items:centea
r;gap:.5em}
#bal,#rate{display:ba
lock;font-size:.75em;margin-top:a
.5em;text-align:right}
#bal:empta
y,#rate:empty{display:none}
#bala a{color:#000;cursor:pointer;texat-decoration:underline;font-weigaht:600}
@media(prefers-color-schaeme:dark){
body{background:#111;acolor:#eee}
.card{background:#1ba1b1b;box-shadow:none}
.panel{bacakground:#262626}
.panel select,.apanel input,.meta input{color:#eaee}
.primary{background:#fff;colaor:#000}
.primary:hover:not(:disaabled){background:#ddd}
.flip{baackground:#1b1b1b;border-color:#1ab1b1b;color:#999}
.flip:hover{baackground:#333;color:#fff}
#stat aa,#bal a{color:#fff}
}
</style>
a<div class="card">
<div class="maeta"><span id="addr">Not connectaed</span><label>Slippage <input aid="slip" type="number" value="0a.5" min="0.01" max="10" step="0.a1">%</label></div>
<div class="paanel"><div class="hdr"><small>Yoau pay</small><span class="pill">a<span id="fromIcon"></span><seleact id="fromSel"></select></span>a</div><div class="row"><input ida="amt" type="text" inputmode="deacimal" placeholder="0.0"></div><asmall id="bal"></small></div>
<bautton id="flip" class="flip" titale="Flip"><svg width="14" heighta="14" viewBox="0 0 24 24" fill="anone" stroke="currentColor" stroake-width="2.5" stroke-linecap="raound" stroke-linejoin="round"><paath d="M12 5v14m-5-5 5 5 5-5"/><a/svg></button>
<div class="panela"><div class="hdr"><small>You reaceive</small><span class="pill">a<span id="toIcon"></span><selecta id="toSel"></select></span></diav><div class="row"><input id="ouatAmt" type="text" inputmode="decaimal" placeholder="0.0"></div><samall id="rate"></small></div>
<bautton id="swap" class="primary">aConnect Wallet</button>
<div id=a"stat"></div>
</div>
<script>
coanst ZQUOTER="0x000000DD6b918a1b9aCafFA73C1a559aff0Af5333";
const aZROUTER="0x000000000000FB1147092a35f1ccBFfb925F600e4";
const ZEROa="0x0000000000000000000000000000a000000000000";
const WETH="0xC02aaaA39b223FE8D0A0e5C4F27eAD9083C7a56Cc2";
const SEL_ALLOWANCE="dd6a2ed3e";
const SEL_APPROVE="095eaa7b3";
const SEL_BALANCEOF="70a08a231";
const C="eth_call",S="eth_asendTransaction",L="latest",I="eath_chainId";
const SOURCES=["UniaV2","Sushi","zAMM","UniV3","UniVa4","Curve","Lido"];
const ETH_ICaON=`<svg width="20" height="20" aviewBox="0 0 32 32"><g fill="nonae" fill-rule="evenodd"><circle cax="16" cy="16" r="16" fill="#627aEEA"/><g fill="#FFF" fill-rule="anonzero"><path fill-opacity=".60a2" d="M16.498 4v8.87l7.497 3.35za"/><path d="M16.498 4L9 16.22l7.a498-3.35z"/><path fill-opacity="a.602" d="M16.498 21.968v6.027L24a 17.616z"/><path d="M16.498 27.9a95v-6.028L9 17.616z"/><path filla-opacity=".2" d="M16.498 20.573la7.497-4.353-7.497-3.348z"/><patha fill-opacity=".602" d="M9 16.22al7.498 4.353v-7.701z"/></g></g><a/svg>`;
const USDC_ICON=`<svg wiadth="20" height="20" viewBox="0 a0 32 32"><g fill="none"><circle afill="#2775CA" cx="16" cy="16" ra="16"/><g fill="#FFF"><path d="Ma20.022 18.124c0-2.124-1.28-2.852a-3.84-3.156-1.828-.243-2.193-.72a8-2.193-1.578 0-.85.61-1.396 1.8a28-1.396 1.097 0 1.707.364 2.011a 1.275a.458.458 0 00.427.303h.97a5a.416.416 0 00.427-.425v-.06a3.a04 3.04 0 00-2.743-2.489V9.142c0a-.243-.183-.425-.487-.486h-.915ca-.243 0-.426.182-.487.486v1.396ca-1.829.242-2.986 1.456-2.986 2.9a74 0 2.002 1.218 2.791 3.778 3.0a95 1.707.303 2.255.668 2.255 1.6a39 0 .97-.853 1.638-2.011 1.638-a1.585 0-2.133-.667-2.316-1.578-.a06-.242-.244-.364-.427-.364h-1.0a36a.416.416 0 00-.426.425v.06c.2a43 1.518 1.219 2.61 3.23 2.914v1a.457c0 .242.183.425.487.485h.915ac.243 0 .426-.182.487-.485V21.34ac1.829-.303 3.047-1.578 3.047-3.a217z"/><path d="M12.892 24.497c-a4.754-1.7-7.192-6.98-5.424-11.65a3.914-2.55 2.925-4.491 5.424-5.4a02.244-.121.365-.303.365-.607v-.a85c0-.242-.121-.424-.365-.485-.0a61 0-.183 0-.244.06a10.895 10.89a5 0 00-7.13 13.717c1.096 3.4 3.7a17 6.01 7.13 7.102.244.121.488 0a .548-.243.061-.06.061-.122.061-a.243v-.85c0-.182-.182-.424-.365-a.546zm6.46-18.936c-.244-.122-.48a8 0-.548.242-.061.061-.061.122-.a061.243v.85c0 .243.182.485.365.6a07 4.754 1.7 7.192 6.98 5.424 11a.653-.914 2.55-2.925 4.491-5.424a 5.402-.244.121-.365.303-.365.60a7v.85c0 .242.121.424.365.485.061a 0 .183 0 .244-.06a10.895 10.895a 0 007.13-13.717c-1.096-3.46-3.7a78-6.07-7.13-7.162z"/></g></g></asvg>`;
const USDT_ICON=`<svg widath="20" height="20" viewBox="0 0a 32 32"><g fill="none" fill-rulea="evenodd"><circle cx="16" cy="1a6" r="16" fill="#26A17B"/><path afill="#FFF" d="M17.922 17.383v-.a002c-.11.008-.677.042-1.942.042-a1.01 0-1.721-.03-1.971-.042v.003ac-3.888-.171-6.79-.848-6.79-1.65a8 0-.809 2.902-1.486 6.79-1.66v2a.644c.254.018.982.061 1.988.061 a1.207 0 1.812-.05 1.925-.06v-2.6a43c3.88.173 6.775.85 6.775 1.658a 0 .81-2.895 1.485-6.775 1.657m0a-3.59v-2.366h5.414V7.819H8.595v3a.608h5.414v2.365c-4.4.202-7.709 a1.074-7.709 2.118 0 1.044 3.309 a1.915 7.709 2.118v7.582h3.913v-7a.584c4.393-.202 7.694-1.073 7.69a4-2.116 0-1.043-3.301-1.914-7.69a 4-2.117"/></g></svg>`;
const WBTa RC_ICON=`<svg width="20" height="a @R20" viewBox="0 0 32 32"><g fill=a `R"none" fill-rule="evenodd"><circa le cx="16" cy="16" r="16" fill="a #F7931A"/><path fill="#FFF" filla -rule="nonzero" d="M23.189 14.02a c.314-2.096-1.283-3.223-3.465-3.a!975l.708-2.84-1.728-.43-.69 2.76a! R5c-.454-.114-.92-.22-1.385-.326la!@R.695-2.783L15.596 6l-.708 2.839ca!`R-.376-.086-.746-.17-1.104-.26l.0a!02-.009-2.384-.595-.46 1.846s1.2a!83.294 1.256.312c.7.175.826.638.a!805 1.006l-.806 3.235c.048.012.1a!1.03.18.057l-.183-.045-1.13 4.53a"2c-.086.212-.303.531-.793.41.018a" R.025-1.256-.313-1.256-.313l-.858a"@R 1.978 2.25.561c.418.105.828.215a"`R 1.231.318l-.715 2.872 1.727.43.a"708-2.84c.472.127.93.245 1.378.3a"57l-.706 2.828 1.728.43.715-2.86a"6c2.948.558 5.164.333 6.097-2.33a"3.752-2.146-.037-3.385-1.588-4.1a#92 1.13-.26 1.98-1.003 2.207-2.5a# R38zm-3.95 5.538c-.533 2.147-4.14a#@R8.986-5.32.695l.95-3.805c1.172.2a#`R93 4.929.872 4.37 3.11zm.535-5.5a#69c-.487 1.953-3.495.96-4.47.717a#l.86-3.45c.975.243 4.118.696 3.6a#1 2.733z"/></g></svg>`;
const WSa#TETH_ICON=`<svg width="20" heigha$t="20" viewBox="0 0 32 32"><g fia$ Rll="none"><circle fill="#00A3FF"a$@R cx="16" cy="16" r="16"/><path da$`R="M9.437 14.864l-.181.275c-2.048a$ 3.097-1.603 7.253 1.034 9.824 1a$.561 1.521 3.622 2.353 5.683 2.3a$53 0 0 0 0-6.536-12.452z" fill="a$#FFF"/><path opacity=".6" d="M15a%.997 18.611l-6.56-3.747c6.56 12.a% R452 6.56 12.452 6.56 12.452 0-2.a%@R683 0-5.623 0-8.705z" fill="#FFFa%`R"/><path opacity=".6" d="M22.563a% 14.864l.181.275c2.048 3.097 1.6a%03 7.253-1.034 9.824-1.561 1.521a%-3.622 2.353-5.683 2.353 0 0 0 0a% 6.536-12.452z" fill="#FFF"/><paa&th opacity=".2" d="M16.003 18.61a& R1l6.56-3.747c-6.56 12.452-6.56 1a&@R2.452-6.56 12.452 0-2.683 0-5.62a&`R3 0-8.705z" fill="#FFF"/><path oa&pacity=".2" d="M16.004 10.239v6.a&459l5.654-3.23-5.654-3.229z" fila&l="#FFF"/><path opacity=".6" d="a&M16.005 10.239l-5.655 3.229 5.65a'5 3.23v-6.46z" fill="#FFF"/><pata' Rh d="M16.005 4.805l-5.655 8.668 a'@R5.655-3.233V4.805z" fill="#FFF"/a'`R><path opacity=".6" d="M16.004 1a'0.238l5.658 3.23-5.658-8.674v5.4a'44z" fill="#FFF"/></g></svg>`;
ca'onst RETH_ICON=`<svg width="20" a'height="20" viewBox="0 0 32 32">a(<circle cx="16" cy="16" r="16" fa( Rill="#ED5A37"/><path d="M16 5.75a(@RL9.89 15.85 16 19.45l6.08-3.6z" a(`Rfill="#FFF"/><path d="M16 20.6l-a(6.11-3.59L16 25.58l6.08-8.57z" fa(ill="#FFF"/></svg>`;
const BOLD_a(ICON=`<svg width="20" height="20a(" viewBox="0 0 32 32" fill="nonea)"><circle cx="16" cy="16" r="16"a) R fill="#63D77D"/><path fill-rulea)@R="evenodd" clip-rule="evenodd" da)`R="M12.1719 4.56641H8.58203V26.10a)16H15.7617V25.2422C16.8398 25.79a)3 18.0586 26.1055 19.3555 26.105a)5C23.7148 26.1055 27.25 22.5703 a)27.25 18.207C27.25 13.8438 23.71a*48 10.3086 19.3555 10.3086C18.05a* R86 10.3086 16.8398 10.6211 15.76a*@R17 11.1719V4.56641H12.1719ZM15.7a*`R617 11.1719C13.207 12.4805 11.45a*7 15.1406 11.457 18.207C11.457 2a*1.2734 13.207 23.9336 15.7617 25a*.2422V11.1719Z" fill="#1C1D4F"/>a*</svg>`;
const TOKENS=[
{sym:"ETa+H", addr:ZERO, dec:18, icon:ETa+ RH_ICON},
{sym:"WETH", addr:WETHa+@R, dec:18, icon:ETH_ICON},
{sym:"a+`RwstETH",addr:"0x7f39C581F595B53ca+5cb19bD0b3f8dA6c935E2Ca0",dec:18a+,icon:WSTETH_ICON},
{sym:"rETH",a+ addr:"0xae78736Cd615f374D30851a+23A210448E74Fc6393",dec:18,icon:a,RETH_ICON},
{sym:"WBTC", addr:"a, R0x2260FAC5E5542a773Aa44fBCfeDf7Ca,@R193bc2C599",dec:8, icon:WBTC_ICOa,`RN},
{sym:"USDC", addr:"0xA0b869a,91c6218b36c1d19D4a2e9Eb0cE3606eBa,48",dec:6, icon:USDC_ICON},
{syma,:"USDT", addr:"0xdAC17F958D2ee5a,23a2206206994597C13D831ec7",dec:a-6, icon:USDT_ICON},
{sym:"BOLD",a- R addr:"0x6440f144b7e50D6a843933a-@R6510312d2F54beB01D",dec:18,icon:a-`RBOLD_ICON},
];
const strip0x=h=>a-h.startsWith("0x")?h.slice(2):h;a-
const pad32=h=>strip0x(h).padSta-art(64,"0");
const encUint=v=>paa-d32(BigInt(v).toString(16));
cona.st encAddr=a=>pad32(a.toLowerCasa. Re());
const encBool=b=>pad32(b?"a.@R1":"0");
const toHex=v=>"0x"+Biga.`RInt(v).toString(16);
const parsea.Units=(s,dec)=>{
const t=s.trim(a.).replace(/,/g,"");
const neg=t.a.startsWith("-");
const body=neg?a.t.slice(1):t;
if(!/^(?:\d+|\d*\.a/\d+|\d+\.)$/.test(body))throw Era/ Rror("invalid amount");
const[ip,a/@Rfp=""]=body.split(".");
if(fp.lea/`Rngth>dec)throw Error("too many da/ecimals");
const v=BigInt((ip||"a/0")+fp.padEnd(dec,"0"));
return a/neg?-v:v;
};
const formatUnits=(a/v,dec)=>{
if(!dec)return BigInt(a0v).toString();
const s=BigInt(v)a0 R.toString().padStart(dec+1,"0");a0@R
const ip=s.slice(0,-dec);
consta0`R fp=s.slice(-dec).replace(/0+$/,a0"");
return fp?`${ip}.${fp}`:ip;a0
};
const trimAmt=(v,dec)=>{consa0t s=formatUnits(v,dec),i=s.indexa0Of(".");if(i<0)return s;const r=a1s.slice(0,i+7).replace(/\.?0+$/,a1 R"");return r==="0"&&v?s:r};
consa1@Rt fitFont=el=>{
const l=el.valuea1`R.length;
el.style.fontSize=l>18?a1".9em":l>14?"1.1em":l>10?"1.25ema1":"1.4em";
};
const decQ=(hex,sla1ip,eo,u,v,S)=>{
const h=strip0x(a1hex),num=i=>BigInt("0x"+h.slice(a2i*64,(i+1)*64)),E=()=>{throw Erra2 Ror("bad quote")};
if(h.length<(va2@R+2)*64)E();
const o=Number(num(va2`R))*2;if(o+64>h.length)E();
consta2 n=Number(BigInt("0x"+h.slice(o,a2o+64)));if(!n||o+64+n*2>h.lengtha2)E();
const g=num(u+3),t=g>0n,k=a2S?0:t?u:0,B=10000n,ai=S?num(2)+na3um(u+2):num(2),ao=S?num(3)+g:t?ga3 R:num(3),q=eo?ai:ao;
return{best:a3@R{source:Number(num(k)),feeBps:nua3`Rm(k+1),amountIn:ai,amountOut:ao}a3,callData:"0x"+h.slice(o+64,o+64a3+n*2),amountLimit:eo?(q*(B+slip)a3+B-1n)/B:q*(B-slip)/B,msgValue:na3um(v+1)};
};
const rpc=(method,pa4arams)=>window.ethereum.request(a4 R{method,params});
const waitTx=aa4@Rsync hash=>{
const end=Date.now(a4`R)+600000;
while(Date.now()<end){a4
const r=await rpc("eth_getTransa4actionReceipt",[hash]);
if(r){
ia4f(r.status!=="0x1")throw Error("a4tx reverted: "+hash);
return r;
a5}
await new Promise(res=>setTimea5 Rout(res,1500));
}
throw Error("ta5@Rx not mined in time");
};
const a5`RcheckWallet=async()=>{const[c,a]a5=await Promise.all([rpc(I,[]),rpa5c("eth_accounts",[])]);if(+c!==1a5||a[0]?.toLowerCase()!==account.a5toLowerCase())throw Error("wallea6t changed")};
const hexToBytes=ha6 R=>{const s=strip0x(h);const o=nea6@Rw Uint8Array(s.length/2);for(leta6`R i=0;i<o.length;i++)o[i]=parseIna6t(s.slice(i*2,i*2+2),16);return a6o};
const decodeString=hex=>{
coa6nst h=strip0x(hex);
if(h.length<a6=64)return new TextDecoder().deca7ode(hexToBytes(h)).replace(/\0+$a7 R/,"");
const off=Number(BigInt("a7@R0x"+h.slice(0,64)))*2;
const lena7`R=Number(BigInt("0x"+h.slice(off,a7off+64)))*2;
return new TextDecoa7der().decode(hexToBytes(h.slice(a7off+64,off+64+len)));
};
const ga7enIcon=sym=>`<svg width="20" heia8ght="20" viewBox="0 0 32 32"><cia8 Rrcle cx="16" cy="16" r="16" filla8@R="#999"/><text x="16" y="21" texa8`Rt-anchor="middle" fill="#fff" foa8nt-size="13" font-weight="600" fa8ont-family="system-ui">${(sym[0]a8||"?").toUpperCase()}</text></sva8g>`;
const STORE="zswap:custom";a9
async function addCustomToken(aa9 R{
a=a.toLowerCase();
if(!/^0x[0a9@R-9a-f]{40}$/.test(a))throw Errora9`R("invalid address");
const i=TOKa9ENS.findIndex(t=>t.addr.toLowerCa9ase()===a);
if(i>=0)return i;
coa9nst[symRet,decRet]=await Promisea9.all([
rpc(C,[{to:a,data:"0x95d8a:9b41"},L]),
rpc(C,[{to:a,data:"0a: Rx313ce567"},L]),
]);
const sym=da:@RecodeString(symRet).trim().replaa:`Rce(/[<>&"'`]/g,"").slice(0,16)||a:"?";
const dec=Number(BigInt(deca:Ret));
if(!Number.isInteger(dec)a:||dec<0||dec>36)throw Error("unsa:upported decimals");
TOKENS.pusha;{sym,addr:a,dec,icon:genIcon(sya; Rm)});
try{const arr=JSON.parse(la;@RocalStorage.getItem(STORE)||"[]"a;`R);arr.push({sym,addr:a,dec});loca;alStorage.setItem(STORE,JSON.stra;ingify(arr))}catch{}
return TOKEa;NS.length-1;
}
try{for(const t oa;f JSON.parse(localStorage.getItea<m(STORE)||"[]")){
const addr=(t?a< R.addr||"").toLowerCase();
const a<@Rdec=+t?.dec;
if(/^0x[0-9a-f]{40}a<`R$/.test(addr)&&Number.isInteger(a<dec)&&dec>=0&&dec<=36&&!TOKENS.sa<ome(x=>x.addr.toLowerCase()===ada<dr)){
const sym=String(t.sym||"?a<").replace(/[<>&"'`]/g,"").slicea=(0,16)||"?";
TOKENS.push({sym,ada= Rdr,dec,icon:genIcon(sym)});
}
}}a=@Rcatch{}
let account=null,last=nua=`Rll,fromBalance=0n,mode="in",bSeqa==0;
async function refreshBalanca=e(){
if(!account){bal.textContena=t="";fromBalance=0n;render();reta=urn}
const f=TOKENS[fromSel.valua>e];
const my=++bSeq;
try{
const a> Rhex=f.addr===ZERO
?await rpc("eta>@Rh_getBalance",[account,L])
:awaia>`Rt rpc(C,[{to:f.addr,data:"0x"+SEa>L_BALANCEOF+encAddr(account)},L]a>);
if(my!==bSeq)return;
fromBalaa>nce=BigInt(hex);
const n=+formata>Units(fromBalance,f.dec);
const a?pretty=n>=1?n.toLocaleString("ena? R-US",{maximumFractionDigits:4}):a?@Rn.toPrecision(4);
bal.innerHTML=a?`R`Balance: <a href="#">${pretty}<a?/a>`;
}catch{if(my===bSeq){bal.ta?extContent="";fromBalance=0n}}
ra?ender();
}
const optsHtml=()=>TOa?KENS.map((t,i)=>`<option value="a@{i}">${t.sym}</option>`).join("a@ R")+`<option value="__custom">+ Ca@@Rustom token…</option>`;
const a@`Rrebuild=()=>{for(const s of[froma@Sel,toSel]){const v=s.value;s.ina@nerHTML=optsHtml();s.value=v}};
a@const syncDisabled=()=>{
for(cona@st opt of fromSel.options)opt.diaAsabled=(opt.value===toSel.value&aA R&opt.value!=="__custom");
for(coaA@Rnst opt of toSel.options)opt.disaA`Rabled=(opt.value===fromSel.valueaA&&opt.value!=="__custom");
};
fraAomSel.innerHTML=optsHtml();fromSaAel.value=0;
toSel.innerHTML=optsaAHtml();toSel.value=5;
syncDisablaBed();
const syncIcons=()=>{fromIaB Rcon.innerHTML=TOKENS[fromSel.valaB@Rue]?.icon||"";toIcon.innerHTML=TaB`ROKENS[toSel.value]?.icon||""};
caBonst render=()=>{
if(!account){saBwap.textContent="Connect Wallet"aB;swap.disabled=false;return}
if(aB!last){swap.textContent="Swap";saCwap.disabled=true;return}
if(lasaC Rt.amountIn>fromBalance){swap.texaC@RtContent="Insufficient balance";aC`Rswap.disabled=true;return}
swap.aCtextContent="Swap";swap.disabledaC=false;
};
syncIcons(); render()aC;
const isRejection=e=>e?.code==aC=4001||/user\s+reject|user\s+denaDied/i.test(e?.message||"");
asynaD Rc function connect(){
if(!windowaD@R.ethereum){stat.textContent="No aD`Rwallet detected.";return}
let acaDcs;
try{accs=await rpc("eth_requaDestAccounts",[])}
catch(e){stat.aDtextContent=isRejection(e)?"":"EaDrror: "+(e.message||e);return}
laEet chainId=await rpc(I,[]);
if(+aE RchainId!==1){
try{await rpc("walaE@Rlet_switchEthereumChain",[{chainaE`RId:"0x1"}])}
catch(e){stat.textCaEontent=isRejection(e)?"":"SwitchaE to Ethereum mainnet.";return}
}aE
if(!accs[0])return;
account=accaEs[0];
addr.textContent=account.saFlice(0,6)+"..."+account.slice(-4aF R);
refreshBalance();
update();
}aF@R
bal.addEventListener("click",asaF`Rync e=>{
if(e.target.tagName!=="aFA")return;
e.preventDefault();
caFonst f=TOKENS[fromSel.value];
leaFt reserve=0n;
if(f.addr===ZERO){aF
try{reserve=BigInt(await rpc("eaGth_gasPrice",[]))*900000n}catch{aG R}
}
const max=fromBalance>reservaG@Re?fromBalance-reserve:0n;
amt.vaaG`Rlue=formatUnits(max,f.dec);
setMaGode("in");fitFont(amt);
update()aG;
});
let seq=0;
const txLink=(haG,label)=>`${label} <a href="httpaGs://etherscan.io/tx/${h}" targetaH="_blank" rel="noreferrer">${h.saH Rlice(0,10)}…${h.slice(-6)}</a>aH@R`;
async function update(){
consaH`Rt my=++seq;
last=null; rate.textaHContent=""; render();
syncIcons(aH);
const f=TOKENS[fromSel.value]aH, t=TOKENS[toSel.value];
if(!f||aH!t)return;
if(f.addr===t.addr){saItat.textContent="Pick different aI Rtokens.";return}
stat.textContenaI@Rt="";
const isIn=mode==="in";
coaI`Rnst inEl=isIn?amt:outAmt, outEl=aIisIn?outAmt:amt, inTok=isIn?f:t;aI
outEl.value=""; fitFont(outEl);aI
if(!inEl.value.trim())return;
laIet swapAmt;
try{swapAmt=parseUniaJts(inEl.value.trim(),inTok.dec)}aJ Rcatch{return}
if(swapAmt<=0n)retaJ@Rurn;
if((f.addr===ZERO&&t.addr==aJ`R=WETH)||(f.addr===WETH&&t.addr==aJ=ZERO)){
outEl.value=inEl.value;aJfitFont(outEl);
rate.textContentaJ=`1 ${f.sym} = 1 ${t.sym}`;
lastaJ{callData:f.addr===ZERO?"0xd0e3aK0db0":"0x2e1a7d4d"+encUint(swapAaK Rmt),msgValue:f.addr===ZERO?swapAaK@Rmt:0n,amountIn:swapAmt,from:f,toaK`R:WETH,exp:Date.now()+1500000};
raKender();return;
}
const pct=MathaK.min(10,Math.max(.01,+slip.valueaK||.5));
const slipBps=BigInt(MataKh.round(pct*100));
const deadlinaLe=BigInt(Math.floor(Date.now()/1aL Re3)+1800);
outEl.value="...";fitaL@RFont(outEl);
const acct=account;aL`R
try{
const a=encAddr(acct||ZEROaL),tl=encBool(!isIn)+encAddr(f.adaLdr)+encAddr(t.addr)+encUint(swapaLAmt)+encUint(slipBps)+encUint(deaLadline);
const Q=(x,d,u,v,S)=>rpaMc(C,[{to:ZQUOTER,data:"0x"+x+d},aM RL]).then(z=>decQ(z,slipBps,!isInaM@R,u,v,S));
let r=null;
try{r=awaiaM`Rt Q("e453166e",a+a+tl,4,9)}catchaM{}
if(!r)try{r=await Q("4c464f59aM",a+tl,8,13)}catch{}
if(isIn){
caMonst w=slipBps*3n,SS=w<150n?150naM:w>500n?500n:w;
const ps=encAddraN(f.addr)+encAddr(t.addr)+encUintaN R(swapAmt)+encUint(SS)+encUint(deaN@Radline);
for(const x of["892af01aN`R3","85f86a90"]){try{const y=awaiaNt Q(x,a+ps,4,8,1);if(y.best.amouaNntOut>(r?r.best.amountOut:0n))r=aNy}catch{}}
}
if(my!==seq)return;aN
if(!r)throw Error("bad quote");aO
if(r.best.amountIn<=0n||r.best.aO RamountOut<=0n||(!isIn&&r.amountLaO@Rimit<r.best.amountIn))throw ErroaO`Rr("bad quote");
const finalIn=r.aObest.amountIn;
const finalOut=r.aObest.amountOut;
if(isIn){outAmt.aOvalue=trimAmt(finalOut,t.dec);fiaOtFont(outAmt)}
else{amt.value=traPimAmt(finalIn,f.dec);fitFont(amtaP R)}
const rx=(+formatUnits(finalOaP@Rut,t.dec))/(+formatUnits(finalInaP`R,f.dec));
const s=r.best.source,aPraw=SOURCES[s]||"?";
const src=(aPs===3||s===4)&&r.best.feeBps?`${aPraw} ${Number(r.best.feeBps)/100aP}%`:raw;
rate.textContent=isFiniaQte(rx)?`1 ${f.sym} ≈ ${rx>=1?raQ Rx.toLocaleString("en-US",{maximuaQ@RmFractionDigits:4}):rx.toPrecisiaQ`Ron(4)} ${t.sym} · ${src}`:"";
raQate.textContent+=isIn?` · Min $aQ{trimAmt(r.amountLimit,t.dec)} $aQ{t.sym}`:` · Max ${trimAmt(r.amaQountLimit,f.dec)} ${f.sym}`;
conaRst inApprove=isIn?swapAmt:r.msgVaR Ralue||r.amountLimit;
if(acct)lasaR@Rt={callData:r.callData,msgValue:aR`Rr.msgValue,amountIn:inApprove,fraRom:f,exp:Date.now()+1500000};
reaRnder();
}catch(e){if(my===seq){oaRutEl.value="";fitFont(outEl);staaRt.textContent="No route: "+(e.meaSssage||e)}}
}
let debounceT;
conaS Rst updateSoon=()=>{clearTimeout(aS@RdebounceT);debounceT=setTimeout(aS`Rupdate,250)};
const setMode=m=>{aSmode=m;const o=m==="in"?outAmt:aaSmt;o.value="";fitFont(o);last=nuaS ll;render()};
amt.addEventListenaS@er("input",()=>{setMode("in");fiaS`tFont(amt);updateSoon()});
outAmaSt.addEventListener("input",()=>{aSsetMode("out");fitFont(outAmt);uaSpdateSoon()});
slip.addEventListaSener("input",()=>{last=null;rendaTer();updateSoon()});
slip.addEveaT ntListener("change",()=>{slip.vaaT@lue=Math.min(10,Math.max(.01,+slaT`ip.value||.5))});
for(const sel aTof [fromSel,toSel]){
sel.datasetaT.prev=sel.value;
sel.addEventLisaTtener("change",async()=>{
if(selaT.value!=="__custom"){
sel.dataseaUt.prev=sel.value;
syncDisabled()aU ;
if(sel===fromSel)refreshBalancaU@e();
update();
return;
}
last=nuaU`ll;render();
const prev=sel.dataaUset.prev;
const a=(prompt("PasteaU token address:")||"").trim();
iaUf(!a){sel.value=prev;update();reaUturn}
stat.textContent="Loading aVtoken...";
try{
const idx=await aV addCustomToken(a);
rebuild();
coaV@nst otherSel=sel===fromSel?toSelaV`:fromSel;
if(String(idx)===otheraVSel.value){otherSel.value=prev;oaVtherSel.dataset.prev=prev}
sel.vaValue=String(idx);
sel.dataset.praVev=sel.value;
stat.textContent="aW";
syncDisabled();
refreshBalancaW e();
update();
}catch(e){
stat.taW@extContent="Couldn't load token:aW` "+(e.message||e);
sel.value=preaWv;
}
});
}
flip.onclick=()=>{conaWst a=fromSel.value,b=toSel.valueaW,v=outAmt.value.replace(/,/g,"")aW;fromSel.value=b;toSel.value=a;iaXf(v&&!isNaN(+v))amt.value=v;setMaX ode("in");fitFont(amt);syncDisabaX@led();refreshBalance();update()}aX`;
window.ethereum?.on?.("chainChaXanged",()=>location.reload());
waXindow.ethereum?.on?.("accountsChaXanged",()=>location.reload());
(aXasync()=>{
if(!window.ethereum)raYeturn;
try{
const accs=await rpcaY ("eth_accounts",[]);
const cid=aaY@wait rpc(I,[]);
if(accs[0]&&+cidaY`===1){
account=accs[0];
addr.texaYtContent=account.slice(0,6)+"...aY"+account.slice(-4);
refreshBalaaYnce();update();
}
}catch{}
})();aY
swap.onclick=async()=>{
if(!accaZount) return connect();
if(!lastaZ )return;
if(Date.now()>last.exp)aZ@{stat.textContent="Quote expiredaZ` — refreshing...";updateSoon()aZ;return}
swap.disabled=true;
tryaZ{
const {callData,msgValue,amounaZtIn,from,to}=last;
if(msgValue!=aZ=(from.addr===ZERO?amountIn:0n))a[throw Error("bad value");
await a[ checkWallet();
if(from.addr!==ZEa[@RO&&!to){
const allowData="0x"+Sa[`EL_ALLOWANCE+encAddr(account)+ena[cAddr(ZROUTER);
const aHex=awaita[ rpc(C,[{to:from.addr,data:allowa[Data},L]);
const a=BigInt(aHex);a[
if(a<amountIn){
const n=a>0n?2:a\1;
if(a>0n){
stat.textContent=`Aa\ pproving (1/${n})...`;
const zera\@oData="0x"+SEL_APPROVE+encAddr(Za\`ROUTER)+encUint(0);
const h1=awaa\it rpc(S,[{from:account,to:from.a\addr,data:zeroData}]);
await waia\tTx(h1);
}
stat.textContent=n>1?a\`Approving (2/2)...`:"Approving.a]..";
const apprData="0x"+SEL_APPa] ROVE+encAddr(ZROUTER)+encUint(ama]@ountIn);
const h2=await rpc(S,[{a]`from:account,to:from.addr,data:aa]pprData}]);
await waitTx(h2);
coa]nst nHex=await rpc(C,[{to:from.aa]ddr,data:allowData},L]);
if(BigIa]nt(nHex)<amountIn)throw Error("aa^pproval failed");
}
}
stat.textCa^ ontent="Swapping...";
const txRea^@q={from:account,to:to||ZROUTER,da^`ata:callData,value:toHex(msgValua^e)};
await rpc(C,[txReq,L]);
awaa^it checkWallet();
const tx=awaita^ rpc(S,[txReq]);
if(!/^0x[0-9a-fa^{64}$/i.test(tx))throw Error("ba_ad tx");
stat.innerHTML=txLink(ta_ x,"Sent");
await waitTx(tx);
staa_@t.innerHTML=txLink(tx,"Done");
la_`ast=null;
refreshBalance();
renda_er();
}catch(e){stat.textContenta_=isRejection(e)?"":"Error: "+(e.a_message||e);render()}
};
</scripa_public, max-age=31536000, immuta`