send-crypto
Version:
A minimal JavaScript library / wallet for sending crypto assets
88 lines • 8.02 kB
JavaScript
import axios from "axios";
import { URLSearchParams } from "url";
import { sortUTXOs } from "../../lib/utxo";
import { DEFAULT_TIMEOUT } from "./timeout";
export var BlockchainNetwork;
(function (BlockchainNetwork) {
BlockchainNetwork["Bitcoin"] = "btc";
BlockchainNetwork["BitcoinCash"] = "bch";
BlockchainNetwork["BitcoinTestnet"] = "btc-testnet";
BlockchainNetwork["BitcoinCashTestnet"] = "bch-testnet";
})(BlockchainNetwork || (BlockchainNetwork = {}));
const fetchLatestBlock = async (network) => {
const statsUrl = `https://api.blockchain.info/haskoin-store/${network}/block/best?notx=true`;
const statsResponse = (await axios.get(statsUrl)).data;
return statsResponse.height;
};
const fetchUTXO = (network) => async (txHash, vOut) => {
const url = `https://api.blockchain.info/haskoin-store/${network}/transaction/${txHash}`;
const response = (await axios.get(`${url}`, {
timeout: DEFAULT_TIMEOUT,
})).data;
const confirmations = !response.block || !response.block.height
? 0
: Math.max((await fetchLatestBlock(network)) -
response.block.height +
1, 0);
return {
txHash,
vOut,
amount: response.outputs[vOut].value,
confirmations,
};
};
const fetchUTXOs = (network) => async (address, confirmations, limit = 25, offset = 0) => fetchTXs(network)(address, confirmations, limit, offset, true);
const fetchTXs = (network) => async (address, confirmations = 0, limit = 25, offset = 0, onlyUnspent = false) => {
const url = `https://api.blockchain.info/haskoin-store/${network}/address/${address}/transactions/full?limit=${limit}&offset=${offset}`;
const response = (await axios.get(url, {
timeout: DEFAULT_TIMEOUT,
})).data;
let latestBlock;
const received = [];
for (const tx of response) {
latestBlock = latestBlock || (await fetchLatestBlock(network));
const txConfirmations = tx.block && tx.block.height
? Math.max(latestBlock - tx.block.height + 1, 0)
: 0;
for (let i = 0; i < tx.outputs.length; i++) {
const vout = tx.outputs[i];
if (vout.address === address &&
// If the onlyUnspent flag is true, check that the tx is unspent.
(!onlyUnspent || vout.spent === false)) {
received.push({
txHash: tx.txid,
amount: vout.value,
vOut: i,
confirmations: txConfirmations,
});
}
}
}
return received
.filter((utxo) => confirmations === 0 || utxo.confirmations >= confirmations)
.sort(sortUTXOs);
};
export const broadcastTransaction = (network) => async (txHex) => {
if (network !== BlockchainNetwork.Bitcoin) {
throw new Error(`Broadcasting ${network} transactions not supported by endpoint.`);
}
const url = `https://blockchain.info/pushtx`;
const params = new URLSearchParams();
params.append("tx", txHex);
const response = await axios.post(url, params, {
timeout: DEFAULT_TIMEOUT,
});
if (response.data.error) {
throw new Error(response.data.error);
}
// TODO
return response.data;
};
export const Blockchain = {
networks: BlockchainNetwork,
fetchUTXO,
fetchUTXOs,
broadcastTransaction,
fetchTXs,
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tjaGFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21tb24vYXBpcy9ibG9ja2NoYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRXRDLE9BQU8sRUFBRSxTQUFTLEVBQVEsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRTVDLE1BQU0sQ0FBTixJQUFZLGlCQUtYO0FBTEQsV0FBWSxpQkFBaUI7SUFDekIsb0NBQWUsQ0FBQTtJQUNmLHdDQUFtQixDQUFBO0lBQ25CLG1EQUE4QixDQUFBO0lBQzlCLHVEQUFrQyxDQUFBO0FBQ3RDLENBQUMsRUFMVyxpQkFBaUIsS0FBakIsaUJBQWlCLFFBSzVCO0FBZ0RELE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxFQUMxQixPQUEwQixFQUNYLEVBQUU7SUFDakIsTUFBTSxRQUFRLEdBQUcsNkNBQTZDLE9BQU8sdUJBQXVCLENBQUM7SUFDN0YsTUFBTSxhQUFhLEdBQUcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQXFCLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzNFLE9BQU8sYUFBYSxDQUFDLE1BQU0sQ0FBQztBQUNoQyxDQUFDLENBQUM7QUFFRixNQUFNLFNBQVMsR0FDWCxDQUFDLE9BQTBCLEVBQUUsRUFBRSxDQUMvQixLQUFLLEVBQUUsTUFBYyxFQUFFLElBQVksRUFBaUIsRUFBRTtJQUNsRCxNQUFNLEdBQUcsR0FBRyw2Q0FBNkMsT0FBTyxnQkFBZ0IsTUFBTSxFQUFFLENBQUM7SUFFekYsTUFBTSxRQUFRLEdBQUcsQ0FDYixNQUFNLEtBQUssQ0FBQyxHQUFHLENBQXdCLEdBQUcsR0FBRyxFQUFFLEVBQUU7UUFDN0MsT0FBTyxFQUFFLGVBQWU7S0FD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