UNPKG

@samouraiwallet/electrum-client

Version:
265 lines 10.5 kB
import { Client } from "./lib/client.js"; export class ElectrumClient extends Client { /** * Constructs an instance of ElectrumClient. * * @param {number} port - The port number to connect to. * @param {string} host - The host address to connect to. * @param {Protocol} protocol - The protocol to use for the connection. * @param {Callbacks} [callbacks] - Optional callbacks for connection events. */ constructor(port, host, protocol, callbacks) { super(port, host, protocol, callbacks); this.onConnectCallback = callbacks?.onConnect ?? null; this.onCloseCallback = callbacks?.onClose ?? null; this.onLogCallback = callbacks?.onLog ? callbacks.onLog : (str) => { console.log(str); }; this.timeLastCall = 0; this.persistencePolicy = { retryPeriod: 10000, maxRetry: 1000, pingPeriod: 120000, callback: null, }; this.electrumConfig = null; this.pingInterval = null; this.versionInfo = ["", ""]; } /** * Creates an instance of ElectrumClient and initializes it with the provided configuration. * * @param {CreateClientParams} params - The parameters required to create and initialize the client. * @param {number} params.port - The port number to connect to. * @param {string} params.host - The host address to connect to. * @param {Protocol} params.protocol - The protocol to use for the connection. * @param {Callbacks} [params.callbacks] - Optional callbacks for connection events. * @param {ElectrumConfig} params.electrumConfig - The Electrum configuration to use. * @param {PersistencePolicy} [params.persistencePolicy] - Optional persistence policy for the client. * * @returns {Promise<ElectrumClient>} A promise that resolves to an initialized ElectrumClient instance. */ static createClient(params) { const client = new ElectrumClient(params.port, params.host, params.protocol, params.callbacks); return client.initElectrum(params.electrumConfig, params.persistencePolicy); } /** * Initializes the Electrum client with the provided configuration and persistence policy. * * @param {ElectrumConfig} electrumConfig - The Electrum configuration to use. * @param {PersistencePolicy} [persistencePolicy] - Optional persistence policy for the client. * @returns {Promise<ElectrumClient>} A promise that resolves to the initialized ElectrumClient instance. */ async initElectrum(electrumConfig, persistencePolicy) { this.persistencePolicy = { ...this.persistencePolicy, ...persistencePolicy, }; this.electrumConfig = electrumConfig; this.timeLastCall = 0; await this.connect(); this.versionInfo = (await this.server_version(electrumConfig.client, electrumConfig.version)); if (this.onConnectCallback != null) { this.onConnectCallback(this, this.versionInfo); } return this; } async request(method, params) { this.timeLastCall = Date.now(); const response = await super.request(method, params); this.keepAlive(); return response; } async requestBatch(method, params, secondParam) { this.timeLastCall = Date.now(); const response = await super.requestBatch(method, params, secondParam); this.keepAlive(); return response; } onClose() { super.onClose(); const list = [ "server.peers.subscribe", "blockchain.numblocks.subscribe", "blockchain.headers.subscribe", "blockchain.address.subscribe", ]; for (const event of list) this.subscribe.removeAllListeners(event); let retryPeriod = 10000; if (this.persistencePolicy.retryPeriod > 0) { retryPeriod = this.persistencePolicy.retryPeriod; } if (this.onCloseCallback != null) { this.onCloseCallback(this); } setTimeout(() => { if (this.persistencePolicy.maxRetry > 0) { this.reconnect().catch((error) => { this.onError(error); }); this.persistencePolicy.maxRetry -= 1; } else if (this.persistencePolicy.callback != null) { this.persistencePolicy.callback(); } }, retryPeriod); } keepAlive() { if (this.pingInterval != null) { clearInterval(this.pingInterval); } let pingPeriod = 120000; if (this.persistencePolicy.pingPeriod > 0) { pingPeriod = this.persistencePolicy.pingPeriod; } this.pingInterval = setInterval(() => { if (this.timeLastCall !== 0 && Date.now() > this.timeLastCall + pingPeriod) { this.server_ping().catch((error) => { this.log(`Keep-Alive ping failed: ${error}`); }); } }, pingPeriod); } /** * Closes the Electrum client connection and stops the keep-alive ping interval. * * @returns {void} */ close() { super.close(); if (this.pingInterval != null) { clearInterval(this.pingInterval); } this.reconnect = this.reconnect = this.onClose = this.keepAlive = () => Promise.resolve(this); // dirty hack to make it stop reconnecting } reconnect() { this.log("Electrum attempting reconnect..."); this.initSocket(); return this.persistencePolicy == null ? // biome-ignore lint/style/noNonNullAssertion: this.initElectrum(this.electrumConfig) : // biome-ignore lint/style/noNonNullAssertion: this.initElectrum(this.electrumConfig, this.persistencePolicy); } log(str) { this.onLogCallback(str); } // ElectrumX API server_version(client_name, protocol_version) { return this.request("server.version", [client_name, protocol_version]); } server_banner() { return this.request("server.banner", []); } server_features() { return this.request("server.features", []); } server_ping() { return this.request("server.ping", []); } server_addPeer(features) { return this.request("server.add_peer", [features]); } serverDonation_address() { return this.request("server.donation_address", []); } serverPeers_subscribe() { return this.request("server.peers.subscribe", []); } blockchainAddress_getProof(address) { return this.request("blockchain.address.get_proof", [address]); } blockchainScripthash_getBalance(scripthash) { return this.request("blockchain.scripthash.get_balance", [scripthash]); } blockchainScripthash_getBalanceBatch(scripthashes) { return this.requestBatch("blockchain.scripthash.get_balance", scripthashes); } blockchainScripthash_listunspentBatch(scripthashes) { return this.requestBatch("blockchain.scripthash.listunspent", scripthashes); } blockchainScripthash_getHistory(scripthash) { return this.request("blockchain.scripthash.get_history", [scripthash]); } blockchainScripthash_getHistoryBatch(scripthashes) { return this.requestBatch("blockchain.scripthash.get_history", scripthashes); } blockchainScripthash_getMempool(scripthash) { return this.request("blockchain.scripthash.get_mempool", [scripthash]); } blockchainScripthash_listunspent(scripthash) { return this.request("blockchain.scripthash.listunspent", [scripthash]); } blockchainScripthash_subscribe(scripthash) { return this.request("blockchain.scripthash.subscribe", [scripthash]); } blockchainBlock_getHeader(height) { return this.request("blockchain.block.get_header", [height]); } blockchainBlock_headers(start_height, count) { return this.request("blockchain.block.headers", [start_height, count]); } blockchainEstimatefee(number) { return this.request("blockchain.estimatefee", [number]); } blockchainHeaders_subscribe() { return this.request("blockchain.headers.subscribe", []); } blockchain_relayfee() { return this.request("blockchain.relayfee", []); } blockchainTransaction_broadcast(rawtx) { return this.request("blockchain.transaction.broadcast", [rawtx]); } blockchainTransaction_get(tx_hash, verbose = false) { return this.request("blockchain.transaction.get", [tx_hash, verbose]); } blockchainTransaction_getBatch(tx_hashes, verbose = false) { return this.requestBatch("blockchain.transaction.get", tx_hashes, verbose); } blockchainTransaction_getMerkle(tx_hash, height) { return this.request("blockchain.transaction.get_merkle", [tx_hash, height]); } mempool_getFeeHistogram() { return this.request("mempool.get_fee_histogram", []); } // --------------------------------- // protocol 1.1 deprecated method // --------------------------------- blockchainUtxo_getAddress(tx_hash, index) { return this.request("blockchain.utxo.get_address", [tx_hash, index]); } blockchainNumblocks_subscribe() { return this.request("blockchain.numblocks.subscribe", []); } // --------------------------------- // protocol 1.2 deprecated method // --------------------------------- blockchainBlock_getChunk(index) { return this.request("blockchain.block.get_chunk", [index]); } blockchainAddress_getBalance(address) { return this.request("blockchain.address.get_balance", [address]); } blockchainAddress_getHistory(address) { return this.request("blockchain.address.get_history", [address]); } blockchainAddress_getMempool(address) { return this.request("blockchain.address.get_mempool", [address]); } blockchainAddress_listunspent(address) { return this.request("blockchain.address.listunspent", [address]); } blockchainAddress_subscribe(address) { return this.request("blockchain.address.subscribe", [address]); } } //# sourceMappingURL=index.js.map