From 8642956dc2bd9583374b6e57092ae0576224f0f0 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Mon, 7 Aug 2023 14:13:41 +0900 Subject: [PATCH] Add track-scriptpubkeys websocket subscription --- backend/src/api/websocket-handler.ts | 53 +++++++++++++++++++ .../src/app/interfaces/websocket.interface.ts | 1 + 2 files changed, 54 insertions(+) diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index c0493d6c1..e20e41014 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -245,6 +245,20 @@ class WebsocketHandler { } } + if (parsedMessage && parsedMessage['track-scriptpubkeys'] && Array.isArray(parsedMessage['track-scriptpubkeys'])) { + const spks: string[] = []; + for (const spk of parsedMessage['track-scriptpubkeys']) { + if (/^[a-fA-F0-9]+$/.test(spk)) { + spks.push(spk); + } + } + if (spks.length) { + client['track-scriptpubkeys'] = spks; + } else { + client['track-scriptpubkeys'] = null; + } + } + if (parsedMessage && parsedMessage['track-asset']) { if (/^[a-fA-F0-9]{64}$/.test(parsedMessage['track-asset'])) { client['track-asset'] = parsedMessage['track-asset']; @@ -597,6 +611,27 @@ class WebsocketHandler { } } + if (client['track-scriptpubkeys']) { + const spkMap: { [spk: string]: AddressTransactions } = {}; + for (const spk of client['track-scriptpubkeys'] || []) { + const foundTransactions = Array.from(addressCache[spk as string]?.values() || []); + // txs may be missing prevouts in non-esplora backends + // so fetch the full transactions now + const fullTransactions = (config.MEMPOOL.BACKEND !== 'esplora') ? await this.getFullTransactions(foundTransactions) : foundTransactions; + if (fullTransactions?.length) { + spkMap[spk] = { + mempool: fullTransactions, + confirmed: [], + removed: [], + }; + } + } + + if (Object.keys(spkMap).length > 0) { + response['multi-scriptpubkey-transactions'] = JSON.stringify(spkMap); + } + } + if (client['track-asset']) { const foundTransactions: TransactionExtended[] = []; @@ -914,6 +949,24 @@ class WebsocketHandler { } } + if (client['track-scriptpubkeys']) { + const spkMap: { [spk: string]: AddressTransactions } = {}; + for (const spk of client['track-scriptpubkeys'] || []) { + const fullTransactions = Array.from(addressCache[spk as string]?.values() || []); + if (fullTransactions?.length) { + spkMap[spk] = { + mempool: [], + confirmed: fullTransactions, + removed: [], + }; + } + } + + if (Object.keys(spkMap).length > 0) { + response['multi-scriptpubkey-transactions'] = JSON.stringify(spkMap); + } + } + if (client['track-asset']) { const foundTransactions: TransactionExtended[] = []; diff --git a/frontend/src/app/interfaces/websocket.interface.ts b/frontend/src/app/interfaces/websocket.interface.ts index fb488e705..35bcbe9cc 100644 --- a/frontend/src/app/interfaces/websocket.interface.ts +++ b/frontend/src/app/interfaces/websocket.interface.ts @@ -28,6 +28,7 @@ export interface WebsocketResponse { 'track-tx'?: string; 'track-address'?: string; 'track-addresses'?: string[]; + 'track-scriptpubkeys'?: string[]; 'track-asset'?: string; 'track-mempool-block'?: number; 'track-rbf'?: string;