0x42dcd51e…043f·#25,775,366·view on Etherscan
{await this.subscribe();for await(const A of this.client.fetch(this.topic))await this.#i(A.message)}async close(A){if(this.closing.aborted)return;await this.unsubscribe();const t=new CloseEvent("close",{reason:A});this.dispatchEvent(t),this.#A.abort(A)}}var fn;class Ce extends U{#A=fn;name=this.#A.name;constructor(){super(6e3,"User disconnected")}}fn=Ce;class Re extends EventTarget{channel;constructor(A){super(),this.channel=A,A.addEventListener("request",this.#n.bind(this),{signal:this.closing}),A.addEventListener("close",this.#A.bind(this),{signal:this.closing})}addEventListener(A,t,n){super.addEventListener(A,t,n)}get closing(){return this.channel.closing}#A(A){const{reason:t}=A,n=new CloseEvent("close",{reason:t});this.dispatchEvent(n)}#n(A){const t=A.data;if(t.method==="wc_sessionPing")return this.#e(A);if(t.method==="wc_sessionSettle")return this.#t(A);if(t.method==="wc_sessionExtend")return this.#r(A);if(t.method==="wc_sessionEvent")return this.#o(A);if(t.method==="wc_sessionUpdate")return this.#g(A);if(t.method==="wc_sessionRequest")return this.#i(A);if(t.method==="wc_sessionDelete")return this.#s(A)}#e(A){const t=new Event("ping");this.dispatchEvent(t),A.respondWith(!0)}#t(A){const t=A.data,n=new BA("settle",{data:t.params});this.dispatchEvent(n),A.respondWith(!0)}#r(A){const t=A.data,n=new BA("extend",{data:t.params});this.dispatchEvent(n),A.respondWith(!0)}#o(A){const t=A.data,n=new BA("event",{data:t.params});this.dispatchEvent(n),A.respondWith(!0)}#g(A){const t=A.data,n=new BA("update",{data:t.params});this.dispatchEvent(n),A.respondWith(!0)}#i(A){const t=A.data,n=new ft("request",{data:t.params});this.dispatchEvent(n),A.waitUntil(n.extension),n.response!=null&&A.respondWith(n.response)}#s(A){const t=A.data,n=new BA("delete",{data:t.params});this.dispatchEvent(n),A.waitUntil(this.close()),A.respondWith(!0)}async open(){await this.channel.open()}async close(A){await this.channel.close(A)}async ping(A=new AbortController().signal){await this.channel.request({method:"wc_sessionPing",params:{}},A).then(t=>t.getOrThrow())}async settle(A,t=new AbortController().signal){await this.channel.request({method:"wc_sessionSettle",params:A},t).then(n=>n.getOrThrow())}async extend(A,t=new AbortController().signal){await this.channel.request({method:"wc_sessionExtend",params:A},t).then(n=>n.getOrThrow())}async event(A,t=new AbortController().signal){await this.channel.request({method:"wc_sessionEvent",params:A},t).then(n=>n.getOrThrow())}async update(A,t=new AbortController().signal){await this.channel.request({method:"wc_sessionUpdate",params:A},t).then(n=>n.getOrThrow())}async request(A,t=new AbortController().signal){return await this.channel.request({method:"wc_sessionRequest",params:A},t).then(n=>n.getOrThrow())}async delete(A=new Ce){await this.channel.publish({method:"wc_sessionDelete",params:A})}}var Zt;(function(r){function A(n){const{protocol:o,version:g,pairingTopic:I,relayProtocol:a,symKey:c}=n,u=new URL(`${o}${I}@${g}`);return u.searchParams.set("relay-protocol",a),u.searchParams.set("symKey",c.toHex()),u.toString()}r.stringify=A;function t(n){const{protocol:o,pathname:g,searchParams:I}=new URL(n);if(o!=="wc:")throw new Error("Unknown protocol");const[a,c]=g.split("@");if(c!=="2")throw new Error("Unknown version");const u=at.wrap(I.get("relay-protocol")).getOrThrow();if(u!=="irn")throw new Error("Unknown relay protocol");const E=at.wrap(I.get("symKey")).getOrThrow(),l=Uint8Array.fromHex(E);return{protocol:o,pairingTopic:a,version:c,relayProtocol:u,symKey:l}}r.parse=t})(Zt||(Zt={}));class ct extends EventTarget{channel;keypair;params;constructor(A,t,n){super(),this.channel=A,this.keypair=t,this.params=n,A.addEventListener("close",this.#A.bind(this),{signal:this.closing}),A.addEventListener("request",this.#n.bind(this),{signal:this.closing})}static async generate(A){const t=crypto.getRandomValues(new Uint8Array(32)),n=new Uint8Array(await crypto.subtle.digest("SHA-256",t)).toHex(),o=new ZA(A,n,t),g=await crypto.subtle.generateKey("X25519",!1,["deriveBits"]);return new ct(o,g,{protocol:"wc:",version:"2",relayProtocol:"irn",pairingTopic:n,symKey:t})}static async from(A,t){const{pairingTopic:n,symKey:o}=t,g=new ZA(A,n,o),I=await crypto.subtle.generateKey("X25519",!1,["deriveBits"]);return new ct(g,I,t)}addEventListener(A,t,n){super.addEventListener(A,t,n)}get closing(){return this.channel.closing}#A(A){const{reason:t}=A,n=new CloseEvent("close",{reason:t});this.dispatchEvent(n)}#n(A){const t=A.data;if(t.method==="wc_sessionPropose")return this.#e(A);if(t.method==="wc_pairingPing")return this.#t(A);if(t.method==="wc_pairingDelete")return this.#r(A)}#e(A){const t=A.data,n=new ft("propose",{data:t.params});this.dispatchEvent(n),A.waitUntil(n.extension),n.response!=null&&A.respondWith(n.response)}#t(A){const t=new Event("ping");this.dispatchEvent(t),A.respondWith(!0)}#r(A){const t=A.data,n=new BA("delete",{data:t.params});this.dispatchEvent(n),A.waitUntil(this.close()),A.respondWith(!0)}get url(){return Zt.stringify(this.params)}async open(){await this.channel.open()}async close(A){await this.channel.close(A)}async propose(A){const{self:t,requiredNamespaces:n={},optionalNamespaces:o={}}=A,a={publicKey:new Uint8Array(await crypto.subtle.exportKey("raw",this.keypair.publicKey)).toHex(),metadata:t},c=[this.channel.client.relay],u=await this.channel.request({method:"wc_sessionPropose",params:{proposer:a,relays:c,requiredNamespaces:n,optionalNamespaces:o}}).then(F=>F.getOrThrow()),E=Uint8Array.fromHex(u.responderPublicKey),l=await crypto.subtle.importKey("raw",E,"X25519",!1,[]),f=new Uint8Array(await crypto.subtle.deriveBits({name:"X25519",public:l},this.keypair.privateKey,256)),w=await crypto.subtle.importKey("raw",f,"HKDF",!1,["deriveBits"]),d={name:"HKDF",hash:"SHA-256",info:new Uint8Array,salt:new Uint8Array},y=new Uint8Array(await crypto.subtle.deriveBits(d,w,8*32)),J=new Uint8Array(await crypto.subtle.digest("SHA-256",y)).toHex(),D=new Re(new ZA(this.channel.client,J,y));this.dispatchEvent(new BA("upgrade",{data:D}))}async respond(A){const{relay:t}=this.channel.client,o=new Uint8Array(await crypto.subtle.exportKey("raw",this.keypair.publicKey)).toHex(),g=Uint8Array.fromHex(A.proposer.publicKey),I=await crypto.subtle.importKey("raw",g,"X25519",!1,[]),a=new Uint8Array(await crypto.subtle.deriveBits({name:"X25519",public:I},this.keypair.privateKey,256)),c=await crypto.subtle.importKey("raw",a,"HKDF",!1,["deriveBits"]),u={name:"HKDF",hash:"SHA-256",info:new Uint8Array,salt:new Uint8Array},E=new Uint8Array(await crypto.subtle.deriveBits(u,c,8*32)),l=new Uint8Array(await crypto.subtle.digest("SHA-256",E)).toHex(),f=new Re(new ZA(this.channel.client,l,E));return this.dispatchEvent(new BA("upgrade",{data:f})),{relay:t,responderPublicKey:o}}async ping(A=new AbortController().signal){await this.channel.request({method:"wc_pairingPing",params:{}},A).then(t=>t.getOrThrow())}async extend(A,t=new AbortController().signal){await this.channel.request({method:"wc_pairingExtend",params:{expiry:A}},t).then(n=>n.getOrThrow())}async delete(A=new Ce){await this.channel.publish({method:"wc_pairingDelete",params:A})}}var zt;(function(r){r.RELAY="wss://relay.walletconnect.org"})(zt||(zt={}));const ei="c6c9bacd35afa3eb9e6cccf6d8464395",ni={name:"svZCHF Chalet",description:"Frankencoin Savings Vault (svZCHF) — deposit ZCHF, earn the Swiss rate",url:typeof location<"u"?location.origin:"https://localhost",icons:[]};function ri(r){const n=r?.eip155?.accounts?.[0];if(!n)return null;const o=n.split(":");return o.length<3?null:{chainId:Number(o[1]),address:o[2]}}class Qe{#A;#n;#e;#t;projectId;constructor(A=ei){this.projectId=A}get state(){return this.#t}get connected(){return this.#t!=null&&this.#e!=null}async connect(A,t=[1]){const n=crypto.getRandomValues(new Uint8Array(32)),o=await ae.open(zt.RELAY,n,this.projectId);this.#A=o;const g=await ct.generate(o);this.#n=g,A.onUri(g.url);const I=new Promise((c,u)=>{g.addEventListener("upgrade",E=>{const l=E.data;this.#e=l,l.addEventListener("settle",f=>{const w=f.data,d=ri(w.namespaces);if(!d){u(new Error("Wallet approved but returned no eip155 account"));return}this.#t=d,A.onConnected(d),c(d)}),l.addEventListener("event",f=>{const{event:w,chainId:d}=f.data;if(w.name==="chainChanged"){const y=Number(w.data??d);this.#t&&(this.#t={...this.#t,chainId:y}),A.onChainChanged?.(y)}if(w.name==="accountsChanged"){const J=w.data?.[0];J&&this.#t&&(this.#t={...this.#t,address:J},A.onAccountsChanged?.(J))}}),l.addEventListener("close",()=>A.onDisconnected("session closed")),l.addEventListener("delete",f=>A.onDisconnected(f.data?.message??"session deleted")),l.open().catch(u)})}),a=c=>`eip155:${c}`;return g.propose({self:ni,optionalNamespaces:{eip155:{chains:t.map(a),methods:["eth_sendTransaction","eth_signTransaction","eth_call","personal_sign","eth_accounts","eth_chainId","wallet_switchEthereumChain","wallet_sendCalls","wallet_getCapabilities","wallet_getCallsStatus"],events:["chainChanged","accountsChanged"]}}}).catch(c=>{A.onDisconnected(c?.message??"pairing failed")}),await g.open(),I}async request(A,t,n){if(!this.#e||!this.#t)throw new Error("Wallet not connected");const o=n??this.#t.chainId;return this.#e.request({chainId:`eip155:${o}`,request:{method:A,params:t}})}async sendTransaction(A){return this.request("eth_sendTransaction",[A])}async disconnect(){try{await this.#e?.close("user disconnected")}catch{}try{this.#A?.close("user disconnected")}catch{}this.#e=void 0,this.#n=void 0,this.#A=void 0,this.#t=void 0}}function dn(){return typeof globalThis.ethereum<"u"}class pn{#A;#n="";#e=0;constructor(A){const t=A??globalThis.ethereum;if(!t)throw new Error("No injected wallet found (window.ethereum is undefined).");this.#A=t}async connect(A){const t=await this.#A.request({method:"eth_requestAccounts"});if(!t?.length)throw new Error("Wallet returned no accounts.");this.#n=t[0];const n=await this.#A.request({method:"eth_chainId"});return this.#e=parseInt(n,16),this.#A.on?.("accountsChanged",o=>{if(!o?.length)return A.onDisconnected?.();this.#n=o[0],A.onAccountsChanged?.(o[0])}),this.#A.on?.("chainChanged",o=>{this.#e=parseInt(o,16),A.onChainChanged?.(this.#e)}),{address:this.#n,chainId:this.#e}}get state(){return{address:this.#n,chainId:this.#e}}async request(A,t){return this.#A.request({method:A,params:t})}async sendTransaction(A){return this.#A.request({method:"eth_sendTransaction",params:[{from:A.from??this.#n,to:A.to,data:A.data,value:A.value,gas:A.gas}]})}async switchToMainnet(){await this.#A.request({method:"wallet_switchEthereumChain",params:[{chainId:"0x1"}]})}}const yn=["https://ethereum.publicnode.com","https://eth.llamarpc.com","https://rpc.mevblocker.io","https://cloudflare-eth.com"];let $t=null;function Ee(r){$t=r}async function Dn(r,A,t){const n=await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:A,params:t})});if(!n.ok)throw new Error(`rpc http ${n.status}`);const o=await n.json();if(o.error)throw new Error(o.error.message??"rpc error");return o.result}async function aA(r,A){if($t)try{return await $t(r,A)}catch{}let t;for(const n of yn)try{return await Dn(n,"eth_call",[{to:r,data:A},"latest"])}catch(o){t=o}throw t instanceof Error?t:new Error("All RPC endpoints failed")}async function ii(r,A=12e4){const t=Date.now()+A;for(;;){let n=null;for(const o of yn)try{n=await Dn(o,"eth_getTransactionReceipt",[r]);break}catch{}if(n){if(n.status!=="0x1")throw new Error(`Transaction reverted: ${r}`);return}if(Date.now()>t)throw new Error(`Timed out waiting for ${r}`);await new Promise(o=>setTimeout(o,2500))}}const AA={convertToAssets:"0x07a2d13a",convertToShares:"0xc6e6f592",totalAssets:"0x01e1d114",totalSupply:"0x18160ddd",balanceOf:"0x70a08231",allowance:"0xdd62ed3e",approve:"0x095ea7b3",deposit:"0x6e553f65",savings:"0xc86d6ae4",currentRatePPM:"0x06a7b376"};function Ct(r){return r.toString(16).padStart(64,"0")}function GA(r){return r.toLowerCase().replace(/^0x/,"").padStart(64,"0")}function DA(r,...A){return r+A.join("")}function QA(r){return BigInt(r)}function oi(r){return"0x"+r.slice(-40)}function tA(r){const A=r<0n,t=(A?-r:r).toString().padStart(19,"0"),n=t.slice(0,-18),o=t.slice(-18).replace(/0+$/,"");return(A?"-":"")+n+(o?"."+o:"")}function Nn(r){const A=r.match(/^(\d+)(?:\.(\d{1,18}))?$/);if(!A)throw new Error(`bad decimal: ${r}`);const t=(A[2]??"").padEnd(18,"0");return BigInt(A[1]+t)}const jA=1,eA="0xe5f130253ff137f9917c0107659a4c5262abf6b0",Qt="0xB58E61C3098d85632Df34EecfB899A1Ed80921cB",gi="0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",si=10n**18n;async function ai(r){const[A,t,n]=await Promise.all([aA(eA,DA(AA.convertToAssets,Ct(si))).then(QA),aA(eA,AA.totalAssets).then(QA),aA(eA,AA.totalSupply).then(QA)]);let o=gi;try{o=oi(await aA(eA,AA.savings))}catch{}let g=0;try{g=Number(QA(await aA(o,AA.currentRatePPM)))}catch{}let I=0n,a=0n,c=0n;r&&([I,a,c]=await Promise.all([aA(Qt,DA(AA.balanceOf,GA(r))).then(QA),aA(eA,DA(AA.balanceOf,GA(r))).then(QA),aA(Qt,DA(AA.allowance,GA(r),GA(eA))).then(QA)]));const u=Number(tA(A)),E=Number(tA(a));return{sharePrice:u,totalAssets:Number(tA(t)),totalSupply:Number(tA(n)),savingsModule:o,ratePPM:g,zchfBalance:Number(tA(I)),zchfBalanceRaw:I,svBalance:E,svBalanceRaw:a,svValue:E*u,allowance:Number(tA(c)),allowanceRaw:c}}async function Ii(r){if(!isFinite(r)||r<=0)return 0;const A=QA(await aA(eA,DA(AA.convertToShares,Ct(Nn(String(r))))));return Number(tA(A))}const b=r=>document.getElementById(r),p={connectBtn:b("btn-connect"),disconnectBtn:b("btn-disconnect"),walletPill:b("wallet-pill"),connectPanel:b("connect-panel"),connectWc:b("btn-connect-wc"),connectInjected:b("btn-connect-injected"),connectCancel:b("btn-connect-cancel"),wcUriArea:b("wc-uri-area"),wcUri:b("wc-uri"),wcQr:b("wc-qr"),copyUri:b("btn-copy-uri"),wrongChain:b("wrong-chain"),switchChain:b("btn-switch-chain"),statPrice:b("stat-price"),statRate:b("stat-rate"),statTvl:b("stat-tvl"),userBalance:b("user-balance"),depAmount:b("dep-amount"),depMax:b("dep-max"),depPreview:b("dep-preview"),saveBtn:b("btn-save"),saveStatus:b("save-status"),log:b("log")};let j=null,pt=null,X=null,fA=0,T=null,tt=!1;const Le=new Intl.NumberFormat("de-CH",{maximumFractionDigits:2}),Ae=new Intl.NumberFormat("de-CH",{maximumFractionDigits:4});function yt(r){return r.length>12?`${r.slice(0,6)}…${r.slice(-4)}`:r}function O(r,A){p.log.classList.remove("hidden");const t=document.createElement("li");A&&(t.className=A),t.textContent=r,p.log.prepend(t)}function mn(r,A){p.log.classList.remove("hidden");const t=document.createElement("li");t.innerHTML=`${r}: <a href="https://etherscan.io/tx/${A}" target="_blank" rel="noreferrer">${yt(A)}</a>`,p.log.prepend(t)}function oA(r){p.saveStatus.textContent=r}const et="";function he(){const r=X!=null;p.connectBtn.classList.toggle("hidden",r),p.disconnectBtn.classList.toggle("hidden",!r),p.walletPill.classList.toggle("hidden",!r),r&&(p.walletPill.textContent=`${yt(X)} · ${pt==="latrine"?"WC":"browser"}`),p.wrongChain.classList.toggle("hidden",!r||fA===jA)}function Fn(){T&&(p.statPrice.textContent=`CHF ${Ae.format(T.sharePrice)}`,p.statTvl.textContent=`CHF ${Le.format(T.totalAssets)}`,p.statRate.textContent=T.ratePPM>0?`${(T.ratePPM/1e4).toFixed(2)}% p.a.`:"—",X?(p.userBalance.textContent=`Balance: ZCHF ${Le.format(T.zchfBalance)} · ${Ae.format(T.svBalance)} svZCHF`,p.userBalance.title=`${tA(T.zchfBalanceRaw)} ZCHF (exact)`):(p.userBalance.textContent="Connect a wallet",p.userBalance.title=""))}function NA(){const r=le(p.depAmount),A=!tt&&!!(j&&X&&fA===jA&&T&&r&&r.wei<=T.zchfBalanceRaw);p.saveBtn.disabled=!A,T&&r&&r.wei<=T.allowanceRaw?p.saveBtn.textContent="Deposit":p.saveBtn.textContent="Approve & Deposit"}function OA(){he(),Fn(),NA()}async function nA(){try{T=await ai(X??void 0),Fn(),NA()}catch(r){O(`Chain read failed: ${r.message}`,"err")}}async function Bi(){p.statPrice.textContent="loading…",await nA()}async function ci(){p.wcUriArea.classList.remove("hidden");const r=new Qe;try{await r.connect({onUri:A=>{p.wcUri.value=A,vA.toCanvas(p.wcQr,A,{width:176,margin:1},()=>{})},onConnected:A=>{j=r,pt="latrine",X=A.address,fA=A.chainId,Ee((t,n)=>r.request("eth_call",[{to:t,data:n},"latest"])),p.connectPanel.classList.add("hidden"),O(`Connected ${yt(A.address)} via WalletConnect`,"ok"),nA(),OA()},onDisconnected:A=>{X&&O(`Wallet disconnected (${A??"?"})`,"err"),ue()},onChainChanged:A=>{fA=A,he(),NA(),A===jA&&nA()},onAccountsChanged:A=>{X=A,nA(),OA()}})}catch(A){O(`WalletConnect failed: ${A.message}`,"err"),p.wcUriArea.classList.add("hidden")}}async function Ci(){if(!dn()){O("No browser wallet found (window.ethereum missing)","err");return}const r=new pn;try{const A=await r.connect({onAccountsChanged:t=>{X=t,nA(),OA()},onChainChanged:t=>{fA=t,he(),NA(),t===jA&&nA()},onDisconnected:()=>ue()});j=r,pt="injected",X=A.address,fA=A.chainId,Ee((t,n)=>r.request("eth_call",[{to:t,data:n},"latest"])),p.connectPanel.classList.add("hidden"),O(`Connected ${yt(A.address)} via browser wallet`,"ok"),nA(),OA()}catch(A){O(`Browser wallet failed: ${A.message}`,"err")}}function ue(){Ee(null),j=null,pt=null,X=null,fA=0,nA(),OA()}function kn(){if(!j||!X)throw new Error("Connect a wallet first");if(fA!==jA)throw new Error("Switch to Ethereum mainnet first");return X}function le(r){const A=r.value.trim();if(!/^\d+(\.\d{1,18})?$/.test(A))return null;const t=Number(A);return!isFinite(t)||t<=0?null:{value:t,wei:Nn(A)}}async function Gn(r,A){if(!j)throw new Error("Wallet not connected");return j instanceof Qe,j.request(r,A)}function we(r){const t=JSON.stringify(r,Object.getOwnPropertyNames(r)).match(/e450d38c[0-9a-f]{24}([0-9a-f]{40})[0-9a-f]*?([0-9a-f]{64})([0-9a-f]{64})/i);if(t){const n=tA(BigInt("0x"+t[2])),o=tA(BigInt("0x"+t[3]));return`insufficient token balance (has ${n}, needs ${o} — ERC-4626 rounding leaves you a wei short; use MAX)`}return r.message??String(r)}async function Lt(r,A,t){try{const n=kn();O(`${r}: sending…`);const o=await j.sendTransaction({from:n,to:A,data:t});return mn(r,o),O(`${r}: waiting for confirmation…`),await ii(o),O(`${r}: confirmed ✔`,"ok"),await nA(),!0}catch(n){return O(`${r} failed: ${we(n)}`,"err"),!1}}async function Qi(r){const A=Date.now()+12e4;for(;;){const t=await Gn("wallet_getCallsStatus",[r]),n=t?.status,o=t?.receipts?.[0]?.transactionHash;if(o&&mn("Batched approve + deposit",o),n===200||n==="200"||String(n).toUpperCase()==="CONFIRMED")return;if(typeof n=="number"&&n>=400||["REVERTED","FAILED","REJECTED"].includes(String(n).toUpperCase()))throw new Error(`batch failed on-chain (status ${n})`);if(Date.now()>A)throw new Error("batch still pending after 2 minutes — check your wallet");await new Promise(g=>setTimeout(g,2e3))}}async function Ei(r){const A=kn(),t=DA(AA.approve,GA(eA),Ct(r)),n=DA(AA.deposit,Ct(r),GA(A));if(T&&r<=T.allowanceRaw){oA("Allowance already covers this — depositing directly…"),await Lt("Deposit",eA,n),oA(et);return}try{oA("Trying batched approve + deposit (EIP-5792)…");const I=await Gn("wallet_sendCalls",[{version:"1.0",chainId:"0x1",from:A,calls:[{to:Qt,data:t},{to:eA,data:n}]}]);O("Batched approve + deposit submitted — waiting for confirmation…"),oA("Batch submitted — waiting for confirmation…"),await Qi(String(I)),O("Approve + deposit confirmed in one transaction ✔","ok"),oA("Done — approve + deposit confirmed in one transaction ✔"),await nA();return}catch(I){O(`Batched calls unavailable (${we(I)}) — falling back to two transactions`,"err")}if(oA("Step 1 of 2: approving ZCHF…"),!await Lt("Approve ZCHF",Qt,t)){oA(et);return}oA("Step 2 of 2: depositing…");const g=await Lt("Deposit",eA,n);oA(g?"Done — deposit confirmed ✔":et)}p.connectBtn.addEventListener("click",()=>p.connectPanel.classList.remove("hidden"));p.connectCancel.addEventListener("click",()=>p.connectPanel.classList.add("hidden"));p.connectWc.addEventListener("click",()=>void ci());p.connectInjected.addEventListener("click",()=>void Ci());p.disconnectBtn.addEventListener("click",async()=>{j instanceof Qe&&await j.disconnect(),ue(),O("Disconnected")});p.copyUri.addEventListener("click",async()=>{await navigator.clipboard.writeText(p.wcUri.value),p.copyUri.textContent="Copied",setTimeout(()=>p.copyUri.textContent="Copy",1200)});p.switchChain.addEventListener("click",async()=>{if(j instanceof pn)try{await j.switchToMainnet()}catch(r){O(`Chain switch failed: ${r.message}`,"err")}else O("Switch to Ethereum mainnet inside your wallet app","err")});let qe;async function Un(){const r=le(p.depAmount);if(!r){p.depPreview.textContent="You receive ≈ — svZCHF";return}try{const A=await Ii(r.value);p.depPreview.textContent=`You receive ≈ ${Ae.format(A)} svZCHF at the current share price`}catch{p.depPreview.textContent="Preview unavailable (RPC unreachable)"}}p.depAmount.addEventListener("input",()=>{NA(),clearTimeout(qe),qe=window.setTimeout(()=>void Un(),300)});p.depMax.addEventListener("click",()=>{T&&(p.depAmount.value=tA(T.zchfBalanceRaw),p.depAmount.dispatchEvent(new Event("input")))});p.saveBtn.addEventListener("click",async()=>{const r=le(p.depAmount);if(!(!r||tt)){tt=!0,NA();try{await Ei(r.wei),T&&p.depAmount.value&&(p.depAmount.value="",Un())}catch(A){O(`Deposit failed: ${we(A)}`,"err"),oA(et)}finally{tt=!1,NA()}}});dn()||(p.connectInjected.disabled=!0,p.connectInjected.title="No window.ethereum provider found");Bi();setInterval(()=>void nA(),3e4);
</script>
<style>
:root{--red: #ff0000;--ink: #000;--muted: #666;--line: #ddd}*{box-sizing:border-box}body{margin:0;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;background:#fff;color:var(--ink);line-height:1.5}main{max-width:560px;margin:0 auto;padding:64px 20px 96px}header{display:flex;justify-content:space-between;align-items:center;padding:14px 20px;border-bottom:1px solid var(--ink)}.wordmark{display:flex;align-items:center;gap:9px;font-weight:700;font-size:18px;letter-spacing:-.3px}.cross{width:20px;height:20px;background:var(--red);display:inline-block;position:relative;flex:none}.cross:after{content:"";position:absolute;inset:0;background:linear-gradient(#fff,#fff) center/11px 3.5px no-repeat,linear-gradient(#fff,#fff) center/3.5px 11px no-repeat}.cross.small{width:14px;height:14px}.cross.small:after{background:linear-gradient(#fff,#fff) center/8px 2.5px no-repeat,linear-gradient(#fff,#fff) center/2.5px 8px no-repeat}.wallet-area{display:flex;align-items:center;gap:14px}.pill{font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:12px;border:1px solid var(--ink);padding:3px 10px}.btn{font:inherit;font-weight:600;border:1px solid var(--ink);background:#fff;color:var(--ink);padding:7px 14px;border-radius:0;cursor:pointer}.btn:hover:not(:disabled){background:var(--ink);color:#fff}.btn:disabled{opacity:.3;cursor:not-allowed}.btn-red{background:var(--red);border-color:var(--red);color:#fff}.btn-red:hover:not(:disabled){background:#c00;border-color:#c00;color:#fff}.btn-ghost{border-color:var(--line)}.btn-big{width:100%;padding:14px;font-size:17px}.linklike{font:inherit;border:none;background:none;padding:0;color:var(--red);cursor:pointer;text-decoration:underline}.connect-panel{position:fixed;inset:0;background:#ffffffeb;display:flex;align-items:center;justify-content:center;z-index:20}.connect-box{background:#fff;border:1px solid var(--ink);padding:32px;width:min(400px,calc(100vw - 40px));text-align:center}.connect-box h2{margin:0 0 20px}.connect-options{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}.connect-box>.linklike{margin-top:16px}.wc-uri-area{margin-top:20px}.wc-uri-area canvas{border:1px solid var(--ink)}.wc-uri-row{display:flex;gap:8px;margin-top:8px}.wc-uri-row input{flex:1;font-family:ui-monospace,Menlo,monospace;font-size:11px;padding:7px;border:1px solid var(--line);border-radius:0;min-width:0}.waiting{color:var(--red);font-weight:600;font-size:13px}.banner{background:var(--red);color:#fff;padding:10px 20px;text-align:center;font-weight:600;font-size:14px}.banner .linklike{color:#fff;margin-left:8px}h1{font-size:44px;line-height:1.05;letter-