Solana from scratch
There was no pattern in the codebase to follow. A new chain package in 133 files, then a rewrite onto Cake's own libraries a year later, then SPL tokens, Token-2022, NFTs and Jupiter swaps on top.
Context
When I joined Cake in April 2023 the wallet held Monero, Bitcoin and a handful of EVM chains. Every chain that came after Ethereum had followed Ethereum’s shape. Solana does not have Ethereum’s shape.
The first Solana wallet landed in February 2024 in 133 files. I have written every merged Solana change since: 18 pull requests, about 14,900 lines added and 2,400 removed, across 528 file touches.
Problem
A new chain in this app needs a package, a proxy layer so the app never imports chain code directly, node handling, create and restore flows, send and receive, a token model, token management screens, an address validator, deep-link registration and 24 translation files. None of it existed for a chain that was neither EVM nor Monero.
Then the chain’s own rules. Accounts can be destroyed by a send that empties them. Tokens live in separate accounts that have to exist, and that the sender pays to create. History lives on the token account, not the wallet. Two transaction formats put the fee payer in different places. Token-2022 is a different program with different derived addresses.
Constraints
Non-custodial and offline-safe. Signing has to be separate from broadcasting, so the confirmation screen means something.
The exchange-only build. Cake ships a Monero-only variant from the same codebase, so shared code cannot import Solana types. Everything chain-specific lives behind the proxy and the parent currency type.
Wallets already in people’s hands. Any change to derivation or storage has to keep restoring the wallets that exist.
Decisions and trade-offs
Rewrite it a year in, onto Cake’s own libraries (March 2025). The first version used a third-party Solana package and it worked. It was also the only chain in the app not built on the two libraries Cake maintains and already used for Tron and the EVM chains, so Solana could not do what they could without waiting on someone else, and its derivation could not take a passphrase. I rewrote the client, the wallet, the derivation, the signing and the history parsing in one change. Review asked whether existing wallets still restored. They did. Everything after this, passphrase-derived sibling wallets, versioned transactions, metadata read straight from the chain, Token-2022, Jupiter, needed the primitives that rewrite brought in.
Detect the token program from the mint, and pay for it only when spending (January 2026). Assume the standard program and every Token-2022 balance silently disappears. Always resolve the program and you add a network call to every lookup, including the ones done for history. I do both: try the standard program first because it is the common case, use the detected id as the fallback on reads, and on the sending path re-read the mint’s actual owner rather than trusting the earlier detection. The library’s transfer helper could not be parameterised, so the instruction is encoded by hand.
Advance the sync cursor only after the data is on disk (July 2026). The fast version records the newest signature as soon as it is fetched. That leaves a permanent hole in someone’s history the moment a save fails. I chained the saves into a queue, made each save report success, and only move the per-source cursor when the save confirmed and nothing in the run failed. Slower and more code. It is the only version where a failure re-syncs instead of skipping.
Show the verified badge only on a yes (August 2026). A reviewer asked for the badge to be removed from tokens the check reported as unverified. I said no, because the data has three states: verified, unverified, and nothing at all when the mint is not indexed or the call fails. Treating the last two as unverified would mark legitimate tokens whenever the lookup broke. So the badge is a positive signal only, and its absence means nothing.
Take the amount from the balance change, not the instruction (2025). Challenged on whether there was a more accurate way, I kept it: the delta on the wallet’s own accounts is what left the wallet. The cost is a parser that has to reason about fee payers, intermediate accounts and both transaction versions, which is exactly what the swap history later had to extend.
What was hard
The first review found a real bug in the send flow. The pending transaction’s commit step was empty, so the transaction was going out at sign time, and a tester had seen one broadcast after an error was shown. Separating signing from broadcasting came out of that thread. It took 33 days and three rounds of changes to land the first build.
Third-party data is wrong in specific, quiet ways. The indexer and the node disagree about a token’s symbol. On-chain symbols come back padded with null bytes. A mint’s metadata URI often does not resolve to an image. Decimals arrive as a number sometimes and a string other times. Every one of those has a line of code in these PRs.
History got slower as wallets got older. The first version fetched every signature every sync. Then it batched. Then it streamed to the screen per batch, then per five tokens, then cached the token info, then cached the token accounts, and finally, two and a half years in, stopped re-fetching what it had already seen.
Result
You can create or restore a Solana wallet, including as a passphrase-derived sibling of the other wallets on the same seed, from a seed, a private key in either common format, or a QR code. You can send and receive SOL and SPL tokens, including Token-2022, with the fee quoted from the node before you confirm, a refusal if the send would drop the account below the rent minimum, and an error in your own language when something fails.
Tokens the wallet already holds are discovered and offered rather than typed in. Adding one by address fills in its name, symbol, decimals and icon, and says whether Jupiter has verified that mint. You can swap between SOL and any SPL token inside the app, with the total fee broken out and the swap landing in history as both sides of the trade.
NFTs appear in their own tab whether or not the indexer is reachable, are listed only if the chain agrees they are one of one, and can be sent. History streams in as it loads and, after the first sync, fetches only what is new.
There is no priority-fee feature in the wallet itself, and no benchmark behind the sync work. I would rather say what it stopped doing than guess how much faster it got.
Links
Amounts as BigInt, fee estimation by commitment
29 March 2024
Token metadata and icons when adding by address
8 April 2024
Refuse a send that would break rent exemption
13 December 2024
The re-implementation on Cake's own libraries
14 March 2025
14 March 2025
15 April 2025
Transfer parsing for versioned transactions
19 June 2025
16 January 2026
Token-2022 via the mint's program id
20 January 2026
SPL balances without the six-decimal assumption
13 March 2026
Incremental sync and a serialised save queue
16 July 2026
Jupiter verification badge on add-token
6 August 2026
NFT sending, persistence and ownership checks
2 September 2026