send-crypto
Version:
A minimal JavaScript library / wallet for sending crypto assets
148 lines • 17.5 kB
JavaScript
;
var __createBinding = (this && this.__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() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BTCHandler = exports._apiFallbacks = void 0;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const bitcoin = __importStar(require("bitgo-utxo-lib"));
const immutable_1 = require("immutable");
const blockchain_1 = require("../../common/apis/blockchain");
const blockchair_1 = require("../../common/apis/blockchair");
const blockstream_1 = require("../../common/apis/blockstream");
const electrumx_1 = require("../../common/apis/electrumx");
const jsonrpc_1 = require("../../common/apis/jsonrpc");
const sochain_1 = require("../../common/apis/sochain");
const bitgoUtxoLib_1 = require("../../common/libraries/bitgoUtxoLib");
const confirmations_1 = require("../../lib/confirmations");
const promiEvent_1 = require("../../lib/promiEvent");
const retry_1 = require("../../lib/retry");
const utils_1 = require("../../lib/utils");
exports._apiFallbacks = {
fetchUTXO: (testnet, txHash, vOut) => [
...(0, utils_1.shuffleArray)(() => blockstream_1.Blockstream.fetchUTXO(testnet)(txHash, vOut), () => blockchair_1.Blockchair.fetchUTXO(testnet
? blockchair_1.Blockchair.networks.BITCOIN_TESTNET
: blockchair_1.Blockchair.networks.BITCOIN)(txHash, vOut)),
() => blockchain_1.Blockchain.fetchUTXO(testnet
? blockchain_1.BlockchainNetwork.BitcoinTestnet
: blockchain_1.BlockchainNetwork.Bitcoin)(txHash, vOut),
],
fetchUTXOs: (testnet, address, confirmations, scriptHash) => [
...(0, utils_1.shuffleArray)(() => blockstream_1.Blockstream.fetchUTXOs(testnet)(address, confirmations), () => blockchair_1.Blockchair.fetchUTXOs(testnet
? blockchair_1.Blockchair.networks.BITCOIN_TESTNET
: blockchair_1.Blockchair.networks.BITCOIN)(address, confirmations)),
() => sochain_1.Sochain.fetchUTXOs(testnet ? "BTCTEST" : "BTC")(address, confirmations),
() => blockchain_1.Blockchain.fetchUTXOs(testnet
? blockchain_1.BlockchainNetwork.BitcoinTestnet
: blockchain_1.BlockchainNetwork.Bitcoin)(address, confirmations),
() => electrumx_1.ElectrumX.fetchUTXOs("bitcoin", testnet)(address, confirmations, scriptHash),
],
fetchTXs: (testnet, address, confirmations = 0, scriptHash) => [
...(0, utils_1.shuffleArray)(() => blockstream_1.Blockstream.fetchTXs(testnet)(address), () => blockchair_1.Blockchair.fetchTXs(testnet
? blockchair_1.Blockchair.networks.BITCOIN_TESTNET
: blockchair_1.Blockchair.networks.BITCOIN)(address, confirmations), () => sochain_1.Sochain.fetchTXs(testnet ? "BTCTEST" : "BTC")(address, confirmations), () => blockchain_1.Blockchain.fetchUTXOs(testnet
? blockchain_1.BlockchainNetwork.BitcoinTestnet
: blockchain_1.BlockchainNetwork.Bitcoin)(address, confirmations)),
],
broadcastTransaction: (testnet, hex) => [
...(0, utils_1.shuffleArray)(() => blockstream_1.Blockstream.broadcastTransaction(testnet)(hex), () => blockchair_1.Blockchair.broadcastTransaction(testnet
? blockchair_1.Blockchair.networks.BITCOIN_TESTNET
: blockchair_1.Blockchair.networks.BITCOIN)(hex)),
() => sochain_1.Sochain.broadcastTransaction(testnet ? "BTCTEST" : "BTC")(hex),
() => jsonrpc_1.JSONRPC.broadcastTransaction(testnet ? jsonrpc_1.MULTICHAIN_URLS.BTCTEST : jsonrpc_1.MULTICHAIN_URLS.BTC)(hex),
testnet
? undefined
: () => blockchain_1.Blockchain.broadcastTransaction(blockchain_1.BlockchainNetwork.Bitcoin)(hex),
],
};
class BTCHandler {
constructor(privateKey, network) {
this.decimals = 8;
// Returns whether or not this can handle the asset
this.handlesAsset = (asset) => typeof asset === "string" &&
["BTC", "BITCOIN"].indexOf(asset.toUpperCase()) !== -1;
this.address = async (asset, options) => this.privateKey.getAddress();
// Balance
this.getBalance = async (asset, options) => (await this.getBalanceInSats(asset, options)).dividedBy(new bignumber_js_1.default(10).exponentiatedBy(this.decimals));
this.getBalanceInSats = async (asset, options) => {
const utxos = await BTCHandler.getUTXOs(this.testnet, Object.assign(Object.assign({}, options), { address: (options && options.address) || (await this.address(asset)) }));
return utxos.reduce((sum, utxo) => sum.plus(utxo.amount), new bignumber_js_1.default(0));
};
// Transfer
this.send = (to, value, asset, options) => this.sendSats(to, value.times(new bignumber_js_1.default(10).exponentiatedBy(this.decimals)), asset, options);
this.sendSats = (to, valueIn, asset, options) => {
const promiEvent = (0, promiEvent_1.newPromiEvent)();
let txHash;
let errored;
(async () => {
const fromAddress = await this.address(asset);
const changeAddress = fromAddress;
const utxos = (0, immutable_1.List)(await BTCHandler.getUTXOs(this.testnet, Object.assign(Object.assign({}, options), { address: fromAddress })))
.sortBy((utxo) => utxo.amount)
.reverse()
.toArray();
const built = await bitgoUtxoLib_1.BitgoUTXOLib.buildUTXO(this.testnet
? bitcoin.networks.testnet
: bitcoin.networks.bitcoin, this.privateKey, changeAddress, to, valueIn, utxos, options);
txHash = await (0, retry_1.retryNTimes)(() => (0, retry_1.fallback)(exports._apiFallbacks.broadcastTransaction(this.testnet, built.toHex())), 3);
promiEvent.emit("transactionHash", txHash);
promiEvent.resolve(txHash);
})().catch((error) => {
errored = true;
promiEvent.reject(error);
});
(0, confirmations_1.subscribeToConfirmations)(promiEvent, () => errored, async () => (txHash ? this._getConfirmations(txHash) : 0));
return promiEvent;
};
this._getConfirmations = async (txHash) => (await (0, retry_1.fallback)(
// Fetch confirmations for first output of transaction.
exports._apiFallbacks.fetchUTXO(this.testnet, txHash, 0))).confirmations;
this.testnet = network !== "mainnet";
this.privateKey = bitgoUtxoLib_1.BitgoUTXOLib.loadPrivateKey(this.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin, privateKey);
}
}
exports.BTCHandler = BTCHandler;
_a = BTCHandler;
BTCHandler.getUTXOs = async (testnet, options) => {
const confirmations = options && options.confirmations !== undefined
? options.confirmations
: 0;
const endpoints = exports._apiFallbacks.fetchUTXOs(testnet, options.address, confirmations, options.scriptHash);
return (0, retry_1.fallback)(endpoints);
};
BTCHandler.getUTXO = async (testnet, txHash, vOut) => {
const endpoints = exports._apiFallbacks.fetchUTXO(testnet, txHash, vOut);
return (0, retry_1.fallback)(endpoints);
};
BTCHandler.getTransactions = async (testnet, options) => {
const confirmations = options && options.confirmations !== undefined
? options.confirmations
: 0;
const endpoints = exports._apiFallbacks.fetchTXs(testnet, options.address, confirmations, options.scriptHash);
return (0, retry_1.fallback)(endpoints);
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQlRDSGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9oYW5kbGVycy9CVEMvQlRDSGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxnRUFBcUM7QUFDckMsd0RBQTBDO0FBQzFDLHlDQUFpQztBQUVqQyw2REFBNkU7QUFDN0UsNkRBQTBEO0FBQzFELCtEQUE0RDtBQUM1RCwyREFBd0Q7QUFDeEQsdURBQXFFO0FBQ3JFLHVEQUFvRDtBQUNwRCxzRUFBbUU7QUFDbkUsMkRBQW1FO0FBQ25FLHFEQUFpRTtBQUNqRSwyQ0FBd0Q7QUFDeEQsMkNBQStDO0FBY2xDLFFBQUEsYUFBYSxHQUFHO0lBQ3pCLFNBQVMsRUFBRSxDQUFDLE9BQWdCLEVBQUUsTUFBYyxFQUFFLElBQVksRUFBRSxFQUFFLENBQUM7UUFDM0QsR0FBRyxJQUFBLG9CQUFZLEVBQ1gsR0FBRyxFQUFFLENBQUMseUJBQVcsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUNsRCxHQUFHLEVBQUUsQ0FDRCx1QkFBVSxDQUFDLFNBQVMsQ0FDaEIsT0FBTztZQUNILENBQUMsQ0FBQyx1QkFBVSxDQUFDLFFBQVEsQ0FBQyxlQUFlO1lBQ3JDLENBQUMsQ0FBQyx1QkFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQ3BDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUN0QjtRQUNELEdBQUcsRUFBRSxDQUNELHVCQUFVLENBQUMsU0FBUyxDQUNoQixPQUFPO1lBQ0gsQ0FBQyxDQUFDLDhCQUFpQixDQUFDLGNBQWM7WUFDbEMsQ0FBQyxDQUFDLDhCQUFpQixDQUFDLE9BQU8sQ0FDbEMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDO0tBQ3RCO0lBRUQsVUFBVSxFQUFFLENBQ1IsT0FBZ0IsRUFDaEIsT0FBZSxFQUNmLGFBQXFCLEVBQ3JCLFVBQW1C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