@xchainjs/xchain-bitcoincash
Version:
Custom bitcoincash client and utilities used by XChainJS clients
1,995 lines (1,817 loc) • 59.8 kB
JavaScript
'use strict';
var bitcash = require('@psf/bitcoincashjs-lib');
var xchainClient = require('@xchainjs/xchain-client');
var xchainCrypto = require('@xchainjs/xchain-crypto');
var xchainUtxo = require('@xchainjs/xchain-utxo');
var xchainUtil = require('@xchainjs/xchain-util');
var xchainUtxoProviders = require('@xchainjs/xchain-utxo-providers');
var bchaddr = require('bchaddrjs');
var require$$0 = require('buffer');
var AppBtc = require('@ledgerhq/hw-app-btc');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var bitcash__namespace = /*#__PURE__*/_interopNamespace(bitcash);
var bchaddr__namespace = /*#__PURE__*/_interopNamespace(bchaddr);
var require$$0__default = /*#__PURE__*/_interopDefault(require$$0);
var AppBtc__default = /*#__PURE__*/_interopDefault(AppBtc);
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
function __awaiter(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());
});
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var utils;
var hasRequiredUtils;
function requireUtils () {
if (hasRequiredUtils) return utils;
hasRequiredUtils = 1;
// baseline estimates, used to improve performance
var TX_EMPTY_SIZE = 4 + 1 + 1 + 4;
var TX_INPUT_BASE = 32 + 4 + 1 + 4;
var TX_INPUT_PUBKEYHASH = 107;
var TX_OUTPUT_BASE = 8 + 1;
var TX_OUTPUT_PUBKEYHASH = 25;
function inputBytes (input) {
return TX_INPUT_BASE + (input.script ? input.script.length : TX_INPUT_PUBKEYHASH)
}
function outputBytes (output) {
return TX_OUTPUT_BASE + (output.script ? output.script.length : TX_OUTPUT_PUBKEYHASH)
}
function dustThreshold (output, feeRate) {
/* ... classify the output for input estimate */
return inputBytes({}) * feeRate
}
function transactionBytes (inputs, outputs) {
return TX_EMPTY_SIZE +
inputs.reduce(function (a, x) { return a + inputBytes(x) }, 0) +
outputs.reduce(function (a, x) { return a + outputBytes(x) }, 0)
}
function uintOrNaN (v) {
if (typeof v !== 'number') return NaN
if (!isFinite(v)) return NaN
if (Math.floor(v) !== v) return NaN
if (v < 0) return NaN
return v
}
function sumForgiving (range) {
return range.reduce(function (a, x) { return a + (isFinite(x.value) ? x.value : 0) }, 0)
}
function sumOrNaN (range) {
return range.reduce(function (a, x) { return a + uintOrNaN(x.value) }, 0)
}
var BLANK_OUTPUT = outputBytes({});
function finalize (inputs, outputs, feeRate) {
var bytesAccum = transactionBytes(inputs, outputs);
var feeAfterExtraOutput = feeRate * (bytesAccum + BLANK_OUTPUT);
var remainderAfterExtraOutput = sumOrNaN(inputs) - (sumOrNaN(outputs) + feeAfterExtraOutput);
// is it worth a change output?
if (remainderAfterExtraOutput > dustThreshold({}, feeRate)) {
outputs = outputs.concat({ value: remainderAfterExtraOutput });
}
var fee = sumOrNaN(inputs) - sumOrNaN(outputs);
if (!isFinite(fee)) return { fee: feeRate * bytesAccum }
return {
inputs: inputs,
outputs: outputs,
fee: fee
}
}
utils = {
dustThreshold: dustThreshold,
finalize: finalize,
inputBytes: inputBytes,
outputBytes: outputBytes,
sumOrNaN: sumOrNaN,
sumForgiving: sumForgiving,
transactionBytes: transactionBytes,
uintOrNaN: uintOrNaN
};
return utils;
}
var accumulative$1;
var hasRequiredAccumulative;
function requireAccumulative () {
if (hasRequiredAccumulative) return accumulative$1;
hasRequiredAccumulative = 1;
var utils = requireUtils();
// add inputs until we reach or surpass the target value (or deplete)
// worst-case: O(n)
accumulative$1 = function accumulative (utxos, outputs, feeRate) {
if (!isFinite(utils.uintOrNaN(feeRate))) return {}
var bytesAccum = utils.transactionBytes([], outputs);
var inAccum = 0;
var inputs = [];
var outAccum = utils.sumOrNaN(outputs);
for (var i = 0; i < utxos.length; ++i) {
var utxo = utxos[i];
var utxoBytes = utils.inputBytes(utxo);
var utxoFee = feeRate * utxoBytes;
var utxoValue = utils.uintOrNaN(utxo.value);
// skip detrimental input
if (utxoFee > utxo.value) {
if (i === utxos.length - 1) return { fee: feeRate * (bytesAccum + utxoBytes) }
continue
}
bytesAccum += utxoBytes;
inAccum += utxoValue;
inputs.push(utxo);
var fee = feeRate * bytesAccum;
// go again?
if (inAccum < outAccum + fee) continue
return utils.finalize(inputs, outputs, feeRate)
}
return { fee: feeRate * bytesAccum }
};
return accumulative$1;
}
var accumulativeExports = requireAccumulative();
var accumulative = /*@__PURE__*/getDefaultExportFromCjs(accumulativeExports);
/**
* Lower bound for transaction fee rate.
*/
const LOWER_FEE_BOUND = 1;
/**
* Upper bound for transaction fee rate.
*/
const UPPER_FEE_BOUND = 500;
/**
* Decimal places for Bitcoin Cash.
*/
const BCH_DECIMAL = 8;
/**
* Chain identifier for Bitcoin Cash.
*/
const BCHChain = 'BCH';
/**
* Base "chain" asset on Bitcoin Cash mainnet.
* Defined according to Thorchain's asset structure.
* @see https://gitlab.com/thorchain/thornode/-/blob/master/common/asset.go#L12-24
*/
const AssetBCH = { chain: BCHChain, symbol: 'BCH', ticker: 'BCH', type: xchainUtil.AssetType.NATIVE };
/**
* Explorer provider URLs for Bitcoin Cash.
*/
const BCH_MAINNET_EXPLORER = new xchainClient.ExplorerProvider('https://www.blockchain.com/bch/', 'https://www.blockchain.com/bch/address/%%ADDRESS%%', 'https://www.blockchain.com/bch/tx/%%TX_ID%%');
const BCH_TESTNET_EXPLORER = new xchainClient.ExplorerProvider('https://www.blockchain.com/bch-testnet/', 'https://www.blockchain.com/bch-testnet/address/%%ADDRESS%%', 'https://www.blockchain.com/bch-testnet/tx/%%TX_ID%%');
const explorerProviders = {
[xchainClient.Network.Testnet]: BCH_TESTNET_EXPLORER,
[xchainClient.Network.Stagenet]: BCH_MAINNET_EXPLORER,
[xchainClient.Network.Mainnet]: BCH_MAINNET_EXPLORER,
};
/**
* Haskoin data providers for Bitcoin Cash.
*/
const testnetHaskoinProvider = new xchainUtxoProviders.HaskoinProvider('https://api.haskoin.com', BCHChain, AssetBCH, 8, xchainUtxoProviders.HaskoinNetwork.BCHTEST);
const mainnetHaskoinProvider = new xchainUtxoProviders.HaskoinProvider('https://haskoin.ninerealms.com', BCHChain, AssetBCH, 8, xchainUtxoProviders.HaskoinNetwork.BCH);
const HaskoinDataProviders = {
[xchainClient.Network.Testnet]: testnetHaskoinProvider,
[xchainClient.Network.Stagenet]: mainnetHaskoinProvider,
[xchainClient.Network.Mainnet]: mainnetHaskoinProvider,
};
/**
* Bitgo data providers for Bitcoin Cash.
*/
const mainnetBitgoProvider = new xchainUtxoProviders.BitgoProvider({
baseUrl: 'https://app.bitgo.com',
chain: BCHChain,
});
const BitgoProviders = {
[xchainClient.Network.Testnet]: undefined,
[xchainClient.Network.Stagenet]: mainnetBitgoProvider,
[xchainClient.Network.Mainnet]: mainnetBitgoProvider,
};
var safeBuffer = {exports: {}};
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
var hasRequiredSafeBuffer;
function requireSafeBuffer () {
if (hasRequiredSafeBuffer) return safeBuffer.exports;
hasRequiredSafeBuffer = 1;
(function (module, exports) {
/* eslint-disable node/no-deprecated-api */
var buffer = require$$0__default.default;
var Buffer = buffer.Buffer;
// alternative to using Object.keys for old browsers
function copyProps (src, dst) {
for (var key in src) {
dst[key] = src[key];
}
}
if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
module.exports = buffer;
} else {
// Copy properties from require('buffer')
copyProps(buffer, exports);
exports.Buffer = SafeBuffer;
}
function SafeBuffer (arg, encodingOrOffset, length) {
return Buffer(arg, encodingOrOffset, length)
}
SafeBuffer.prototype = Object.create(Buffer.prototype);
// Copy static methods from Buffer
copyProps(Buffer, SafeBuffer);
SafeBuffer.from = function (arg, encodingOrOffset, length) {
if (typeof arg === 'number') {
throw new TypeError('Argument must not be a number')
}
return Buffer(arg, encodingOrOffset, length)
};
SafeBuffer.alloc = function (size, fill, encoding) {
if (typeof size !== 'number') {
throw new TypeError('Argument must be a number')
}
var buf = Buffer(size);
if (fill !== undefined) {
if (typeof encoding === 'string') {
buf.fill(fill, encoding);
} else {
buf.fill(fill);
}
} else {
buf.fill(0);
}
return buf
};
SafeBuffer.allocUnsafe = function (size) {
if (typeof size !== 'number') {
throw new TypeError('Argument must be a number')
}
return Buffer(size)
};
SafeBuffer.allocUnsafeSlow = function (size) {
if (typeof size !== 'number') {
throw new TypeError('Argument must be a number')
}
return buffer.SlowBuffer(size)
};
} (safeBuffer, safeBuffer.exports));
return safeBuffer.exports;
}
/*
info from:
https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/src/chainparams.cpp
*/
var bch;
var hasRequiredBch;
function requireBch () {
if (hasRequiredBch) return bch;
hasRequiredBch = 1;
var common = {
name: 'BitcoinCash',
per1: 1e8,
unit: 'BCH'
};
var main = Object.assign({}, {
hashGenesisBlock: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
// nDefaultPort
port: 8333,
portRpc: 8332,
protocol: {
// pchMessageStart
magic: 0xe8f3e1e3 // careful, sent over wire as little endian
},
// vSeeds
seedsDns: [
'seed.bitcoinabc.org',
'seed-abc.bitcoinforks.org',
'btccash-seeder.bitcoinunlimited.info',
'seed.bitprim.org',
'seed.deadalnix.me',
'seeder.criptolayer.net'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 145,
private: 0x80,
public: 0x00,
scripthash: 0x05
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943',
port: 18333,
portRpc: 18332,
protocol: {
magic: 0xf4f3e5f4
},
seedsDns: [
'testnet-seed.bitcoinabc.org',
'testnet-seed-abc.bitcoinforks.org',
'testnet-seed.bitprim.org',
'testnet-seed.deadalnix.me',
'testnet-seeder.criptolayer.net'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
var regtest = Object.assign({}, {
hashGenesisBlock: '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
port: 18444,
portRpc: 18332,
protocol: {
magic: 0xfabfb5da
},
seedsDns: [],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
bch = {
main: main,
test: test,
regtest: regtest
};
return bch;
}
/*
info from:
https://github.com/rat4/blackcoin/blob/master/src/chainparams.cpp
*/
var blk;
var hasRequiredBlk;
function requireBlk () {
if (hasRequiredBlk) return blk;
hasRequiredBlk = 1;
var common = {
name: 'BlackCoin',
per1: 1e8,
unit: 'BLK'
};
var main = Object.assign({}, {
hashGenesisBlock: '000001faef25dec4fbcf906e6242621df2c183bf232f263d0ba5b101911e4563',
port: 15714,
portRpc: 15715,
protocol: {
magic: 0x05223570 // careful, sent over wire as little endian
},
seedsDns: [
'rat4.blackcoin.co',
'seed.blackcoin.co',
'archon.darkfox.id.au',
'foxy.seeds.darkfox.id.au',
'6.syllabear.us.to',
'bcseed.syllabear.us.to'
],
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 0xa,
private: 0x99,
public: 0x19,
scripthash: 0x55
}
}, common);
blk = {
main: main,
test: null
};
return blk;
}
/*
info from:
https://github.com/bitcoin/bitcoin/blob/master/src/chainparams.cpp
*/
var btc;
var hasRequiredBtc;
function requireBtc () {
if (hasRequiredBtc) return btc;
hasRequiredBtc = 1;
var common = {
name: 'Bitcoin',
per1: 1e8,
unit: 'BTC',
messagePrefix: '\x18Bitcoin Signed Message:\n'
};
var main = Object.assign({}, {
hashGenesisBlock: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
// nDefaultPort
port: 8333,
portRpc: 8332,
protocol: {
// pchMessageStart
magic: 0xd9b4bef9 // careful, sent over wire as little endian
},
bech32: 'bc',
// vSeeds
seedsDns: [
'seed.bitcoin.sipa.be',
'dnsseed.bluematt.me',
'seed.bitcoinstats.com',
'seed.bitcoin.jonasschnelli.ch',
'seed.btc.petertodd.org',
'seed.bitcoin.sprovoost.nl',
'dnsseed.emzy.de'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 0,
private: 0x80,
public: 0x00,
scripthash: 0x05
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943',
port: 18333,
portRpc: 18332,
protocol: {
magic: 0x0709110b
},
bech32: 'tb',
seedsDns: [
'testnet-seed.alexykot.me',
'testnet-seed.bitcoin.schildbach.de',
'testnet-seed.bitcoin.petertodd.org',
'testnet-seed.bluematt.me'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
var regtest = Object.assign({}, {
hashGenesisBlock: '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
port: 18444,
portRpc: 18332,
protocol: {
magic: 0xdab5bffa
},
bech32: 'bcrt',
seedsDns: [],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
btc = {
main: main,
test: test,
regtest: regtest
};
return btc;
}
/*
info from:
https://github.com/BTCGPU/BTCGPU/blob/master/src/chainparams.cpp
*/
var btg;
var hasRequiredBtg;
function requireBtg () {
if (hasRequiredBtg) return btg;
hasRequiredBtg = 1;
var common = {
name: 'Bitcoin Gold',
unit: 'BTG'
};
var main = Object.assign({}, {
hashGenesisBlock: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
// nDefaultPort
port: 8338,
protocol: {
// pchMessageStart
magic: 0x446d47e1 // careful, sent over wire as little endian
},
bech32: 'btg',
// vSeeds
seedsDns: [
'eu-dnsseed.bitcoingold-official.org',
'dnsseed.bitcoingold.org',
'dnsseed.btcgpu.org'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 156,
private: 0x80,
public: 0x26,
scripthash: 0x17
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '0x00000000e0781ebe24b91eedc293adfea2f557b53ec379e78959de3853e6f9f6',
port: 18338,
portRpc: 18332,
protocol: {
magic: 0x456e48e2
},
bech32: 'tbtg',
seedsDns: [
'test-dnsseed.bitcoingold.org',
'test-dnsseed.btcgpu.org',
'eu-test-dnsseed.bitcoingold-official.org'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 156,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
btg = {
main: main,
test: test
};
return btg;
}
/*
info from:
https://github.com/dashpay/dash/blob/master/src/chainparams.cpp
*/
var dash;
var hasRequiredDash;
function requireDash () {
if (hasRequiredDash) return dash;
hasRequiredDash = 1;
var common = {
name: 'Dash',
unit: 'DASH'
};
var main = Object.assign({}, {
hashGenesisBlock: '00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6',
// nDefaultPort
port: 9999,
portRpc: 9998,
protocol: {
magic: 0xbd6b0cbf // careful, sent over wire as little endian
},
// vSeeds
seedsDns: [
'dash.org',
'dnsseed.dash.org',
'dashdot.io',
'dnsseed.dashdot.io',
'masternode.io',
'dnsseed.masternode.io',
'dashpay.io',
'dnsseed.dashpay.io'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 5,
private: 0xcc,
public: 0x4c,
scripthash: 0x10
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '00000bafbc94add76cb75e2ec92894837288a481e5c005f6563d91623bf8bc2c',
port: 19999,
portRpc: 19998,
seedsDns: [
'dashdot.io',
'testnet-seed.dashdot.io',
'masternode.io',
'test.dnsseed.masternode.io'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x8c,
scripthash: 0x13
}
}, common);
dash = {
main: main,
test: test
};
return dash;
}
var dcr;
var hasRequiredDcr;
function requireDcr () {
if (hasRequiredDcr) return dcr;
hasRequiredDcr = 1;
var common = {
name: 'Decred',
unit: 'DCR'
};
// https://github.com/decred/dcrd/blob/ef71103c95cbf77e5a0418e3d413b5906e710b25/chaincfg/params.go
// https://github.com/decred/bitcore/blob/a92381b2b0023b28a1b7eb03e6cb0bfb7800200d/lib/networks.js
var main = Object.assign({}, {
hashGenesisBlock: '298e5cc3d985bfe7f81dc135f360abe089edd4396b86d2de66b0cef42b21d980',
port: 9108,
portRpc: 9109,
protocol: {
magic: 0xf900b4d9
},
seedsDns: [
'mainnet-seed.decred.mindcry.org',
'mainnet-seed.decred.netpurgatory.com',
'mainnet.decredseed.org',
'mainnet-seed.decred.org'
],
versions: {
bip32: {
private: 0x02fda4e8,
public: 0x02fda926
},
bip44: 42,
private: 0x22de,
public: 0x073f,
scripthash: 0x071a
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '5b7466edf6739adc9b32aaedc54e24bdc59a05f0ced855088835fe3cbe58375f',
port: 19108,
portRpc: 19109,
protocol: {
magic: 0x48e7a065
},
seedsDns: [
'testnet-seed.decred.mindcry.org',
'testnet-seed.decred.netpurgatory.org',
'testnet.decredseed.org',
'testnet-seed.decred.org'
],
versions: {
bip32: {
private: 0x04358397,
public: 0x043587d1
},
bip44: 42,
private: 0x230e,
public: 0x0f21,
scripthash: 0x0efc
}
}, common);
dcr = {
main: main,
test: test
};
return dcr;
}
/*
info from:
https://github.com/digibyte/digibyte/blob/9e4c0b3ddfd10a7ab852240ff716a7b93af89a07/src/chainparams.cpp
*/
var dgb;
var hasRequiredDgb;
function requireDgb () {
if (hasRequiredDgb) return dgb;
hasRequiredDgb = 1;
var common = {
name: 'DigiByte',
per1: 1e8,
unit: 'DGB'
};
var main = Object.assign({}, {
hashGenesisBlock: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
// nDefaultPort
port: 12024,
portRpc: 14022,
protocol: {
// pchMessageStart
magic: 0xfac3b6da // careful, sent over wire as little endian
},
bech32: 'dgb',
// vSeeds
seedsDns: [
'seed.digibyte.io',
'digiexplorer.info',
'digihash.co'
],
// base58Prefixes
versions: {
bip44: 0x80000014,
private: 0x80,
public: 0x1e,
scripthash: 0x3f, // new 'S' prefix
scripthash2: 0x05 // old '3' prefix
}
}, common);
dgb = { main: main };
return dgb;
}
var doge;
var hasRequiredDoge;
function requireDoge () {
if (hasRequiredDoge) return doge;
hasRequiredDoge = 1;
// https://github.com/dogecoin/dogecoin/blob/master/src/chainparams.cpp
var common = {
name: 'Dogecoin',
unit: 'DOGE'
};
var main = Object.assign({}, {
hashGenesisBlock: '1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691',
port: 22556,
protocol: {
magic: 0xc0c0c0c0
},
seedsDns: [
'seed.dogecoin.com',
'seed.multidoge.org',
'seed2.multidoge.org',
'seed.doger.dogecoin.com'
],
versions: {
bip32: {
private: 0x02fac398,
public: 0x02facafd
},
bip44: 3,
private: 0x9e,
public: 0x1e,
scripthash: 0x16
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: 'bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e',
versions: {
bip44: 1,
private: 0xf1,
public: 0x71,
scripthash: 0xc4
}
}, common);
doge = {
main: main,
test: test
};
return doge;
}
var ltc;
var hasRequiredLtc;
function requireLtc () {
if (hasRequiredLtc) return ltc;
hasRequiredLtc = 1;
// https://github.com/litecoin-project/litecoin/blob/master-0.10/src/chainparams.cpp
var common = {
name: 'Litecoin',
unit: 'LTC'
};
var main = Object.assign({}, {
hashGenesisBlock: '12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2',
port: 9333,
protocol: {
magic: 0xdbb6c0fb
},
bech32: 'ltc',
seedsDns: [
'dnsseed.litecointools.com',
'dnsseed.litecoinpool.org',
'dnsseed.ltc.xurious.com',
'dnsseed.koin-project.com',
'dnsseed.weminemnc.com'
],
versions: {
bip32: {
private: 0x019d9cfe,
public: 0x019da462
},
bip44: 2,
private: 0xb0,
public: 0x30,
scripthash: 0x32,
scripthash2: 0x05 // old '3' prefix. available for backward compatibility.
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: 'f5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f',
bech32: 'tltc',
versions: {
bip32: {
private: 0x0436ef7d,
public: 0x0436f6e1
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0x3a,
scripthash2: 0xc4
}
}, common);
ltc = {
main: main,
test: test
};
return ltc;
}
var via;
var hasRequiredVia;
function requireVia () {
if (hasRequiredVia) return via;
hasRequiredVia = 1;
// https://github.com/viacoin/viacoin/blob/master/src/chainparams.cpp
var common = {
name: 'Viacoin',
unit: 'VIA'
};
var main = Object.assign({}, {
hashGenesisBlock: '4e9b54001f9976049830128ec0331515eaabe35a70970d79971da1539a400ba1',
port: 5223,
protocol: {
magic: 0xcbc6680f
},
seedsDns: [
'seed.viacoin.net',
'viaseeder.barbatos.fr',
'mainnet.viacoin.net'
],
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 14,
private: 0xc7,
public: 0x47,
scripthash: 0x21
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '770aa712aa08fdcbdecc1c8df1b3e2d4e17a7cf6e63a28b785b32e74c96cb27d',
port: 25223,
protocol: {
magic: 0x92efc5a9
},
seedsDns: [
'testnet.viacoin.net',
'seed-testnet.viacoin.net'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xff,
public: 0x7f,
scripthash: 0xc4
}
}, common);
via = {
main: main,
test: test
};
return via;
}
var mona;
var hasRequiredMona;
function requireMona () {
if (hasRequiredMona) return mona;
hasRequiredMona = 1;
// https://github.com/monacoinproject/monacoin/blob/master-0.13/src/chainparams.cpp
var common = {
name: 'Monacoin',
unit: 'MONA'
};
var main = Object.assign({}, {
hashGenesisBlock: 'ff9f1c0116d19de7c9963845e129f9ed1bfc0b376eb54fd7afa42e0d418c8bb6',
port: 9401,
portRpc: 9402,
protocol: {
magic: 0xdbb6c0fb
},
bech32: 'mona',
seedsDns: [
'dnsseed.monacoin.org'
],
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 22,
private: 0xb0,
private2: 0xb2, // old wif
public: 0x32,
scripthash: 0x37,
scripthash2: 0x05 // old '3' prefix. available for backward compatibility.
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: 'a2b106ceba3be0c6d097b2a6a6aacf9d638ba8258ae478158f449c321061e0b2',
port: 19403,
portRpc: 19402,
protocol: {
magic: 0xf1c8d2fd
},
bech32: 'tmona',
seedsDns: [
'testnet-dnsseed.monacoin.org'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0x75,
scripthash2: 0xc4
}
}, common);
mona = {
main: main,
test: test
};
return mona;
}
var nbt;
var hasRequiredNbt;
function requireNbt () {
if (hasRequiredNbt) return nbt;
hasRequiredNbt = 1;
var common = {
name: 'NuBits',
per1: 1e6,
unit: 'NBT'
};
var main = Object.assign({}, {
hashGenesisBlock: '000003cc2da5a0a289ad0a590c20a8b975219ddc1204efd169e947dd4cbad73f',
// nDefaultPort
port: 7890,
portRpc: 14002,
protocol: {
// pchMessageStart
magic: 0xd9b4bef9 // careful, sent over wire as little endian
},
// vSeeds
seedsDns: [
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 12,
private: 0x96,
public: 0x19,
scripthash: 0x1a
}
}, common);
nbt = {
main: main
};
return nbt;
}
var nmc;
var hasRequiredNmc;
function requireNmc () {
if (hasRequiredNmc) return nmc;
hasRequiredNmc = 1;
var common = {
name: 'Namecoin',
unit: 'NMC'
};
var main = Object.assign({}, {
hashGenesisBlock: '000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770',
versions: {
bip44: 7,
private: 0xb4,
public: 0x34,
scripthash: 0x05
}
}, common);
nmc = {
main: main,
test: null
};
return nmc;
}
var ppc;
var hasRequiredPpc;
function requirePpc () {
if (hasRequiredPpc) return ppc;
hasRequiredPpc = 1;
// https://github.com/peercoin/peercoin/tree/v0.7.0ppc/src
// https://github.com/peercoin/peercoin/blob/v0.7.0ppc/src/${filename}
var common = {
name: 'Peercoin',
per1: 1e6, // util.h:40
unit: 'PPC',
messagePrefix: '\x18Peercoin Signed Message:\n' // main.cpp:77
};
var main = Object.assign({}, {
hashGenesisBlock: '0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3', // main.h:84
// nDefaultPort
port: 9901, // protocol.h:18
portRpc: 9902, // protocol.h:19
protocol: {
// pchMessageStart
magic: 0xe5e9e8e6 // careful, sent over wire as little endian protocol.cpp:31
},
// vSeeds
seedsDns: [
// net.cpp:1209
'seed.peercoin.net',
'seed2.peercoin.net',
'seed.peercoin-library.org',
'ppcseed.ns.7server.net'
],
versions: {
// not implemented in Peercoin <= v0.7.x nodes, only 3rd party wallets
// https://github.com/jmacwhyte/recovery-phrase-recovery/blob/52073aba08e9d01032c0b5aff8c682911fe2e5fc/js/bitcoinjs-extensions.js#L58
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 6, // https://github.com/satoshilabs/slips/blob/master/slip-0044.md
private: 0xb7, // base58.h:402 ; 128 + PUBKEY_ADDRESS
public: 0x37, // base58.h:276
scripthash: 0x75 // base58.h:277
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '00000001f757bb737f6596503e17cd17b0658ce630cc727c0cca81aec47c9f06',
port: 9903,
portRpc: 9904,
protocol: {
magic: 0xefc0f2cb
},
seedsDns: [
'tseed.peercoin.net',
'tseed2.peercoin.net',
'tseed.peercoin-library.org'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
ppc = {
main: main,
test: test
};
return ppc;
}
/*
info from:
https://github.com/qtumproject/qtum/blob/master/src/chainparams.cpp
*/
var qtum;
var hasRequiredQtum;
function requireQtum () {
if (hasRequiredQtum) return qtum;
hasRequiredQtum = 1;
var common = {
name: 'Qtum',
unit: 'QTUM'
};
var main = Object.assign({}, {
hashGenesisBlock: '000075aef83cf2853580f8ae8ce6f8c3096cfa21d98334d6e3f95e5582ed986c',
// nDefaultPort
port: 3888,
protocol: {
// pchMessageStart
magic: 0xd3a6cff1 // careful, sent over wire as little endian
},
bech32: 'qc',
// vSeeds
seedsDns: [
'qtum3.dynu.net'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 2301,
private: 0x80,
public: 0x3A,
scripthash: 0x32
}
}, common);
qtum = {
main: main
};
return qtum;
}
var rvn;
var hasRequiredRvn;
function requireRvn () {
if (hasRequiredRvn) return rvn;
hasRequiredRvn = 1;
// https://github.com/RavenProject/Ravencoin/blob/master/src/chainparams.cpp
var common = {
name: 'Ravencoin',
unit: 'RVN'
};
var main = Object.assign({}, {
hashGenesisBlock: '0000006b444bc2f2ffe627be9d9e7e7a0730000870ef6eb6da46c8eae389df90',
port: 8767,
protocol: {
magic: 0x4e564152
},
seedsDns: [
'seed-raven.bitactivate.com',
'seed-raven.ravencoin.com',
'seed-raven.ravencoin.org'
],
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 175,
private: 0x80,
public: 0x3c,
scripthash: 0x7a
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '000000ecfc5e6324a079542221d00e10362bdc894d56500c414060eea8a3ad5a',
port: 18770,
protocol: {
magic: 0x544e5652
},
seedsDns: [
'seed-testnet-raven.bitactivate.com',
'seed-testnet-raven.ravencoin.com',
'seed-testnet-raven.ravencoin.org'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
rvn = {
main: main,
test: test
};
return rvn;
}
var rdd;
var hasRequiredRdd;
function requireRdd () {
if (hasRequiredRdd) return rdd;
hasRequiredRdd = 1;
var common = {
name: 'ReddCoin',
unit: 'RDD'
};
var main = Object.assign({}, {
hashGenesisBlock: 'b868e0d95a3c3c0e0dadc67ee587aaf9dc8acbf99e3b4b3110fad4eb74c1decc',
versions: {
bip44: 4,
private: 0xbd,
public: 0x3d,
scripthash: 0x05
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: 'a12ac9bd4cd26262c53a6277aafc61fe9dfe1e2b05eaa1ca148a5be8b394e35a',
versions: {
bip44: 1,
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
rdd = {
main: main,
test: test
};
return rdd;
}
/*
info from:
https://github.com/vertcoin/vertcoin/blob/master/src/chainparams.cpp
*/
var vtc;
var hasRequiredVtc;
function requireVtc () {
if (hasRequiredVtc) return vtc;
hasRequiredVtc = 1;
var common = {
name: 'Vertcoin',
unit: 'VTC'
};
var main = Object.assign({}, {
hashGenesisBlock: '4d96a915f49d40b1e5c2844d1ee2dccb90013a990ccea12c492d22110489f0c4',
// nDefaultPort
port: 5889,
protocol: {
// pchMessageStart
magic: 0xdab5bffa // careful, sent over wire as little endian
},
bech32: 'vtc',
// vSeeds
seedsDns: [
'useast1.vtconline.org',
'vtc.gertjaap.org',
'seed.vtc.bryangoodson.org',
'dnsseed.pknight.ca',
'seed.orderofthetaco.org',
'seed.alexturek.org',
'vertcoin.mbl.cash'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 28,
private: 0x80,
public: 0x47,
scripthash: 0x05
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: 'cee8f24feb7a64c8f07916976aa4855decac79b6741a8ec2e32e2747497ad2c9',
port: 15889,
// portRpc: 18332,
protocol: {
magic: 0x74726576
},
bech32: 'tvtc',
seedsDns: [
'jlovejoy.mit.edu',
'gertjaap.ddns.net',
'fr1.vtconline.org',
'tvtc.vertcoin.org'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
private: 0xef,
public: 0x4a,
scripthash: 0xc4
}
}, common);
var regtest = Object.assign({}, {
hashGenesisBlock: '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
port: 18444,
// portRpc: 18332,
protocol: {
magic: 0xdab5bffa
},
seedsDns: [],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
private: 0xef,
public: 0x6f,
scripthash: 0xc4
}
}, common);
vtc = {
main: main,
test: test,
regtest: regtest
};
return vtc;
}
/*
info from:
https://github.com/zcash/zcash/blob/v1.0.12/src/chainparamsbase.cpp
https://github.com/zcash/zcash/blob/v1.0.12/src/chainparams.cpp
*/
var zec;
var hasRequiredZec;
function requireZec () {
if (hasRequiredZec) return zec;
hasRequiredZec = 1;
var common = {
name: 'Zcash',
unit: 'ZEC'
};
var main = Object.assign({}, {
hashGenesisBlock: '00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08',
// nDefaultPort
port: 8233,
portRpc: 8232,
protocol: {
// pchMessageStart
magic: 0x6427e924 // careful, sent over wire as little endian
},
// vSeeds
seedsDns: [
'dnsseed.z.cash',
'dnsseed.str4d.xyz',
'dnsseed.znodes.org'
],
// base58Prefixes
versions: {
bip32: {
private: 0x0488ade4,
public: 0x0488b21e
},
bip44: 133,
private: 0x80,
public: 0x1cb8,
scripthash: 0x1cbd
}
}, common);
var test = Object.assign({}, {
hashGenesisBlock: '0x05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38',
port: 18233,
portRpc: 18232,
protocol: {
magic: 0xbff91afa
},
seedsDns: [
'dnsseed.testnet.z.cash'
],
versions: {
bip32: {
private: 0x04358394,
public: 0x043587cf
},
bip44: 133,
private: 0xef,
public: 0x1d25,
scripthash: 0x1cba
}
}, common);
zec = {
main: main,
test: test
};
return zec;
}
var coininfo_1;
var hasRequiredCoininfo;
function requireCoininfo () {
if (hasRequiredCoininfo) return coininfo_1;
hasRequiredCoininfo = 1;
var Buffer = requireSafeBuffer().Buffer;
// annoyingly, this is for browserify
var coins = [
requireBch(),
requireBlk(),
requireBtc(),
requireBtg(),
requireDash(),
requireDcr(),
requireDgb(),
requireDoge(),
requireLtc(),
requireVia(),
requireMona(),
requireNbt(),
requireNmc(),
requirePpc(),
requireQtum(),
requireRvn(),
requireRdd(),
requireVtc(),
requireZec()
];
var supportedCoins = {};
coins.forEach(function (coin) {
var unit = coin.main.unit.toLowerCase();
var name = coin.main.name.toLowerCase();
coin.main.testnet = false;
coin.main.toBitcoinJS = toBitcoinJS.bind(coin.main);
coin.main.toBitcore = toBitcore.bind(coin.main);
supportedCoins[unit] = coin.main;
supportedCoins[name] = coin.main;
if (coin.test) {
coin.test.testnet = true;
coin.test.toBitcoinJS = toBitcoinJS.bind(coin.test);
coin.test.toBitcore = toBitcore.bind(coin.test);
supportedCoins[unit + '-test'] = coin.test;
supportedCoins[name + '-test'] = coin.test;
}
if (coin.regtest) {
coin.regtest.testnet = true;
coin.regtest.toBitcoinJS = toBitcoinJS.bind(coin.regtest);
coin.regtest.toBitcore = toBitcore.bind(coin.regtest);
supportedCoins[unit + '-regtest'] = coin.regtest;
supportedCoins[name + '-regtest'] = coin.regtest;
}
});
function coininfo (input) {
var coin = input.toLowerCase();
if (!(coin in supportedCoins)) {
return null
} else {
return supportedCoins[coin]
}
}
coins.forEach(function (coin) {
coininfo[coin.main.name.toLowerCase()] = coin;
});
function toBitcoinJS () {
return Object.assign({}, this, {
messagePrefix: this.messagePrefix || ('\x19' + this.name + ' Signed Message:\n'),
bech32: this.bech32,
bip32: {
public: (this.versions.bip32 || {}).public,
private: (this.versions.bip32 || {}).private
},
pubKeyHash: this.versions.public,
scriptHash: this.versions.scripthash,
wif: this.versions.private,
dustThreshold: null // TODO
})
}
function toBitcore () {
// reverse magic
var nm = Buffer.allocUnsafe(4);
nm.writeUInt32BE(this.protocol ? this.protocol.magic : 0, 0);
nm = nm.readUInt32LE(0);
return Object.assign({}, this, {
name: this.testnet ? 'testnet' : 'livenet',
alias: this.testnet ? 'testnet' : 'mainnet',
pubkeyhash: this.versions.public,
privatekey: this.versions.private,
scripthash: this.versions.scripthash,
xpubkey: (this.versions.bip32 || {}).public,
xprivkey: (this.versions.bip32 || {}).private,
networkMagic: nm,
port: this.port,
dnsSeeds: this.seedsDns || []
})
}
coininfo_1 = coininfo;
return coininfo_1;
}
var coininfoExports = requireCoininfo();
var coininfo = /*@__PURE__*/getDefaultExportFromCjs(coininfoExports);
/**
* Module importing and providing utilities for Bitcoin Cash (BCH) transactions and addresses.
*/
/**
* Size constants for BCH transactions.
*/
const TX_EMPTY_SIZE = 4 + 1 + 1 + 4;
const TX_INPUT_BASE = 32 + 4 + 1 + 4;
const TX_INPUT_PUBKEYHASH = 107;
const TX_OUTPUT_BASE = 8 + 1;
const TX_OUTPUT_PUBKEYHASH = 25;
/**
* Retrieves the BCH network to be used with bitcore-lib.
* @param {Network} network The network type.
* @returns {BCHNetwork} The BCH network.
*/
const bchNetwork = (network) => {
switch (network) {
case xchainClient.Network.Mainnet:
case xchainClient.Network.Stagenet:
return coininfo.bitcoincash.main.toBitcoinJS();
case xchainClient.Network.Testnet:
return coininfo.bitcoincash.test.toBitcoinJS();
}
};
/**
* Retrieves the BCH address prefix.
*
* @returns {string} The BCH address prefix.
*/
const getPrefix = () => '';
/**
* Strips the BCH address prefix.
* @param {Address} address The BCH address.
* @returns {Address} The address with the prefix removed.
*/
const stripPrefix = (address) => address.replace(/(bchtest:|bitcoincash:)/, '');
/**
* Converts the BCH address to a legacy address format.
* @param {Address} address The BCH address.
* @returns {Address} The legacy address.
*/
const toLegacyAddress = (address) => {
return bchaddr__namespace.toLegacyAddress(address);
};
/**
* Converts the BCH address to a cash address format.
* @param {Address} address The BCH address.
* @returns {Address} The cash address.
*/
const toCashAddress = (address) => {
return bchaddr__namespace.toCashAddress(address);
};
/**
* Checks whether the address is a cash address.
* @param {Address} address The BCH address.
* @returns {boolean} Whether the address is a cash address.
*/
const isCashAddress = (address) => {
return bchaddr__namespace.isCashAddress(address);
};
/**
* Parses a BCH transaction.
* @param {Transaction} tx The BCH transaction.
* @returns {Tx} The parsed transaction.
*/
const parseTransaction = (tx) => {
return {
asset: AssetBCH,
from: tx.inputs
.filter((input) => !!input.address)
.map((input) => ({
from: stripPrefix(input.address),
amount: xchainUtil.baseAmount(input.value, BCH_DECIMAL),
})),
to: tx.outputs
.filter((output) => !!output.address)
.map((output) => ({
to: stripPrefix(output.address),
amount: xchainUtil.baseAmount(output.value, BCH_DECIMAL),
})),
date: new Date(tx.time * 1000),
type: xchainClient.TxType.Transfer,
hash: tx.txid,
};
};
/**
* Converts the XChain network to a BCH address network.
* @param {Network} network The XChain network.
* @returns {string} The BCH address network.
*/
const toBCHAddressNetwork = (network) => {
switch (network) {
case xchainClient.Network.Mainnet:
case xchainClient.Network.Stagenet:
return bchaddr__namespace.Network.Mainnet;
case xchainClient.Network.Testnet:
return bchaddr__namespace.Network.Testnet;
}
};
/**
* Validates the BCH address.
* @param {string} address The BCH address.
* @param {Network} network The XChain network.
* @returns {boolean} Whether the address is valid.
*/
const validateAddress = (address, network) => {
const toAddress = toCashAddress(address);
return bchaddr__namespace.isValidAddress(toAddress) && bchaddr__namespace.detectAddressNetwork(toAddress) === toBCHAddressNetwork(network);
};
// Default parameters for Bitcoin Cash (BCH) client
const defaultBchParams = {
network: xchainClient.Network.Mainnet,
phrase: '',
explorerProviders: explorerProviders,
dataProviders: [BitgoProviders, HaskoinDataProviders],
rootDerivationPaths: {
[xchainClient.Network.Mainnet]: `m/44'/145'/0'/0/`,
[xchainClient.Network.Testnet]: `m/44'/1'/0'/0/`,
[xchainClient.Network.Stagenet]: `m/44'/145'/0'/0/`, // Default root derivation path for Stagenet
},
feeBounds: {
lower: LOWER_FEE_BOUND,
upper: UPPER_FEE_BOUND, // Default upper fee bound
},
};
/**
* Custom Bitcoin Cash client class.
*/
class Client extends xchainUtxo.Client {
/**
* Constructor for the Client class.
*
* @param {UtxoClientParams} params - Parameters for initializing the client.
*/
constructor(params = defaultBchParams) {
// Call the constructor of the parent class (UTXOClient) with BCHChain as the chain and provided parameters
super(BCHChain, {
network: params.network,
rootDerivationPaths: params.rootDerivationPaths,
phrase: params.phrase,
feeBounds: params.feeBounds,
explorerProviders: params.explorerProviders,
dataProviders: params.dataProviders,
});
}
/**
* Get information about the BCH asset.
* @returns Information about the BCH asset.
*/
getAssetInfo() {
const assetInfo = {
asset: AssetBCH,
decimal: BCH_DECIMAL, // Decimal precision
};
return assetInfo;
}
/**
* Validate the given address.
*
* @param {Address} address
* @returns {boolean} `true` or `false`
*/
validateAddress(address) {
return validateAddress(address, this.network);
}
/**
* Build a BCH transaction.
* @param {BuildParams} params - The transaction build options.
* @returns {Transaction} A promise that resolves with the transaction builder, UTXOs, and inputs.
* @deprecated
*/
buildTx({ amount, recipient, memo, feeRate, sender, }) {
return __awaiter(this, void 0, void 0, function* () {
// Convert recipient address to CashAddress format
const recipientCashAddress = toCashAddress(recipient);
// Validate recipient address
if (!this.validateAddress(recipientCashAddress))
throw new Error('Invalid address');
// Scan UTXOs for the sender address
const utxos = yield this.scanUTXOs(sender, false);
// Throw error if no UTXOs are found
if (utxos.length === 0)
throw new Error('No utxos to send');
// Convert fee rate to a whole number
const feeRateWhole = Number(feeRate.toFixed(0));
// Compile memo if provided
const compiledMemo = memo ? this.compileMemo(memo) : null;
const targetOutputs = [];
// Add output amount and recipient to target outputs
targetOutputs.push({
address: recipient,
value: amount.amount().toNumber(),
});
// Calculate transaction inputs and outputs
const { inputs, outputs } = accumulative(utxos, targetOutputs, feeRateWhole);
// Throw error if no solution is found
if (!inputs || !outputs)
throw new Error('Insufficient Balance for transaction');
// Initialize a new transaction builder
const transactionBuilder = new bitcash__namespace.TransactionBuilder(bchNetwork(this.network));
// Add inputs to the transaction builder
inputs.forEach((utxo) => transactionBuilder.addInput(bitcash__namespace.Transaction.fromBuffer(Buffer.from(utxo.txHex || '', 'hex')), utxo.index));
// Add outputs to the transaction builder
// eslint-disable-next-line @typescript-eslint/no-explicit-any
outputs.forEach((output) => {
let out = undefined;
if (!output.address) {
// An empty address means this is the change address
out = bitcash__namespace.address.toOutputScript(toLegacyAddress(sender), bchNetwork(this.network));
}
else if (output.address) {
out = bitcash__namespace.address.toOutputScript(toLegacyAddress(output.address), bchNetwork(this.network));
}
transactionBuilder.addOutput(out, output.value);
});
// Add output for memo if compiled
if (compiledMemo) {
transactionBuilder.addOutput(compiledMemo, 0); // Add OP_RETURN {script, value}
}
// Return transaction builder, UTXOs, and inputs
return {
builder: transactionBuilder,
utxos,
inputs,
};
});
}
/**
* Prepare a BCH transaction.
* @param {TxParams&Address&FeeRate} params - The transaction preparation options.
* @returns {PreparedTx} A promise that resolves with the prepared transaction and UTXOs.
*/
prepareTx({ sender, memo, amount, recipient, feeRate, }) {
return __awaiter(this, void 0, void 0, function* () {
// Build the transaction using provided options
const { builder, utxos, inputs } = yield this.buildTx({
sender,
recipient,
amount,
memo,
feeRate,
});
// Return the raw unsigned transaction and UTXOs
return { rawUnsignedTx: builder.buildIncomplete().toHex(), utxos, inputs };
});
}
/**
* Compile a memo.
* @param {string} memo - The memo to be compiled.
* @returns {Buffer} - The compiled memo.
*/
compileMemo(memo) {
const data = Buffer.from(memo, 'utf8'); // converts MEMO to buffer
return bitcash__namespace.script.compile([bitcash__namespace.opcodes.OP_RETURN, data]); // Compile OP_RETURN script
}
/**
* Calculate the transaction fee.
* @param {UTXO[]} inputs - The UTXOs.
* @param {FeeRate} feeRate - The fee rate.
* @param {Buffer | null} data - The compiled memo (optional).
* @returns {number} - The fee amount.
*/
getFeeFromUtxos(inputs, feeRate, data = null) {
let totalWeight = TX_EMPTY_SIZE;
totalWeight += (TX_INPUT_PUBKEYHASH + TX_INPUT_BASE) * inputs.length;
totalWeight += (TX_OUTPUT_BASE + TX_OUTPUT_PUBKEYHASH) * 2;
if (data) {
totalWeight += 9 + data.length;
}
return Math.ceil(totalWeight * feeRate);
}
}
/**
* Custom Bitcoin client extended to support keystore functionality
*/
class ClientKeystore extends Client {
/**
* @deprecated This function eventually will be removed. Use getAddressAsync instead.
* Get the address associated with the given index.
* @param {number} index The index of the address.
* @returns {Address} The Bitcoin address.
* @t