UNPKG

nerve-sdk-js

Version:
897 lines (753 loc) 29 kB
"use strict"; var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function get() { return m[k]; } }; } Object.defineProperty(o, k2, desc); } : function (o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; }); var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); } : function (o, v) { o["default"] = v; }); var __importStar = void 0 && (void 0).__importStar || function () { var _ownKeys = function ownKeys(o) { _ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) { if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; } return ar; }; return _ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = _ownKeys(mod), i = 0; i < k.length; i++) { if (k[i] !== "default") __createBinding(result, mod, k[i]); } __setModuleDefault(result, mod); return result; }; }(); Object.defineProperty(exports, "__esModule", { value: true }); var tbc = __importStar(require("tbc-lib-js")); var FT = require("./ft"); class MultiSig { /** * Create a multi-signature transaction * @param address_from The address from which the transaction is sent * @param pubKeys An array of public keys involved in the multi-signature * @param signatureCount The number of signatures required to authorize the transaction * @param publicKeyCount The total number of public keys in the multi-signature * @param amount_tbc The amount to be sent in TBC * @param utxos An array of unspent transaction outputs to be used as inputs * @param privateKey The private key used to sign the transaction * @returns The raw serialized transaction string */ static createMultiSigWallet(address_from, pubKeys, signatureCount, publicKeyCount, tbc_amount, utxos, privateKey) { var address = MultiSig.getMultiSigAddress(pubKeys, signatureCount, publicKeyCount); var script_asm = MultiSig.getMultiSigLockScript(address); var tx = new tbc.Transaction(); tx.from(utxos); tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm), satoshis: Math.floor(tbc_amount * 1e6) })); for (var i = 0; i < publicKeyCount; i++) { tx.addOutput(new tbc.Transaction.Output({ script: MultiSig.buildHoldScript(pubKeys[i]), satoshis: 200 })); } tx.addOutput(new tbc.Transaction.Output({ script: MultiSig.buildTapeScript(address, pubKeys), satoshis: 0 })).change(address_from); var txSize = tx.getEstimateSize(); if (txSize < 1000) { tx.fee(80); } else { tx.feePerKb(100); } tx.sign(privateKey).seal(); var raw = tx.uncheckedSerialize(); return raw; } /** * Create a P2PKH to multi-signature transaction * @param address_from The address from which the transaction is sent * @param address_to The address to which the transaction is sent * @param amount_tbc The amount to be sent in TBC * @param utxos An array of unspent transaction outputs to be used as inputs * @param privateKey The private key used to sign the transaction * @returns The raw serialized transaction string */ static p2pkhToMultiSig_sendTBC(address_from, address_to, amount_tbc, utxos, privateKey, additionalInfo) { var script_asm = MultiSig.getMultiSigLockScript(address_to); var amount_satoshis = Math.floor(amount_tbc * Math.pow(10, 6)); var tx = new tbc.Transaction().from(utxos).addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm), satoshis: amount_satoshis })); if (additionalInfo) { //Additional infromation output var additionalInfoScript = tbc.Script.fromASM('OP_FALSE OP_RETURN'); additionalInfoScript = additionalInfoScript.add(additionalInfo); tx.addOutput(new tbc.Transaction.Output({ script: additionalInfoScript, satoshis: 0 })); } tx.change(address_from); var txSize = tx.getEstimateSize(); if (txSize < 1000) { tx.fee(80); } else { tx.feePerKb(100); } tx.sign(privateKey).seal(); var raw = tx.uncheckedSerialize(); return raw; } /** * Build a multi-signature transaction * @param address_from The address from which the transaction is sent * @param address_to The address to which the transaction is sent * @param amount_tbc The amount to be sent in TBC * @param utxos An array of unspent transaction outputs to be used as inputs * @returns The raw serialized transaction string */ static buildMultiSigTransaction_sendTBC(address_from, address_to, amount_tbc, utxos, additionalInfo) { var script_asm_from = MultiSig.getMultiSigLockScript(address_from); var amount_satoshis = Math.floor(amount_tbc * Math.pow(10, 6)); var count = 0; var amounts = []; for (var i = 0; i < utxos.length; i++) { count += utxos[i].satoshis; amounts.push(utxos[i].satoshis); } var tx = new tbc.Transaction().from(utxos); tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: count - amount_satoshis - 1000 })).to(address_to, amount_satoshis); //Additional infromation output if (additionalInfo) { var additionalInfoScript = tbc.Script.fromASM('OP_FALSE OP_RETURN'); additionalInfoScript = additionalInfoScript.add(additionalInfo); tx.addOutput(new tbc.Transaction.Output({ script: additionalInfoScript, satoshis: 0 })); } var txraw = tx.uncheckedSerialize(); return { txraw, amounts }; } /** * Build a multi-signature transaction * @param address_from The address from which the transaction is sent * @param address_to The address to which the transaction is sent * @param amount_tbc The amount to be sent in TBC * @param utxos An array of unspent transaction outputs to be used as inputs * @returns The raw serialized transaction string */ static buildMultiSigTransaction_sendTBCToMultiSig(address_from, address_to, amount_tbc, utxos, additionalInfo) { var script_asm_from = MultiSig.getMultiSigLockScript(address_from); var script_asm_to = MultiSig.getMultiSigLockScript(address_to); var amount_satoshis = Math.floor(amount_tbc * Math.pow(10, 6)); var count = 0; var amounts = []; for (var i = 0; i < utxos.length; i++) { count += utxos[i].satoshis; amounts.push(utxos[i].satoshis); } var tx_source = new tbc.Transaction().from(utxos); tx_source.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_to), satoshis: amount_satoshis })); tx_source.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: count - amount_satoshis - 1000 })); //Additional infromation output if (additionalInfo) { var additionalInfoScript = tbc.Script.fromASM('OP_FALSE OP_RETURN'); additionalInfoScript = additionalInfoScript.add(additionalInfo); tx_source.addOutput(new tbc.Transaction.Output({ script: additionalInfoScript, satoshis: 0 })); } var tx_source_raw = tx_source.uncheckedSerialize(); if (count - amount_satoshis - 1100 > 80) { var tx = new tbc.Transaction(); tx.addInputFromPrevTx(tx_source, 1).addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: count - amount_satoshis - 1100 })); var tx_raw = tx.uncheckedSerialize(); return [{ txraw: tx_source_raw, amounts }, { txraw: tx_raw, amounts: [count - amount_satoshis - 1000] }]; } else { return [{ txraw: tx_source_raw, amounts }]; } } /** * Sign a multi-signature transaction * @param address_from The address from which the transaction is sent * @param multiSigTxraw The raw serialized transaction string * @param privateKey The private key used to sign the transaction * @returns An array of signatures */ static signMultiSigTransaction_sendTBC(address_from, multiSigTxraw, privateKey) { var script_asm = MultiSig.getMultiSigLockScript(address_from); var { txraw, amounts } = multiSigTxraw; var tx = new tbc.Transaction(txraw); for (var i = 0; i < amounts.length; i++) { tx.inputs[i].output = new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm), satoshis: amounts[i] }); } var sigs = []; for (var _i = 0; _i < amounts.length; _i++) { sigs[_i] = tx.getSignature(_i, privateKey); } return sigs; } /** * Sign multi-signature transactions * @param address_from The address from which the transaction is sent * @param multiSigTxraws The raw serialized transaction string * @param privateKey The private key used to sign the transaction * @returns An array of signatures */ static batchSignMultiSigTransaction_sendTBC(address_from, multiSigTxraws, privateKey) { var allSigs = []; for (var txIndex = 0; txIndex < multiSigTxraws.length; txIndex++) { var sigs = MultiSig.signMultiSigTransaction_sendTBC(address_from, multiSigTxraws[txIndex], privateKey); allSigs.push(sigs); } return allSigs; } /** * Finish a multi-signature transaction * @param txraw The raw serialized transaction string * @param sigs An array of signatures * @param pubkeys An array of public keys * @returns The raw serialized transaction string */ static finishMultiSigTransaction_sendTBC(txraw, sigs, pubKeys) { var multiPubKeys = ""; for (var i = 0; i < pubKeys.length; i++) { multiPubKeys = multiPubKeys + pubKeys[i]; } var tx = new tbc.Transaction(txraw); var _loop = function _loop(j) { tx.setInputScript({ inputIndex: j }, tx => { var signature = ""; for (var _i2 = 0; _i2 < sigs[j].length; _i2++) { if (_i2 < sigs[j].length - 1) { signature = signature + sigs[j][_i2] + " "; } else { signature = signature + sigs[j][_i2]; } } var unlockingScript = tbc.Script.fromASM("OP_0 ".concat(signature, " ").concat(multiPubKeys)); return unlockingScript; }); }; for (var j = 0; j < sigs.length; j++) { _loop(j); } return tx.uncheckedSerialize(); } /** * Finish multi-signature transactions * @param txraws The raw serialized transaction string * @param sigs An array of signatures * @param pubkeys An array of public keys * @returns The raw serialized transaction string */ static batchFinishMultiSigTransaction_sendTBC(txraws, sigs, pubKeys) { var finishedTxs = []; for (var txIndex = 0; txIndex < txraws.length; txIndex++) { var finishedTx = MultiSig.finishMultiSigTransaction_sendTBC(txraws[txIndex], sigs[txIndex], pubKeys); finishedTxs.push(finishedTx); } return finishedTxs; } /** * Transfer FT from a multi-signature address to another address * @param address_from The address from which the transaction is sent * @param address_to The address to which the transaction is sent * @param ft The FT contract * @param ft_amount The amount to be sent in FT * @param utxo The UTXO to be used as input * @param ftutxos An array of UTXOs to be used as inputs * @param preTX An array of previous transactions * @param prepreTxData An array of previous transaction data * @param privateKey The private key used to sign the transaction * @returns The raw serialized transaction string */ static p2pkhToMultiSig_transferFT(address_from, address_to, ft, ft_amount, utxo, ftutxos, preTXs, prepreTxDatas, privateKey, tbc_amount, additionalInfo) { var code = ft.codeScript; var tape = ft.tapeScript; var decimal = ft.decimal; var tapeAmountSetIn = []; if (ft_amount < 0) { throw new Error("Invalid amount"); } var amountbn = BigInt(Math.floor(ft_amount * Math.pow(10, decimal))); var tapeAmountSum = BigInt(0); for (var i = 0; i < ftutxos.length; i++) { tapeAmountSetIn.push(ftutxos[i].ftBalance); tapeAmountSum += BigInt(tapeAmountSetIn[i]); } if (amountbn > tapeAmountSum) { throw new Error("Insufficient balance, please add more FT UTXOs"); } if (decimal > 18) { throw new Error("The maximum value for decimal cannot exceed 18"); } var maxAmount = Math.floor(Math.pow(10, 18 - decimal)); if (ft_amount > maxAmount) { throw new Error("When decimal is ".concat(decimal, ", the maximum amount cannot exceed ").concat(maxAmount)); } var { amountHex, changeHex } = FT.buildTapeAmount(amountbn, tapeAmountSetIn); var script_asm = MultiSig.getMultiSigLockScript(address_to); var tx = new tbc.Transaction().from(ftutxos).from(utxo); if (tbc_amount && Number(tbc_amount) > 0) { var amount_satoshis = Math.floor(tbc_amount * Math.pow(10, 6)); tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm), satoshis: amount_satoshis })); } var hash = tbc.crypto.Hash.sha256ripemd160(tbc.crypto.Hash.sha256(tbc.Script.fromASM(script_asm).toBuffer())).toString("hex"); var codeScript = FT.buildFTtransferCode(code, hash); tx.addOutput(new tbc.Transaction.Output({ script: codeScript, satoshis: 2000 })); var tapeScript = FT.buildFTtransferTape(tape, amountHex); tx.addOutput(new tbc.Transaction.Output({ script: tapeScript, satoshis: 0 })); if (amountbn < tapeAmountSum) { var changeCodeScript = FT.buildFTtransferCode(code, address_from); tx.addOutput(new tbc.Transaction.Output({ script: changeCodeScript, satoshis: 2000 })); var changeTapeScript = FT.buildFTtransferTape(tape, changeHex); tx.addOutput(new tbc.Transaction.Output({ script: changeTapeScript, satoshis: 0 })); } if (additionalInfo) { //Additional infromation output var additionalInfoScript = tbc.Script.fromASM('OP_FALSE OP_RETURN'); additionalInfoScript = additionalInfoScript.add(additionalInfo); tx.addOutput(new tbc.Transaction.Output({ script: additionalInfoScript, satoshis: 0 })); } tx.change(address_from); var txSize = tx.getEstimateSize(); if (txSize < 1000) { tx.fee(80); } else { tx.feePerKb(100); } var _loop2 = function _loop2(_i3) { tx.setInputScript({ inputIndex: _i3 }, tx => { var unlockingScript = ft.getFTunlock(privateKey, tx, preTXs[_i3], prepreTxDatas[_i3], _i3, ftutxos[_i3].outputIndex); return unlockingScript; }); }; for (var _i3 = 0; _i3 < ftutxos.length; _i3++) { _loop2(_i3); } tx.sign(privateKey).seal(); return tx.uncheckedSerialize(); } /** * Build a multi-signature transaction for transferring FT * @param address_from The address from which the transaction is sent * @param address_to The address to which the transaction is sent * @param ft The FT contract * @param ft_amount The amount to be sent in FT * @param utxo The UTXO to be used as input * @param ftutxos An array of UTXOs to be used as inputs * @param preTX An array of previous transactions * @param prepreTxData An array of previous transaction data * @param privateKey The private key used to sign the transaction * @returns The raw serialized transaction string */ static buildMultiSigTransaction_transferFT(address_from, address_to, ft, ft_amount, utxo, ftutxos, preTXs, prepreTxDatas, contractTX, privateKey, tbc_amount, additionalInfo) { var code = ft.codeScript; var tape = ft.tapeScript; var decimal = ft.decimal; var tapeAmountSetIn = []; var script_asm_from = MultiSig.getMultiSigLockScript(address_from); var hash_from = tbc.crypto.Hash.sha256ripemd160(tbc.crypto.Hash.sha256(tbc.Script.fromASM(script_asm_from).toBuffer())).toString("hex"); var amountbn = BigInt(Math.floor(ft_amount * Math.pow(10, decimal))); var tapeAmountSum = BigInt(0); for (var i = 0; i < ftutxos.length; i++) { tapeAmountSetIn.push(ftutxos[i].ftBalance); tapeAmountSum += BigInt(tapeAmountSetIn[i]); } if (amountbn > tapeAmountSum) { throw new Error("Insufficient balance, please add more FT UTXOs"); } if (decimal > 18) { throw new Error("The maximum value for decimal cannot exceed 18"); } var maxAmount = Math.floor(Math.pow(10, 18 - decimal)); if (ft_amount > maxAmount) { throw new Error("When decimal is ".concat(decimal, ", the maximum amount cannot exceed ").concat(maxAmount)); } var { amountHex, changeHex } = FT.buildTapeAmount(amountbn, tapeAmountSetIn, 1); var tx = new tbc.Transaction().from(utxo).from(ftutxos); var amount_satoshis = 0; if (tbc_amount) { amount_satoshis = Math.floor(tbc_amount * Math.pow(10, 6)); } switch (ftutxos.length) { case 1: tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: utxo.satoshis - amount_satoshis - 4000 })); break; case 2: tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: utxo.satoshis - amount_satoshis - 5500 })); break; case 3: tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: utxo.satoshis - amount_satoshis - 7000 })); break; case 4: tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: utxo.satoshis - amount_satoshis - 8500 })); break; case 5: tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm_from), satoshis: utxo.satoshis - amount_satoshis - 10000 })); break; } var codeScript; if (address_to.startsWith("1")) { codeScript = FT.buildFTtransferCode(code, address_to); } else { var hash_to = tbc.crypto.Hash.sha256ripemd160(tbc.crypto.Hash.sha256(tbc.Script.fromASM(MultiSig.getMultiSigLockScript(address_to)).toBuffer())).toString("hex"); codeScript = FT.buildFTtransferCode(code, hash_to); } tx.addOutput(new tbc.Transaction.Output({ script: codeScript, satoshis: 2000 })); var tapeScript = FT.buildFTtransferTape(tape, amountHex); tx.addOutput(new tbc.Transaction.Output({ script: tapeScript, satoshis: 0 })); if (amountbn < tapeAmountSum) { var changeCodeScript = FT.buildFTtransferCode(code, hash_from); tx.addOutput(new tbc.Transaction.Output({ script: changeCodeScript, satoshis: 2000 })); var changeTapeScript = FT.buildFTtransferTape(tape, changeHex); tx.addOutput(new tbc.Transaction.Output({ script: changeTapeScript, satoshis: 0 })); } if (tbc_amount) { tx.addOutput(new tbc.Transaction.Output({ script: tbc.Script.buildPublicKeyHashOut(address_to), satoshis: amount_satoshis })); } //Additional infromation output if (additionalInfo) { var additionalInfoScript = tbc.Script.fromASM('OP_FALSE OP_RETURN'); additionalInfoScript = additionalInfoScript.add(additionalInfo); tx.addOutput(new tbc.Transaction.Output({ script: additionalInfoScript, satoshis: 0 })); } var _loop3 = function _loop3(_i4) { tx.setInputScript({ inputIndex: _i4 + 1 }, tx_source => { var unlockingScript = ft.getFTunlockSwap(privateKey, tx_source, preTXs[_i4], prepreTxDatas[_i4], contractTX, _i4 + 1, ftutxos[_i4].outputIndex); return unlockingScript; }); }; for (var _i4 = 0; _i4 < ftutxos.length; _i4++) { _loop3(_i4); } var txraw = tx.uncheckedSerialize(); return { txraw, amounts: [utxo.satoshis] }; } /** * Sign a multi-signature transaction for transferring FT * @param address_from The address from which the transaction is sent * @param multiSigTxraw The raw serialized transaction string * @param privateKey The private key used to sign the transaction * @returns An array of signatures */ static signMultiSigTransaction_transferFT(multiSig_address, multiSigTxraw, privateKey) { var script_asm = MultiSig.getMultiSigLockScript(multiSig_address); var { txraw, amounts } = multiSigTxraw; var tx = new tbc.Transaction(txraw); tx.inputs[0].output = new tbc.Transaction.Output({ script: tbc.Script.fromASM(script_asm), satoshis: amounts[0] }); var sigs = []; sigs[0] = tx.getSignature(0, privateKey); return sigs; } /** * Sign multi-signature transactions for transferring FT * @param multiSig_address The multi-signature address * @param multiSigTxraws The raw serialized transaction strings * @param privateKey The private key used to sign the transaction * @returns An array of signatures */ static batchSignMultiSigTransaction_transferFT(multiSig_address, multiSigTxraws, privateKey) { var allSigs = []; for (var txIndex = 0; txIndex < multiSigTxraws.length; txIndex++) { var sigs = MultiSig.signMultiSigTransaction_transferFT(multiSig_address, multiSigTxraws[txIndex], privateKey); allSigs.push(sigs); } return allSigs; } /** * Finish a multi-signature transaction for transferring FT * @param txraw The raw serialized transaction string * @param sigs An array of signatures * @param pubkeys The public keys * @returns The raw serialized transaction string */ static finishMultiSigTransaction_transferFT(txraw, sigs, pubKeys) { var multiPubKeys = ""; for (var i = 0; i < pubKeys.length; i++) { multiPubKeys = multiPubKeys + pubKeys[i]; } var tx = new tbc.Transaction(txraw); tx.setInputScript({ inputIndex: 0 }, tx => { var signature = ""; for (var _i5 = 0; _i5 < sigs[0].length; _i5++) { if (_i5 < sigs[0].length - 1) { signature = signature + sigs[0][_i5] + " "; } else { signature = signature + sigs[0][_i5]; } } var unlockingScript = tbc.Script.fromASM("OP_0 ".concat(signature, " ").concat(multiPubKeys)); return unlockingScript; }); return tx.uncheckedSerialize(); } /** * Finish multi-signature transactions for transferring FT * @param txraws The raw serialized transaction strings * @param sigs An array of signatures * @param pubkeys The public keys * @returns The raw serialized transaction strings */ static batchFinishMultiSigTransaction_transferFT(txraws, sigs, pubKeys) { var finishedTxs = []; for (var txIndex = 0; txIndex < txraws.length; txIndex++) { var finishedTx = MultiSig.finishMultiSigTransaction_transferFT(txraws[txIndex], sigs[txIndex], pubKeys); finishedTxs.push(finishedTx); } return finishedTxs; } /** * Get multi-signature address * @param pubkeys Public keys * @param signatureCount Number of signatures * @param publicKeyCount Number of public keys * @returns Multi-signature address */ static getMultiSigAddress(pubKeys, signatureCount, publicKeyCount) { if (signatureCount < 1 || signatureCount > 6) { throw new Error("Invalid signatureCount."); } else if (publicKeyCount < 3 || publicKeyCount > 10) { throw new Error("Invalid publicKeyCount."); } else if (signatureCount > publicKeyCount) { throw new Error("SignatureCount must be less than publicKeyCount."); } var hash = MultiSig.getHash(pubKeys); var prefix = signatureCount << 4 | publicKeyCount & 0x0f; var versionBuffer = Buffer.from([prefix]); var addressBuffer = Buffer.concat([versionBuffer, hash]); var addressHash = tbc.crypto.Hash.sha256sha256(addressBuffer); var checksum = addressHash.subarray(0, 4); var addressWithChecksum = Buffer.concat([addressBuffer, checksum]); return tbc.encoding.Base58.encode(addressWithChecksum); } /** * Get the signature and public key count from a multi-signature address * @param address Multi-signature address * @returns Signature and public key count */ static getSignatureAndPublicKeyCount(address) { var buf = Buffer.from(tbc.encoding.Base58.decode(address)); var prefix = buf[0]; var signatureCount = prefix >> 4 & 0x0f; var publicKeyCount = prefix & 0x0f; return { signatureCount, publicKeyCount }; } /** * Verify a multi-signature address * @param pubkeys Public keys * @param address Multi-signature address * @returns True if the address is valid, false otherwise */ static verifyMultiSigAddress(pubKeys, address) { var hash_from_pubkeys = MultiSig.getHash(pubKeys).toString("hex"); var buf = Buffer.from(tbc.encoding.Base58.decode(address)); var hash_from_address = Buffer.from(buf.subarray(1, 21)).toString("hex"); return hash_from_pubkeys === hash_from_address; } /** * Generate a multi-signature lock script(script_asm) from a multi-signature address * @param address Multi-signature address * @returns Lock script for the multi-signature contract * @throws Error if signature count or public key count is invalid * * The generated lock script performs the following: * 1. Splits the input public keys * 2. Duplicates and concatenates the public keys * 3. Verifies the hash matches the address * 4. Checks that the required number of signatures are valid */ static getMultiSigLockScript(address) { var buf = Buffer.from(tbc.encoding.Base58.decode(address)); var { signatureCount, publicKeyCount } = MultiSig.getSignatureAndPublicKeyCount(address); if (signatureCount < 1 || signatureCount > 6) { throw new Error("Invalid signatureCount."); } else if (publicKeyCount < 3 || publicKeyCount > 10) { throw new Error("Invalid publicKeyCount."); } else if (signatureCount > publicKeyCount) { throw new Error("SignatureCount must be less than publicKeyCount."); } var hash = Buffer.from(buf.subarray(1, 21)).toString("hex"); var lockScriptPrefix = ""; for (var i = 0; i < publicKeyCount - 1; i++) { lockScriptPrefix = lockScriptPrefix + "21 OP_SPLIT "; } for (var _i6 = 0; _i6 < publicKeyCount; _i6++) { lockScriptPrefix = lockScriptPrefix + "OP_".concat(publicKeyCount - 1, " OP_PICK "); } for (var _i7 = 0; _i7 < publicKeyCount - 1; _i7++) { lockScriptPrefix = lockScriptPrefix + "OP_CAT "; } var script_asm = "OP_".concat(signatureCount, " OP_SWAP ") + lockScriptPrefix + "OP_HASH160 ".concat(hash, " OP_EQUALVERIFY OP_").concat(publicKeyCount, " OP_CHECKMULTISIG"); return script_asm; } /** * Get the combine hash from a multi-signature address * @param address Multi-signature address * @returns Combine hash */ static getCombineHash(address) { var combine_hash = tbc.crypto.Hash.sha256ripemd160(tbc.crypto.Hash.sha256(tbc.Script.fromASM(MultiSig.getMultiSigLockScript(address)).toBuffer())).toString("hex") + "01"; return combine_hash; } static getHash(pubKeys) { var multiPubKeys = ""; for (var i = 0; i < pubKeys.length; i++) { multiPubKeys = multiPubKeys + pubKeys[i]; } var buf = Buffer.from(multiPubKeys, "hex"); var hash = tbc.crypto.Hash.sha256ripemd160(buf); return hash; } static buildHoldScript(pubKey) { var publicKeyHash = tbc.crypto.Hash.sha256ripemd160(Buffer.from(pubKey, "hex")).toString("hex"); return new tbc.Script("OP_DUP OP_HASH160" + " 0x14 0x" + publicKeyHash + " OP_EQUALVERIFY OP_CHECKSIG OP_RETURN 0x08 0x6d756c7469736967"); } static buildTapeScript(address, pubKeys) { var data = { address: address, pubkeys: pubKeys }; var dataHex = Buffer.from(JSON.stringify(data)).toString("hex"); return tbc.Script.fromASM("OP_FALSE OP_RETURN " + dataHex + " 4d54617065"); } } module.exports = MultiSig;