A covenant-held name's certificate is at the covenant's address, so the gateway's holdings - which looked for certificates among a wallet's coins - never listed it under anyone. It is now listed under the key its verified state names, with its expiry and where it is in its life. covenant-registrar.js is one function per thing an owner does with the built-in wallet: move a name into the covenant, renew, publish records, transfer, release. Each announces the new state, and refuses a stale view of the name rather than guess where the certificate went. Tested against a simulated chain: every transaction is run through the VM, applied, and read back through the resolver. The name index fetched its transactions one at a time, which had grown to most of half a minute before a registration could be quoted; it now fetches eight at a time.
7 lines
97 KiB
JavaScript
7 lines
97 KiB
JavaScript
import{generateBip39Mnemonic as br,deriveSeedFromBip39Mnemonic as Un,deriveHdPrivateNodeFromSeed as Tr,deriveHdPath as Er,secp256k1 as Cn,hash160 as kr,encodeCashAddress as Ai,lockingBytecodeToCashAddress as Sr,cashAddressToLockingBytecode as Ii,binToHex as Ar,hexToBin as vi,utf8ToBin as Mn,binToBase64 as ke,base64ToBin as Se}from"@bitauth/libauth";var vt={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}},An="chipnet";function Xo(){let t=typeof globalThis<"u"?globalThis.BNS_NETWORK:null,e=typeof process<"u"&&process.env?process.env.BNS_NETWORK:null;return String(t||e||An).trim().toLowerCase()}function lt(t){if(t&&typeof t=="object")return t;let e=t||Xo(),n=vt[e];if(!n)throw new Error(`unknown network "${e}" (known: ${Object.keys(vt).join(", ")})`);return n}var b=lt();function Pe(t=b){let e=lt(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 Oi=b.beacon,yi=b.beaconScripthash,Pi=b.tldBeacon,_i=b.tldBeaconScripthash,xi=b.electrum,wi=vt.chipnet.electrum,bi=b.electrumListName,xn="BNS1";var In="bch",qo=/^[a-z0-9-]{1,32}$/,vn=/^[a-z0-9-]{1,16}$/,_e=/^[a-z0-9-]{1,32}(\.[a-z0-9-]{1,16})?$/;function jt(t){return t.includes(".")?t:t+"."+In}var Ft=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},te=t=>[...new TextEncoder().encode(t)].map(e=>e.toString(16).padStart(2,"0")).join("");function jo(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,r;if(n.length===1?(o=n[0],r=In):(r=n[n.length-1],o=n[n.length-2]),!qo.test(o)||!vn.test(r))throw new Error(`invalid name "${t}" (allowed: <label>.<tld>, [a-z0-9-])`);return`${o}.${r}`}var zt=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 r=async()=>{try{await this.call("server.version",["bns-web","1.4.2"]),e(this)}catch(a){n(a)}},s=a=>n(new Error("electrum ws error: "+(a?.message||this.url))),i=a=>this._onData(typeof a.data=="string"?a.data:a.data.toString());o.addEventListener?(o.addEventListener("open",r),o.addEventListener("error",s),o.addEventListener("message",i)):(o.onopen=r,o.onerror=s,o.onmessage=i)})}_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 r=this.buf.slice(0,n).trim();if(this.buf=this.buf.slice(n+1),r)try{this._handle(JSON.parse(r))}catch{}}let o=this.buf.trim();if(o)try{let r=JSON.parse(o);this._handle(r),this.buf=""}catch{}}call(e,n=[]){let o=++this.id;return new Promise((r,s)=>{this.pending.set(o,{resolve:r,reject:s}),this.ws.send(JSON.stringify({id:o,method:e,params:n})+`
|
|
`),setTimeout(()=>{this.pending.has(o)&&(this.pending.delete(o),s(new Error(`electrum timeout: ${e}`)))},2e4)})}close(){try{this.ws.close()}catch{}}},zo=t=>typeof t=="string"?{url:t}:t;async function Jt(t,e,{directIP:n=!1}={}){let o;for(let r of t){let s=zo(r);try{return await new zt(s.url,e).connect()}catch(i){o=i}if(n&&s.ip)try{let i=new URL(s.url),a=`${i.protocol}//${s.ip}:${i.port}`;return await new zt(a,e,{servername:i.hostname}).connect()}catch(i){o=i}}throw o??new Error("no electrum server reachable")}function Jo(t){if(!t||!t.startsWith("6a"))return null;let e=Ft(t),n=1,o=[];for(;n<e.length;){let s=e[n++],i;if(s<=75)i=s;else if(s===76)i=e[n++];else if(s===77)i=e[n]|e[n+1]<<8,n+=2;else return null;o.push(e.slice(n,n+i)),n+=i}let r=new TextDecoder().decode(o[0]??new Uint8Array);if(!r.startsWith(xn))return null;try{let s=JSON.parse(r.slice(xn.length));if(!Zo.has(s.o))return null;if(s.o==="CMT")return typeof s.h=="string"&&/^[0-9a-f]{64}$/.test(s.h)?s:null;if(typeof s.n=="string"||s.o==="RPT"&&Array.isArray(s.n)&&s.n.every(i=>typeof i=="string"))return s}catch{}return null}function ee(t){let e=null;for(let n of t||[]){let o=Jo(n&&n.scriptPubKey?n.scriptPubKey.hex:null);if(o){if(e)return null;e=o}}return e}var Zo=new Set(["REG","UPD","REL","TREG","TUPD","RPT","BLK","UBK","CMT"]);function xe(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 we(t,e){let n=new Set(t.map(a=>a.tx_hash)),o=new Map(t.map(a=>{let c=new Set;for(let l of e.get(a.tx_hash)?.vin??[])l.txid&&l.txid!==a.tx_hash&&n.has(l.txid)&&c.add(l.txid);return[a.tx_hash,c]})),r=new Set,s=[],i=[...t];for(;i.length;){let a=i.findIndex(l=>[...o.get(l.tx_hash)].every(p=>r.has(p)));a<0&&(a=0);let[c]=i.splice(a,1);r.add(c.tx_hash),s.push(c)}return s}function Rn(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(i=>i&&i.txid===o&&i.vout===0)||(t.vout||[]).filter(i=>i.tokenData&&i.tokenData.category===o).length!==1)return!1;let r=n.nft.capability;if(r!=null&&r!==""&&r!=="none")return!1;let s;try{s=BigInt(n.amount??0)}catch{return!1}return s===0n}function ye(t){let e=t.lastIndexOf(".");return e<0?t:t.slice(e+1)}function tr(t,e,n){let o=n.get(t);return o?o.regHeight>0&&e>0?o.regHeight<=e:!0:!1}async function be(t,e=b){let{tldBeaconScripthash:n}=Pe(e),o=typeof t.unionHistory=="function"?(await t.unionHistory(n)).history:await t.call("blockchain.scripthash.get_history",[n]);o.sort(xe);let r=new Map;for(let{tx_hash:i}of o)try{r.set(i,await t.call("blockchain.transaction.get",[i,!0]))}catch{}let s=new Map;for(let{tx_hash:i,height:a}of we(o.filter(c=>r.has(c.tx_hash)),r)){let c=r.get(i),l=c.vout||[],p=ee(l);if(!p||typeof p.n!="string"||!vn.test(p.n))continue;let f=p.n;if(p.o==="TREG"){if(s.has(f))continue;let d=te(f),u=l.find(g=>g.tokenData?.nft&&g.tokenData.nft.commitment===d);if(!u||!Rn(c,u))continue;s.set(f,{category:u.tokenData.category,regHeight:a,regTxid:i,mintScriptHex:u.scriptPubKey?.hex??null,records:p.r??{},updates:[{height:a,txid:i,records:p.r??{}}]})}else if(p.o==="TUPD"){let d=s.get(f);if(!d||!l.some(u=>u.tokenData&&u.tokenData.category===d.category))continue;d.records=p.r??{},d.updates.push({height:a,txid:i,records:d.records})}}return s}function er(t,e){if(!t)return{};let n=t.updates||[];if(!n.length)return t.records||{};let o={};for(let r of n)e>0&&(r.height<=0||r.height>e)||(o=r.records||{});return o}function nr(t,e){let n=er(t,e);return n.policy==="cosign"||n.hidden===1||n.hidden===!0||n.hidden==="1"}function or(t,e,n){let o=te(n);return(t||[]).some(r=>r.tokenData&&r.tokenData.category===e.category&&r.tokenData.nft&&r.tokenData.nft.commitment===o)}function wn(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 Bn(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 rr(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 r=Bn(o,n);return!!(r&&r.tokenData&&r.tokenData.nft&&r.tokenData.category===e.category)})}function sr(t,e){return t===void 0?!0:t>0?!(e>0)||e>t:!1}function ir(t,e,n){return Dt(Zt(Ft(t+te(e)+n)))}function ar({ordered:t,txs:e,network:n=b,keyOf:o=s=>s,admits:r}){let s=lt(n).commitReveal||{required:!1,minAge:1,maxAge:0,contestBlocks:0},i=new Map,a=new Map;for(let{tx_hash:u,height:g}of t){let h=e.get(u),O=h?ee(h.vout):null;if(O){if(O.o==="CMT")i.has(O.h)||i.set(O.h,{height:g,txid:u,used:!1});else if(O.o==="REG"&&typeof O.n=="string"&&_e.test(O.n)){let m=o(O.n);a.has(m)||a.set(m,[]),a.get(m).push({tx_hash:u,height:g,payload:O,pos:a.get(m).length})}}}let c=1/0,l=u=>{let g=r(e.get(u.tx_hash),u.payload,u.height);if(!g)return null;let h=u.payload.s;if(h===void 0)return s.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 O=i.get(ir(h,u.payload.n,g.scriptPubKey.hex));if(!O||O.used||!(O.height>0))return null;if(u.height>0){let m=u.height-O.height;if(m<s.minAge||m>s.maxAge)return null}return{r:u,mint:g,commit:O,rank:[O.height,O.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},f=new Map;function d(u,g){let h=a.get(g)||[],O=h.findIndex(_=>_.tx_hash===u);if(O<0)return null;let m=f.get(g);if(m&&m!==u)return null;let y=l(h[O]);if(!y)return m&&f.delete(g),null;if(!m){let _=(h[O].height>0?h[O].height:c)+s.contestBlocks,k=y;for(let T of h.slice(O+1)){if(!(T.height>0?T.height<=_:_===c))continue;let P=l(T);P&&p(P,k)&&(k=P)}if(k!==y)return f.set(g,k.r.tx_hash),null}return f.delete(g),y.commit&&(y.commit.used=!0),{mint:y.mint,commit:y.commit}}return{decide:d,commits:i,rules:s}}async function xt({network:t=b,electrum:e=lt(t).electrum,WebSocket:n,client:o,directIP:r=!1,enforceTld:s=!1,cosignGate:i=!0,height:a=null}={}){let c=Pe(t),l=o??await Jt(e,n,{directIP:r});try{let p=null;if(s||i)try{p=await be(l,c)}catch(P){if(s)throw P;p=null}let f=null,d;if(typeof l.unionHistory=="function"){let P=await l.unionHistory(c.beaconScripthash);d=P.history,f={servers:P.servers,unreachable:P.unreachable,disagreements:P.disagreements}}else d=await l.call("blockchain.scripthash.get_history",[c.beaconScripthash]);d.sort(xe);let u=new Map,g=new Map,h=d.map(P=>P.tx_hash),O=async()=>{for(let P=h.shift();P!==void 0;P=h.shift())try{g.set(P,await l.call("blockchain.transaction.get",[P,!0]))}catch{}};await Promise.all(Array.from({length:Math.min(8,h.length)},O));for(let{tx_hash:P}of d)g.has(P)&&u.set(P,g.get(P));let m=new Map,y=new Map,_=we(d.filter(P=>u.has(P.tx_hash)),u),k=ar({ordered:_,txs:u,network:c,keyOf:jt,admits:(P,B,S)=>{let E=jt(B.n);if(s&&!tr(ye(E),S,p))return null;if(i&&p){let w=p.get(ye(E));if(w&&nr(w,S)&&!or(P.vout||[],w,ye(E)))return null}let v=te(B.n),A=(P.vout||[]).find(w=>w.tokenData?.nft&&w.tokenData.nft.commitment===v);return A&&Rn(P,A)?A:null}});for(let{tx_hash:P,height:B}of _){let S=u.get(P),E=S.vout||[],v=ee(E);if(!v)continue;let A=v.n;if(typeof A!="string"||!_e.test(A))continue;let w=jt(A);if(v.o==="REG"){if(m.has(w)||!sr(y.get(w),B))continue;let x=k.decide(P,w);if(!x)continue;let R=x.mint;m.set(w,{name:w,category:R.tokenData.category,records:v.r??{},txid:P,height:B,updatedTxid:null,...x.commit?{commit:{height:x.commit.height,txid:x.commit.txid}}:{},owner:wn(R)}),bn(m.get(w),v,R,S,B,c),y.delete(w)}else if(v.o==="REL"){let x=m.get(w);if(!x||!rr(S,x,u))continue;m.delete(w),y.set(w,B)}else if(v.o==="UPD"){let x=m.get(w);if(!x)continue;let R=E.find(L=>L.tokenData&&L.tokenData.category===x.category);if(!R||!bn(x,v,R,S,B,c))continue;x.records=v.r??{},x.updatedTxid=P,x.covenant||(x.owner=wn(R)??x.owner)}}let T=a;if(!(T>0))try{let P=await l.call("blockchain.headers.subscribe",[]);P&&P.height>0&&(T=P.height)}catch{}return Or(m,Math.max(T>0?T:0,gr(d)),c),f&&Object.defineProperty(m,"integrity",{value:f,enumerable:!1}),Object.defineProperty(m,"released",{value:y,enumerable:!1}),m}finally{o||l.close()}}var cr=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]),pt=(t,e)=>t>>>e|t<<32-e;function Zt(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 r=new DataView(o.buffer);r.setUint32(o.length-8,Math.floor(n*8/4294967296)),r.setUint32(o.length-4,n*8>>>0);let s=new Uint32Array(64);for(let c=0;c<o.length;c+=64){for(let m=0;m<16;m++)s[m]=r.getUint32(c+m*4);for(let m=16;m<64;m++){let y=pt(s[m-15],7)^pt(s[m-15],18)^s[m-15]>>>3,_=pt(s[m-2],17)^pt(s[m-2],19)^s[m-2]>>>10;s[m]=s[m-16]+y+s[m-7]+_|0}let l=e[0],p=e[1],f=e[2],d=e[3],u=e[4],g=e[5],h=e[6],O=e[7];for(let m=0;m<64;m++){let y=O+(pt(u,6)^pt(u,11)^pt(u,25))+(u&g^~u&h)+cr[m]+s[m]|0,_=(pt(l,2)^pt(l,13)^pt(l,22))+(l&p^l&f^p&f)|0;O=h,h=g,g=u,u=d+y|0,d=f,f=p,p=l,l=y+_|0}e[0]+=l,e[1]+=p,e[2]+=f,e[3]+=d,e[4]+=u,e[5]+=g,e[6]+=h,e[7]+=O}let i=new Uint8Array(32),a=new DataView(i.buffer);for(let c=0;c<8;c++)a.setUint32(c*4,e[c]);return i}var Dt=t=>[...t].map(e=>e.toString(16).padStart(2,"0")).join(""),Ln="qpzry9x8gf2tvdw0s3jn54khce6mua7l";function Nn(t){let e=[0x98f2bc8e61n,0x79b76d99e2n,0xf33e5fb3c4n,0xae2eabe2a8n,0x1e4f43e470n],n=1n;for(let o of t){let r=n>>35n;n=(n&0x07ffffffffn)<<5n^BigInt(o);for(let s=0;s<5;s++)r>>BigInt(s)&1n&&(n^=e[s])}return n^1n}function Te(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),r=[...e.slice(n+1)].map(d=>Ln.indexOf(d));if(r.length<9||r.some(d=>d<0))throw new Error(`not a cashaddr: "${t}"`);if(Nn([...[...o].map(d=>d.charCodeAt(0)&31),0,...r])!==0n)throw new Error(`bad cashaddr checksum: "${t}"`);let s=[],i=0,a=0;for(let d of r.slice(0,-8))for(i=i<<5|d,a+=5;a>=8;)a-=8,s.push(i>>a&255);let c=s[0],l=c>>3&15,p=Dt(s.slice(1)),f=[20,24,28,32,40,48,56,64][c&7];if(p.length!==f*2)throw new Error(`cashaddr hash length mismatch: "${t}"`);if((l===0||l===2)&&f===20)return"76a914"+p+"88ac";if((l===1||l===3)&&f===20)return"a914"+p+"87";if((l===1||l===3)&&f===32)return"aa20"+p+"87";throw new Error(`unsupported address type: "${t}"`)}function lr(t){return Dt(Zt(Ft(Te(t))).reverse())}function ur(t,e=b.prefix){let n=[],o=0,r=0;for(let a of[0,...Ft(t)])for(o=(o<<8|a)&4095,r+=8;r>=5;)r-=5,n.push(o>>r&31);r&&n.push(o<<5-r&31);let s=Nn([...[...e].map(a=>a.charCodeAt(0)&31),0,...n,0,0,0,0,0,0,0,0]),i=[];for(let a=0;a<8;a++)i.push(Number(s>>BigInt(5*(7-a))&31n));return e+":"+[...n,...i].map(a=>Ln[a]).join("")}var dr=5e8;function Ee(t,e){let n=String(t).split(".")[0];return e.tiers.findIndex(o=>n.length<=o.maxLabel)}function fr(t,e,n,o){let r=o>>>0,s=[r&255,r>>>8&255,r>>>16&255,r>>>24&255],i="14"+n+"04"+Dt(s)+t.tiers[e].head+t.tail;return"aa20"+Dt(Zt(Zt(Ft(i))))+"87"}function hr(t,e,n,o=b){let r=lt(o).covenant,s=t?t.c:null;if(!r||!s||typeof s!="object"||!e||!e.scriptPubKey||typeof s.o!="string"||!/^[0-9a-f]{40}$/.test(s.o)||!Number.isInteger(s.e)||s.e<=0||s.e>=dr)return null;let i=Ee(n,r);return i<0||e.scriptPubKey.hex!==fr(r,i,s.o,s.e)?null:{ownerPkh:s.o,expiry:s.e,tier:i+1,version:r.version}}function pr(t,e,n,o=b){let r=lt(o).covenant;if(!r||!t||!(n>0))return!1;let s=0;for(let a of e.vout||[])a&&a.scriptPubKey&&a.scriptPubKey.hex===r.fundLock&&!a.tokenData&&(s+=Math.round(Number(a.value)*1e8));let i=Math.floor(s/r.tiers[t.tier-1].renewalSats);return i>=1&&t.expiry<=n+i*r.blocksPerYear}function bn(t,e,n,o,r,s=b){let i=hr(e,n,t.name,s);if(t.covenant){if(!i)return!1}else if(!i||!pr(i,o,r,s))return!0;return t.covenant=i,t.owner=ur(i.ownerPkh,lt(s).prefix),!0}function mr(t,e,n=b){let o=lt(n).covenant;if(!t||!o)return null;let r=t.expiry+o.graceBlocks;return{status:e<t.expiry?"active":e<r?"idle":"open",expiry:t.expiry,idleEnd:r}}function gr(t){let e=0;for(let n of t||[])n&&n.height>e&&(e=n.height);return e}function Or(t,e,n=b){for(let o of t.values()){let r=mr(o.covenant,e,n);r&&(o.status=r.status,o.expiry=r.expiry,o.idleEnd=r.idleEnd,r.status==="open"&&(o.lapsedRecords=o.records,o.records={}))}return Object.defineProperty(t,"height",{value:e,enumerable:!1,configurable:!0}),t}var Tn=new Set(["phishing","impersonation","malware","scam-financial","csam","stolen"]);function En(t,e,n){return(t.vin||[]).some(o=>{let r=Bn(o,n);return!!(r&&r.scriptPubKey&&r.scriptPubKey.hex===e)})}var yr=t=>typeof t=="string"&&/^[0-9a-f]{64}$/.test(t);function kn(t){return typeof t=="string"&&_e.test(t)?jt(t):null}function Pr({history:t,txs:e,address:n,source:o=null}){let r=Te(n),s=e instanceof Map?e:new Map(Object.entries(e||{})),i=we([...t||[]].filter(p=>s.has(p.tx_hash)).sort(xe),s),a=p=>ee(p.vout),c=new Map;for(let{tx_hash:p,height:f}of i){let d=s.get(p),u=a(d);if(!u||u.o!=="RPT"||!En(d,r,s)||u.t!=="block"&&u.t!=="unblock")continue;let g=(u.n||[]).map(kn);!g.length||g.some(h=>!h)||u.t==="block"&&!Tn.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:f})}let l=new Map;for(let{tx_hash:p,height:f}of i){let d=s.get(p),u=a(d);if(!u||u.o!=="BLK"&&u.o!=="UBK"||!En(d,r,s))continue;let g=kn(u.n);if(!g||!yr(u.p))continue;let h=c.get(u.p);if(!(!h||!h.names.has(g)))if(u.o==="BLK"){if(h.type!=="block"||!Tn.has(u.r)||h.reason!==u.r)continue;l.set(g,{name:g,reason:u.r,reportTxid:u.p,txid:p,height:f,evidence:u.e??h.evidence,vote:h.vote,source:o,address:n})}else{if(h.type!=="unblock")continue;l.delete(g)}}return l}function Sn(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 Te(n),n}catch{}return t?.beacon??null}async function _r({network:t=b,lists:e,index:n=null,electrum:o,WebSocket:r,client:s,directIP:i=!1}={}){let a=lt(t),c=e??a.blocklists??[],l=new Map;if(!c.length)return l;let p=o??a.electrum.filter(d=>!a.beaconOnly.test(typeof d=="string"?d:d.url)),f=s;if(!f)try{f=await Jt(p,r,{directIP:i})}catch(d){let u=new Set((a.blocklists||[]).map(g=>g.beacon));if(o||!c.every(g=>u.has(Sn(g,n))))throw d;f=await Jt(a.electrum,r,{directIP:i})}try{for(let d of c){let u=Sn(d,n);if(!u)continue;let g=lr(u),h=typeof f.unionHistory=="function"?(await f.unionHistory(g)).history:await f.call("blockchain.scripthash.get_history",[g]);if(!h||!h.length)continue;let O=new Map;for(let{tx_hash:m}of h)try{O.set(m,await f.call("blockchain.transaction.get",[m,!0]))}catch{}for(let[m,y]of Pr({history:h,txs:O,address:u,source:d.name??u})){let _=l.get(m);_?_.sources.push(y):l.set(m,{...y,sources:[y]})}}return l}finally{s||f.close()}}function xr(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 wr(t,e={}){let n=jo(t),o=lt(e.network),r=e.blocklists===void 0?o.blocklists??[]:e.blocklists||[];if(!r.length)return(await xt(e)).get(n)??null;let s=e.client??await Jt(e.electrum??o.electrum,e.WebSocket,{directIP:!!e.directIP});try{let i=await xt({...e,client:s}),a=i.get(n)??null;if(!a)return null;let c=null;try{c=await _r(e.client?{network:o,lists:r,index:i,client:e.client}:{network:o,lists:r,index:i,WebSocket:e.WebSocket,directIP:!!e.directIP})}catch{}return xr(a,c)}finally{e.client||s.close()}}var Ti=b.rootTldName,Ei=b.bootstrapTlds.slice();var Ir="bchtest",vr="bitcoincash",Mt=b.prefix,Ae="m/44'/145'/0'",Rr=5,ne="bns.wallet.v1";function Kn(t){let e=kr(t);return Uint8Array.from([118,169,20,...e,136,172])}function Dn(t,e,n){let o=Sr({bytecode:Kn(t),prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(`address encoding failed: ${o}`);return o.address}var Ie=class t{constructor(e,n,o=Mt,r=Ae){this.mnemonic=e,this.prefix=o,this.accountPath=r,this._root=Tr(n),this._keys=new Map,this._derive()}static async create(e=Mt,n=Ae){let o=br();return new t(o,await Un(o),e,n)}static async fromMnemonic(e,n=Mt,o=Ae){let r=String(e).trim().toLowerCase().replace(/\s+/g," "),s=await Un(r);if(typeof s=="string")throw new Error(`invalid recovery phrase: ${s}`);return new t(r,s,n,o)}_derive(){this.receive=[],this.change=[];for(let[e,n]of[[0,this.receive],[1,this.change]])for(let o=0;o<Rr;o++){let r=`${this.accountPath}/${e}/${o}`,s=Er(this._root,r);if(typeof s=="string")throw new Error(`HD derivation failed at ${r}: ${s}`);let i=Cn.derivePublicKeyCompressed(s.privateKey);if(typeof i=="string")throw new Error(`pubkey derivation failed: ${i}`);let a=Kn(i),c={path:r,branch:e,index:o,privateKey:s.privateKey,publicKey:i,lockingBytecode:a,address:Dn(i,this.prefix,!1),tokenAddress:Dn(i,this.prefix,!0)};n.push(c),this._keys.set(Ar(a),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,r=[...this.receive,...this.change].find(p=>p.address===o);if(!r)throw new Error(`no key for address ${o}`);let s=Cn.signMessageHashRecoverableCompact(r.privateKey,e);if(typeof s=="string")throw new Error(`signMessage failed: ${s}`);let{signature:i}=s,a=s.recoveryId??s.recovery;if(typeof a!="number")throw new Error("signMessage: no recovery id in signature result");let c=31+a,l=new Uint8Array(65);return l[0]=c,l.set(i,1),l}async encrypt(e){let n=crypto.getRandomValues(new Uint8Array(16)),o=crypto.getRandomValues(new Uint8Array(12)),r=await Fn(e,n),s=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:o},r,Mn(this.mnemonic)));return JSON.stringify({v:1,kdf:"PBKDF2-SHA256",iterations:ve,prefix:this.prefix,salt:ke(n),iv:ke(o),ct:ke(s)})}static async decrypt(e,n){let o=typeof e=="string"?JSON.parse(e):e,r=await Fn(n,Se(o.salt),o.iterations??ve),s;try{s=await crypto.subtle.decrypt({name:"AES-GCM",iv:Se(o.iv)},r,Se(o.ct))}catch{throw new Error("wrong password")}return t.fromMnemonic(new TextDecoder().decode(s),o.prefix??Mt)}async save(e,n=globalThis.localStorage){n.setItem(ne,await this.encrypt(e))}static async load(e,n=globalThis.localStorage){let o=n.getItem(ne);return o?t.decrypt(o,e):null}static exists(e=globalThis.localStorage){return!!e?.getItem(ne)}static forget(e=globalThis.localStorage){e.removeItem(ne)}},ve=25e4;async function Fn(t,e,n=ve){let o=await crypto.subtle.importKey("raw",Mn(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 Ni=vt.chipnet.electrum.map(t=>t.url),oe=b.electrum.map(t=>t.url),Re=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 r=async()=>{try{await this.call("server.version",["bns-web","1.4.2"]),e(this)}catch(a){n(a)}},s=a=>n(new Error("electrum ws error: "+(a?.message||this.url))),i=a=>this._onData(typeof a.data=="string"?a.data:a.data.toString());o.addEventListener?(o.addEventListener("open",r),o.addEventListener("error",s),o.addEventListener("message",i)):(o.onopen=r,o.onerror=s,o.onmessage=i)})}_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 r=this.buf.slice(0,n).trim();if(this.buf=this.buf.slice(n+1),r)try{this._handle(JSON.parse(r))}catch{}}let o=this.buf.trim();if(o)try{let r=JSON.parse(o);this._handle(r),this.buf=""}catch{}}call(e,n=[]){let o=++this.id;return new Promise((r,s)=>{this.pending.set(o,{resolve:r,reject:s}),this.ws.send(JSON.stringify({id:o,method:e,params:n})+`
|
|
`),setTimeout(()=>{this.pending.has(o)&&(this.pending.delete(o),s(new Error(`electrum timeout: ${e}`)))},2e4)})}close(){try{this.ws.close()}catch{}}};async function Hn(t=oe,e){let n=[];for(let o of t)try{return await new Re(o,e).connect()}catch(r){n.push(`${o}: ${r?.message??r}`)}throw Br(t.length,n)}function Br(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 Lr,lockingBytecodeToCashAddress as Nr,sha256 as Ur,hash160 as Di,binToHex as Cr,hexToBin as Fi}from"@bitauth/libauth";function Yn(t){return Cr(Ur.hash(t).slice().reverse())}function N(t){let e=Lr(t);if(typeof e=="string")throw new Error(`bad address "${t}": ${e}`);return e.bytecode}function Dr(t){return Yn(N(t))}function Q(t){let e=N(t),n=String(t).includes(":")?t.split(":")[0]:b.prefix,o=Nr({bytecode:e,prefix:n,tokenSupport:!0});if(typeof o=="string")throw new Error(`cannot token-encode "${t}": ${o}`);return o.address}async function re(t,e){let n=N(e),o=Yn(n);return(await t.call("blockchain.scripthash.listunspent",[o,"include_tokens"])).map(s=>({txid:s.tx_hash,vout:s.tx_pos,satoshis:BigInt(s.value),height:s.height,address:e,lockingBytecode:n,token:s.token_data?{category:s.token_data.category,amount:BigInt(s.token_data.amount??0),nft:s.token_data.nft?{capability:s.token_data.nft.capability,commitment:s.token_data.nft.commitment}:void 0}:void 0}))}async function K(t,e){let n=[];for(let o of e)n.push(...await re(t,o));return n}async function X(t,e){return t.call("blockchain.transaction.broadcast",[e])}async function Be(t,e,n=!0){return t.call("blockchain.transaction.get",[e,n])}import{binToHex as Et,hexToBin as z,utf8ToBin as mt,binToUtf8 as Ce,encodeTransaction as Fr,decodeTransaction as Yi,sha256 as Mr}from"@bitauth/libauth";var $n="BNS1",gt=b.beacon,De=b.tldBeacon,I=600n,C=1000n,F=546n,Le="bch",Ne=200,Kr=/^[a-z0-9-]{1,32}$/,Gn=/^[a-z0-9-]{1,16}$/;function Bt(t){let e=String(t).toLowerCase().trim().replace(/^\.+/,"").replace(/\.+$/,"");if(!Gn.test(e))throw new Error(`invalid TLD "${t}" (allowed: [a-z0-9-]{1,16})`);return e}var se=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 U(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=Le):(o=e[e.length-1],n=e[e.length-2]),!Kr.test(n)||!Gn.test(o))throw new Error(`invalid name "${t}" (allowed: <label>.<tld>, [a-z0-9-])`);return o===Le?n:`${n}.${o}`}function $(t){return t.includes(".")?t:`${t}.${Le}`}function q(t,e,n,o=null,r=null){let s=JSON.stringify({o:t,n:e,r:n??{},...o?{c:o}:{},...r?{s:r}:{}}),i=mt($n+s);if(i.length>Ne)throw new Error(`records too large (${i.length} > ${Ne} bytes)`);return i}function Fe(t,e="REG"){return Ne-q(e,t,{}).length}var Rt=16;function Me(){return crypto.getRandomValues(new Uint8Array(Rt))}var Ue=t=>t instanceof Uint8Array?t:z(t);function ie(t,e,n){let o=Ue(t);if(o.length!==Rt)throw new Error(`the registration salt must be exactly ${Rt} bytes`);let r=mt(U(e)),s=Ue(n),i=new Uint8Array(o.length+r.length+s.length);return i.set(o),i.set(r,o.length),i.set(s,o.length+r.length),Mr.hash(i)}function Hr(t){let e=typeof t=="string"?t:Et(t);if(!/^[0-9a-f]{64}$/.test(e))throw new Error("a commitment is 32 bytes");return mt($n+JSON.stringify({o:"CMT",h:e}))}function Yr(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 j(t){return Uint8Array.from([106,...Yr(t)])}function Ke(){return Uint8Array.from([65,...new Uint8Array(65),33,...new Uint8Array(33)])}var $r=t=>!t.token;function M(t,e,{requireGenesis:n=!0}={}){let o=t.filter($r),r=[],s=0n;if(n){let a=o.filter(c=>c.vout===0).sort((c,l)=>l.satoshis>c.satoshis?1:-1);if(a.length===0)throw new se("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)");r.push(a[0]),s+=a[0].satoshis}let i=o.filter(a=>!r.some(c=>c.txid===a.txid&&c.vout===a.vout)).sort((a,c)=>c.satoshis>a.satoshis?1:-1);for(let a of i){if(s>=e)break;r.push(a),s+=a.satoshis}return{inputs:r,totalSats:s}}function Ot(t){return{outpointTransactionHash:z(t.txid),outpointIndex:t.vout,sequenceNumber:4294967294,unlockingBytecode:Ke()}}function wt(t){return{...Ot(t),lockingBytecode:t.lockingBytecode,valueSatoshis:t.satoshis,...t.token?{token:{amount:t.token.amount??0n,category:z(t.token.category),...t.token.nft?{nft:{capability:t.token.nft.capability,commitment:z(t.token.nft.commitment||"")}}:{}}}:{}}}function ut(t){return Fr(t).length}function He({name:t,ownerAddress:e,ownerTokenAddress:n,changeAddress:o,records:r={},utxos:s,feeAddress:i=null,feeSats:a=0n,tldFeeAddress:c=null,tldFeeSats:l=0n,beaconAddress:p=gt,feeRate:f=1,addressToLockingBytecode:d,cosignUtxo:u=null,cosignTokenAddress:g=null,salt:h=null}){if(typeof d!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let O=U(t),m=h?Et(Ue(h)):null;if(m&&m.length!==Rt*2)throw new Error(`the registration salt must be exactly ${Rt} bytes`);let y=q("REG",O,r,null,m),_=BigInt(a??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,P=u?d(g??n??e):null;if(_>0n&&!i)throw new Error("feeSats set but feeAddress missing");if(k>0n&&!c)throw new Error("tldFeeSats set but tldFeeAddress missing");let B=d(o??e),S=d(n??e),E=d(p),v=_>0n?d(i):null,A=k>0n?d(c):null,w=C+I+_+k+T,x=M(s,w+300n-T),R=0n,L=0n,Y=!0;for(let V=0;V<6;V++){let{inputs:tt}=x,it=u?[...tt,u]:tt,W=x.totalSats+T,at=it[0],_n=z(at.txid),Oe=(At,It)=>{let ct=[];return At&&ct.push({lockingBytecode:B,valueSatoshis:It}),ct.push({lockingBytecode:S,valueSatoshis:C,token:{amount:0n,category:_n,nft:{capability:"none",commitment:mt(O)}}}),ct.push({lockingBytecode:j(y),valueSatoshis:0n}),ct.push({lockingBytecode:E,valueSatoshis:I}),A&&ct.push({lockingBytecode:A,valueSatoshis:k}),v&&ct.push({lockingBytecode:v,valueSatoshis:_}),u&&ct.push({lockingBytecode:P,valueSatoshis:T,token:{amount:BigInt(u.token.amount??0),category:z(u.token.category),nft:{capability:u.token.nft.capability,commitment:z(u.token.nft.commitment||"")}}}),{version:2,locktime:0,inputs:it.map(Ot),outputs:ct}},Vo=Oe(!0,1000000n),Wo=ut(Vo);R=BigInt(Math.ceil(Wo*f));let Ct=w+R;if(W<Ct){let At=M(s,Ct+200n-T);if(At.inputs.length>tt.length){x=At;continue}throw new J(`not enough funds: need ${Ct} sat, have ${W} sat`,{needSats:Ct,haveSats:W})}if(L=W-Ct,Y=L>=F,!Y){let At=Oe(!1,0n);R=W-w;let It=BigInt(Math.ceil(ut(At)*f));if(R<It){let ct=M(s,w+It+F+200n-T);if(ct.inputs.length>tt.length){x=ct;continue}throw new J(`not enough funds: need ${w+It} sat, have ${W} sat`,{needSats:w+It,haveSats:W})}L=0n}let Qo=Oe(Y,L),_t={},Tt=0;return Y&&(_t.change=Tt++),_t.certificate=Tt++,_t.opReturn=Tt++,_t.beacon=Tt++,A&&(_t.tldOwnerFee=Tt++),v&&(_t.serviceFee=Tt++),u&&(_t.cosignCertificate=Tt++),{name:O,displayName:$(O),category:Et(_n),transaction:Qo,sourceOutputs:it.map(wt),inputUtxos:it,outputMap:_t,payload:y,costs:{certificateDustSats:C,beaconDustSats:I,serviceFeeSats:_,tldOwnerFeeSats:k,chainFeeSats:R,changeSats:L,totalInputSats:W,netCostSats:_+k+R+I}}}throw new Error("could not converge on a fee \u2014 please retry")}function Ye({commitment:t,utxos:e,changeAddress:n,beaconAddress:o=gt,feeRate:r=1,addressToLockingBytecode:s}){if(typeof s!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let i=Hr(t),a=s(n),c=s(o),l=M(e,I+F+400n,{requireGenesis:!1});for(let p=0;p<6;p++){let{inputs:f,totalSats:d}=l,u=m=>({version:2,locktime:0,inputs:f.map(Ot),outputs:[{lockingBytecode:a,valueSatoshis:m},{lockingBytecode:j(i),valueSatoshis:0n},{lockingBytecode:c,valueSatoshis:I}]}),g=BigInt(Math.ceil(ut(u(1000000n))*r)),h=I+g+F;if(d<h){let m=M(e,h+200n,{requireGenesis:!1});if(m.inputs.length>f.length){l=m;continue}throw new J(`not enough funds: need ${h} sat, have ${d} sat`,{needSats:h,haveSats:d})}let O=d-I-g;return{transaction:u(O),sourceOutputs:f.map(wt),inputUtxos:f,outputMap:{change:0,opReturn:1,beacon:2},payload:i,costs:{beaconDustSats:I,chainFeeSats:g,changeSats:O,netCostSats:I+g}}}throw new Error("could not converge on a fee \u2014 please retry")}function ae({tld:t,ownerAddress:e,ownerTokenAddress:n,changeAddress:o,records:r={},utxos:s,feeAddress:i=null,feeSats:a=0n,beaconAddress:c=De,feeRate:l=1,addressToLockingBytecode:p}){if(typeof p!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let f=Bt(t),d=q("TREG",f,r),u=BigInt(a??0n);if(u>0n&&!i)throw new Error("feeSats set but feeAddress missing");let g=p(o??e),h=p(n??e),O=p(c),m=u>0n?p(i):null,y=C+I+u,_=M(s,y+300n),k=0n,T=0n,P=!0;for(let B=0;B<6;B++){let{inputs:S,totalSats:E}=_,v=S[0],A=z(v.txid),w=(it,W)=>{let at=[];return it&&at.push({lockingBytecode:g,valueSatoshis:W}),at.push({lockingBytecode:h,valueSatoshis:C,token:{amount:0n,category:A,nft:{capability:"none",commitment:mt(f)}}}),at.push({lockingBytecode:j(d),valueSatoshis:0n}),at.push({lockingBytecode:O,valueSatoshis:I}),m&&at.push({lockingBytecode:m,valueSatoshis:u}),{version:2,locktime:0,inputs:S.map(Ot),outputs:at}},x=w(!0,1000000n),R=ut(x);k=BigInt(Math.ceil(R*l));let L=y+k;if(E<L){let it=M(s,L+200n);if(it.inputs.length>S.length){_=it;continue}throw new J(`not enough funds: need ${L} sat, have ${E} sat`,{needSats:L,haveSats:E})}if(T=E-L,P=T>=F,!P){let it=w(!1,0n);k=E-y;let W=BigInt(Math.ceil(ut(it)*l));if(k<W){let at=M(s,y+W+F+200n);if(at.inputs.length>S.length){_=at;continue}throw new J(`not enough funds: need ${y+W} sat, have ${E} sat`,{needSats:y+W,haveSats:E})}T=0n}let Y=w(P,T),V={},tt=0;return P&&(V.change=tt++),V.certificate=tt++,V.opReturn=tt++,V.beacon=tt++,m&&(V.serviceFee=tt++),{tld:f,category:Et(A),transaction:Y,sourceOutputs:S.map(wt),inputUtxos:S,outputMap:V,payload:d,costs:{certificateDustSats:C,beaconDustSats:I,serviceFeeSats:u,chainFeeSats:k,changeSats:T,totalInputSats:E,netCostSats:u+k+I}}}throw new Error("could not converge on a fee \u2014 please retry")}function Kt({name:t,ownerAddress:e,ownerTokenAddress:n,records:o={},certificateUtxo:r,utxos:s,beaconAddress:i=gt,feeRate:a=1,addressToLockingBytecode:c}){if(typeof c!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let l=U(t);if(!r?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let p=Et(mt(l));if(r.token.nft.commitment!==p)throw new Error(`certificate commitment mismatch: holds "${Ce(z(r.token.nft.commitment))}", asked to update "${l}"`);let f=q("UPD",l,o),d=c(e),u=c(n??e),g=c(i),h=C+I,O=M(s,h+400n,{requireGenesis:!1}),m=0n,y=0n,_=!0;for(let k=0;k<6;k++){let T=[r,...O.inputs],P=r.satoshis+O.totalSats,B=(x,R)=>{let L=[];return x&&L.push({lockingBytecode:d,valueSatoshis:R}),L.push({lockingBytecode:u,valueSatoshis:C,token:{amount:0n,category:z(r.token.category),nft:{capability:"none",commitment:mt(l)}}}),L.push({lockingBytecode:j(f),valueSatoshis:0n}),L.push({lockingBytecode:g,valueSatoshis:I}),{version:2,locktime:0,inputs:T.map(Ot),outputs:L}},S=ut(B(!0,1000000n));m=BigInt(Math.ceil(S*a));let E=h+m;if(P<E){let x=M(s,E+200n,{requireGenesis:!1});if(x.inputs.length>O.inputs.length){O=x;continue}throw new J(`not enough funds: need ${E} sat, have ${P} sat`,{needSats:E,haveSats:P})}y=P-E,_=y>=F,_||(m=P-h,y=0n);let v=B(_,y),A={},w=0;return _&&(A.change=w++),A.certificate=w++,A.opReturn=w++,A.beacon=w++,{name:l,displayName:$(l),category:r.token.category,transaction:v,sourceOutputs:T.map(wt),inputUtxos:T,outputMap:A,payload:f,costs:{certificateDustSats:C,beaconDustSats:I,serviceFeeSats:0n,chainFeeSats:m,changeSats:y,totalInputSats:P,netCostSats:m+I}}}throw new Error("could not converge on a fee \u2014 please retry")}function $e({name:t,ownerAddress:e,certificateUtxo:n,utxos:o=[],beaconAddress:r=gt,feeRate:s=1,addressToLockingBytecode:i}){if(typeof i!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let a=U(t);if(!n?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let c=Et(mt(a));if(n.token.nft.commitment!==c)throw new Error(`certificate commitment mismatch: holds "${Ce(z(n.token.nft.commitment))}", asked to release "${a}"`);let l=q("REL",a,{}),p=i(e),f=i(r),d=I,u={inputs:[],totalSats:0n},g=0n,h=0n,O=!0;for(let m=0;m<6;m++){let y=[n,...u.inputs],_=n.satoshis+u.totalSats,k=(v,A)=>{let w=[];return v&&w.push({lockingBytecode:p,valueSatoshis:A}),w.push({lockingBytecode:j(l),valueSatoshis:0n}),w.push({lockingBytecode:f,valueSatoshis:I}),{version:2,locktime:0,inputs:y.map(Ot),outputs:w}},T=BigInt(Math.ceil(ut(k(!1,0n))*s)),P=BigInt(Math.ceil(ut(k(!0,1000000n))*s));if(_<d+T){let v=M(o,d+P+200n,{requireGenesis:!1});if(v.inputs.length>u.inputs.length){u=v;continue}throw new J(`not enough funds: need ${d+T} sat, have ${_} sat`,{needSats:d+T,haveSats:_})}h=_-d-P,O=h>=F,O?g=P:(g=_-d,h=0n);let B=k(O,h),S={},E=0;return O&&(S.change=E++),S.opReturn=E++,S.beacon=E++,{name:a,displayName:$(a),category:n.token.category,transaction:B,sourceOutputs:y.map(wt),inputUtxos:y,outputMap:S,payload:l,costs:{beaconDustSats:I,chainFeeSats:g,changeSats:h,totalInputSats:_,netCostSats:g+I}}}throw new Error("could not converge on a fee \u2014 please retry")}function Vn({tld:t,ownerAddress:e,ownerTokenAddress:n,records:o={},certificateUtxo:r,utxos:s,beaconAddress:i=De,feeRate:a=1,addressToLockingBytecode:c}){if(typeof c!="function")throw new Error("addressToLockingBytecode must be injected (see chain.js)");let l=Bt(t);if(!r?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let p=Et(mt(l));if(r.token.nft.commitment!==p)throw new Error(`TLD certificate commitment mismatch: holds "${Ce(z(r.token.nft.commitment))}", asked to update ".${l}"`);let f=q("TUPD",l,o),d=c(e),u=c(n??e),g=c(i),h=C+I,O=M(s,h+400n,{requireGenesis:!1}),m=0n,y=0n,_=!0;for(let k=0;k<6;k++){let T=[r,...O.inputs],P=r.satoshis+O.totalSats,B=(x,R)=>{let L=[];return x&&L.push({lockingBytecode:d,valueSatoshis:R}),L.push({lockingBytecode:u,valueSatoshis:C,token:{amount:0n,category:z(r.token.category),nft:{capability:"none",commitment:mt(l)}}}),L.push({lockingBytecode:j(f),valueSatoshis:0n}),L.push({lockingBytecode:g,valueSatoshis:I}),{version:2,locktime:0,inputs:T.map(Ot),outputs:L}},S=ut(B(!0,1000000n));m=BigInt(Math.ceil(S*a));let E=h+m;if(P<E){let x=M(s,E+200n,{requireGenesis:!1});if(x.inputs.length>O.inputs.length){O=x;continue}throw new J(`not enough funds: need ${E} sat, have ${P} sat`,{needSats:E,haveSats:P})}y=P-E,_=y>=F,_||(m=P-h,y=0n);let v=B(_,y),A={},w=0;return _&&(A.change=w++),A.certificate=w++,A.opReturn=w++,A.beacon=w++,{tld:l,displayName:`.${l}`,category:r.token.category,transaction:v,sourceOutputs:T.map(wt),inputUtxos:T,outputMap:A,payload:f,costs:{certificateDustSats:C,beaconDustSats:I,serviceFeeSats:0n,chainFeeSats:m,changeSats:y,totalInputSats:P,netCostSats:m+I}}}throw new Error("could not converge on a fee \u2014 please retry")}function Lt({ownerAddress:t,utxos:e,amountSats:n=10000n,feeRate:o=1,addressToLockingBytecode:r}){let s=r(t),i=M(e,n+400n,{requireGenesis:!1});if(i.inputs.length===0)throw new J("wallet is empty");for(let a=0;a<6;a++){let{inputs:c,totalSats:l}=i,p=(g,h)=>({version:2,locktime:0,inputs:c.map(Ot),outputs:[{lockingBytecode:s,valueSatoshis:n},...g?[{lockingBytecode:s,valueSatoshis:h}]:[]]}),f=BigInt(Math.ceil(ut(p(!0,1000000n))*o));if(l<n+f){let g=BigInt(Math.ceil(ut(p(!1,0n))*o));if(l<=g+F)throw new J(`not enough funds to prepare the wallet: have ${l} sat`,{needSats:g+F,haveSats:l});return{transaction:{version:2,locktime:0,inputs:c.map(Ot),outputs:[{lockingBytecode:s,valueSatoshis:l-g}]},sourceOutputs:c.map(wt),inputUtxos:c,costs:{chainFeeSats:g}}}let d=l-n-f,u=d>=F;return{transaction:p(u,d),sourceOutputs:c.map(wt),inputUtxos:c,costs:{chainFeeSats:u?f:l-n}}}throw new Error("could not converge on a fee \u2014 please retry")}function kt(t){return t.some(e=>e.vout===0&&!e.token)}function Wn({transaction:t,sourceOutputs:e},{broadcast:n=!0,userPrompt:o}={}){return{transaction:t,sourceOutputs:e,broadcast:n,...o?{userPrompt:o}:{}}}import{generateSigningSerializationBCH as Gr,hash256 as Xn,secp256k1 as Vr,encodeTransaction as Wr,binToHex as Ge}from"@bitauth/libauth";var Qn=65;function dt(t,e,n){let o={...t,inputs:t.inputs.map((s,i)=>{let a=e[i],c=n(Ge(a.lockingBytecode));if(!c)throw new Error(`no key for input ${i} \u2014 cannot sign`);let l=Gr({inputIndex:i,sourceOutputs:e,transaction:t},{coveredBytecode:a.lockingBytecode,signingSerializationType:Uint8Array.of(Qn)}),p=Xn(l),f=Vr.signMessageHashSchnorr(c.privateKey,p);if(typeof f=="string")throw new Error(`signing failed on input ${i}: ${f}`);let d=Uint8Array.from([...f,Qn]);return{...s,unlockingBytecode:Uint8Array.from([d.length,...d,c.publicKey.length,...c.publicKey])}})},r=Wr(o);return{transaction:o,hex:Ge(r),txid:Ve(r)}}function Ve(t){return Ge(Xn(t).slice().reverse())}function We(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 Ve(e)}var D={network:b.id,addressPrefix:b.prefix,explorerTx:b.explorerTx,selfHosted:null,get electrum(){return this.selfHosted?[this.selfHosted,...oe]:oe},beacon:b.beacon,tldBeacon:b.tldBeacon,serviceFee:{address:b.operatorAddress,sats:10000n},feeRate:1,wizardConnect:{dappName:"Silent Mode",dappIcon:"https://silentmode.st/icon.png"},faucets:b.faucets};function Qr(t){let e=s=>(Number(s)/1e8).toFixed(8).replace(/0+$/,"").replace(/\.$/,""),n=[],o=BigInt(t.tldOwnerFeeSats??0n),r=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:r,bch:e(r),note:"covers the resolver + gateway + indexer"})):n.push({label:"Service fee",sats:r,bch:e(r)}),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 eo,binToHex as nt,decodeTransaction as Zr,lockingBytecodeToCashAddress as ts,sha256 as es,utf8ToBin as ns,binToBase64 as os}from"@bitauth/libauth";import{encodeTransaction as Xe,decodeTransaction as qn,generateSigningSerializationBCH as jn,hash256 as qe,hash160 as Xr,secp256k1 as zn,hexToBin as yt,binToHex as H,utf8ToBin as Jn}from"@bitauth/libauth";var St=65,Qe=195,Z=(t,e)=>({outpointTransactionHash:yt(t.txid),outpointIndex:t.vout,sequenceNumber:4294967294,unlockingBytecode:e??Ke()}),ft=t=>t?{amount:BigInt(t.amount??0),category:yt(t.category),...t.nft?{nft:{capability:t.nft.capability,commitment:yt(t.nft.commitment||"")}}:{}}:void 0,je=t=>({lockingBytecode:t.lockingBytecode instanceof Uint8Array?H(t.lockingBytecode):String(t.lockingBytecode),valueSatoshis:String(t.valueSatoshis),...t.token?{token:{category:t.token.category instanceof Uint8Array?H(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?H(t.token.nft.commitment):String(t.token.nft.commitment||"")}}:{}}}:{}}),ze=t=>({lockingBytecode:yt(t.lockingBytecode),valueSatoshis:BigInt(t.valueSatoshis??t.satoshis),...t.token?{token:ft(t.token)}:{}}),et=(t,e)=>({...Z(t,e),lockingBytecode:t.lockingBytecode instanceof Uint8Array?t.lockingBytecode:yt(t.lockingBytecode),valueSatoshis:BigInt(t.satoshis),...t.token?{token:ft(t.token)}:{}});function Zn(t,e,n,o,r){let s=e[n],i=jn({inputIndex:n,sourceOutputs:e,transaction:t},{coveredBytecode:s.lockingBytecode,signingSerializationType:Uint8Array.of(r)}),a=qe(i),c=zn.signMessageHashSchnorr(o.privateKey,a);if(typeof c=="string")throw new Error(`signing failed on input ${n}: ${c}`);let l=Uint8Array.from([...c,r]);return Uint8Array.from([l.length,...l,o.publicKey.length,...o.publicKey])}function bt(t,e,n,{sighash:o=St,skip:r=[]}={}){let s={...t,inputs:t.inputs.map((a,c)=>{if(r.includes(c))return a;let l=n(H(e[c].lockingBytecode));return l?{...a,unlockingBytecode:Zn(t,e,c,l,o)}:a})},i=Xe(s);return{transaction:s,hex:H(i),txid:H(qe(i).slice().reverse())}}function qr({name:t,certificateUtxo:e,priceSats:n,sellerAddress:o,addressToLockingBytecode:r,keyFor:s}){let i=U(t),a=BigInt(n);if(a<F)throw new Error(`price must be at least ${F} sat`);if(!e?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");if(e.token.nft.commitment!==H(Jn(i)))throw new Error("certificate commitment does not match the name");let c=r(o),l=et(e),p={version:2,locktime:0,inputs:[Z(e)],outputs:[{lockingBytecode:c,valueSatoshis:a}]},f=s(H(l.lockingBytecode));if(!f)throw new Error("this wallet does not hold the key for the certificate");return p.inputs[0].unlockingBytecode=Zn(p,[l],0,f,Qe),{v:1,name:i,seller:o,price_sats:a.toString(),category:e.token.category,partial_tx:H(Xe(p)),source_output:{txid:e.txid,vout:e.vout,satoshis:BigInt(e.satoshis).toString(),lockingBytecode:H(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 jr(t){let e=t[0],n=t.slice(1,1+e),o=t[1+e],r=t.slice(2+e,2+e+o);return{sig:n,pubkey:r}}var zr=t=>Uint8Array.from([118,169,20,...Xr(t),136,172]);function to(t,e={}){let n=o=>({ok:!1,error:o});try{if(!t||t.v!==1)return n("unsupported listing version");let o=U(t.name),r=qn(yt(t.partial_tx));if(typeof r=="string")return n("partial_tx does not decode: "+r);if(r.inputs.length!==1||r.outputs.length<1)return n("partial_tx must have exactly one input and a payment output");let s=t.source_output;if(!s?.token?.nft)return n("source_output carries no certificate");if(H(r.inputs[0].outpointTransactionHash)!==s.txid||r.inputs[0].outpointIndex!==s.vout)return n("input does not spend source_output");if(s.token.nft.commitment!==H(Jn(o)))return n("certificate commitment does not match the name");if(e.category&&s.token.category!==e.category)return n("certificate category does not match the registry");let i=r.outputs[0].valueSatoshis;if(i<F)return n("price below dust");if(BigInt(t.price_sats)!==i)return n("price_sats does not match output 0");let{sig:a,pubkey:c}=jr(r.inputs[0].unlockingBytecode);if(a.length!==65||a[64]!==Qe)return n("input 0 is not signed SINGLE|ANYONECANPAY");let l=yt(s.lockingBytecode);if(H(zr(c))!==H(l))return n("public key does not own the certificate output");if(e.ownerLockingBytecode&&H(l)!==e.ownerLockingBytecode)return n("certificate is not held by the current owner");if(H(r.outputs[0].lockingBytecode)!==H(l))return n("payment does not go to the certificate holder");let p={...r.inputs[0],lockingBytecode:l,valueSatoshis:BigInt(s.satoshis),token:ft(s.token)},f=jn({inputIndex:0,sourceOutputs:[p],transaction:r},{coveredBytecode:l,signingSerializationType:Uint8Array.of(Qe)});return zn.verifySignatureSchnorr(a.slice(0,64),c,qe(f))?{ok:!0,name:o,price_sats:i,seller_lock:H(l),category:s.token.category}:n("seller signature is invalid")}catch(o){return n(String(o?.message||o))}}function Jr({listing:t,buyerAddress:e,buyerTokenAddress:n,utxos:o,records:r={},beaconAddress:s=gt,feeRate:i=1,addressToLockingBytecode:a}){let c=to(t);if(!c.ok)throw new Error("bad listing: "+c.error);let l=c.name,p=qn(yt(t.partial_tx)),f=t.source_output,d=p.inputs[0],u={...d,lockingBytecode:yt(f.lockingBytecode),valueSatoshis:BigInt(f.satoshis),token:ft(f.token)},g=p.outputs[0],h=g.valueSatoshis,O=a(e),m=a(n??e),y=a(s),_=q("UPD",l,r),k=h+C+I-BigInt(f.satoshis),T=M(o,k+400n,{requireGenesis:!1}),P=B=>Xe(B).length;for(let B=0;B<6;B++){let{inputs:S,totalSats:E}=T,v=(Y,V)=>({version:2,locktime:0,inputs:[d,...S.map(tt=>Z(tt))],outputs:[g,{lockingBytecode:m,valueSatoshis:C,token:ft(f.token)},{lockingBytecode:j(_),valueSatoshis:0n},{lockingBytecode:y,valueSatoshis:I},...Y?[{lockingBytecode:O,valueSatoshis:V}]:[]]}),A=BigInt(Math.ceil(P(v(!0,1000000n))*i)),w=k+A;if(E<w){let Y=M(o,w+200n,{requireGenesis:!1});if(Y.inputs.length>S.length){T=Y;continue}let V=new Error(`not enough funds: need ${w} sat, have ${E} sat`);throw V.needSats=w,V.haveSats=E,V}let x=E-w,R=x>=F;R||(x=0n);let L=v(R,x);return{name:l,transaction:L,sourceOutputs:[u,...S.map(Y=>et(Y))],sellerInputIndex:0,costs:{priceSats:h,beaconDustSats:I,certificateDustSats:C,chainFeeSats:R?A:E-k,changeSats:x,totalInputSats:E}}}throw new Error("could not converge on a fee \u2014 please retry")}var rs=90n,ss=100n;async function no(t,e,n=D.addressPrefix){let r=(await be(t)).get(String(e).toLowerCase());if(!r?.mintScriptHex)return null;try{let s=eo(r.mintScriptHex),i=ts({bytecode:s,prefix:n,tokenSupport:!1});return typeof i=="string"?null:i.address}catch{return null}}function oo(t){let e=BigInt(t??0n),n=e*rs/ss,o=e-n;return{tldOwnerFeeSats:n,platformFeeSats:o}}var is=b.beaconOnly;async function as({electrum:t=D.electrum,WebSocket:e,beaconOk:n=!1}={}){let o=n?t:t.filter(r=>!is.test(typeof r=="string"?r:r.url||""));return Hn(o,e)}async function ce(t,e){let n=U(e),o=$(n),r=await xt({client:t}),s=r.get(o)??null,i=r.released?.get(o),a=i!==void 0&&!(i>0),c=b.commitReveal?.contestBlocks??0,l=s?{open:!(s.height>0)||(r.height??0)+1<=s.height+c,finalAt:s.height>0?s.height+c+1:null,rank:s.commit?[s.commit.height,s.commit.txid]:[s.height>0?s.height:1/0,s.txid]}:null;return{name:o,rawName:n,available:!s&&!a,entry:s,contest:l,releasedAt:i??null,releasePending:a,reason:s?"registered":a?"release-pending":null,recordBudgetBytes:Fe(n)}}async function le(t,{name:e,ownerAddress:n,records:o={},utxos:r,serviceFee:s=D.serviceFee,feeRate:i=D.feeRate,cosignUtxo:a=null,cosignTokenAddress:c=null,salt:l=null}){let p=r??await K(t,[n]),f=U(e),d=f.indexOf("."),u=d<0?"bch":f.slice(d+1),g=BigInt(s.sats??0n),h=null,O=0n,m=g;if(g>0n){try{h=await no(t,u)}catch{h=null}if(h&&h!==n){let y=oo(g);O=y.tldOwnerFeeSats,m=y.platformFeeSats}}return He({name:e,ownerAddress:n,ownerTokenAddress:Q(n),records:o,utxos:p,feeAddress:m>0n?s.address:null,feeSats:m,tldFeeAddress:O>0n?h:null,tldFeeSats:O,beaconAddress:D.beacon,feeRate:i,addressToLockingBytecode:N,cosignUtxo:a,cosignTokenAddress:c,salt:l})}function ro(t,{tld:e,category:n}){let o=[...new TextEncoder().encode(String(e).toLowerCase())].map(r=>r.toString(16).padStart(2,"0")).join("");return t.find(r=>r.token?.nft&&(!n||r.token.category===n)&&r.token.nft.commitment===o)??null}async function so(t,{wallet:e,utxos:n,feeRate:o,onProgress:r}){if(kt(n))return{utxos:n,prepTxid:null};r("preparing-wallet");let s=Lt({ownerAddress:e.address,utxos:n,feeRate:o,addressToLockingBytecode:N}),i=dt(s.transaction,s.sourceOutputs,l=>e.keyFor(l)),a=await X(t,i.hex);return r("prepared",{txid:a}),{utxos:i.transaction.outputs.slice(0,2).map((l,p)=>({txid:a,vout:p,satoshis:l.valueSatoshis,address:e.address,lockingBytecode:N(e.address)})),prepTxid:a}}async function cs(t,{wallet:e,name:n,records:o={},serviceFee:r=D.serviceFee,feeRate:s=D.feeRate,tldCert:i,onProgress:a=()=>{}}){if(!i?.utxo?.token?.nft||!i.owner)throw new Error("tldCert must be the /api/tld-cert response ({ owner, utxo })");a("checking-availability");let c=await ce(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`);a("loading-coins");let l=await K(t,e.watchedAddresses);if(l.filter(O=>!O.token).reduce((O,m)=>O+m.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let f=null;({utxos:l,prepTxid:f}=await so(t,{wallet:e,utxos:l,feeRate:s,onProgress:a})),a("building");let d=await le(t,{name:n,ownerAddress:e.address,records:o,utxos:l,serviceFee:r,feeRate:s,cosignUtxo:{...i.utxo,address:i.owner},cosignTokenAddress:Q(i.owner)}),u=d.transaction.inputs.length-1;a("signing");let g={...d.transaction,inputs:d.transaction.inputs.map((O,m)=>m===u?{...O,unlockingBytecode:new Uint8Array}:O)},h=bt(g,d.sourceOutputs,O=>e.keyFor(O),{skip:[u]});return{name:d.name,displayName:d.displayName,category:d.category,tx:h.hex,sourceOutputs:d.sourceOutputs.map(je),cosignInputIndex:u,costs:d.costs,prepTxid:f}}function ls(t,e){let n=Zr(eo(String(t.tx||"")));if(typeof n=="string")throw new Error("invalid transaction: "+n);let o=(t.sourceOutputs||[]).map(ze);if(o.length!==n.inputs.length)throw new Error("sourceOutputs do not match the transaction inputs");let r=[],s=0;n.inputs.forEach((a,c)=>{let l=o[c];if(!e(nt(l.lockingBytecode))){r.push(c);return}if(l.token?.nft&&!n.outputs.some(f=>f.token&&nt(f.token.category)===nt(l.token.category)&&nt(f.token.nft?.commitment??new Uint8Array)===nt(l.token.nft.commitment??new Uint8Array)&&nt(f.lockingBytecode)===nt(l.lockingBytecode)&&f.valueSatoshis>=l.valueSatoshis))throw new Error("refusing to sign: the request would not return your TLD certificate to you");s+=1});let i=bt(n,o,e,{skip:r});return{hex:i.hex,txid:i.txid,signedInputs:s}}async function us(t,{wallet:e,name:n,records:o={},serviceFee:r=D.serviceFee,feeRate:s=D.feeRate,cosign:i=null,commit:a=null,onProgress:c=()=>{}}){let l=null;if(a){if(U(a.name)!==U(n))throw new Error("this commit was made for another name");if(a.lock!==nt(N(e.address)))throw new Error("this commit was made for another owner");let y=l=await io(t,a);if(!y.mature)throw new Error(y.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 ce(t,n);if(!p.available){let y=p.contest,_=l&&y&&(l.height<y.rank[0]||l.height===y.rank[0]&&a.txid<y.rank[1]);if(!(y?.open&&_))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:y.finalAt})}c("loading-coins");let f=await K(t,e.watchedAddresses);if(f.filter(y=>!y.token).reduce((y,_)=>y+_.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let u=null;if(i&&(u=ro(f,i),!u))throw new Error(`this wallet does not hold the certificate for .${i.tld} \u2014 only the TLD owner can co-sign`);let g=null;({utxos:f,prepTxid:g}=await so(t,{wallet:e,utxos:f,feeRate:s,onProgress:c})),c("building");let h=await le(t,{name:n,ownerAddress:e.address,records:o,utxos:f,serviceFee:r,feeRate:s,cosignUtxo:u,cosignTokenAddress:u?Q(e.address):null,salt:a?a.salt:null});c("signing");let O=dt(h.transaction,h.sourceOutputs,y=>e.keyFor(y));c("broadcasting");let m=await X(t,O.hex);return c("registered",{txid:m,category:h.category}),{name:h.name,displayName:h.displayName,category:h.category,txid:m,prepTxid:g,ownerAddress:e.address,certificateAddress:Q(e.address),costs:h.costs,hex:O.hex}}async function ds(t,{wallet:e,name:n,certificateLock:o=null,feeRate:r=D.feeRate,onProgress:s=()=>{}}){let i=U(n),a=o??N(e.address),c=Me(),l=ie(c,i,a);s("loading-coins");let p=await K(t,e.watchedAddresses);s("building");let f=Ye({commitment:l,utxos:p,changeAddress:e.address,feeRate:r,addressToLockingBytecode:N});s("signing");let d=dt(f.transaction,f.sourceOutputs,h=>e.keyFor(h)),u={name:i,salt:nt(c),lock:nt(a),commitment:nt(l),txid:d.txid,createdAt:Date.now()};s("committing",{pending:u}),s("broadcasting");let g=await X(t,d.hex);return s("committed",{txid:g,pending:u}),{...u,txid:g,costs:f.costs,hex:d.hex}}async function io(t,e){let n=b.commitReveal??{minAge:1,maxAge:0},o=null;try{o=await Be(t,e.txid,!0)}catch{}let r=o?.confirmations??0;if(!(r>=1))return{confirmations:0,height:null,mature:!1,expired:!1,revealBy:null};let i=(await t.call("blockchain.headers.subscribe",[]))?.height??0,a=i-r+1,c=i+1-a;return{confirmations:r,height:a,mature:c>=n.minAge&&c<=n.maxAge,expired:c>n.maxAge,revealBy:a+n.maxAge}}async function fs(t,{wallet:e,tld:n,records:o={},serviceFee:r={address:null,sats:0n},feeRate:s=D.feeRate,tldListUrl:i=null,onProgress:a=()=>{}}){let c=Bt(n);if(a("checking-availability"),i)try{let h=await fetch(i);if(h.ok){let O=await h.json();if(Array.isArray(O.tlds)&&O.tlds.some(y=>(y.tld||y)===c))throw new Error(`".${c}" is already registered as a TLD`)}}catch(h){if(/already registered/.test(h.message))throw h}a("loading-coins");let l=await K(t,e.watchedAddresses);if(l.filter(h=>!h.token).reduce((h,O)=>h+O.satoshis,0n)===0n)throw new Error("wallet is empty \u2014 fund the address first");let f=null;if(!kt(l)){a("preparing-wallet");let h=Lt({ownerAddress:e.address,utxos:l,feeRate:s,addressToLockingBytecode:N}),O=dt(h.transaction,h.sourceOutputs,m=>e.keyFor(m));f=await X(t,O.hex),a("prepared",{txid:f}),l=[{txid:f,vout:0,satoshis:O.transaction.outputs[0].valueSatoshis,address:e.address,lockingBytecode:N(e.address)},...O.transaction.outputs.length>1?[{txid:f,vout:1,satoshis:O.transaction.outputs[1].valueSatoshis,address:e.address,lockingBytecode:N(e.address)}]:[]]}a("building");let d=ae({tld:c,ownerAddress:e.address,ownerTokenAddress:Q(e.address),changeAddress:e.address,records:o,utxos:l,feeAddress:r.address||null,feeSats:BigInt(r.sats??0n),feeRate:s,addressToLockingBytecode:N});a("signing");let u=dt(d.transaction,d.sourceOutputs,h=>e.keyFor(h));a("broadcasting");let g=await X(t,u.hex);return a("registered",{txid:g,category:d.category}),{tld:d.tld,category:d.category,txid:g,prepTxid:f,ownerAddress:e.address,certificateAddress:Q(e.address),costs:d.costs,hex:u.hex}}async function hs(t,{session:e,tld:n,records:o={},serviceFee:r={address:null,sats:0n},feeRate:s=D.feeRate,tldListUrl:i=null,onProgress:a=()=>{}}){let c=Bt(n);if(a("checking-availability"),i)try{let O=await fetch(i);if(O.ok){let m=await O.json();if(Array.isArray(m.tlds)&&m.tlds.some(_=>(_.tld||_)===c))throw new Error(`".${c}" is already registered as a TLD`)}}catch(O){if(/already registered/.test(O.message))throw O}a("reading-wallet");let l=await e.getAddresses();if(!l.length)throw new Error("the wallet exposed no addresses");let p=l[0];a("loading-coins");let f=await K(t,l);if(f.filter(O=>!O.token).reduce((O,m)=>O+m.satoshis,0n)===0n)throw new Error("the connected wallet has no spendable coins");let d=null;if(!kt(f)){a("preparing-wallet");let O=Lt({ownerAddress:p,utxos:f,feeRate:s,addressToLockingBytecode:N}),m=await e.signTransaction(O,{userPrompt:"One-time setup so your wallet can create a TLD certificate"});d=await Ht(t,e,m,a),a("prepared",{txid:d}),f=[{txid:d,vout:0,satoshis:O.transaction.outputs[0].valueSatoshis,address:p,lockingBytecode:N(p)},...f.filter(y=>!y.token&&!O.inputUtxos.some(_=>_.txid===y.txid&&_.vout===y.vout))]}a("building");let u=ae({tld:c,ownerAddress:p,ownerTokenAddress:Q(p),changeAddress:p,records:o,utxos:f,feeAddress:r.address||null,feeSats:BigInt(r.sats??0n),feeRate:s,addressToLockingBytecode:N});a("awaiting-approval");let g=await e.signTransaction(u,{userPrompt:`Register .${c} \u2014 the TLD certificate is minted to your own address`}),h=await Ht(t,e,g,a);return a("registered",{txid:h,category:u.category}),{tld:u.tld,category:u.category,txid:h,prepTxid:d,ownerAddress:p,certificateAddress:Q(p),costs:u.costs}}async function Ht(t,e,n,o){let r=n.signedTransactionHash??We(n.signedTransaction);if(e.walletBroadcasts)return r;o("broadcasting");try{return await X(t,n.signedTransaction)}catch(s){let i=String(s?.message??s);if(/already|duplicate|txn-already|in mempool/i.test(i))return r;throw s}}async function ps(t,{session:e,name:n,ownerAddress:o,records:r={},serviceFee:s=D.serviceFee,feeRate:i=D.feeRate,onProgress:a=()=>{}}){a("checking-availability");let c=await ce(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`);a("reading-wallet");let l=await e.getAddresses();if(!l.length)throw new Error("the wallet exposed no addresses");let p=o??l[0];a("loading-coins");let f=await K(t,l);if(!f.some(h=>!h.token))throw new Error("the connected wallet has no spendable coins");if(!kt(f)){a("preparing-wallet");let h=Lt({ownerAddress:p,utxos:f,feeRate:i,addressToLockingBytecode:N}),O=await e.signTransaction(h,{userPrompt:"One-time setup so your wallet can create a name certificate"}),m=await Ht(t,e,O,a);a("prepared",{txid:m}),f=[{txid:m,vout:0,satoshis:h.transaction.outputs[0].valueSatoshis,address:p,lockingBytecode:N(p)},...f.filter(y=>!y.token&&!h.inputUtxos.some(_=>_.txid===y.txid&&_.vout===y.vout))]}a("building");let d=await le(t,{name:n,ownerAddress:p,records:r,utxos:f,serviceFee:s,feeRate:i});a("awaiting-approval");let u=await e.signTransaction(d,{userPrompt:`Register ${d.displayName} \u2014 the certificate is minted to your own address`}),g=await Ht(t,e,u,a);return a("registered",{txid:g,category:d.category}),{name:d.name,displayName:d.displayName,category:d.category,txid:g,ownerAddress:p,certificateAddress:Q(p),costs:d.costs}}async function ms(t,{addresses:e,category:n,rawName:o}){let r=await K(t,e),s=[...new TextEncoder().encode(o)].map(i=>i.toString(16).padStart(2,"0")).join("");return r.find(i=>i.token?.category===n&&i.token?.nft?.commitment===s)??null}async function gs(t,{wallet:e,name:n,records:o,feeRate:r=D.feeRate,onProgress:s=()=>{}}){s("resolving");let i=U(n),c=(await xt({client:t})).get($(i));if(!c)throw new Error(`"${$(i)}" is not registered`);s("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 "${$(i)}" \u2014 only the owner can change its records`);s("building");let f=Kt({name:n,ownerAddress:e.address,ownerTokenAddress:Q(e.address),records:o,certificateUtxo:p,utxos:l.filter(g=>!g.token),beaconAddress:D.beacon,feeRate:r,addressToLockingBytecode:N});s("signing");let d=dt(f.transaction,f.sourceOutputs,g=>e.keyFor(g));s("broadcasting");let u=await X(t,d.hex);return s("updated",{txid:u}),{name:f.name,displayName:f.displayName,category:f.category,txid:u,records:o,costs:f.costs}}async function ao(t,e,n=D.beacon){let o=await Be(t,e.txid,!0),r=nt(N(n));return(o?.vout??[]).some(s=>s.scriptPubKey?.hex===r)}async function Os(t,{wallet:e,name:n,feeRate:o=D.feeRate,onProgress:r=()=>{}}){r("resolving");let s=U(n),a=(await xt({client:t})).get($(s));if(!a)throw new Error(`"${$(s)}" is not registered`);r("loading-coins");let c=h=>h.token?.category===a.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 "${$(s)}" \u2014 only the owner can release it`);let f=null;if(!await ao(t,p)){r("anchoring");let h=Kt({name:n,ownerAddress:e.address,ownerTokenAddress:Q(e.address),records:a.records??{},certificateUtxo:p,utxos:l.filter(m=>!m.token),beaconAddress:D.beacon,feeRate:o,addressToLockingBytecode:N}),O=dt(h.transaction,h.sourceOutputs,m=>e.keyFor(m));f=await X(t,O.hex),r("anchored",{txid:f}),p=null;for(let m=0;m<12&&!p;m++)await new Promise(y=>setTimeout(y,1500)),l=await K(t,e.watchedAddresses),p=l.find(y=>c(y)&&y.txid===f)??null;if(!p)throw new Error("the anchoring update was broadcast but is not visible yet \u2014 try the release again in a minute")}r("building");let d=$e({name:n,ownerAddress:e.address,certificateUtxo:p,utxos:l.filter(h=>!h.token),beaconAddress:D.beacon,feeRate:o,addressToLockingBytecode:N});r("signing");let u=dt(d.transaction,d.sourceOutputs,h=>e.keyFor(h));r("broadcasting");let g=await X(t,u.hex);return r("released",{txid:g}),{name:d.name,displayName:d.displayName,category:d.category,txid:g,anchorTxid:f,costs:d.costs}}async function ys(t,{session:e,name:n,records:o,feeRate:r=D.feeRate,onProgress:s=()=>{}}){s("resolving");let i=U(n),c=(await xt({client:t})).get($(i));if(!c)throw new Error(`"${$(i)}" is not registered`);s("reading-wallet");let l=await e.getAddresses(),p=await K(t,l),f=p.find(h=>h.token?.category===c.category&&h.token?.nft);if(!f)throw new Error(`this wallet does not hold the certificate for "${$(i)}" \u2014 only the owner can change its records`);s("building");let d=Kt({name:n,ownerAddress:f.address,ownerTokenAddress:Q(f.address),records:o,certificateUtxo:f,utxos:p.filter(h=>!h.token),beaconAddress:D.beacon,feeRate:r,addressToLockingBytecode:N});s("awaiting-approval");let u=await e.signTransaction(d,{userPrompt:`Point ${d.displayName} somewhere new`}),g=await Ht(t,e,u,s);return s("updated",{txid:g}),{name:d.name,displayName:d.displayName,category:d.category,txid:g,records:o,costs:d.costs}}async function Ps(t,{wallet:e,tld:n,records:o,category:r,feeRate:s=D.feeRate,onProgress:i=()=>{}}){if(!r)throw new Error("setTldRecords requires the TLD certificate's category id");i("loading-coins");let a=await K(t,e.watchedAddresses),c=a.find(d=>d.token?.category===r&&d.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`);i("building");let l=Vn({tld:n,ownerAddress:e.address,ownerTokenAddress:Q(e.address),records:o,certificateUtxo:c,utxos:a.filter(d=>!d.token),feeRate:s,addressToLockingBytecode:N});i("signing");let p=dt(l.transaction,l.sourceOutputs,d=>e.keyFor(d));i("broadcasting");let f=await X(t,p.hex);return i("updated",{txid:f}),{tld:l.tld,displayName:l.displayName,category:l.category,txid:f,records:o,costs:l.costs}}async function _s(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(Je(n)),r=es.hash(ns(o)),s=t.signMessage(r);return{...e,sig:os(s)}}function Je(t){if(t!=null){if(Array.isArray(t))return t.map(Je).filter(e=>e!==void 0);if(typeof t=="object"){let e={};for(let n of Object.keys(t).sort()){let o=Je(t[n]);o!==void 0&&(e[n]=o)}return e}return t}}async function xs(t,e){let n=await K(t,e),o=n.filter(r=>!r.token);return{sats:o.reduce((r,s)=>r+s.satoshis,0n),confirmedSats:o.filter(r=>r.height>0).reduce((r,s)=>r+s.satoshis,0n),coins:o.length,certificates:n.filter(r=>r.token?.nft),hasGenesisInput:kt(n)}}import{hexToBin as Io,binToHex as vo}from"@bitauth/libauth";import{hexToBin as lo,binToHex as Ze,encodeDataPush as tn,bigIntToVmNumber as ws,hash256 as en,encodeLockingBytecodeP2sh32 as bs,encodeLockingBytecodeP2pkh as Ts,lockingBytecodeToCashAddress as Es,secp256k1 as ks,generateSigningSerializationBCH as Ss,encodeTransaction as co,flattenBinArray as Yt,OpcodesBCH as As}from"@bitauth/libauth";var Pt=t=>tn(ws(BigInt(t))),ot=t=>tn(t),rt=t=>t instanceof Uint8Array?t:lo(t),uo=t=>Ts(rt(t));function nn(t){let e=n=>{let o=As[n];if(o===void 0)throw new Error("unknown opcode "+n);return Uint8Array.of(o)};return Yt(t.trim().split(/\s+/).filter(Boolean).map(n=>n.startsWith("OP_")?e(n):tn(lo(n))))}var fo=t=>Object.fromEntries(t.abi.map((e,n)=>[e.name,n]));var ho=t=>bs(en(t));function on(t,e=b.prefix,n=!0){let o=Es({bytecode:t,prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(o);return o.address}function po(t,e,n,o,r){let s=Ss({inputIndex:n,sourceOutputs:e,transaction:t},{coveredBytecode:o,signingSerializationType:Uint8Array.of(St)}),i=ks.signMessageHashSchnorr(r,en(s));if(typeof i=="string")throw new Error(i);return Yt([i,Uint8Array.of(St)])}var mo=new Uint8Array(65),go=new Uint8Array(33),rn=Symbol("sig"),sn=Symbol("pubkey");function Oo({selector:t=null,redeem:e,args:n=[],key:o=null,transaction:r,sourceOutputs:s,inputIndex:i}){let a=n.map(c=>c===rn?ot(o?po(r,s,i,e,o.privateKey):mo):c===sn?ot(o?o.publicKey:go):typeof c=="number"||typeof c=="bigint"?Pt(c):ot(rt(c))).reverse();return Yt([...a,...t===null?[]:[Pt(t)],ot(e)])}function yo(t,e){return{utxo:t,unlock:(n,o,r,s)=>{if(!s)return Yt([ot(mo),ot(go)]);let i=o[r].lockingBytecode,a=e(Ze(i));if(!a)throw new Error(`no key for the coin at input ${r}`);return Yt([ot(po(n,o,r,i,a.privateKey)),ot(a.publicKey)])}}}var Is=(t,e)=>({...t,sequenceNumber:e});function $t({special:t,outputs:e,extra:n=[],coins:o=[],changeLock:r=null,keyFor:s=()=>null,locktime:i=0,feeRate:a=1,noChange:c=!1,tamper:l=null}){let p=[...e,...n],f=p.reduce((h,O)=>h+O.valueSatoshis,0n)-t.reduce((h,O)=>h+BigInt(O.utxo.satoshis),0n),d=[...o].filter(h=>!h.token).sort((h,O)=>BigInt(O.satoshis)>BigInt(h.satoshis)?1:-1),u=[],g=0n;for(let h=0;h<=d.length;h++){let O=(_,k,T)=>{let P=[...t.map(x=>et(x.utxo)),...u.map(x=>et(x))],B={version:2,locktime:i,inputs:[...t.map(x=>Is(Z(x.utxo),x.sequence??4294967294)),...u.map(x=>Z(x))],outputs:[...p,..._?[{lockingBytecode:r,valueSatoshis:k}]:[]]},S=T&&l?l(B):B,E=P.map((x,R)=>({...x,sequenceNumber:S.inputs[R].sequenceNumber})),v=t.map((x,R)=>R),A=T?bt(S,E,s,{skip:v}).transaction:S,w=A.inputs.map((x,R)=>R<t.length?{...x,unlockingBytecode:t[R].unlock(A,E,R,T)}:x);return{transaction:{...A,inputs:w},sourceOutputs:E}},m=!c&&!!r,y=BigInt(Math.ceil((co(O(m,1000000n,!1).transaction).length+u.length*107)*a));if(g>=f+y){let _=g-f-y,k=m&&_>=F,T=O(k,_,!0),P=co(T.transaction);return{...T,hex:Ze(P),txid:Ze(en(P).slice().reverse()),feeSats:k?y:g-f,changeSats:k?_:0n}}if(h===d.length)break;u.push(d[h]),g+=BigInt(d[h].satoshis)}throw new Error(`not enough funds: need ${f} sat plus the fee, have ${g} sat`)}import{binToHex as Gt,hash256 as xa,utf8ToBin as wa,numberToBinUint32LE as Us,binToNumberUint32LE as ba,secp256k1 as Ta,sha256 as Ea,flattenBinArray as ln}from"@bitauth/libauth";var an={contractName:"NameRegistry",constructorInputs:[{name:"fundLock",type:"bytes"},{name:"stewardPk",type:"pubkey"},{name:"commitBoxCode",type:"bytes"},{name:"renewalSats",type:"int"},{name:"premiumSats",type:"int"},{name:"floorSats",type:"int"},{name:"graceBlocks",type:"int"},{name:"blocksPerYear",type:"int"},{name:"ownerPercentIdle",type:"int"},{name:"expiry",type:"bytes4"},{name:"ownerPkh",type:"bytes20"}],abi:[{name:"renew",inputs:[{name:"pk",type:"pubkey"},{name:"s",type:"sig"},{name:"years",type:"int"}]},{name:"transfer",inputs:[{name:"pk",type:"pubkey"},{name:"s",type:"sig"},{name:"newOwnerPkh",type:"bytes20"}]},{name:"takeover",inputs:[{name:"newOwnerPkh",type:"bytes20"},{name:"salt",type:"bytes"}]},{name:"release",inputs:[{name:"pk",type:"pubkey"},{name:"s",type:"sig"}]},{name:"migrate",inputs:[{name:"pk",type:"pubkey"},{name:"s",type:"sig"},{name:"approval",type:"datasig"},{name:"newCode",type:"bytes"}]}],bytecode:"OP_11 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_12 OP_PICK OP_HASH160 OP_11 OP_PICK OP_EQUALVERIFY OP_13 OP_ROLL OP_13 OP_ROLL OP_CHECKSIGVERIFY OP_12 OP_PICK OP_1 OP_GREATERTHANOREQUAL OP_VERIFY OP_9 OP_ROLL OP_BIN2NUM OP_12 OP_PICK OP_9 OP_ROLL OP_MUL OP_ADD OP_DUP 0065cd1d OP_LESSTHAN OP_VERIFY 14 OP_10 OP_ROLL OP_CAT OP_4 OP_CAT OP_SWAP OP_4 OP_NUM2BIN OP_CAT OP_ACTIVEBYTECODE 1a OP_SPLIT OP_NIP OP_CAT OP_HASH256 OP_0 OP_OUTPUTBYTECODE aa20 OP_ROT OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_INPUTINDEX OP_UTXOVALUE OP_GREATERTHANOREQUAL OP_VERIFY OP_1 OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTVALUE OP_3 OP_ROLL OP_9 OP_ROLL OP_MUL OP_GREATERTHANOREQUAL OP_VERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_2DROP OP_2DROP OP_2DROP OP_DROP OP_1 OP_ELSE OP_11 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_14 OP_ROLL OP_SIZE 14 OP_EQUALVERIFY OP_13 OP_PICK OP_HASH160 OP_12 OP_ROLL OP_EQUALVERIFY OP_13 OP_ROLL OP_13 OP_ROLL OP_CHECKSIGVERIFY 14 OP_SWAP OP_CAT OP_4 OP_CAT OP_10 OP_ROLL OP_CAT OP_ACTIVEBYTECODE 1a OP_SPLIT OP_NIP OP_CAT OP_HASH256 OP_0 OP_OUTPUTBYTECODE aa20 OP_ROT OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_INPUTINDEX OP_UTXOVALUE OP_GREATERTHANOREQUAL OP_VERIFY OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE OP_11 OP_PICK OP_2 OP_NUMEQUAL OP_IF OP_12 OP_ROLL OP_SIZE 14 OP_EQUALVERIFY OP_10 OP_ROLL OP_BIN2NUM OP_DUP OP_CHECKLOCKTIMEVERIFY OP_DROP OP_TXLOCKTIME OP_DUP 0065cd1d OP_LESSTHAN OP_VERIFY OP_SWAP OP_9 OP_PICK OP_ADD OP_8 OP_PICK OP_0 OP_2OVER OP_LESSTHAN OP_IF OP_10 OP_PICK OP_10 OP_PICK OP_12 OP_PICK OP_SUB OP_4 OP_PICK OP_6 OP_PICK OP_SUB OP_MUL OP_13 OP_PICK OP_DIV OP_ADD OP_ROT OP_DROP OP_SWAP OP_OVER OP_14 OP_PICK OP_MUL 64 OP_DIV OP_NIP OP_ENDIF OP_16 OP_PICK OP_SIZE OP_NIP 20 OP_NUMEQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT 11 OP_ROLL OP_CAT OP_HASH256 14 OP_6 OP_PICK OP_CAT 20 OP_CAT OP_SWAP OP_CAT OP_8 OP_ROLL OP_CAT OP_1 OP_UTXOBYTECODE aa20 OP_ROT OP_HASH256 OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_3 OP_PICK OP_12 OP_PICK OP_ADD 0065cd1d OP_LESSTHAN OP_VERIFY 14 OP_5 OP_ROLL OP_CAT OP_4 OP_CAT OP_4 OP_ROLL OP_11 OP_ROLL OP_ADD OP_4 OP_NUM2BIN OP_CAT OP_ACTIVEBYTECODE 1a OP_SPLIT OP_NIP OP_CAT OP_HASH256 OP_0 OP_OUTPUTBYTECODE aa20 OP_ROT OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_INPUTINDEX OP_UTXOVALUE OP_GREATERTHANOREQUAL OP_VERIFY OP_1 OP_OUTPUTBYTECODE OP_4 OP_ROLL OP_EQUALVERIFY OP_1 OP_OUTPUTVALUE OP_ROT OP_2 OP_PICK OP_SUB OP_GREATERTHANOREQUAL OP_VERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_DUP OP_0 OP_GREATERTHAN OP_IF OP_2 OP_OUTPUTBYTECODE 76a914 OP_10 OP_PICK OP_CAT 88ac OP_CAT OP_EQUALVERIFY OP_2 OP_OUTPUTVALUE OP_OVER OP_GREATERTHANOREQUAL OP_VERIFY OP_2 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE OP_11 OP_PICK OP_3 OP_NUMEQUAL OP_IF OP_12 OP_PICK OP_HASH160 OP_11 OP_ROLL OP_EQUALVERIFY OP_12 OP_ROLL OP_12 OP_ROLL OP_CHECKSIGVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_TXOUTPUTCOUNT OP_4 OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_OVER OP_EQUAL OP_NOT OP_VERIFY OP_TXOUTPUTCOUNT OP_1 OP_GREATERTHAN OP_IF OP_1 OP_OUTPUTTOKENCATEGORY OP_OVER OP_EQUAL OP_NOT OP_VERIFY OP_ENDIF OP_TXOUTPUTCOUNT OP_2 OP_GREATERTHAN OP_IF OP_2 OP_OUTPUTTOKENCATEGORY OP_OVER OP_EQUAL OP_NOT OP_VERIFY OP_ENDIF OP_TXOUTPUTCOUNT OP_3 OP_GREATERTHAN OP_IF OP_3 OP_OUTPUTTOKENCATEGORY OP_OVER OP_EQUAL OP_NOT OP_VERIFY OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE OP_11 OP_ROLL OP_4 OP_NUMEQUALVERIFY OP_11 OP_PICK OP_HASH160 OP_11 OP_PICK OP_EQUALVERIFY OP_12 OP_ROLL OP_12 OP_ROLL OP_CHECKSIGVERIFY OP_ACTIVEBYTECODE 1a OP_SPLIT OP_NIP OP_HASH256 OP_12 OP_ROLL OP_SWAP OP_13 OP_PICK OP_HASH256 OP_CAT OP_HASH256 OP_3 OP_ROLL OP_CHECKDATASIGVERIFY 14 OP_10 OP_ROLL OP_CAT OP_4 OP_CAT OP_9 OP_ROLL OP_CAT OP_9 OP_ROLL OP_CAT OP_HASH256 OP_0 OP_OUTPUTBYTECODE aa20 OP_ROT OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_INPUTINDEX OP_UTXOVALUE OP_GREATERTHANOREQUAL OP_VERIFY OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF",compiler:{name:"cashc",version:"0.13.3",options:{enforceFunctionParameterTypes:!0,enforceLocktimeGuard:!0}}};var Po={contractName:"CommitBox",constructorInputs:[{name:"commitHash",type:"bytes32"},{name:"ownerPkh",type:"bytes20"}],abi:[{name:"spend",inputs:[{name:"pk",type:"pubkey"},{name:"s",type:"sig"}]}],bytecode:"OP_2 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_ROT OP_ROT OP_CHECKSIGVERIFY OP_1 OP_CHECKSEQUENCEVERIFY OP_DROP OP_SIZE OP_NIP 20 OP_NUMEQUAL",compiler:{name:"cashc",version:"0.13.3",options:{enforceFunctionParameterTypes:!0,enforceLocktimeGuard:!0}}};var vs=[{tier:1,maxLength:2,renewalSats:2000000n},{tier:2,maxLength:4,renewalSats:500000n},{tier:3,maxLength:7,renewalSats:200000n},{tier:4,maxLength:1/0,renewalSats:100000n}],Rs=50n,Bs=5n;function cn(t){let e=vs.find(n=>n.tier===t);if(!e)throw new Error(`unknown tier ${t}`);return e}var _o=(t,e=1)=>cn(t).renewalSats*BigInt(e),xo=t=>cn(t).renewalSats*Rs,wo=t=>cn(t).renewalSats*Bs;var bo={ownerPercentIdle:30n,ownerPercentOpen:0n,minerPercent:0n};var Cs=nn(an.bytecode),Ds=nn(Po.bytecode),Fs=fo(an);function To({tier:t,fundLock:e,stewardPk:n}){let o=rt(e),r=rt(n);if(r.length!==33)throw new Error("stewardPk must be a 33-byte compressed public key");if(!o.length)throw new Error("fundLock is required");return{tier:t,fundLock:o,stewardPk:r,commitBoxCode:Ds,renewalSats:_o(t),premiumSats:xo(t),floorSats:wo(t),graceBlocks:26280,blocksPerYear:52560,ownerPercentIdle:bo.ownerPercentIdle}}function Ms(t){return ln([Pt(t.ownerPercentIdle),Pt(t.blocksPerYear),Pt(t.graceBlocks),Pt(t.floorSats),Pt(t.premiumSats),Pt(t.renewalSats),ot(t.commitBoxCode),ot(t.stewardPk),ot(t.fundLock),Cs])}function Ks({ownerPkh:t,expiry:e}){let n=rt(t);if(n.length!==20)throw new Error("ownerPkh must be 20 bytes");if(!Number.isInteger(e)||e<=0||e>=2147483647)throw new Error("expiry must be a block height");return ln([Uint8Array.of(20),n,Uint8Array.of(4),Us(e)])}var ue=(t,e)=>ln([Ks(e),Ms(t)]),Vt=(t,e)=>ho(ue(t,e));var Hs=t=>({o:Gt(rt(t.ownerPkh)),e:t.expiry});function Eo({name:t,records:e={},beaconLock:n,salt:o=null},r,s="UPD"){if(!n)throw new Error("announce.beaconLock is required");let i=q(s,U(t),e,r?Hs(r):null,o?Gt(rt(o)):null);return[{lockingBytecode:j(i),valueSatoshis:0n},{lockingBytecode:rt(n),valueSatoshis:I}]}var un=(t,e,n,o)=>t?[...Eo(t,e,o),...n]:n;function ko({cert:t,terms:e,name:n,records:o={},ownerPkh:r,height:s,years:i=1,beaconLock:a,coins:c,changeLock:l,keyFor:p,feeRate:f=1}){if(!Number.isInteger(i)||i<1)throw new Error("years must be a whole number, at least 1");if(!t.token)throw new Error("cert must be the certificate's UTXO");let d={ownerPkh:Gt(rt(r)),expiry:s+i*e.blocksPerYear};return{...$t({special:[yo(t,p)],outputs:[dn(Vt(e,d),t),{lockingBytecode:e.fundLock,valueSatoshis:BigInt(e.renewalSats)*BigInt(i)}],extra:Eo({name:n,records:o,beaconLock:a},d),coins:c,changeLock:l,keyFor:p,feeRate:f}),state:d}}var dn=(t,e)=>({lockingBytecode:t,valueSatoshis:BigInt(e.satoshis)<C?C:BigInt(e.satoshis),token:ft(e.token)}),fn=(t,e)=>{let n=t(Gt(uo(e.ownerPkh)));if(!n)throw new Error("this wallet does not hold the owner key of this name");return n},hn=(t,e,n,o,r)=>({utxo:t,unlock:(s,i,a,c)=>Oo({selector:Fs[n],redeem:e,transaction:s,sourceOutputs:i,inputIndex:a,key:c?o:null,args:n==="takeover"?r:[sn,rn,...r]})});function So({cov:t,terms:e,state:n,years:o=1,coins:r,changeLock:s,keyFor:i,announce:a=null,extra:c=[],feeRate:l=1,tamper:p=null}){if(!Number.isInteger(o)||o<1)throw new Error("years must be a whole number, at least 1");let f=ue(e,n),d={ownerPkh:n.ownerPkh,expiry:n.expiry+o*e.blocksPerYear};return{...$t({special:[hn(t,f,"renew",fn(i,n),[o])],outputs:[dn(Vt(e,d),t),{lockingBytecode:e.fundLock,valueSatoshis:BigInt(e.renewalSats)*BigInt(o)}],extra:un(a,d,c),coins:r,changeLock:s,keyFor:i,feeRate:l,tamper:p}),state:d}}function pn({cov:t,terms:e,state:n,newOwnerPkh:o,coins:r,changeLock:s,keyFor:i,announce:a=null,extra:c=[],feeRate:l=1,tamper:p=null}){let f=ue(e,n),d={ownerPkh:Gt(rt(o)),expiry:n.expiry};return{...$t({special:[hn(t,f,"transfer",fn(i,n),[rt(o)])],outputs:[dn(Vt(e,d),t)],extra:un(a,d,c),coins:r,changeLock:s,keyFor:i,feeRate:l,tamper:p}),state:d}}function Ao({cov:t,terms:e,state:n,coins:o=[],changeLock:r,keyFor:s,announce:i=null,extra:a=[],feeRate:c=1,tamper:l=null}){if(a=un(i?{...i,records:{}}:null,null,a,"REL"),a.length>3)throw new Error("a release may have at most four outputs in total");let p=ue(e,n);return $t({special:[hn(t,p,"release",fn(s,n),[])],outputs:[{lockingBytecode:r,valueSatoshis:F}],extra:a,coins:o,changeLock:r,keyFor:s,feeRate:c,tamper:l})}var Ro=(t=b)=>{if(!t.covenant)throw new Error(`${t.label} has no registry covenant yet`);return t.covenant},Wt=()=>N(b.beacon),Nt=t=>N(t.address),Bo=t=>vo(Nt(t).slice(3,23)),Qt=t=>e=>t.keyFor(e),de=async(t,e)=>(await K(t,e.watchedAddresses)).filter(n=>!n.token),Lo=t=>[...new TextEncoder().encode(U(t))].map(e=>e.toString(16).padStart(2,"0")).join("");function fe(t,e=b){let n=Ro(e),o=Ee($(U(t)),n)+1;if(o<1)throw new Error(`no price tier fits "${t}"`);return To({tier:o,fundLock:Io(n.fundLock),stewardPk:Io(n.steward)})}function Ys(t,e=b){let n=fe(t,e);return{tier:n.tier,yearSats:BigInt(n.renewalSats),blocksPerYear:n.blocksPerYear,graceBlocks:n.graceBlocks}}function $s(t,e,n=b){let o=Ro(n),r=t.covenant.expiry,s=r+o.graceBlocks,i=e<r?"active":e<s?"idle":"open";return{status:i,expiry:r,idleEnd:s,blocksLeft:i==="active"?r-e:i==="idle"?s-e:0}}var Gs=t=>{if(!t?.covenant)throw new Error(`${t?.name??"this name"} is not held by the covenant`);return{ownerPkh:t.covenant.ownerPkh,expiry:t.covenant.expiry}};async function Xt(t,e){let n=Gs(e),o=fe(e.name),r=Vt(o,n),i=(await re(t,on(r,b.prefix))).find(a=>a.token?.category===e.category&&a.token?.nft?.commitment===Lo(e.name));if(!i)throw new Error(`the certificate of ${e.name} is not at the covenant address the registry last saw \u2014 it was moved, renewed or taken over without an announcement`);return{cov:{...i,lockingBytecode:r},state:n,terms:o}}var he=(t,e)=>{if(Bo(t)!==e.ownerPkh)throw new Error("this wallet does not hold the owner key of this name")},qt=async(t,e,n,o)=>{n("broadcasting");let r=await X(t,e.hex);return n(o,{txid:r}),{txid:r,hex:e.hex,feeSats:e.feeSats,state:e.state??null}};async function Vs(t,{wallet:e,entry:n,years:o=1,onProgress:r=()=>{}}){if(n.covenant)throw new Error(`${n.name} is already held by the covenant`);let s=fe(n.name);r("loading-coins");let i=await K(t,e.watchedAddresses),a=i.find(p=>p.token?.category===n.category&&p.token?.nft?.commitment===Lo(n.name));if(!a)throw new Error("certificate not found in this wallet (already moved?)");let c=await t.call("blockchain.headers.subscribe",[]);if(!(c?.height>0))throw new Error("could not read the chain height");r("building");let l=ko({cert:a,terms:s,name:n.name,records:n.records??{},ownerPkh:Bo(e),height:c.height,years:o,beaconLock:Wt(),coins:i.filter(p=>!p.token),changeLock:Nt(e),keyFor:Qt(e)});return qt(t,l,r,"entered")}async function Ws(t,{wallet:e,entry:n,years:o=1,onProgress:r=()=>{}}){r("resolving");let{cov:s,state:i,terms:a}=await Xt(t,n);he(e,i),r("building");let c=So({cov:s,terms:a,state:i,years:o,announce:{name:n.name,records:n.lapsedRecords??n.records??{},beaconLock:Wt()},coins:await de(t,e),changeLock:Nt(e),keyFor:Qt(e)});return qt(t,c,r,"renewed")}async function Qs(t,{wallet:e,entry:n,records:o,onProgress:r=()=>{}}){r("resolving");let{cov:s,state:i,terms:a}=await Xt(t,n);he(e,i),r("building");let c=pn({cov:s,terms:a,state:i,newOwnerPkh:i.ownerPkh,announce:{name:n.name,records:o??{},beaconLock:Wt()},coins:await de(t,e),changeLock:Nt(e),keyFor:Qt(e)});return qt(t,c,r,"updated")}async function Xs(t,{wallet:e,entry:n,toAddress:o,onProgress:r=()=>{}}){let s=N(o);if(s.length!==25||s[0]!==118)throw new Error("a covenant-held name can only be transferred to an ordinary address, not a script address");r("resolving");let{cov:i,state:a,terms:c}=await Xt(t,n);he(e,a),r("building");let l=pn({cov:i,terms:c,state:a,newOwnerPkh:vo(s.slice(3,23)),announce:{name:n.name,records:n.records??{},beaconLock:Wt()},coins:await de(t,e),changeLock:Nt(e),keyFor:Qt(e)});return qt(t,l,r,"transferred")}async function qs(t,{wallet:e,entry:n,onProgress:o=()=>{}}){o("resolving");let{cov:r,state:s,terms:i}=await Xt(t,n);he(e,s),o("building");let a=Ao({cov:r,terms:i,state:s,announce:{name:n.name,beaconLock:Wt()},coins:await de(t,e),changeLock:Nt(e),keyFor:Qt(e)});return qt(t,a,o,"released")}import{hexToBin as st,binToHex as ht,encodeDataPush as G,bigIntToVmNumber as me,hash256 as mn,hash160 as js,encodeLockingBytecodeP2sh32 as zs,encodeLockingBytecodeP2pkh as Do,lockingBytecodeToCashAddress as Js,OpcodesBCH as Zs,numberToBinUint32LE as Ya,binToNumberUint32LE as Uo,secp256k1 as Fo,sha256 as ti,generateSigningSerializationBCH as ei,encodeTransaction as Mo,flattenBinArray as Ut}from"@bitauth/libauth";var No={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 ni=2,gn=1200,oi=7200,ri=t=>{let e=Zs[t];if(e===void 0)throw new Error("unknown opcode "+t);return Uint8Array.of(e)};function si(t){let e=t.trim().split(/\s+/).filter(Boolean).map(n=>n.startsWith("OP_")?ri(n):G(st(n)));return Ut(e)}var ii=si(No.bytecode),pe=t=>G(me(BigInt(t))),ai=0,Co=1;function ci(t){let e=st(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 ht(e.slice(3,23))}function On({oraclePk:t,sellerPkh:e,targetCents:n,floorSats:o,ceilSats:r,maxAgeSecs:s=gn}){if(!(BigInt(n)>0n)||!(BigInt(o)>0n)||BigInt(r)<BigInt(o))throw new Error("bad listing terms");return Ut([pe(s),pe(r),pe(o),pe(n),G(st(e)),G(st(t)),ii])}var ge=t=>zs(mn(t));function yn(t,e=b.prefix){let n=Js({bytecode:ge(t),prefix:e});if(typeof n=="string")throw new Error(n);return n.address}function Ko({targetCents:t,priceCents:e,floorSats:n,ceilSats:o}){let r=BigInt(t)*100000000n/BigInt(e);return r<BigInt(n)&&(r=BigInt(n)),r>BigInt(o)&&(r=BigInt(o)),r}var Ho=t=>({ts:Uo(t.slice(0,4)),priceCents:Uo(t.slice(4,8)),outpointTxid:ht(t.slice(8,40).slice().reverse())});function Yo(t,e,n){return Fo.verifySignatureSchnorr(n,t,ti.hash(e))===!0}var Pn=(t,e,n,o,{requireGenesis:r=!1}={})=>{let s=M(t,e+600n,{requireGenesis:r});for(let i=0;i<6;i++){let{inputs:a,totalSats:c}=s,l=o(a,!0,1000000n),p=BigInt(Math.ceil(Mo(l.transaction).length*n)),f=e+p;if(c<f){let g=M(t,f+200n,{requireGenesis:r});if(g.inputs.length>a.length){s=g;continue}let h=new Error(`not enough funds: need ${f} sat, have ${c} sat`);throw h.needSats=f,h.haveSats=c,h}let d=c-f,u=d>=F;return u||(d=0n),{...o(a,u,d),fee:u?p:c-e,change:d}}throw new Error("could not converge on a fee \u2014 please retry")};function li({name:t,certificateUtxo:e,utxos:n,sellerAddress:o,oraclePk:r,targetCents:s,floorSats:i,ceilSats:a,maxAgeSecs:c=gn,records:l={},beaconAddress:p=gt,feeRate:f=1,addressToLockingBytecode:d}){let u=U(t);if(!e?.token?.nft)throw new Error("certificateUtxo does not carry a certificate");let g=d(o),h=ci(ht(d(e.address||o))),O=On({oraclePk:r,sellerPkh:h,targetCents:s,floorSats:i,ceilSats:a,maxAgeSecs:c}),m=ge(O),y=q("UPD",u,l),_=n.filter(P=>!P.token),k=C+I-BigInt(e.satoshis);return{...Pn(_,k>0n?k:0n,f,(P,B,S)=>({transaction:{version:2,locktime:0,inputs:[Z(e),...P.map(E=>Z(E))],outputs:[{lockingBytecode:m,valueSatoshis:C,token:ft(e.token)},{lockingBytecode:j(y),valueSatoshis:0n},{lockingBytecode:d(p),valueSatoshis:I},...B?[{lockingBytecode:g,valueSatoshis:S}]:[]]},sourceOutputs:[et(e),...P.map(E=>et(E))]})),name:u,redeem:O,redeemHex:ht(O),address:yn(O,o.split(":")[0]),sellerPkh:h,covenantVout:0}}function $o(t){let e=st(t.redeem_hex);return{redeem:e,utxo:{txid:t.outpoint.txid,vout:t.outpoint.vout,satoshis:BigInt(t.outpoint.satoshis??C),lockingBytecode:ge(e),token:t.token}}}function ui({listing:t,quote:e,buyerAddress:n,buyerTokenAddress:o,utxos:r,records:s={},beaconAddress:i=gt,feeRate:a=1,addressToLockingBytecode:c}){let l=U(t.name),p=st(e.message),f=st(e.signature);if(!Yo(st(t.oracle_pk),p,f))throw new Error("oracle signature does not verify against the listing's oracle key");let{ts:d,priceCents:u,outpointTxid:g}=Ho(p);if(g!==String(t.outpoint.txid).toLowerCase())throw new Error("quote was issued for a different listing");let h=Ko({targetCents:t.target_cents,priceCents:u,floorSats:t.floor_sats,ceilSats:t.ceil_sats}),{redeem:O,utxo:m}=$o(t),y=Do(st(t.seller_pkh)),_=Ut([G(f),G(p),G(me(BigInt(ai))),G(O)]),k=c(n),T=c(o??n),P=q("UPD",l,s),B=r.filter(v=>!v.token),S=h+C+I-m.satoshis;return{...Pn(B,S,a,(v,A,w)=>({transaction:{version:2,locktime:Math.max(0,d-oi),inputs:[Z(m,_),...v.map(x=>Z(x))],outputs:[{lockingBytecode:y,valueSatoshis:h},{lockingBytecode:T,valueSatoshis:C,token:ft(m.token)},{lockingBytecode:j(P),valueSatoshis:0n},{lockingBytecode:c(i),valueSatoshis:I},...A?[{lockingBytecode:k,valueSatoshis:w}]:[]]},sourceOutputs:[et(m),...v.map(x=>et(x))]})),name:l,covenantInputIndex:0,priceSats:h,priceCents:u,quoteTs:d}}function di({listing:t,sellerAddress:e,sellerTokenAddress:n,utxos:o,records:r={},beaconAddress:s=gt,feeRate:i=1,addressToLockingBytecode:a,keyFor:c}){let l=U(t.name),{redeem:p,utxo:f}=$o(t),d=Do(st(t.seller_pkh)),u=c(ht(d));if(!u)throw new Error("this wallet does not hold the seller key for this listing");let g=u.privateKey,h=u.publicKey,O=a(n??e),m=q("UPD",l,r),y=o.filter(x=>!x.token),_=C+I-f.satoshis,k=Ut([G(new Uint8Array(65)),G(h),G(me(BigInt(Co))),G(p)]),T=Pn(y,_>0n?_:0n,i,(x,R,L)=>({transaction:{version:2,locktime:0,inputs:[Z(f,k),...x.map(Y=>Z(Y))],outputs:[{lockingBytecode:O,valueSatoshis:C,token:ft(f.token)},{lockingBytecode:j(m),valueSatoshis:0n},{lockingBytecode:a(s),valueSatoshis:I},...R?[{lockingBytecode:a(e),valueSatoshis:L}]:[]]},sourceOutputs:[et(f),...x.map(Y=>et(Y))]})),P=bt(T.transaction,T.sourceOutputs,c,{skip:[0]}),B=ei({inputIndex:0,sourceOutputs:T.sourceOutputs,transaction:P.transaction},{coveredBytecode:p,signingSerializationType:Uint8Array.of(St)}),S=Fo.signMessageHashSchnorr(g,mn(B));if(typeof S=="string")throw new Error(S);let E=Ut([S,Uint8Array.of(St)]),v=Ut([G(E),G(h),G(me(BigInt(Co))),G(p)]),A={...P.transaction,inputs:P.transaction.inputs.map((x,R)=>R===0?{...x,unlockingBytecode:v}:x)},w=Mo(A);return{name:l,transaction:A,sourceOutputs:T.sourceOutputs,hex:ht(w),txid:ht(mn(w).slice().reverse())}}function fi(t,{oraclePk:e}={}){let n=o=>({ok:!1,error:o});try{if(t?.kind!=="usd"||t.v!==ni)return n("not a v2 usd listing");for(let s 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[s]==null)return n("missing "+s);if(e&&t.oracle_pk!==e)return n("listing was made for a different oracle key");let o=On({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(ht(o)!==t.redeem_hex)return n("redeem script does not match the stated terms");let r=String(t.seller).split(":")[0]||b.prefix;return yn(o,r)!==t.covenant_address?n("covenant address does not match"):ht(js(st(t.seller_pkh))).length!==40?n("bad seller pkh"):t.token?.category!==t.category||!t.token?.nft?n("token does not match category"):st(t.token.nft.commitment||"").length===0||ht(new TextEncoder().encode(U(t.name)))!==t.token.nft.commitment?n("commitment does not match the name"):{ok:!0,name:U(t.name),covenant_lock:ht(ge(o))}}catch(o){return n(String(o?.message||o))}}import{hash160 as hi,lockingBytecodeToCashAddress as pi,binToHex as qa}from"@bitauth/libauth";function Go(t){return Uint8Array.from([118,169,20,...hi(t),136,172])}function mi(t,e=b.prefix,n=!1){let o=pi({bytecode:Go(t),prefix:e,tokenSupport:n});if(typeof o=="string")throw new Error(`address encoding failed: ${o}`);return o.address}function gi(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 hc,hexToBin as pc}from"@bitauth/libauth";import{stringify as gc}from"@bitauth/libauth";export{Ie as BuiltInWallet,Ir as CHIPNET_PREFIX,gn as DEFAULT_MAX_AGE_SECS,An as DEFAULT_NETWORK_ID,Mt as DEFAULT_PREFIX,J as InsufficientFundsError,vr as MAINNET_PREFIX,b as NETWORK,vt as NETWORKS,se as NoGenesisInputError,D as REGISTRAR,Rt as REG_SALT_BYTES,De as TLD_BEACON,N as addressToLockingBytecode,Dr as addressToScripthash,hc as binToHex,X as broadcast,Ye as buildCommitTx,cs as buildCosignRequest,xt as buildIndex,qr as buildListing,Lt as buildPrepTx,He as buildRegistrationTx,$e as buildReleaseTx,ae as buildTldRegistrationTx,Kt as buildUpdateTx,ui as buildUsdBuyTx,di as buildUsdCancelTx,li as buildUsdListingTx,ce as checkAvailability,io as commitState,ds as commitWithBuiltInWallet,ie as commitmentHash,Jr as completeSale,as as connect,$s as covenantLifecycle,Ys as covenantQuote,fe as covenantTerms,gi as describeGenesisRequirement,$ as displayName,Vs as enterCovenantWithBuiltInWallet,ms as findCertificateUtxo,Xt as findCovenantUtxo,ro as findTldCertificateUtxo,no as findTldOwnerAddress,xs as getBalance,lt as getNetwork,re as getUtxos,K as getUtxosForAddresses,kt as hasGenesisInput,pc as hexToBin,ao as isAnchored,Me as newRegistrationSalt,U as normalizeName,Bt as normalizeTld,Ho as parseOracleMessage,Fe as payloadBudget,Ko as payoutSats,Qr as priceSummary,mi as pubkeyToAddress,Go as pubkeyToLockingBytecode,le as quoteRegistration,fs as registerTldWithBuiltInWallet,hs as registerTldWithExternalWallet,us as registerWithBuiltInWallet,ps as registerWithExternalWallet,qs as releaseCovenantNameWithBuiltInWallet,Os as releaseWithBuiltInWallet,Ws as renewCovenantNameWithBuiltInWallet,Pe as requireBeacons,wr as resolveName,Qs as setCovenantRecordsWithBuiltInWallet,gs as setRecordsWithBuiltInWallet,ys as setRecordsWithExternalWallet,Ps as setTldRecordsWithBuiltInWallet,ls as signCosignRequest,bt as signInputs,_s as signRecordsManifest,dt as signTransaction,ze as sourceOutputFromJson,je as sourceOutputToJson,oo as splitServiceFee,gc as stringify,Q as toTokenAddress,Wn as toWcTransactionObject,Xs as transferCovenantNameWithBuiltInWallet,Ve as txidOf,We as txidOfHex,yn as usdListingAddress,On as usdListingRedeem,to as verifyListing,Yo as verifyOracleMessage,fi as verifyUsdListing};
|