memoscan
← all memos

Memo 0x7bd11465…e1aa01 on Ethereum

0x68575b07…67c7·#25,913,388·view on Etherscan
er,lnArtBytes,lnArtMime)}; const sim=await rpc(C,[req,L]); const candidate=/^0x[0-9a-fA-F]{128}$/.test(sim||"")?"0x"+strip0x(sim).slice(24,64):null; const receipt=await waitTx(await sendTx([req]));sGot(); lnSet(false); lnName.value="";lnSym.value="";lnSupply.value="";lnAlloc.value=""; const topic=kecStr("Launched(address,address,address,uint256,uint256,uint256)"); const lg=(receipt.logs||[]).find(l=>(l.address||"").toLowerCase()===PLAUNCH.toLowerCase() &&(l.topics||[])[0]&&l.topics[0].toLowerCase()===topic.toLowerCase()); let token=lg?"0x"+strip0x(lg.topics[1]).slice(24):null;if(token&&!isAddr(token))token=null; if(!token&&candidate){ try{ const c=await rpc(C,[{to:PLAUNCH,data:"0x"+SEL_CREATOROF+encAddr(candidate)},L]); if(c&&"0x"+strip0x(c).slice(24)===owner.toLowerCase())token=candidate; }catch{} } if(token){ try{ const idx=await addCustomToken(token); TOKENS[idx].launched=1; rebuild(); fromSel.value=String(Math.max(0,TOKENS.findIndex(t=>t.addr===ZERO))); fromSel.dataset.prev=fromSel.value; toSel.value=String(idx); toSel.dataset.prev=toSel.value; pairChosen=true; syncDisabled();syncNftUI(); refreshBalance(); update(); }catch{} } stat.innerHTML=token?`${safeSym(sym)} is live at ` +`<a href="${chainCfg().explorer}/token/${token}" target="_blank" rel="noreferrer">${short(token)}</a>` +` \u00b7 0.4% of each trade goes to you \u2014 collect it from the coin panel` :`${safeSym(sym)} is live \u00b7 0.4% of each trade goes to you`; lnArtBytes=null;lnArtNote.textContent="none";lnArtNote.classList.remove("set"); lnPrev.classList.remove("set");lnArt.value=""; }catch(e){err(e)} finally{lnGo.disabled=false} }; const SEL_MARKETS="29c21083",SEL_TAPE="29a65241"; const SEL_BYCREATOR="7d78be2b",SEL_TOKEN1="d21220a7",SEL_BYCREATOR_N="aa5e6b5b",SEL_RESERVE0="443cb4bc",SEL_FEERECIP="46904840"; const LAUNCHED=[]; const LAUNCH_SHOW=24; const LAUNCH_SCAN=256; const FINE=300,COARSE=14400,TFS=[["5m",300],["1h",3600],["4h",14400],["1d",86400]]; const CH_POOLS=8; const srcFor=tf=>tf>=COARSE?COARSE:FINE; let chFloor=0,chSupply=0,chFloorKey="",chCoin1=0; let chKind=LS.ck==="line"?"line":"candle",chInv=false,chInvKey="",chPeriod=300,chBars=null,chSeq=0,chPools=null,chOpen=LS.ch==="1",chCache={}; let chDraw=null; const chKeep=(key,val)=>{ chCache[key]=val; for(const k in chCache)if(k!==key&&Date.now()-chCache[k].at>60000)delete chCache[k]; }; const unf=p=>(p&0xffffff)*2**(p>>>24); const decBar=w=>{if(!w)return null;const f=s=>Number((w>>BigInt(s))&0xffffffffn); return{b:Number(w&0xffffffffn),o:unf(f(32)),h:unf(f(64)),l:unf(f(96)),c:unf(f(128)),v:unf(f(160)),n:Number((w>>192n)&0xffffn)}}; const rollUp=(bars,src,dst)=>{if(dst<=src)return bars.filter(Boolean); const out=[];let g=null,k=null; for(let i=bars.length-1;i>=0;i--){const b=bars[i];if(!b)continue; const key=Math.floor(b.b*src/dst); if(key!==k){if(g)out.push(g);k=key;g={b:key,o:b.o,h:b.h,l:b.l,c:b.c,v:b.v,n:b.n}} else{g.h=Math.max(g.h,b.h);g.l=Math.min(g.l,b.l);g.c=b.c;g.v+=b.v;g.n+=b.n}} if(g)out.push(g);return out.reverse()}; const CH_WICK_SHARE=.01; const mergeTapes=tapes=>{const m=new Map(); for(const bars of tapes)for(const b of bars||[]){if(!b)continue; let e=m.get(b.b); if(!e)m.set(b.b,e={b:b.b,v:0,n:0,ov:0,cv:0,parts:[]}); e.v+=b.v;e.n+=b.n;e.ov+=b.o*b.v;e.cv+=b.c*b.v;e.parts.push(b)} const out=[...m.values()].sort((x,y)=>y.b-x.b); for(const e of out){ const big=e.v>0?e.parts.filter(x=>x.v>=e.v*CH_WICK_SHARE):[]; const src=big.length?big:e.parts; let h=-Infinity,l=Infinity; for(const x of src){if(x.h>h)h=x.h;if(x.l<l)l=x.l} e.h=h;e.l=l; if(e.v>0){e.o=e.ov/e.v;e.c=e.cv/e.v}else{e.o=src[0].o;e.c=src[0].c} delete e.ov;delete e.cv;delete e.parts} return out}; const chPair=()=>{const f=TOKENS[fromSel.value],t=TOKENS[toSel.value]; if(!f||!t||f.addr===t.addr)return null; return f.addr.toLowerCase()<t.addr.toLowerCase()?[f,t]:[t,f]}; let chLoading=""; async function loadChart(){ const p0=chPair(); const k0=chPairKey(p0); if(k0&&chLoading===k0)return; chBars=null;chPools=null; const p=p0; if(tab!=="swap"||!p){syncChartUI();return} const my=++chSeq,key=k0; const hit=chCache[key]; if(hit&&Date.now()-hit.at<30000){chBars=hit.bars;chPools=hit.pools;syncChartUI();return} chLoading=key; try{ if(PPLENS===ZERO||(await rpc("eth_getCode",[PPLENS,L])).length<5)return syncChartUI(); const marketsFor=async pair=>{ const [raw]=await mc3([{to:PPLENS,data:"0x"+SEL_MARKETS+encAddr(pair[0].addr)+encAddr(pair[1].addr) +encAddr(ZERO)+encUint(0)+encUint(LQ_SCAN)+encUint(0)}]); const found=[]; if(raw){const h=strip0x(raw),n=Number(BigInt("0x"+h.slice(64,128))),base=128; for(let i=0;i<n&&i<LQ_SCAN;i++){const at=k=>BigInt("0x"+h.slice(base+(i*PI_WORDS+k)*64,base+(i*PI_WORDS+k+1)*64)); if(at(PI_HOOK)!==0n||at(PI_LIQ)===0n)continue; found.push({a:"0x"+h.slice(base+(i*PI_WORDS+PI_POOL)*64+24,base+(i*PI_WORDS+PI_POOL+1)*64),liq:at(PI_LIQ)})}} found.sort((x,y)=>y.liq>x.liq?1:y.liq<x.liq?-1:0); return found.slice(0,CH_POOLS).map(x=>x.a); }; let eff=p,pools=await marketsFor(p); if(my!==chSeq)return; if(!pools.length){ const alt=chOtherForm(p); if(alt){ const altPools=await marketsFor(alt); if(my!==chSeq)return; if(altPools.length){eff=alt;pools=altPools} } } const [t0,t1]=eff; if(!pools.length){chKeep(key,{at:Date.now(),bars:null,pools:null,pair:null});return syncChartUI()} const reqs=[]; for(const a of pools)reqs.push({to:a,data:"0x"+SEL_TAPE+encUint(FINE)+encUint(256)}, {to:a,data:"0x"+SEL_TAPE+encUint(COARSE)+encUint(256)}); const tapes=await mc3Deep(reqs); if(my!==chSeq)return; const dec1Tape=hex=>{if(!hex)return null; const h=strip0x(hex),n=Number(BigInt("0x"+h.slice(64,128))),bars=[]; for(let j=0;j<n;j++)bars.push(decBar(BigInt("0x"+h.slice(128+j*64,128+(j+1)*64)))); return bars}; const decoded=tapes.map(dec1Tape); const fine=[],coarse=[]; for(let i=0;i<pools.length;i++){fine.push(decoded[i*2]);coarse.push(decoded[i*2+1])} const sc=10**(t0.dec-t1.dec)/1e18; const build=set=>{const m=mergeTapes(set); for(const b of m){b.o*=sc;b.h*=sc;b.l*=sc;b.c*=sc}return m.length?m:null}; const f=build(fine); let c=build(coarse); if(f&&c){const lead=rollUp(f,FINE,COARSE).filter(b=>b.b>c[0].b); if(lead.length)c=lead.concat(c)} chBars=f||c?{[FINE]:f,[COARSE]:c}:null; const live=set=>set.filter(d=>d&&d.some(Boolean)).length; chPools=chBars?{[FINE]:live(fine),[COARSE]:live(coarse)}:null; chKeep(key,{at:Date.now(),bars:chBars,pools:chPools,pair:eff===p?null:eff}); }catch{chBars=null;chPools=null} finally{if(chLoading===k0)chLoading=""} if(my===chSeq)syncChartUI(); } const chPoolsAt=step=>chPools&&chPools[step]||0; const chLabel=p=>chInv?`${p[0].sym} per ${p[1].sym}`:`${p[1].sym} per ${p[0].sym}`; async function chFloorFor(p){ const key=chPairKey(p); if(key===chFloorKey)return; chFloorKey=key;chFloor=0;chSupply=0;chCoin1=0; const tok=p&&p[1]&&p[1].launched?p[1].addr:p&&p[0]&&p[0].launched?p[0].addr:""; if(!tok)return; chCoin1=p[1]&&p[1].launched?1:0; try{ const [fp,sup]=await mc3Deep([{to:PLAUNCH,data:"0x"+SEL_FLOORPRICE+encAddr(tok)}, {to:tok,data:"0x"+SEL_TOTALSUPPLY}]); if(key!==chFloorKey)return; chFloor=fp?+formatUnits(BigInt(fp),18):0; chSupply=sup?+formatUnits(BigInt(sup),18):0; }catch{} } function syncChartUI(){ const on=tab==="swap"&&!!chBars; chTog.classList.toggle("hide",!on); chBox.classList.toggle("hide",!on||!chOpen); chTog.setAttribute("aria-expanded",on&&chOpen?"true":"false"); if(!on||!chOpen)return; const p=chEff(); chNote.textContent=p?chLabel(p):""; drawChart();syncInv(); } const NUMERAIRES=new Set([ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "0xdac17f958d2ee523a2206206994597c13d831ec7", "0x6b175474e89094c44da98b954eedeac495271d0f", ]); const moneyRank=a=>{a=(a||"").toLowerCase(); return NUMERAIRES.has(a)?2:(a===ZERO||a===WETH.toLowerCase())?1:0}; const chPairKey=p=>p?p[0].addr.toLowerCase()+":"+p[1].addr.toLowerCase():""; const chNaturalInv=p=>!!p&&moneyRank(p[0].addr)>moneyRank(p[1].addr); const chOtherForm=p=>{ const eth=p.filter(x=>isEthLike(x.addr)); if(eth.length!==1)return null; const cur=eth[0],rest=p[0]===cur?p[1]:p[0]; const sub=TOKENS.find(x=>x.addr.toLowerCase()===(cur.addr===ZERO?WETH:ZERO).toLowerCase()); if(!sub)return null; return sub.addr.toLowerCase()<rest.addr.toLowerCase()?[sub,rest]:[rest,sub]; }; const chEff=()=>{const p=chPair();if(!p)return p; const hit=chCache[chPairKey(p)]; return (hit&&hit.pair)||p;}; const CH_SLOTS=Math.floor((340-2-42)/3),CH_FILL=.34; const chFinest=()=>chBars&&chBars[FINE]?FINE:COARSE; const chSeries=secs=>{ if(!chBars)return null; const src=srcFor(secs),step=chBars[src]?src:chFinest(),base=chBars[step]; if(!base||!base.length)return null; const per=Math.max(secs,step); let pts=rollUp(base,step,per).slice().reverse(); pts=pts.map(b=>{const{o,c}=b; if(!(o>0)||!(c>0)||!isFinite(o)||!isFinite(c))return null; const h=b.h>0&&isFinite(b.h)?b.h:0,l=b.l>0&&isFinite(b.l)?b.l:Infinity; return{...b,h:Math.max(h,o,c),l:Math.min(l,o,c)}}).filter(Boolean); return pts.length?{pts,per,step}:null; }; const chAutoPeriod=()=>{ if(!chBars)return null; const fit=secs=>{const s=chSeries(secs); if(!s||s.per!==secs)return null; const pts=s.pts,newest=pts[pts.length-1].b; const shown=pts.filter(b=>newest-b.b<CH_SLOTS); if(!shown.length)return null; const fill=shown.length/(newest-shown[0].b+1); const whole=newest-pts[0].b+1<=CH_SLOTS; return{score:shown.length*fill,ok:shown.length>=6&&fill>=CH_FILL&&whole}}; let best=null,bestS=-1; for(const[,secs] of TFS){const f=fit(secs); if(!f)continue; if(f.ok)return secs; if(f.score>bestS){best=secs;bestS=f.score}} return best==null?chFinest():best; }; let chTfKey=""; const chSyncPeriod=()=>{ const k=chPairKey(chEff()); if(k===chTfKey)return; const auto=chAutoPeriod(); if(auto==null)return; chTfKey=k;chPeriod=auto; }; const chSyncTfs=()=>{ const finest=chFinest(); if(chPeriod<finest)chPeriod=finest; for(const c of chTf.children){if(!c.dataset.secs)continue; const secs=Number(c.dataset.secs); c.disabled=!!chBars&&secs<finest; c.title=c.disabled?"This pair has no five-minute tape to draw":""; c.classList.toggle("on",secs===chPeriod)} }; const chSyncOrientation=()=>{ const p=chEff(),k=chPairKey(p); if(k===chInvKey)return; chInvKey=k;chInv=chNaturalInv(p); }; const hudFor=i=>{ if(!chDraw)return; const{pts,num,UP,DN,ch,per,hd}=chDraw; if(!hd)return; if(i<0){const b=pts[pts.length-1]; let note="",flip=""; if(chInv&&isFinite(ch)&&ch>-100){ const other=(1/(1+ch/100)-1)*100; const pr=chEff&&chEff(); const base=pr&&pr[0]?pr[0].sym:"the token"; note=` title="${safeSym(base)} is ${other>=0?"+":""}${other.toFixed(2)}% over this window. ` +`This chart prices the pair the other way up, so its line moves the opposite way."`; flip=` <span class="chflip">${safeSym(base)} ${other>=0?"+":""}${other.toFixed(2)}%</span>`; } hd.innerHTML=`<b>${num(b.c)}</b> <span style="color:${ch>=0?UP:DN}"${note}>${ch>=0?"+":""}${ch.toFixed(2)}%</span>${flip}`; return} const b=pts[i],up=b.c>=b.o,d=new Date(b.b*per*1e3); const when=per>=86400 ?d.toLocaleDateString("en-US",{month:"short",day:"numeric"}) :d.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",hour12:false}); hd.innerHTML=`<b style="color:${up?UP:DN}">${num(b.c)}</b> <span>${when}</span>` +`<span class="ohlc">H ${num(b.h)} L ${num(b.l)} · ${b.n} trade${b.n===1?"":"s"}</span>`; }; const chPoint=e=>{ if(!chDraw)return; const r=chArt.getBoundingClientRect(); if(!r.width)return; const{pts,W,PL,st,b0}=chDraw; const x=(e.clientX-r.left)/r.width*W; const at=b0+Math.round((x-PL)/st-.5); let i=0,near=Infinity; for(let j=0;j<pts.length;j++){const d=Math.abs(pts[j].b-at); if(d<near){near=d;i=j}} hudFor(i); if(!chDraw.svg)return; let el=chDraw.cross; if(!el){ el=document.createElementNS("http://www.w3.org/2000/svg","line"); el.setAttribute("class","cross"); el.setAttribute("y1","0");el.setAttribute("y2","150"); el.setAttribute("stroke","currentColor");el.setAttribute("stroke-opacity",".35"); el.setAttribute("stroke-width",".8"); chDraw.svg.appendChild(el);chDraw.cross=el; } const cx=chDraw.X(i).toFixed(1); el.setAttribute("x1",cx);el.setAttribute("x2",cx); }; chArt.addEventListener("pointermove",chPoint); chArt.addEventListener("pointerdown",chPoint); chArt.addEventListener("pointerleave",()=>{ if(chDraw&&chDraw.cross){chDraw.cross.remove();chDraw.cross=null} hudFor(-1)}); function drawChart(){ if(!chBars)return; const W=340,H=150,PL=2,PR=42,PT=10,PB=14,VH=22; const pw=W-PL-PR,ph=H-PT-PB-VH; chSyncPeriod();chSyncOrientation();chSyncTfs(); const ser=chSeries(chPeriod); if(!ser){chArt.innerHTML='<div class="msg">No trades in this window.</div>';chDraw=null;return} const per=ser.per; let pts=ser.pts; const newest=pts[pts.length-1].b,cap=Math.floor(pw/3); const kept=pts.filter(b=>newest-b.b<cap); const clipped=kept.length<pts.length; pts=kept; if(chInv)pts=pts.map(b=>({...b,o:1/b.o,h:1/b.l,l:1/b.h,c:1/b.c})) .filter(b=>isFinite(b.o)&&isFinite(b.h)&&isFinite(b.l)&&isFinite(b.c)); if(!pts.length){chArt.innerHTML='<div class="msg">No trades in this window.</div>';chDraw=null;return} let hi=-Infinity,lo=Infinity,vm=0; for(const b of pts){if(b.v>vm)vm=b.v} if(chKind==="line"){ for(const b of pts){if(b.c>hi)hi=b.c;if(b.c<lo)lo=b.c} }else{ let bh=-Infinity,bl=Infinity; for(const b of pts){const t=Math.max(b.o,b.c),u=Math.min(b.o,b.c); if(t>bh)bh=t;if(u<bl)bl=u} const span=bh>bl?bh-bl:bh*.1; const cutHi=Math.min(bh+span*CH_WICK_CAP,bh*2), cutLo=Math.max(bl-span*CH_WICK_CAP,bl/2); for(const b of pts){ const h=Math.min(b.h,cutHi),l=Math.max(b.l,cutLo); if(h>hi)hi=h;if(l<lo)lo=l} } if(hi===lo){hi*=1.001;lo*=0.999} const rawLo=lo; let sp=hi-lo;hi+=sp*.09; lo-=Math.min(sp*.09,rawLo>0?rawLo*.1:0); if(lo<=0)lo=rawLo>0?rawLo*.9:0; sp=hi-lo; const n=pts.length,b0=pts[0].b,slots=pts[n-1].b-b0+1; const st=pw/slots,bw=Math.max(1,Math.min(9,st*.68)); const X=i=>PL+st*(pts[i].b-b0+.5),Y=p=>PT+ph*(1-(p-lo)/sp),vt=PT+ph+6,VY=v=>vt+(VH-6)*(1-(vm?v/vm:0)); const num=v=>v>=1000?v.toLocaleString("en-US",{maximumFractionDigits:2}):v>=1?v.toFixed(3):fmtPx(v); const UP="#16a34a",DN="#c33"; const p0=chEff(),lbl=p0?chLabel(p0):"Price"; let s=`<svg viewBox="0 0 ${W} ${H}" preserveAspectRatio="none" role="img" aria-label="${lbl}, ${n} bars, ${num(pts[n-1].c)} now, range ${num(lo)} to ${num(hi)}">`; for(let g=0;g<=3;g++){const p=lo+sp*g/3,y=Y(p).toFixed(1); s+=`<line x1="${PL}" y1="${y}" x2="${W-PR}" y2="${y}" stroke="currentColor" stroke-opacity=".1"/>` +`<text x="${W-PR+4}" y="${(Y(p)+2.5).toFixed(1)}" font-size="7" fill="currentColor" fill-opacity=".5">${p>0?num(p):"0"}</text>`} for(let i=0;i<n;i++){const b=pts[i],y=VY(b.v); s+=`<rect x="${(X(i)-bw/2).toFixed(1)}" y="${y.toFixed(1)}" width="${bw.toFixed(1)}" height="${Math.max(.4,vt+VH-y).toFixed(1)}" fill="currentColor" fill-opacity=".18"/>`} const chNum=p0&&(chCoin1?p0[0]:p0[1]); const ethNum=!!chNum&&(chNum.addr===ZERO||chNum.addr===WETH); const fl=chFloor>0&&ethNum?(chCoin1?(chInv?chFloor:1/chFloor):(chInv?1/chFloor:chFloor)):0; if(fl>0&&fl>=lo&&fl<=hi){ const fy=Y(fl).toFixed(1); s+=`<line x1="${PL}" y1="${fy}" x2="${W-PR}" y2="${fy}" stroke="currentColor" stroke-opacity=".45" stroke-width=".7" stroke-dasharray="3 2"/>` +`<text x="${PL+3}" y="${(Y(fl)-2.5).toFixed(1)}" font-size="6.5" fill="currentColor" fill-opacity=".6">floor</text>`; } const rise=pts[n-1].c>=pts[0].o; if(chKind==="line"){ const d=pts.map((b,i)=>`${i?"L":"M"}${X(i).toFixed(1)} ${Y(b.c).toFixed(1)}`).join(" "); const col=rise?UP:DN; s+=`<path d="${d} L${X(n-1).toFixed(1)} ${(PT+ph).toFixed(1)} L${X(0).toFixed(1)} ${(PT+ph).toFixed(1)} Z" fill="${col}" fill-opacity=".1"/>` +`<path d="${d}" fill="none" stroke="${col}" stroke-width="1.2" stroke-linejoin="round"/>` +`<circle cx="${X(n-1).toFixed(1)}" cy="${Y(pts[n-1].c).toFixed(1)}" r="1.8" fill="${col}"/>`; }else{ for(let i=0;i<n;i++){const b=pts[i],col=b.c>=b.o?UP:DN,x=X(i); const t=Y(Math.max(b.o,b.c)),bo=Y(Math.min(b.o,b.c)); s+=`<line x1="${x.toFixed(1)}" y1="${Y(b.h).toFixed(1)}" x2="${x.toFixed(1)}" y2="${Y(b.l).toFixed(1)}" stroke="${col}" stroke-width=".8"/>` +`<rect x="${(x-bw/2).toFixed(1)}" y="${t.toFixed(1)}" width="${bw.toFixed(1)}" height="${Math.max(.8,bo-t).toFixed(1)}" fill="${col}"/>`} } const spanS=(pts[n-1].b-pts[0].b+1)*per; const tAt=b=>{const d=new Date(b*per*1000); return spanS>129600?d.toLocaleDateString("en-US",{month:"short",day:"numeric"}) :d.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",hour12:false})}; const ticks=n>=3?[[0,"start"],[n>>1,"middle"],[n-1,"end"]]:[[0,"start"],[n-1,"end"]]; const tLbl=ticks.map(([i])=>i>=0&&i<n?tAt(pts[i].b):""); ticks.forEach(([i,anc],k)=>{if(i<0||i>=n)return; if(anc==="middle"&&(tLbl[k]===tLbl[0]||tLbl[k]===tLbl[tLbl.length-1]))return; s+=`<text x="${X(i).toFixed(1)}" y="${H-3.5}" font-size="6.5" text-anchor="${anc}" ` +`fill="currentColor" fill-opacity=".45">${tLbl[k]}</text>`}); s+="</svg>"; const last=pts[n-1],first=pts[0],ch=((last.c-first.o)/first.o)*100; chArt.innerHTML=s+'<div class="hd"></div>'; chDraw={pts,X,W,PL,st,b0,num,UP,DN,ch,per, hd:chArt.querySelector(".hd"),svg:chArt.querySelector("svg"),cross:null}; hudFor(-1); const took=rel(Math.max(per,(slots-1)*per)); const np=chPoolsAt(ser.step); const fine=(chBars&&chBars[chFinest()])||null; const newestBar=fine?fine.find(b=>b&&b.c>0):null; const latest=newestBar?newestBar.c:pts[n-1].c; const canon=latest>0?1/latest:0; const px=chCoin1?canon:latest; const mcap=chSupply>0&&px>0?chSupply*px:0; chNote.textContent=p0?[chLabel(p0), mcap>0?`${mcap>=1000?Math.round(mcap).toLocaleString("en-US"):mcap.toFixed(mcap>=1?1:3)} ${ethNum?"ETH":chCoin1?p0[0].sym:p0[1].sym} mcap${ ethNum&&ethUsd>0?` (${fmtUsd(mcap*ethUsd)})`:""}`:"", `${np} pool${np===1?"":"s"}`,`${clipped?"last ":""}${took}`].filter(Boolean).join(" · "):""; if(p0){const was=chFloor+":"+chSupply+":"+chCoin1; chFloorFor(p0).then(()=>{if(chFloor+":"+chSupply+":"+chCoin1!==was)drawChart()});} } for(const[label,secs]of TFS){const b=document.createElement("button"); b.textContent=label;b.dataset.secs=String(secs);if(secs===chPeriod)b.className="on"; b.onclick=()=>{chPeriod=secs;chTfKey=chPairKey(chEff());drawChart()}; chTf.appendChild(b)} const kindBtn=document.createElement("button"); kindBtn.className="chk"; const syncKind=()=>{kindBtn.textContent=chKind==="candle"?"Line":"Candle"; kindBtn.title=`Switch to ${kindBtn.textContent.toLowerCase()} chart`}; syncKind(); kindBtn.onclick=()=>{chKind=chKind==="candle"?"line":"candle";LS.ck=chKind;syncKind();drawChart()}; chTf.appendChild(kindBtn); const invBtn=document.createElement("button"); invBtn.className="chk"; invBtn.textContent="⇅"; const syncInv=()=>{const p=chEff(); invBtn.title=p?`Price ${chInv?p[1].sym:p[0].sym} instead — currently ${chInv?p[0].sym:p[1].sym} per ${chInv?p[1].sym:p[0].sym}`:"Invert the price"; invBtn.setAttribute("aria-pressed",chInv?"true":"false")}; syncInv(); invBtn.onclick=()=>{chInv=!chInv;syncInv();drawChart()}; chTf.appendChild(invBtn); const syncChart=()=>{chSyncOrientation();syncInv();loadChart()}; chTog.onclick=()=>{chOpen=!chOpen;LS.ch=chOpen?"1":"0";syncChartUI()}; const lsecs=v=>{const m=/^(\d+)([mhdw]?)$/.exec((v||"").trim()); return m?+m[1]*(m[2]=="d"?86400:m[2]=="h"?3600:m[2]=="w"?604800:m[2]=="m"?60:1):NaN}; const symAddr=x=>{const m=TOKENS.filter(t=>t.sym.toLowerCase()===x); return m.length===1?m[0].addr.toLowerCase():""}; const ARCADE=".arcade.wei",SC_OWNER="6352211e",SC_TEXT="308e3386"; const scEl=document.getElementById("scEl"); let scSeq=0; const scShow=async name=>{ const my=++scSeq; const n=String(name||"").trim().toLowerCase(); if(!/^[a-z0-9-]{1,63}\.arcade\.wei$/.test(n)){scEl.classList.add("hide");return} const lbl=n.slice(0,-ARCADE.length); scEl.classList.remove("hide"); scEl.textContent="Reading "+n+"\u2026"; let owner="",rec=""; try{ const id=namehash(n); const[o,t]=await cfgBatch([{to:WNS,data:"0x"+SC_OWNER+pad32(id)}, {to:WNS,data:"0x"+SC_TEXT+pad32(id)+encUint(64)+strTail("score")}]); if(my!==scSeq)return; const a="0x"+strip0x(o||"").slice(24); if(!/^0x[0-9a-f]{40}$/i.test(a)||/^0x0{40}$/i.test(a))throw Error("gone"); owner=a; try{rec=decStr(t)}catch{} }catch{if(my===scSeq)scEl.textContent="No such name \u2014 "+n+" has never been minted.";return} const m=/^(\d+)(?:-w(\d+))?-[0-9a-z]+$/.exec(lbl); scEl.textContent=""; const b=document.createElement("b");b.textContent=n;scEl.appendChild(b); const line=t=>{const d=document.createElement("div");d.textContent=t;scEl.appendChild(d);return d}; if(m)line(`Minted score ${(+m[1]).toLocaleString("en-US")}`+(m[2]?` \u00b7 reached wave ${m[2]}`:"")); else line("Not a score name \u2014 the label carries no run."); line("Held by "+short(owner)); if(m)line("Anyone can mint a name with any number \u2014 this says it was claimed, not earned.").className="scw"; if(m&&rec&&rec!==m[1])line(`The score record now reads ${rec}, not ${m[1]} \u2014 the holder changed it.`).className="scw"; const go=document.createElement("button");go.type="button";go.textContent="Play invaders"; go.onclick=()=>{sBlip();invPlay()}; scEl.appendChild(go); }; let lSeq=0,listReady=false; const lkWrote=Object.create(null); const lkKeep=(el,v)=>{const w=lkWrote[el.id]; if(el.value!==""&&el.value!==w&&(w!==undefined||el.type!=="select-one"))return false; el.value=v;lkWrote[el.id]=v;return true; }; async function applyLink(e){ const q=new URLSearchParams(location.hash.slice(1)); const my=++lSeq; if(![...q.keys()].length){ if(e){ if(typeof amt!=="undefined"&&amt){amt.value="";fitFont(amt)} if(typeof outAmt!=="undefined"&&outAmt){outAmt.value="";fitFont(outAmt)} if(typeof rc!=="undefined"&&rc){rc.value="";rc.classList.remove("bad")} if(typeof rcvEl!=="undefined"&&rcvEl)rcvEl.textContent=""; if(typeof scEl!=="undefined"&&scEl)scEl.classList.add("hide"); setMode("in"); last=null; try{update()}catch{} } return;} const wantChain=+q.get("chain")||0; if(CHAINS[wantChain]&&wantChain!==CHAIN_ID){ if(prov()){if(wireWallet.probed)stat.textContent=`This link is for ${CHAINS[wantChain].name} \u2014 switch your wallet there to use it.`;return} setChain(wantChain);showNet();await loadTokenList();if(my!==lSeq)return; } const at=a=>a?TOKENS.findIndex(t=>t.addr.toLowerCase()===a):-1; const tok=async v=>{if(!v)return "";const x=v.trim().toLowerCase(); if(!/^0x[0-9a-f]{40}$/.test(x))return symAddr(x); if(at(x)<0)try{await addCustomToken(x,0)}catch{} return at(x)<0?"":x}; if(symAddr((q.get("token")||"").trim().toLowerCase())||symAddr((q.get("out")||"").trim().toLowerCase()))pairChosen=true; const both=async()=>[await tok(q.get("token")),await tok(q.get("out"))]; let[fa,ta]=await both(); if(my!==lSeq)return; if((fa&&at(fa)<0)||(ta&&at(ta)<0)){[fa,ta]=await both();if(my!==lSeq)return} if(!listReady){ const named=["token","out"].map(k=>(q.get(k)||"").trim()).filter(Boolean); if(named.some(v=>!/^0x[0-9a-f]{40}$/i.test(v)&&!symAddr(v.toLowerCase())))return; } const fi=at(fa),oi=at(ta); if(fi>=0||oi>=0)pairChosen=true; rebuild(); if(fi>=0){fromSel.value=fi;fromSel.dataset.prev=fromSel.value} if(oi>=0&&oi!==fi){toSel.value=oi;toSel.dataset.prev=toSel.value} if(q.get("score"))scShow(q.get("score"));else scEl.classList.add("hide"); const to=q.get("to"),lk=lsecs(q.get("lock")),want=q.get("tab"),n=q.get("amount"); const t=want==="swap"||want==="send"||want==="book"?want :q.get("out")?"swap":(to||!isNaN(lk))?"send":tab; if(fromSel.value===toSel.value){ const alt=String(TOKENS.findIndex((x,i)=>String(i)!==fromSel.value&&(t==="book"||x.std!=="nft"))); if(alt!=="-1"){if(oi>=0)fromSel.value=alt;else toSel.value=alt} } const rcMine=rc.value!==""&&rc.value!==lkWrote.rc; const wantLq=q.get("lq")==="1"; const linkWantsCard=fi>=0||oi>=0||to||n||!isNaN(lk)||q.get("token")||q.get("out"); if(!wantLq&&lqMode&&linkWantsCard)lqSet(false); if(linkWantsCard){if(lnMode)lnSet(false);if(wnMode)wnSet(false);if(pvMode)pvSet(false)} setTab(t); if(wantLq&&t==="swap"&&!lqMode)lqSet(true); if(to&&!rcMine)lkKeep(rc,to); if(!isNaN(lk)){const os=[...dly.options].map(x=>+x.value).sort((a,b)=>a-b); const v=String(os.find(o=>o>=lk)??os[os.length-1]); if(t==="book")bookD=v;else if(t==="send")sendD=v; if(t!=="swap")lkKeep(dly,v)} if(n&&/^\d*\.?\d+$/.test(n)){ if(q.get("exactOut")==="1"&&q.get("out")){if(lkKeep(outAmt,n)){setMode("out");fitFont(outAmt)}} else{if(lkKeep(amt,n)){setMode("in");fitFont(amt)}} } refreshBala