site/js/bns-register.js
Silent Mode 1862e2c411 feat(portal): the name's settings show what its subdomains serve, and let you change it
The per-name tab was a DNS record table: eight record types, of which the
stack reads exactly one, and then only as a last resort when a name carries
no content record. Everything else was signed, stored and read by nobody —
furniture that looked like configuration. Meanwhile the thing a name owner
actually has, a folder tree that already answers on matching subdomains, was
not visible anywhere and could not be changed.

The tab now leads with what answers today: the apex, every folder in the
name's storage next to the subdomain it serves on, and which of those a rule
overrides. Below it, the rules — point a subdomain at a different folder,
redirect it, or switch it off.

Classic DNS keeps its table, behind a disclosure that says plainly what
those records do today and what they are waiting for. Nobody loses a record
they published; they just stop being the first thing a name owner is asked
to think about. The table gains a Host column, so records can belong to a
subdomain rather than only the apex.

Both halves are one signed manifest and one publish button — they always
were one file, and two buttons for it only ever invited a half-saved state.
Labels and values are separated in the generated rows so the words
translate and the owner's own folder and URL do not.

The signer accepted v1 manifests only, which would have rejected every
publish from this screen.
2026-09-28 01:21:47 +02:00

7 lines
60 KiB
JavaScript

import{generateBip39Mnemonic as Bn,deriveSeedFromBip39Mnemonic as Ae,deriveHdPrivateNodeFromSeed as In,deriveHdPath as Pn,secp256k1 as Be,hash160 as Nn,encodeCashAddress as ss,lockingBytecodeToCashAddress as Rn,cashAddressToLockingBytecode as rs,binToHex as Ln,hexToBin as is,utf8ToBin as Ne,binToBase64 as Yt,base64ToBin as Vt}from"@bitauth/libauth";var kt={chipnet:{id:"chipnet",label:"chipnet",prefix:"bchtest",beacon:"bchtest:qp8njaa9a3ahg7259s5qajnce526n0rttsq8qwx4jl",beaconScripthash:"e1cdbba719436f49acb4bf245b44df875c6d6b405eda46a9d3e736d138102f3b",tldBeacon:"bchtest:qzc4c76vtw9nd49g6x8nmvc0jz62uvk4dc7hmpmerh",tldBeaconScripthash:"c85db10e106606273422b2733b2a6fb8b35a4d0e7dbfb20cf59bdb0833c008b8",electrum:[{url:"wss://silentmode.st/electrum",ip:"195.184.247.106"},{url:"wss://coinspectrum.duckdns.org:50011",ip:"195.184.247.106"},{url:"wss://chipnet.bch.ninja:50004",ip:"135.148.236.244"},{url:"wss://chipnet.imaginary.cash:50004",ip:"66.29.152.199"},{url:"wss://tbch4.loping.net:62002",ip:"183.89.202.207"}],beaconOnly:/silentmode\.st\/electrum|coinspectrum\.duckdns\.org:50011/,electrumListName:"electrum.bch",rootTldName:"tlds.bch",bootstrapTlds:["bch"],startHeight:2e5,hostingBucket:"bns",nameListUrl:"https://s3.silentmode.st:8600/bns/name-list.json",cdnIndexUrl:"https://dl.silentmode.st/bns-name-index.json",nostrTags:{names:"bns-name-list",tlds:"bns-tld-list"},explorerTx:"https://chipnet.imaginary.cash/tx/",faucets:[{name:"tbch.googol.cash",url:"https://tbch.googol.cash/"},{name:"chipnet.bch.ninja faucet",url:"https://chipnet.bch.ninja/faucet"}],operatorAddress:"bchtest:qzew3dqcsj0guwe5y3uxf9q2xs5ajgy9lca4z093cu",accountPath:"m/44'/145'/0'",bchnRpcPort:48332},mainnet:{id:"mainnet",label:"mainnet",prefix:"bitcoincash",beacon:null,beaconScripthash:null,tldBeacon:null,tldBeaconScripthash:null,electrum:[{url:"wss://bch.imaginary.cash:50004",ip:"67.223.119.97"},{url:"wss://electrum.imaginary.cash:50004",ip:"15.204.113.162"},{url:"wss://electroncash.dk:50004",ip:"87.63.200.138"},{url:"wss://bch.loping.net:50004",ip:"183.89.202.207"},{url:"wss://bch.soul-dev.com:50004",ip:"174.141.196.204"},{url:"wss://cashnode.bch.ninja:50004",ip:"135.148.236.246"}],beaconOnly:/(?!)/,electrumListName:"electrum.bch",rootTldName:"tlds.bch",bootstrapTlds:["bch"],startHeight:null,hostingBucket:"bns-mainnet",nameListUrl:"https://s3.silentmode.st:8600/bns-mainnet/name-list.json",cdnIndexUrl:"https://dl.silentmode.st/bns-mainnet-name-index.json",nostrTags:{names:"bns-mainnet-name-list",tlds:"bns-mainnet-tld-list"},explorerTx:"https://blockchair.com/bitcoin-cash/transaction/",faucets:[],operatorAddress:null,accountPath:"m/44'/145'/0'",bchnRpcPort:8332}},Se="chipnet";function gn(){let t=typeof globalThis<"u"?globalThis.BNS_NETWORK:null,e=typeof process<"u"&&process.env?process.env.BNS_NETWORK:null;return String(t||e||Se).trim().toLowerCase()}function Pt(t){if(t&&typeof t=="object")return t;let e=t||gn(),n=kt[e];if(!n)throw new Error(`unknown network "${e}" (known: ${Object.keys(kt).join(", ")})`);return n}var T=Pt();function zt(t=T){let e=Pt(t);if(!e.beaconScripthash||!e.tldBeaconScripthash)throw new Error(`${e.label}: beacon addresses are not pinned yet (see ROADMAP-MAINNET.md \xA76)`);return e}var jo=T.beacon,Yo=T.beaconScripthash,Vo=T.tldBeacon,Xo=T.tldBeaconScripthash,Jo=T.electrum,Qo=kt.chipnet.electrum,Zo=T.electrumListName,ke="BNS1";var Te="bch",mn=/^[a-z0-9-]{1,32}$/,Ee=/^[a-z0-9-]{1,16}$/,yn=/^[a-z0-9-]{1,32}(\.[a-z0-9-]{1,16})?$/;function wn(t){return t.includes(".")?t:t+"."+Te}var xn=t=>{let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e},qt=t=>[...new TextEncoder().encode(t)].map(e=>e.toString(16).padStart(2,"0")).join("");function kn(t){let n=String(t).toLowerCase().trim().replace(/^[a-z]+:\/\//,"").split("/")[0].replace(/\.$/,"").split(".").filter(Boolean);if(n.length===0)throw new Error(`invalid name "${t}"`);let o,s;if(n.length===1?(o=n[0],s=Te):(s=n[n.length-1],o=n[n.length-2]),!mn.test(o)||!Ee.test(s))throw new Error(`invalid name "${t}" (allowed: <label>.<tld>, [a-z0-9-])`);return`${o}.${s}`}var It=class{constructor(e,n,o){this.url=e,this.WS=n||globalThis.WebSocket,this.options=o,this.id=0,this.pending=new Map,this.buf=""}connect(){return new Promise((e,n)=>{let o=this.options?new this.WS(this.url,this.options):new this.WS(this.url);this.ws=o;let s=async()=>{try{await this.call("server.version",["bns-web","1.4.2"]),e(this)}catch(i){n(i)}},r=i=>n(new Error("electrum ws error: "+(i?.message||this.url))),a=i=>this._onData(typeof i.data=="string"?i.data:i.data.toString());o.addEventListener?(o.addEventListener("open",s),o.addEventListener("error",r),o.addEventListener("message",a)):(o.onopen=s,o.onerror=r,o.onmessage=a)})}_handle(e){let n=this.pending.get(e.id);n&&(this.pending.delete(e.id),e.error?n.reject(new Error(JSON.stringify(e.error))):n.resolve(e.result))}_onData(e){this.buf+=e;let n;for(;(n=this.buf.indexOf(`
`))>=0;){let s=this.buf.slice(0,n).trim();if(this.buf=this.buf.slice(n+1),s)try{this._handle(JSON.parse(s))}catch{}}let o=this.buf.trim();if(o)try{let s=JSON.parse(o);this._handle(s),this.buf=""}catch{}}call(e,n=[]){let o=++this.id;return new Promise((s,r)=>{this.pending.set(o,{resolve:s,reject:r}),this.ws.send(JSON.stringify({id:o,method:e,params:n})+`
`),setTimeout(()=>{this.pending.has(o)&&(this.pending.delete(o),r(new Error(`electrum timeout: ${e}`)))},2e4)})}close(){try{this.ws.close()}catch{}}},bn=t=>typeof t=="string"?{url:t}:t;async function Sn(t,e,{directIP:n=!1}={}){let o;for(let s of t){let r=bn(s);try{return await new It(r.url,e).connect()}catch(a){o=a}if(n&&r.ip)try{let a=new URL(r.url),i=`${a.protocol}//${r.ip}:${a.port}`;return await new It(i,e,{servername:a.hostname}).connect()}catch(a){o=a}}throw o??new Error("no electrum server reachable")}function _e(t){if(!t||!t.startsWith("6a"))return null;let e=xn(t),n=1,o=[];for(;n<e.length;){let r=e[n++],a;if(r<=75)a=r;else if(r===76)a=e[n++];else if(r===77)a=e[n]|e[n+1]<<8,n+=2;else return null;o.push(e.slice(n,n+a)),n+=a}let s=new TextDecoder().decode(o[0]??new Uint8Array);if(!s.startsWith(ke))return null;try{let r=JSON.parse(s.slice(ke.length));if(Tn.has(r.o)&&typeof r.n=="string")return r}catch{}return null}var Tn=new Set(["REG","UPD","TREG","TUPD"]);function Oe(t,e){let n=t.height>0?t.height:1/0,o=e.height>0?e.height:1/0;return n-o||t.tx_hash.localeCompare(e.tx_hash)}function ve(t,e){let n=new Set(t.map(i=>i.tx_hash)),o=new Map(t.map(i=>{let l=new Set;for(let c of e.get(i.tx_hash)?.vin??[])c.txid&&c.txid!==i.tx_hash&&n.has(c.txid)&&l.add(c.txid);return[i.tx_hash,l]})),s=new Set,r=[],a=[...t];for(;a.length;){let i=a.findIndex(c=>[...o.get(c.tx_hash)].every(h=>s.has(h)));i<0&&(i=0);let[l]=a.splice(i,1);s.add(l.tx_hash),r.push(l)}return r}function Gt(t){let e=t.lastIndexOf(".");return e<0?t:t.slice(e+1)}function En(t,e,n){let o=n.get(t);return o?o.regHeight>0&&e>0?o.regHeight<=e:!0:!1}async function jt(t,e=T){let{tldBeaconScripthash:n}=zt(e),o=typeof t.unionHistory=="function"?(await t.unionHistory(n)).history:await t.call("blockchain.scripthash.get_history",[n]);o.sort(Oe);let s=new Map;for(let{tx_hash:a}of o)try{s.set(a,await t.call("blockchain.transaction.get",[a,!0]))}catch{}let r=new Map;for(let{tx_hash:a,height:i}of ve(o.filter(l=>s.has(l.tx_hash)),s)){let c=s.get(a).vout||[],h=null;for(let d of c)h=_e(d.scriptPubKey?.hex)??h;if(!h||typeof h.n!="string"||!Ee.test(h.n))continue;let u=h.n;if(h.o==="TREG"){if(r.has(u))continue;let d=qt(u),p=c.find(m=>m.tokenData?.nft&&m.tokenData.nft.commitment===d);if(!p)continue;r.set(u,{category:p.tokenData.category,regHeight:i,regTxid:a,mintScriptHex:p.scriptPubKey?.hex??null,records:h.r??{},updates:[{height:i,txid:a,records:h.r??{}}]})}else if(h.o==="TUPD"){let d=r.get(u);if(!d||!c.some(p=>p.tokenData&&p.tokenData.category===d.category))continue;d.records=h.r??{},d.updates.push({height:i,txid:a,records:d.records})}}return r}function _n(t,e){if(!t)return{};let n=t.updates||[];if(!n.length)return t.records||{};let o={};for(let s of n)e>0&&(s.height<=0||s.height>e)||(o=s.records||{});return o}function On(t,e){let n=_n(t,e);return n.policy==="cosign"||n.hidden===1||n.hidden===!0||n.hidden==="1"}function vn(t,e,n){let o=qt(n);return(t||[]).some(s=>s.tokenData&&s.tokenData.category===e.category&&s.tokenData.nft&&s.tokenData.nft.commitment===o)}function be(t){if(!t||!t.scriptPubKey)return null;let e=t.scriptPubKey;return typeof e.address=="string"?e.address:Array.isArray(e.addresses)&&e.addresses.length?e.addresses[0]:null}async function bt({network:t=T,electrum:e=Pt(t).electrum,WebSocket:n,client:o,directIP:s=!1,enforceTld:r=!1,cosignGate:a=!0}={}){let i=zt(t),l=o??await Sn(e,n,{directIP:s});try{let c=null;if(r||a)try{c=await jt(l,i)}catch(m){if(r)throw m;c=null}let h=null,u;if(typeof l.unionHistory=="function"){let m=await l.unionHistory(i.beaconScripthash);u=m.history,h={servers:m.servers,unreachable:m.unreachable,disagreements:m.disagreements}}else u=await l.call("blockchain.scripthash.get_history",[i.beaconScripthash]);u.sort(Oe);let d=new Map;for(let{tx_hash:m}of u)try{d.set(m,await l.call("blockchain.transaction.get",[m,!0]))}catch{}let p=new Map;for(let{tx_hash:m,height:f}of ve(u.filter(g=>d.has(g.tx_hash)),d)){let y=d.get(m).vout||[],w=null;for(let S of y)w=_e(S.scriptPubKey?.hex)??w;if(!w)continue;let x=w.n;if(!yn.test(x))continue;let _=wn(x);if(w.o==="REG"){if(p.has(_)||r&&!En(Gt(_),f,c))continue;if(a&&c){let O=c.get(Gt(_));if(O&&On(O,f)&&!vn(y,O,Gt(_)))continue}let S=qt(x),k=y.find(O=>O.tokenData?.nft&&O.tokenData.nft.commitment===S);if(!k)continue;p.set(_,{name:_,category:k.tokenData.category,records:w.r??{},txid:m,height:f,updatedTxid:null,owner:be(k)})}else if(w.o==="UPD"){let S=p.get(_);if(!S)continue;let k=y.find(O=>O.tokenData&&O.tokenData.category===S.category);if(!k)continue;S.records=w.r??{},S.updatedTxid=m,S.owner=be(k)??S.owner}}return h&&Object.defineProperty(p,"integrity",{value:h,enumerable:!1}),p}finally{o||l.close()}}async function An(t,e={}){let n=kn(t);return(await bt(e)).get(n)??null}var ts=T.rootTldName,es=T.bootstrapTlds.slice();var Dn="bchtest",Cn="bitcoincash",At=T.prefix,Xt="m/44'/145'/0'",Un=5,Nt="bns.wallet.v1";function Re(t){let e=Nn(t);return Uint8Array.from([118,169,20,...e,136,172])}function Ie(t,e,n){let o=Rn({bytecode:Re(t),prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(`address encoding failed: ${o}`);return o.address}var Jt=class t{constructor(e,n,o=At,s=Xt){this.mnemonic=e,this.prefix=o,this.accountPath=s,this._root=In(n),this._keys=new Map,this._derive()}static async create(e=At,n=Xt){let o=Bn();return new t(o,await Ae(o),e,n)}static async fromMnemonic(e,n=At,o=Xt){let s=String(e).trim().toLowerCase().replace(/\s+/g," "),r=await Ae(s);if(typeof r=="string")throw new Error(`invalid recovery phrase: ${r}`);return new t(s,r,n,o)}_derive(){this.receive=[],this.change=[];for(let[e,n]of[[0,this.receive],[1,this.change]])for(let o=0;o<Un;o++){let s=`${this.accountPath}/${e}/${o}`,r=Pn(this._root,s);if(typeof r=="string")throw new Error(`HD derivation failed at ${s}: ${r}`);let a=Be.derivePublicKeyCompressed(r.privateKey);if(typeof a=="string")throw new Error(`pubkey derivation failed: ${a}`);let i=Re(a),l={path:s,branch:e,index:o,privateKey:r.privateKey,publicKey:a,lockingBytecode:i,address:Ie(a,this.prefix,!1),tokenAddress:Ie(a,this.prefix,!0)};n.push(l),this._keys.set(Ln(i),l)}}get address(){return this.receive[0].address}get tokenAddress(){return this.receive[0].tokenAddress}get watchedAddresses(){return[...this.receive,...this.change].map(e=>e.address)}keyFor(e){let n=this._keys.get(e);return n?{privateKey:n.privateKey,publicKey:n.publicKey}:null}signMessage(e,n){if(!(e instanceof Uint8Array)||e.length!==32)throw new Error("signMessage expects a 32-byte Uint8Array digest");let o=n||this.address,s=[...this.receive,...this.change].find(h=>h.address===o);if(!s)throw new Error(`no key for address ${o}`);let r=Be.signMessageHashRecoverableCompact(s.privateKey,e);if(typeof r=="string")throw new Error(`signMessage failed: ${r}`);let{signature:a}=r,i=r.recoveryId??r.recovery;if(typeof i!="number")throw new Error("signMessage: no recovery id in signature result");let l=31+i,c=new Uint8Array(65);return c[0]=l,c.set(a,1),c}async encrypt(e){let n=crypto.getRandomValues(new Uint8Array(16)),o=crypto.getRandomValues(new Uint8Array(12)),s=await Pe(e,n),r=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:o},s,Ne(this.mnemonic)));return JSON.stringify({v:1,kdf:"PBKDF2-SHA256",iterations:Qt,prefix:this.prefix,salt:Yt(n),iv:Yt(o),ct:Yt(r)})}static async decrypt(e,n){let o=typeof e=="string"?JSON.parse(e):e,s=await Pe(n,Vt(o.salt),o.iterations??Qt),r;try{r=await crypto.subtle.decrypt({name:"AES-GCM",iv:Vt(o.iv)},s,Vt(o.ct))}catch{throw new Error("wrong password")}return t.fromMnemonic(new TextDecoder().decode(r),o.prefix??At)}async save(e,n=globalThis.localStorage){n.setItem(Nt,await this.encrypt(e))}static async load(e,n=globalThis.localStorage){let o=n.getItem(Nt);return o?t.decrypt(o,e):null}static exists(e=globalThis.localStorage){return!!e?.getItem(Nt)}static forget(e=globalThis.localStorage){e.removeItem(Nt)}},Qt=25e4;async function Pe(t,e,n=Qt){let o=await crypto.subtle.importKey("raw",Ne(String(t)),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:e,iterations:n,hash:"SHA-256"},o,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}var us=kt.chipnet.electrum.map(t=>t.url),Rt=T.electrum.map(t=>t.url),Zt=class{constructor(e,n){this.url=e,this.WS=n||globalThis.WebSocket,this.id=0,this.pending=new Map,this.buf=""}connect(){return new Promise((e,n)=>{let o=new this.WS(this.url);this.ws=o;let s=async()=>{try{await this.call("server.version",["bns-web","1.4.2"]),e(this)}catch(i){n(i)}},r=i=>n(new Error("electrum ws error: "+(i?.message||this.url))),a=i=>this._onData(typeof i.data=="string"?i.data:i.data.toString());o.addEventListener?(o.addEventListener("open",s),o.addEventListener("error",r),o.addEventListener("message",a)):(o.onopen=s,o.onerror=r,o.onmessage=a)})}_handle(e){let n=this.pending.get(e.id);n&&(this.pending.delete(e.id),e.error?n.reject(new Error(JSON.stringify(e.error))):n.resolve(e.result))}_onData(e){this.buf+=e;let n;for(;(n=this.buf.indexOf(`
`))>=0;){let s=this.buf.slice(0,n).trim();if(this.buf=this.buf.slice(n+1),s)try{this._handle(JSON.parse(s))}catch{}}let o=this.buf.trim();if(o)try{let s=JSON.parse(o);this._handle(s),this.buf=""}catch{}}call(e,n=[]){let o=++this.id;return new Promise((s,r)=>{this.pending.set(o,{resolve:s,reject:r}),this.ws.send(JSON.stringify({id:o,method:e,params:n})+`
`),setTimeout(()=>{this.pending.has(o)&&(this.pending.delete(o),r(new Error(`electrum timeout: ${e}`)))},2e4)})}close(){try{this.ws.close()}catch{}}};async function Le(t=Rt,e){let n=[];for(let o of t)try{return await new Zt(o,e).connect()}catch(s){n.push(`${o}: ${s?.message??s}`)}throw Fn(t.length,n)}function Fn(t,e){let n=new Error(`no electrum server reachable (tried ${t}). These use non-standard ports, which some networks and VPNs block:
${e.join(`
`)}`);return n.code="NO_ELECTRUM",n.failures=e,n}import{cashAddressToLockingBytecode as $n,lockingBytecodeToCashAddress as Mn,sha256 as Hn,hash160 as ps,binToHex as Kn,hexToBin as fs}from"@bitauth/libauth";function De(t){return Kn(Hn.hash(t).slice().reverse())}function L(t){let e=$n(t);if(typeof e=="string")throw new Error(`bad address "${t}": ${e}`);return e.bytecode}function Wn(t){return De(L(t))}function z(t){let e=L(t),n=String(t).includes(":")?t.split(":")[0]:T.prefix,o=Mn({bytecode:e,prefix:n,tokenSupport:!0});if(typeof o=="string")throw new Error(`cannot token-encode "${t}": ${o}`);return o.address}async function Ce(t,e){let n=L(e),o=De(n);return(await t.call("blockchain.scripthash.listunspent",[o,"include_tokens"])).map(r=>({txid:r.tx_hash,vout:r.tx_pos,satoshis:BigInt(r.value),height:r.height,address:e,lockingBytecode:n,token:r.token_data?{category:r.token_data.category,amount:BigInt(r.token_data.amount??0),nft:r.token_data.nft?{capability:r.token_data.nft.capability,commitment:r.token_data.nft.commitment}:void 0}:void 0}))}async function j(t,e){let n=[];for(let o of e)n.push(...await Ce(t,o));return n}async function st(t,e){return t.call("blockchain.transaction.broadcast",[e])}import{binToHex as Dt,hexToBin as X,utf8ToBin as ft,binToUtf8 as Ue,encodeTransaction as Gn,decodeTransaction as ws}from"@bitauth/libauth";var zn="BNS1",dt=T.beacon,ne=T.tldBeacon,B=600n,N=1000n,W=546n,te="bch",ee=200,qn=/^[a-z0-9-]{1,32}$/,Fe=/^[a-z0-9-]{1,16}$/;function Tt(t){let e=String(t).toLowerCase().trim().replace(/^\.+/,"").replace(/\.+$/,"");if(!Fe.test(e))throw new Error(`invalid TLD "${t}" (allowed: [a-z0-9-]{1,16})`);return e}var Lt=class extends Error{constructor(e){super(e),this.name="NoGenesisInputError",this.code="NO_GENESIS_INPUT"}},J=class extends Error{constructor(e,{needSats:n,haveSats:o}={}){super(e),this.name="InsufficientFundsError",this.code="INSUFFICIENT_FUNDS",this.needSats=n,this.haveSats=o}};function H(t){let e=String(t).toLowerCase().trim().replace(/\.$/,"").split(".").filter(Boolean),n,o;if(e.length===0)throw new Error(`invalid name "${t}"`);if(e.length===1?(n=e[0],o=te):(o=e[e.length-1],n=e[e.length-2]),!qn.test(n)||!Fe.test(o))throw new Error(`invalid name "${t}" (allowed: <label>.<tld>, [a-z0-9-])`);return o===te?n:`${n}.${o}`}function Q(t){return t.includes(".")?t:`${t}.${te}`}function Z(t,e,n){let o=JSON.stringify({o:t,n:e,r:n??{}}),s=ft(zn+o);if(s.length>ee)throw new Error(`records too large (${s.length} > ${ee} bytes)`);return s}function oe(t,e="REG"){return ee-Z(e,t,{}).length}function jn(t){return t.length<=75?Uint8Array.from([t.length,...t]):t.length<=255?Uint8Array.from([76,t.length,...t]):Uint8Array.from([77,t.length&255,t.length>>8&255,...t])}function et(t){return Uint8Array.from([106,...jn(t)])}function se(){return Uint8Array.from([65,...new Uint8Array(65),33,...new Uint8Array(33)])}var Yn=t=>!t.token;function M(t,e,{requireGenesis:n=!0}={}){let o=t.filter(Yn),s=[],r=0n;if(n){let i=o.filter(l=>l.vout===0).sort((l,c)=>c.satoshis>l.satoshis?1:-1);if(i.length===0)throw new Lt("wallet has no coin at output index 0, which CashTokens requires to create a new certificate category \u2014 send a small amount to yourself first (buildPrepTx)");s.push(i[0]),r+=i[0].satoshis}let a=o.filter(i=>!s.some(l=>l.txid===i.txid&&l.vout===i.vout)).sort((i,l)=>l.satoshis>i.satoshis?1:-1);for(let i of a){if(r>=e)break;s.push(i),r+=i.satoshis}return{inputs:s,totalSats:r}}function gt(t){return{outpointTransactionHash:X(t.txid),outpointIndex:t.vout,sequenceNumber:4294967294,unlockingBytecode:se()}}function St(t){return{...gt(t),lockingBytecode:t.lockingBytecode,valueSatoshis:t.satoshis,...t.token?{token:{amount:t.token.amount??0n,category:X(t.token.category),...t.token.nft?{nft:{capability:t.token.nft.capability,commitment:X(t.token.nft.commitment||"")}}:{}}}:{}}}function ut(t){return Gn(t).length}function re({name:t,ownerAddress:e,ownerTokenAddress:n,changeAddress:o,records:s={},utxos:r,feeAddress:a=null,feeSats:i=0n,tldFeeAddress:l=null,tldFeeSats:c=0n,beaconAddress:h=dt,feeRate:u=1,addressToLockingBytecode:d,cosignUtxo:p=null,cosignTokenAddress:m=null}){if(typeof d!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let f=H(t),g=Z("REG",f,s),y=BigInt(i??0n),w=BigInt(c??0n);if(p&&!p.token?.nft)throw new Error("cosignUtxo does not carry a TLD certificate");let x=p?BigInt(p.satoshis):0n,_=p?d(m??n??e):null;if(y>0n&&!a)throw new Error("feeSats set but feeAddress missing");if(w>0n&&!l)throw new Error("tldFeeSats set but tldFeeAddress missing");let S=d(o??e),k=d(n??e),O=d(h),I=y>0n?d(a):null,b=w>0n?d(l):null,R=N+B+y+w+x,A=M(r,R+300n-x),v=0n,E=0n,C=!0;for(let P=0;P<6;P++){let{inputs:F}=A,$=p?[...F,p]:F,K=A.totalSats+x,ct=$[0],ot=X(ct.txid),q=(wt,xt)=>{let V=[];return wt&&V.push({lockingBytecode:S,valueSatoshis:xt}),V.push({lockingBytecode:k,valueSatoshis:N,token:{amount:0n,category:ot,nft:{capability:"none",commitment:ft(f)}}}),V.push({lockingBytecode:et(g),valueSatoshis:0n}),V.push({lockingBytecode:O,valueSatoshis:B}),b&&V.push({lockingBytecode:b,valueSatoshis:w}),I&&V.push({lockingBytecode:I,valueSatoshis:y}),p&&V.push({lockingBytecode:_,valueSatoshis:x,token:{amount:BigInt(p.token.amount??0),category:X(p.token.category),nft:{capability:p.token.nft.capability,commitment:X(p.token.nft.commitment||"")}}}),{version:2,locktime:0,inputs:$.map(gt),outputs:V}},hn=q(!0,1000000n),pn=ut(hn);v=BigInt(Math.ceil(pn*u));let vt=R+v;if(K<vt){let wt=M(r,vt+200n-x);if(wt.inputs.length>F.length){A=wt;continue}throw new J(`not enough funds: need ${vt} sat, have ${K} sat`,{needSats:vt,haveSats:K})}if(E=K-vt,C=E>=W,!C){let wt=q(!1,0n);v=K-R;let xt=BigInt(Math.ceil(ut(wt)*u));if(v<xt){let V=M(r,R+xt+W+200n-x);if(V.inputs.length>F.length){A=V;continue}throw new J(`not enough funds: need ${R+xt} sat, have ${K} sat`,{needSats:R+xt,haveSats:K})}E=0n}let fn=q(C,E),lt={},pt=0;return C&&(lt.change=pt++),lt.certificate=pt++,lt.opReturn=pt++,lt.beacon=pt++,b&&(lt.tldOwnerFee=pt++),I&&(lt.serviceFee=pt++),p&&(lt.cosignCertificate=pt++),{name:f,displayName:Q(f),category:Dt(ot),transaction:fn,sourceOutputs:$.map(St),inputUtxos:$,outputMap:lt,payload:g,costs:{certificateDustSats:N,beaconDustSats:B,serviceFeeSats:y,tldOwnerFeeSats:w,chainFeeSats:v,changeSats:E,totalInputSats:K,netCostSats:y+w+v+B}}}throw new Error("could not converge on a fee \u2014 please retry")}function Ct({tld:t,ownerAddress:e,ownerTokenAddress:n,changeAddress:o,records:s={},utxos:r,feeAddress:a=null,feeSats:i=0n,beaconAddress:l=ne,feeRate:c=1,addressToLockingBytecode:h}){if(typeof h!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let u=Tt(t),d=Z("TREG",u,s),p=BigInt(i??0n);if(p>0n&&!a)throw new Error("feeSats set but feeAddress missing");let m=h(o??e),f=h(n??e),g=h(l),y=p>0n?h(a):null,w=N+B+p,x=M(r,w+300n),_=0n,S=0n,k=!0;for(let O=0;O<6;O++){let{inputs:I,totalSats:b}=x,R=I[0],A=X(R.txid),v=(ct,ot)=>{let q=[];return ct&&q.push({lockingBytecode:m,valueSatoshis:ot}),q.push({lockingBytecode:f,valueSatoshis:N,token:{amount:0n,category:A,nft:{capability:"none",commitment:ft(u)}}}),q.push({lockingBytecode:et(d),valueSatoshis:0n}),q.push({lockingBytecode:g,valueSatoshis:B}),y&&q.push({lockingBytecode:y,valueSatoshis:p}),{version:2,locktime:0,inputs:I.map(gt),outputs:q}},E=v(!0,1000000n),C=ut(E);_=BigInt(Math.ceil(C*c));let P=w+_;if(b<P){let ct=M(r,P+200n);if(ct.inputs.length>I.length){x=ct;continue}throw new J(`not enough funds: need ${P} sat, have ${b} sat`,{needSats:P,haveSats:b})}if(S=b-P,k=S>=W,!k){let ct=v(!1,0n);_=b-w;let ot=BigInt(Math.ceil(ut(ct)*c));if(_<ot){let q=M(r,w+ot+W+200n);if(q.inputs.length>I.length){x=q;continue}throw new J(`not enough funds: need ${w+ot} sat, have ${b} sat`,{needSats:w+ot,haveSats:b})}S=0n}let F=v(k,S),$={},K=0;return k&&($.change=K++),$.certificate=K++,$.opReturn=K++,$.beacon=K++,y&&($.serviceFee=K++),{tld:u,category:Dt(A),transaction:F,sourceOutputs:I.map(St),inputUtxos:I,outputMap:$,payload:d,costs:{certificateDustSats:N,beaconDustSats:B,serviceFeeSats:p,chainFeeSats:_,changeSats:S,totalInputSats:b,netCostSats:p+_+B}}}throw new Error("could not converge on a fee \u2014 please retry")}function Ut({name:t,ownerAddress:e,ownerTokenAddress:n,records:o={},certificateUtxo:s,utxos:r,beaconAddress:a=dt,feeRate:i=1,addressToLockingBytecode:l}){if(typeof l!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let c=H(t);if(!s?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let h=Dt(ft(c));if(s.token.nft.commitment!==h)throw new Error(`certificate commitment mismatch: holds "${Ue(X(s.token.nft.commitment))}", asked to update "${c}"`);let u=Z("UPD",c,o),d=l(e),p=l(n??e),m=l(a),f=N+B,g=M(r,f+400n,{requireGenesis:!1}),y=0n,w=0n,x=!0;for(let _=0;_<6;_++){let S=[s,...g.inputs],k=s.satoshis+g.totalSats,O=(E,C)=>{let P=[];return E&&P.push({lockingBytecode:d,valueSatoshis:C}),P.push({lockingBytecode:p,valueSatoshis:N,token:{amount:0n,category:X(s.token.category),nft:{capability:"none",commitment:ft(c)}}}),P.push({lockingBytecode:et(u),valueSatoshis:0n}),P.push({lockingBytecode:m,valueSatoshis:B}),{version:2,locktime:0,inputs:S.map(gt),outputs:P}},I=ut(O(!0,1000000n));y=BigInt(Math.ceil(I*i));let b=f+y;if(k<b){let E=M(r,b+200n,{requireGenesis:!1});if(E.inputs.length>g.inputs.length){g=E;continue}throw new J(`not enough funds: need ${b} sat, have ${k} sat`,{needSats:b,haveSats:k})}w=k-b,x=w>=W,x||(y=k-f,w=0n);let R=O(x,w),A={},v=0;return x&&(A.change=v++),A.certificate=v++,A.opReturn=v++,A.beacon=v++,{name:c,displayName:Q(c),category:s.token.category,transaction:R,sourceOutputs:S.map(St),inputUtxos:S,outputMap:A,payload:u,costs:{certificateDustSats:N,beaconDustSats:B,serviceFeeSats:0n,chainFeeSats:y,changeSats:w,totalInputSats:k,netCostSats:y+B}}}throw new Error("could not converge on a fee \u2014 please retry")}function $e({tld:t,ownerAddress:e,ownerTokenAddress:n,records:o={},certificateUtxo:s,utxos:r,beaconAddress:a=ne,feeRate:i=1,addressToLockingBytecode:l}){if(typeof l!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let c=Tt(t);if(!s?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let h=Dt(ft(c));if(s.token.nft.commitment!==h)throw new Error(`TLD certificate commitment mismatch: holds "${Ue(X(s.token.nft.commitment))}", asked to update ".${c}"`);let u=Z("TUPD",c,o),d=l(e),p=l(n??e),m=l(a),f=N+B,g=M(r,f+400n,{requireGenesis:!1}),y=0n,w=0n,x=!0;for(let _=0;_<6;_++){let S=[s,...g.inputs],k=s.satoshis+g.totalSats,O=(E,C)=>{let P=[];return E&&P.push({lockingBytecode:d,valueSatoshis:C}),P.push({lockingBytecode:p,valueSatoshis:N,token:{amount:0n,category:X(s.token.category),nft:{capability:"none",commitment:ft(c)}}}),P.push({lockingBytecode:et(u),valueSatoshis:0n}),P.push({lockingBytecode:m,valueSatoshis:B}),{version:2,locktime:0,inputs:S.map(gt),outputs:P}},I=ut(O(!0,1000000n));y=BigInt(Math.ceil(I*i));let b=f+y;if(k<b){let E=M(r,b+200n,{requireGenesis:!1});if(E.inputs.length>g.inputs.length){g=E;continue}throw new J(`not enough funds: need ${b} sat, have ${k} sat`,{needSats:b,haveSats:k})}w=k-b,x=w>=W,x||(y=k-f,w=0n);let R=O(x,w),A={},v=0;return x&&(A.change=v++),A.certificate=v++,A.opReturn=v++,A.beacon=v++,{tld:c,displayName:`.${c}`,category:s.token.category,transaction:R,sourceOutputs:S.map(St),inputUtxos:S,outputMap:A,payload:u,costs:{certificateDustSats:N,beaconDustSats:B,serviceFeeSats:0n,chainFeeSats:y,changeSats:w,totalInputSats:k,netCostSats:y+B}}}throw new Error("could not converge on a fee \u2014 please retry")}function Et({ownerAddress:t,utxos:e,amountSats:n=10000n,feeRate:o=1,addressToLockingBytecode:s}){let r=s(t),a=M(e,n+400n,{requireGenesis:!1});if(a.inputs.length===0)throw new J("wallet is empty");for(let i=0;i<6;i++){let{inputs:l,totalSats:c}=a,h=(m,f)=>({version:2,locktime:0,inputs:l.map(gt),outputs:[{lockingBytecode:r,valueSatoshis:n},...m?[{lockingBytecode:r,valueSatoshis:f}]:[]]}),u=BigInt(Math.ceil(ut(h(!0,1000000n))*o));if(c<n+u){let m=BigInt(Math.ceil(ut(h(!1,0n))*o));if(c<=m+W)throw new J(`not enough funds to prepare the wallet: have ${c} sat`,{needSats:m+W,haveSats:c});return{transaction:{version:2,locktime:0,inputs:l.map(gt),outputs:[{lockingBytecode:r,valueSatoshis:c-m}]},sourceOutputs:l.map(St),inputUtxos:l,costs:{chainFeeSats:m}}}let d=c-n-u,p=d>=W;return{transaction:h(p,d),sourceOutputs:l.map(St),inputUtxos:l,costs:{chainFeeSats:p?u:c-n}}}throw new Error("could not converge on a fee \u2014 please retry")}function mt(t){return t.some(e=>e.vout===0&&!e.token)}function Me({transaction:t,sourceOutputs:e},{broadcast:n=!0,userPrompt:o}={}){return{transaction:t,sourceOutputs:e,broadcast:n,...o?{userPrompt:o}:{}}}import{generateSigningSerializationBCH as Vn,hash256 as Ke,secp256k1 as Xn,encodeTransaction as Jn,binToHex as ie}from"@bitauth/libauth";var He=65;function ht(t,e,n){let o={...t,inputs:t.inputs.map((r,a)=>{let i=e[a],l=n(ie(i.lockingBytecode));if(!l)throw new Error(`no key for input ${a} \u2014 cannot sign`);let c=Vn({inputIndex:a,sourceOutputs:e,transaction:t},{coveredBytecode:i.lockingBytecode,signingSerializationType:Uint8Array.of(He)}),h=Ke(c),u=Xn.signMessageHashSchnorr(l.privateKey,h);if(typeof u=="string")throw new Error(`signing failed on input ${a}: ${u}`);let d=Uint8Array.from([...u,He]);return{...r,unlockingBytecode:Uint8Array.from([d.length,...d,l.publicKey.length,...l.publicKey])}})},s=Jn(o);return{transaction:o,hex:ie(s),txid:ae(s)}}function ae(t){return ie(Ke(t).slice().reverse())}function ce(t){let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return ae(e)}var D={network:T.id,addressPrefix:T.prefix,explorerTx:T.explorerTx,selfHosted:null,get electrum(){return this.selfHosted?[this.selfHosted,...Rt]:Rt},beacon:T.beacon,tldBeacon:T.tldBeacon,serviceFee:{address:T.operatorAddress,sats:10000n},feeRate:1,wizardConnect:{dappName:"Silent Mode",dappIcon:"https://silentmode.st/icon.png"},faucets:T.faucets};function Qn(t){let e=r=>(Number(r)/1e8).toFixed(8).replace(/0+$/,"").replace(/\.$/,""),n=[],o=BigInt(t.tldOwnerFeeSats??0n),s=BigInt(t.serviceFeeSats??0n);return o>0n?(n.push({label:"Service fee \u2014 TLD owner (90%)",sats:o,bch:e(o),note:"goes to whoever holds this TLD's certificate on chain"}),n.push({label:"Service fee \u2014 platform (10%)",sats:s,bch:e(s),note:"covers the resolver + gateway + indexer"})):n.push({label:"Service fee",sats:s,bch:e(s)}),n.push({label:"Network fee",sats:t.chainFeeSats,bch:e(t.chainFeeSats)}),n.push({label:"Discovery beacon",sats:t.beaconDustSats,bch:e(t.beaconDustSats)}),n.push({label:"Held in the certificate",sats:t.certificateDustSats,bch:e(t.certificateDustSats),note:"stays yours \u2014 it lives in the certificate you now own"}),n.push({label:"Total",sats:t.netCostSats,bch:e(t.netCostSats),total:!0}),n}import{hexToBin as Ve,binToHex as yt,decodeTransaction as so,lockingBytecodeToCashAddress as ro,sha256 as io,utf8ToBin as ao,binToBase64 as co}from"@bitauth/libauth";import{encodeTransaction as ue,decodeTransaction as We,generateSigningSerializationBCH as Ge,hash256 as de,hash160 as Zn,secp256k1 as ze,hexToBin as rt,binToHex as U,utf8ToBin as qe}from"@bitauth/libauth";var Ft=65,le=195,nt=(t,e)=>({outpointTransactionHash:rt(t.txid),outpointIndex:t.vout,sequenceNumber:4294967294,unlockingBytecode:e??se()}),it=t=>t?{amount:BigInt(t.amount??0),category:rt(t.category),...t.nft?{nft:{capability:t.nft.capability,commitment:rt(t.nft.commitment||"")}}:{}}:void 0,he=t=>({lockingBytecode:t.lockingBytecode instanceof Uint8Array?U(t.lockingBytecode):String(t.lockingBytecode),valueSatoshis:String(t.valueSatoshis),...t.token?{token:{category:t.token.category instanceof Uint8Array?U(t.token.category):String(t.token.category),amount:String(t.token.amount??0),...t.token.nft?{nft:{capability:t.token.nft.capability,commitment:t.token.nft.commitment instanceof Uint8Array?U(t.token.nft.commitment):String(t.token.nft.commitment||"")}}:{}}}:{}}),pe=t=>({lockingBytecode:rt(t.lockingBytecode),valueSatoshis:BigInt(t.valueSatoshis??t.satoshis),...t.token?{token:it(t.token)}:{}}),at=(t,e)=>({...nt(t,e),lockingBytecode:t.lockingBytecode instanceof Uint8Array?t.lockingBytecode:rt(t.lockingBytecode),valueSatoshis:BigInt(t.satoshis),...t.token?{token:it(t.token)}:{}});function je(t,e,n,o,s){let r=e[n],a=Ge({inputIndex:n,sourceOutputs:e,transaction:t},{coveredBytecode:r.lockingBytecode,signingSerializationType:Uint8Array.of(s)}),i=de(a),l=ze.signMessageHashSchnorr(o.privateKey,i);if(typeof l=="string")throw new Error(`signing failed on input ${n}: ${l}`);let c=Uint8Array.from([...l,s]);return Uint8Array.from([c.length,...c,o.publicKey.length,...o.publicKey])}function _t(t,e,n,{sighash:o=Ft,skip:s=[]}={}){let r={...t,inputs:t.inputs.map((i,l)=>{if(s.includes(l))return i;let c=n(U(e[l].lockingBytecode));return c?{...i,unlockingBytecode:je(t,e,l,c,o)}:i})},a=ue(r);return{transaction:r,hex:U(a),txid:U(de(a).slice().reverse())}}function to({name:t,certificateUtxo:e,priceSats:n,sellerAddress:o,addressToLockingBytecode:s,keyFor:r}){let a=H(t),i=BigInt(n);if(i<W)throw new Error(`price must be at least ${W} sat`);if(!e?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");if(e.token.nft.commitment!==U(qe(a)))throw new Error("certificate commitment does not match the name");let l=s(o),c=at(e),h={version:2,locktime:0,inputs:[nt(e)],outputs:[{lockingBytecode:l,valueSatoshis:i}]},u=r(U(c.lockingBytecode));if(!u)throw new Error("this wallet does not hold the key for the certificate");return h.inputs[0].unlockingBytecode=je(h,[c],0,u,le),{v:1,name:a,seller:o,price_sats:i.toString(),category:e.token.category,partial_tx:U(ue(h)),source_output:{txid:e.txid,vout:e.vout,satoshis:BigInt(e.satoshis).toString(),lockingBytecode:U(c.lockingBytecode),token:{category:e.token.category,amount:String(e.token.amount??0),nft:e.token.nft?{capability:e.token.nft.capability,commitment:e.token.nft.commitment}:void 0}},created_at:new Date().toISOString()}}function eo(t){let e=t[0],n=t.slice(1,1+e),o=t[1+e],s=t.slice(2+e,2+e+o);return{sig:n,pubkey:s}}var no=t=>Uint8Array.from([118,169,20,...Zn(t),136,172]);function Ye(t,e={}){let n=o=>({ok:!1,error:o});try{if(!t||t.v!==1)return n("unsupported listing version");let o=H(t.name),s=We(rt(t.partial_tx));if(typeof s=="string")return n("partial_tx does not decode: "+s);if(s.inputs.length!==1||s.outputs.length<1)return n("partial_tx must have exactly one input and a payment output");let r=t.source_output;if(!r?.token?.nft)return n("source_output carries no certificate");if(U(s.inputs[0].outpointTransactionHash)!==r.txid||s.inputs[0].outpointIndex!==r.vout)return n("input does not spend source_output");if(r.token.nft.commitment!==U(qe(o)))return n("certificate commitment does not match the name");if(e.category&&r.token.category!==e.category)return n("certificate category does not match the registry");let a=s.outputs[0].valueSatoshis;if(a<W)return n("price below dust");if(BigInt(t.price_sats)!==a)return n("price_sats does not match output 0");let{sig:i,pubkey:l}=eo(s.inputs[0].unlockingBytecode);if(i.length!==65||i[64]!==le)return n("input 0 is not signed SINGLE|ANYONECANPAY");let c=rt(r.lockingBytecode);if(U(no(l))!==U(c))return n("public key does not own the certificate output");if(e.ownerLockingBytecode&&U(c)!==e.ownerLockingBytecode)return n("certificate is not held by the current owner");if(U(s.outputs[0].lockingBytecode)!==U(c))return n("payment does not go to the certificate holder");let h={...s.inputs[0],lockingBytecode:c,valueSatoshis:BigInt(r.satoshis),token:it(r.token)},u=Ge({inputIndex:0,sourceOutputs:[h],transaction:s},{coveredBytecode:c,signingSerializationType:Uint8Array.of(le)});return ze.verifySignatureSchnorr(i.slice(0,64),l,de(u))?{ok:!0,name:o,price_sats:a,seller_lock:U(c),category:r.token.category}:n("seller signature is invalid")}catch(o){return n(String(o?.message||o))}}function oo({listing:t,buyerAddress:e,buyerTokenAddress:n,utxos:o,records:s={},beaconAddress:r=dt,feeRate:a=1,addressToLockingBytecode:i}){let l=Ye(t);if(!l.ok)throw new Error("bad listing: "+l.error);let c=l.name,h=We(rt(t.partial_tx)),u=t.source_output,d=h.inputs[0],p={...d,lockingBytecode:rt(u.lockingBytecode),valueSatoshis:BigInt(u.satoshis),token:it(u.token)},m=h.outputs[0],f=m.valueSatoshis,g=i(e),y=i(n??e),w=i(r),x=Z("UPD",c,s),_=f+N+B-BigInt(u.satoshis),S=M(o,_+400n,{requireGenesis:!1}),k=O=>ue(O).length;for(let O=0;O<6;O++){let{inputs:I,totalSats:b}=S,R=(F,$)=>({version:2,locktime:0,inputs:[d,...I.map(K=>nt(K))],outputs:[m,{lockingBytecode:y,valueSatoshis:N,token:it(u.token)},{lockingBytecode:et(x),valueSatoshis:0n},{lockingBytecode:w,valueSatoshis:B},...F?[{lockingBytecode:g,valueSatoshis:$}]:[]]}),A=BigInt(Math.ceil(k(R(!0,1000000n))*a)),v=_+A;if(b<v){let F=M(o,v+200n,{requireGenesis:!1});if(F.inputs.length>I.length){S=F;continue}let $=new Error(`not enough funds: need ${v} sat, have ${b} sat`);throw $.needSats=v,$.haveSats=b,$}let E=b-v,C=E>=W;C||(E=0n);let P=R(C,E);return{name:c,transaction:P,sourceOutputs:[p,...I.map(F=>at(F))],sellerInputIndex:0,costs:{priceSats:f,beaconDustSats:B,certificateDustSats:N,chainFeeSats:C?A:b-_,changeSats:E,totalInputSats:b}}}throw new Error("could not converge on a fee \u2014 please retry")}var lo=90n,uo=100n;async function Xe(t,e,n=D.addressPrefix){let s=(await jt(t)).get(String(e).toLowerCase());if(!s?.mintScriptHex)return null;try{let r=Ve(s.mintScriptHex),a=ro({bytecode:r,prefix:n,tokenSupport:!1});return typeof a=="string"?null:a.address}catch{return null}}function Je(t){let e=BigInt(t??0n),n=e*lo/uo,o=e-n;return{tldOwnerFeeSats:n,platformFeeSats:o}}var ho=T.beaconOnly;async function po({electrum:t=D.electrum,WebSocket:e,beaconOk:n=!1}={}){let o=n?t:t.filter(s=>!ho.test(typeof s=="string"?s:s.url||""));return Le(o,e)}async function $t(t,e){let n=H(e),o=Q(n),r=(await bt({client:t})).get(o)??null;return{name:o,rawName:n,available:!r,entry:r,recordBudgetBytes:oe(n)}}async function Mt(t,{name:e,ownerAddress:n,records:o={},utxos:s,serviceFee:r=D.serviceFee,feeRate:a=D.feeRate,cosignUtxo:i=null,cosignTokenAddress:l=null}){let c=s??await j(t,[n]),h=H(e),u=h.indexOf("."),d=u<0?"bch":h.slice(u+1),p=BigInt(r.sats??0n),m=null,f=0n,g=p;if(p>0n){try{m=await Xe(t,d)}catch{m=null}if(m&&m!==n){let y=Je(p);f=y.tldOwnerFeeSats,g=y.platformFeeSats}}return re({name:e,ownerAddress:n,ownerTokenAddress:z(n),records:o,utxos:c,feeAddress:g>0n?r.address:null,feeSats:g,tldFeeAddress:f>0n?m:null,tldFeeSats:f,beaconAddress:D.beacon,feeRate:a,addressToLockingBytecode:L,cosignUtxo:i,cosignTokenAddress:l})}function Qe(t,{tld:e,category:n}){let o=[...new TextEncoder().encode(String(e).toLowerCase())].map(s=>s.toString(16).padStart(2,"0")).join("");return t.find(s=>s.token?.nft&&(!n||s.token.category===n)&&s.token.nft.commitment===o)??null}async function Ze(t,{wallet:e,utxos:n,feeRate:o,onProgress:s}){if(mt(n))return{utxos:n,prepTxid:null};s("preparing-wallet");let r=Et({ownerAddress:e.address,utxos:n,feeRate:o,addressToLockingBytecode:L}),a=ht(r.transaction,r.sourceOutputs,c=>e.keyFor(c)),i=await st(t,a.hex);return s("prepared",{txid:i}),{utxos:a.transaction.outputs.slice(0,2).map((c,h)=>({txid:i,vout:h,satoshis:c.valueSatoshis,address:e.address,lockingBytecode:L(e.address)})),prepTxid:i}}async function fo(t,{wallet:e,name:n,records:o={},serviceFee:s=D.serviceFee,feeRate:r=D.feeRate,tldCert:a,onProgress:i=()=>{}}){if(!a?.utxo?.token?.nft||!a.owner)throw new Error("tldCert must be the /api/tld-cert response ({ owner, utxo })");i("checking-availability");let l=await $t(t,n);if(!l.available)throw new Error(`"${l.name}" is already registered`);i("loading-coins");let c=await j(t,e.watchedAddresses);if(c.filter(g=>!g.token).reduce((g,y)=>g+y.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let u=null;({utxos:c,prepTxid:u}=await Ze(t,{wallet:e,utxos:c,feeRate:r,onProgress:i})),i("building");let d=await Mt(t,{name:n,ownerAddress:e.address,records:o,utxos:c,serviceFee:s,feeRate:r,cosignUtxo:{...a.utxo,address:a.owner},cosignTokenAddress:z(a.owner)}),p=d.transaction.inputs.length-1;i("signing");let m={...d.transaction,inputs:d.transaction.inputs.map((g,y)=>y===p?{...g,unlockingBytecode:new Uint8Array}:g)},f=_t(m,d.sourceOutputs,g=>e.keyFor(g),{skip:[p]});return{name:d.name,displayName:d.displayName,category:d.category,tx:f.hex,sourceOutputs:d.sourceOutputs.map(he),cosignInputIndex:p,costs:d.costs,prepTxid:u}}function go(t,e){let n=so(Ve(String(t.tx||"")));if(typeof n=="string")throw new Error("invalid transaction: "+n);let o=(t.sourceOutputs||[]).map(pe);if(o.length!==n.inputs.length)throw new Error("sourceOutputs do not match the transaction inputs");let s=[],r=0;n.inputs.forEach((i,l)=>{let c=o[l];if(!e(yt(c.lockingBytecode))){s.push(l);return}if(c.token?.nft&&!n.outputs.some(u=>u.token&&yt(u.token.category)===yt(c.token.category)&&yt(u.token.nft?.commitment??new Uint8Array)===yt(c.token.nft.commitment??new Uint8Array)&&yt(u.lockingBytecode)===yt(c.lockingBytecode)&&u.valueSatoshis>=c.valueSatoshis))throw new Error("refusing to sign: the request would not return your TLD certificate to you");r+=1});let a=_t(n,o,e,{skip:s});return{hex:a.hex,txid:a.txid,signedInputs:r}}async function mo(t,{wallet:e,name:n,records:o={},serviceFee:s=D.serviceFee,feeRate:r=D.feeRate,cosign:a=null,onProgress:i=()=>{}}){i("checking-availability");let l=await $t(t,n);if(!l.available)throw new Error(`"${l.name}" is already registered`);i("loading-coins");let c=await j(t,e.watchedAddresses);if(c.filter(g=>!g.token).reduce((g,y)=>g+y.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let u=null;if(a&&(u=Qe(c,a),!u))throw new Error(`this wallet does not hold the certificate for .${a.tld} \u2014 only the TLD owner can co-sign`);let d=null;({utxos:c,prepTxid:d}=await Ze(t,{wallet:e,utxos:c,feeRate:r,onProgress:i})),i("building");let p=await Mt(t,{name:n,ownerAddress:e.address,records:o,utxos:c,serviceFee:s,feeRate:r,cosignUtxo:u,cosignTokenAddress:u?z(e.address):null});i("signing");let m=ht(p.transaction,p.sourceOutputs,g=>e.keyFor(g));i("broadcasting");let f=await st(t,m.hex);return i("registered",{txid:f,category:p.category}),{name:p.name,displayName:p.displayName,category:p.category,txid:f,prepTxid:d,ownerAddress:e.address,certificateAddress:z(e.address),costs:p.costs,hex:m.hex}}async function yo(t,{wallet:e,tld:n,records:o={},serviceFee:s={address:null,sats:0n},feeRate:r=D.feeRate,tldListUrl:a=null,onProgress:i=()=>{}}){let l=Tt(n);if(i("checking-availability"),a)try{let f=await fetch(a);if(f.ok){let g=await f.json();if(Array.isArray(g.tlds)&&g.tlds.some(w=>(w.tld||w)===l))throw new Error(`".${l}" is already registered as a TLD`)}}catch(f){if(/already registered/.test(f.message))throw f}i("loading-coins");let c=await j(t,e.watchedAddresses);if(c.filter(f=>!f.token).reduce((f,g)=>f+g.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let u=null;if(!mt(c)){i("preparing-wallet");let f=Et({ownerAddress:e.address,utxos:c,feeRate:r,addressToLockingBytecode:L}),g=ht(f.transaction,f.sourceOutputs,y=>e.keyFor(y));u=await st(t,g.hex),i("prepared",{txid:u}),c=[{txid:u,vout:0,satoshis:g.transaction.outputs[0].valueSatoshis,address:e.address,lockingBytecode:L(e.address)},...g.transaction.outputs.length>1?[{txid:u,vout:1,satoshis:g.transaction.outputs[1].valueSatoshis,address:e.address,lockingBytecode:L(e.address)}]:[]]}i("building");let d=Ct({tld:l,ownerAddress:e.address,ownerTokenAddress:z(e.address),changeAddress:e.address,records:o,utxos:c,feeAddress:s.address||null,feeSats:BigInt(s.sats??0n),feeRate:r,addressToLockingBytecode:L});i("signing");let p=ht(d.transaction,d.sourceOutputs,f=>e.keyFor(f));i("broadcasting");let m=await st(t,p.hex);return i("registered",{txid:m,category:d.category}),{tld:d.tld,category:d.category,txid:m,prepTxid:u,ownerAddress:e.address,certificateAddress:z(e.address),costs:d.costs,hex:p.hex}}async function wo(t,{session:e,tld:n,records:o={},serviceFee:s={address:null,sats:0n},feeRate:r=D.feeRate,tldListUrl:a=null,onProgress:i=()=>{}}){let l=Tt(n);if(i("checking-availability"),a)try{let g=await fetch(a);if(g.ok){let y=await g.json();if(Array.isArray(y.tlds)&&y.tlds.some(x=>(x.tld||x)===l))throw new Error(`".${l}" is already registered as a TLD`)}}catch(g){if(/already registered/.test(g.message))throw g}i("reading-wallet");let c=await e.getAddresses();if(!c.length)throw new Error("the wallet exposed no addresses");let h=c[0];i("loading-coins");let u=await j(t,c);if(u.filter(g=>!g.token).reduce((g,y)=>g+y.satoshis,0n)===0n)throw new Error("the connected wallet has no spendable coins");let d=null;if(!mt(u)){i("preparing-wallet");let g=Et({ownerAddress:h,utxos:u,feeRate:r,addressToLockingBytecode:L}),y=await e.signTransaction(g,{userPrompt:"One-time setup so your wallet can create a TLD certificate"});d=await Bt(t,e,y,i),i("prepared",{txid:d}),u=[{txid:d,vout:0,satoshis:g.transaction.outputs[0].valueSatoshis,address:h,lockingBytecode:L(h)},...u.filter(w=>!w.token&&!g.inputUtxos.some(x=>x.txid===w.txid&&x.vout===w.vout))]}i("building");let p=Ct({tld:l,ownerAddress:h,ownerTokenAddress:z(h),changeAddress:h,records:o,utxos:u,feeAddress:s.address||null,feeSats:BigInt(s.sats??0n),feeRate:r,addressToLockingBytecode:L});i("awaiting-approval");let m=await e.signTransaction(p,{userPrompt:`Register .${l} \u2014 the TLD certificate is minted to your own address`}),f=await Bt(t,e,m,i);return i("registered",{txid:f,category:p.category}),{tld:p.tld,category:p.category,txid:f,prepTxid:d,ownerAddress:h,certificateAddress:z(h),costs:p.costs}}async function Bt(t,e,n,o){let s=n.signedTransactionHash??ce(n.signedTransaction);if(e.walletBroadcasts)return s;o("broadcasting");try{return await st(t,n.signedTransaction)}catch(r){let a=String(r?.message??r);if(/already|duplicate|txn-already|in mempool/i.test(a))return s;throw r}}async function xo(t,{session:e,name:n,ownerAddress:o,records:s={},serviceFee:r=D.serviceFee,feeRate:a=D.feeRate,onProgress:i=()=>{}}){i("checking-availability");let l=await $t(t,n);if(!l.available)throw new Error(`"${l.name}" is already registered`);i("reading-wallet");let c=await e.getAddresses();if(!c.length)throw new Error("the wallet exposed no addresses");let h=o??c[0];i("loading-coins");let u=await j(t,c);if(!u.some(f=>!f.token))throw new Error("the connected wallet has no spendable coins");if(!mt(u)){i("preparing-wallet");let f=Et({ownerAddress:h,utxos:u,feeRate:a,addressToLockingBytecode:L}),g=await e.signTransaction(f,{userPrompt:"One-time setup so your wallet can create a name certificate"}),y=await Bt(t,e,g,i);i("prepared",{txid:y}),u=[{txid:y,vout:0,satoshis:f.transaction.outputs[0].valueSatoshis,address:h,lockingBytecode:L(h)},...u.filter(w=>!w.token&&!f.inputUtxos.some(x=>x.txid===w.txid&&x.vout===w.vout))]}i("building");let d=await Mt(t,{name:n,ownerAddress:h,records:s,utxos:u,serviceFee:r,feeRate:a});i("awaiting-approval");let p=await e.signTransaction(d,{userPrompt:`Register ${d.displayName} \u2014 the certificate is minted to your own address`}),m=await Bt(t,e,p,i);return i("registered",{txid:m,category:d.category}),{name:d.name,displayName:d.displayName,category:d.category,txid:m,ownerAddress:h,certificateAddress:z(h),costs:d.costs}}async function ko(t,{addresses:e,category:n,rawName:o}){let s=await j(t,e),r=[...new TextEncoder().encode(o)].map(a=>a.toString(16).padStart(2,"0")).join("");return s.find(a=>a.token?.category===n&&a.token?.nft?.commitment===r)??null}async function bo(t,{wallet:e,name:n,records:o,feeRate:s=D.feeRate,onProgress:r=()=>{}}){r("resolving");let a=H(n),l=(await bt({client:t})).get(Q(a));if(!l)throw new Error(`"${Q(a)}" is not registered`);r("loading-coins");let c=await j(t,e.watchedAddresses),h=c.find(m=>m.token?.category===l.category&&m.token?.nft);if(!h)throw new Error(`this wallet does not hold the certificate for "${Q(a)}" \u2014 only the owner can change its records`);r("building");let u=Ut({name:n,ownerAddress:e.address,ownerTokenAddress:z(e.address),records:o,certificateUtxo:h,utxos:c.filter(m=>!m.token),beaconAddress:D.beacon,feeRate:s,addressToLockingBytecode:L});r("signing");let d=ht(u.transaction,u.sourceOutputs,m=>e.keyFor(m));r("broadcasting");let p=await st(t,d.hex);return r("updated",{txid:p}),{name:u.name,displayName:u.displayName,category:u.category,txid:p,records:o,costs:u.costs}}async function So(t,{session:e,name:n,records:o,feeRate:s=D.feeRate,onProgress:r=()=>{}}){r("resolving");let a=H(n),l=(await bt({client:t})).get(Q(a));if(!l)throw new Error(`"${Q(a)}" is not registered`);r("reading-wallet");let c=await e.getAddresses(),h=await j(t,c),u=h.find(f=>f.token?.category===l.category&&f.token?.nft);if(!u)throw new Error(`this wallet does not hold the certificate for "${Q(a)}" \u2014 only the owner can change its records`);r("building");let d=Ut({name:n,ownerAddress:u.address,ownerTokenAddress:z(u.address),records:o,certificateUtxo:u,utxos:h.filter(f=>!f.token),beaconAddress:D.beacon,feeRate:s,addressToLockingBytecode:L});r("awaiting-approval");let p=await e.signTransaction(d,{userPrompt:`Point ${d.displayName} somewhere new`}),m=await Bt(t,e,p,r);return r("updated",{txid:m}),{name:d.name,displayName:d.displayName,category:d.category,txid:m,records:o,costs:d.costs}}async function To(t,{wallet:e,tld:n,records:o,category:s,feeRate:r=D.feeRate,onProgress:a=()=>{}}){if(!s)throw new Error("setTldRecords requires the TLD certificate's category id");a("loading-coins");let i=await j(t,e.watchedAddresses),l=i.find(d=>d.token?.category===s&&d.token?.nft);if(!l)throw new Error(`this wallet does not hold the TLD certificate for ".${n}" \u2014 only the owner can change its policy`);a("building");let c=$e({tld:n,ownerAddress:e.address,ownerTokenAddress:z(e.address),records:o,certificateUtxo:l,utxos:i.filter(d=>!d.token),feeRate:r,addressToLockingBytecode:L});a("signing");let h=ht(c.transaction,c.sourceOutputs,d=>e.keyFor(d));a("broadcasting");let u=await st(t,h.hex);return a("updated",{txid:u}),{tld:c.tld,displayName:c.displayName,category:c.category,txid:u,records:o,costs:c.costs}}async function Eo(t,e){if(!e||e.v!==1&&e.v!==2)throw new Error("manifest.v must be 1 or 2");if(!e.name)throw new Error("manifest.name is required");if(typeof e.seq!="number"||e.seq<0)throw new Error("manifest.seq must be a non-negative integer");let n={...e};delete n.sig;let o=JSON.stringify(fe(n)),s=io.hash(ao(o)),r=t.signMessage(s);return{...e,sig:co(r)}}function fe(t){if(t!=null){if(Array.isArray(t))return t.map(fe).filter(e=>e!==void 0);if(typeof t=="object"){let e={};for(let n of Object.keys(t).sort()){let o=fe(t[n]);o!==void 0&&(e[n]=o)}return e}return t}}async function _o(t,e){let n=await j(t,e),o=n.filter(s=>!s.token);return{sats:o.reduce((s,r)=>s+r.satoshis,0n),confirmedSats:o.filter(s=>s.height>0).reduce((s,r)=>s+r.satoshis,0n),coins:o.length,certificates:n.filter(s=>s.token?.nft),hasGenesisInput:mt(n)}}import{hexToBin as Y,binToHex as tt,encodeDataPush as G,bigIntToVmNumber as Kt,hash256 as ge,hash160 as Oo,encodeLockingBytecodeP2sh32 as vo,encodeLockingBytecodeP2pkh as on,lockingBytecodeToCashAddress as Ao,OpcodesBCH as Bo,numberToBinUint32LE as Ms,binToNumberUint32LE as en,secp256k1 as sn,sha256 as Io,generateSigningSerializationBCH as Po,encodeTransaction as rn,flattenBinArray as Ot}from"@bitauth/libauth";var tn={contractName:"UsdListing",constructorInputs:[{name:"oraclePk",type:"pubkey"},{name:"sellerPkh",type:"bytes20"},{name:"targetCents",type:"int"},{name:"floorSats",type:"int"},{name:"ceilSats",type:"int"},{name:"maxAgeSecs",type:"int"}],abi:[{name:"buy",inputs:[{name:"oracleMsg",type:"bytes"},{name:"oracleSig",type:"datasig"}]},{name:"cancel",inputs:[{name:"pk",type:"pubkey"},{name:"s",type:"sig"}]}],bytecode:"OP_6 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP OP_7 OP_PICK OP_SIZE OP_NIP 28 OP_NUMEQUALVERIFY OP_8 OP_ROLL OP_8 OP_PICK OP_ROT OP_CHECKDATASIGVERIFY OP_6 OP_ROLL OP_4 OP_SPLIT OP_4 OP_SPLIT OP_ROT OP_BIN2NUM OP_ROT OP_BIN2NUM OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY OP_ROT OP_INPUTINDEX OP_OUTPOINTTXHASH OP_EQUALVERIFY OP_TXLOCKTIME 302a OP_ADD OP_2 OP_PICK OP_GREATERTHANOREQUAL OP_VERIFY OP_TXLOCKTIME OP_ROT OP_7 OP_ROLL OP_ADD OP_LESSTHANOREQUAL OP_VERIFY OP_ROT 00e1f505 OP_MUL OP_SWAP OP_DIV OP_DUP OP_3 OP_PICK OP_LESSTHAN OP_IF OP_2 OP_PICK OP_NIP OP_ENDIF OP_DUP OP_4 OP_PICK OP_GREATERTHAN OP_IF OP_3 OP_PICK OP_NIP OP_ENDIF OP_0 OP_OUTPUTBYTECODE 76a914 OP_3 OP_ROLL OP_CAT 88ac OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCOMMITMENT OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_EQUAL OP_NIP OP_NIP OP_NIP OP_ELSE OP_6 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_6 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_6 OP_ROLL OP_6 OP_ROLL OP_CHECKSIGVERIFY OP_2DROP OP_2DROP OP_DROP OP_1 OP_ENDIF",compiler:{name:"cashc",version:"0.13.3",options:{enforceFunctionParameterTypes:!0,enforceLocktimeGuard:!0}}};var No=2,me=1200,Ro=7200,Lo=t=>{let e=Bo[t];if(e===void 0)throw new Error("unknown opcode "+t);return Uint8Array.of(e)};function Do(t){let e=t.trim().split(/\s+/).filter(Boolean).map(n=>n.startsWith("OP_")?Lo(n):G(Y(n)));return Ot(e)}var Co=Do(tn.bytecode),Ht=t=>G(Kt(BigInt(t))),Uo=0,nn=1;function Fo(t){let e=Y(t);if(e.length!==25||e[0]!==118||e[1]!==169||e[2]!==20)throw new Error("seller must hold the certificate on a plain P2PKH address");return tt(e.slice(3,23))}function ye({oraclePk:t,sellerPkh:e,targetCents:n,floorSats:o,ceilSats:s,maxAgeSecs:r=me}){if(!(BigInt(n)>0n)||!(BigInt(o)>0n)||BigInt(s)<BigInt(o))throw new Error("bad listing terms");return Ot([Ht(r),Ht(s),Ht(o),Ht(n),G(Y(e)),G(Y(t)),Co])}var Wt=t=>vo(ge(t));function we(t,e=T.prefix){let n=Ao({bytecode:Wt(t),prefix:e});if(typeof n=="string")throw new Error(n);return n.address}function an({targetCents:t,priceCents:e,floorSats:n,ceilSats:o}){let s=BigInt(t)*100000000n/BigInt(e);return s<BigInt(n)&&(s=BigInt(n)),s>BigInt(o)&&(s=BigInt(o)),s}var cn=t=>({ts:en(t.slice(0,4)),priceCents:en(t.slice(4,8)),outpointTxid:tt(t.slice(8,40).slice().reverse())});function ln(t,e,n){return sn.verifySignatureSchnorr(n,t,Io.hash(e))===!0}var xe=(t,e,n,o,{requireGenesis:s=!1}={})=>{let r=M(t,e+600n,{requireGenesis:s});for(let a=0;a<6;a++){let{inputs:i,totalSats:l}=r,c=o(i,!0,1000000n),h=BigInt(Math.ceil(rn(c.transaction).length*n)),u=e+h;if(l<u){let m=M(t,u+200n,{requireGenesis:s});if(m.inputs.length>i.length){r=m;continue}let f=new Error(`not enough funds: need ${u} sat, have ${l} sat`);throw f.needSats=u,f.haveSats=l,f}let d=l-u,p=d>=W;return p||(d=0n),{...o(i,p,d),fee:p?h:l-e,change:d}}throw new Error("could not converge on a fee \u2014 please retry")};function $o({name:t,certificateUtxo:e,utxos:n,sellerAddress:o,oraclePk:s,targetCents:r,floorSats:a,ceilSats:i,maxAgeSecs:l=me,records:c={},beaconAddress:h=dt,feeRate:u=1,addressToLockingBytecode:d}){let p=H(t);if(!e?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let m=d(o),f=Fo(tt(d(e.address||o))),g=ye({oraclePk:s,sellerPkh:f,targetCents:r,floorSats:a,ceilSats:i,maxAgeSecs:l}),y=Wt(g),w=Z("UPD",p,c),x=n.filter(k=>!k.token),_=N+B-BigInt(e.satoshis);return{...xe(x,_>0n?_:0n,u,(k,O,I)=>({transaction:{version:2,locktime:0,inputs:[nt(e),...k.map(b=>nt(b))],outputs:[{lockingBytecode:y,valueSatoshis:N,token:it(e.token)},{lockingBytecode:et(w),valueSatoshis:0n},{lockingBytecode:d(h),valueSatoshis:B},...O?[{lockingBytecode:m,valueSatoshis:I}]:[]]},sourceOutputs:[at(e),...k.map(b=>at(b))]})),name:p,redeem:g,redeemHex:tt(g),address:we(g,o.split(":")[0]),sellerPkh:f,covenantVout:0}}function un(t){let e=Y(t.redeem_hex);return{redeem:e,utxo:{txid:t.outpoint.txid,vout:t.outpoint.vout,satoshis:BigInt(t.outpoint.satoshis??N),lockingBytecode:Wt(e),token:t.token}}}function Mo({listing:t,quote:e,buyerAddress:n,buyerTokenAddress:o,utxos:s,records:r={},beaconAddress:a=dt,feeRate:i=1,addressToLockingBytecode:l}){let c=H(t.name),h=Y(e.message),u=Y(e.signature);if(!ln(Y(t.oracle_pk),h,u))throw new Error("oracle signature does not verify against the listing's oracle key");let{ts:d,priceCents:p,outpointTxid:m}=cn(h);if(m!==String(t.outpoint.txid).toLowerCase())throw new Error("quote was issued for a different listing");let f=an({targetCents:t.target_cents,priceCents:p,floorSats:t.floor_sats,ceilSats:t.ceil_sats}),{redeem:g,utxo:y}=un(t),w=on(Y(t.seller_pkh)),x=Ot([G(u),G(h),G(Kt(BigInt(Uo))),G(g)]),_=l(n),S=l(o??n),k=Z("UPD",c,r),O=s.filter(R=>!R.token),I=f+N+B-y.satoshis;return{...xe(O,I,i,(R,A,v)=>({transaction:{version:2,locktime:Math.max(0,d-Ro),inputs:[nt(y,x),...R.map(E=>nt(E))],outputs:[{lockingBytecode:w,valueSatoshis:f},{lockingBytecode:S,valueSatoshis:N,token:it(y.token)},{lockingBytecode:et(k),valueSatoshis:0n},{lockingBytecode:l(a),valueSatoshis:B},...A?[{lockingBytecode:_,valueSatoshis:v}]:[]]},sourceOutputs:[at(y),...R.map(E=>at(E))]})),name:c,covenantInputIndex:0,priceSats:f,priceCents:p,quoteTs:d}}function Ho({listing:t,sellerAddress:e,sellerTokenAddress:n,utxos:o,records:s={},beaconAddress:r=dt,feeRate:a=1,addressToLockingBytecode:i,keyFor:l}){let c=H(t.name),{redeem:h,utxo:u}=un(t),d=on(Y(t.seller_pkh)),p=l(tt(d));if(!p)throw new Error("this wallet does not hold the seller key for this listing");let m=p.privateKey,f=p.publicKey,g=i(n??e),y=Z("UPD",c,s),w=o.filter(E=>!E.token),x=N+B-u.satoshis,_=Ot([G(new Uint8Array(65)),G(f),G(Kt(BigInt(nn))),G(h)]),S=xe(w,x>0n?x:0n,a,(E,C,P)=>({transaction:{version:2,locktime:0,inputs:[nt(u,_),...E.map(F=>nt(F))],outputs:[{lockingBytecode:g,valueSatoshis:N,token:it(u.token)},{lockingBytecode:et(y),valueSatoshis:0n},{lockingBytecode:i(r),valueSatoshis:B},...C?[{lockingBytecode:i(e),valueSatoshis:P}]:[]]},sourceOutputs:[at(u),...E.map(F=>at(F))]})),k=_t(S.transaction,S.sourceOutputs,l,{skip:[0]}),O=Po({inputIndex:0,sourceOutputs:S.sourceOutputs,transaction:k.transaction},{coveredBytecode:h,signingSerializationType:Uint8Array.of(Ft)}),I=sn.signMessageHashSchnorr(m,ge(O));if(typeof I=="string")throw new Error(I);let b=Ot([I,Uint8Array.of(Ft)]),R=Ot([G(b),G(f),G(Kt(BigInt(nn))),G(h)]),A={...k.transaction,inputs:k.transaction.inputs.map((E,C)=>C===0?{...E,unlockingBytecode:R}:E)},v=rn(A);return{name:c,transaction:A,sourceOutputs:S.sourceOutputs,hex:tt(v),txid:tt(ge(v).slice().reverse())}}function Ko(t,{oraclePk:e}={}){let n=o=>({ok:!1,error:o});try{if(t?.kind!=="usd"||t.v!==No)return n("not a v2 usd listing");for(let r of["name","seller","seller_pkh","category","target_cents","floor_sats","ceil_sats","max_age_secs","oracle_pk","redeem_hex","covenant_address","outpoint","token"])if(t[r]==null)return n("missing "+r);if(e&&t.oracle_pk!==e)return n("listing was made for a different oracle key");let o=ye({oraclePk:t.oracle_pk,sellerPkh:t.seller_pkh,targetCents:t.target_cents,floorSats:t.floor_sats,ceilSats:t.ceil_sats,maxAgeSecs:t.max_age_secs});if(tt(o)!==t.redeem_hex)return n("redeem script does not match the stated terms");let s=String(t.seller).split(":")[0]||T.prefix;return we(o,s)!==t.covenant_address?n("covenant address does not match"):tt(Oo(Y(t.seller_pkh))).length!==40?n("bad seller pkh"):t.token?.category!==t.category||!t.token?.nft?n("token does not match category"):Y(t.token.nft.commitment||"").length===0||tt(new TextEncoder().encode(H(t.name)))!==t.token.nft.commitment?n("commitment does not match the name"):{ok:!0,name:H(t.name),covenant_lock:tt(Wt(o))}}catch(o){return n(String(o?.message||o))}}import{hash160 as Wo,lockingBytecodeToCashAddress as Go,binToHex as js}from"@bitauth/libauth";function dn(t){return Uint8Array.from([118,169,20,...Wo(t),136,172])}function zo(t,e=T.prefix,n=!1){let o=Go({bytecode:dn(t),prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(`address encoding failed: ${o}`);return o.address}function qo(t){return t?{ready:!0,approvals:1,explanation:"Your wallet can mint the certificate directly."}:{ready:!1,approvals:2,explanation:"Your wallet needs one small setup transaction to itself before it can create a certificate \u2014 a rule of the Bitcoin Cash token system, not a fee we charge. You will be asked to approve it, then the registration. This happens only once."}}import{binToHex as lr,hexToBin as ur}from"@bitauth/libauth";import{stringify as hr}from"@bitauth/libauth";export{Jt as BuiltInWallet,Dn as CHIPNET_PREFIX,me as DEFAULT_MAX_AGE_SECS,Se as DEFAULT_NETWORK_ID,At as DEFAULT_PREFIX,J as InsufficientFundsError,Cn as MAINNET_PREFIX,T as NETWORK,kt as NETWORKS,Lt as NoGenesisInputError,D as REGISTRAR,ne as TLD_BEACON,L as addressToLockingBytecode,Wn as addressToScripthash,lr as binToHex,st as broadcast,fo as buildCosignRequest,bt as buildIndex,to as buildListing,Et as buildPrepTx,re as buildRegistrationTx,Ct as buildTldRegistrationTx,Ut as buildUpdateTx,Mo as buildUsdBuyTx,Ho as buildUsdCancelTx,$o as buildUsdListingTx,$t as checkAvailability,oo as completeSale,po as connect,qo as describeGenesisRequirement,Q as displayName,ko as findCertificateUtxo,Qe as findTldCertificateUtxo,Xe as findTldOwnerAddress,_o as getBalance,Pt as getNetwork,Ce as getUtxos,j as getUtxosForAddresses,mt as hasGenesisInput,ur as hexToBin,H as normalizeName,Tt as normalizeTld,cn as parseOracleMessage,oe as payloadBudget,an as payoutSats,Qn as priceSummary,zo as pubkeyToAddress,dn as pubkeyToLockingBytecode,Mt as quoteRegistration,yo as registerTldWithBuiltInWallet,wo as registerTldWithExternalWallet,mo as registerWithBuiltInWallet,xo as registerWithExternalWallet,zt as requireBeacons,An as resolveName,bo as setRecordsWithBuiltInWallet,So as setRecordsWithExternalWallet,To as setTldRecordsWithBuiltInWallet,go as signCosignRequest,_t as signInputs,Eo as signRecordsManifest,ht as signTransaction,pe as sourceOutputFromJson,he as sourceOutputToJson,Je as splitServiceFee,hr as stringify,z as toTokenAddress,Me as toWcTransactionObject,ae as txidOf,ce as txidOfHex,we as usdListingAddress,ye as usdListingRedeem,Ye as verifyListing,ln as verifyOracleMessage,Ko as verifyUsdListing};