I'm looking to replicate the functionality provided by cryptocurrency exchanges such as Kraken and Poloniex when it comes to depositing ETH and tokens. Namely:
- Users can generate and send funds to one or more deposit addresses for ETH, EOS, OMG, and other tokens
- The relevant user's balance is updated when a deposit is detected for a given token or asset
- Sent funds are stored in accounts controlled by the exchange
What's the best way to achieve this?
I have a few ideas using web3, but I'm not sure they're the most efficient or scalable solutions:
ETH
- For each user who wants to make a deposit, generate an ETH address and private key using
web3.eth.accounts.create()
. Map the generated address to the user and store the private key. - Use
web3.eth.filter
to monitor the latest block on the ETH blockchain. Match transactions in the block against the user addresses stored and update user balances as appropriate.
Issues with this approach: monitoring each block and matching against stored addresses is computationally intensive especially if the number of addresses tracked becomes large (hundreds of thousands). How can this scale?
ERC20 Tokens
- For each user who wants to make a deposit, generate an ETH address and private key using
web3.eth.accounts.create()
. Map the generated address to the user and relevant token, and store the private key. - ERC20 contracts emit
Transfer
events when a transaction happens on the contract. Monitor this event usingweb3.eth.filter
. When aTransfer
event occurs for an address that exists in our database, update the relevant user's balance on the exchange with the transferred amount.
Issues with this approach: How do you set up the web3 filter to detect Transfer
events only from the token in question, not the entire network? Should I set up 1 filter per address, or 1 filter for all user addresses? How many addresses can web3 filter track at a time? What if the tracked addresses become very high (hundreds of thousands)?
Is this the right way to think about all this or am I missing something? I'm surprised there isn't more obvious documentation around this flow since it's quite popular (in exchanges and any other service that accepts digital currency payments).
Best Answer
It'd probably go something like this:
User wants to deposit a token to your exchange
If it's the first time the user is depositing that token then this occurs:
Next time they hit the deposit button to get the deposit address you'll already have a unique deposit address for the user stored in the database that you can present to the user
The user deposits token to the deposit address
Call the token contracts balanceOf method passing it the deposit address you've generated tied to the user in order to display the users token balance in the exchange. You only display that particular token balance and nothing else for that address.
The user wants to withdraw their token