<p>Actually, there is no need to periodically query the node for the number of confirmations. The number of confirmations is implicitly given by the block height where the transaction was confirmed and the current block height.</p>
<p>The following assumes you store your 100,000+ addresses in a database with reasonably fast lookups, that it can also store additional data, and that you index columns that you use in queries.</p>
<h2>Only confirmed transactions</h2>
<p>The problem is quite simple if you only need to track transactions once they get their first confirmation. Listen for the <code>rawblock</code> ZMQ event, go through all transactions, and whenever a transaction sends to an address you're tracking, add this transaction to the database along with the block height where it was confirmed. Then, if you want perform some action after e.g. 3 confirmations, when a new block arrives, just look up transactions confirmed 3 blocks earlier. Depending on what it is you do, for extra robustness you might want to keep track of which confirmed transactions were already successfully acted upon.</p>
<h2>Unconfirmed transactions</h2>
<p>If you also want to show unconfirmed transactions, it gets more complicated as transactions might get replaced or dropped from your node's mempool. See <a href="https://bitcoin.stackexchange.com/q/114635/121614">this question</a> on how to potentially deal with this. Whatever approach you use, the rest is the same as above.</p>
<h2>Catching up</h2>
<p>If your application has to restart or crashes, you might miss blocks. To guard against this, you can keep track of the last processed block height, and on startup query the node for the current block height. If you find out you're behind, just query the missing blocks (using the <code>getblock</code> RPC) and process them as usual.</p>
<h2>Reorg safety</h2>
<p>There are a few extra steps in order to make your application work correctly in the event of a chain reorganization. An approach I've found to work well is to store a few* recent block headers** (just the hash and height is enough), and when a new block arrives, follow its previous block hash (using the <code>getblockheader</code> RPC) until your database has the same block hash at that height as your node, then rollback any transactions made after that height. If no reorg has happened, the latest common header will just be one block behind the new chaintip, so you won't need to rollback anything.</p>
<p>* If you're not worried about a few tens of MB's of storage, you can just as well store all block headers.<br />
** Storing block headers is also a convenient way of keeping track of what was the last block you processed.</p>

CC BY-SA 4.0
2022-10-31T01:44:21.703Z
2022-10-31T01:44:21.703Z
Vojtěch Strnad
<p>I am designing an exchange application where users can deposit funds into their account by sending BTC to a unique address.</p>
<p>What is the best way to monitor 100,000+ addresses for incoming transactions that meet a certain number of minimum confirmations?</p>
<p>One approach would be to listen to the <em>rawtx</em> event using ZMQ in order to discover new transactions, then write a program to periodically query the number of confirmations for each transaction using JSON-RPC. However, this method seems slow since it would involve repeatedly hammering the node with RPC calls. I do not wish to use external APIs like <a href="https://blockchain.info" rel="nofollow noreferrer">https://blockchain.info</a>.</p>
<p>What would be the most efficient way to accomplish this?</p>

<wallet><bitcoind><json-rpc><zeromq>
Optimal way to design BTC deposit flow?
Bob Grant
# Optimal way to design BTC deposit flow?

(Asked by: username_0 on 2022-10-31)

I am designing an exchange application where users can deposit funds into their account by sending BTC to a unique address.

What is the best way to monitor 100,000+ addresses for incoming transactions that meet a certain number of minimum confirmations?

One approach would be to listen to the *rawtx* event using ZMQ in order to discover new transactions, then write a program to periodically query the number of confirmations for each transaction using JSON-RPC. However, this method seems slow since it would involve repeatedly hammering the node with RPC calls. I do not wish to use external APIs like <https://blockchain.info>.

What would be the most efficient way to accomplish this?

**Tags:** wallet, bitcoind, json-rpc, zeromq


---

## 1 answers

### Answer by username_1 on 2022-10-31. Score: 1 | Accepted answer

Actually, there is no need to periodically query the node for the number of confirmations. The number of confirmations is implicitly given by the block height where the transaction was confirmed and the current block height.

The following assumes you store your 100,000+ addresses in a database with reasonably fast lookups, that it can also store additional data, and that you index columns that you use in queries.

## Only confirmed transactions

The problem is quite simple if you only need to track transactions once they get their first confirmation. Listen for the `rawblock` ZMQ event, go through all transactions, and whenever a transaction sends to an address you're tracking, add this transaction to the database along with the block height where it was confirmed. Then, if you want perform some action after e.g. 3 confirmations, when a new block arrives, just look up transactions confirmed 3 blocks earlier. Depending on what it is you do, for extra robustness you might want to keep track of which confirmed transactions were already successfully acted upon.

## Unconfirmed transactions

If you also want to show unconfirmed transactions, it gets more complicated as transactions might get replaced or dropped from your node's mempool. See [this question](https://bitcoin.stackexchange.com/q/114635/121614) on how to potentially deal with this. Whatever approach you use, the rest is the same as above.

## Catching up

If your application has to restart or crashes, you might miss blocks. To guard against this, you can keep track of the last processed block height, and on startup query the node for the current block height. If you find out you're behind, just query the missing blocks (using the `getblock` RPC) and process them as usual.

## Reorg safety

There are a few extra steps in order to make your application work correctly in the event of a chain reorganization. An approach I've found to work well is to store a few\* recent block headers\*\* (just the hash and height is enough), and when a new block arrives, follow its previous block hash (using the `getblockheader` RPC) until your database has the same block hash at that height as your node, then rollback any transactions made after that height. If no reorg has happened, the latest common header will just be one block behind the new chaintip, so you won't need to rollback anything.

\* If you're not worried about a few tens of MB's of storage, you can just as well store all block headers.  
\*\* Storing block headers is also a convenient way of keeping track of what was the last block you processed.


---

