precompute address transactions for websocket msg loop
This commit is contained in:
parent
cac2a984ab
commit
3074d814e7
@ -192,7 +192,7 @@ class WebsocketHandler {
|
|||||||
if (/^04[a-fA-F0-9]{128}$/.test(parsedMessage['track-address'])) {
|
if (/^04[a-fA-F0-9]{128}$/.test(parsedMessage['track-address'])) {
|
||||||
client['track-address'] = null;
|
client['track-address'] = null;
|
||||||
client['track-scriptpubkey'] = '41' + matchedAddress + 'ac';
|
client['track-scriptpubkey'] = '41' + matchedAddress + 'ac';
|
||||||
} else if (/^|(02|03)[a-fA-F0-9]{64}$/.test(parsedMessage['track-address'])) {
|
} else if (/^(02|03)[a-fA-F0-9]{64}$/.test(parsedMessage['track-address'])) {
|
||||||
client['track-address'] = null;
|
client['track-address'] = null;
|
||||||
client['track-scriptpubkey'] = '21' + matchedAddress + 'ac';
|
client['track-scriptpubkey'] = '21' + matchedAddress + 'ac';
|
||||||
} else {
|
} else {
|
||||||
@ -480,6 +480,9 @@ class WebsocketHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pre-compute address transactions
|
||||||
|
const addressCache = this.makeAddressCache(newTransactions);
|
||||||
|
|
||||||
this.wss.clients.forEach(async (client) => {
|
this.wss.clients.forEach(async (client) => {
|
||||||
if (client.readyState !== WebSocket.OPEN) {
|
if (client.readyState !== WebSocket.OPEN) {
|
||||||
return;
|
return;
|
||||||
@ -519,78 +522,23 @@ class WebsocketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (client['track-address']) {
|
if (client['track-address']) {
|
||||||
const foundTransactions: TransactionExtended[] = [];
|
const foundTransactions = Array.from(addressCache[client['track-address']]?.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;
|
||||||
|
|
||||||
for (const tx of newTransactions) {
|
if (fullTransactions.length) {
|
||||||
const someVin = tx.vin.some((vin) => !!vin.prevout && vin.prevout.scriptpubkey_address === client['track-address']);
|
response['address-transactions'] = JSON.stringify(fullTransactions);
|
||||||
if (someVin) {
|
|
||||||
if (config.MEMPOOL.BACKEND !== 'esplora') {
|
|
||||||
try {
|
|
||||||
const fullTx = await transactionUtils.$getMempoolTransactionExtended(tx.txid, true);
|
|
||||||
foundTransactions.push(fullTx);
|
|
||||||
} catch (e) {
|
|
||||||
logger.debug('Error finding transaction in mempool: ' + (e instanceof Error ? e.message : e));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const someVout = tx.vout.some((vout) => vout.scriptpubkey_address === client['track-address']);
|
|
||||||
if (someVout) {
|
|
||||||
if (config.MEMPOOL.BACKEND !== 'esplora') {
|
|
||||||
try {
|
|
||||||
const fullTx = await transactionUtils.$getMempoolTransactionExtended(tx.txid, true);
|
|
||||||
foundTransactions.push(fullTx);
|
|
||||||
} catch (e) {
|
|
||||||
logger.debug('Error finding transaction in mempool: ' + (e instanceof Error ? e.message : e));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundTransactions.length) {
|
|
||||||
response['address-transactions'] = JSON.stringify(foundTransactions);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client['track-scriptpubkey']) {
|
if (client['track-scriptpubkey']) {
|
||||||
const foundTransactions: TransactionExtended[] = [];
|
const foundTransactions = Array.from(addressCache[client['track-address']]?.values() || []);
|
||||||
|
// txs may be missing prevouts in non-esplora backends
|
||||||
for (const tx of newTransactions) {
|
// so fetch the full transactions now
|
||||||
const someVin = tx.vin.some((vin) => !!vin.prevout && vin.prevout.scriptpubkey_type === 'p2pk' && vin.prevout.scriptpubkey === client['track-scriptpubkey']);
|
const fullTransactions = (config.MEMPOOL.BACKEND !== 'esplora') ? await this.getFullTransactions(foundTransactions) : foundTransactions;
|
||||||
if (someVin) {
|
|
||||||
if (config.MEMPOOL.BACKEND !== 'esplora') {
|
|
||||||
try {
|
|
||||||
const fullTx = await transactionUtils.$getMempoolTransactionExtended(tx.txid, true);
|
|
||||||
foundTransactions.push(fullTx);
|
|
||||||
} catch (e) {
|
|
||||||
logger.debug('Error finding transaction in mempool: ' + (e instanceof Error ? e.message : e));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const someVout = tx.vout.some((vout) => vout.scriptpubkey_type === 'p2pk' && vout.scriptpubkey === client['track-scriptpubkey']);
|
|
||||||
if (someVout) {
|
|
||||||
if (config.MEMPOOL.BACKEND !== 'esplora') {
|
|
||||||
try {
|
|
||||||
const fullTx = await transactionUtils.$getMempoolTransactionExtended(tx.txid, true);
|
|
||||||
foundTransactions.push(fullTx);
|
|
||||||
} catch (e) {
|
|
||||||
logger.debug('Error finding transaction in mempool: ' + (e instanceof Error ? e.message : e));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundTransactions.length) {
|
if (foundTransactions.length) {
|
||||||
response['address-transactions'] = JSON.stringify(foundTransactions);
|
response['address-transactions'] = JSON.stringify(fullTransactions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,7 +546,6 @@ class WebsocketHandler {
|
|||||||
const foundTransactions: TransactionExtended[] = [];
|
const foundTransactions: TransactionExtended[] = [];
|
||||||
|
|
||||||
newTransactions.forEach((tx) => {
|
newTransactions.forEach((tx) => {
|
||||||
|
|
||||||
if (client['track-asset'] === Common.nativeAssetId) {
|
if (client['track-asset'] === Common.nativeAssetId) {
|
||||||
if (tx.vin.some((vin) => !!vin.is_pegin)) {
|
if (tx.vin.some((vin) => !!vin.is_pegin)) {
|
||||||
foundTransactions.push(tx);
|
foundTransactions.push(tx);
|
||||||
@ -784,6 +731,9 @@ class WebsocketHandler {
|
|||||||
const fees = feeApi.getRecommendedFee();
|
const fees = feeApi.getRecommendedFee();
|
||||||
const mempoolInfo = memPool.getMempoolInfo();
|
const mempoolInfo = memPool.getMempoolInfo();
|
||||||
|
|
||||||
|
// pre-compute address transactions
|
||||||
|
const addressCache = this.makeAddressCache(transactions);
|
||||||
|
|
||||||
// update init data
|
// update init data
|
||||||
this.updateSocketDataFields({
|
this.updateSocketDataFields({
|
||||||
'mempoolInfo': mempoolInfo,
|
'mempoolInfo': mempoolInfo,
|
||||||
@ -843,17 +793,7 @@ class WebsocketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (client['track-address']) {
|
if (client['track-address']) {
|
||||||
const foundTransactions: TransactionExtended[] = [];
|
const foundTransactions: TransactionExtended[] = Array.from(addressCache[client['track-address']]?.values() || []);
|
||||||
|
|
||||||
transactions.forEach((tx) => {
|
|
||||||
if (tx.vin && tx.vin.some((vin) => !!vin.prevout && vin.prevout.scriptpubkey_address === client['track-address'])) {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tx.vout && tx.vout.some((vout) => vout.scriptpubkey_address === client['track-address'])) {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (foundTransactions.length) {
|
if (foundTransactions.length) {
|
||||||
foundTransactions.forEach((tx) => {
|
foundTransactions.forEach((tx) => {
|
||||||
@ -870,17 +810,7 @@ class WebsocketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (client['track-scriptpubkey']) {
|
if (client['track-scriptpubkey']) {
|
||||||
const foundTransactions: TransactionExtended[] = [];
|
const foundTransactions: TransactionExtended[] = Array.from(addressCache[client['track-scriptpubkey']]?.values() || []);
|
||||||
|
|
||||||
transactions.forEach((tx) => {
|
|
||||||
if (tx.vin && tx.vin.some((vin) => !!vin.prevout && vin.prevout.scriptpubkey_type === 'p2pk' && vin.prevout.scriptpubkey === client['track-scriptpubkey'])) {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tx.vout && tx.vout.some((vout) => vout.scriptpubkey_type === 'p2pk' && vout.scriptpubkey === client['track-scriptpubkey'])) {
|
|
||||||
foundTransactions.push(tx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (foundTransactions.length) {
|
if (foundTransactions.length) {
|
||||||
foundTransactions.forEach((tx) => {
|
foundTransactions.forEach((tx) => {
|
||||||
@ -958,6 +888,52 @@ class WebsocketHandler {
|
|||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private makeAddressCache(transactions: MempoolTransactionExtended[]): { [address: string]: Set<MempoolTransactionExtended> } {
|
||||||
|
const addressCache: { [address: string]: Set<MempoolTransactionExtended> } = {};
|
||||||
|
for (const tx of transactions) {
|
||||||
|
for (const vin of tx.vin) {
|
||||||
|
if (vin?.prevout?.scriptpubkey_address) {
|
||||||
|
if (!addressCache[vin.prevout.scriptpubkey_address]) {
|
||||||
|
addressCache[vin.prevout.scriptpubkey_address] = new Set();
|
||||||
|
}
|
||||||
|
addressCache[vin.prevout.scriptpubkey_address].add(tx);
|
||||||
|
}
|
||||||
|
if (vin?.prevout?.scriptpubkey) {
|
||||||
|
if (!addressCache[vin.prevout.scriptpubkey]) {
|
||||||
|
addressCache[vin.prevout.scriptpubkey] = new Set();
|
||||||
|
}
|
||||||
|
addressCache[vin.prevout.scriptpubkey].add(tx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const vout of tx.vout) {
|
||||||
|
if (vout?.scriptpubkey_address) {
|
||||||
|
if (!addressCache[vout?.scriptpubkey_address]) {
|
||||||
|
addressCache[vout?.scriptpubkey_address] = new Set();
|
||||||
|
}
|
||||||
|
addressCache[vout?.scriptpubkey_address].add(tx);
|
||||||
|
}
|
||||||
|
if (vout?.scriptpubkey) {
|
||||||
|
if (!addressCache[vout.scriptpubkey]) {
|
||||||
|
addressCache[vout.scriptpubkey] = new Set();
|
||||||
|
}
|
||||||
|
addressCache[vout.scriptpubkey].add(tx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addressCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getFullTransactions(transactions: MempoolTransactionExtended[]): Promise<MempoolTransactionExtended[]> {
|
||||||
|
for (let i = 0; i < transactions.length; i++) {
|
||||||
|
try {
|
||||||
|
transactions[i] = await transactionUtils.$getMempoolTransactionExtended(transactions[i].txid, true);
|
||||||
|
} catch (e) {
|
||||||
|
logger.debug('Error finding transaction in mempool: ' + (e instanceof Error ? e.message : e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return transactions;
|
||||||
|
}
|
||||||
|
|
||||||
private printLogs(): void {
|
private printLogs(): void {
|
||||||
if (this.wss) {
|
if (this.wss) {
|
||||||
const count = this.wss?.clients?.size || 0;
|
const count = this.wss?.clients?.size || 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user