In this series of articles, I’m doing a walkthrough of a hobby project I’ve worked on, a payment system for the Ethereum blockchain. You can read the intro article for more context about the project.
I have covered the majority of the technical details in parts one through three. In this fourth and final part, I will to cover the following:
- How to extend the code to support more features or data providers
- Important things to consider when dealing with blockchain data
- Insights on what blockchain and web3 can enable in terms of product experience design
The content of this article will feel like a collection of somewhat disconnected ideas, and the goal is to do a brain dump of the biggest takeaways and learnings I had while I was developing a system for the Ethereum blockchain.
Extending the payment system
For my implementation, I have hardcoded a few things in order to build faster, in this list, I want to point these things out so you know where they are in case you want to reuse this code.
Redundant data providers
I used the Etherscan Developer API as a data provider to poll the Ethereum blockchain, and I’ve hardcoded it in the PaymentManager class. Before using this code in production, I would recommend adding utility functions for at least one data provider, if not two, just to account for the fact that failures can happen and will happen, and that having another few backup providers can help with keeping all systems online and operational in case such failure were to happen.
Limited couponing features
I have implemented a whitelist feature, also referred as allowlist or reserve list, which allows for adding specific wallet addresses and giving them discounted or free access.
I have also added hooks in the data model in order to support coupons, but I have not implemented the feature. If you need couponing, you’ll have to write this implementation yourself.
Testing networks
In order to test this payment system, I have used some of the Ethereum testing networks. The selection of whether the system should use the test network or the main Ethereum network (i.e. the production one where money is real) is controlled manually. One has to change two lines, one in the frontend and one in the backend. This manual process is not ideal because it can be very error prone. If you plan on going to production with this code, you definitely would want to add some automation and safeguards for this code.
Multiple Deposit Wallets
For this simple project, I used a single deposit wallet, which means that all buyers pay the seller into the same wallet. While this simplifies the system a lot, it also has drawbacks, in particular, it’s easy to check that wallet to know who interacted with it, how much money there is in it, etc. A more secure and privacy-friendly solution is to create one unique wallet per each buyer and transaction. This solution is more complex but has the following advantages:
- Increase the privacy of the buyers, as it makes it more difficult for an external observer to know what service the buyer purchased for this particular transfer.
- Increase the privacy of the seller, as it obfuscates how many transactions happened and how much money the seller really collected. This can be particularly useful if businesses having adversarial goals towards the seller are trying to assess how much volume is the seller doing.
- It simplifies the recovery process in case of incidents: imagine a buyer who tried to buy multiple products of the same price and faced a transaction issue. With a single wallet it would be more difficult to trace what happened to which purchase, whereas with a single wallet per transaction, backtracking individual purchases would be easier even for the same buyer.
If you start your project and you expect very little payment volume, then I recommend that you stick to having a single deposit wallet, as it will simplify your implementation a lot. However, if you expect to have high volumes or if you line of business requires higher privacy, then you can go for the multi-wallet.
To implement this efficiently, you’d have to deploy a custom smart contract that would create a unique wallet per customer, and would then automatically forward the payment to a central wallet. The forwarding to a central wallet is a step that can potentially reveal information about the buyers and the seller and make the whole effort useful, so you want to be very careful with that. You probably want multiple central wallets, you want to rotate them regularly, and you want to use multiple centralized exchanges as exit points to protect anonymity.
This article about the CREATE2 opcode, and this other article about how Coinbase processes USDC payments are excellent starting points.
What I’ve learned about interacting with the Ethereum blockchain
Writing code to interact with the Ethereum blockchain is relatively easy thanks to the many free APIs and data providers out there. Nonetheless, there are a few caveats I’ve learned and on which I shall warm you if you take this journey.
Store all prices as strings
The smallest unit of value in the Ethereum implementation is called a “wei”, and one ether is one quintillion wei, or 1e18 (one followed by 18 zeros). Therefore, you should store all prices for the Ethereum blockchain as strings, because 1e18 does not fit in the standard implementations of most programming languages and database systems. You could also one step further to save some disk space, and not store the numbers as strings in base 10, but in base 16, or why not, base 64.
For the implementation of my payment system, because it’s a toy project, I decided to make things simple for myself and make the requirements for all prices to range from 0.00001 to 10 ETH, which can be encoded with regular integers. If you plan to go to production, for anything that has to do with the Ethereum blockchain, payment or not, then you absolutely have to use a library that can do arithmetics on big numbers, such as BN.js.
Store all wallet addresses in lowercase, and search with insensitive case
Wallet addresses can be passed by crypto wallets in all combinations of cases. You should always clean up addresses before storing them by converting them to lowercase, and in addition just to be safe, you should run all database queries on wallet addresses as being case insensitive.
Interacting with wallets from the web browser is a mess
There are many different wallets, and not all of them are sharing the same API. At some point you can expect that the industry will come up with a technical standard that all wallet makers will follow. Until then, you have two choices: either implement the support for the most common wallets and ignore the long tail, or pay for a third-party library that will provide the integration to all wallets for you, such as Beacon.
Build your application with a wallet reconciliation in mind
A user can have multiple wallets, and may start using your product from different wallets, and later one, he or she might want to claim ownership of all wallets and merge the data on your site or product into a single view.
When building for web3, keep this fact in mind, and that a user may be the owner of multiple wallets and think ahead about how you will deal with a possible data reconciliation process. This will save you from having to refactor a mess later on.
Product insights about blockchain
For the final section of this article series, I want to share some of the things I’ve learned about what blockchain can enable from a product perspective.
Crypto wallets are still too difficult to use
Crypto wallets are still very cumbersome to use, and scams are rampant. Even power users fall prey to scam, given that it’s very difficult to always know what you’re signing or approving with your wallet. The learning curve is very steep and is a huge barrier to mass adoption. A lot still needs to be done in order to simplify and secure the mass utilization of crypto wallets by non-tech users.
Crypto wallets could become the new password
I’ve seen that many web3 websites are now gated not by having to fill in a login and password (or often, an email address), but by having to connect a crypto wallet. This means that in the coming year, we could see crypto wallets taking over the password as a solution for authentication. I wouldn’t be surprised if Apple integrates a safe chip in their phones to store your crypto keys, and then use biometric data to unlock those keys and ends up being used by many other websites as a form of online authentication.
Web3 is not as decentralized as it claims to be
Another important point is that many of the web3 applications are actually using very web2 infrastructure: very few are running their own nodes and connecting directly to the blockchain. This was the case with the payment system I implemented here, given that I was using the Etherscan API to access blockchain data. Most of web3 relies on platforms that are not as decentralized and not as reliable as the blockchain itself, and this will be a problem in the long run if it’s not fixed. To learn more, I recommend that you read Moxie Marlinspike’s article on web3.
Accepting crypto payments requires particular accounting
From an accounting and financial perspective, there are some caveats related to accepting payments in crypto currencies. Indeed, at least in the United States, if a company accepts payments in crypto and then wants to sell or exchange those assets for US dollars, this transaction is subject to both gains and losses, which will be running through the company income statement. Because the exchange rate of ETH to USD is volatile, the rate won’t be the same at the moment that a customer made a payment and at the moment that the company wants to convert it to cash, hence why the gains or losses must be declared. This means that you should make sure your accounting department is aware and prepared to handle crypto payments so that those payments can be reflected and taxed with all the legal requirements.
NFTs can be used as a way to do login or gatekeeping
Payment is not the only way to grant access to a product or tool, and indeed, NFTs—currently under the standards of ERC-721 and ERC-1155—can also be used as a way for a company to do an initial fund raising, and later on, to offer gated access to a tool or a resource. This would also mean that only a limited number of people can access the software at the same time, usually 1,000 to 10,000 looking at the current size of NFT collections, and software ownership can be resold or passed on to another user by transferring the NFT to their wallet. This opens up for new possibilities of selling and accessing online software, and we’re going to see a few applications using this model in the coming year.
What’s Next?
I hope you had fun reading this article series and that you learned something from it.
My next steps with the blockchain are going to be around the creation of smart contracts using Solidity, still on the Ethereum blockchain. There is a lot of content and courses online already out there, so if I end up writing something, it will have to be because I feel I can add my unique point of view to it, otherwise I might not post at all.
You can always support me by signing up for my newsletter and you’ll get notified any time that I post something new.
Be First to Comment