UNPKG

@node-dlc/chainmon

Version:
103 lines (90 loc) 2.79 kB
import { OutPoint, Script, Tx, Value } from '@node-dlc/bitcoin'; import { BitcoindClient } from '@node-dlc/bitcoind'; import { EventEmitter } from 'events'; export class TxWatcher extends EventEmitter { /** * Outpoints that are being watched */ public watchedOutPoints: Map<string, OutPoint>; /** * ScriptPubKeys that are being watched */ public watchedScriptPubKeys: Map<string, [Script, Value]>; private _client: BitcoindClient; /** * TxWatcher listens for transactions that match certain patterns * and events when a transaction is found matching the pattern * * @param client */ constructor(client: BitcoindClient) { super(); this._client = client; this.watchedOutPoints = new Map<string, OutPoint>(); this.watchedScriptPubKeys = new Map<string, [Script, Value]>(); } /** * Starts watching for transactions */ public start(): void { this._client.subscribeRawTx(); this._client.on('rawtx', this._onRawTx.bind(this)); } /** * Stops watching for transactions */ public stop(): void { // this._client.close(); } /** * Watches an outpoint for broadcase in a new transaction * @param outpoint */ public watchOutpoint(outpoint: OutPoint): void { const key = outpoint.toString(); this.watchedOutPoints.set(key, outpoint); } /** * Watches a scriptpubkey for broadcast in a new transaction * @param scriptPubKey * @param value */ public watchScriptPubKey(scriptPubKey: Script, value?: Value): void { const key = scriptPubKey.toString(); this.watchedScriptPubKeys.set(key, [scriptPubKey, value]); } //////////////////////////////////////////////////////////////// private _checkOutpoints(tx: Tx) { for (const vin of tx.inputs) { const key = vin.outpoint.toString(); const watchedOutpoint = this.watchedOutPoints.get(key); if (watchedOutpoint) { this.watchedOutPoints.delete(key); this.emit('outpointspent', tx, watchedOutpoint); } } } private _checkScriptPubkeys(tx: Tx) { for (const vout of tx.outputs) { const key = vout.scriptPubKey.toString(); const watchedScriptPubKey = this.watchedScriptPubKeys.get(key); if (watchedScriptPubKey) { const [, value] = watchedScriptPubKey; if (!value || (value && vout.value === value)) { this.watchedScriptPubKeys.delete(key); this.emit('scriptpubkeyreceived', tx, watchedScriptPubKey); } } } } private _onRawTx(buf: Buffer) { try { const tx = Tx.fromBuffer(buf); this.emit('tx', tx); this._checkOutpoints(tx); this._checkScriptPubkeys(tx); } catch (e) { console.error('Failed to deserialize tx', buf.toString('hex')); } } }