@thorwallet/xchain-bitcoin
Version:
Custom Bitcoin client and utilities used by XChainJS clients
196 lines • 6.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSuggestedTxFee = exports.getConfirmedUnspentTxs = exports.getIsTxConfirmed = exports.getUnspentTxs = exports.getBalance = exports.getTx = exports.getAddress = void 0;
const tslib_1 = require("tslib");
const axios_1 = tslib_1.__importDefault(require("axios"));
const xchain_util_1 = require("@thorwallet/xchain-util");
const utils_1 = require("./utils");
const DEFAULT_SUGGESTED_TRANSACTION_FEE = 127;
const toSochainNetwork = (net) => {
return net === 'testnet' ? 'BTCTEST' : 'BTC';
};
/**
* Get address information.
*
* @see https://sochain.com/api#get-display-data-address
*
* @param {string} sochainUrl The sochain node url.
* @param {string} network
* @param {string} address
* @returns {BtcAddressDTO}
*/
const getAddress = ({ sochainUrl, network, address }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
const url = `${sochainUrl}/address/${toSochainNetwork(network)}/${address}`;
const response = yield axios_1.default.get(url);
const addressResponse = response.data;
return addressResponse.data;
}
catch (error) {
return Promise.reject(error);
}
});
exports.getAddress = getAddress;
/**
* Get transaction by hash.
*
* @see https://sochain.com/api#get-tx
*
* @param {string} sochainUrl The sochain node url.
* @param {string} network network id
* @param {string} hash The transaction hash.
* @returns {Transactions}
*/
const getTx = ({ sochainUrl, network, hash }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
const url = `${sochainUrl}/get_tx/${toSochainNetwork(network)}/${hash.toLowerCase()}`;
const response = yield axios_1.default.get(url);
const tx = response.data;
return tx.data;
}
catch (error) {
return Promise.reject(error);
}
});
exports.getTx = getTx;
/**
* Get address balance.
*
* @see https://sochain.com/api#get-balance
*
* @param {string} sochainUrl The sochain node url.
* @param {string} network
* @param {string} address
* @returns {number}
*/
const getBalance = ({ sochainUrl, network, address }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
const url = `${sochainUrl}/get_address_balance/${toSochainNetwork(network)}/${address}`;
const response = yield axios_1.default.get(url);
const balanceResponse = response.data;
const confirmed = xchain_util_1.assetAmount(balanceResponse.data.confirmed_balance, utils_1.BTC_DECIMAL);
const unconfirmed = xchain_util_1.assetAmount(balanceResponse.data.unconfirmed_balance, utils_1.BTC_DECIMAL);
const netAmt = confirmed.amount().plus(unconfirmed.amount());
const result = xchain_util_1.assetToBase(xchain_util_1.assetAmount(netAmt, utils_1.BTC_DECIMAL));
return result;
}
catch (error) {
return Promise.reject(error);
}
});
exports.getBalance = getBalance;
/**
* Get unspent txs
*
* @see https://sochain.com/api#get-unspent-tx
*
* @param {string} sochainUrl The sochain node url.
* @param {string} network
* @param {string} address
* @returns {BtcAddressUTXOs}
*/
const getUnspentTxs = ({ sochainUrl, network, address, startingFromTxId, }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
let resp = null;
if (startingFromTxId) {
resp = yield axios_1.default.get(`${sochainUrl}/get_tx_unspent/${toSochainNetwork(network)}/${address}/${startingFromTxId}`);
}
else {
resp = yield axios_1.default.get(`${sochainUrl}/get_tx_unspent/${toSochainNetwork(network)}/${address}`);
}
const response = resp.data;
const txs = response.data.txs;
if (txs.length === 100) {
//fetch the next batch
const lastTxId = txs[99].txid;
const nextBatch = yield exports.getUnspentTxs({
sochainUrl,
network,
address,
startingFromTxId: lastTxId,
});
return txs.concat(nextBatch);
}
else {
return txs;
}
}
catch (error) {
return Promise.reject(error);
}
});
exports.getUnspentTxs = getUnspentTxs;
/**
* Get Tx Confirmation status
*
* @see https://sochain.com/api#get-is-tx-confirmed
*
* @param {string} sochainUrl The sochain node url.
* @param {string} network mainnet | testnet
* @param {string} hash tx id
* @returns {TxConfirmedStatus}
*/
const getIsTxConfirmed = ({ sochainUrl, network, hash }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
const { data } = yield axios_1.default.get(`${sochainUrl}/is_tx_confirmed/${toSochainNetwork(network)}/${hash.toLowerCase()}`);
return data.data;
}
catch (error) {
return Promise.reject(error);
}
});
exports.getIsTxConfirmed = getIsTxConfirmed;
/**
* Get unspent txs and filter out pending UTXOs
*
* @see https://sochain.com/api#get-unspent-tx
*
* @param {string} sochainUrl The sochain node url.
* @param {string} network
* @param {string} address
* @returns {BtcAddressUTXOs}
*/
const getConfirmedUnspentTxs = ({ sochainUrl, network, address, }) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
try {
const txs = yield exports.getUnspentTxs({
sochainUrl,
network,
address,
});
const confirmedUTXOs = [];
yield Promise.all(txs.map((tx) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
const { is_confirmed: isTxConfirmed } = yield exports.getIsTxConfirmed({
sochainUrl,
network,
hash: tx.txid,
});
if (isTxConfirmed) {
confirmedUTXOs.push(tx);
}
})));
return confirmedUTXOs;
}
catch (error) {
return Promise.reject(error);
}
});
exports.getConfirmedUnspentTxs = getConfirmedUnspentTxs;
/**
* Get Bitcoin suggested transaction fee.
*
* @returns {number} The Bitcoin suggested transaction fee per bytes in sat.
*/
const getSuggestedTxFee = () => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
//Note: sochain does not provide fee rate related data
//So use Bitgo API for fee estimation
//Refer: https://app.bitgo.com/docs/#operation/v2.tx.getfeeestimate
try {
const response = yield axios_1.default.get('https://app.bitgo.com/api/v2/btc/tx/fee');
return response.data.feePerKb / 1000; // feePerKb to feePerByte
}
catch (error) {
return DEFAULT_SUGGESTED_TRANSACTION_FEE;
}
});
exports.getSuggestedTxFee = getSuggestedTxFee;
//# sourceMappingURL=sochain-api.js.map