KroWallet - crypto wallet
My Journey Building a Crypto Wallet App with React Native Expo
TL;DR: Building a crypto wallet app has been one of the best projects I built, just for the knowledge that I got from it and experience.
If you’re considering building a similar project or simply curious about the process, I hope this write-up helps you navigate the complexities of crypto and mobile development!
Also if you want to contribute or ask questions feel free to do so.
Why Build a Crypto Wallet App?
Ever since I first discovered crypto, I started by looking for a good wallet app that has nice look and feel, but also functionality.
However, there weren't many apps that fit what I was looking for, so that would be the reason for this.
My goal was to create a simple, intuitive, and secure crypto wallet that allows users to manage multiple cryptocurrencies, check their balance, and make transactions.
I chose to build the app in React Native to create a cross-platform experience, and I decided to start with Nano/Banano, and Stellar due to its efficient transaction model and focus on enabling low-cost, cross-border payments.
Step 1: Setting Up the Core App in React Native
I started by setting up a basic React Native app using Expo, which turned out to be a double-edged sword because of some things not working correctly. Some initial setup choices were easy:
- Expo Secure Store for securely storing wallet data.
- Expo Clipboard for easy copy-paste functionality of keys.
- React Native Gesture Handler for smooth interactions within the app.
Choosing the right libraries and tools made a significant difference. For example, using expo-secure-store allowed me to focus more on wallet functionality without worrying too much about the security of sensitive information, like private keys.
Step 2: Generating and Importing Wallets
The first major feature was the ability to generate and import Stellar wallets. I implemented this by integrating Stellar SDK to handle wallet creation and transaction signing. Creating new key pairs with the SDK was straightforward, but securely storing the keys was a priority.
Here’s a high-level look at how I handled it:
- Generate Keypair: I used StellarSdk.Keypair.random() to generate a public and secret key pair.
- Store Secret Key: Using Expo’s Secure Store, I securely stored the secret key so that users wouldn’t have to re-enter it every time.
- Import Existing Wallet: For users who already had a Stellar wallet, I allowed them to import it by entering their secret key.
Step 3: Checking Account Balance
Displaying the wallet balance was more challenging than I expected. I used the Stellar Horizon API to fetch the account balance, but I needed to format the response data and handle potential issues like unfunded accounts. Here’s how I approached it:
- API Call: I used the
server.loadAccount(publicKey)
function to retrieve the account’s balance. - Formatting: Since Stellar allows multiple asset types, I looped through each balance object to identify the native XLM balance and displayed it in a user-friendly way.
- Error Handling: If an account was unfunded (no balance), I displayed a message prompting the user to fund the account.
Handling decimals was also a key challenge. Cryptocurrency balances can have many decimal places, so I rounded them to two decimal places for a cleaner look.
const formatBalance = (balance) => parseFloat(balance).toFixed(2);
Step 4: Sending Transactions
Sending XLM from the wallet was a significant milestone. This process involved:
- Taking user input for the destination address and amount.
- Verifying the inputs to ensure validity.
- Building, signing, and submitting the transaction using Stellar’s SDK.
Ensuring a secure and seamless experience for sending transactions took a bit of work:
- Funding account for the first time: One thing I overlooked was adding support for sending XLM to a new address that is receving funds for the first time, for that there is a
StellarSdk.Operation.createAccount
- Validation: Stellar has specific address formats, so I added checks to ensure the destination address was valid.
- Feedback: Users want to know their transaction’s status, so I displayed loading states and transaction results.
Step 5: Displaying Recent Transactions
This was one of the more rewarding features to implement. Displaying a list of recent transactions makes the wallet feel complete and gives users more transparency over their activity.
To fetch transaction history, I used the server.payments() method from the Stellar SDK, filtering for recent payment operations related to the user’s public key. I then displayed each transaction as a “sent” or “received” transaction by comparing the source and destination addresses.
Here’s a simplified version of the code that powers the transaction display:
const fetchTransactions = async () => {
const payments = await server
.payments()
.forAccount(publicKey)
.order("desc")
.limit(10)
.call();
const formattedTransactions = payments.records.map((payment) => ({
id: payment.id,
amount: parseFloat(payment.amount).toFixed(2),
type: payment.from === publicKey ? "Sent" : "Received",
created_at: payment.created_at,
}));
setTransactions(formattedTransactions);
};
Key Challenges and Takeaways
Building this wallet app came with its share of challenges and learning moments. Here are a few key takeaways:
- Security First: Managing private keys is a huge responsibility, and prioritizing secure storage is essential. Using Expo Secure Store was a lifesaver, but I also had to be mindful of other security best practices.
- User Experience Matters: Crypto apps can be complex, but my goal was to make the wallet as user-friendly as possible. This meant limiting decimals in balances, providing clear error messages, and making sure transactions were easy to send.
- Error Handling is Essential: In crypto, things don’t always go smoothly. From unfunded accounts to network errors, there are many points where things can go wrong. Building in error handling made the app much more robust.
- Understanding Blockchain Basics: Working with Stellar gave me a deeper understanding of blockchain transactions, key pairs, and network APIs. I found that having a solid grasp of these fundamentals helped me make more informed development choices.
This is the final look i came up with for the Stellar (XLM) Screen
What’s Next?
This is just the beginning! My goal is to expand the app to support multiple cryptocurrencies like Bitcoin, Nano, and Dogecoin. I’m also planning to implement dark mode, add a settings screen, and maybe even introduce notifications for incoming transactions.
Building this app has been an amazing learning experience, and I’m excited to keep improving it. If you’re interested in developing your own crypto wallet app, I’d encourage you to dive in and experiment—you’ll learn a ton along the way.
Thank you for reading, and stay tuned for updates on my app!
This post could serve as a great resource for other developers curious about crypto and mobile development, but also for me since there are probably a lot of people that can come up with brilliant ideas.
Top comments (0)