Inform client when Electrum server limit exceeded

This commit is contained in:
softsimon 2021-01-05 17:30:53 +07:00
parent 1a6c2e79e6
commit f46728080d
No known key found for this signature in database
GPG Key ID: 488D7DCFB5A430D7
3 changed files with 70 additions and 42 deletions

View File

@ -83,29 +83,35 @@ class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
}); });
} }
const balance = await this.$getScriptHashBalance(addressInfo.scriptPubKey); try {
const history = await this.$getScriptHashHistory(addressInfo.scriptPubKey); const balance = await this.$getScriptHashBalance(addressInfo.scriptPubKey);
const history = await this.$getScriptHashHistory(addressInfo.scriptPubKey);
const unconfirmed = history.filter((h) => h.fee).length; const unconfirmed = history.filter((h) => h.fee).length;
return { return {
'address': addressInfo.address, 'address': addressInfo.address,
'chain_stats': { 'chain_stats': {
'funded_txo_count': 0, 'funded_txo_count': 0,
'funded_txo_sum': balance.confirmed ? balance.confirmed : 0, 'funded_txo_sum': balance.confirmed ? balance.confirmed : 0,
'spent_txo_count': 0, 'spent_txo_count': 0,
'spent_txo_sum': balance.confirmed < 0 ? balance.confirmed : 0, 'spent_txo_sum': balance.confirmed < 0 ? balance.confirmed : 0,
'tx_count': history.length - unconfirmed, 'tx_count': history.length - unconfirmed,
}, },
'mempool_stats': { 'mempool_stats': {
'funded_txo_count': 0, 'funded_txo_count': 0,
'funded_txo_sum': balance.unconfirmed > 0 ? balance.unconfirmed : 0, 'funded_txo_sum': balance.unconfirmed > 0 ? balance.unconfirmed : 0,
'spent_txo_count': 0, 'spent_txo_count': 0,
'spent_txo_sum': balance.unconfirmed < 0 ? -balance.unconfirmed : 0, 'spent_txo_sum': balance.unconfirmed < 0 ? -balance.unconfirmed : 0,
'tx_count': unconfirmed, 'tx_count': unconfirmed,
}
};
} catch (e) {
if (e === 'failed to get confirmed status') {
e = 'The number of transactions on this address exceeds the Electrum server limit';
} }
}; throw new Error(e);
}
} }
async $getAddressTransactions(address: string, lastSeenTxId: string): Promise<IEsploraApi.Transaction[]> { async $getAddressTransactions(address: string, lastSeenTxId: string): Promise<IEsploraApi.Transaction[]> {
@ -113,26 +119,34 @@ class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
if (!addressInfo || !addressInfo.isvalid) { if (!addressInfo || !addressInfo.isvalid) {
return []; return [];
} }
const transactions: IEsploraApi.Transaction[] = [];
const history = await this.$getScriptHashHistory(addressInfo.scriptPubKey);
history.reverse();
let startingIndex = 0; try {
if (lastSeenTxId) { const transactions: IEsploraApi.Transaction[] = [];
const pos = history.findIndex((historicalTx) => historicalTx.tx_hash === lastSeenTxId); const history = await this.$getScriptHashHistory(addressInfo.scriptPubKey);
if (pos) { history.reverse();
startingIndex = pos + 1;
let startingIndex = 0;
if (lastSeenTxId) {
const pos = history.findIndex((historicalTx) => historicalTx.tx_hash === lastSeenTxId);
if (pos) {
startingIndex = pos + 1;
}
} }
}
for (let i = startingIndex; i < Math.min(startingIndex + 10, history.length); i++) { for (let i = startingIndex; i < Math.min(startingIndex + 10, history.length); i++) {
const tx = await this.$getRawTransaction(history[i].tx_hash, false, true); const tx = await this.$getRawTransaction(history[i].tx_hash, false, true);
if (tx) { if (tx) {
transactions.push(tx); transactions.push(tx);
}
} }
}
return transactions; return transactions;
} catch (e) {
if (e === 'failed to get confirmed status') {
e = 'The number of transactions on this address exceeds the Electrum server limit';
}
throw new Error(e);
}
} }
private $getScriptHashBalance(scriptHash: string): Promise<IElectrumApi.ScriptHashBalance> { private $getScriptHashBalance(scriptHash: string): Promise<IElectrumApi.ScriptHashBalance> {

View File

@ -538,7 +538,7 @@ class Routes {
res.status(500).send('Error fetching transaction.'); res.status(500).send('Error fetching transaction.');
} }
} catch (e) { } catch (e) {
res.status(500).send(e.message); res.status(500).send(e.message || e);
} }
} }
@ -547,7 +547,7 @@ class Routes {
const result = await bitcoinApi.$getBlock(req.params.hash); const result = await bitcoinApi.$getBlock(req.params.hash);
res.json(result); res.json(result);
} catch (e) { } catch (e) {
res.status(500).send(e.message); res.status(500).send(e.message || e);
} }
} }
@ -580,7 +580,7 @@ class Routes {
res.json(returnBlocks); res.json(returnBlocks);
} catch (e) { } catch (e) {
res.status(500).send(e.message); res.status(500).send(e.message || e);
} }
} }
@ -598,7 +598,7 @@ class Routes {
} }
res.json(transactions); res.json(transactions);
} catch (e) { } catch (e) {
res.status(500).send(e.message); res.status(500).send(e.message || e);
} }
} }
@ -607,7 +607,7 @@ class Routes {
const blockHash = await bitcoinApi.$getBlockHash(parseInt(req.params.height, 10)); const blockHash = await bitcoinApi.$getBlockHash(parseInt(req.params.height, 10));
res.send(blockHash); res.send(blockHash);
} catch (e) { } catch (e) {
res.status(500).send(e.message); res.status(500).send(e.message || e);
} }
} }
@ -621,7 +621,10 @@ class Routes {
const addressData = await bitcoinApi.$getAddress(req.params.address); const addressData = await bitcoinApi.$getAddress(req.params.address);
res.json(addressData); res.json(addressData);
} catch (e) { } catch (e) {
res.status(500).send(e.message); if (e.message && e.message.indexOf('exceeds') > 0) {
return res.status(413).send(e.message);
}
res.status(500).send(e.message || e);
} }
} }
@ -635,7 +638,10 @@ class Routes {
const transactions = await bitcoinApi.$getAddressTransactions(req.params.address, req.params.txId); const transactions = await bitcoinApi.$getAddressTransactions(req.params.address, req.params.txId);
res.json(transactions); res.json(transactions);
} catch (e) { } catch (e) {
res.status(500).send(e.message); if (e.message && e.message.indexOf('exceeds') > 0) {
return res.status(413).send(e.message);
}
res.status(500).send(e.message || e);
} }
} }

View File

@ -105,6 +105,14 @@
<span i18n="address.error.loading-address-data">Error loading address data.</span> <span i18n="address.error.loading-address-data">Error loading address data.</span>
<br> <br>
<i>{{ error.error }}</i> <i>{{ error.error }}</i>
<ng-template [ngIf]="error.status === 413">
<br><br>
Consider view this address on the official Mempool website instead:
<br>
<a href="https://mempool.space/address/{{ addressString }}" target="_blank">https://mempool.space/address/{{ addressString }}</a>
<br>
<a href="http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/address/{{ addressString }}" target="_blank">http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/address/{{ addressString }}</a>
</ng-template>
</div> </div>
</ng-template> </ng-template>