@secux/app-btc
Version:
SecuX Hardware Wallet BTC API
18 lines (15 loc) • 29.7 kB
JavaScript
"use strict";
/*!
Copyright 2022 SecuX Technology Inc
Copyright Chen Wei-En
Copyright Wu Tsung-Yu
Licensed under the Apache License, Version 2.0 (the License);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an AS IS BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/var _SecuxPsbt_instances,_SecuxPsbt_data,_SecuxPsbt_coin,_SecuxPsbt_payment,_SecuxPsbt_tx,_SecuxPsbt_isRBF,_SecuxPsbt_paths,_SecuxPsbt_inScripts,_SecuxPsbt_multiSig,_SecuxPsbt_fetchInputScript,_SecuxPsbt_extractInput,_SecuxPsbt_estimateVSize,_SecuxPsbt_checkDust,_SecuxPsbt_checkSighashType,_SecuxPsbt_modifyByFee,_PsbtTransaction_tx,__classPrivateFieldSet=this&&this.__classPrivateFieldSet||function(receiver,state,value,kind,f){if("m"===kind)throw new TypeError("Private method is not writable");if("a"===kind&&!f)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof state?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===kind?f.call(receiver,value):f?f.value=value:state.set(receiver,value),value},__classPrivateFieldGet=this&&this.__classPrivateFieldGet||function(receiver,state,kind,f){if("a"===kind&&!f)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof state?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===kind?f:"a"===kind?f.call(receiver):f?f.value:state.get(receiver)};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SecuxPsbt=void 0;const utils_1=require("bip174/src/lib/utils"),secp256k1=require("secp256k1/elliptic"),hash_js_1=require("hash.js"),bignumber_js_1=require("bignumber.js"),parser_1=require("./parser"),Script=require("./script"),utility_1=require("@secux/utility"),interface_1=require("./interface"),utils_2=require("./utils"),payment_1=require("./payment"),transaction_1=require("./transaction"),coindef_1=require("./coindef"),communication_1=require("@secux/utility/lib/communication"),protocol_transaction_1=require("@secux/protocol-transaction/lib/protocol-transaction"),bip340_1=require("./bip340"),logger=null===utility_1.Logger||void 0===utility_1.Logger?void 0:utility_1.Logger.child({id:"psbt"});class SecuxPsbt{constructor(coin,isRBF=!1,data=new parser_1.Psbtv2(new PsbtTransaction)){_SecuxPsbt_instances.add(this),_SecuxPsbt_data.set(this,void 0),_SecuxPsbt_coin.set(this,void 0),_SecuxPsbt_payment.set(this,void 0),_SecuxPsbt_tx.set(this,void 0),_SecuxPsbt_isRBF.set(this,void 0),_SecuxPsbt_paths.set(this,[]),_SecuxPsbt_inScripts.set(this,{}),_SecuxPsbt_multiSig.set(this,{m:0,publickeys:[],scriptPublickey:void 0,witnessScript:void 0}),__classPrivateFieldSet(this,_SecuxPsbt_data,data,"f"),__classPrivateFieldSet(this,_SecuxPsbt_coin,coin,"f"),__classPrivateFieldSet(this,_SecuxPsbt_payment,(0,utils_2.getPayment)(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")),"f"),__classPrivateFieldSet(this,_SecuxPsbt_isRBF,isRBF,"f"),__classPrivateFieldSet(this,_SecuxPsbt_tx,__classPrivateFieldGet(this,_SecuxPsbt_data,"f").globalMap.unsignedTx.tx,"f"),coin===interface_1.CoinType.BITCOINCASH&&(__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").version=1)}static FromBuffer(data,coin){const psbtBase=parser_1.Psbtv2.fromBuffer(data,(x=>new PsbtTransaction(x)));return new SecuxPsbt(coin,!1,psbtBase)}toBuffer(){return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").toBuffer()}AddInput(input){var _a;if(!(0,utility_1.isSupportedCoin)(input.path))throw Error(`ArgumentError: unsupport bip32 path, got "${input.path}"`);const mix1={},mix2={},publickey=(0,utils_2.getPublickey)(input.publickey),script=null!==(_a=input.script)&&void 0!==_a?_a:(0,utils_2.getDefaultScript)(input.path),value=new bignumber_js_1.BigNumber(input.satoshis).toNumber();switch(script){case interface_1.ScriptType.P2PKH:mix1.witnessUtxo={script:__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2pkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey}).scriptPublickey,value};break;case interface_1.ScriptType.P2SH_P2PKH:const p2pkh=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2pkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey});mix2.redeemScript=p2pkh.scriptPublickey,mix1.witnessUtxo={script:__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2sh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{redeemScript:p2pkh.scriptPublickey}).scriptPublickey,value};break;case interface_1.ScriptType.P2SH_P2WPKH:const p2wpkh=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2wpkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey});mix2.redeemScript=p2wpkh.scriptPublickey,mix1.witnessUtxo={script:__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2sh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{redeemScript:p2wpkh.scriptPublickey}).scriptPublickey,value};break;case interface_1.ScriptType.P2WPKH:mix1.witnessUtxo={script:__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2wpkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey}).scriptPublickey,value};break;case interface_1.ScriptType.P2TR:mix1.witnessUtxo={script:__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2tr(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey}).scriptPublickey,value},mix2.sighashType=transaction_1.Transaction.SIGHASH_ALL|transaction_1.Transaction.SIGHASH_ANYONECANPAY;break;default:throw Error(`ArgumentError: Invalid ScriptType of input#${__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length}, got "${interface_1.ScriptType[script]}"`)}if(input.txHex){const tx=transaction_1.Transaction.fromBuffer(Buffer.from(input.txHex,"hex"));if((0,utils_2.getSerializer)(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")).getId(tx)!==input.hash)throw Error(`UTXO hash for input #${__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length} doesn't match the hash specified in the prevout`);const out=tx.outs[input.vout];if(!new bignumber_js_1.BigNumber(out.value).eq(input.satoshis))throw Error(`UTXO value for input #${__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length} doesn't match the value specified in the prevout`);out.script.equals(mix1.witnessUtxo.script)||null==logger||logger.warn(`Input script generation error: ${out.script.toString("hex")}, got "${mix1.witnessUtxo.script}"`)}const data=Object.assign(Object.assign({hash:input.hash,index:input.vout,sequence:__classPrivateFieldGet(this,_SecuxPsbt_isRBF,"f")?4294967293:void 0},mix1),mix2);return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").addInput(data),__classPrivateFieldGet(this,_SecuxPsbt_paths,"f").push(input.path),this}AddInputs(inputs){for(const input of inputs)this.AddInput(input);return this}initializeMultiSig(m,publickeys){if(![interface_1.CoinType.BITCOIN,interface_1.CoinType.TESTNET,interface_1.CoinType.REGTEST].includes(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")))throw Error(`unsupported chain: ${interface_1.CoinType[__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")]}`);__classPrivateFieldGet(this,_SecuxPsbt_multiSig,"f").m=m;const pks=publickeys.map((pk=>(0,utils_2.getPublickey)(pk)));__classPrivateFieldGet(this,_SecuxPsbt_multiSig,"f").publickeys=pks;const redeemScript=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2ms(m,pks).scriptPubicKey,p2wsh=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2wsh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{redeemScript});return __classPrivateFieldGet(this,_SecuxPsbt_multiSig,"f").scriptPublickey=p2wsh.scriptPublickey,__classPrivateFieldGet(this,_SecuxPsbt_multiSig,"f").witnessScript=redeemScript,{address:p2wsh.address,redeemScript:redeemScript.toString("hex")}}addMultiSigInput(input){const mix1={},mix2={},value=new bignumber_js_1.BigNumber(input.satoshis).toNumber();if(mix2.witnessScript=__classPrivateFieldGet(this,_SecuxPsbt_multiSig,"f").witnessScript,mix1.witnessUtxo={script:__classPrivateFieldGet(this,_SecuxPsbt_multiSig,"f").scriptPublickey,value},input.txHex){const tx=transaction_1.Transaction.fromBuffer(Buffer.from(input.txHex,"hex"));if((0,utils_2.getSerializer)(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")).getId(tx)!==input.hash)throw Error(`UTXO hash for input #${__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length} doesn't match the hash specified in the prevout`);const out=tx.outs[input.vout];if(!new bignumber_js_1.BigNumber(out.value).eq(input.satoshis))throw Error(`UTXO value for input #${__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length} doesn't match the value specified in the prevout`);out.script.equals(mix1.witnessUtxo.script)||null==logger||logger.warn(`Input script generation error: ${out.script.toString("hex")}, got "${mix1.witnessUtxo.script}"`)}const data=Object.assign(Object.assign({hash:input.hash,index:input.vout,sequence:__classPrivateFieldGet(this,_SecuxPsbt_isRBF,"f")?4294967293:void 0},mix1),mix2);return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").addInput(data),this}AddOutput(output){var _a;let out,script,path,value=new bignumber_js_1.BigNumber(output.satoshis).toNumber();if(out=(0,interface_1.isOutuptScriptExtended)(output)){const pk=(0,utils_2.getPublickey)(out.publickey);path=out.path;const scriptType=null!==(_a=out.script)&&void 0!==_a?_a:(0,utils_2.getDefaultScript)(path);switch(scriptType){case interface_1.ScriptType.P2SH_P2WPKH:{if(!out.path.startsWith("m/49'/"))throw Error("P2SH(...) should use m/49' path");const p2wpkh=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2wpkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey:pk});script=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2sh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{redeemScript:p2wpkh.scriptPublickey}).scriptPublickey;break}case interface_1.ScriptType.P2SH_P2PKH:{if(!out.path.startsWith("m/49'/"))throw Error("P2SH(...) should use m/49' path");const p2pkh=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2pkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey:pk});script=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2sh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{redeemScript:p2pkh.scriptPublickey}).scriptPublickey;break}case interface_1.ScriptType.P2PKH:if(!out.path.startsWith("m/44'/"))throw Error("P2PKH should use m/44' path");script=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2pkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey:pk}).scriptPublickey;break;case interface_1.ScriptType.P2WPKH:if(!out.path.startsWith("m/84'/"))throw Error("P2WPKH should use m/84' path");script=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2wpkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey:pk}).scriptPublickey;break;case interface_1.ScriptType.P2TR:if(!out.path.startsWith("m/86'/"))throw Error("P2TR should use m/86' path");script=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").p2tr(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{publickey:pk}).scriptPublickey;break;default:throw Error(`ArgumentError: Invalid ScriptType of output#${__classPrivateFieldGet(this,_SecuxPsbt_data,"f").outputs.length}, got "${interface_1.ScriptType[scriptType]}"`)}}else if(out=(0,interface_1.isOutputAddress)(output))script=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").decode(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),out.address);else{if(!(out=(0,interface_1.isOutuptScript)(output)))throw Error("Invalid parameter of output");script=Buffer.from(out.scriptHex,"hex")}return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").addOutput({script,value,path}),this}AddOutputs(outputs){for(const output of outputs)this.AddOutput(output);return this}PrepareSign(feeRate){feeRate&&__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_modifyByFee).call(this,feeRate,__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs.length-1),__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_checkDust).call(this,!!feeRate);const outConfirm=Buffer.from([__classPrivateFieldGet(this,_SecuxPsbt_data,"f").outputs.length,...(0,utility_1.BigIntToBuffer)(__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs[0].value,8),__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs[0].script.length,...__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs[0].script,...__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs.slice(1).reduce(((data,out)=>[...data,...(0,utility_1.BigIntToBuffer)(out.value,8),...(0,utility_1.buildPathBuffer)(out.path).pathBuffer]),[])]),txs=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.map(((_,i)=>{const data=this.getDataForSig(i);if(null==logger||logger.debug(`tx data [${i}]: ${data.toString("hex")}`),data.length+communication_1.MAX_HEAD_SIZE>communication_1.ONESIGN_THRESHOLD)throw Error("ArgumentError: utxo exceed maximum payload size");return data}));null==logger||logger.debug(`confirm data: ${outConfirm.toString("hex")}`);const commands=[];let _txs=[],_paths=[],confirmBuf=__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")!==interface_1.CoinType.BITCOINCASH&&__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,0).type===interface_1.ScriptType.P2PKH?Buffer.alloc(0):outConfirm;for(let i=0,size=0;i<txs.length;i++){if(size+=txs[i].length+communication_1.MAX_HEAD_SIZE,_txs.push(txs[i]),_paths.push(__classPrivateFieldGet(this,_SecuxPsbt_paths,"f")[i]),size+confirmBuf.length<communication_1.ONESIGN_THRESHOLD)continue;_txs.pop(),_paths.pop(),commands.push(protocol_transaction_1.SecuxTransactionTool.signRawTransactionList(_paths,_txs,confirmBuf)),size=txs[i].length+communication_1.MAX_HEAD_SIZE,_txs=[txs[i]],_paths=[__classPrivateFieldGet(this,_SecuxPsbt_paths,"f")[i]];const{type}=__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,i);confirmBuf=__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")!==interface_1.CoinType.BITCOINCASH&&type===interface_1.ScriptType.P2PKH?Buffer.alloc(0):outConfirm}return _txs.length>0&&commands.push(protocol_transaction_1.SecuxTransactionTool.signRawTransactionList(_paths,_txs,confirmBuf)),{commands,rawTx:__classPrivateFieldGet(this,_SecuxPsbt_data,"f").toHex()}}appendSignature(signatures,publickeys){var _a,_b;if(signatures.length!==publickeys.length)throw Error(`ArgumentError: each signature is correspond to one publickey, got ${signatures.length} signatures and ${publickeys.length} publickeys`);for(let i=0;i<__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length;i++){const data=this.getDataForSig(i);if(__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,i).type!==interface_1.ScriptType.P2TR){const hash=__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")===interface_1.CoinType.GROESTL?Buffer.from((0,hash_js_1.sha256)().update(data).digest()):Buffer.from((0,hash_js_1.sha256)().update((0,hash_js_1.sha256)().update(data).digest()).digest()),publickey=publickeys[i];if(!secp256k1.ecdsaVerify(signatures[i],hash,publickey))throw Error(`Signature Error #${i}`);let sighashType=null!==(_a=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs[i].sighashType)&&void 0!==_a?_a:transaction_1.Transaction.SIGHASH_ALL;__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")===interface_1.CoinType.BITCOINCASH&&(sighashType|=64);const partialSig=[{pubkey:publickey,signature:Script.encode(signatures[i],sighashType)}];__classPrivateFieldGet(this,_SecuxPsbt_data,"f").updateInput(i,{partialSig})}else{const hash=(0,utils_2.taggedHash)("TapSighash",data),tweaked=(0,utils_2.toTweakedPublickey)(publickeys[i]),signature=signatures[i].slice(0,64);if(!(0,bip340_1.taprootVerify)(signature,hash,tweaked))throw Error(`Signature Error #${i}`);const sighashType=null!==(_b=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs[i].sighashType)&&void 0!==_b?_b:transaction_1.Transaction.SIGHASH_DEFAULT;__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs[i].partialSig=[{pubkey:tweaked,signature:sighashType===transaction_1.Transaction.SIGHASH_DEFAULT?signature:Buffer.from([...signature,sighashType])}]}}return this}submitSignature(index,data){var _a;const input=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs[index];input.partialSig||(input.partialSig=[]);const sighashType=null!==(_a=input.sighashType)&&void 0!==_a?_a:transaction_1.Transaction.SIGHASH_ALL;return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").updateInput(index,{partialSig:[{pubkey:data.publickey,signature:Script.encode(data.signature,sighashType)}]}),this}finalizeAllInputs(){if(__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.length<1)throw Error("utxo input cannot be empty");return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.forEach(((input,idx)=>{(0,utils_1.checkForInput)(__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs,idx);const{script,scriptType}=getScriptFromInput(input,__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"));if(!script)throw new Error(`No script found for input #${idx}`);__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_checkSighashType).call(this,input,scriptType);const{finalScriptSig,finalScriptWitness}=function(scriptType,input){let finalScriptSig,finalScriptWitness;const{signature,pubkey}=input.partialSig[0];switch(scriptType){case interface_1.ScriptType.P2PKH:finalScriptSig=Script.compile([signature,pubkey]);break;case interface_1.ScriptType.P2SH_P2PKH:finalScriptSig=(()=>{const input=Script.compile([signature,pubkey]),chunks=Script.decompile(input),redeem={output:chunks[chunks.length-1],input:Script.compile(chunks.slice(0,-1))};return Script.compile([].concat(Script.decompile(redeem.input),redeem.output))})();break;case interface_1.ScriptType.P2SH_P2WPKH:finalScriptWitness=(0,utils_2.witnessStackToScriptWitness)([signature,pubkey]),finalScriptSig=(()=>{const input=Buffer.alloc(0),hash=(0,payment_1.Hash160)(pubkey),output=Script.compile([coindef_1.OPCODES.OP_0,hash]);return Script.compile([].concat(Script.decompile(input),output))})();break;case interface_1.ScriptType.P2SH_P2MS:finalScriptSig=(()=>{const signatures=getSortedSignatures(input),_input=Script.compile([coindef_1.OPCODES.OP_0].concat(signatures));return Script.compile([].concat(Script.decompile(_input),input.redeemScript))})();break;case interface_1.ScriptType.P2WPKH:finalScriptWitness=(0,utils_2.witnessStackToScriptWitness)([signature,pubkey]);break;case interface_1.ScriptType.P2WSH_P2MS:{const signatures=getSortedSignatures(input),scriptSig=Script.toStack([coindef_1.OPCODES.OP_0,...signatures]);finalScriptWitness=(0,utils_2.witnessStackToScriptWitness)([...scriptSig,input.witnessScript]);break}case interface_1.ScriptType.P2TR:finalScriptWitness=signature}return{finalScriptSig,finalScriptWitness}}(scriptType,input);if(finalScriptSig&&__classPrivateFieldGet(this,_SecuxPsbt_data,"f").updateInput(idx,{finalScriptSig}),finalScriptWitness&&__classPrivateFieldGet(this,_SecuxPsbt_data,"f").updateInput(idx,{finalScriptWitness}),!finalScriptSig&&!finalScriptWitness)throw new Error(`Unknown error finalizing input #${idx}`)})),this}extractTransaction(){const tx=__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").clone();__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.forEach(((input,idx)=>__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_extractInput).call(this,tx,idx,input)));const input=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.reduce(((sum,txIn)=>sum.plus(txIn.witnessUtxo.value)),new bignumber_js_1.BigNumber(0)),output=tx.outs.reduce(((sum,txOut)=>sum.plus(txOut.value)),new bignumber_js_1.BigNumber(0)),fee=input.minus(output),minFee=tx.virtualSize();if(fee.lt(minFee))throw Error(`Transaction fee must >= ${minFee}, but got ${fee}.`);return tx}virtualSize(){const tx=__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").clone();return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.forEach(((input,idx)=>__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_extractInput).call(this,tx,idx,input))),tx.virtualSize()}getDataForSig(inputIndex){var _a,_b;const txIn=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs[inputIndex],unsignedTx=__classPrivateFieldGet(this,_SecuxPsbt_tx,"f");let sighashType=null!==(_a=txIn.sighashType)&&void 0!==_a?_a:transaction_1.Transaction.SIGHASH_ALL;const serializer=(0,utils_2.getSerializer)(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"));void 0===txIn.witnessUtxo&&Error("Need a Utxo input item for signing");const prevout=txIn.witnessUtxo,{type,scriptPubkey}=__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,inputIndex);let data;switch(type){case interface_1.ScriptType.P2WPKH:case interface_1.ScriptType.P2SH_P2WPKH:null==logger||logger.debug(interface_1.ScriptType[type]);const signingScript=(0,utils_2.getPayment)(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")).p2pkh(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),{hash:scriptPubkey.slice(2)}).scriptPublickey;data=serializer.dataForWitnessV0(unsignedTx,inputIndex,signingScript,prevout.value,sighashType);break;case interface_1.ScriptType.P2WSH:case interface_1.ScriptType.P2WSH_P2MS:null==logger||logger.debug(interface_1.ScriptType[type]),data=serializer.dataForWitnessV0(unsignedTx,inputIndex,txIn.witnessScript,prevout.value,sighashType);break;case interface_1.ScriptType.P2TR:null==logger||logger.debug("p2tr"),sighashType=null!==(_b=txIn.sighashType)&&void 0!==_b?_b:transaction_1.Transaction.SIGHASH_DEFAULT,data=serializer.dataForWitnessV1(unsignedTx,inputIndex,__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.map(((_,i)=>__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,i).scriptPubkey)),__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.map((x=>x.witnessUtxo.value)),sighashType);break;default:__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")===interface_1.CoinType.BITCOINCASH?(null==logger||logger.debug("bch using bip143"),data=serializer.dataForWitnessV0(unsignedTx,inputIndex,scriptPubkey,prevout.value,64|sighashType)):(null==logger||logger.debug("non-segwit"),data=serializer.dataForSignature(unsignedTx,inputIndex,scriptPubkey,sighashType))}return data}}function getScriptFromInput(input,coin){let script,scriptType;const payment=(0,utils_2.getPayment)(coin);if(input.witnessScript){if(script=input.witnessScript,scriptType=payment.classify(script),scriptType!==interface_1.ScriptType.P2MS)throw Error(`unknown script: ${script.toString("hex")}`);scriptType=interface_1.ScriptType.P2WSH_P2MS}else if(input.redeemScript)switch(script=input.redeemScript,scriptType=payment.classify(script),scriptType){case interface_1.ScriptType.P2PKH:scriptType=interface_1.ScriptType.P2SH_P2PKH;break;case interface_1.ScriptType.P2WPKH:scriptType=interface_1.ScriptType.P2SH_P2WPKH;break;case interface_1.ScriptType.P2MS:scriptType=interface_1.ScriptType.P2SH_P2MS;break;default:throw Error(`unknown script: ${script.toString("hex")}`)}else script=input.witnessUtxo.script,scriptType=payment.classify(script);return{script,scriptType}}function getSortedSignatures(input){var _a;const chunk=Script.decompile(null!==(_a=input.witnessScript)&&void 0!==_a?_a:input.redeemScript),m=chunk[0]-coindef_1.OPCODES.OP_INT_BASE,sigData=input.partialSig,signatures=[],orderedPublickeys=chunk.slice(1,-2);for(const pk of orderedPublickeys){const sig=sigData.find((sig=>sig.pubkey.equals(pk)));sig&&signatures.push(sig.signature)}if(signatures.length<m)throw Error(`${m} signatures needed, but got ${sigData.length}`);return signatures}exports.SecuxPsbt=SecuxPsbt,_SecuxPsbt_data=new WeakMap,_SecuxPsbt_coin=new WeakMap,_SecuxPsbt_payment=new WeakMap,_SecuxPsbt_tx=new WeakMap,_SecuxPsbt_isRBF=new WeakMap,_SecuxPsbt_paths=new WeakMap,_SecuxPsbt_inScripts=new WeakMap,_SecuxPsbt_multiSig=new WeakMap,_SecuxPsbt_instances=new WeakSet,_SecuxPsbt_fetchInputScript=function(index){if(__classPrivateFieldGet(this,_SecuxPsbt_inScripts,"f")[index])return __classPrivateFieldGet(this,_SecuxPsbt_inScripts,"f")[index];const txIn=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs[index],prevout=txIn.witnessUtxo,type=getScriptFromInput(txIn,__classPrivateFieldGet(this,_SecuxPsbt_coin,"f")).scriptType,scriptPubkey=function(script,scriptType,redeemScript){let meaningfulScript;switch(scriptType){case interface_1.ScriptType.P2SH:case interface_1.ScriptType.P2SH_P2PKH:case interface_1.ScriptType.P2SH_P2WPKH:case interface_1.ScriptType.P2SH_P2MS:if(!redeemScript)throw Error("scriptPubkey is P2SH but redeemScript missing");meaningfulScript=redeemScript;break;default:meaningfulScript=script}if(!meaningfulScript)throw Error("cannot extract script");return meaningfulScript}(prevout.script,type,txIn.redeemScript);null==logger||logger.debug(`input #${index} script type: ${interface_1.ScriptType[type]}`),null==logger||logger.debug(`script: ${scriptPubkey.toString("hex")}`);const obj={type,scriptPubkey};return __classPrivateFieldGet(this,_SecuxPsbt_inScripts,"f")[index]=obj,obj},_SecuxPsbt_extractInput=function(tx,index,_){if(!_.finalScriptSig&&!_.finalScriptWitness)throw Error(`input#${index} not finalized.`);_.finalScriptSig&&(tx.ins[index].script=_.finalScriptSig),_.finalScriptWitness&&(__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,index).type!==interface_1.ScriptType.P2TR?tx.ins[index].witness=(0,utils_2.scriptWitnessToWitnessStack)(_.finalScriptWitness):tx.ins[index].witness=[_.finalScriptWitness])},_SecuxPsbt_estimateVSize=function(){const txForFee=__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").clone();let scriptSize=0,witnessSize=2;return __classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.forEach(((txIn,i)=>{const{type}=__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_fetchInputScript).call(this,i);scriptSize+=(0,utils_2.getInScriptSize)(type);const witness=(0,utils_2.getWitnessSize)(type,txIn.sighashType);witnessSize+=(0,utils_2.vectorSize)(witness)})),txForFee.virtualSize()+scriptSize+witnessSize/4},_SecuxPsbt_checkDust=function(throwError){let error;for(let i=0;i<__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs.length;i++){const{script,value}=__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs[i];if(__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").isArbitraryData(script))continue;const type=__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").isP2SH(script)?interface_1.ScriptType.P2SH_P2WPKH:__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").classify(script),dust=(0,utils_2.getDustThreshold)(type,3),_value=(0,bignumber_js_1.BigNumber)(value);null==logger||logger.debug(`output #${i}\n${__classPrivateFieldGet(this,_SecuxPsbt_payment,"f").encode(__classPrivateFieldGet(this,_SecuxPsbt_coin,"f"),script)}\n${_value.toFixed(0)}`),_value.lt(dust)&&(null==logger||logger.warn(`output #${i}: dust threshold is ${dust}, but got ${_value.toFixed(0)}`),error||(error=Error("Transaction has output below a certain value (Dust).")))}if(throwError&&error)throw error},_SecuxPsbt_checkSighashType=function(input,type){if(type===interface_1.ScriptType.P2TR)return;if(!input.sighashType)return;if(!input.partialSig)return;const{partialSig,sighashType}=input;for(const sig of partialSig){const{hashType}=Script.decode(sig.signature);if(hashType!==sighashType)throw Error("Signature sighash does not match input sighash type")}},_SecuxPsbt_modifyByFee=function(feeRate,changeIndex=0){const vSize=__classPrivateFieldGet(this,_SecuxPsbt_instances,"m",_SecuxPsbt_estimateVSize).call(this),estimateFee=Math.round(vSize*feeRate);null==logger||logger.info(`Estimated fee is ${estimateFee}, with ${feeRate} fee rates.`);const actualFee=__classPrivateFieldGet(this,_SecuxPsbt_data,"f").inputs.reduce(((a,txIn)=>a+txIn.witnessUtxo.value),0)-__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs.reduce(((a,txOut)=>a+txOut.value),0);actualFee<estimateFee&&(null==logger||logger.warn(`Estimated fee is ${estimateFee}, but got ${actualFee}.`));const change=__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs[changeIndex].value,modified_change=change+(actualFee-estimateFee);__classPrivateFieldGet(this,_SecuxPsbt_tx,"f").outs[changeIndex].value=modified_change,null==logger||logger.info(`Modify output#${changeIndex} amount from ${change} to ${modified_change}.`)};class PsbtTransaction{constructor(buffer=Buffer.from([2,0,0,0,0,0,0,0,0,0])){_PsbtTransaction_tx.set(this,void 0),__classPrivateFieldSet(this,_PsbtTransaction_tx,transaction_1.Transaction.fromBuffer(buffer),"f")}getInputOutputCounts(){return{inputCount:__classPrivateFieldGet(this,_PsbtTransaction_tx,"f").ins.length,outputCount:__classPrivateFieldGet(this,_PsbtTransaction_tx,"f").outs.length}}addInput(input){if(void 0===input.hash||void 0===input.index||!Buffer.isBuffer(input.hash)&&"string"!=typeof input.hash||"number"!=typeof input.index)throw new Error("Error adding input.");const hash="string"==typeof input.hash?Buffer.from(Buffer.from(input.hash,"hex").reverse()):input.hash;__classPrivateFieldGet(this,_PsbtTransaction_tx,"f").addInput(hash,input.index,input.sequence)}addOutput(output){if(void 0===output.script||void 0===output.value||!Buffer.isBuffer(output.script)||"number"!=typeof output.value)throw new Error("Error adding output.");__classPrivateFieldGet(this,_PsbtTransaction_tx,"f").addOutput(output.script,output.value,output.path)}toBuffer(){return __classPrivateFieldGet(this,_PsbtTransaction_tx,"f").toBuffer()}get tx(){return __classPrivateFieldGet(this,_PsbtTransaction_tx,"f")}}_PsbtTransaction_tx=new WeakMap;