@babylonlabs-io/ts-sdk 6.0.0 → 6.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PayoutManager-BHeiLQ1j.js → PayoutManager-3-MzBVLj.js} +2 -2
- package/dist/{PayoutManager-BHeiLQ1j.js.map → PayoutManager-3-MzBVLj.js.map} +1 -1
- package/dist/{PayoutManager-B5nR0x1t.cjs → PayoutManager-PQqeqX41.cjs} +2 -2
- package/dist/{PayoutManager-B5nR0x1t.cjs.map → PayoutManager-PQqeqX41.cjs.map} +1 -1
- package/dist/{PeginManager-6ghglb4r.cjs → PeginManager-D_ZUfbIy.cjs} +2 -2
- package/dist/{PeginManager-6ghglb4r.cjs.map → PeginManager-D_ZUfbIy.cjs.map} +1 -1
- package/dist/{PeginManager-CXNqbgA4.js → PeginManager-m3IlM4wS.js} +4 -4
- package/dist/{PeginManager-CXNqbgA4.js.map → PeginManager-m3IlM4wS.js.map} +1 -1
- package/dist/{buildAndBroadcastReclaim-CXOMHHgK.cjs → buildAndBroadcastReclaim-CMjlyooo.cjs} +2 -2
- package/dist/{buildAndBroadcastReclaim-CXOMHHgK.cjs.map → buildAndBroadcastReclaim-CMjlyooo.cjs.map} +1 -1
- package/dist/{buildAndBroadcastReclaim-Bs_zdDGN.js → buildAndBroadcastReclaim-D8l-QJWo.js} +4 -4
- package/dist/{buildAndBroadcastReclaim-Bs_zdDGN.js.map → buildAndBroadcastReclaim-D8l-QJWo.js.map} +1 -1
- package/dist/{challengeAssert-CuX_8Twt.cjs → challengeAssert-DlzX_kjF.cjs} +2 -2
- package/dist/{challengeAssert-CuX_8Twt.cjs.map → challengeAssert-DlzX_kjF.cjs.map} +1 -1
- package/dist/{challengeAssert-D_lRvsO0.js → challengeAssert-hpOHGPXX.js} +2 -2
- package/dist/{challengeAssert-D_lRvsO0.js.map → challengeAssert-hpOHGPXX.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +307 -305
- package/dist/index.js.map +1 -1
- package/dist/peginState-B4t_PDgj.cjs.map +1 -1
- package/dist/peginState-CXdbSit3.js.map +1 -1
- package/dist/signer-set-reader-CNEfzwuA.cjs +2 -0
- package/dist/signer-set-reader-CNEfzwuA.cjs.map +1 -0
- package/dist/{signer-set-reader-DiwLeqik.js → signer-set-reader-Csz8RXQi.js} +6 -5
- package/dist/signer-set-reader-Csz8RXQi.js.map +1 -0
- package/dist/tbv/core/clients/eth/__tests__/contract-address-resolver.test.d.ts +2 -0
- package/dist/tbv/core/clients/eth/__tests__/contract-address-resolver.test.d.ts.map +1 -0
- package/dist/tbv/core/clients/eth/contract-address-resolver.d.ts +3 -1
- package/dist/tbv/core/clients/eth/contract-address-resolver.d.ts.map +1 -1
- package/dist/tbv/core/clients/eth/index.cjs +1 -1
- package/dist/tbv/core/clients/eth/index.js +1 -1
- package/dist/tbv/core/clients/index.cjs +1 -1
- package/dist/tbv/core/clients/index.js +1 -1
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.js +305 -303
- package/dist/tbv/core/index.js.map +1 -1
- package/dist/tbv/core/managers/index.cjs +1 -1
- package/dist/tbv/core/managers/index.js +2 -2
- package/dist/tbv/core/primitives/index.cjs +1 -1
- package/dist/tbv/core/primitives/index.d.ts +5 -0
- package/dist/tbv/core/primitives/index.d.ts.map +1 -1
- package/dist/tbv/core/primitives/index.js +31 -29
- package/dist/tbv/core/primitives/index.js.map +1 -1
- package/dist/tbv/core/primitives/psbt/__tests__/signetPeginHashlockSpend.fixture.d.ts +19 -0
- package/dist/tbv/core/primitives/psbt/__tests__/signetPeginHashlockSpend.fixture.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/__tests__/verifyPeginHashlockSpend.test.d.ts +9 -0
- package/dist/tbv/core/primitives/psbt/__tests__/verifyPeginHashlockSpend.test.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/verifyPeginHashlockSpend.d.ts +73 -0
- package/dist/tbv/core/primitives/psbt/verifyPeginHashlockSpend.d.ts.map +1 -0
- package/dist/tbv/core/services/deposit/peginState.d.ts +16 -5
- package/dist/tbv/core/services/deposit/peginState.d.ts.map +1 -1
- package/dist/tbv/core/services/index.cjs +1 -1
- package/dist/tbv/core/services/index.js +2 -2
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +305 -303
- package/dist/tbv/index.js.map +1 -1
- package/dist/{toRefundInputs-Cl4KgzIc.js → toRefundInputs-D5tx3eeA.js} +4 -4
- package/dist/{toRefundInputs-Cl4KgzIc.js.map → toRefundInputs-D5tx3eeA.js.map} +1 -1
- package/dist/{toRefundInputs-DyIgmGJq.cjs → toRefundInputs-Df6eRITl.cjs} +2 -2
- package/dist/{toRefundInputs-DyIgmGJq.cjs.map → toRefundInputs-Df6eRITl.cjs.map} +1 -1
- package/dist/{verifyKeyPathSchnorrSignature-BVrAmVL3.cjs → verifyKeyPathSchnorrSignature-B7Za6aa1.cjs} +2 -2
- package/dist/{verifyKeyPathSchnorrSignature-BVrAmVL3.cjs.map → verifyKeyPathSchnorrSignature-B7Za6aa1.cjs.map} +1 -1
- package/dist/{verifyKeyPathSchnorrSignature-CIE3jlVt.js → verifyKeyPathSchnorrSignature-dw7xhm5Y.js} +2 -2
- package/dist/{verifyKeyPathSchnorrSignature-CIE3jlVt.js.map → verifyKeyPathSchnorrSignature-dw7xhm5Y.js.map} +1 -1
- package/dist/verifyPeginHashlockSpend-CdTFR2K6.js +167 -0
- package/dist/verifyPeginHashlockSpend-CdTFR2K6.js.map +1 -0
- package/dist/verifyPeginHashlockSpend-CisfqMuT.cjs +2 -0
- package/dist/verifyPeginHashlockSpend-CisfqMuT.cjs.map +1 -0
- package/dist/{verifyScriptPathSchnorrSignature-DLNGgm4j.js → verifyScriptPathSchnorrSignature-BVGPEZXW.js} +9 -8
- package/dist/{verifyScriptPathSchnorrSignature-DLNGgm4j.js.map → verifyScriptPathSchnorrSignature-BVGPEZXW.js.map} +1 -1
- package/dist/{verifyScriptPathSchnorrSignature-BHskbJJx.cjs → verifyScriptPathSchnorrSignature-p3sVoWQi.cjs} +2 -2
- package/dist/{verifyScriptPathSchnorrSignature-BHskbJJx.cjs.map → verifyScriptPathSchnorrSignature-p3sVoWQi.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/signer-set-reader-CJfV-GDz.cjs +0 -2
- package/dist/signer-set-reader-CJfV-GDz.cjs.map +0 -1
- package/dist/signer-set-reader-DiwLeqik.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var Te=Object.defineProperty;var Ee=(o,e,t)=>e in o?Te(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var w=(o,e,t)=>Ee(o,typeof e!="symbol"?e+"":e,t);const P=require("./sha2-Ce6KewYx.cjs"),O=require("bitcoinjs-lib"),I=require("buffer"),ee=require("viem"),te=require("./pegin-registration-client-DOb-Iznp.cjs"),le=require("./tbv/core/clients/mempool/index.cjs"),Y=require("./tbv/core/wasm/index.cjs"),C=require("./verifyScriptPathSchnorrSignature-BHskbJJx.cjs"),$=require("./verifyKeyPathSchnorrSignature-BVrAmVL3.cjs"),h=require("./bitcoin-D-O2GjbC.cjs"),Se=require("./signing-DvISftFk.cjs"),L=require("./validation-C6XTfZak.cjs"),ue=require("./deriveVaultRoot-C3uqnJto.cjs"),E=require("./PayoutManager-B5nR0x1t.cjs"),_e=require("./registration-records-CKc0OVuK.cjs"),oe=require("./psbtInputFields-BrV_ZfL_.cjs"),ne=require("./fundPeginTransaction-54-Rwb2k.cjs"),U=require("./constants-BCg6O0PX.cjs"),Be=require("./btcTxHash-CGb5BqFL.cjs"),Ae=require("./parseFundingOutpoints-C_-PT9BT.cjs"),Ce=require("@bitcoin-js/tiny-secp256k1-asmjs"),V=require("./bip322Verify-DLxJR9CQ.cjs");function he(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const pe=he(O),Ie=he(Ce),M=BigInt(2**32-1),se=BigInt(32);function He(o,e=!1){return e?{h:Number(o&M),l:Number(o>>se&M)}:{h:Number(o>>se&M)|0,l:Number(o&M)|0}}function $e(o,e=!1){const t=o.length;let n=new Uint32Array(t),r=new Uint32Array(t);for(let s=0;s<t;s++){const{h:i,l:a}=He(o[s],e);[n[s],r[s]]=[i,a]}return[n,r]}const Oe=(o,e,t)=>o<<t|e>>>32-t,Re=(o,e,t)=>e<<t|o>>>32-t,Fe=(o,e,t)=>e<<t-32|o>>>64-t,We=(o,e,t)=>o<<t-32|e>>>64-t,Ve=64;function de(o){const e=o.prepeginTxid.toLowerCase();if(!/^[0-9a-f]+$/.test(e)||e.length!==Ve)throw new Error(`buildDepositTerms: prepeginTxid must be 64 hex chars, got "${o.prepeginTxid}"`);if(o.peginAmounts.length===0)throw new Error("buildDepositTerms: at least one pegin amount is required");if(o.timelockPegin<=0||o.timelockAssert<=0||o.timelockRefund<=0)throw new Error("buildDepositTerms: timelocks must be positive");if(!Number.isInteger(o.maxAcceptableCommissionBps)||o.maxAcceptableCommissionBps<0||o.maxAcceptableCommissionBps>=U.MAX_VP_COMMISSION_BPS_EXCLUSIVE)throw new Error(`buildDepositTerms: maxAcceptableCommissionBps must be an integer in [0, ${U.MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${o.maxAcceptableCommissionBps}`);const t=BigInt(U.BPS_DENOMINATOR),n=o.peginAmounts.map((r,s)=>({htlcVout:s,vaultProviderBtcPubkey:o.vaultProviderBtcPubkey,peginAmount:r,commissionFee:r*BigInt(o.maxAcceptableCommissionBps)/t,depositorClaimValue:o.depositorClaimValue,peginMaxFee:o.peginMaxFee}));return{vaultCoreVersion:o.vaultCoreVersion,protocolFeeRate:o.protocolFeeRate,timelockPegin:o.timelockPegin,timelockAssert:o.timelockAssert,timelockRefund:o.timelockRefund,prepeginTxid:e,prepeginMaxFee:o.prepeginMaxFee,vaultKeeperBtcPubkeys:[...o.vaultKeeperBtcPubkeys],universalChallengerBtcPubkeys:[...o.universalChallengerBtcPubkeys],vaults:n}}const Me=/^0x[0-9a-f]+$/i,De=/^[0-9a-f]+$/i,Ke=/^[A-Za-z0-9+/]+={0,2}$/;function A(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty public key");return h.processPublicKeyToXOnly(o).toLowerCase()}function Ne(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty BIP-322 signature");if(o.startsWith("0x")||o.startsWith("0X")){if(!Me.test(o)||o.length<4||o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return o.toLowerCase()}if(De.test(o)){if(o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return`0x${o.toLowerCase()}`}if(!Ke.test(o)||o.length%4!==0)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");const e=I.Buffer.from(o,"base64");if(e.length===0||e.toString("base64")!==o)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");return`0x${e.toString("hex")}`}async function ge(o){const{wallet:e,depositTerms:t,fundedPrePeginTxHex:n,depositorBtcPubkey:r}=o,s=typeof e.approveDepositTerms=="function"?e.approveDepositTerms:void 0;if(!s&&!t)return;const i=n.startsWith("0x")?n.slice(2):n,l=O.Transaction.fromHex(i).getId();if(t&&t.prepeginTxid.replace(/^0x/,"").toLowerCase()!==l)throw new Error(`Deposit terms do not match the transaction being broadcast: terms are for prepeginTxid ${t.prepeginTxid}, but this transaction is ${l}.`);if(!s)return;if(!t)throw new Error("This wallet requires approved deposit terms before signing the Pre-PegIn transaction, but none were provided. Pass PreparePeginResult.depositTerms (fresh flows) or a resume rebuild.");if(typeof e.deriveContextHash!="function")throw new Error("A deposit-approval wallet must also implement deriveContextHash, but this one does not.");if(typeof e.holdsApprovedDepositTerms=="function"){let m=!1;try{m=await e.holdsApprovedDepositTerms(t)}catch{}if(m)return}typeof e.validateDepositTerms=="function"&&await e.validateDepositTerms(t);const p=Ae.parseFundingOutpointsFromTx(n);(await ue.deriveVaultRoot({deriveContextHash:e.deriveContextHash.bind(e)},{depositorBtcPubkey:h.hexToUint8Array(A(r)),fundingOutpoints:p})).fill(0),await s.call(e,t)}const Le=BigInt(0),H=BigInt(1),Ue=BigInt(2),Xe=BigInt(7),qe=BigInt(256),ze=BigInt(113),fe=[],me=[],Pe=[];for(let o=0,e=H,t=1,n=0;o<24;o++){[t,n]=[n,(2*t+3*n)%5],fe.push(2*(5*n+t)),me.push((o+1)*(o+2)/2%64);let r=Le;for(let s=0;s<7;s++)e=(e<<H^(e>>Xe)*ze)%qe,e&Ue&&(r^=H<<(H<<BigInt(s))-H);Pe.push(r)}const be=$e(Pe,!0),Ge=be[0],je=be[1],ie=(o,e,t)=>t>32?Fe(o,e,t):Oe(o,e,t),re=(o,e,t)=>t>32?We(o,e,t):Re(o,e,t);function Ye(o,e=24){const t=new Uint32Array(10);for(let n=24-e;n<24;n++){for(let i=0;i<10;i++)t[i]=o[i]^o[i+10]^o[i+20]^o[i+30]^o[i+40];for(let i=0;i<10;i+=2){const a=(i+8)%10,l=(i+2)%10,p=t[l],d=t[l+1],m=ie(p,d,1)^t[a],k=re(p,d,1)^t[a+1];for(let y=0;y<50;y+=10)o[i+y]^=m,o[i+y+1]^=k}let r=o[2],s=o[3];for(let i=0;i<24;i++){const a=me[i],l=ie(r,s,a),p=re(r,s,a),d=fe[i];r=o[d],s=o[d+1],o[d]=l,o[d+1]=p}for(let i=0;i<50;i+=10){for(let a=0;a<10;a++)t[a]=o[i+a];for(let a=0;a<10;a++)o[i+a]^=~t[(a+2)%10]&t[(a+4)%10]}o[0]^=Ge[n],o[1]^=je[n]}P.clean(t)}class Z{constructor(e,t,n,r=!1,s=24){w(this,"state");w(this,"pos",0);w(this,"posOut",0);w(this,"finished",!1);w(this,"state32");w(this,"destroyed",!1);w(this,"blockLen");w(this,"suffix");w(this,"outputLen");w(this,"enableXOF",!1);w(this,"rounds");if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.rounds=s,P.anumber(n,"outputLen"),!(0<e&&e<200))throw new Error("only keccak-f1600 function is supported");this.state=new Uint8Array(200),this.state32=P.u32(this.state)}clone(){return this._cloneInto()}keccak(){P.swap32IfBE(this.state32),Ye(this.state32,this.rounds),P.swap32IfBE(this.state32),this.posOut=0,this.pos=0}update(e){P.aexists(this),P.abytes(e);const{blockLen:t,state:n}=this,r=e.length;for(let s=0;s<r;){const i=Math.min(t-this.pos,r-s);for(let a=0;a<i;a++)n[this.pos++]^=e[s++];this.pos===t&&this.keccak()}return this}finish(){if(this.finished)return;this.finished=!0;const{state:e,suffix:t,pos:n,blockLen:r}=this;e[n]^=t,(t&128)!==0&&n===r-1&&this.keccak(),e[r-1]^=128,this.keccak()}writeInto(e){P.aexists(this,!1),P.abytes(e),this.finish();const t=this.state,{blockLen:n}=this;for(let r=0,s=e.length;r<s;){this.posOut>=n&&this.keccak();const i=Math.min(n-this.posOut,s-r);e.set(t.subarray(this.posOut,this.posOut+i),r),this.posOut+=i,r+=i}return e}xofInto(e){if(!this.enableXOF)throw new Error("XOF is not possible for this instance");return this.writeInto(e)}xof(e){return P.anumber(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(P.aoutput(e,this),this.finished)throw new Error("digest() was already called");return this.writeInto(e),this.destroy(),e}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,P.clean(this.state)}_cloneInto(e){const{blockLen:t,suffix:n,outputLen:r,rounds:s,enableXOF:i}=this;return e||(e=new Z(t,n,r,i,s)),e.state32.set(this.state32),e.pos=this.pos,e.posOut=this.posOut,e.finished=this.finished,e.rounds=s,e.suffix=n,e.outputLen=r,e.enableXOF=i,e.destroyed=this.destroyed,e}}const Qe=(o,e,t,n={})=>P.createHasher(()=>new Z(e,o,t),n),Ze=Qe(1,136,32),ae=64,x=20,Q=4,we=2,Je=0,et=1,D=[64,64],tt=o=>Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("");function J(o){return _e.ripemd160(P.sha256(o))}function ye(o){return(1<<o)-1}function ot(o){let e=1;for(;e*e<o+1;)e++;return Math.max(e,2)}function nt(o){const e=Q,t=o*ye(e);return{d:e,n:o,checksum_radix:ot(t)}}function X(o,e){const t=[];let n=e;for(;n>0;)t.push(n&255),n>>>=8;const r=new Uint8Array(o.length+t.length);r.set(o);for(let s=0;s<t.length;s++)r[o.length+s]=t[s];return J(r)}function q(o,e){let t=o;for(let n=0;n<e;n++)t=J(t);return t}function st(o,e){const t=ye(e.d),n=e.checksum_radix-1,r=Math.floor(e.n*t/e.checksum_radix),s=[];for(let d=0;d<e.n;d++){const m=X(o,d+we),k=q(m,t);s.push(Array.from(k))}const i=X(o,Je),a=q(i,n),l=X(o,et),p=q(l,r);return{config:e,message_terminals:s,checksum_major_terminal:Array.from(p),checksum_minor_terminal:Array.from(a)}}async function xe(o){try{if(o.length!==ae)throw new Error(`WOTS seed must be exactly ${ae} bytes, got ${o.length}`);const e=[];for(let t=0;t<D.length;t++){const n=D[t],r=nt(n),s=new Uint8Array(o.length+1);s.set(o),s[o.length]=t;const i=J(s);try{const a=st(i,r);if(a.config.d!==Q)throw new Error(`Block ${t}: expected d=${Q}, got d=${a.config.d}`);if(a.config.n!==n)throw new Error(`Block ${t}: expected n=${n}, got n=${a.config.n}`);if(a.message_terminals.length!==n)throw new Error(`Block ${t}: expected ${n} message terminals, got ${a.message_terminals.length}`);for(let l=0;l<a.message_terminals.length;l++)if(a.message_terminals[l].length!==x)throw new Error(`Block ${t} terminal ${l}: expected ${x} bytes, got ${a.message_terminals[l].length}`);if(a.checksum_minor_terminal.length!==x)throw new Error(`Block ${t} checksum_minor: expected ${x} bytes`);if(a.checksum_major_terminal.length!==x)throw new Error(`Block ${t} checksum_major: expected ${x} bytes`);e.push(a)}finally{s.fill(0),i.fill(0)}}if(e.length!==D.length)throw new Error(`Expected ${D.length} blocks, got ${e.length}`);return e}finally{o.fill(0)}}function z(o,e,t){if(o.length!==x)throw new Error(`Block ${e} ${t}: expected ${x} bytes, got ${o.length}`);for(let n=0;n<o.length;n++){const r=o[n];if(!Number.isInteger(r)||r<0||r>255)throw new Error(`Block ${e} ${t}[${n}]: invalid byte value ${r}`)}}function ke(o){if(o.length===0)throw new Error("Public keys array must not be empty");for(let s=0;s<o.length;s++){const i=o[s];z(i.checksum_minor_terminal,s,"checksum_minor_terminal"),z(i.checksum_major_terminal,s,"checksum_major_terminal");for(let a=0;a<i.message_terminals.length;a++)z(i.message_terminals[a],s,`message_terminal[${a}]`)}let e=0;for(const s of o)e+=we+s.message_terminals.length;const t=new Uint8Array(e*x);let n=0;for(const s of o){t.set(s.checksum_minor_terminal,n),n+=x,t.set(s.checksum_major_terminal,n),n+=x;for(const i of s.message_terminals)t.set(i,n),n+=x}const r=Ze(t);return`0x${tt(r)}`}async function ve(o,e){const t=[],n=[],r=[],s=[];try{for(let i=0;i<e;i++){const a=await Y.expandWotsSeed(o,i);try{const p=await xe(a);t.push(p),n.push(ke(p))}finally{a.fill(0)}const l=await Y.expandHashlockSecret(o,i);try{const p=h.uint8ArrayToHex(l);r.push(p),s.push(E.computeHashlock(h.ensureHexPrefix(p)).slice(2))}finally{l.fill(0)}}}finally{o.fill(0)}return{perVaultWotsKeys:t,wotsPkHashes:n,htlcSecretHexes:r,hashlocks:s}}const it=1,rt=2,at=33,ct=2,lt=3,ut=1,K=64,ht=0,G=1,ce=/^[0-9a-f]{64}$/i,pt=/^(?:[0-9a-f]{2})+$/;function dt(o){const e=o.slice(2);if(!pt.test(e))throw new Error("proof of possession witness is not even-length lowercase hex");return $.decodeWitnessStack(Uint8Array.from(I.Buffer.from(e,"hex")),"proof of possession witness")}function gt(o,e,t){var r;const n=dt(t);if(n.length===it){const[s]=n;let i,a;if(s.length===K)i=s,a=ht;else if(s.length===K+1&&s[K]===G)i=s.subarray(0,K),a=G;else throw new Error("proof of possession witness item must be a 64-byte Schnorr signature (or 65 bytes ending in 0x01)");if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const l=Uint8Array.from(I.Buffer.from(e,"hex"));if(!V.verifyBip322Simple(o,l,i,a))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2tr-verified"}}if(n.length===rt){if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const[s,i]=n;if(i.length!==at||i[0]!==ct&&i[0]!==lt)throw new Error(`proof of possession P2WPKH witness item 1 is not a compressed public key (${i.length} bytes, prefix 0x${((r=i[0])==null?void 0:r.toString(16))??"none"})`);if(!Ie.isPointCompressed(i))throw new Error("proof of possession P2WPKH witness pubkey is not a valid secp256k1 point");const a=I.Buffer.from(i.subarray(ut)).toString("hex");if(a!==e.toLowerCase())throw new Error(`proof of possession witness pubkey does not match the depositor key: witness carries ${a}, expected ${e}`);if(s.length<V.P2WPKH_ENCODED_SIG_MIN||s.length>V.P2WPKH_ENCODED_SIG_MAX)throw new Error(`proof of possession signature is ${s.length} bytes; vault ingestion accepts only 71/72-byte DER signatures with a sighash byte — try a different account or a Taproot address`);if(s[s.length-1]!==G)throw new Error(`proof of possession P2WPKH signature must end in a SIGHASH_ALL (0x01) byte, got 0x${s[s.length-1].toString(16)}`);if(!V.verifyBip322P2wpkhSimple(o,i,s))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2wpkh-verified"}}throw new Error(`proof of possession witness has ${n.length} items; expected 1 (P2TR) or 2 (P2WPKH)`)}const j="00".repeat(32),ft="00".repeat(32);function mt(o,e){const t={bitcoin:"bc",testnet:"tb",signet:"tb",regtest:"bcrt"};try{const n=pe.address.fromBech32(o);return n.prefix===t[e]&&n.version===0&&n.data.length===20}catch{return!1}}function Pt(o,e,t,n){const r=t==null?void 0:t[`${o}:${e}`];return r?Promise.resolve({txid:o,vout:e,value:r.value,scriptPubKey:r.scriptPubKey}):le.getUtxoInfo(o,e,n)}class bt{constructor(e){w(this,"config");this.config=e}async preparePegin(e){if(e.amounts.length===0)throw new Error("amounts must contain at least one entry");const t=await this.config.btcWallet.getPublicKeyHex(),n=A(t);if(E.supportsDepositApproval(this.config.btcWallet)){const c=(await E.requireChangeAddress(this.config.btcWallet)).trim();if(e.changeAddress.trim()!==c)throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not the approval wallet's change address ("${c}"). Refusing to build a tx the signing device would reject.`)}else if(!h.isAddressFromPublicKey(e.changeAddress,t,this.config.btcNetwork))throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not derived from the connected wallet's public key. Refusing to build a tx that would send change to an address the signing key doesn't control.`);const r=await this.prepareSizing(n,e);if(E.supportsDepositApproval(this.config.btcWallet)){const{validateDepositTerms:c}=this.config.btcWallet;typeof c=="function"&&await c.call(this.config.btcWallet,this.buildPeginDepositTerms({params:e,prepeginTxid:ft,prepeginMaxFee:r.fee,depositorClaimValue:r.depositorClaimValue,peginMaxFee:r.minPeginFee}))}const s=r.selectedUTXOs.map(c=>({txid:h.hexToUint8Array(c.txid),vout:c.vout})),i=await ue.deriveVaultRoot(this.config.btcWallet,{depositorBtcPubkey:h.hexToUint8Array(n),fundingOutpoints:s});try{if(A(await this.config.btcWallet.getPublicKeyHex())!==n)throw new Error("BTC wallet account changed during vault secret derivation. The wallet no longer reports the account this deposit started with, so the derived secrets cannot be used. Restart the deposit with the original account.")}catch(c){throw i.fill(0),c}let a,l;try{const c=await Y.expandAuthAnchor(i);try{a=h.uint8ArrayToHex(c),l=h.uint8ArrayToHex(P.sha256(c))}finally{c.fill(0)}}catch(c){throw i.fill(0),c}const p=await ve(i,e.amounts.length),{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,hashlocks:y}=p,f=await this.preparePeginCommit({depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:y,authAnchorHash:l,sizing:r,params:e});for(let c=0;c<f.perVault.length;c++)if(f.perVault[c].htlcVout!==c)throw new Error(`Internal invariant violation: htlcVout/index mismatch at vault ${c} (expected ${c}, got ${f.perVault[c].htlcVout})`);E.assertAuthAnchorOpReturn(f.fundedPrePeginTxHex,e.amounts.length,l);const{depositTerms:S,...v}=f;return{transaction:{...v,selectedUTXOs:r.selectedUTXOs,fee:r.fee,changeAmount:r.changeAmount},depositorBtcPubkey:n,derivedSecrets:{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,authAnchorHex:a},depositTerms:S}}async prepareSizing(e,t){const n=t.amounts.map(()=>j),r=t.vaultKeeperBtcPubkeys.length,s=await C.buildPrePeginPsbt({vaultCoreVersion:t.vaultCoreVersion,depositorPubkey:e,vaultProviderPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),hashlocks:n,timelockRefund:t.timelockRefund,pegInAmounts:t.amounts,feeRate:t.protocolFeeRate,minPeginFeeRate:t.minPeginFeeRate,numLocalChallengers:r,councilQuorum:t.councilQuorum,councilSize:t.councilSize,network:this.config.btcNetwork,authAnchorHash:j}),i=oe.selectUtxosForPegin([...t.availableUTXOs],s.totalOutputValue,t.mempoolFeeRate,ne.peginOutputCount(s.htlcValues.length,!0));return{selectedUTXOs:i.selectedUTXOs,fee:i.fee,changeAmount:i.changeAmount,depositorClaimValue:s.depositorClaimValue,minPeginFee:s.minPeginFee}}buildPeginDepositTerms(e){const{params:t}=e;return de({vaultCoreVersion:t.vaultCoreVersion,protocolFeeRate:t.protocolFeeRate,timelockPegin:t.timelockPegin,timelockAssert:t.timelockAssert,timelockRefund:t.timelockRefund,prepeginTxid:e.prepeginTxid,prepeginMaxFee:e.prepeginMaxFee,vaultProviderBtcPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperBtcPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerBtcPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),maxAcceptableCommissionBps:te.capMaxAcceptableCommissionBps(t.commissionBps),peginAmounts:t.amounts,depositorClaimValue:e.depositorClaimValue,peginMaxFee:e.peginMaxFee})}async preparePeginCommit(e){const{depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:r,authAnchorHash:s,sizing:i,params:a}=e,l=j.toLowerCase();for(let u=0;u<r.length;u++)if(r[u].toLowerCase()===l)throw new Error(`preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${u} — internal substitution bug`);if(s.toLowerCase()===l)throw new Error("preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug");const p=h.stripHexPrefix(a.vaultProviderBtcPubkey),d=a.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),m=a.universalChallengerBtcPubkeys.map(h.stripHexPrefix),k=d.length,y={vaultCoreVersion:a.vaultCoreVersion,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlocks:r,timelockRefund:a.timelockRefund,pegInAmounts:a.amounts,feeRate:a.protocolFeeRate,minPeginFeeRate:a.minPeginFeeRate,numLocalChallengers:k,councilQuorum:a.councilQuorum,councilSize:a.councilSize,network:this.config.btcNetwork,authAnchorHash:s},f=await C.buildPrePeginPsbt(y);if(f.depositorClaimValue!==i.depositorClaimValue||f.minPeginFee!==i.minPeginFee)throw new Error(`Pre-PegIn sizing/commit divergence: depositorClaimValue ${i.depositorClaimValue} -> ${f.depositorClaimValue}, minPeginFee ${i.minPeginFee} -> ${f.minPeginFee}. The provisional deposit terms validated before derivation would not match the terms sent for approval; refusing to continue.`);const S=h.getNetwork(this.config.btcNetwork),v=ne.fundPeginTransaction({unfundedTxHex:f.psbtHex,selectedUTXOs:i.selectedUTXOs,changeAddress:a.changeAddress,changeAmount:i.changeAmount,network:S}),c=i.selectedUTXOs.reduce((u,B)=>u+BigInt(B.value),0n)-f.totalOutputValue-i.changeAmount;if(c!==i.fee)throw new Error(`Pre-PegIn funded fee ${c} does not match the sizing-pass fee ${i.fee}; refusing to publish a deposit-terms fee bound the funded transaction does not pay.`);const R=h.stripHexPrefix(Be.calculateBtcTxHash(v)),F=[],g=[],b=[];for(let u=0;u<r.length;u++){const B=await C.buildPeginTxFromFundedPrePegin({prePeginParams:y,timelockPegin:a.timelockPegin,fundedPrePeginTxHex:v,htlcVout:u}),N=await $.buildPeginInputPsbt({vaultCoreVersion:a.vaultCoreVersion,peginTxHex:B.txHex,fundedPrePeginTxHex:v,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlock:r[u],timelockRefund:a.timelockRefund,network:this.config.btcNetwork});F.push(B),g.push(N.psbtHex),b.push(Se.createTaprootScriptPathSignOptions(t,1))}const T=this.buildPeginDepositTerms({params:a,prepeginTxid:R,prepeginMaxFee:i.fee,depositorClaimValue:f.depositorClaimValue,peginMaxFee:f.minPeginFee});E.supportsDepositApproval(this.config.btcWallet)&&await this.config.btcWallet.approveDepositTerms(T);const _=await E.signPsbtsWithFallback(this.config.btcWallet,g,b),W=[];for(let u=0;u<_.length;u++){C.assertPsbtUnsignedTxMatches({requestedPsbtHex:g[u],returnedPsbtHex:_[u]});const B=$.extractPeginInputSignature(_[u],n);C.assertScriptPathSchnorrSignature({requestedPsbtHex:g[u],signatureHex:B,signerXOnlyPubkeyHex:n,inputIndex:0});const N=$.finalizePeginInputPsbt(_[u]);W.push({htlcVout:u,htlcValue:f.htlcValues[u],peginTxHex:N,peginTxid:F[u].txid,peginInputSignature:B,vaultScriptPubKey:F[u].vaultScriptPubKey})}return{fundedPrePeginTxHex:v,prePeginTxid:R,perVault:W,depositTerms:T}}async signAndBroadcast(e){const{fundedPrePeginTxHex:t,depositorBtcPubkey:n}=e,r=t.startsWith("0x")?t.slice(2):t,s=O.Transaction.fromHex(r);if(s.ins.length===0)throw new Error("Transaction has no inputs");const i=new O.Psbt;i.setVersion(s.version),i.setLocktime(s.locktime);const a=I.Buffer.from(A(n),"hex"),l=this.config.mempoolApiUrl,p=s.ins.map(g=>{const b=I.Buffer.from(g.hash).reverse().toString("hex"),T=g.index;return Pt(b,T,e.localPrevouts,l).then(_=>({input:g,utxoData:_,txid:b,vout:T}))}),d=await Promise.all(p),m=d.reduce((g,b)=>g+BigInt(b.utxoData.value),0n),k=s.outs.reduce((g,b)=>g+BigInt(b.value),0n);if(m<k)throw new Error(`UTXO value mismatch: total input value (${m} sat) is less than total output value (${k} sat). This may indicate the mempool API returned manipulated UTXO data.`);const y=m-k;if(y>L.MAX_REASONABLE_FEE_SATS)throw new Error(`Implied transaction fee (${y} sat) exceeds maximum reasonable fee (${L.MAX_REASONABLE_FEE_SATS} sat). This may indicate manipulated UTXO data.`);for(const{input:g,utxoData:b,txid:T,vout:_}of d){const W=oe.getPsbtInputFields({value:b.value,scriptPubKey:b.scriptPubKey},a);i.addInput({hash:g.hash,index:g.index,sequence:g.sequence,...W})}for(const g of s.outs)i.addOutput({script:g.script,value:g.value});await ge({wallet:this.config.btcWallet,depositTerms:e.depositTerms,fundedPrePeginTxHex:t,depositorBtcPubkey:n});const f=i.toHex(),S=await this.config.btcWallet.signPsbt(f);C.assertPsbtUnsignedTxMatches({requestedPsbtHex:f,returnedPsbtHex:S});const v=$.assertReturnedKeyPathSignatures({requestedPsbtHex:f,returnedPsbtHex:S});if(E.supportsDepositApproval(this.config.btcWallet)&&v!==i.data.inputs.length)throw new Error(`Key-path verification covered ${v} of ${i.data.inputs.length} Pre-PegIn inputs; an approval wallet signs every input key-path, so the unverified ones must not be broadcast.`);const c=O.Psbt.fromHex(S);try{c.finalizeAllInputs()}catch(g){if(!c.data.inputs.every(T=>T.finalScriptWitness||T.finalScriptSig))throw new Error(`PSBT finalization failed and wallet did not auto-finalize: ${g}`)}const R=c.extractTransaction().toHex();return await le.pushTx(R,l)}async registerPeginOnChain(e){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.depositorPayoutBtcAddress??await this.config.btcWallet.getAddress(),s=this.resolvePayoutScriptPubKey(n,r);return this.createRegistrationClient().registerPeginOnChain({unsignedPrePeginTx:e.unsignedPrePeginTx,depositorSignedPeginTx:e.depositorSignedPeginTx,vaultProvider:e.vaultProvider,hashlock:e.hashlock,htlcVout:e.htlcVout,depositorPayoutScriptPubKey:s,depositorBtcPubkeyRaw:n,depositorWotsPkHash:e.depositorWotsPkHash,popSignature:e.popSignature,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint})}async registerPeginBatchOnChain(e){if(e.requests.length===0)throw new Error("Batch pegin requires at least one request");if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.requests.map(s=>this.resolvePayoutScriptPubKey(n,s.depositorPayoutBtcAddress));return this.createRegistrationClient().registerPeginBatchOnChain({vaultProvider:e.vaultProvider,unsignedPrePeginTx:e.unsignedPrePeginTx,popSignature:e.popSignature,depositorBtcPubkeyRaw:n,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint,requests:e.requests.map((s,i)=>({depositorSignedPeginTx:s.depositorSignedPeginTx,hashlock:s.hashlock,htlcVout:s.htlcVout,depositorPayoutScriptPubKey:r[i],depositorWotsPkHash:s.depositorWotsPkHash}))})}createRegistrationClient(){return new te.ViemPeginRegistrationClient({ethWallet:this.config.ethWallet,ethChain:this.config.ethChain,publicClient:this.config.publicClient,btcVaultRegistry:this.config.vaultContracts.btcVaultRegistry,requireQuotedCommissionBps:E.supportsDepositApproval(this.config.btcWallet)})}resolvePayoutScriptPubKey(e,t){if(!h.isAddressFromPublicKey(t,e,this.config.btcNetwork))throw h.stripHexPrefix(e).length===L.X_ONLY_PUBKEY_HEX_LEN&&mt(t,this.config.btcNetwork)?new Error(`BTC payout address "${t}" is a P2WPKH (Native SegWit) address, but the connected wallet only exposes an x-only public key. P2WPKH validation requires a compressed key with known y-parity. Use a P2TR (Taproot) payout address instead.`):new Error(`BTC payout address "${t}" is not derived from the connected wallet's public key. The payout sink must be controlled by the same key that signs the pegin; refusing to register a mismatched address.`);const n=h.getNetwork(this.config.btcNetwork);let r;try{r=pe.address.toOutputScript(t,n).toString("hex")}catch{throw new Error(`Invalid BTC payout address: "${t}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`)}return r}async signProofOfPossession(){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const e=this.config.ethWallet.account.address,t=A(await this.config.btcWallet.getPublicKeyHex()),n=this.config.vaultContracts.btcVaultRegistry,r=`${e.toLowerCase()}:${this.config.ethChain.id}:pegin:${n.toLowerCase()}`,s=await this.config.btcWallet.signMessage(r,"bip322-simple"),i=Ne(s);return gt(new TextEncoder().encode(r),t,i),{btcPopSignature:i,depositorEthAddress:e,depositorBtcPubkey:t}}async assertPopMatchesBtcWallet(e){const t=await this.config.btcWallet.getPublicKeyHex(),n=A(t),r=A(e.depositorBtcPubkey);if(n!==r)throw new Error(`Proof of possession was signed with BTC pubkey ${r} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`);return t}getNetwork(){return this.config.btcNetwork}getVaultContractAddress(){return this.config.vaultContracts.btcVaultRegistry}}exports.PeginManager=bt;exports.buildDepositTerms=de;exports.computeWotsBlockPublicKeysHash=ke;exports.deriveWotsBlocksFromSeed=xe;exports.ensurePrePeginTermsApproval=ge;exports.expandPerVaultSecrets=ve;
|
|
2
|
-
//# sourceMappingURL=PeginManager-
|
|
1
|
+
"use strict";var Te=Object.defineProperty;var Ee=(o,e,t)=>e in o?Te(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var w=(o,e,t)=>Ee(o,typeof e!="symbol"?e+"":e,t);const P=require("./sha2-Ce6KewYx.cjs"),O=require("bitcoinjs-lib"),I=require("buffer"),ee=require("viem"),te=require("./pegin-registration-client-DOb-Iznp.cjs"),le=require("./tbv/core/clients/mempool/index.cjs"),Y=require("./tbv/core/wasm/index.cjs"),C=require("./verifyScriptPathSchnorrSignature-p3sVoWQi.cjs"),$=require("./verifyKeyPathSchnorrSignature-B7Za6aa1.cjs"),h=require("./bitcoin-D-O2GjbC.cjs"),Se=require("./signing-DvISftFk.cjs"),L=require("./validation-C6XTfZak.cjs"),ue=require("./deriveVaultRoot-C3uqnJto.cjs"),E=require("./PayoutManager-PQqeqX41.cjs"),_e=require("./registration-records-CKc0OVuK.cjs"),oe=require("./psbtInputFields-BrV_ZfL_.cjs"),ne=require("./fundPeginTransaction-54-Rwb2k.cjs"),U=require("./constants-BCg6O0PX.cjs"),Be=require("./btcTxHash-CGb5BqFL.cjs"),Ae=require("./parseFundingOutpoints-C_-PT9BT.cjs"),Ce=require("@bitcoin-js/tiny-secp256k1-asmjs"),V=require("./bip322Verify-DLxJR9CQ.cjs");function he(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const pe=he(O),Ie=he(Ce),M=BigInt(2**32-1),se=BigInt(32);function He(o,e=!1){return e?{h:Number(o&M),l:Number(o>>se&M)}:{h:Number(o>>se&M)|0,l:Number(o&M)|0}}function $e(o,e=!1){const t=o.length;let n=new Uint32Array(t),r=new Uint32Array(t);for(let s=0;s<t;s++){const{h:i,l:a}=He(o[s],e);[n[s],r[s]]=[i,a]}return[n,r]}const Oe=(o,e,t)=>o<<t|e>>>32-t,Re=(o,e,t)=>e<<t|o>>>32-t,Fe=(o,e,t)=>e<<t-32|o>>>64-t,We=(o,e,t)=>o<<t-32|e>>>64-t,Ve=64;function de(o){const e=o.prepeginTxid.toLowerCase();if(!/^[0-9a-f]+$/.test(e)||e.length!==Ve)throw new Error(`buildDepositTerms: prepeginTxid must be 64 hex chars, got "${o.prepeginTxid}"`);if(o.peginAmounts.length===0)throw new Error("buildDepositTerms: at least one pegin amount is required");if(o.timelockPegin<=0||o.timelockAssert<=0||o.timelockRefund<=0)throw new Error("buildDepositTerms: timelocks must be positive");if(!Number.isInteger(o.maxAcceptableCommissionBps)||o.maxAcceptableCommissionBps<0||o.maxAcceptableCommissionBps>=U.MAX_VP_COMMISSION_BPS_EXCLUSIVE)throw new Error(`buildDepositTerms: maxAcceptableCommissionBps must be an integer in [0, ${U.MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${o.maxAcceptableCommissionBps}`);const t=BigInt(U.BPS_DENOMINATOR),n=o.peginAmounts.map((r,s)=>({htlcVout:s,vaultProviderBtcPubkey:o.vaultProviderBtcPubkey,peginAmount:r,commissionFee:r*BigInt(o.maxAcceptableCommissionBps)/t,depositorClaimValue:o.depositorClaimValue,peginMaxFee:o.peginMaxFee}));return{vaultCoreVersion:o.vaultCoreVersion,protocolFeeRate:o.protocolFeeRate,timelockPegin:o.timelockPegin,timelockAssert:o.timelockAssert,timelockRefund:o.timelockRefund,prepeginTxid:e,prepeginMaxFee:o.prepeginMaxFee,vaultKeeperBtcPubkeys:[...o.vaultKeeperBtcPubkeys],universalChallengerBtcPubkeys:[...o.universalChallengerBtcPubkeys],vaults:n}}const Me=/^0x[0-9a-f]+$/i,De=/^[0-9a-f]+$/i,Ke=/^[A-Za-z0-9+/]+={0,2}$/;function A(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty public key");return h.processPublicKeyToXOnly(o).toLowerCase()}function Ne(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty BIP-322 signature");if(o.startsWith("0x")||o.startsWith("0X")){if(!Me.test(o)||o.length<4||o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return o.toLowerCase()}if(De.test(o)){if(o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return`0x${o.toLowerCase()}`}if(!Ke.test(o)||o.length%4!==0)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");const e=I.Buffer.from(o,"base64");if(e.length===0||e.toString("base64")!==o)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");return`0x${e.toString("hex")}`}async function ge(o){const{wallet:e,depositTerms:t,fundedPrePeginTxHex:n,depositorBtcPubkey:r}=o,s=typeof e.approveDepositTerms=="function"?e.approveDepositTerms:void 0;if(!s&&!t)return;const i=n.startsWith("0x")?n.slice(2):n,l=O.Transaction.fromHex(i).getId();if(t&&t.prepeginTxid.replace(/^0x/,"").toLowerCase()!==l)throw new Error(`Deposit terms do not match the transaction being broadcast: terms are for prepeginTxid ${t.prepeginTxid}, but this transaction is ${l}.`);if(!s)return;if(!t)throw new Error("This wallet requires approved deposit terms before signing the Pre-PegIn transaction, but none were provided. Pass PreparePeginResult.depositTerms (fresh flows) or a resume rebuild.");if(typeof e.deriveContextHash!="function")throw new Error("A deposit-approval wallet must also implement deriveContextHash, but this one does not.");if(typeof e.holdsApprovedDepositTerms=="function"){let m=!1;try{m=await e.holdsApprovedDepositTerms(t)}catch{}if(m)return}typeof e.validateDepositTerms=="function"&&await e.validateDepositTerms(t);const p=Ae.parseFundingOutpointsFromTx(n);(await ue.deriveVaultRoot({deriveContextHash:e.deriveContextHash.bind(e)},{depositorBtcPubkey:h.hexToUint8Array(A(r)),fundingOutpoints:p})).fill(0),await s.call(e,t)}const Le=BigInt(0),H=BigInt(1),Ue=BigInt(2),Xe=BigInt(7),qe=BigInt(256),ze=BigInt(113),fe=[],me=[],Pe=[];for(let o=0,e=H,t=1,n=0;o<24;o++){[t,n]=[n,(2*t+3*n)%5],fe.push(2*(5*n+t)),me.push((o+1)*(o+2)/2%64);let r=Le;for(let s=0;s<7;s++)e=(e<<H^(e>>Xe)*ze)%qe,e&Ue&&(r^=H<<(H<<BigInt(s))-H);Pe.push(r)}const be=$e(Pe,!0),Ge=be[0],je=be[1],ie=(o,e,t)=>t>32?Fe(o,e,t):Oe(o,e,t),re=(o,e,t)=>t>32?We(o,e,t):Re(o,e,t);function Ye(o,e=24){const t=new Uint32Array(10);for(let n=24-e;n<24;n++){for(let i=0;i<10;i++)t[i]=o[i]^o[i+10]^o[i+20]^o[i+30]^o[i+40];for(let i=0;i<10;i+=2){const a=(i+8)%10,l=(i+2)%10,p=t[l],d=t[l+1],m=ie(p,d,1)^t[a],k=re(p,d,1)^t[a+1];for(let y=0;y<50;y+=10)o[i+y]^=m,o[i+y+1]^=k}let r=o[2],s=o[3];for(let i=0;i<24;i++){const a=me[i],l=ie(r,s,a),p=re(r,s,a),d=fe[i];r=o[d],s=o[d+1],o[d]=l,o[d+1]=p}for(let i=0;i<50;i+=10){for(let a=0;a<10;a++)t[a]=o[i+a];for(let a=0;a<10;a++)o[i+a]^=~t[(a+2)%10]&t[(a+4)%10]}o[0]^=Ge[n],o[1]^=je[n]}P.clean(t)}class Z{constructor(e,t,n,r=!1,s=24){w(this,"state");w(this,"pos",0);w(this,"posOut",0);w(this,"finished",!1);w(this,"state32");w(this,"destroyed",!1);w(this,"blockLen");w(this,"suffix");w(this,"outputLen");w(this,"enableXOF",!1);w(this,"rounds");if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.rounds=s,P.anumber(n,"outputLen"),!(0<e&&e<200))throw new Error("only keccak-f1600 function is supported");this.state=new Uint8Array(200),this.state32=P.u32(this.state)}clone(){return this._cloneInto()}keccak(){P.swap32IfBE(this.state32),Ye(this.state32,this.rounds),P.swap32IfBE(this.state32),this.posOut=0,this.pos=0}update(e){P.aexists(this),P.abytes(e);const{blockLen:t,state:n}=this,r=e.length;for(let s=0;s<r;){const i=Math.min(t-this.pos,r-s);for(let a=0;a<i;a++)n[this.pos++]^=e[s++];this.pos===t&&this.keccak()}return this}finish(){if(this.finished)return;this.finished=!0;const{state:e,suffix:t,pos:n,blockLen:r}=this;e[n]^=t,(t&128)!==0&&n===r-1&&this.keccak(),e[r-1]^=128,this.keccak()}writeInto(e){P.aexists(this,!1),P.abytes(e),this.finish();const t=this.state,{blockLen:n}=this;for(let r=0,s=e.length;r<s;){this.posOut>=n&&this.keccak();const i=Math.min(n-this.posOut,s-r);e.set(t.subarray(this.posOut,this.posOut+i),r),this.posOut+=i,r+=i}return e}xofInto(e){if(!this.enableXOF)throw new Error("XOF is not possible for this instance");return this.writeInto(e)}xof(e){return P.anumber(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(P.aoutput(e,this),this.finished)throw new Error("digest() was already called");return this.writeInto(e),this.destroy(),e}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,P.clean(this.state)}_cloneInto(e){const{blockLen:t,suffix:n,outputLen:r,rounds:s,enableXOF:i}=this;return e||(e=new Z(t,n,r,i,s)),e.state32.set(this.state32),e.pos=this.pos,e.posOut=this.posOut,e.finished=this.finished,e.rounds=s,e.suffix=n,e.outputLen=r,e.enableXOF=i,e.destroyed=this.destroyed,e}}const Qe=(o,e,t,n={})=>P.createHasher(()=>new Z(e,o,t),n),Ze=Qe(1,136,32),ae=64,x=20,Q=4,we=2,Je=0,et=1,D=[64,64],tt=o=>Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("");function J(o){return _e.ripemd160(P.sha256(o))}function ye(o){return(1<<o)-1}function ot(o){let e=1;for(;e*e<o+1;)e++;return Math.max(e,2)}function nt(o){const e=Q,t=o*ye(e);return{d:e,n:o,checksum_radix:ot(t)}}function X(o,e){const t=[];let n=e;for(;n>0;)t.push(n&255),n>>>=8;const r=new Uint8Array(o.length+t.length);r.set(o);for(let s=0;s<t.length;s++)r[o.length+s]=t[s];return J(r)}function q(o,e){let t=o;for(let n=0;n<e;n++)t=J(t);return t}function st(o,e){const t=ye(e.d),n=e.checksum_radix-1,r=Math.floor(e.n*t/e.checksum_radix),s=[];for(let d=0;d<e.n;d++){const m=X(o,d+we),k=q(m,t);s.push(Array.from(k))}const i=X(o,Je),a=q(i,n),l=X(o,et),p=q(l,r);return{config:e,message_terminals:s,checksum_major_terminal:Array.from(p),checksum_minor_terminal:Array.from(a)}}async function xe(o){try{if(o.length!==ae)throw new Error(`WOTS seed must be exactly ${ae} bytes, got ${o.length}`);const e=[];for(let t=0;t<D.length;t++){const n=D[t],r=nt(n),s=new Uint8Array(o.length+1);s.set(o),s[o.length]=t;const i=J(s);try{const a=st(i,r);if(a.config.d!==Q)throw new Error(`Block ${t}: expected d=${Q}, got d=${a.config.d}`);if(a.config.n!==n)throw new Error(`Block ${t}: expected n=${n}, got n=${a.config.n}`);if(a.message_terminals.length!==n)throw new Error(`Block ${t}: expected ${n} message terminals, got ${a.message_terminals.length}`);for(let l=0;l<a.message_terminals.length;l++)if(a.message_terminals[l].length!==x)throw new Error(`Block ${t} terminal ${l}: expected ${x} bytes, got ${a.message_terminals[l].length}`);if(a.checksum_minor_terminal.length!==x)throw new Error(`Block ${t} checksum_minor: expected ${x} bytes`);if(a.checksum_major_terminal.length!==x)throw new Error(`Block ${t} checksum_major: expected ${x} bytes`);e.push(a)}finally{s.fill(0),i.fill(0)}}if(e.length!==D.length)throw new Error(`Expected ${D.length} blocks, got ${e.length}`);return e}finally{o.fill(0)}}function z(o,e,t){if(o.length!==x)throw new Error(`Block ${e} ${t}: expected ${x} bytes, got ${o.length}`);for(let n=0;n<o.length;n++){const r=o[n];if(!Number.isInteger(r)||r<0||r>255)throw new Error(`Block ${e} ${t}[${n}]: invalid byte value ${r}`)}}function ke(o){if(o.length===0)throw new Error("Public keys array must not be empty");for(let s=0;s<o.length;s++){const i=o[s];z(i.checksum_minor_terminal,s,"checksum_minor_terminal"),z(i.checksum_major_terminal,s,"checksum_major_terminal");for(let a=0;a<i.message_terminals.length;a++)z(i.message_terminals[a],s,`message_terminal[${a}]`)}let e=0;for(const s of o)e+=we+s.message_terminals.length;const t=new Uint8Array(e*x);let n=0;for(const s of o){t.set(s.checksum_minor_terminal,n),n+=x,t.set(s.checksum_major_terminal,n),n+=x;for(const i of s.message_terminals)t.set(i,n),n+=x}const r=Ze(t);return`0x${tt(r)}`}async function ve(o,e){const t=[],n=[],r=[],s=[];try{for(let i=0;i<e;i++){const a=await Y.expandWotsSeed(o,i);try{const p=await xe(a);t.push(p),n.push(ke(p))}finally{a.fill(0)}const l=await Y.expandHashlockSecret(o,i);try{const p=h.uint8ArrayToHex(l);r.push(p),s.push(E.computeHashlock(h.ensureHexPrefix(p)).slice(2))}finally{l.fill(0)}}}finally{o.fill(0)}return{perVaultWotsKeys:t,wotsPkHashes:n,htlcSecretHexes:r,hashlocks:s}}const it=1,rt=2,at=33,ct=2,lt=3,ut=1,K=64,ht=0,G=1,ce=/^[0-9a-f]{64}$/i,pt=/^(?:[0-9a-f]{2})+$/;function dt(o){const e=o.slice(2);if(!pt.test(e))throw new Error("proof of possession witness is not even-length lowercase hex");return $.decodeWitnessStack(Uint8Array.from(I.Buffer.from(e,"hex")),"proof of possession witness")}function gt(o,e,t){var r;const n=dt(t);if(n.length===it){const[s]=n;let i,a;if(s.length===K)i=s,a=ht;else if(s.length===K+1&&s[K]===G)i=s.subarray(0,K),a=G;else throw new Error("proof of possession witness item must be a 64-byte Schnorr signature (or 65 bytes ending in 0x01)");if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const l=Uint8Array.from(I.Buffer.from(e,"hex"));if(!V.verifyBip322Simple(o,l,i,a))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2tr-verified"}}if(n.length===rt){if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const[s,i]=n;if(i.length!==at||i[0]!==ct&&i[0]!==lt)throw new Error(`proof of possession P2WPKH witness item 1 is not a compressed public key (${i.length} bytes, prefix 0x${((r=i[0])==null?void 0:r.toString(16))??"none"})`);if(!Ie.isPointCompressed(i))throw new Error("proof of possession P2WPKH witness pubkey is not a valid secp256k1 point");const a=I.Buffer.from(i.subarray(ut)).toString("hex");if(a!==e.toLowerCase())throw new Error(`proof of possession witness pubkey does not match the depositor key: witness carries ${a}, expected ${e}`);if(s.length<V.P2WPKH_ENCODED_SIG_MIN||s.length>V.P2WPKH_ENCODED_SIG_MAX)throw new Error(`proof of possession signature is ${s.length} bytes; vault ingestion accepts only 71/72-byte DER signatures with a sighash byte — try a different account or a Taproot address`);if(s[s.length-1]!==G)throw new Error(`proof of possession P2WPKH signature must end in a SIGHASH_ALL (0x01) byte, got 0x${s[s.length-1].toString(16)}`);if(!V.verifyBip322P2wpkhSimple(o,i,s))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2wpkh-verified"}}throw new Error(`proof of possession witness has ${n.length} items; expected 1 (P2TR) or 2 (P2WPKH)`)}const j="00".repeat(32),ft="00".repeat(32);function mt(o,e){const t={bitcoin:"bc",testnet:"tb",signet:"tb",regtest:"bcrt"};try{const n=pe.address.fromBech32(o);return n.prefix===t[e]&&n.version===0&&n.data.length===20}catch{return!1}}function Pt(o,e,t,n){const r=t==null?void 0:t[`${o}:${e}`];return r?Promise.resolve({txid:o,vout:e,value:r.value,scriptPubKey:r.scriptPubKey}):le.getUtxoInfo(o,e,n)}class bt{constructor(e){w(this,"config");this.config=e}async preparePegin(e){if(e.amounts.length===0)throw new Error("amounts must contain at least one entry");const t=await this.config.btcWallet.getPublicKeyHex(),n=A(t);if(E.supportsDepositApproval(this.config.btcWallet)){const c=(await E.requireChangeAddress(this.config.btcWallet)).trim();if(e.changeAddress.trim()!==c)throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not the approval wallet's change address ("${c}"). Refusing to build a tx the signing device would reject.`)}else if(!h.isAddressFromPublicKey(e.changeAddress,t,this.config.btcNetwork))throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not derived from the connected wallet's public key. Refusing to build a tx that would send change to an address the signing key doesn't control.`);const r=await this.prepareSizing(n,e);if(E.supportsDepositApproval(this.config.btcWallet)){const{validateDepositTerms:c}=this.config.btcWallet;typeof c=="function"&&await c.call(this.config.btcWallet,this.buildPeginDepositTerms({params:e,prepeginTxid:ft,prepeginMaxFee:r.fee,depositorClaimValue:r.depositorClaimValue,peginMaxFee:r.minPeginFee}))}const s=r.selectedUTXOs.map(c=>({txid:h.hexToUint8Array(c.txid),vout:c.vout})),i=await ue.deriveVaultRoot(this.config.btcWallet,{depositorBtcPubkey:h.hexToUint8Array(n),fundingOutpoints:s});try{if(A(await this.config.btcWallet.getPublicKeyHex())!==n)throw new Error("BTC wallet account changed during vault secret derivation. The wallet no longer reports the account this deposit started with, so the derived secrets cannot be used. Restart the deposit with the original account.")}catch(c){throw i.fill(0),c}let a,l;try{const c=await Y.expandAuthAnchor(i);try{a=h.uint8ArrayToHex(c),l=h.uint8ArrayToHex(P.sha256(c))}finally{c.fill(0)}}catch(c){throw i.fill(0),c}const p=await ve(i,e.amounts.length),{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,hashlocks:y}=p,f=await this.preparePeginCommit({depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:y,authAnchorHash:l,sizing:r,params:e});for(let c=0;c<f.perVault.length;c++)if(f.perVault[c].htlcVout!==c)throw new Error(`Internal invariant violation: htlcVout/index mismatch at vault ${c} (expected ${c}, got ${f.perVault[c].htlcVout})`);E.assertAuthAnchorOpReturn(f.fundedPrePeginTxHex,e.amounts.length,l);const{depositTerms:S,...v}=f;return{transaction:{...v,selectedUTXOs:r.selectedUTXOs,fee:r.fee,changeAmount:r.changeAmount},depositorBtcPubkey:n,derivedSecrets:{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,authAnchorHex:a},depositTerms:S}}async prepareSizing(e,t){const n=t.amounts.map(()=>j),r=t.vaultKeeperBtcPubkeys.length,s=await C.buildPrePeginPsbt({vaultCoreVersion:t.vaultCoreVersion,depositorPubkey:e,vaultProviderPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),hashlocks:n,timelockRefund:t.timelockRefund,pegInAmounts:t.amounts,feeRate:t.protocolFeeRate,minPeginFeeRate:t.minPeginFeeRate,numLocalChallengers:r,councilQuorum:t.councilQuorum,councilSize:t.councilSize,network:this.config.btcNetwork,authAnchorHash:j}),i=oe.selectUtxosForPegin([...t.availableUTXOs],s.totalOutputValue,t.mempoolFeeRate,ne.peginOutputCount(s.htlcValues.length,!0));return{selectedUTXOs:i.selectedUTXOs,fee:i.fee,changeAmount:i.changeAmount,depositorClaimValue:s.depositorClaimValue,minPeginFee:s.minPeginFee}}buildPeginDepositTerms(e){const{params:t}=e;return de({vaultCoreVersion:t.vaultCoreVersion,protocolFeeRate:t.protocolFeeRate,timelockPegin:t.timelockPegin,timelockAssert:t.timelockAssert,timelockRefund:t.timelockRefund,prepeginTxid:e.prepeginTxid,prepeginMaxFee:e.prepeginMaxFee,vaultProviderBtcPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperBtcPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerBtcPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),maxAcceptableCommissionBps:te.capMaxAcceptableCommissionBps(t.commissionBps),peginAmounts:t.amounts,depositorClaimValue:e.depositorClaimValue,peginMaxFee:e.peginMaxFee})}async preparePeginCommit(e){const{depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:r,authAnchorHash:s,sizing:i,params:a}=e,l=j.toLowerCase();for(let u=0;u<r.length;u++)if(r[u].toLowerCase()===l)throw new Error(`preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${u} — internal substitution bug`);if(s.toLowerCase()===l)throw new Error("preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug");const p=h.stripHexPrefix(a.vaultProviderBtcPubkey),d=a.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),m=a.universalChallengerBtcPubkeys.map(h.stripHexPrefix),k=d.length,y={vaultCoreVersion:a.vaultCoreVersion,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlocks:r,timelockRefund:a.timelockRefund,pegInAmounts:a.amounts,feeRate:a.protocolFeeRate,minPeginFeeRate:a.minPeginFeeRate,numLocalChallengers:k,councilQuorum:a.councilQuorum,councilSize:a.councilSize,network:this.config.btcNetwork,authAnchorHash:s},f=await C.buildPrePeginPsbt(y);if(f.depositorClaimValue!==i.depositorClaimValue||f.minPeginFee!==i.minPeginFee)throw new Error(`Pre-PegIn sizing/commit divergence: depositorClaimValue ${i.depositorClaimValue} -> ${f.depositorClaimValue}, minPeginFee ${i.minPeginFee} -> ${f.minPeginFee}. The provisional deposit terms validated before derivation would not match the terms sent for approval; refusing to continue.`);const S=h.getNetwork(this.config.btcNetwork),v=ne.fundPeginTransaction({unfundedTxHex:f.psbtHex,selectedUTXOs:i.selectedUTXOs,changeAddress:a.changeAddress,changeAmount:i.changeAmount,network:S}),c=i.selectedUTXOs.reduce((u,B)=>u+BigInt(B.value),0n)-f.totalOutputValue-i.changeAmount;if(c!==i.fee)throw new Error(`Pre-PegIn funded fee ${c} does not match the sizing-pass fee ${i.fee}; refusing to publish a deposit-terms fee bound the funded transaction does not pay.`);const R=h.stripHexPrefix(Be.calculateBtcTxHash(v)),F=[],g=[],b=[];for(let u=0;u<r.length;u++){const B=await C.buildPeginTxFromFundedPrePegin({prePeginParams:y,timelockPegin:a.timelockPegin,fundedPrePeginTxHex:v,htlcVout:u}),N=await $.buildPeginInputPsbt({vaultCoreVersion:a.vaultCoreVersion,peginTxHex:B.txHex,fundedPrePeginTxHex:v,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlock:r[u],timelockRefund:a.timelockRefund,network:this.config.btcNetwork});F.push(B),g.push(N.psbtHex),b.push(Se.createTaprootScriptPathSignOptions(t,1))}const T=this.buildPeginDepositTerms({params:a,prepeginTxid:R,prepeginMaxFee:i.fee,depositorClaimValue:f.depositorClaimValue,peginMaxFee:f.minPeginFee});E.supportsDepositApproval(this.config.btcWallet)&&await this.config.btcWallet.approveDepositTerms(T);const _=await E.signPsbtsWithFallback(this.config.btcWallet,g,b),W=[];for(let u=0;u<_.length;u++){C.assertPsbtUnsignedTxMatches({requestedPsbtHex:g[u],returnedPsbtHex:_[u]});const B=$.extractPeginInputSignature(_[u],n);C.assertScriptPathSchnorrSignature({requestedPsbtHex:g[u],signatureHex:B,signerXOnlyPubkeyHex:n,inputIndex:0});const N=$.finalizePeginInputPsbt(_[u]);W.push({htlcVout:u,htlcValue:f.htlcValues[u],peginTxHex:N,peginTxid:F[u].txid,peginInputSignature:B,vaultScriptPubKey:F[u].vaultScriptPubKey})}return{fundedPrePeginTxHex:v,prePeginTxid:R,perVault:W,depositTerms:T}}async signAndBroadcast(e){const{fundedPrePeginTxHex:t,depositorBtcPubkey:n}=e,r=t.startsWith("0x")?t.slice(2):t,s=O.Transaction.fromHex(r);if(s.ins.length===0)throw new Error("Transaction has no inputs");const i=new O.Psbt;i.setVersion(s.version),i.setLocktime(s.locktime);const a=I.Buffer.from(A(n),"hex"),l=this.config.mempoolApiUrl,p=s.ins.map(g=>{const b=I.Buffer.from(g.hash).reverse().toString("hex"),T=g.index;return Pt(b,T,e.localPrevouts,l).then(_=>({input:g,utxoData:_,txid:b,vout:T}))}),d=await Promise.all(p),m=d.reduce((g,b)=>g+BigInt(b.utxoData.value),0n),k=s.outs.reduce((g,b)=>g+BigInt(b.value),0n);if(m<k)throw new Error(`UTXO value mismatch: total input value (${m} sat) is less than total output value (${k} sat). This may indicate the mempool API returned manipulated UTXO data.`);const y=m-k;if(y>L.MAX_REASONABLE_FEE_SATS)throw new Error(`Implied transaction fee (${y} sat) exceeds maximum reasonable fee (${L.MAX_REASONABLE_FEE_SATS} sat). This may indicate manipulated UTXO data.`);for(const{input:g,utxoData:b,txid:T,vout:_}of d){const W=oe.getPsbtInputFields({value:b.value,scriptPubKey:b.scriptPubKey},a);i.addInput({hash:g.hash,index:g.index,sequence:g.sequence,...W})}for(const g of s.outs)i.addOutput({script:g.script,value:g.value});await ge({wallet:this.config.btcWallet,depositTerms:e.depositTerms,fundedPrePeginTxHex:t,depositorBtcPubkey:n});const f=i.toHex(),S=await this.config.btcWallet.signPsbt(f);C.assertPsbtUnsignedTxMatches({requestedPsbtHex:f,returnedPsbtHex:S});const v=$.assertReturnedKeyPathSignatures({requestedPsbtHex:f,returnedPsbtHex:S});if(E.supportsDepositApproval(this.config.btcWallet)&&v!==i.data.inputs.length)throw new Error(`Key-path verification covered ${v} of ${i.data.inputs.length} Pre-PegIn inputs; an approval wallet signs every input key-path, so the unverified ones must not be broadcast.`);const c=O.Psbt.fromHex(S);try{c.finalizeAllInputs()}catch(g){if(!c.data.inputs.every(T=>T.finalScriptWitness||T.finalScriptSig))throw new Error(`PSBT finalization failed and wallet did not auto-finalize: ${g}`)}const R=c.extractTransaction().toHex();return await le.pushTx(R,l)}async registerPeginOnChain(e){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.depositorPayoutBtcAddress??await this.config.btcWallet.getAddress(),s=this.resolvePayoutScriptPubKey(n,r);return this.createRegistrationClient().registerPeginOnChain({unsignedPrePeginTx:e.unsignedPrePeginTx,depositorSignedPeginTx:e.depositorSignedPeginTx,vaultProvider:e.vaultProvider,hashlock:e.hashlock,htlcVout:e.htlcVout,depositorPayoutScriptPubKey:s,depositorBtcPubkeyRaw:n,depositorWotsPkHash:e.depositorWotsPkHash,popSignature:e.popSignature,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint})}async registerPeginBatchOnChain(e){if(e.requests.length===0)throw new Error("Batch pegin requires at least one request");if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.requests.map(s=>this.resolvePayoutScriptPubKey(n,s.depositorPayoutBtcAddress));return this.createRegistrationClient().registerPeginBatchOnChain({vaultProvider:e.vaultProvider,unsignedPrePeginTx:e.unsignedPrePeginTx,popSignature:e.popSignature,depositorBtcPubkeyRaw:n,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint,requests:e.requests.map((s,i)=>({depositorSignedPeginTx:s.depositorSignedPeginTx,hashlock:s.hashlock,htlcVout:s.htlcVout,depositorPayoutScriptPubKey:r[i],depositorWotsPkHash:s.depositorWotsPkHash}))})}createRegistrationClient(){return new te.ViemPeginRegistrationClient({ethWallet:this.config.ethWallet,ethChain:this.config.ethChain,publicClient:this.config.publicClient,btcVaultRegistry:this.config.vaultContracts.btcVaultRegistry,requireQuotedCommissionBps:E.supportsDepositApproval(this.config.btcWallet)})}resolvePayoutScriptPubKey(e,t){if(!h.isAddressFromPublicKey(t,e,this.config.btcNetwork))throw h.stripHexPrefix(e).length===L.X_ONLY_PUBKEY_HEX_LEN&&mt(t,this.config.btcNetwork)?new Error(`BTC payout address "${t}" is a P2WPKH (Native SegWit) address, but the connected wallet only exposes an x-only public key. P2WPKH validation requires a compressed key with known y-parity. Use a P2TR (Taproot) payout address instead.`):new Error(`BTC payout address "${t}" is not derived from the connected wallet's public key. The payout sink must be controlled by the same key that signs the pegin; refusing to register a mismatched address.`);const n=h.getNetwork(this.config.btcNetwork);let r;try{r=pe.address.toOutputScript(t,n).toString("hex")}catch{throw new Error(`Invalid BTC payout address: "${t}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`)}return r}async signProofOfPossession(){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const e=this.config.ethWallet.account.address,t=A(await this.config.btcWallet.getPublicKeyHex()),n=this.config.vaultContracts.btcVaultRegistry,r=`${e.toLowerCase()}:${this.config.ethChain.id}:pegin:${n.toLowerCase()}`,s=await this.config.btcWallet.signMessage(r,"bip322-simple"),i=Ne(s);return gt(new TextEncoder().encode(r),t,i),{btcPopSignature:i,depositorEthAddress:e,depositorBtcPubkey:t}}async assertPopMatchesBtcWallet(e){const t=await this.config.btcWallet.getPublicKeyHex(),n=A(t),r=A(e.depositorBtcPubkey);if(n!==r)throw new Error(`Proof of possession was signed with BTC pubkey ${r} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`);return t}getNetwork(){return this.config.btcNetwork}getVaultContractAddress(){return this.config.vaultContracts.btcVaultRegistry}}exports.PeginManager=bt;exports.buildDepositTerms=de;exports.computeWotsBlockPublicKeysHash=ke;exports.deriveWotsBlocksFromSeed=xe;exports.ensurePrePeginTermsApproval=ge;exports.expandPerVaultSecrets=ve;
|
|
2
|
+
//# sourceMappingURL=PeginManager-D_ZUfbIy.cjs.map
|