The addendum gains a section stating the rule that was implemented and why the contest window and the commit's lifetime differ from the first specification. The run records a front-runner registering a name first and losing it to the older commit.
7 lines
80 KiB
JavaScript
7 lines
80 KiB
JavaScript
import{generateBip39Mnemonic as ko,deriveSeedFromBip39Mnemonic as en,deriveHdPrivateNodeFromSeed as So,deriveHdPath as To,secp256k1 as nn,hash160 as vo,encodeCashAddress as Qs,lockingBytecodeToCashAddress as Eo,cashAddressToLockingBytecode as Zs,binToHex as _o,hexToBin as tr,utf8ToBin as rn,binToBase64 as ae,base64ToBin as ce}from"@bitauth/libauth";var Et={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://dl.silentmode.st/bns-name-snapshot.json",nameListMirrorUrl:"https://navigate.st/bns/silentmode.bch/bns-name-snapshot.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,blocklists:[{name:"sirius-blocklist.x",beacon:"bchtest:qrrnwvuasq5fy63mdvp3umx5qfavtu7mnq950rdssw",scripthash:"fa14c5fd7a22bd1856b44168823a1ab3ff50961c917dafbcba749aeaa7b26646"}],commitReveal:{required:!1,minAge:1,maxAge:144,contestBlocks:6},covenant:{version:1,fundLock:"76a914b2e8b418849e8e3b34247864940a3429d92085fe88ac",steward:"02817a308db60d949f5a0543085f6757578dab169d4381934e997cbaef52c34c0d",blocksPerYear:52560,graceBlocks:26280,tiers:[{maxLabel:2,renewalSats:2e6,head:"011e0350cd0002a86604809698000400e1f5050380841e"},{maxLabel:4,renewalSats:5e5,head:"011e0350cd0002a86603a025260440787d010320a107"},{maxLabel:7,renewalSats:2e5,head:"011e0350cd0002a8660340420f048096980003400d03"},{maxLabel:255,renewalSats:1e5,head:"011e0350cd0002a8660320a10703404b4c03a08601"}],tail:"105279a97b887b7bad51b275827701209c2102817a308db60d949f5a0543085f6757578dab169d4381934e997cbaef52c34c0d1976a914b2e8b418849e8e3b34247864940a3429d92085fe88ac5b79009c635c79a95b79885d7a5d7aad5c7951a269597a815c79597a959376040065cd1d9f6901145a7a7e547e7c54807ec1011a7f777eaa00cd02aa207b7e01877e8800d1c0ce8800d2c0cf8800ccc0c6a26951cd8851cc537a597a95a26951d100886d6d6d7551675b79519c635e7a820114885d79a95c7a885d7a5d7aad01147c7e547e5a7a7ec1011a7f777eaa00cd02aa207b7e01877e8800d1c0ce8800d2c0cf8800ccc0c6a2696d6d6d6d6d51675b79529c635c7a820114885a7a8176b175c576040065cd1d9f697c597993587900709f635a795a795c79945479567994955d7996937b757c785e799501649677686079827701209dc0cf01117a7eaa011456797e01207e7c7e587a7e51c702aa207baa7e01877e8853795c7993040065cd1d9f690114557a7e547e547a5b7a9354807ec1011a7f777eaa00cd02aa207b7e01877e8800d1c0ce8800d2c0cf8800ccc0c6a26951cd547a8851cc7b527994a26951d100887600a06352cd0376a9145a797e0288ac7e8852cc78a26952d10088686d6d6d6d6d51675b79539c635c79a95b7a885c7a5c7aadc0cec454a16900d178879169c451a06351d17887916968c452a06352d17887916968c453a06353d178879169686d6d6d6d6d6d51675b7a549d5b79a95b79885c7a5c7aadc1011a7f77aa5c7a7c5d79aa7eaa537abb01145a7a7e547e597a7e597a7eaa00cd02aa207b7e01877e8800d1c0ce8800d2c0cf8800ccc0c6a2696d6d6d6d5168686868"}},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,blocklists:[],commitReveal:{required:!0,minAge:1,maxAge:144,contestBlocks:6},covenant:null}},Ye="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||Ye).trim().toLowerCase()}function rt(t){if(t&&typeof t=="object")return t;let e=t||Gn(),n=Et[e];if(!n)throw new Error(`unknown network "${e}" (known: ${Object.keys(Et).join(", ")})`);return n}var v=rt();function ee(t=v){let e=rt(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 Hs=v.beacon,Ks=v.beaconScripthash,Ws=v.tldBeacon,Gs=v.tldBeaconScripthash,js=v.electrum,qs=Et.chipnet.electrum,zs=v.electrumListName,He="BNS1";var Ve="bch",jn=/^[a-z0-9-]{1,32}$/,Xe=/^[a-z0-9-]{1,16}$/,ne=/^[a-z0-9-]{1,32}(\.[a-z0-9-]{1,16})?$/;function Ut(t){return t.includes(".")?t:t+"."+Ve}var Rt=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},Ht=t=>[...new TextEncoder().encode(t)].map(e=>e.toString(16).padStart(2,"0")).join("");function qn(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=Ve):(s=n[n.length-1],o=n[n.length-2]),!jn.test(o)||!Xe.test(s))throw new Error(`invalid name "${t}" (allowed: <label>.<tld>, [a-z0-9-])`);return`${o}.${s}`}var Ft=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{}}},zn=t=>typeof t=="string"?{url:t}:t;async function Mt(t,e,{directIP:n=!1}={}){let o;for(let s of t){let r=zn(s);try{return await new Ft(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 Ft(i,e,{servername:a.hostname}).connect()}catch(a){o=a}}throw o??new Error("no electrum server reachable")}function Yn(t){if(!t||!t.startsWith("6a"))return null;let e=Rt(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(He))return null;try{let r=JSON.parse(s.slice(He.length));if(!Vn.has(r.o))return null;if(r.o==="CMT")return typeof r.h=="string"&&/^[0-9a-f]{64}$/.test(r.h)?r:null;if(typeof r.n=="string"||r.o==="RPT"&&Array.isArray(r.n)&&r.n.every(a=>typeof a=="string"))return r}catch{}return null}function Kt(t){let e=null;for(let n of t||[]){let o=Yn(n&&n.scriptPubKey?n.scriptPubKey.hex:null);if(o){if(e)return null;e=o}}return e}var Vn=new Set(["REG","UPD","REL","TREG","TUPD","RPT","BLK","UBK","CMT"]);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 se(t,e){let n=new Set(t.map(i=>i.tx_hash)),o=new Map(t.map(i=>{let c=new Set;for(let l of e.get(i.tx_hash)?.vin??[])l.txid&&l.txid!==i.tx_hash&&n.has(l.txid)&&c.add(l.txid);return[i.tx_hash,c]})),s=new Set,r=[],a=[...t];for(;a.length;){let i=a.findIndex(l=>[...o.get(l.tx_hash)].every(p=>s.has(p)));i<0&&(i=0);let[c]=a.splice(i,1);s.add(c.tx_hash),r.push(c)}return r}function Je(t,e){let n=e&&e.tokenData;if(!n||!n.nft||typeof n.category!="string")return!1;let o=n.category;if(!(t.vin||[]).some(a=>a&&a.txid===o&&a.vout===0)||(t.vout||[]).filter(a=>a.tokenData&&a.tokenData.category===o).length!==1)return!1;let s=n.nft.capability;if(s!=null&&s!==""&&s!=="none")return!1;let r;try{r=BigInt(n.amount??0)}catch{return!1}return r===0n}function te(t){let e=t.lastIndexOf(".");return e<0?t:t.slice(e+1)}function Xn(t,e,n){let o=n.get(t);return o?o.regHeight>0&&e>0?o.regHeight<=e:!0:!1}async function re(t,e=v){let{tldBeaconScripthash:n}=ee(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 se(o.filter(c=>s.has(c.tx_hash)),s)){let c=s.get(a),l=c.vout||[],p=Kt(l);if(!p||typeof p.n!="string"||!Xe.test(p.n))continue;let d=p.n;if(p.o==="TREG"){if(r.has(d))continue;let f=Ht(d),u=l.find(g=>g.tokenData?.nft&&g.tokenData.nft.commitment===f);if(!u||!Je(c,u))continue;r.set(d,{category:u.tokenData.category,regHeight:i,regTxid:a,mintScriptHex:u.scriptPubKey?.hex??null,records:p.r??{},updates:[{height:i,txid:a,records:p.r??{}}]})}else if(p.o==="TUPD"){let f=r.get(d);if(!f||!l.some(u=>u.tokenData&&u.tokenData.category===f.category))continue;f.records=p.r??{},f.updates.push({height:i,txid:a,records:f.records})}}return r}function Jn(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 Qn(t,e){let n=Jn(t,e);return n.policy==="cosign"||n.hidden===1||n.hidden===!0||n.hidden==="1"}function Zn(t,e,n){let o=Ht(n);return(t||[]).some(s=>s.tokenData&&s.tokenData.category===e.category&&s.tokenData.nft&&s.tokenData.nft.commitment===o)}function Ke(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}function Qe(t,e){let n=t&&t.txid?e.get(t.txid):null;return!n||!Array.isArray(n.vout)?null:n.vout.find(o=>o&&o.n===t.vout)??n.vout[t.vout]??null}function to(t,e,n){return!t||!e||!e.category||(t.vout||[]).some(o=>o.tokenData&&o.tokenData.category===e.category)?!1:(t.vin||[]).some(o=>{let s=Qe(o,n);return!!(s&&s.tokenData&&s.tokenData.nft&&s.tokenData.category===e.category)})}function eo(t,e){return t===void 0?!0:t>0?!(e>0)||e>t:!1}function no(t,e,n){return Nt($t(Rt(t+Ht(e)+n)))}function oo({ordered:t,txs:e,network:n=v,keyOf:o=r=>r,admits:s}){let r=rt(n).commitReveal||{required:!1,minAge:1,maxAge:0,contestBlocks:0},a=new Map,i=new Map;for(let{tx_hash:u,height:g}of t){let h=e.get(u),m=h?Kt(h.vout):null;if(m){if(m.o==="CMT")a.has(m.h)||a.set(m.h,{height:g,txid:u,used:!1});else if(m.o==="REG"&&typeof m.n=="string"&&ne.test(m.n)){let y=o(m.n);i.has(y)||i.set(y,[]),i.get(y).push({tx_hash:u,height:g,payload:m,pos:i.get(y).length})}}}let c=1/0,l=u=>{let g=s(e.get(u.tx_hash),u.payload,u.height);if(!g)return null;let h=u.payload.s;if(h===void 0)return r.required?null:{r:u,mint:g,commit:null,rank:[u.height>0?u.height:c,u.tx_hash,u.pos]};if(typeof h!="string"||!/^[0-9a-f]{32}$/.test(h)||!g.scriptPubKey||typeof g.scriptPubKey.hex!="string")return null;let m=a.get(no(h,u.payload.n,g.scriptPubKey.hex));if(!m||m.used||!(m.height>0))return null;if(u.height>0){let y=u.height-m.height;if(y<r.minAge||y>r.maxAge)return null}return{r:u,mint:g,commit:m,rank:[m.height,m.txid,u.pos]}},p=(u,g)=>{for(let h=0;h<3;h++)if(u.rank[h]!==g.rank[h])return u.rank[h]<g.rank[h];return!1},d=new Map;function f(u,g){let h=i.get(g)||[],m=h.findIndex(w=>w.tx_hash===u);if(m<0)return null;let y=d.get(g);if(y&&y!==u)return null;let x=l(h[m]);if(!x)return y&&d.delete(g),null;if(!y){let w=(h[m].height>0?h[m].height:c)+r.contestBlocks,k=x;for(let T of h.slice(m+1)){if(!(T.height>0?T.height<=w:w===c))continue;let S=l(T);S&&p(S,k)&&(k=S)}if(k!==x)return d.set(g,k.r.tx_hash),null}return d.delete(g),x.commit&&(x.commit.used=!0),{mint:x.mint,commit:x.commit}}return{decide:f,commits:a,rules:r}}async function xt({network:t=v,electrum:e=rt(t).electrum,WebSocket:n,client:o,directIP:s=!1,enforceTld:r=!1,cosignGate:a=!0,height:i=null}={}){let c=ee(t),l=o??await Mt(e,n,{directIP:s});try{let p=null;if(r||a)try{p=await re(l,c)}catch(w){if(r)throw w;p=null}let d=null,f;if(typeof l.unionHistory=="function"){let w=await l.unionHistory(c.beaconScripthash);f=w.history,d={servers:w.servers,unreachable:w.unreachable,disagreements:w.disagreements}}else f=await l.call("blockchain.scripthash.get_history",[c.beaconScripthash]);f.sort(oe);let u=new Map;for(let{tx_hash:w}of f)try{u.set(w,await l.call("blockchain.transaction.get",[w,!0]))}catch{}let g=new Map,h=new Map,m=se(f.filter(w=>u.has(w.tx_hash)),u),y=oo({ordered:m,txs:u,network:c,keyOf:Ut,admits:(w,k,T)=>{let S=Ut(k.n);if(r&&!Xn(te(S),T,p))return null;if(a&&p){let b=p.get(te(S));if(b&&Qn(b,T)&&!Zn(w.vout||[],b,te(S)))return null}let I=Ht(k.n),O=(w.vout||[]).find(b=>b.tokenData?.nft&&b.tokenData.nft.commitment===I);return O&&Je(w,O)?O:null}});for(let{tx_hash:w,height:k}of m){let T=u.get(w),S=T.vout||[],I=Kt(S);if(!I)continue;let O=I.n;if(typeof O!="string"||!ne.test(O))continue;let b=Ut(O);if(I.o==="REG"){if(g.has(b)||!eo(h.get(b),k))continue;let E=y.decide(w,b);if(!E)continue;let B=E.mint;g.set(b,{name:b,category:B.tokenData.category,records:I.r??{},txid:w,height:k,updatedTxid:null,...E.commit?{commit:{height:E.commit.height,txid:E.commit.txid}}:{},owner:Ke(B)}),We(g.get(b),I,B,T,k,c),h.delete(b)}else if(I.o==="REL"){let E=g.get(b);if(!E||!to(T,E,u))continue;g.delete(b),h.set(b,k)}else if(I.o==="UPD"){let E=g.get(b);if(!E)continue;let B=S.find(_=>_.tokenData&&_.tokenData.category===E.category);if(!B||!We(E,I,B,T,k,c))continue;E.records=I.r??{},E.updatedTxid=w,E.covenant||(E.owner=Ke(B)??E.owner)}}let x=i;if(!(x>0))try{let w=await l.call("blockchain.headers.subscribe",[]);w&&w.height>0&&(x=w.height)}catch{}return go(g,Math.max(x>0?x:0,po(f)),c),d&&Object.defineProperty(g,"integrity",{value:d,enumerable:!1}),Object.defineProperty(g,"released",{value:h,enumerable:!1}),g}finally{o||l.close()}}var so=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),lt=(t,e)=>t>>>e|t<<32-e;function $t(t){let e=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),n=t.length,o=new Uint8Array(n+9+63>>6<<6);o.set(t),o[n]=128;let s=new DataView(o.buffer);s.setUint32(o.length-8,Math.floor(n*8/4294967296)),s.setUint32(o.length-4,n*8>>>0);let r=new Uint32Array(64);for(let c=0;c<o.length;c+=64){for(let y=0;y<16;y++)r[y]=s.getUint32(c+y*4);for(let y=16;y<64;y++){let x=lt(r[y-15],7)^lt(r[y-15],18)^r[y-15]>>>3,w=lt(r[y-2],17)^lt(r[y-2],19)^r[y-2]>>>10;r[y]=r[y-16]+x+r[y-7]+w|0}let l=e[0],p=e[1],d=e[2],f=e[3],u=e[4],g=e[5],h=e[6],m=e[7];for(let y=0;y<64;y++){let x=m+(lt(u,6)^lt(u,11)^lt(u,25))+(u&g^~u&h)+so[y]+r[y]|0,w=(lt(l,2)^lt(l,13)^lt(l,22))+(l&p^l&d^p&d)|0;m=h,h=g,g=u,u=f+x|0,f=d,d=p,p=l,l=x+w|0}e[0]+=l,e[1]+=p,e[2]+=d,e[3]+=f,e[4]+=u,e[5]+=g,e[6]+=h,e[7]+=m}let a=new Uint8Array(32),i=new DataView(a.buffer);for(let c=0;c<8;c++)i.setUint32(c*4,e[c]);return a}var Nt=t=>[...t].map(e=>e.toString(16).padStart(2,"0")).join(""),Ze="qpzry9x8gf2tvdw0s3jn54khce6mua7l";function tn(t){let e=[0x98f2bc8e61n,0x79b76d99e2n,0xf33e5fb3c4n,0xae2eabe2a8n,0x1e4f43e470n],n=1n;for(let o of t){let s=n>>35n;n=(n&0x07ffffffffn)<<5n^BigInt(o);for(let r=0;r<5;r++)s>>BigInt(r)&1n&&(n^=e[r])}return n^1n}function ie(t){let e=String(t).trim().toLowerCase(),n=e.indexOf(":");if(n<1)throw new Error(`address needs its network prefix: "${t}"`);let o=e.slice(0,n),s=[...e.slice(n+1)].map(f=>Ze.indexOf(f));if(s.length<9||s.some(f=>f<0))throw new Error(`not a cashaddr: "${t}"`);if(tn([...[...o].map(f=>f.charCodeAt(0)&31),0,...s])!==0n)throw new Error(`bad cashaddr checksum: "${t}"`);let r=[],a=0,i=0;for(let f of s.slice(0,-8))for(a=a<<5|f,i+=5;i>=8;)i-=8,r.push(a>>i&255);let c=r[0],l=c>>3&15,p=Nt(r.slice(1)),d=[20,24,28,32,40,48,56,64][c&7];if(p.length!==d*2)throw new Error(`cashaddr hash length mismatch: "${t}"`);if((l===0||l===2)&&d===20)return"76a914"+p+"88ac";if((l===1||l===3)&&d===20)return"a914"+p+"87";if((l===1||l===3)&&d===32)return"aa20"+p+"87";throw new Error(`unsupported address type: "${t}"`)}function ro(t){return Nt($t(Rt(ie(t))).reverse())}function io(t,e=v.prefix){let n=[],o=0,s=0;for(let i of[0,...Rt(t)])for(o=(o<<8|i)&4095,s+=8;s>=5;)s-=5,n.push(o>>s&31);s&&n.push(o<<5-s&31);let r=tn([...[...e].map(i=>i.charCodeAt(0)&31),0,...n,0,0,0,0,0,0,0,0]),a=[];for(let i=0;i<8;i++)a.push(Number(r>>BigInt(5*(7-i))&31n));return e+":"+[...n,...a].map(i=>Ze[i]).join("")}var ao=5e8;function co(t,e){let n=String(t).split(".")[0];return e.tiers.findIndex(o=>n.length<=o.maxLabel)}function lo(t,e,n,o){let s=o>>>0,r=[s&255,s>>>8&255,s>>>16&255,s>>>24&255],a="14"+n+"04"+Nt(r)+t.tiers[e].head+t.tail;return"aa20"+Nt($t($t(Rt(a))))+"87"}function uo(t,e,n,o=v){let s=rt(o).covenant,r=t?t.c:null;if(!s||!r||typeof r!="object"||!e||!e.scriptPubKey||typeof r.o!="string"||!/^[0-9a-f]{40}$/.test(r.o)||!Number.isInteger(r.e)||r.e<=0||r.e>=ao)return null;let a=co(n,s);return a<0||e.scriptPubKey.hex!==lo(s,a,r.o,r.e)?null:{ownerPkh:r.o,expiry:r.e,tier:a+1,version:s.version}}function fo(t,e,n,o=v){let s=rt(o).covenant;if(!s||!t||!(n>0))return!1;let r=0;for(let i of e.vout||[])i&&i.scriptPubKey&&i.scriptPubKey.hex===s.fundLock&&!i.tokenData&&(r+=Math.round(Number(i.value)*1e8));let a=Math.floor(r/s.tiers[t.tier-1].renewalSats);return a>=1&&t.expiry<=n+a*s.blocksPerYear}function We(t,e,n,o,s,r=v){let a=uo(e,n,t.name,r);if(t.covenant){if(!a)return!1}else if(!a||!fo(a,o,s,r))return!0;return t.covenant=a,t.owner=io(a.ownerPkh,rt(r).prefix),!0}function ho(t,e,n=v){let o=rt(n).covenant;if(!t||!o)return null;let s=t.expiry+o.graceBlocks;return{status:e<t.expiry?"active":e<s?"idle":"open",expiry:t.expiry,idleEnd:s}}function po(t){let e=0;for(let n of t||[])n&&n.height>e&&(e=n.height);return e}function go(t,e,n=v){for(let o of t.values()){let s=ho(o.covenant,e,n);s&&(o.status=s.status,o.expiry=s.expiry,o.idleEnd=s.idleEnd,s.status==="open"&&(o.lapsedRecords=o.records,o.records={}))}return Object.defineProperty(t,"height",{value:e,enumerable:!1,configurable:!0}),t}var Ge=new Set(["phishing","impersonation","malware","scam-financial","csam","stolen"]);function je(t,e,n){return(t.vin||[]).some(o=>{let s=Qe(o,n);return!!(s&&s.scriptPubKey&&s.scriptPubKey.hex===e)})}var mo=t=>typeof t=="string"&&/^[0-9a-f]{64}$/.test(t);function qe(t){return typeof t=="string"&&ne.test(t)?Ut(t):null}function yo({history:t,txs:e,address:n,source:o=null}){let s=ie(n),r=e instanceof Map?e:new Map(Object.entries(e||{})),a=se([...t||[]].filter(p=>r.has(p.tx_hash)).sort(oe),r),i=p=>Kt(p.vout),c=new Map;for(let{tx_hash:p,height:d}of a){let f=r.get(p),u=i(f);if(!u||u.o!=="RPT"||!je(f,s,r)||u.t!=="block"&&u.t!=="unblock")continue;let g=(u.n||[]).map(qe);!g.length||g.some(h=>!h)||u.t==="block"&&!Ge.has(u.r)||c.set(p,{type:u.t,names:new Set(g),reason:u.r??null,evidence:u.e??null,vote:u.v??null,height:d})}let l=new Map;for(let{tx_hash:p,height:d}of a){let f=r.get(p),u=i(f);if(!u||u.o!=="BLK"&&u.o!=="UBK"||!je(f,s,r))continue;let g=qe(u.n);if(!g||!mo(u.p))continue;let h=c.get(u.p);if(!(!h||!h.names.has(g)))if(u.o==="BLK"){if(h.type!=="block"||!Ge.has(u.r)||h.reason!==u.r)continue;l.set(g,{name:g,reason:u.r,reportTxid:u.p,txid:p,height:d,evidence:u.e??h.evidence,vote:h.vote,source:o,address:n})}else{if(h.type!=="unblock")continue;l.delete(g)}}return l}function ze(t,e){let n=t&&t.name&&e&&typeof e.get=="function"?e.get(t.name)?.records?.bl:null;if(typeof n=="string")try{return ie(n),n}catch{}return t?.beacon??null}async function xo({network:t=v,lists:e,index:n=null,electrum:o,WebSocket:s,client:r,directIP:a=!1}={}){let i=rt(t),c=e??i.blocklists??[],l=new Map;if(!c.length)return l;let p=o??i.electrum.filter(f=>!i.beaconOnly.test(typeof f=="string"?f:f.url)),d=r;if(!d)try{d=await Mt(p,s,{directIP:a})}catch(f){let u=new Set((i.blocklists||[]).map(g=>g.beacon));if(o||!c.every(g=>u.has(ze(g,n))))throw f;d=await Mt(i.electrum,s,{directIP:a})}try{for(let f of c){let u=ze(f,n);if(!u)continue;let g=ro(u),h=typeof d.unionHistory=="function"?(await d.unionHistory(g)).history:await d.call("blockchain.scripthash.get_history",[g]);if(!h||!h.length)continue;let m=new Map;for(let{tx_hash:y}of h)try{m.set(y,await d.call("blockchain.transaction.get",[y,!0]))}catch{}for(let[y,x]of yo({history:h,txs:m,address:u,source:f.name??u})){let w=l.get(y);w?w.sources.push(x):l.set(y,{...x,sources:[x]})}}return l}finally{r||d.close()}}function wo(t,e){let n=t&&e&&typeof e.get=="function"?e.get(t.name):null;return n?{...t,blocked:!0,blockReason:n.reason,blockReportTxid:n.reportTxid,blockedBy:n.source}:t}async function bo(t,e={}){let n=qn(t),o=rt(e.network),s=e.blocklists===void 0?o.blocklists??[]:e.blocklists||[];if(!s.length)return(await xt(e)).get(n)??null;let r=e.client??await Mt(e.electrum??o.electrum,e.WebSocket,{directIP:!!e.directIP});try{let a=await xt({...e,client:r}),i=a.get(n)??null;if(!i)return null;let c=null;try{c=await xo(e.client?{network:o,lists:s,index:a,client:e.client}:{network:o,lists:s,index:a,WebSocket:e.WebSocket,directIP:!!e.directIP})}catch{}return wo(i,c)}finally{e.client||r.close()}}var Ys=v.rootTldName,Vs=v.bootstrapTlds.slice();var Oo="bchtest",Ao="bitcoincash",Lt=v.prefix,le="m/44'/145'/0'",Bo=5,Wt="bns.wallet.v1";function an(t){let e=vo(t);return Uint8Array.from([118,169,20,...e,136,172])}function on(t,e,n){let o=Eo({bytecode:an(t),prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(`address encoding failed: ${o}`);return o.address}var ue=class t{constructor(e,n,o=Lt,s=le){this.mnemonic=e,this.prefix=o,this.accountPath=s,this._root=So(n),this._keys=new Map,this._derive()}static async create(e=Lt,n=le){let o=ko();return new t(o,await en(o),e,n)}static async fromMnemonic(e,n=Lt,o=le){let s=String(e).trim().toLowerCase().replace(/\s+/g," "),r=await en(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<Bo;o++){let s=`${this.accountPath}/${e}/${o}`,r=To(this._root,s);if(typeof r=="string")throw new Error(`HD derivation failed at ${s}: ${r}`);let a=nn.derivePublicKeyCompressed(r.privateKey);if(typeof a=="string")throw new Error(`pubkey derivation failed: ${a}`);let i=an(a),c={path:s,branch:e,index:o,privateKey:r.privateKey,publicKey:a,lockingBytecode:i,address:on(a,this.prefix,!1),tokenAddress:on(a,this.prefix,!0)};n.push(c),this._keys.set(_o(i),c)}}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(p=>p.address===o);if(!s)throw new Error(`no key for address ${o}`);let r=nn.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 c=31+i,l=new Uint8Array(65);return l[0]=c,l.set(a,1),l}async encrypt(e){let n=crypto.getRandomValues(new Uint8Array(16)),o=crypto.getRandomValues(new Uint8Array(12)),s=await sn(e,n),r=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:o},s,rn(this.mnemonic)));return JSON.stringify({v:1,kdf:"PBKDF2-SHA256",iterations:de,prefix:this.prefix,salt:ae(n),iv:ae(o),ct:ae(r)})}static async decrypt(e,n){let o=typeof e=="string"?JSON.parse(e):e,s=await sn(n,ce(o.salt),o.iterations??de),r;try{r=await crypto.subtle.decrypt({name:"AES-GCM",iv:ce(o.iv)},s,ce(o.ct))}catch{throw new Error("wrong password")}return t.fromMnemonic(new TextDecoder().decode(r),o.prefix??Lt)}async save(e,n=globalThis.localStorage){n.setItem(Wt,await this.encrypt(e))}static async load(e,n=globalThis.localStorage){let o=n.getItem(Wt);return o?t.decrypt(o,e):null}static exists(e=globalThis.localStorage){return!!e?.getItem(Wt)}static forget(e=globalThis.localStorage){e.removeItem(Wt)}},de=25e4;async function sn(t,e,n=de){let o=await crypto.subtle.importKey("raw",rn(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 sr=Et.chipnet.electrum.map(t=>t.url),Gt=v.electrum.map(t=>t.url),fe=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 cn(t=Gt,e){let n=[];for(let o of t)try{return await new fe(o,e).connect()}catch(s){n.push(`${o}: ${s?.message??s}`)}throw Io(t.length,n)}function Io(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 Po,lockingBytecodeToCashAddress as No,sha256 as Ro,hash160 as ar,binToHex as Lo,hexToBin as cr}from"@bitauth/libauth";function ln(t){return Lo(Ro.hash(t).slice().reverse())}function R(t){let e=Po(t);if(typeof e=="string")throw new Error(`bad address "${t}": ${e}`);return e.bytecode}function Co(t){return ln(R(t))}function q(t){let e=R(t),n=String(t).includes(":")?t.split(":")[0]:v.prefix,o=No({bytecode:e,prefix:n,tokenSupport:!0});if(typeof o=="string")throw new Error(`cannot token-encode "${t}": ${o}`);return o.address}async function un(t,e){let n=R(e),o=ln(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 K(t,e){let n=[];for(let o of e)n.push(...await un(t,o));return n}async function J(t,e){return t.call("blockchain.transaction.broadcast",[e])}async function he(t,e,n=!0){return t.call("blockchain.transaction.get",[e,n])}import{binToHex as kt,hexToBin as Y,utf8ToBin as ut,binToUtf8 as ye,encodeTransaction as Do,decodeTransaction as fr,sha256 as Uo}from"@bitauth/libauth";var dn="BNS1",dt=v.beacon,xe=v.tldBeacon,A=600n,C=1000n,M=546n,pe="bch",ge=200,Fo=/^[a-z0-9-]{1,32}$/,fn=/^[a-z0-9-]{1,16}$/;function Ot(t){let e=String(t).toLowerCase().trim().replace(/^\.+/,"").replace(/\.+$/,"");if(!fn.test(e))throw new Error(`invalid TLD "${t}" (allowed: [a-z0-9-]{1,16})`);return e}var jt=class extends Error{constructor(e){super(e),this.name="NoGenesisInputError",this.code="NO_GENESIS_INPUT"}},V=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 D(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=pe):(o=e[e.length-1],n=e[e.length-2]),!Fo.test(n)||!fn.test(o))throw new Error(`invalid name "${t}" (allowed: <label>.<tld>, [a-z0-9-])`);return o===pe?n:`${n}.${o}`}function z(t){return t.includes(".")?t:`${t}.${pe}`}function Q(t,e,n,o=null,s=null){let r=JSON.stringify({o:t,n:e,r:n??{},...o?{c:o}:{},...s?{s}:{}}),a=ut(dn+r);if(a.length>ge)throw new Error(`records too large (${a.length} > ${ge} bytes)`);return a}function we(t,e="REG"){return ge-Q(e,t,{}).length}var _t=16;function be(){return crypto.getRandomValues(new Uint8Array(_t))}var me=t=>t instanceof Uint8Array?t:Y(t);function ke(t,e,n){let o=me(t);if(o.length!==_t)throw new Error(`the registration salt must be exactly ${_t} bytes`);let s=ut(D(e)),r=me(n),a=new Uint8Array(o.length+s.length+r.length);return a.set(o),a.set(s,o.length),a.set(r,o.length+s.length),Uo.hash(a)}function Mo(t){let e=typeof t=="string"?t:kt(t);if(!/^[0-9a-f]{64}$/.test(e))throw new Error("a commitment is 32 bytes");return ut(dn+JSON.stringify({o:"CMT",h:e}))}function $o(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 Z(t){return Uint8Array.from([106,...$o(t)])}function Se(){return Uint8Array.from([65,...new Uint8Array(65),33,...new Uint8Array(33)])}var Ho=t=>!t.token;function F(t,e,{requireGenesis:n=!0}={}){let o=t.filter(Ho),s=[],r=0n;if(n){let i=o.filter(c=>c.vout===0).sort((c,l)=>l.satoshis>c.satoshis?1:-1);if(i.length===0)throw new jt("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(c=>c.txid===i.txid&&c.vout===i.vout)).sort((i,c)=>c.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 ht(t){return{outpointTransactionHash:Y(t.txid),outpointIndex:t.vout,sequenceNumber:4294967294,unlockingBytecode:Se()}}function wt(t){return{...ht(t),lockingBytecode:t.lockingBytecode,valueSatoshis:t.satoshis,...t.token?{token:{amount:t.token.amount??0n,category:Y(t.token.category),...t.token.nft?{nft:{capability:t.token.nft.capability,commitment:Y(t.token.nft.commitment||"")}}:{}}}:{}}}function it(t){return Do(t).length}function Te({name:t,ownerAddress:e,ownerTokenAddress:n,changeAddress:o,records:s={},utxos:r,feeAddress:a=null,feeSats:i=0n,tldFeeAddress:c=null,tldFeeSats:l=0n,beaconAddress:p=dt,feeRate:d=1,addressToLockingBytecode:f,cosignUtxo:u=null,cosignTokenAddress:g=null,salt:h=null}){if(typeof f!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let m=D(t),y=h?kt(me(h)):null;if(y&&y.length!==_t*2)throw new Error(`the registration salt must be exactly ${_t} bytes`);let x=Q("REG",m,s,null,y),w=BigInt(i??0n),k=BigInt(l??0n);if(u&&!u.token?.nft)throw new Error("cosignUtxo does not carry a TLD certificate");let T=u?BigInt(u.satoshis):0n,S=u?f(g??n??e):null;if(w>0n&&!a)throw new Error("feeSats set but feeAddress missing");if(k>0n&&!c)throw new Error("tldFeeSats set but tldFeeAddress missing");let I=f(o??e),O=f(n??e),b=f(p),E=w>0n?f(a):null,B=k>0n?f(c):null,_=C+A+w+k+T,P=F(r,_+300n-T),U=0n,N=0n,H=!0;for(let G=0;G<6;G++){let{inputs:X}=P,nt=u?[...X,u]:X,j=P.totalSats+T,ot=nt[0],$e=Y(ot.txid),Zt=(Tt,vt)=>{let st=[];return Tt&&st.push({lockingBytecode:I,valueSatoshis:vt}),st.push({lockingBytecode:O,valueSatoshis:C,token:{amount:0n,category:$e,nft:{capability:"none",commitment:ut(m)}}}),st.push({lockingBytecode:Z(x),valueSatoshis:0n}),st.push({lockingBytecode:b,valueSatoshis:A}),B&&st.push({lockingBytecode:B,valueSatoshis:k}),E&&st.push({lockingBytecode:E,valueSatoshis:w}),u&&st.push({lockingBytecode:S,valueSatoshis:T,token:{amount:BigInt(u.token.amount??0),category:Y(u.token.category),nft:{capability:u.token.nft.capability,commitment:Y(u.token.nft.commitment||"")}}}),{version:2,locktime:0,inputs:nt.map(ht),outputs:st}},Hn=Zt(!0,1000000n),Kn=it(Hn);U=BigInt(Math.ceil(Kn*d));let Pt=_+U;if(j<Pt){let Tt=F(r,Pt+200n-T);if(Tt.inputs.length>X.length){P=Tt;continue}throw new V(`not enough funds: need ${Pt} sat, have ${j} sat`,{needSats:Pt,haveSats:j})}if(N=j-Pt,H=N>=M,!H){let Tt=Zt(!1,0n);U=j-_;let vt=BigInt(Math.ceil(it(Tt)*d));if(U<vt){let st=F(r,_+vt+M+200n-T);if(st.inputs.length>X.length){P=st;continue}throw new V(`not enough funds: need ${_+vt} sat, have ${j} sat`,{needSats:_+vt,haveSats:j})}N=0n}let Wn=Zt(H,N),yt={},bt=0;return H&&(yt.change=bt++),yt.certificate=bt++,yt.opReturn=bt++,yt.beacon=bt++,B&&(yt.tldOwnerFee=bt++),E&&(yt.serviceFee=bt++),u&&(yt.cosignCertificate=bt++),{name:m,displayName:z(m),category:kt($e),transaction:Wn,sourceOutputs:nt.map(wt),inputUtxos:nt,outputMap:yt,payload:x,costs:{certificateDustSats:C,beaconDustSats:A,serviceFeeSats:w,tldOwnerFeeSats:k,chainFeeSats:U,changeSats:N,totalInputSats:j,netCostSats:w+k+U+A}}}throw new Error("could not converge on a fee \u2014 please retry")}function ve({commitment:t,utxos:e,changeAddress:n,beaconAddress:o=dt,feeRate:s=1,addressToLockingBytecode:r}){if(typeof r!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let a=Mo(t),i=r(n),c=r(o),l=F(e,A+M+400n,{requireGenesis:!1});for(let p=0;p<6;p++){let{inputs:d,totalSats:f}=l,u=y=>({version:2,locktime:0,inputs:d.map(ht),outputs:[{lockingBytecode:i,valueSatoshis:y},{lockingBytecode:Z(a),valueSatoshis:0n},{lockingBytecode:c,valueSatoshis:A}]}),g=BigInt(Math.ceil(it(u(1000000n))*s)),h=A+g+M;if(f<h){let y=F(e,h+200n,{requireGenesis:!1});if(y.inputs.length>d.length){l=y;continue}throw new V(`not enough funds: need ${h} sat, have ${f} sat`,{needSats:h,haveSats:f})}let m=f-A-g;return{transaction:u(m),sourceOutputs:d.map(wt),inputUtxos:d,outputMap:{change:0,opReturn:1,beacon:2},payload:a,costs:{beaconDustSats:A,chainFeeSats:g,changeSats:m,netCostSats:A+g}}}throw new Error("could not converge on a fee \u2014 please retry")}function qt({tld:t,ownerAddress:e,ownerTokenAddress:n,changeAddress:o,records:s={},utxos:r,feeAddress:a=null,feeSats:i=0n,beaconAddress:c=xe,feeRate:l=1,addressToLockingBytecode:p}){if(typeof p!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let d=Ot(t),f=Q("TREG",d,s),u=BigInt(i??0n);if(u>0n&&!a)throw new Error("feeSats set but feeAddress missing");let g=p(o??e),h=p(n??e),m=p(c),y=u>0n?p(a):null,x=C+A+u,w=F(r,x+300n),k=0n,T=0n,S=!0;for(let I=0;I<6;I++){let{inputs:O,totalSats:b}=w,E=O[0],B=Y(E.txid),_=(nt,j)=>{let ot=[];return nt&&ot.push({lockingBytecode:g,valueSatoshis:j}),ot.push({lockingBytecode:h,valueSatoshis:C,token:{amount:0n,category:B,nft:{capability:"none",commitment:ut(d)}}}),ot.push({lockingBytecode:Z(f),valueSatoshis:0n}),ot.push({lockingBytecode:m,valueSatoshis:A}),y&&ot.push({lockingBytecode:y,valueSatoshis:u}),{version:2,locktime:0,inputs:O.map(ht),outputs:ot}},P=_(!0,1000000n),U=it(P);k=BigInt(Math.ceil(U*l));let N=x+k;if(b<N){let nt=F(r,N+200n);if(nt.inputs.length>O.length){w=nt;continue}throw new V(`not enough funds: need ${N} sat, have ${b} sat`,{needSats:N,haveSats:b})}if(T=b-N,S=T>=M,!S){let nt=_(!1,0n);k=b-x;let j=BigInt(Math.ceil(it(nt)*l));if(k<j){let ot=F(r,x+j+M+200n);if(ot.inputs.length>O.length){w=ot;continue}throw new V(`not enough funds: need ${x+j} sat, have ${b} sat`,{needSats:x+j,haveSats:b})}T=0n}let H=_(S,T),G={},X=0;return S&&(G.change=X++),G.certificate=X++,G.opReturn=X++,G.beacon=X++,y&&(G.serviceFee=X++),{tld:d,category:kt(B),transaction:H,sourceOutputs:O.map(wt),inputUtxos:O,outputMap:G,payload:f,costs:{certificateDustSats:C,beaconDustSats:A,serviceFeeSats:u,chainFeeSats:k,changeSats:T,totalInputSats:b,netCostSats:u+k+A}}}throw new Error("could not converge on a fee \u2014 please retry")}function Ct({name:t,ownerAddress:e,ownerTokenAddress:n,records:o={},certificateUtxo:s,utxos:r,beaconAddress:a=dt,feeRate:i=1,addressToLockingBytecode:c}){if(typeof c!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let l=D(t);if(!s?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let p=kt(ut(l));if(s.token.nft.commitment!==p)throw new Error(`certificate commitment mismatch: holds "${ye(Y(s.token.nft.commitment))}", asked to update "${l}"`);let d=Q("UPD",l,o),f=c(e),u=c(n??e),g=c(a),h=C+A,m=F(r,h+400n,{requireGenesis:!1}),y=0n,x=0n,w=!0;for(let k=0;k<6;k++){let T=[s,...m.inputs],S=s.satoshis+m.totalSats,I=(P,U)=>{let N=[];return P&&N.push({lockingBytecode:f,valueSatoshis:U}),N.push({lockingBytecode:u,valueSatoshis:C,token:{amount:0n,category:Y(s.token.category),nft:{capability:"none",commitment:ut(l)}}}),N.push({lockingBytecode:Z(d),valueSatoshis:0n}),N.push({lockingBytecode:g,valueSatoshis:A}),{version:2,locktime:0,inputs:T.map(ht),outputs:N}},O=it(I(!0,1000000n));y=BigInt(Math.ceil(O*i));let b=h+y;if(S<b){let P=F(r,b+200n,{requireGenesis:!1});if(P.inputs.length>m.inputs.length){m=P;continue}throw new V(`not enough funds: need ${b} sat, have ${S} sat`,{needSats:b,haveSats:S})}x=S-b,w=x>=M,w||(y=S-h,x=0n);let E=I(w,x),B={},_=0;return w&&(B.change=_++),B.certificate=_++,B.opReturn=_++,B.beacon=_++,{name:l,displayName:z(l),category:s.token.category,transaction:E,sourceOutputs:T.map(wt),inputUtxos:T,outputMap:B,payload:d,costs:{certificateDustSats:C,beaconDustSats:A,serviceFeeSats:0n,chainFeeSats:y,changeSats:x,totalInputSats:S,netCostSats:y+A}}}throw new Error("could not converge on a fee \u2014 please retry")}function Ee({name:t,ownerAddress:e,certificateUtxo:n,utxos:o=[],beaconAddress:s=dt,feeRate:r=1,addressToLockingBytecode:a}){if(typeof a!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let i=D(t);if(!n?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let c=kt(ut(i));if(n.token.nft.commitment!==c)throw new Error(`certificate commitment mismatch: holds "${ye(Y(n.token.nft.commitment))}", asked to release "${i}"`);let l=Q("REL",i,{}),p=a(e),d=a(s),f=A,u={inputs:[],totalSats:0n},g=0n,h=0n,m=!0;for(let y=0;y<6;y++){let x=[n,...u.inputs],w=n.satoshis+u.totalSats,k=(E,B)=>{let _=[];return E&&_.push({lockingBytecode:p,valueSatoshis:B}),_.push({lockingBytecode:Z(l),valueSatoshis:0n}),_.push({lockingBytecode:d,valueSatoshis:A}),{version:2,locktime:0,inputs:x.map(ht),outputs:_}},T=BigInt(Math.ceil(it(k(!1,0n))*r)),S=BigInt(Math.ceil(it(k(!0,1000000n))*r));if(w<f+T){let E=F(o,f+S+200n,{requireGenesis:!1});if(E.inputs.length>u.inputs.length){u=E;continue}throw new V(`not enough funds: need ${f+T} sat, have ${w} sat`,{needSats:f+T,haveSats:w})}h=w-f-S,m=h>=M,m?g=S:(g=w-f,h=0n);let I=k(m,h),O={},b=0;return m&&(O.change=b++),O.opReturn=b++,O.beacon=b++,{name:i,displayName:z(i),category:n.token.category,transaction:I,sourceOutputs:x.map(wt),inputUtxos:x,outputMap:O,payload:l,costs:{beaconDustSats:A,chainFeeSats:g,changeSats:h,totalInputSats:w,netCostSats:g+A}}}throw new Error("could not converge on a fee \u2014 please retry")}function hn({tld:t,ownerAddress:e,ownerTokenAddress:n,records:o={},certificateUtxo:s,utxos:r,beaconAddress:a=xe,feeRate:i=1,addressToLockingBytecode:c}){if(typeof c!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let l=Ot(t);if(!s?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let p=kt(ut(l));if(s.token.nft.commitment!==p)throw new Error(`TLD certificate commitment mismatch: holds "${ye(Y(s.token.nft.commitment))}", asked to update ".${l}"`);let d=Q("TUPD",l,o),f=c(e),u=c(n??e),g=c(a),h=C+A,m=F(r,h+400n,{requireGenesis:!1}),y=0n,x=0n,w=!0;for(let k=0;k<6;k++){let T=[s,...m.inputs],S=s.satoshis+m.totalSats,I=(P,U)=>{let N=[];return P&&N.push({lockingBytecode:f,valueSatoshis:U}),N.push({lockingBytecode:u,valueSatoshis:C,token:{amount:0n,category:Y(s.token.category),nft:{capability:"none",commitment:ut(l)}}}),N.push({lockingBytecode:Z(d),valueSatoshis:0n}),N.push({lockingBytecode:g,valueSatoshis:A}),{version:2,locktime:0,inputs:T.map(ht),outputs:N}},O=it(I(!0,1000000n));y=BigInt(Math.ceil(O*i));let b=h+y;if(S<b){let P=F(r,b+200n,{requireGenesis:!1});if(P.inputs.length>m.inputs.length){m=P;continue}throw new V(`not enough funds: need ${b} sat, have ${S} sat`,{needSats:b,haveSats:S})}x=S-b,w=x>=M,w||(y=S-h,x=0n);let E=I(w,x),B={},_=0;return w&&(B.change=_++),B.certificate=_++,B.opReturn=_++,B.beacon=_++,{tld:l,displayName:`.${l}`,category:s.token.category,transaction:E,sourceOutputs:T.map(wt),inputUtxos:T,outputMap:B,payload:d,costs:{certificateDustSats:C,beaconDustSats:A,serviceFeeSats:0n,chainFeeSats:y,changeSats:x,totalInputSats:S,netCostSats:y+A}}}throw new Error("could not converge on a fee \u2014 please retry")}function At({ownerAddress:t,utxos:e,amountSats:n=10000n,feeRate:o=1,addressToLockingBytecode:s}){let r=s(t),a=F(e,n+400n,{requireGenesis:!1});if(a.inputs.length===0)throw new V("wallet is empty");for(let i=0;i<6;i++){let{inputs:c,totalSats:l}=a,p=(g,h)=>({version:2,locktime:0,inputs:c.map(ht),outputs:[{lockingBytecode:r,valueSatoshis:n},...g?[{lockingBytecode:r,valueSatoshis:h}]:[]]}),d=BigInt(Math.ceil(it(p(!0,1000000n))*o));if(l<n+d){let g=BigInt(Math.ceil(it(p(!1,0n))*o));if(l<=g+M)throw new V(`not enough funds to prepare the wallet: have ${l} sat`,{needSats:g+M,haveSats:l});return{transaction:{version:2,locktime:0,inputs:c.map(ht),outputs:[{lockingBytecode:r,valueSatoshis:l-g}]},sourceOutputs:c.map(wt),inputUtxos:c,costs:{chainFeeSats:g}}}let f=l-n-d,u=f>=M;return{transaction:p(u,f),sourceOutputs:c.map(wt),inputUtxos:c,costs:{chainFeeSats:u?d:l-n}}}throw new Error("could not converge on a fee \u2014 please retry")}function St(t){return t.some(e=>e.vout===0&&!e.token)}function pn({transaction:t,sourceOutputs:e},{broadcast:n=!0,userPrompt:o}={}){return{transaction:t,sourceOutputs:e,broadcast:n,...o?{userPrompt:o}:{}}}import{generateSigningSerializationBCH as Ko,hash256 as mn,secp256k1 as Wo,encodeTransaction as Go,binToHex as _e}from"@bitauth/libauth";var gn=65;function at(t,e,n){let o={...t,inputs:t.inputs.map((r,a)=>{let i=e[a],c=n(_e(i.lockingBytecode));if(!c)throw new Error(`no key for input ${a} \u2014 cannot sign`);let l=Ko({inputIndex:a,sourceOutputs:e,transaction:t},{coveredBytecode:i.lockingBytecode,signingSerializationType:Uint8Array.of(gn)}),p=mn(l),d=Wo.signMessageHashSchnorr(c.privateKey,p);if(typeof d=="string")throw new Error(`signing failed on input ${a}: ${d}`);let f=Uint8Array.from([...d,gn]);return{...r,unlockingBytecode:Uint8Array.from([f.length,...f,c.publicKey.length,...c.publicKey])}})},s=Go(o);return{transaction:o,hex:_e(s),txid:Oe(s)}}function Oe(t){return _e(mn(t).slice().reverse())}function Ae(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 Oe(e)}var L={network:v.id,addressPrefix:v.prefix,explorerTx:v.explorerTx,selfHosted:null,get electrum(){return this.selfHosted?[this.selfHosted,...Gt]:Gt},beacon:v.beacon,tldBeacon:v.tldBeacon,serviceFee:{address:v.operatorAddress,sats:10000n},feeRate:1,wizardConnect:{dappName:"Silent Mode",dappIcon:"https://silentmode.st/icon.png"},faucets:v.faucets};function jo(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 Tn,binToHex as tt,decodeTransaction as Jo,lockingBytecodeToCashAddress as Qo,sha256 as Zo,utf8ToBin as ts,binToBase64 as es}from"@bitauth/libauth";import{encodeTransaction as Ie,decodeTransaction as yn,generateSigningSerializationBCH as xn,hash256 as Pe,hash160 as qo,secp256k1 as wn,hexToBin as pt,binToHex as $,utf8ToBin as bn}from"@bitauth/libauth";var zt=65,Be=195,ft=(t,e)=>({outpointTransactionHash:pt(t.txid),outpointIndex:t.vout,sequenceNumber:4294967294,unlockingBytecode:e??Se()}),gt=t=>t?{amount:BigInt(t.amount??0),category:pt(t.category),...t.nft?{nft:{capability:t.nft.capability,commitment:pt(t.nft.commitment||"")}}:{}}:void 0,Ne=t=>({lockingBytecode:t.lockingBytecode instanceof Uint8Array?$(t.lockingBytecode):String(t.lockingBytecode),valueSatoshis:String(t.valueSatoshis),...t.token?{token:{category:t.token.category instanceof Uint8Array?$(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?$(t.token.nft.commitment):String(t.token.nft.commitment||"")}}:{}}}:{}}),Re=t=>({lockingBytecode:pt(t.lockingBytecode),valueSatoshis:BigInt(t.valueSatoshis??t.satoshis),...t.token?{token:gt(t.token)}:{}}),mt=(t,e)=>({...ft(t,e),lockingBytecode:t.lockingBytecode instanceof Uint8Array?t.lockingBytecode:pt(t.lockingBytecode),valueSatoshis:BigInt(t.satoshis),...t.token?{token:gt(t.token)}:{}});function kn(t,e,n,o,s){let r=e[n],a=xn({inputIndex:n,sourceOutputs:e,transaction:t},{coveredBytecode:r.lockingBytecode,signingSerializationType:Uint8Array.of(s)}),i=Pe(a),c=wn.signMessageHashSchnorr(o.privateKey,i);if(typeof c=="string")throw new Error(`signing failed on input ${n}: ${c}`);let l=Uint8Array.from([...c,s]);return Uint8Array.from([l.length,...l,o.publicKey.length,...o.publicKey])}function Bt(t,e,n,{sighash:o=zt,skip:s=[]}={}){let r={...t,inputs:t.inputs.map((i,c)=>{if(s.includes(c))return i;let l=n($(e[c].lockingBytecode));return l?{...i,unlockingBytecode:kn(t,e,c,l,o)}:i})},a=Ie(r);return{transaction:r,hex:$(a),txid:$(Pe(a).slice().reverse())}}function zo({name:t,certificateUtxo:e,priceSats:n,sellerAddress:o,addressToLockingBytecode:s,keyFor:r}){let a=D(t),i=BigInt(n);if(i<M)throw new Error(`price must be at least ${M} sat`);if(!e?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");if(e.token.nft.commitment!==$(bn(a)))throw new Error("certificate commitment does not match the name");let c=s(o),l=mt(e),p={version:2,locktime:0,inputs:[ft(e)],outputs:[{lockingBytecode:c,valueSatoshis:i}]},d=r($(l.lockingBytecode));if(!d)throw new Error("this wallet does not hold the key for the certificate");return p.inputs[0].unlockingBytecode=kn(p,[l],0,d,Be),{v:1,name:a,seller:o,price_sats:i.toString(),category:e.token.category,partial_tx:$(Ie(p)),source_output:{txid:e.txid,vout:e.vout,satoshis:BigInt(e.satoshis).toString(),lockingBytecode:$(l.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 Yo(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 Vo=t=>Uint8Array.from([118,169,20,...qo(t),136,172]);function Sn(t,e={}){let n=o=>({ok:!1,error:o});try{if(!t||t.v!==1)return n("unsupported listing version");let o=D(t.name),s=yn(pt(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($(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!==$(bn(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<M)return n("price below dust");if(BigInt(t.price_sats)!==a)return n("price_sats does not match output 0");let{sig:i,pubkey:c}=Yo(s.inputs[0].unlockingBytecode);if(i.length!==65||i[64]!==Be)return n("input 0 is not signed SINGLE|ANYONECANPAY");let l=pt(r.lockingBytecode);if($(Vo(c))!==$(l))return n("public key does not own the certificate output");if(e.ownerLockingBytecode&&$(l)!==e.ownerLockingBytecode)return n("certificate is not held by the current owner");if($(s.outputs[0].lockingBytecode)!==$(l))return n("payment does not go to the certificate holder");let p={...s.inputs[0],lockingBytecode:l,valueSatoshis:BigInt(r.satoshis),token:gt(r.token)},d=xn({inputIndex:0,sourceOutputs:[p],transaction:s},{coveredBytecode:l,signingSerializationType:Uint8Array.of(Be)});return wn.verifySignatureSchnorr(i.slice(0,64),c,Pe(d))?{ok:!0,name:o,price_sats:a,seller_lock:$(l),category:r.token.category}:n("seller signature is invalid")}catch(o){return n(String(o?.message||o))}}function Xo({listing:t,buyerAddress:e,buyerTokenAddress:n,utxos:o,records:s={},beaconAddress:r=dt,feeRate:a=1,addressToLockingBytecode:i}){let c=Sn(t);if(!c.ok)throw new Error("bad listing: "+c.error);let l=c.name,p=yn(pt(t.partial_tx)),d=t.source_output,f=p.inputs[0],u={...f,lockingBytecode:pt(d.lockingBytecode),valueSatoshis:BigInt(d.satoshis),token:gt(d.token)},g=p.outputs[0],h=g.valueSatoshis,m=i(e),y=i(n??e),x=i(r),w=Q("UPD",l,s),k=h+C+A-BigInt(d.satoshis),T=F(o,k+400n,{requireGenesis:!1}),S=I=>Ie(I).length;for(let I=0;I<6;I++){let{inputs:O,totalSats:b}=T,E=(H,G)=>({version:2,locktime:0,inputs:[f,...O.map(X=>ft(X))],outputs:[g,{lockingBytecode:y,valueSatoshis:C,token:gt(d.token)},{lockingBytecode:Z(w),valueSatoshis:0n},{lockingBytecode:x,valueSatoshis:A},...H?[{lockingBytecode:m,valueSatoshis:G}]:[]]}),B=BigInt(Math.ceil(S(E(!0,1000000n))*a)),_=k+B;if(b<_){let H=F(o,_+200n,{requireGenesis:!1});if(H.inputs.length>O.length){T=H;continue}let G=new Error(`not enough funds: need ${_} sat, have ${b} sat`);throw G.needSats=_,G.haveSats=b,G}let P=b-_,U=P>=M;U||(P=0n);let N=E(U,P);return{name:l,transaction:N,sourceOutputs:[u,...O.map(H=>mt(H))],sellerInputIndex:0,costs:{priceSats:h,beaconDustSats:A,certificateDustSats:C,chainFeeSats:U?B:b-k,changeSats:P,totalInputSats:b}}}throw new Error("could not converge on a fee \u2014 please retry")}var ns=90n,os=100n;async function vn(t,e,n=L.addressPrefix){let s=(await re(t)).get(String(e).toLowerCase());if(!s?.mintScriptHex)return null;try{let r=Tn(s.mintScriptHex),a=Qo({bytecode:r,prefix:n,tokenSupport:!1});return typeof a=="string"?null:a.address}catch{return null}}function En(t){let e=BigInt(t??0n),n=e*ns/os,o=e-n;return{tldOwnerFeeSats:n,platformFeeSats:o}}var ss=v.beaconOnly;async function rs({electrum:t=L.electrum,WebSocket:e,beaconOk:n=!1}={}){let o=n?t:t.filter(s=>!ss.test(typeof s=="string"?s:s.url||""));return cn(o,e)}async function Yt(t,e){let n=D(e),o=z(n),s=await xt({client:t}),r=s.get(o)??null,a=s.released?.get(o),i=a!==void 0&&!(a>0),c=v.commitReveal?.contestBlocks??0,l=r?{open:!(r.height>0)||(s.height??0)+1<=r.height+c,finalAt:r.height>0?r.height+c+1:null,rank:r.commit?[r.commit.height,r.commit.txid]:[r.height>0?r.height:1/0,r.txid]}:null;return{name:o,rawName:n,available:!r&&!i,entry:r,contest:l,releasedAt:a??null,releasePending:i,reason:r?"registered":i?"release-pending":null,recordBudgetBytes:we(n)}}async function Vt(t,{name:e,ownerAddress:n,records:o={},utxos:s,serviceFee:r=L.serviceFee,feeRate:a=L.feeRate,cosignUtxo:i=null,cosignTokenAddress:c=null,salt:l=null}){let p=s??await K(t,[n]),d=D(e),f=d.indexOf("."),u=f<0?"bch":d.slice(f+1),g=BigInt(r.sats??0n),h=null,m=0n,y=g;if(g>0n){try{h=await vn(t,u)}catch{h=null}if(h&&h!==n){let x=En(g);m=x.tldOwnerFeeSats,y=x.platformFeeSats}}return Te({name:e,ownerAddress:n,ownerTokenAddress:q(n),records:o,utxos:p,feeAddress:y>0n?r.address:null,feeSats:y,tldFeeAddress:m>0n?h:null,tldFeeSats:m,beaconAddress:L.beacon,feeRate:a,addressToLockingBytecode:R,cosignUtxo:i,cosignTokenAddress:c,salt:l})}function _n(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 On(t,{wallet:e,utxos:n,feeRate:o,onProgress:s}){if(St(n))return{utxos:n,prepTxid:null};s("preparing-wallet");let r=At({ownerAddress:e.address,utxos:n,feeRate:o,addressToLockingBytecode:R}),a=at(r.transaction,r.sourceOutputs,l=>e.keyFor(l)),i=await J(t,a.hex);return s("prepared",{txid:i}),{utxos:a.transaction.outputs.slice(0,2).map((l,p)=>({txid:i,vout:p,satoshis:l.valueSatoshis,address:e.address,lockingBytecode:R(e.address)})),prepTxid:i}}async function is(t,{wallet:e,name:n,records:o={},serviceFee:s=L.serviceFee,feeRate:r=L.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 c=await Yt(t,n);if(!c.available)throw new Error(c.releasePending?`"${c.name}" was just released \u2014 it can be registered once that release is in a block`:`"${c.name}" is already registered`);i("loading-coins");let l=await K(t,e.watchedAddresses);if(l.filter(m=>!m.token).reduce((m,y)=>m+y.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let d=null;({utxos:l,prepTxid:d}=await On(t,{wallet:e,utxos:l,feeRate:r,onProgress:i})),i("building");let f=await Vt(t,{name:n,ownerAddress:e.address,records:o,utxos:l,serviceFee:s,feeRate:r,cosignUtxo:{...a.utxo,address:a.owner},cosignTokenAddress:q(a.owner)}),u=f.transaction.inputs.length-1;i("signing");let g={...f.transaction,inputs:f.transaction.inputs.map((m,y)=>y===u?{...m,unlockingBytecode:new Uint8Array}:m)},h=Bt(g,f.sourceOutputs,m=>e.keyFor(m),{skip:[u]});return{name:f.name,displayName:f.displayName,category:f.category,tx:h.hex,sourceOutputs:f.sourceOutputs.map(Ne),cosignInputIndex:u,costs:f.costs,prepTxid:d}}function as(t,e){let n=Jo(Tn(String(t.tx||"")));if(typeof n=="string")throw new Error("invalid transaction: "+n);let o=(t.sourceOutputs||[]).map(Re);if(o.length!==n.inputs.length)throw new Error("sourceOutputs do not match the transaction inputs");let s=[],r=0;n.inputs.forEach((i,c)=>{let l=o[c];if(!e(tt(l.lockingBytecode))){s.push(c);return}if(l.token?.nft&&!n.outputs.some(d=>d.token&&tt(d.token.category)===tt(l.token.category)&&tt(d.token.nft?.commitment??new Uint8Array)===tt(l.token.nft.commitment??new Uint8Array)&&tt(d.lockingBytecode)===tt(l.lockingBytecode)&&d.valueSatoshis>=l.valueSatoshis))throw new Error("refusing to sign: the request would not return your TLD certificate to you");r+=1});let a=Bt(n,o,e,{skip:s});return{hex:a.hex,txid:a.txid,signedInputs:r}}async function cs(t,{wallet:e,name:n,records:o={},serviceFee:s=L.serviceFee,feeRate:r=L.feeRate,cosign:a=null,commit:i=null,onProgress:c=()=>{}}){let l=null;if(i){if(D(i.name)!==D(n))throw new Error("this commit was made for another name");if(i.lock!==tt(R(e.address)))throw new Error("this commit was made for another owner");let x=l=await An(t,i);if(!x.mature)throw new Error(x.expired?"this commit is too old to reveal \u2014 commit again":"this commit is not in a block yet \u2014 the registration can be sent after the next block")}c("checking-availability");let p=await Yt(t,n);if(!p.available){let x=p.contest,w=l&&x&&(l.height<x.rank[0]||l.height===x.rank[0]&&i.txid<x.rank[1]);if(!(x?.open&&w))throw new Error(p.releasePending?`"${p.name}" was just released \u2014 it can be registered once that release is in a block`:`"${p.name}" is already registered`);c("contesting",{incumbent:p.entry.txid,finalAt:x.finalAt})}c("loading-coins");let d=await K(t,e.watchedAddresses);if(d.filter(x=>!x.token).reduce((x,w)=>x+w.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let u=null;if(a&&(u=_n(d,a),!u))throw new Error(`this wallet does not hold the certificate for .${a.tld} \u2014 only the TLD owner can co-sign`);let g=null;({utxos:d,prepTxid:g}=await On(t,{wallet:e,utxos:d,feeRate:r,onProgress:c})),c("building");let h=await Vt(t,{name:n,ownerAddress:e.address,records:o,utxos:d,serviceFee:s,feeRate:r,cosignUtxo:u,cosignTokenAddress:u?q(e.address):null,salt:i?i.salt:null});c("signing");let m=at(h.transaction,h.sourceOutputs,x=>e.keyFor(x));c("broadcasting");let y=await J(t,m.hex);return c("registered",{txid:y,category:h.category}),{name:h.name,displayName:h.displayName,category:h.category,txid:y,prepTxid:g,ownerAddress:e.address,certificateAddress:q(e.address),costs:h.costs,hex:m.hex}}async function ls(t,{wallet:e,name:n,certificateLock:o=null,feeRate:s=L.feeRate,onProgress:r=()=>{}}){let a=D(n),i=o??R(e.address),c=be(),l=ke(c,a,i);r("loading-coins");let p=await K(t,e.watchedAddresses);r("building");let d=ve({commitment:l,utxos:p,changeAddress:e.address,feeRate:s,addressToLockingBytecode:R});r("signing");let f=at(d.transaction,d.sourceOutputs,h=>e.keyFor(h)),u={name:a,salt:tt(c),lock:tt(i),commitment:tt(l),txid:f.txid,createdAt:Date.now()};r("committing",{pending:u}),r("broadcasting");let g=await J(t,f.hex);return r("committed",{txid:g,pending:u}),{...u,txid:g,costs:d.costs,hex:f.hex}}async function An(t,e){let n=v.commitReveal??{minAge:1,maxAge:0},o=null;try{o=await he(t,e.txid,!0)}catch{}let s=o?.confirmations??0;if(!(s>=1))return{confirmations:0,height:null,mature:!1,expired:!1,revealBy:null};let a=(await t.call("blockchain.headers.subscribe",[]))?.height??0,i=a-s+1,c=a+1-i;return{confirmations:s,height:i,mature:c>=n.minAge&&c<=n.maxAge,expired:c>n.maxAge,revealBy:i+n.maxAge}}async function us(t,{wallet:e,tld:n,records:o={},serviceFee:s={address:null,sats:0n},feeRate:r=L.feeRate,tldListUrl:a=null,onProgress:i=()=>{}}){let c=Ot(n);if(i("checking-availability"),a)try{let h=await fetch(a);if(h.ok){let m=await h.json();if(Array.isArray(m.tlds)&&m.tlds.some(x=>(x.tld||x)===c))throw new Error(`".${c}" is already registered as a TLD`)}}catch(h){if(/already registered/.test(h.message))throw h}i("loading-coins");let l=await K(t,e.watchedAddresses);if(l.filter(h=>!h.token).reduce((h,m)=>h+m.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let d=null;if(!St(l)){i("preparing-wallet");let h=At({ownerAddress:e.address,utxos:l,feeRate:r,addressToLockingBytecode:R}),m=at(h.transaction,h.sourceOutputs,y=>e.keyFor(y));d=await J(t,m.hex),i("prepared",{txid:d}),l=[{txid:d,vout:0,satoshis:m.transaction.outputs[0].valueSatoshis,address:e.address,lockingBytecode:R(e.address)},...m.transaction.outputs.length>1?[{txid:d,vout:1,satoshis:m.transaction.outputs[1].valueSatoshis,address:e.address,lockingBytecode:R(e.address)}]:[]]}i("building");let f=qt({tld:c,ownerAddress:e.address,ownerTokenAddress:q(e.address),changeAddress:e.address,records:o,utxos:l,feeAddress:s.address||null,feeSats:BigInt(s.sats??0n),feeRate:r,addressToLockingBytecode:R});i("signing");let u=at(f.transaction,f.sourceOutputs,h=>e.keyFor(h));i("broadcasting");let g=await J(t,u.hex);return i("registered",{txid:g,category:f.category}),{tld:f.tld,category:f.category,txid:g,prepTxid:d,ownerAddress:e.address,certificateAddress:q(e.address),costs:f.costs,hex:u.hex}}async function ds(t,{session:e,tld:n,records:o={},serviceFee:s={address:null,sats:0n},feeRate:r=L.feeRate,tldListUrl:a=null,onProgress:i=()=>{}}){let c=Ot(n);if(i("checking-availability"),a)try{let m=await fetch(a);if(m.ok){let y=await m.json();if(Array.isArray(y.tlds)&&y.tlds.some(w=>(w.tld||w)===c))throw new Error(`".${c}" is already registered as a TLD`)}}catch(m){if(/already registered/.test(m.message))throw m}i("reading-wallet");let l=await e.getAddresses();if(!l.length)throw new Error("the wallet exposed no addresses");let p=l[0];i("loading-coins");let d=await K(t,l);if(d.filter(m=>!m.token).reduce((m,y)=>m+y.satoshis,0n)===0n)throw new Error("the connected wallet has no spendable coins");let f=null;if(!St(d)){i("preparing-wallet");let m=At({ownerAddress:p,utxos:d,feeRate:r,addressToLockingBytecode:R}),y=await e.signTransaction(m,{userPrompt:"One-time setup so your wallet can create a TLD certificate"});f=await Dt(t,e,y,i),i("prepared",{txid:f}),d=[{txid:f,vout:0,satoshis:m.transaction.outputs[0].valueSatoshis,address:p,lockingBytecode:R(p)},...d.filter(x=>!x.token&&!m.inputUtxos.some(w=>w.txid===x.txid&&w.vout===x.vout))]}i("building");let u=qt({tld:c,ownerAddress:p,ownerTokenAddress:q(p),changeAddress:p,records:o,utxos:d,feeAddress:s.address||null,feeSats:BigInt(s.sats??0n),feeRate:r,addressToLockingBytecode:R});i("awaiting-approval");let g=await e.signTransaction(u,{userPrompt:`Register .${c} \u2014 the TLD certificate is minted to your own address`}),h=await Dt(t,e,g,i);return i("registered",{txid:h,category:u.category}),{tld:u.tld,category:u.category,txid:h,prepTxid:f,ownerAddress:p,certificateAddress:q(p),costs:u.costs}}async function Dt(t,e,n,o){let s=n.signedTransactionHash??Ae(n.signedTransaction);if(e.walletBroadcasts)return s;o("broadcasting");try{return await J(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 fs(t,{session:e,name:n,ownerAddress:o,records:s={},serviceFee:r=L.serviceFee,feeRate:a=L.feeRate,onProgress:i=()=>{}}){i("checking-availability");let c=await Yt(t,n);if(!c.available)throw new Error(c.releasePending?`"${c.name}" was just released \u2014 it can be registered once that release is in a block`:`"${c.name}" is already registered`);i("reading-wallet");let l=await e.getAddresses();if(!l.length)throw new Error("the wallet exposed no addresses");let p=o??l[0];i("loading-coins");let d=await K(t,l);if(!d.some(h=>!h.token))throw new Error("the connected wallet has no spendable coins");if(!St(d)){i("preparing-wallet");let h=At({ownerAddress:p,utxos:d,feeRate:a,addressToLockingBytecode:R}),m=await e.signTransaction(h,{userPrompt:"One-time setup so your wallet can create a name certificate"}),y=await Dt(t,e,m,i);i("prepared",{txid:y}),d=[{txid:y,vout:0,satoshis:h.transaction.outputs[0].valueSatoshis,address:p,lockingBytecode:R(p)},...d.filter(x=>!x.token&&!h.inputUtxos.some(w=>w.txid===x.txid&&w.vout===x.vout))]}i("building");let f=await Vt(t,{name:n,ownerAddress:p,records:s,utxos:d,serviceFee:r,feeRate:a});i("awaiting-approval");let u=await e.signTransaction(f,{userPrompt:`Register ${f.displayName} \u2014 the certificate is minted to your own address`}),g=await Dt(t,e,u,i);return i("registered",{txid:g,category:f.category}),{name:f.name,displayName:f.displayName,category:f.category,txid:g,ownerAddress:p,certificateAddress:q(p),costs:f.costs}}async function hs(t,{addresses:e,category:n,rawName:o}){let s=await K(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 ps(t,{wallet:e,name:n,records:o,feeRate:s=L.feeRate,onProgress:r=()=>{}}){r("resolving");let a=D(n),c=(await xt({client:t})).get(z(a));if(!c)throw new Error(`"${z(a)}" is not registered`);r("loading-coins");let l=await K(t,e.watchedAddresses),p=l.find(g=>g.token?.category===c.category&&g.token?.nft);if(!p)throw new Error(`this wallet does not hold the certificate for "${z(a)}" \u2014 only the owner can change its records`);r("building");let d=Ct({name:n,ownerAddress:e.address,ownerTokenAddress:q(e.address),records:o,certificateUtxo:p,utxos:l.filter(g=>!g.token),beaconAddress:L.beacon,feeRate:s,addressToLockingBytecode:R});r("signing");let f=at(d.transaction,d.sourceOutputs,g=>e.keyFor(g));r("broadcasting");let u=await J(t,f.hex);return r("updated",{txid:u}),{name:d.name,displayName:d.displayName,category:d.category,txid:u,records:o,costs:d.costs}}async function Bn(t,e,n=L.beacon){let o=await he(t,e.txid,!0),s=tt(R(n));return(o?.vout??[]).some(r=>r.scriptPubKey?.hex===s)}async function gs(t,{wallet:e,name:n,feeRate:o=L.feeRate,onProgress:s=()=>{}}){s("resolving");let r=D(n),i=(await xt({client:t})).get(z(r));if(!i)throw new Error(`"${z(r)}" is not registered`);s("loading-coins");let c=h=>h.token?.category===i.category&&h.token?.nft,l=await K(t,e.watchedAddresses),p=l.find(c);if(!p)throw new Error(`this wallet does not hold the certificate for "${z(r)}" \u2014 only the owner can release it`);let d=null;if(!await Bn(t,p)){s("anchoring");let h=Ct({name:n,ownerAddress:e.address,ownerTokenAddress:q(e.address),records:i.records??{},certificateUtxo:p,utxos:l.filter(y=>!y.token),beaconAddress:L.beacon,feeRate:o,addressToLockingBytecode:R}),m=at(h.transaction,h.sourceOutputs,y=>e.keyFor(y));d=await J(t,m.hex),s("anchored",{txid:d}),p=null;for(let y=0;y<12&&!p;y++)await new Promise(x=>setTimeout(x,1500)),l=await K(t,e.watchedAddresses),p=l.find(x=>c(x)&&x.txid===d)??null;if(!p)throw new Error("the anchoring update was broadcast but is not visible yet \u2014 try the release again in a minute")}s("building");let f=Ee({name:n,ownerAddress:e.address,certificateUtxo:p,utxos:l.filter(h=>!h.token),beaconAddress:L.beacon,feeRate:o,addressToLockingBytecode:R});s("signing");let u=at(f.transaction,f.sourceOutputs,h=>e.keyFor(h));s("broadcasting");let g=await J(t,u.hex);return s("released",{txid:g}),{name:f.name,displayName:f.displayName,category:f.category,txid:g,anchorTxid:d,costs:f.costs}}async function ms(t,{session:e,name:n,records:o,feeRate:s=L.feeRate,onProgress:r=()=>{}}){r("resolving");let a=D(n),c=(await xt({client:t})).get(z(a));if(!c)throw new Error(`"${z(a)}" is not registered`);r("reading-wallet");let l=await e.getAddresses(),p=await K(t,l),d=p.find(h=>h.token?.category===c.category&&h.token?.nft);if(!d)throw new Error(`this wallet does not hold the certificate for "${z(a)}" \u2014 only the owner can change its records`);r("building");let f=Ct({name:n,ownerAddress:d.address,ownerTokenAddress:q(d.address),records:o,certificateUtxo:d,utxos:p.filter(h=>!h.token),beaconAddress:L.beacon,feeRate:s,addressToLockingBytecode:R});r("awaiting-approval");let u=await e.signTransaction(f,{userPrompt:`Point ${f.displayName} somewhere new`}),g=await Dt(t,e,u,r);return r("updated",{txid:g}),{name:f.name,displayName:f.displayName,category:f.category,txid:g,records:o,costs:f.costs}}async function ys(t,{wallet:e,tld:n,records:o,category:s,feeRate:r=L.feeRate,onProgress:a=()=>{}}){if(!s)throw new Error("setTldRecords requires the TLD certificate's category id");a("loading-coins");let i=await K(t,e.watchedAddresses),c=i.find(f=>f.token?.category===s&&f.token?.nft);if(!c)throw new Error(`this wallet does not hold the TLD certificate for ".${n}" \u2014 only the owner can change its policy`);a("building");let l=hn({tld:n,ownerAddress:e.address,ownerTokenAddress:q(e.address),records:o,certificateUtxo:c,utxos:i.filter(f=>!f.token),feeRate:r,addressToLockingBytecode:R});a("signing");let p=at(l.transaction,l.sourceOutputs,f=>e.keyFor(f));a("broadcasting");let d=await J(t,p.hex);return a("updated",{txid:d}),{tld:l.tld,displayName:l.displayName,category:l.category,txid:d,records:o,costs:l.costs}}async function xs(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(Le(n)),s=Zo.hash(ts(o)),r=t.signMessage(s);return{...e,sig:es(r)}}function Le(t){if(t!=null){if(Array.isArray(t))return t.map(Le).filter(e=>e!==void 0);if(typeof t=="object"){let e={};for(let n of Object.keys(t).sort()){let o=Le(t[n]);o!==void 0&&(e[n]=o)}return e}return t}}async function ws(t,e){let n=await K(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:St(n)}}import{hexToBin as et,binToHex as ct,encodeDataPush as W,bigIntToVmNumber as Jt,hash256 as Ce,hash160 as bs,encodeLockingBytecodeP2sh32 as ks,encodeLockingBytecodeP2pkh as Rn,lockingBytecodeToCashAddress as Ss,OpcodesBCH as Ts,numberToBinUint32LE as Lr,binToNumberUint32LE as Pn,secp256k1 as Ln,sha256 as vs,generateSigningSerializationBCH as Es,encodeTransaction as Cn,flattenBinArray as It}from"@bitauth/libauth";var In={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 _s=2,De=1200,Os=7200,As=t=>{let e=Ts[t];if(e===void 0)throw new Error("unknown opcode "+t);return Uint8Array.of(e)};function Bs(t){let e=t.trim().split(/\s+/).filter(Boolean).map(n=>n.startsWith("OP_")?As(n):W(et(n)));return It(e)}var Is=Bs(In.bytecode),Xt=t=>W(Jt(BigInt(t))),Ps=0,Nn=1;function Ns(t){let e=et(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 ct(e.slice(3,23))}function Ue({oraclePk:t,sellerPkh:e,targetCents:n,floorSats:o,ceilSats:s,maxAgeSecs:r=De}){if(!(BigInt(n)>0n)||!(BigInt(o)>0n)||BigInt(s)<BigInt(o))throw new Error("bad listing terms");return It([Xt(r),Xt(s),Xt(o),Xt(n),W(et(e)),W(et(t)),Is])}var Qt=t=>ks(Ce(t));function Fe(t,e=v.prefix){let n=Ss({bytecode:Qt(t),prefix:e});if(typeof n=="string")throw new Error(n);return n.address}function Dn({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 Un=t=>({ts:Pn(t.slice(0,4)),priceCents:Pn(t.slice(4,8)),outpointTxid:ct(t.slice(8,40).slice().reverse())});function Fn(t,e,n){return Ln.verifySignatureSchnorr(n,t,vs.hash(e))===!0}var Me=(t,e,n,o,{requireGenesis:s=!1}={})=>{let r=F(t,e+600n,{requireGenesis:s});for(let a=0;a<6;a++){let{inputs:i,totalSats:c}=r,l=o(i,!0,1000000n),p=BigInt(Math.ceil(Cn(l.transaction).length*n)),d=e+p;if(c<d){let g=F(t,d+200n,{requireGenesis:s});if(g.inputs.length>i.length){r=g;continue}let h=new Error(`not enough funds: need ${d} sat, have ${c} sat`);throw h.needSats=d,h.haveSats=c,h}let f=c-d,u=f>=M;return u||(f=0n),{...o(i,u,f),fee:u?p:c-e,change:f}}throw new Error("could not converge on a fee \u2014 please retry")};function Rs({name:t,certificateUtxo:e,utxos:n,sellerAddress:o,oraclePk:s,targetCents:r,floorSats:a,ceilSats:i,maxAgeSecs:c=De,records:l={},beaconAddress:p=dt,feeRate:d=1,addressToLockingBytecode:f}){let u=D(t);if(!e?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let g=f(o),h=Ns(ct(f(e.address||o))),m=Ue({oraclePk:s,sellerPkh:h,targetCents:r,floorSats:a,ceilSats:i,maxAgeSecs:c}),y=Qt(m),x=Q("UPD",u,l),w=n.filter(S=>!S.token),k=C+A-BigInt(e.satoshis);return{...Me(w,k>0n?k:0n,d,(S,I,O)=>({transaction:{version:2,locktime:0,inputs:[ft(e),...S.map(b=>ft(b))],outputs:[{lockingBytecode:y,valueSatoshis:C,token:gt(e.token)},{lockingBytecode:Z(x),valueSatoshis:0n},{lockingBytecode:f(p),valueSatoshis:A},...I?[{lockingBytecode:g,valueSatoshis:O}]:[]]},sourceOutputs:[mt(e),...S.map(b=>mt(b))]})),name:u,redeem:m,redeemHex:ct(m),address:Fe(m,o.split(":")[0]),sellerPkh:h,covenantVout:0}}function Mn(t){let e=et(t.redeem_hex);return{redeem:e,utxo:{txid:t.outpoint.txid,vout:t.outpoint.vout,satoshis:BigInt(t.outpoint.satoshis??C),lockingBytecode:Qt(e),token:t.token}}}function Ls({listing:t,quote:e,buyerAddress:n,buyerTokenAddress:o,utxos:s,records:r={},beaconAddress:a=dt,feeRate:i=1,addressToLockingBytecode:c}){let l=D(t.name),p=et(e.message),d=et(e.signature);if(!Fn(et(t.oracle_pk),p,d))throw new Error("oracle signature does not verify against the listing's oracle key");let{ts:f,priceCents:u,outpointTxid:g}=Un(p);if(g!==String(t.outpoint.txid).toLowerCase())throw new Error("quote was issued for a different listing");let h=Dn({targetCents:t.target_cents,priceCents:u,floorSats:t.floor_sats,ceilSats:t.ceil_sats}),{redeem:m,utxo:y}=Mn(t),x=Rn(et(t.seller_pkh)),w=It([W(d),W(p),W(Jt(BigInt(Ps))),W(m)]),k=c(n),T=c(o??n),S=Q("UPD",l,r),I=s.filter(E=>!E.token),O=h+C+A-y.satoshis;return{...Me(I,O,i,(E,B,_)=>({transaction:{version:2,locktime:Math.max(0,f-Os),inputs:[ft(y,w),...E.map(P=>ft(P))],outputs:[{lockingBytecode:x,valueSatoshis:h},{lockingBytecode:T,valueSatoshis:C,token:gt(y.token)},{lockingBytecode:Z(S),valueSatoshis:0n},{lockingBytecode:c(a),valueSatoshis:A},...B?[{lockingBytecode:k,valueSatoshis:_}]:[]]},sourceOutputs:[mt(y),...E.map(P=>mt(P))]})),name:l,covenantInputIndex:0,priceSats:h,priceCents:u,quoteTs:f}}function Cs({listing:t,sellerAddress:e,sellerTokenAddress:n,utxos:o,records:s={},beaconAddress:r=dt,feeRate:a=1,addressToLockingBytecode:i,keyFor:c}){let l=D(t.name),{redeem:p,utxo:d}=Mn(t),f=Rn(et(t.seller_pkh)),u=c(ct(f));if(!u)throw new Error("this wallet does not hold the seller key for this listing");let g=u.privateKey,h=u.publicKey,m=i(n??e),y=Q("UPD",l,s),x=o.filter(P=>!P.token),w=C+A-d.satoshis,k=It([W(new Uint8Array(65)),W(h),W(Jt(BigInt(Nn))),W(p)]),T=Me(x,w>0n?w:0n,a,(P,U,N)=>({transaction:{version:2,locktime:0,inputs:[ft(d,k),...P.map(H=>ft(H))],outputs:[{lockingBytecode:m,valueSatoshis:C,token:gt(d.token)},{lockingBytecode:Z(y),valueSatoshis:0n},{lockingBytecode:i(r),valueSatoshis:A},...U?[{lockingBytecode:i(e),valueSatoshis:N}]:[]]},sourceOutputs:[mt(d),...P.map(H=>mt(H))]})),S=Bt(T.transaction,T.sourceOutputs,c,{skip:[0]}),I=Es({inputIndex:0,sourceOutputs:T.sourceOutputs,transaction:S.transaction},{coveredBytecode:p,signingSerializationType:Uint8Array.of(zt)}),O=Ln.signMessageHashSchnorr(g,Ce(I));if(typeof O=="string")throw new Error(O);let b=It([O,Uint8Array.of(zt)]),E=It([W(b),W(h),W(Jt(BigInt(Nn))),W(p)]),B={...S.transaction,inputs:S.transaction.inputs.map((P,U)=>U===0?{...P,unlockingBytecode:E}:P)},_=Cn(B);return{name:l,transaction:B,sourceOutputs:T.sourceOutputs,hex:ct(_),txid:ct(Ce(_).slice().reverse())}}function Ds(t,{oraclePk:e}={}){let n=o=>({ok:!1,error:o});try{if(t?.kind!=="usd"||t.v!==_s)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=Ue({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(ct(o)!==t.redeem_hex)return n("redeem script does not match the stated terms");let s=String(t.seller).split(":")[0]||v.prefix;return Fe(o,s)!==t.covenant_address?n("covenant address does not match"):ct(bs(et(t.seller_pkh))).length!==40?n("bad seller pkh"):t.token?.category!==t.category||!t.token?.nft?n("token does not match category"):et(t.token.nft.commitment||"").length===0||ct(new TextEncoder().encode(D(t.name)))!==t.token.nft.commitment?n("commitment does not match the name"):{ok:!0,name:D(t.name),covenant_lock:ct(Qt(o))}}catch(o){return n(String(o?.message||o))}}import{hash160 as Us,lockingBytecodeToCashAddress as Fs,binToHex as Hr}from"@bitauth/libauth";function $n(t){return Uint8Array.from([118,169,20,...Us(t),136,172])}function Ms(t,e=v.prefix,n=!1){let o=Fs({bytecode:$n(t),prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(`address encoding failed: ${o}`);return o.address}function $s(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 si,hexToBin as ri}from"@bitauth/libauth";import{stringify as ai}from"@bitauth/libauth";export{ue as BuiltInWallet,Oo as CHIPNET_PREFIX,De as DEFAULT_MAX_AGE_SECS,Ye as DEFAULT_NETWORK_ID,Lt as DEFAULT_PREFIX,V as InsufficientFundsError,Ao as MAINNET_PREFIX,v as NETWORK,Et as NETWORKS,jt as NoGenesisInputError,L as REGISTRAR,_t as REG_SALT_BYTES,xe as TLD_BEACON,R as addressToLockingBytecode,Co as addressToScripthash,si as binToHex,J as broadcast,ve as buildCommitTx,is as buildCosignRequest,xt as buildIndex,zo as buildListing,At as buildPrepTx,Te as buildRegistrationTx,Ee as buildReleaseTx,qt as buildTldRegistrationTx,Ct as buildUpdateTx,Ls as buildUsdBuyTx,Cs as buildUsdCancelTx,Rs as buildUsdListingTx,Yt as checkAvailability,An as commitState,ls as commitWithBuiltInWallet,ke as commitmentHash,Xo as completeSale,rs as connect,$s as describeGenesisRequirement,z as displayName,hs as findCertificateUtxo,_n as findTldCertificateUtxo,vn as findTldOwnerAddress,ws as getBalance,rt as getNetwork,un as getUtxos,K as getUtxosForAddresses,St as hasGenesisInput,ri as hexToBin,Bn as isAnchored,be as newRegistrationSalt,D as normalizeName,Ot as normalizeTld,Un as parseOracleMessage,we as payloadBudget,Dn as payoutSats,jo as priceSummary,Ms as pubkeyToAddress,$n as pubkeyToLockingBytecode,Vt as quoteRegistration,us as registerTldWithBuiltInWallet,ds as registerTldWithExternalWallet,cs as registerWithBuiltInWallet,fs as registerWithExternalWallet,gs as releaseWithBuiltInWallet,ee as requireBeacons,bo as resolveName,ps as setRecordsWithBuiltInWallet,ms as setRecordsWithExternalWallet,ys as setTldRecordsWithBuiltInWallet,as as signCosignRequest,Bt as signInputs,xs as signRecordsManifest,at as signTransaction,Re as sourceOutputFromJson,Ne as sourceOutputToJson,En as splitServiceFee,ai as stringify,q as toTokenAddress,pn as toWcTransactionObject,Oe as txidOf,Ae as txidOfHex,Fe as usdListingAddress,Ue as usdListingRedeem,Sn as verifyListing,Fn as verifyOracleMessage,Ds as verifyUsdListing};
|