bsv-sdk
Version:
bsv sdk
432 lines (349 loc) • 15.1 kB
JavaScript
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
import _regeneratorRuntime from "@babel/runtime/regenerator";
import { bsv } from "scryptlib";
import { MetaSVProvider } from "showpay-providers";
import { getTransferNeedUtxosAndFee } from "./utils/Txutils";
import Sensible from "./modules/sensible";
var HdWallet = /*#__PURE__*/function () {
function HdWallet(mnemonic, network, metasvAuth, feeb) {
if (feeb === void 0) {
feeb = 0.5;
}
this.hdPrivateKey = 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 MetaSVProvider(network, metasvAuth);
this.feeb = feeb;
this.addressWifMap = new Map();
this.network = network;
this.metasvAuth = metasvAuth;
}
var _proto = HdWallet.prototype;
_proto.ftMerge = /*#__PURE__*/function () {
var _ftMerge = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(codehash, genesis, sensibleId) {
var sensible;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
sensible = new Sensible(this.network, this.feeb, this.rootWif, this.metasvAuth);
_context.next = 3;
return this.transferAll(this.rootAddress, true);
case 3:
_context.next = 5;
return sensible.ftMerge(codehash, genesis, sensibleId, this.rootWif);
case 5:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function ftMerge(_x, _x2, _x3) {
return _ftMerge.apply(this, arguments);
}
return ftMerge;
}();
_proto.getFtMergeTime = /*#__PURE__*/function () {
var _getFtMergeTime = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(codehash, genesis, sensibleId) {
var sensible, mergeTime;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
sensible = new Sensible(this.network, this.feeb, this.rootWif, this.metasvAuth);
_context2.next = 3;
return sensible.ftMergeTime(codehash, genesis, sensibleId);
case 3:
mergeTime = _context2.sent;
return _context2.abrupt("return", mergeTime);
case 5:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
function getFtMergeTime(_x4, _x5, _x6) {
return _getFtMergeTime.apply(this, arguments);
}
return getFtMergeTime;
}();
_proto.ftMergeOne = /*#__PURE__*/function () {
var _ftMergeOne = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(codehash, genesis, sensibleId) {
var sensible, res;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
sensible = new Sensible(this.network, this.feeb, this.rootWif, this.metasvAuth);
_context3.next = 3;
return this.transferAll(this.rootAddress, true);
case 3:
_context3.next = 5;
return sensible.ftMergeOne(codehash, genesis, sensibleId, this.rootWif);
case 5:
res = _context3.sent;
return _context3.abrupt("return", res);
case 7:
case "end":
return _context3.stop();
}
}
}, _callee3, this);
}));
function ftMergeOne(_x7, _x8, _x9) {
return _ftMergeOne.apply(this, arguments);
}
return ftMergeOne;
}();
_proto.transferAll = /*#__PURE__*/function () {
var _transferAll = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(receiverAddress, broadcast) {
var balanceResp, xpubBalance, utxos, fee, minAmountCanTransfer, tx, privateKeys, _iterator, _step, utxo, txid, txHex, retUtxos, resTxid;
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return this.provider.getXpubBalance(this.xpub);
case 2:
balanceResp = _context4.sent;
xpubBalance = balanceResp.confirmed + balanceResp.unconfirmed;
_context4.next = 6;
return this.getUtxos();
case 6:
utxos = _context4.sent;
if (!(utxos.length == 1 && utxos[0].address == receiverAddress)) {
_context4.next = 9;
break;
}
return _context4.abrupt("return", null);
case 9:
fee = Math.ceil((utxos.length * 148 + 34 + 10) * this.feeb);
minAmountCanTransfer = 135 + fee;
if (!(xpubBalance < minAmountCanTransfer)) {
_context4.next = 13;
break;
}
throw new Error("Insufficient BSV Balance");
case 13:
tx = new bsv.Transaction();
tx.from(utxos.map(function (utxo) {
return {
txId: utxo.txId,
outputIndex: utxo.outputIndex,
satoshis: utxo.satoshis,
script: bsv.Script.buildPublicKeyHashOut(utxo.address).toHex()
};
}));
tx.addOutput(new bsv.Transaction.Output({
satoshis: xpubBalance - fee,
script: bsv.Script.fromAddress(receiverAddress)
}));
privateKeys = [];
for (_iterator = _createForOfIteratorHelperLoose(utxos); !(_step = _iterator()).done;) {
utxo = _step.value;
privateKeys.push(this.addressWifMap.get(utxo.address));
}
tx.fee(fee);
tx.sign(privateKeys);
txid = tx.id;
txHex = tx.serialize(true);
retUtxos = [{
txId: txid,
outputIndex: 0,
satoshis: xpubBalance - fee,
address: receiverAddress
}];
if (!broadcast) {
_context4.next = 29;
break;
}
_context4.next = 26;
return this.provider.broadcast(txHex);
case 26:
resTxid = _context4.sent;
if (resTxid) {
_context4.next = 29;
break;
}
throw new Error("broadcast error");
case 29:
return _context4.abrupt("return", {
txid: txid,
txHex: txHex,
utxos: retUtxos
});
case 30:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
}));
function transferAll(_x10, _x11) {
return _transferAll.apply(this, arguments);
}
return transferAll;
}();
_proto.transfer = /*#__PURE__*/function () {
var _transfer = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(receivers, broadcast) {
var balanceResp, xpubBalance, totalTransferAmount, _iterator2, _step2, receiver, utxos, minTransferFee, utxosAndFee, fee, tx, _iterator3, _step3, _receiver, utxoTotalAmount, privateKeys, _iterator4, _step4, utxo, txid, txHex, retUtxos, i, resTxid;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
if (broadcast === void 0) {
broadcast = true;
}
_context5.next = 3;
return this.provider.getXpubBalance(this.xpub);
case 3:
balanceResp = _context5.sent;
xpubBalance = balanceResp.confirmed + balanceResp.unconfirmed;
totalTransferAmount = 0;
for (_iterator2 = _createForOfIteratorHelperLoose(receivers); !(_step2 = _iterator2()).done;) {
receiver = _step2.value;
totalTransferAmount += receiver.amount;
}
_context5.next = 9;
return this.getUtxos();
case 9:
utxos = _context5.sent;
minTransferFee = Math.ceil((utxos.length * 148 + 34 + 10) * this.feeb);
if (!(xpubBalance < totalTransferAmount + minTransferFee)) {
_context5.next = 13;
break;
}
throw new Error("Insufficient BSV Balance");
case 13:
utxosAndFee = getTransferNeedUtxosAndFee(receivers, utxos, this.feeb);
utxos = utxosAndFee.utxos;
fee = utxosAndFee.fee;
tx = new bsv.Transaction();
tx.from(utxos.map(function (utxo) {
return {
txId: utxo.txId,
outputIndex: utxo.outputIndex,
satoshis: utxo.satoshis,
script: bsv.Script.buildPublicKeyHashOut(utxo.address).toHex()
};
}));
for (_iterator3 = _createForOfIteratorHelperLoose(receivers); !(_step3 = _iterator3()).done;) {
_receiver = _step3.value;
tx.addOutput(new bsv.Transaction.Output({
satoshis: _receiver.amount,
script: bsv.Script.fromAddress(_receiver.address)
}));
}
utxoTotalAmount = 0;
utxos.forEach(function (utxo) {
utxoTotalAmount += utxo.satoshis;
});
if (utxoTotalAmount - fee - totalTransferAmount >= 135) {
tx.addOutput(new bsv.Transaction.Output({
satoshis: utxoTotalAmount - fee - totalTransferAmount,
script: bsv.Script.fromAddress(this.rootAddress)
}));
}
privateKeys = [];
for (_iterator4 = _createForOfIteratorHelperLoose(utxos); !(_step4 = _iterator4()).done;) {
utxo = _step4.value;
privateKeys.push(this.addressWifMap.get(utxo.address));
}
tx.fee(fee);
tx.sign(privateKeys);
txid = tx.id;
txHex = tx.serialize(true);
retUtxos = [];
for (i = 0; i < tx.outputs.length; i++) {
retUtxos.push({
txId: txid,
outputIndex: i,
satoshis: tx.outputs[i].satoshis,
// @ts-ignore
address: bsv.Address.fromScript(tx.outputs[i].script).toString()
});
}
if (!broadcast) {
_context5.next = 36;
break;
}
_context5.next = 33;
return this.provider.broadcast(txHex);
case 33:
resTxid = _context5.sent;
if (resTxid) {
_context5.next = 36;
break;
}
throw new Error("broadcast error");
case 36:
return _context5.abrupt("return", {
txid: txid,
txHex: txHex,
utxos: retUtxos
});
case 37:
case "end":
return _context5.stop();
}
}
}, _callee5, this);
}));
function transfer(_x12, _x13) {
return _transfer.apply(this, arguments);
}
return transfer;
}();
_proto.getUtxos = /*#__PURE__*/function () {
var _getUtxos = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(limit) {
var utxos, gUtxos, _iterator5, _step5, gUtxo, privateKey;
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
if (limit === void 0) {
limit = 300;
}
utxos = [];
_context6.next = 4;
return this.provider.getXpubUtxo(this.xpub, limit);
case 4:
gUtxos = _context6.sent;
for (_iterator5 = _createForOfIteratorHelperLoose(gUtxos); !(_step5 = _iterator5()).done;) {
gUtxo = _step5.value;
if (!this.addressWifMap.has(gUtxo.address)) {
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 _context6.abrupt("return", utxos);
case 7:
case "end":
return _context6.stop();
}
}
}, _callee6, this);
}));
function getUtxos(_x14) {
return _getUtxos.apply(this, arguments);
}
return getUtxos;
}();
return HdWallet;
}();
export { HdWallet as default };