diff --git a/helpers/index.js b/helpers/index.js index 2f3fc11..ca3fa35 100644 --- a/helpers/index.js +++ b/helpers/index.js @@ -4,15 +4,24 @@ const clients = require("./clients"); let electrumKeepAlive = () => null; let electrumKeepAliveInterval = 60000; -const getTimeout = ({ arr = undefined, timeout = 1000 } = {}) => { +const _getTimeout = ({ arr = [], timeout = 1000 } = {}) => { try { + if (!Array.isArray(arr)) arr = _attemptToGetArray(arr); if (arr && Array.isArray(arr)) return arr.length * timeout; - return timeout; + return timeout || 1000; } catch { return timeout; } } +const _attemptToGetArray = (scriptHashes = []) => { + try { + if (Array.isArray(scriptHashes)) return scriptHashes; + if ("data" in scriptHashes) return scriptHashes.data; + return []; + } catch { return []; } +}; + const promiseTimeout = (ms, promise) => { let id; let timeout = new Promise((resolve) => { @@ -56,7 +65,7 @@ const pingServer = ({ id = Math.random() } = {}) => { return new Promise(async (resolve) => { try { if (clients.mainClient[clients.network] === false) await connectToRandomPeer(clients.network, clients.peers[clients.network]); - const { error, data } = await promiseTimeout(getTimeout(), clients.mainClient[clients.network].server_ping()); + const { error, data } = await promiseTimeout(_getTimeout(), clients.mainClient[clients.network].server_ping()); resolve({ id, error, method, data, network: clients.network }); } catch (e) { resolve({ id, error: true, method, data: e, network: clients.network }); @@ -251,7 +260,7 @@ const getAddressScriptHashBalance = ({ scriptHash = "", id = Math.random(), netw return new Promise(async (resolve) => { try { if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); - const { error, data } = await promiseTimeout(getTimeout(), clients.mainClient[network].blockchainScripthash_getBalance(scriptHash)); + const { error, data } = await promiseTimeout(_getTimeout(), clients.mainClient[network].blockchainScripthash_getBalance(scriptHash)); resolve({ id, error, method, data, scriptHash, network }); } catch (e) { console.log(e); @@ -308,7 +317,7 @@ const getFeeEstimate = ({ blocksWillingToWait = 8, id = Math.random(), network = return new Promise(async (resolve) => { try { if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); - const response = await promiseTimeout(getTimeout(), clients.mainClient[network].blockchainEstimatefee(blocksWillingToWait)); + const response = await promiseTimeout(_getTimeout(), clients.mainClient[network].blockchainEstimatefee(blocksWillingToWait)); resolve({ ...response, id, method, network }); } catch (e) { console.log(e); @@ -322,7 +331,8 @@ const getAddressScriptHashBalances = ({ scriptHashes = [], id = Math.random(), n return new Promise(async (resolve) => { try { if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); - const response = await promiseTimeout(getTimeout(), clients.mainClient[network].blockchainScripthash_getBalanceBatch(scriptHashes)); + const timeout = _getTimeout({ arr: scriptHashes }); + const response = await promiseTimeout(timeout, clients.mainClient[network].blockchainScripthash_getBalanceBatch(scriptHashes)); resolve({ ...response, id, method, network }); } catch (e) { console.log(e); @@ -331,12 +341,76 @@ const getAddressScriptHashBalances = ({ scriptHashes = [], id = Math.random(), n }); }; +const listUnspentAddressScriptHashes = ({ scriptHashes = [], id = Math.random(), network = "", timeout = undefined } = {}) => { + const method = "listUnspentAddressScriptHashes"; + return new Promise(async (resolve) => { + try { + if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); + if (!timeout) timeout = _getTimeout({ arr: scriptHashes }); + const { error, data } = await promiseTimeout(timeout, clients.mainClient[network].blockchainScripthash_listunspentBatch(scriptHashes)); + resolve({ id, error, method, data, network }); + } catch (e) { + console.log(e); + resolve({ id, error: true, method, data: e, network }); + } + }); +}; + +const getAddressScriptHashesHistory = ({ scriptHashes = [], id = Math.random(), network = "", timeout = undefined } = {}) => { + const method = "getScriptHashesHistory"; + return new Promise(async (resolve) => { + try { + if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); + if (!timeout) timeout = _getTimeout({ arr: scriptHashes }); + const { error, data } = await promiseTimeout(timeout, clients.mainClient[network].blockchainScripthash_getHistoryBatch(scriptHashes)); + resolve({ id, error, method, data, network }); + } catch (e) { + console.log(e); + resolve({ id, error: true, method, data: e, network }); + } + }); +}; + +const getAddressScriptHashesMempool = ({ scriptHashes = [], id = Math.random(), network = "", timeout = undefined } = {}) => { + const method = "getAddressScriptHashesMempool"; + return new Promise(async (resolve) => { + try { + if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); + if (!timeout) timeout = _getTimeout({ arr: scriptHashes }); + const { error, data } = await promiseTimeout(timeout, clients.mainClient[network].blockchainScripthash_getMempoolBatch(scriptHashes)); + resolve({ id, error, method, data, network }); + } catch (e) { + console.log(e); + resolve({ id, error: true, method, data: e, network }); + } + }); +}; + +const getTransactions = ({ txHashes = [], id = Math.random(), network = "", timeout = undefined } = {}) => { + const method = "getTransactions"; + return new Promise(async (resolve) => { + try { + if (clients.mainClient[network] === false) await connectToRandomPeer(network, clients.peers[network]); + if (!timeout) timeout = _getTimeout({ arr: scriptHashes }); + const { error, data } = await promiseTimeout(timeout, clients.mainClient[network].blockchainTransaction_getBatch(txHashes)); + resolve({ id, error, method, data, network }); + } catch (e) { + console.log(e); + resolve({ id, error: true, method, data: e, network }); + } + }); +}; + module.exports = { start, stop, pingServer, getAddressScriptHashBalance, getAddressScriptHashBalances, + listUnspentAddressScriptHashes, + getAddressScriptHashesHistory, + getAddressScriptHashesMempool, + getTransactions, getPeers, subscribeHeader, subscribeAddress, diff --git a/lib/client.js b/lib/client.js index f32f5c0..85377a1 100644 --- a/lib/client.js +++ b/lib/client.js @@ -53,16 +53,30 @@ class Client { let arguments_far_calls = {}; let contents = []; const { key, data } = params; - for (let item of data) { + if (Array.isArray(data)) { + for (let item of data) { + const id = ++this.id; + let param = ""; + if (key in item) param = item[key]; + if (secondParam !== undefined) { + contents.push(util.makeRequest(method, [param, secondParam], id)); + } else { + contents.push(util.makeRequest(method, [param], id)); + } + arguments_far_calls[id] = { param, data: item }; + } + } + + for (let item of Object.keys(data)) { const id = ++this.id; let param = ""; - if (key in item) param = item[key]; + if (key in data[item]) param = data[item][key]; if (secondParam !== undefined) { contents.push(util.makeRequest(method, [param, secondParam], id)); } else { contents.push(util.makeRequest(method, [param], id)); } - arguments_far_calls[id] = { param, data: item }; + arguments_far_calls[id] = { param, data: data[item] }; } const content = '[' + contents.join(',') + ']'; this.callback_message_queue[this.id] = util.createPromiseResultBatch(resolve, reject, arguments_far_calls); diff --git a/lib/electrum_client.js b/lib/electrum_client.js index d88ff79..38e1719 100644 --- a/lib/electrum_client.js +++ b/lib/electrum_client.js @@ -203,7 +203,7 @@ class ElectrumClient extends Client{ return { error: true, data: e }; } } - + /** * @param {Object[]} scripthashes - [{ scriptHash: "", address: "", path: "" }] * @param {string} scripthashes[].scriptHash - The address scripthash. @@ -344,7 +344,7 @@ class ElectrumClient extends Client{ return { error: true, data: e } } } - + requestBatch(method, params, secondParam) { const parentPromise = super.requestBatch(method, params, secondParam); return parentPromise.then(response => response); @@ -361,6 +361,9 @@ class ElectrumClient extends Client{ blockchainTransaction_getBatch(tx_hashes, verbose) { return this.requestBatch('blockchain.transaction.get', tx_hashes, verbose); } + blockchainScripthash_getMempoolBatch(scripthashes){ + return this.requestBatch('blockchain.scripthash.get_mempool', scripthashes); + } } module.exports = ElectrumClient