memoscan
← all memos

Memo 0xf30e1022…662254 on Ethereum

0x68575b07…67c7·#25,913,375·view on Etherscan
on poly(msg,key){ const P=(1n<<130n)-5n; let r=0n,sk=0n; for(let i=15;i>=0;i--)r=(r<<8n)|BigInt(key[i]); r&=0x0ffffffc0ffffffc0ffffffc0fffffffn; for(let i=31;i>=16;i--)sk=(sk<<8n)|BigInt(key[i]); let a=0n; for(let i=0;i<msg.length;i+=16){ const n=Math.min(16,msg.length-i); let b=0n; for(let j=n-1;j>=0;j--)b=(b<<8n)|BigInt(msg[i+j]); a=((a+b+(1n<<BigInt(8*n)))*r)%P;} a=(a+sk)&((1n<<128n)-1n); const o=new Uint8Array(16); for(let i=0;i<16;i++){o[i]=Number(a&255n);a>>=8n} return o} const p16=n=>n%16?16-n%16:0; const le64=n=>{const b=new Uint8Array(8);for(let i=0;i<8;i++){b[i]=n&255;n=Math.floor(n/256)}return b}; function tagOf(ct,key,nonce){ const otk=chacha(key,nonce,0,new Uint8Array(32)); const pad=new Uint8Array(p16(ct.length)); const m=new Uint8Array(ct.length+pad.length+16); m.set(ct);m.set(pad,ct.length); m.set(le64(0),ct.length+pad.length);m.set(le64(ct.length),ct.length+pad.length+8); return poly(m,otk)} const seal=(key,nonce,pt)=>{ const ct=chacha(key,nonce,1,pt),tg=tagOf(ct,key,nonce); const o=new Uint8Array(ct.length+16);o.set(ct);o.set(tg,ct.length);return o}; const open=(key,nonce,box)=>{ if(box.length<16)return null; const ct=box.subarray(0,box.length-16),tg=box.subarray(box.length-16); const w=tagOf(ct,key,nonce); let bad=0;for(let i=0;i<16;i++)bad|=w[i]^tg[i]; return bad?null:chacha(key,nonce,1,ct)}; const hex=b=>{let s="";for(const x of b)s+=x.toString(16).padStart(2,"0");return s}; const unhex=h=>{const b=new Uint8Array(h.length/2); for(let i=0;i<b.length;i++)b[i]=parseInt(h.substr(i*2,2),16);return b}; const bin=b=>{let s="";for(let i=0;i<b.length;i+=4096)s+=String.fromCharCode.apply(null,b.subarray(i,i+4096));return s}; const b64=b=>btoa(bin(b)); const unb64=s=>{const t=atob(s),b=new Uint8Array(t.length); for(let i=0;i<t.length;i++)b[i]=t.charCodeAt(i);return b}; const b64u=b=>b64(b).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""); const utf8=s=>new TextEncoder().encode(s); const B58="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; const b58=b=>{let n=0n;for(const x of b)n=n*256n+BigInt(x); let s="";while(n>0n){s=B58[Number(n%58n)]+s;n/=58n} for(const x of b){if(x)break;s="1"+s}return s}; const rnd=n=>crypto.getRandomValues(new Uint8Array(n)); const sha256=async b=>new Uint8Array(await crypto.subtle.digest("SHA-256",b)); const topicOf=async k=>hex(await sha256(k)); const encode=(symKey,payload,senderPub)=>{ const iv=rnd(12),pt=utf8(JSON.stringify(payload)); const sealed=seal(symKey,iv,pt); const t=senderPub?1:0; const head=senderPub?1+32:1; const out=new Uint8Array(head+12+sealed.length); out[0]=t; if(senderPub)out.set(senderPub,1); out.set(iv,head);out.set(sealed,head+12); return b64(out)}; const decode=(symKey,msg)=>{ let b;try{b=unb64(msg)}catch{return null} if(!b.length)return null; const t=b[0]; if(t!==0&&t!==1)return null; const head=t===1?33:1; if(b.length<head+12+16)return null; const iv=b.subarray(head,head+12),box=b.subarray(head+12); const pt=open(symKey,iv,box); if(!pt)return null; try{return JSON.parse(new TextDecoder().decode(pt))}catch{return null}}; const didKey=pub=>{const b=new Uint8Array(34);b[0]=0xed;b[1]=0x01;b.set(pub,2); return"did:key:z"+b58(b)}; async function relayJwt(aud){ let kp; try{kp=await crypto.subtle.generateKey({name:"Ed25519"},true,["sign","verify"])} catch{throw Error("This browser cannot do Ed25519. WalletConnect needs a newer " +"browser; an extension wallet works here today.")} const pub=new Uint8Array(await crypto.subtle.exportKey("raw",kp.publicKey)); const iss=didKey(pub); const iat=Math.floor(Date.now()/1e3); const h=b64u(utf8(JSON.stringify({alg:"EdDSA",typ:"JWT"}))); const p=b64u(utf8(JSON.stringify({iss,sub:hex(rnd(32)),aud,iat,exp:iat+86400}))); const sig=new Uint8Array(await crypto.subtle.sign({name:"Ed25519"},kp.privateKey,utf8(h+"."+p))); return h+"."+p+"."+b64u(sig)} async function kex(){ let kp; try{kp=await crypto.subtle.generateKey({name:"X25519"},true,["deriveBits"])} catch{throw Error("This browser cannot do X25519. WalletConnect needs a newer " +"browser; an extension wallet works here today.")} const pub=new Uint8Array(await crypto.subtle.exportKey("raw",kp.publicKey)); return{priv:kp.privateKey,pub}} async function sessionKey(priv,peerHex){ const peer=await crypto.subtle.importKey("raw",unhex(peerHex),{name:"X25519"},false,[]); const bits=new Uint8Array(await crypto.subtle.deriveBits({name:"X25519",public:peer},priv,256)); const hk=await crypto.subtle.importKey("raw",bits,"HKDF",false,["deriveBits"]); const out=await crypto.subtle.deriveBits( {name:"HKDF",hash:"SHA-256",salt:new Uint8Array(0),info:new Uint8Array(0)},hk,256); return new Uint8Array(out)} return{seal,open,chacha,poly,hex,unhex,b64,unb64,b64u,b58,didKey,rnd,sha256, topicOf,encode,decode,relayJwt,kex,sessionKey}; })(); const WCCLI=(U,WSC)=>{ const RELAY="wss://relay.walletconnect.org"; const T_PROPOSE=1100,T_APPROVE=1101,T_SETTLE=1102,T_SETTLE_RES=1103,T_REQ=1108,T_RES=1109; const TTL=300,STTL=604800; let sock=null,nextId=1,waiters={},subs={},onEvent=null,alive=false,gone=""; const rpcId=()=>Date.now()*1000+(nextId++%1000); const sendRaw=o=>{ if(!alive)throw Error(gone||"The wallet connection is closed."); sock.send(JSON.stringify(o))}; function drop(why){ if(!alive&&gone)return; alive=false;gone=why; const ws=waiters;waiters={};subs={}; for(const k in ws)ws[k].rej(Error(why)); if(onEvent)onEvent({t:"closed",why})} function relayCall(method,params){ const id=rpcId(); return new Promise((res,rej)=>{ waiters[id]={res,rej}; sendRaw({id,jsonrpc:"2.0",method,params}); setTimeout(()=>{if(waiters[id]){delete waiters[id];rej(Error("relay timeout"))}},15000)})} function handle(raw){ let m;try{m=JSON.parse(raw)}catch{return} if(m.method==="irn_subscription"){ if(!alive)return; sendRaw({id:m.id,jsonrpc:"2.0",result:true}); const d=m.params&&m.params.data; if(d&&subs[d.topic])Promise.resolve(subs[d.topic](d.message)).catch(()=>{}); return} if(m.id&&waiters[m.id]){ const w=waiters[m.id];delete waiters[m.id]; if(m.error)w.rej(Error(m.error.message||"relay error"));else w.res(m.result)}} async function connect(projectId){ try{sock&&sock.close()}catch{} sock=null;alive=false;gone="";waiters={};subs={}; const jwt=await U.relayJwt(RELAY); const url=`${RELAY}/?auth=${jwt}&projectId=${projectId}&ua=zswap`; const ws=WSC(url); sock=ws; await new Promise((res,rej)=>{ let d=0; const t=setTimeout(()=>{if(!d){d=1;rej(Error("The relay did not answer."))}},15000); const fail=m=>{try{ws.close()}catch{}if(sock===ws)sock=null;rej(Error(m))}; const end=f=>x=>{if(d)return;d=1;clearTimeout(t);f(x)}; sock.onopen=end(()=>{alive=true;res()}); sock.onerror=end(()=>fail("The relay could not be reached.")); sock.onclose=end(e=>fail("The relay closed the connection" +(e&&e.code?" (code "+e.code+(e.reason?": "+e.reason:"")+")":"")+"."))}) sock.onclose=()=>drop("The relay connection dropped. Reconnect your wallet."); sock.onmessage=e=>handle(typeof e.data==="string"?e.data:""); } const subscribe=async(topic,fn)=>{subs[topic]=fn;await relayCall("irn_subscribe",{topic})}; const publish=(topic,message,tag,ttl)=> relayCall("irn_publish",{topic,message,ttl:ttl||TTL,tag,prompt:tag===T_PROPOSE||tag===T_REQ}); async function pair(projectId,meta){ await connect(projectId); const symKey=U.rnd(32); const pTopic=await U.topicOf(symKey); const kp=await U.kex(); const proposeId=rpcId(); let settle=null; const pKey="p"+proposeId; const done=new Promise((res,rej)=>{settle={ res:v=>{delete waiters[pKey];res(v)}, rej:e=>{delete waiters[pKey];rej(e)}}}); waiters[pKey]={res:v=>settle.res(v),rej:e=>settle.rej(e)}; await subscribe(pTopic,async msg=>{ try{ const m=U.decode(symKey,msg); if(!m||m.id!==proposeId)return; if(m.error)return settle.rej(Error(m.error.message||"rejected")); const rp=m.result&&m.result.responderPublicKey; if(!rp)return; const sKey=await U.sessionKey(kp.priv,rp); const sTopic=await U.topicOf(sKey); await subscribe(sTopic,async smsg=>{ const s=U.decode(sKey,smsg); if(!s)return; if(s.method==="wc_sessionSettle"){ await publish(sTopic,U.encode(sKey,{id:s.id,jsonrpc:"2.0",result:true}),T_SETTLE_RES,STTL); const ns=s.params&&s.params.namespaces||{}; const accts=[]; for(const k in ns)for(const a of ns[k].accounts||[])accts.push(a); settle.res({topic:sTopic,key:sKey,accounts:accts, methods:(ns.eip155&&ns.eip155.methods)||[]}); return} if(s.method==="wc_sessionDelete")return drop("The wallet ended the session."); if(s.method&&onEvent)onEvent({t:"session",m:s}); if(s.id&&waiters["s"+s.id]){ const w=waiters["s"+s.id];delete waiters["s"+s.id]; if(s.error)w.rej(Object.assign(Error(s.error.message||"rejected"),{code:s.error.code})); else w.res(s.result)}}); }catch(e){settle.rej(e instanceof Error?e:Error(String(e)))} }); const proposal={id:proposeId,jsonrpc:"2.0",method:"wc_sessionPropose",params:{ relays:[{protocol:"irn"}], proposer:{publicKey:U.hex(kp.pub),metadata:meta}, requiredNamespaces:{}, optionalNamespaces:{eip155:{chains:Object.keys(CHAINS).map(id=>"eip155:"+id), methods:["eth_sendTransaction","personal_sign","eth_signTypedData_v4", "eth_call","eth_chainId","eth_accounts","eth_getBalance", "wallet_switchEthereumChain","wallet_addEthereumChain"], events:["chainChanged","accountsChanged"]}}}}; await publish(pTopic,U.encode(symKey,proposal),T_PROPOSE); const uri=`wc:${pTopic}@2?relay-protocol=irn&symKey=${U.hex(symKey)}`; return{uri,done}} function request(sess,method,params){ const id=rpcId(); const body={id,jsonrpc:"2.0",method:"wc_sessionRequest", params:{request:{method,params:params||[]},chainId:"eip155:1"}}; const p=new Promise((res,rej)=>{ waiters["s"+id]={res,rej}; setTimeout(()=>{if(waiters["s"+id]){delete waiters["s"+id];rej(Error("wallet timed out"))}},300000)}); publish(sess.topic,U.encode(sess.key,body),T_REQ).catch(e=>{ const w=waiters["s"+id];if(!w)return;delete waiters["s"+id];w.rej(e)}); return p} return{pair,request,close:()=>{drop("The wallet connection was closed.");try{sock&&sock.close()}catch{}sock=null}, on:f=>{onEvent=f},_relayCall:relayCall}; }; const QR8=(()=>{ const EXP=new Uint8Array(512),LOG=new Uint8Array(256); (()=>{let x=1;for(let i=0;i<255;i++){EXP[i]=x;LOG[x]=i;x<<=1;if(x&256)x^=285} for(let i=255;i<512;i++)EXP[i]=EXP[i-255]})(); const mul=(a,b)=>a&&b?EXP[LOG[a]+LOG[b]]:0; const gen=n=>{let p=[1]; for(let i=0;i<n;i++){const q=new Array(p.length+1).fill(0); for(let j=0;j<p.length;j++){q[j]^=mul(p[j],EXP[i]);q[j+1]^=p[j]}p=q} return p}; const rs=(data,n)=>{ const g=gen(n),r=new Uint8Array(data.length+n); r.set(data); for(let i=0;i<data.length;i++){ const c=r[i];if(!c)continue; for(let j=0;j<=n;j++)r[i+j]^=mul(g[n-j],c)} return r.subarray(data.length)}; const SZ=49,NBLK=2,DPB=97,ECB=24,ALIGN=[6,24,42]; const bch=(v,g,n)=>{let d=v<<n; const bits=x=>{let c=0;while(x){c++;x>>>=1}return c}; const gl=bits(g); while(bits(d)>=gl)d^=g<<(bits(d)-gl); return d}; const fmtBits=mask=>{ const v=(1<<3)|mask; return ((v<<10)|bch(v,0x537,10))^0x5412}; const verBits=()=>(8<<12)|bch(8,0x1f25,12); function encode(str){ const bytes=new TextEncoder().encode(str); if(bytes.length>NBLK*DPB-2)throw Error("pairing code too long to draw"); const bits=[]; const push=(v,n)=>{for(let i=n-1;i>=0;i--)bits.push((v>>i)&1)}; push(4,4);push(bytes.length,8); for(const b of bytes)push(b,8); const cap=(NBLK*DPB)*8; for(let i=0;i<4&&bits.length<cap;i++)bits.push(0); while(bits.length%8)bits.push(0); const cw=[]; for(let i=0;i<bits.length;i+=8){let v=0;for(let j=0;j<8;j++)v=(v<<1)|bits[i+j];cw.push(v)} const pads=[0xec,0x11]; for(let i=0;cw.length<NBLK*DPB;i++)cw.push(pads[i%2]); const blocks=[],ecs=[]; for(let i=0;i<NBLK;i++){ const d=Uint8Array.from(cw.slice(i*DPB,(i+1)*DPB)); blocks.push(d);ecs.push(rs(d,ECB))} const out=[]; for(let i=0;i<DPB;i++)for(const b of blocks)out.push(b[i]); for(let i=0;i<ECB;i++)for(const e of ecs)out.push(e[i]); return out} function frame(){ const m=[],fn=[]; for(let i=0;i<SZ;i++){m.push(new Array(SZ).fill(0));fn.push(new Array(SZ).fill(0))} const put=(r,c,v)=>{m[r][c]=v;fn[r][c]=1}; const finder=(r,c)=>{ for(let i=-1;i<8;i++)for(let j=-1;j<8;j++){ const rr=r+i,cc=c+j; if(rr<0||cc<0||rr>=SZ||cc>=SZ)continue; const on=(i>=0&&i<=6&&(j===0||j===6))||(j>=0&&j<=6&&(i===0||i===6))||(i>=2&&i<=4&&j>=2&&j<=4); put(rr,cc,on?1:0)}}; finder(0,0);finder(0,SZ-7);finder(SZ-7,0); for(const r of ALIGN)for(const c of ALIGN){ if((r===6&&c===6)||(r===6&&c===ALIGN[ALIGN.length-1])||(r===ALIGN[ALIGN.length-1]&&c===6))continue; for(let i=-2;i<=2;i++)for(let j=-2;j<=2;j++) put(r+i,c+j,(Math.abs(i)===2||Math.abs(j)===2||(i===0&&j===0))?1:0)} for(let i=8;i<SZ-8;i++){put(6,i,i%2?0:1);put(i,6,i%2?0:1)} put(SZ-8,8,1); for(let i=0;i<9;i++){if(!fn[8][i])put(8,i,0);if(!fn[i][8])put(i,8,0)} for(let i=0;i<8;i++){if(!fn[8][SZ-1-i])put(8,SZ-1-i,0);if(!fn[SZ-1-i][8])put(SZ-1-i,8,0)} const vb=verBits(); for(let i=0;i<18;i++){ const b=(vb>>i)&1,r=Math.floor(i/3),c=i%3; put(SZ-11+c,r,b);put(r,SZ-11+c,b)} return{m,fn}} function place(m,fn,cw){ let bit=0,up=1; const get=i=>(cw[i>>3]>>(7-(i&7)))&1; for(let c=SZ-1;c>0;c-=2){ if(c===6)c--; for(let k=0;k<SZ;k++){ const r=up?SZ-1-k:k; for(let j=0;j<2;j++){ const cc=c-j; if(fn[r][cc])continue; m[r][cc]=bit<cw.length*8?get(bit):0;bit++}} up^=1}} const maskFn=(k,r,c)=>[ (r+c)%2===0,r%2===0,c%3===0,(r+c)%3===0, (((r/2)|0)+((c/3)|0))%2===0,((r*c)%2+(r*c)%3)===0, (((r*c)%2+(r*c)%3)%2)===0,(((r+c)%2+(r*c)%3)%2)===0][k]; function penalty(m){ let p=0; for(let i=0;i<SZ;i++){ let rc=1,cc=1; for(let j=1;j<SZ;j++){ rc=m[i][j]===m[i][j-1]?rc+1:1;if(rc===5)p+=3;else if(rc>5)p++; cc=m[j][i]===m[j-1][i]?cc+1:1;if(cc===5)p+=3;else if(cc>5)p++}} for(let i=0;i<SZ-1;i++)for(let j=0;j<SZ-1;j++){ const s=m[i][j]+m[i][j+1]+m[i+1][j]+m[i+1][j+1]; if(s===0||s===4)p+=3} const pat=[1,0,1,1,1,0,1]; const hit=(get)=>{ for(let i=0;i<SZ;i++)for(let j=0;j<SZ-6;j++){ let okk=1;for(let k=0;k<7;k++)if(get(i,j+k)!==pat[k]){okk=0;break} if(!okk)continue; let before=1,after=1; for(let k=j-4;k<j;k++)if(k<0||get(i,k)!==0){before=0;break} for(let k=j+7;k<j+11;k++)if(k>=SZ||get(i,k)!==0){after=0;break} if(before||after)p+=40}}; hit((i,j)=>m[i][j]);hit((i,j)=>m[j][i]); let dark=0;for(let i=0;i<SZ;i++)for(let j=0;j<SZ;j++)dark+=m[i][j]; p+=Math.floor(Math.abs(dark*100/(SZ*SZ)-50)/5)*10; return p} function build(str){ const cw=encode(str); let best=null,bestP=Infinity,bestK=0; for(let k=0;k<8;k++){ const{m,fn}=frame(); place(m,fn,cw); for(let r=0;r<SZ;r++)for(let c=0;c<SZ;c++) if(!fn[r][c]&&maskFn(k,r,c))m[r][c]^=1; const f=fmtBits(k); for(let i=0;i<8;i++){ const b=(f>>i)&1; if(i<6)m[i][8]=b;else if(i===6)m[7][8]=b;else m[8][8]=b; m[8][SZ-1-i]=b} for(let i=8;i<15;i++){ const b=(f>>i)&1,c=14-i; if(c<6)m[8][c]=b;else m[8][7]=b; m[SZ-1-c][8]=b} m[SZ-8][8]=1; const p=penalty(m); if(p<bestP){bestP=p;best=m;bestK=k}} return{size:SZ,modules:best,mask:bestK}} return{build,_encode:encode}; })(); const wcNode=()=>rpcPin()||rpcPool[rpcPi]; const wcHost=()=>{try{return new URL(wcNode()).host}catch{return wcNode()}}; const WC_SIGN=["eth_sendTransaction","eth_signTransaction","personal_sign","eth_sign", "eth_signTypedData","eth_signTypedData_v3","eth_signTypedData_v4"]; const wcToWallet=m=>m.indexOf("wallet_")===0||WC_SIGN.indexOf(m)>=0; async function wcRpc(method,params){ try{return await nodeRead(method,params)} catch(e){if(e&&e.code!=null)throw e; throw Error("Could not reach "+wcHost()+" for reads. Pick another node from the WalletConnect panel.")}} const wcRelay=WCCLI(WCU,u=>new WebSocket(u)); const qrSvg=m=>{let d=""; for(let r=0;r<m.size;r++)for(let c=0;c<m.size;c++)if(m.modules[r][c])d+="M"+c+" "+r+"h1v1h-1z"; return '<svg viewBox="-4 -4 '+(m.size+8)+" "+(m.size+8)+'" role="img" aria-label="WalletConnect pairing code" style="width:100%;height:auto;background:#fff;border-radius:.3em"><path fill="#000" d="'+d+'"/></svg>'}; const wcShow=uri=>{ wkList.textContent=""; const box=document.createElement("div"); box.className="wcq"; box.innerHTML=qrSvg(QR8.build(uri)); const cp=document.createElement("button"); cp.type="button";cp.className="fclink";cp.textContent="copy link"; cp.onclick=()=>{navigator.clipboard?navigator.clipboard.writeText(uri).then(()=>{cp.textContent="copied"}).catch(()=>{cp.textContent="copy blocked"}):cp.textContent="copy blocked"}; const note=document.createElement("div"); note.className="wcn"; note.textContent="Scan with a mobile wallet, or "; note.appendChild(cp); const nd=document.createElement("div"); nd.className="wcn wcnode"; nd.appendChild(document.createTextNode("Reads via "+wcHost()+" ")); const ch=document.createElement("button"); ch.type="button";ch.className="fclink";ch.textContent="change"; ch.onclick=()=>{ const v=prompt("HTTPS Ethereum RPC used for reads — it is pinned to the front of the read pool (the DAO-curated list, then the page's seeds)." +" Signing always goes to your wallet. Leave blank for the default.",wcNode()); if(v===null)return; const t=v.trim(); try{if(!t)localStorage.removeItem(RPC_STORE); else if(/^https:\/\/\S+$/i.test(t))localStorage.setItem(RPC_STORE,t); else return}catch{} nd.firstChild.nodeValue="Reads via "+wcHost()+" "}; nd.appendChild(ch); wkList.appendChild(box);wkList.appendChild(note);wkList.appendChild(nd); wkHdr.textContent="WalletConnect"; wkWrap.classList.remove("hide"); const back=document.activeElement; cp.focus({preventScroll:true}); return new Promise((res,rej)=>{ const esc=e=>{if(e.key==="Escape")stop()}; const off=()=>{removeEventListener("keydown",esc);removeEventListener("keydown",wkTrap,true); wkWrap.onclick=null;if(back&&back.focus)try{back.focus()}catch{}}; const stop=()=>{off();rej(Object.assign(Error(""),{code:4001}))}; wkWrap.onclick=e=>{if(e.target===wkWrap)stop()}; addEventListener("keydown",esc); addEventListener("keydown",wkTrap,true); wcShow.settle=()=>{off();res()}})}; async function wcConnect(){ const meta={name:"zSwap",description:"zSwap",url:location.origin,icons:[]}; const{uri,done}=await wcRelay.pair(WC_PID,meta); const bail=wcShow(uri); stat.textContent="Scan the code with your wallet."; let sess; try{sess=await Promise.race([done,bail])} catch(e){wcRelay.close();throw e} finally{if(wcShow.settle)wcShow.settle(); wkHdr.textContent="Choose a wallet"; wkWrap.classList.add("hide")} const accts=sess.accounts.filter(a=>a.slice(0,9)==="eip155:1:").map(a=>a.split(":").pop()); if(!accts.length){wcRelay.close();throw Error("That wallet settled no Ethereum mainnet account — switch it to Ethereum and reconnect.")} wcRead=sess.methods.indexOf("eth_call")>=0; const read=async(method,params)=>{ try{return await wcRpc(method,params)} catch(e){ if(e&&e.code!==undefined||!wcRead)throw e; return wcRelay.request(sess,method,params||[])}}; const evs=[]; wcRelay.on(ev=>{if(ev&&ev.t==="closed")location.reload(); if(!ev||ev.t!=="session")return; const s=ev.m; if(!s)return; if(s.method==="wc_sessionUpdate")return evs.forEach(f=>f("reload",null)); if(s.method!=="wc_sessionEvent")return; const e=s.params&&s.params.event||{};let d=e.data; if(e.name==="chainChanged"&&typeof d==="string"&&d.includes(":"))d=d.split(":").pop(); if(e.name==="accountsChanged"&&Array.isArray(d))d=d.map(a=>typeof a==="string"&&a.includes(":")?a.split(":").pop():a); if(e.name==="chainChanged"||e.name==="accountsChanged")evs.forEach(f=>f(e.name,d))}); return{request:({method,params})=> method==="eth_requestAccounts"||method==="eth_accounts"?Promise.resolve(accts): method==="eth_chainId"?Promise.resolve("0x1"): wcToWallet(method)?wcRelay.request(sess,method,params||[]): read(method,params), on:(t,f)=>{if(t==="chainChanged"||t==="accountsChanged")evs.push((n,d)=>{if(n==="reload"||n===t)try{f(d)}catch{}})}}} let wcRead=true; const wkWrap=document.getElementById("wkWrap"),wkList=document.getElementById("wkList"); const wkChoices=()=>W6963.map(d=>({name:d.info.name,icon:d.info.icon,rdns:d.info.rdns,get:()=>d.provider})) .concat([{name:"WalletConnect",svg:WC_ICON,rdns:"wc",get:wcConnect}]); const WK="zswap:wk"; const wkRestore=async()=>{ const id=LS[WK]; if(PROV||!id||id==="wc")return; wkScan(); for(let i=0;i<8;i++){ const m=W6963.filter(x=>x.info.rdns===id),d=m.length===1?m[0]:null; if(d){ try{const a=await Promise.race([d.provider.request({method:"eth_accounts"}), new Promise(r=>setTimeout(()=>r(null),1500))]); if(a&&a[0])PROV=d.provider}catch{} return} await new Promise(r=>setTimeout(r,50)); }}; const wkTrap=e=>{ if(e.key!=="Tab")return; const f=[...wkPanel.querySelectorAll('button,[href],input,select,textarea,[tabindex]:not([tabindex="-1"])')] .filter(x=>!x.disabled&&x.offsetParent!==null); if(!f.length)return; const a=f[0],z=f[f.length-1],cur=document.activeElement; if(e.shiftKey?cur===a||!wkPanel.contains(cur):cur===z){e.preventDefault();(e.shiftKey?z:a).focus()} }; const wkPick=cs=>new Promise(res=>{ wkList.textContent=""; let done=false; const back=document.activeElement; const end=v=>{if(done)return;done=true; wkWrap.classList.add("hide");removeEventListener("keydown",esc); removeEventListener("keydown",wkTrap,true); if(back&&back.focus)try{back.focus()}catch{} res(v)}; const esc=e=>{if(e.key==="Escape")end(null)}; cs.forEach(c=>{ const b=document.createElement("button"); b.type="button";b.className="tkr"; if(c.icon){const im=document.createElement("img");im.src=c.icon;im.alt="";b.appendChild(im)} else if(c.svg){const sp=document.createElement("span");sp.className="wki";sp.innerHTML=c.svg;b.appendChild(sp)} b.appendChild(document.createTextNode(c.name)); b.onclick=()=>end(c); wkList.appendChild(b)}); wkWrap.onclick=e=>{if(e.target===wkWrap)end(null)}; addEventListener("keydown",esc); addEventListener("keydown",wkTrap,true); wkWrap.classList.remove("hide"); wkList.firstChild?.focus()}); async function wkResolve(){ if(PROV)return true; wkScan(); const inj=window.ethereum; if(W6963.length<2&&inj)return true; const cs=wkChoices(); const c=await wkPick(cs); if(!c)return false; stat.textContent="Connecting…"; try{PROV=await c.get()} catch(e){if(!isRejection(e))err(e);return false} try{if(c.rdns)LS[WK]=c.rdns}catch{} wkBind(PROV); return true} async function connect(){ if(connecting)return; connecting=true; try{ if(!await wkResolve())return; if(!prov()){stat.textContent=NO_WALLET;return} swap.textContent="Connecting…";swap.disabled=true; lnGo.textContent="Connecting…";lnGo.disabled=true; wnGo.textContent="Connecting…";wnGo.disabled=true; let accs; try{accs=await rpc("eth_requestAccounts",[])} catch(e){err(e);return} if(!accs[0])return; let chainId=await rpc(I,[]); if(!CHAINS[+chainId]){ try{await rpc("wallet_switchEthereumChain",[{chainId:"0x1"}])} catch(e){stat.textContent=isRejection(e)?"":"Switch to a supported network.";return} chainId=await rpc(I,[]); if(!CHAINS[+chainId]){stat.textContent="Switch to a supported network.";return} } setChain(+chainId);showNet(); sessionStorage.removeItem("dc"); account=accs[0];sOpen(); const keepPair=pairAddrs(); showAddr(); if(!listLive){ swap.textContent="Loading tokens\u2026"; await loadTokenList(); } adoptList(keepPair); refreshBalance(); update(); fcMine(); loadPos(); syncChart(); if(lnMode)lnKindQuote(); }finally{connecting=false;swap.disabled=false; lnGo.disabled=false;lnGo.textContent=account?"Launch":"Connect Wallet"; wnGo.disabled=false; if(wnMode){wnPaint();wnQuote();wnRoll()}else wnGo.textContent="Register"; if(pvMode)pvWake();render()} } const lqReserveGas=()=>lqList.querySelector(".lqnew")?LQ_CREATE_GAS+300000n:400000n; const lqFillMax=(tok,max)=>{ const box=lqList.querySelector(".lqadd:not(.hide)"); const pair=chPair(); if(!box||!pair)return false; const side=pair[0].addr.toLowerCase()===tok.addr.toLowerCase()?"0":"1"; const el=box.querySelector(`.lqin[data-side="${side}"]`); if(!el)return false; el.value=formatUnits(max,tok.dec); el.dispatchEvent(new Event("input",{bubbles:true})); return true; }; bal1.addEventListener("click",async e=>{ if(e.target.tagName!=="A")return; e.preventDefault(); const t=TOKENS[toSel.value]; if(!t)return; let reserve=0n; if(t.addr===ZERO){ const g=lqReserveGas(); try{reserve=BigInt(await rpc("eth_gasPrice",[]))*g}catch{} if(reserve<=0n)reserve=GAS_FLOOR*g; } const max=toBalance>reserve?toBalance-reserve:0n; if(lqFillMax(t,max))return; outAmt.value=formatUnits(max,t.dec); fitFont(outAmt); lqPreviewSoon(); }); bal.addEventListener("click",async e=