UNPKG

bsv-sdk

Version:

bsv sdk

198 lines (197 loc) 8.99 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const scryptlib_1 = require("scryptlib"); const showpay_providers_1 = require("showpay-providers"); const Txutils_1 = require("./utils/Txutils"); const sensible_1 = __importDefault(require("./modules/sensible")); class HdWallet { constructor(mnemonic, network, metasvAuth, feeb = 0.5) { this.hdPrivateKey = scryptlib_1.bsv.Mnemonic.fromString(mnemonic).toHDPrivateKey().deriveChild("m/44'/236'/0'"); this.xpriv = this.hdPrivateKey.xprivkey.toString(); this.xpub = this.hdPrivateKey.xpubkey; this.rootWallet = this.hdPrivateKey.deriveChild(0).deriveChild(0); this.rootWif = this.rootWallet.privateKey.toString(); this.rootAddress = this.rootWallet.privateKey.toAddress().toString(); this.provider = new showpay_providers_1.MetaSVProvider(network, metasvAuth); this.feeb = feeb; this.addressWifMap = new Map(); this.network = network; this.metasvAuth = metasvAuth; } ftMerge(codehash, genesis, sensibleId) { return __awaiter(this, void 0, void 0, function* () { const sensible = new sensible_1.default(this.network, this.feeb, this.rootWif, this.metasvAuth); yield this.transferAll(this.rootAddress, true); yield sensible.ftMerge(codehash, genesis, sensibleId, this.rootWif); }); } getFtMergeTime(codehash, genesis, sensibleId) { return __awaiter(this, void 0, void 0, function* () { const sensible = new sensible_1.default(this.network, this.feeb, this.rootWif, this.metasvAuth); const mergeTime = yield sensible.ftMergeTime(codehash, genesis, sensibleId); return mergeTime; }); } ftMergeOne(codehash, genesis, sensibleId) { return __awaiter(this, void 0, void 0, function* () { const sensible = new sensible_1.default(this.network, this.feeb, this.rootWif, this.metasvAuth); yield this.transferAll(this.rootAddress, true); const res = yield sensible.ftMergeOne(codehash, genesis, sensibleId, this.rootWif); return res; }); } transferAll(receiverAddress, broadcast) { return __awaiter(this, void 0, void 0, function* () { const balanceResp = yield this.provider.getXpubBalance(this.xpub); const xpubBalance = balanceResp.confirmed + balanceResp.unconfirmed; const utxos = yield this.getUtxos(); if (utxos.length == 1 && utxos[0].address == receiverAddress) { return null; } const fee = Math.ceil((utxos.length * 148 + 34 + 10) * this.feeb); const minAmountCanTransfer = 135 + fee; if (xpubBalance < minAmountCanTransfer) { throw new Error("Insufficient BSV Balance"); } const tx = new scryptlib_1.bsv.Transaction(); tx.from(utxos.map((utxo) => ({ txId: utxo.txId, outputIndex: utxo.outputIndex, satoshis: utxo.satoshis, script: scryptlib_1.bsv.Script.buildPublicKeyHashOut(utxo.address).toHex() }))); tx.addOutput(new scryptlib_1.bsv.Transaction.Output({ satoshis: xpubBalance - fee, script: scryptlib_1.bsv.Script.fromAddress(receiverAddress) })); let privateKeys = []; for (let utxo of utxos) { privateKeys.push(this.addressWifMap.get(utxo.address)); } tx.fee(fee); tx.sign(privateKeys); const txid = tx.id; const txHex = tx.serialize(true); const retUtxos = [{ txId: txid, outputIndex: 0, satoshis: xpubBalance - fee, address: receiverAddress }]; if (broadcast) { const resTxid = yield this.provider.broadcast(txHex); if (!resTxid) { throw new Error("broadcast error"); } } return { txid, txHex, utxos: retUtxos }; }); } transfer(receivers, broadcast = true) { return __awaiter(this, void 0, void 0, function* () { const balanceResp = yield this.provider.getXpubBalance(this.xpub); const xpubBalance = balanceResp.confirmed + balanceResp.unconfirmed; let totalTransferAmount = 0; for (let receiver of receivers) { totalTransferAmount += receiver.amount; } let utxos = yield this.getUtxos(); const minTransferFee = Math.ceil((utxos.length * 148 + 34 + 10) * this.feeb); if (xpubBalance < totalTransferAmount + minTransferFee) { throw new Error("Insufficient BSV Balance"); } const utxosAndFee = (0, Txutils_1.getTransferNeedUtxosAndFee)(receivers, utxos, this.feeb); utxos = utxosAndFee.utxos; const fee = utxosAndFee.fee; const tx = new scryptlib_1.bsv.Transaction(); tx.from(utxos.map((utxo) => ({ txId: utxo.txId, outputIndex: utxo.outputIndex, satoshis: utxo.satoshis, script: scryptlib_1.bsv.Script.buildPublicKeyHashOut(utxo.address).toHex() }))); for (let receiver of receivers) { tx.addOutput(new scryptlib_1.bsv.Transaction.Output({ satoshis: receiver.amount, script: scryptlib_1.bsv.Script.fromAddress(receiver.address) })); } let utxoTotalAmount = 0; utxos.forEach((utxo) => { utxoTotalAmount += utxo.satoshis; }); if (utxoTotalAmount - fee - totalTransferAmount >= 135) { tx.addOutput(new scryptlib_1.bsv.Transaction.Output({ satoshis: utxoTotalAmount - fee - totalTransferAmount, script: scryptlib_1.bsv.Script.fromAddress(this.rootAddress) })); } let privateKeys = []; for (let utxo of utxos) { privateKeys.push(this.addressWifMap.get(utxo.address)); } tx.fee(fee); tx.sign(privateKeys); const txid = tx.id; const txHex = tx.serialize(true); let retUtxos = []; for (let i = 0; i < tx.outputs.length; i++) { retUtxos.push({ txId: txid, outputIndex: i, satoshis: tx.outputs[i].satoshis, // @ts-ignore address: scryptlib_1.bsv.Address.fromScript(tx.outputs[i].script).toString() }); } if (broadcast) { const resTxid = yield this.provider.broadcast(txHex); if (!resTxid) { throw new Error("broadcast error"); } } return { txid, txHex, utxos: retUtxos }; }); } getUtxos(limit = 300) { return __awaiter(this, void 0, void 0, function* () { let utxos = []; let gUtxos = yield this.provider.getXpubUtxo(this.xpub, limit); for (let gUtxo of gUtxos) { if (!this.addressWifMap.has(gUtxo.address)) { const privateKey = this.hdPrivateKey.deriveChild(gUtxo.addressType).deriveChild(gUtxo.addressIndex).privateKey; this.addressWifMap.set(gUtxo.address, privateKey); } utxos.push({ txId: gUtxo.txid, outputIndex: gUtxo.txIndex, satoshis: gUtxo.value, address: gUtxo.address, flag: gUtxo.flag }); } return utxos; }); } } exports.default = HdWallet;