bsv-sdk
Version:
bsv sdk
198 lines (197 loc) • 8.99 kB
JavaScript
"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;