Support multi address websocket subscriptions

This commit is contained in:
Mononaut 2023-08-07 10:52:40 +09:00
parent de7db08ae3
commit 57c3861ca6
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
2 changed files with 72 additions and 0 deletions

View File

@ -24,6 +24,12 @@ import { ApiPrice } from '../repositories/PricesRepository';
import accelerationApi from './services/acceleration';
import mempool from './mempool';
interface AddressTransactions {
mempool: MempoolTransactionExtended[],
confirmed: MempoolTransactionExtended[],
removed: string[],
}
// valid 'want' subscriptions
const wantable = [
'blocks',
@ -213,6 +219,32 @@ class WebsocketHandler {
}
}
if (parsedMessage && parsedMessage['track-addresses'] && Array.isArray(parsedMessage['track-addresses'])) {
const addressMap: { [address: string]: string } = {};
for (const address of parsedMessage['track-addresses']) {
if (/^([a-km-zA-HJ-NP-Z1-9]{26,35}|[a-km-zA-HJ-NP-Z1-9]{80}|[a-z]{2,5}1[ac-hj-np-z02-9]{8,100}|[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100}|04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64})$/.test(address)) {
let matchedAddress = address;
if (/^[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100}$/.test(address)) {
matchedAddress = matchedAddress.toLowerCase();
}
if (/^04[a-fA-F0-9]{128}$/.test(address)) {
addressMap[address] = '41' + matchedAddress + 'ac';
} else if (/^(02|03)[a-fA-F0-9]{64}$/.test(address)) {
addressMap[address] = '21' + matchedAddress + 'ac';
} else {
addressMap[address] = matchedAddress;
}
} else {
// skip invalid address formats
}
}
if (Object.keys(addressMap).length > 0) {
client['track-addresses'] = addressMap;
} else {
client['track-addresses'] = null;
}
}
if (parsedMessage && parsedMessage['track-asset']) {
if (/^[a-fA-F0-9]{64}$/.test(parsedMessage['track-asset'])) {
client['track-asset'] = parsedMessage['track-asset'];
@ -544,6 +576,27 @@ class WebsocketHandler {
}
}
if (client['track-addresses']) {
const addressMap: { [address: string]: AddressTransactions } = {};
for (const [address, key] of Object.entries(client['track-addresses'] || {})) {
const foundTransactions = Array.from(addressCache[key 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) {
addressMap[address] = {
mempool: fullTransactions,
confirmed: [],
removed: [],
};
}
}
if (Object.keys(addressMap).length > 0) {
response['multi-address-transactions'] = JSON.stringify(addressMap);
}
}
if (client['track-asset']) {
const foundTransactions: TransactionExtended[] = [];
@ -843,6 +896,24 @@ class WebsocketHandler {
}
}
if (client['track-addresses']) {
const addressMap: { [address: string]: AddressTransactions } = {};
for (const [address, key] of Object.entries(client['track-addresses'] || {})) {
const fullTransactions = Array.from(addressCache[key as string]?.values() || []);
if (fullTransactions?.length) {
addressMap[address] = {
mempool: [],
confirmed: fullTransactions,
removed: [],
};
}
}
if (Object.keys(addressMap).length > 0) {
response['multi-address-transactions'] = JSON.stringify(addressMap);
}
}
if (client['track-asset']) {
const foundTransactions: TransactionExtended[] = [];

View File

@ -27,6 +27,7 @@ export interface WebsocketResponse {
fees?: Recommendedfees;
'track-tx'?: string;
'track-address'?: string;
'track-addresses'?: string[];
'track-asset'?: string;
'track-mempool-block'?: number;
'track-rbf'?: string;