send-crypto
Version:
A minimal JavaScript library / wallet for sending crypto assets
148 lines • 18 kB
JavaScript
import BigNumber from "bignumber.js";
import * as bitcoin from "bitgo-utxo-lib";
import { List } from "immutable";
import { Insight } from "../../common/apis/insight";
import { JSONRPC, MULTICHAIN_URLS } from "../../common/apis/jsonrpc";
import { Sochain } from "../../common/apis/sochain";
import { BitgoUTXOLib } from "../../common/libraries/bitgoUtxoLib";
import { subscribeToConfirmations } from "../../lib/confirmations";
import { newPromiEvent } from "../../lib/promiEvent";
import { fallback, retryNTimes } from "../../lib/retry";
import { shuffleArray } from "../../lib/utils";
var InsightEndpoints;
(function (InsightEndpoints) {
// Testnet
InsightEndpoints["TestnetZCash"] = "https://explorer.testnet.z.cash/api/";
// Mainnet
InsightEndpoints["ZCash"] = "https://explorer.z.cash/api/";
InsightEndpoints["ZecBlockExplorer"] = "https://zecblockexplorer.com/api/";
InsightEndpoints["ZecChain"] = "https://zechain.net/api/v1/";
InsightEndpoints["BlockExplorer"] = "https://zcash.blockexplorer.com/api/";
})(InsightEndpoints || (InsightEndpoints = {}));
export const _apiFallbacks = {
fetchUTXO: (testnet, txHash, vOut) => testnet
? [
...shuffleArray(() => Insight.fetchUTXO(InsightEndpoints.TestnetZCash)(txHash, vOut)),
() => Sochain.fetchUTXO("ZECTEST")(txHash, vOut),
]
: [
...shuffleArray(() => Insight.fetchUTXO(InsightEndpoints.ZCash)(txHash, vOut), () => Insight.fetchUTXO(InsightEndpoints.ZecBlockExplorer)(txHash, vOut)),
() => Insight.fetchUTXO(InsightEndpoints.ZecChain)(txHash, vOut),
() => Insight.fetchUTXO(InsightEndpoints.BlockExplorer)(txHash, vOut),
],
fetchUTXOs: (testnet, address, confirmations) => testnet
? [
...shuffleArray(() => Insight.fetchUTXOs(InsightEndpoints.TestnetZCash)(address, confirmations)),
() => Sochain.fetchUTXOs("ZECTEST")(address, confirmations),
]
: [
...shuffleArray(() => Insight.fetchUTXOs(InsightEndpoints.ZCash)(address, confirmations), () => Insight.fetchUTXOs(InsightEndpoints.ZecBlockExplorer)(address, confirmations)),
() => Sochain.fetchUTXOs("ZEC")(address, confirmations),
() => Insight.fetchUTXOs(InsightEndpoints.ZecChain)(address, confirmations),
() => Insight.fetchUTXOs(InsightEndpoints.BlockExplorer)(address, confirmations),
],
fetchTXs: (testnet, address, confirmations = 0) => testnet
? [
...shuffleArray(() => Insight.fetchTXs(InsightEndpoints.TestnetZCash)(address, confirmations)),
() => Sochain.fetchTXs("ZECTEST")(address, confirmations),
]
: [
...shuffleArray(() => Insight.fetchTXs(InsightEndpoints.ZCash)(address, confirmations), () => Insight.fetchTXs(InsightEndpoints.ZecBlockExplorer)(address, confirmations)),
() => Sochain.fetchTXs("ZEC")(address, confirmations),
() => Insight.fetchTXs(InsightEndpoints.ZecChain)(address, confirmations),
() => Insight.fetchTXs(InsightEndpoints.BlockExplorer)(address, confirmations),
],
broadcastTransaction: (testnet, hex) => testnet
? [
() => JSONRPC.broadcastTransaction(MULTICHAIN_URLS.ZECTEST)(hex),
() => Insight.broadcastTransaction(InsightEndpoints.TestnetZCash)(hex),
() => Sochain.broadcastTransaction("ZECTEST")(hex),
]
: [
...shuffleArray(() => Insight.broadcastTransaction(InsightEndpoints.ZCash)(hex), () => Insight.broadcastTransaction(InsightEndpoints.ZecBlockExplorer)(hex), () => Sochain.broadcastTransaction("ZEC")(hex)),
() => Insight.broadcastTransaction(InsightEndpoints.ZecChain)(hex),
() => Insight.broadcastTransaction(InsightEndpoints.BlockExplorer)(hex),
() => JSONRPC.broadcastTransaction(MULTICHAIN_URLS.ZEC)(hex),
],
};
export class ZECHandler {
privateKey;
testnet;
decimals = 8;
static getUTXOs = async (testnet, options) => {
const confirmations = options && options.confirmations !== undefined
? options.confirmations
: 0;
return fallback(_apiFallbacks.fetchUTXOs(testnet, options.address, confirmations));
};
static getUTXO = async (testnet, txHash, vOut) => {
const endpoints = _apiFallbacks.fetchUTXO(testnet, txHash, vOut);
return fallback(endpoints);
};
static getTransactions = async (testnet, options) => {
const confirmations = options && options.confirmations !== undefined
? options.confirmations
: 0;
const endpoints = _apiFallbacks.fetchTXs(testnet, options.address, confirmations);
return fallback(endpoints);
};
constructor(privateKey, network) {
this.testnet = network !== "mainnet";
this.privateKey = BitgoUTXOLib.loadPrivateKey(this.testnet ? bitcoin.networks.zcashTest : bitcoin.networks.zcash, privateKey);
}
// Returns whether or not this can handle the asset
handlesAsset = (asset) => typeof asset === "string" &&
["ZEC", "ZCASH"].indexOf(asset.toUpperCase()) !== -1;
address = async (asset, options) => this.privateKey.getAddress();
// Balance
getBalance = async (asset, options) => (await this.getBalanceInSats(asset, options)).dividedBy(new BigNumber(10).exponentiatedBy(this.decimals));
getBalanceInSats = async (asset, options) => {
const utxos = await ZECHandler.getUTXOs(this.testnet, {
...options,
address: (options && options.address) || (await this.address(asset)),
});
return utxos.reduce((sum, utxo) => sum.plus(utxo.amount), new BigNumber(0));
};
// Transfer
send = (to, value, asset, options) => this.sendSats(to, value.times(new BigNumber(10).exponentiatedBy(this.decimals)), asset, options);
sendSats = (to, valueIn, asset, options) => {
const promiEvent = newPromiEvent();
let txHash;
let errored;
(async () => {
const fromAddress = await this.address(asset);
const changeAddress = fromAddress;
const utxos = List(await ZECHandler.getUTXOs(this.testnet, {
...options,
address: fromAddress,
}))
.sortBy((utxo) => utxo.amount)
.reverse()
.toArray();
if (this.testnet) {
// tslint:disable-next-line: no-object-mutation
bitcoin.networks.zcashTest.consensusBranchId["4"] = 37519621;
}
const built = await BitgoUTXOLib.buildUTXO(this.testnet
? bitcoin.networks.zcashTest
: bitcoin.networks.zcash, this.privateKey, changeAddress, to, valueIn, utxos, {
...options,
version: 4,
versionGroupID: 0x892f2085,
consensusBranchId: 0x37519621,
});
txHash = await retryNTimes(() => fallback(_apiFallbacks.broadcastTransaction(this.testnet, built.toHex())), 3);
promiEvent.emit("transactionHash", txHash);
promiEvent.resolve(txHash);
})().catch((error) => {
errored = true;
promiEvent.reject(error);
});
subscribeToConfirmations(promiEvent, () => errored, async () => (txHash ? this._getConfirmations(txHash) : 0));
return promiEvent;
};
_getConfirmations = async (txHash) => (await fallback(
// Fetch confirmations for first output of transaction.
_apiFallbacks.fetchUTXO(this.testnet, txHash, 0))).confirmations;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWkVDSGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9oYW5kbGVycy9aRUMvWkVDSGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFNBQVMsTUFBTSxjQUFjLENBQUM7QUFDckMsT0FBTyxLQUFLLE9BQU8sTUFBTSxnQkFBZ0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRWpDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDbkUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxFQUFFLGFBQWEsRUFBYyxNQUFNLHNCQUFzQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBYy9DLElBQUssZ0JBUUo7QUFSRCxXQUFLLGdCQUFnQjtJQUNqQixVQUFVO0lBQ1YseUVBQXFELENBQUE7SUFDckQsVUFBVTtJQUNWLDBEQUFzQyxDQUFBO0lBQ3RDLDBFQUFzRCxDQUFBO0lBQ3RELDREQUF3QyxDQUFBO0lBQ3hDLDBFQUFzRCxDQUFBO0FBQzFELENBQUMsRUFSSSxnQkFBZ0IsS0FBaEIsZ0JBQWdCLFFBUXBCO0FBRUQsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHO0lBQ3pCLFNBQVMsRUFBRSxDQUFDLE9BQWdCLEVBQUUsTUFBYyxFQUFFLElBQVksRUFBRSxFQUFFLENBQzFELE9BQU87UUFDSCxDQUFD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