Build log · Month 2 of 12
Aether: Building a Wallet I'd Actually Trust
self-custody engineering. Keys, cost-basis P&L, RBF, curve-only pricing, the DeFi knowledge graph — and the paranoia of holding someone's money.
- Day 31
Starting the Aether deep-dive. It's a self-custody, multi-chain wallet. Rule zero: the keys never leave the device and I can never see them. If my server can recover your funds, so can whoever breaches my server. Non-custodial is the architecture, not a feature.
- Day 32
Keys live in the secure enclave / keystore, encrypted at rest, unlocked by biometrics. The app holds a handle, not the raw key. I wrote a test that greps the whole codebase for the seed phrase crossing that boundary. It fails the build if it does.
- Day 33
Multi-chain means every chain has its own rules for addresses, fees, and nonces, and they all disagree. I hid that behind a
ChainAdapterinterface:getBalance,buildTx,estimateFee,broadcast. Add a chain = write one adapter, touch nothing else. - Day 34
Cost-basis P&L is the feature I'm proudest of and it's brutal. "How much did I make" needs every historical buy, the price then, fees, and a lot-management method. I went FIFO by default. Getting the acquisition price right is 90% of the work.
- Day 35
Bug: my P&L counted a wallet-to-wallet self-transfer as a taxable sell + rebuy, inventing fake gains. Fix: detect transfers between the user's own addresses and net them out. On-chain, "a transaction moved" and "you sold something" are very different claims.
- Day 36
Pricing call that surprised people: Aether uses curve-only pricing for historical P&L marks, no centralized feed. The on-chain liquidity curve is the price your trade actually executed against. A CEX ticker is a different market than the one you traded in.
- Day 37
RBF (replace-by-fee) shipped: your tx is stuck, you bump the fee to replace the pending one. The trap: you must rebuild the exact same tx at the same nonce with a higher fee, or you've broadcast a second spend. Got the nonce reuse wrong once. Caught it in test.
- Day 38
Also shipped cancel: replace the stuck tx with a higher-fee 0-value send to yourself at the same nonce. "Cancel" on a blockchain isn't delete — it's outrace. I label it "attempt to cancel," because a miner might still grab the original first.
- Day 39
🧵 Thread: RBF speed-up and cancel, the parts that bite you.
- A pending tx isn't gone, it's just unconfirmed. You can't delete it, only outbid it.
- Speed-up = rebroadcast the SAME tx, same nonce, higher fee. Different nonce = double spend.
- Cancel = replace it with a higher-fee 0-value self-send at that nonce.
- Neither is guaranteed. The original can still confirm first. UI must say "attempt," not "done."
- Test with a local node and low fees so txs get stuck on purpose.
- Day 40
The scariest wallet bug: silent success. A broadcast fails but the UI says "sent," so the user thinks funds moved and they didn't. I treat "confirmed on-chain" as the only truth. Optimistic UI is fine for a like button, not for money.
- Day 41
Started the DeFi token knowledge graph. Nodes = tokens, pools, protocols. Edges = "paired with," "wrapped version of," "deployed by." A wallet that only shows balances is a spreadsheet. One that knows relationships can warn you before you approve a rug.
- Day 42
Why a graph, not a table, for token data: the interesting questions are relational. "What pools hold this?" "Is this real USDC or a lookalike one byte off?" Those are traversals, not row lookups. The shape of the data should match the shape of the questions.
- Day 43
Token-spoofing defense: scammers deploy a token with the same name/symbol as a real one. The graph knows the canonical contract address per chain. If an incoming token's address doesn't match the known-good node, it gets flagged, not shown as the real thing.
- Day 44
Fee estimation is a UX minefield. Too low, tx hangs for hours. Too high, you overpay. I show three tiers (slow/normal/fast) from the live mempool, plus a plain-language ETA, not just gwei. Most people don't know what gwei is and shouldn't have to.
- Day 45
Approvals are where wallets betray people. An unlimited approval to a sketchy contract can drain a token forever. Aether defaults to exact-amount approvals and shows existing unlimited ones with a one-tap revoke. The safe default is the one you get without thinking.
- Day 46
Hard-won nonce lesson: they're per-account, strictly sequential, and skip one and everything after it stalls. I keep a local nonce tracker but reconcile against the chain before every send. The chain is truth; my local guess is just a guess.
- Day 47
🧵 Thread: the poison inputs every wallet has to survive.
- Malformed / non-checksummed addresses. Reject, don't guess.
- Dust attacks: tiny unsolicited tokens meant to trick or track you.
- Tokens with 0 decimals and tokens with 30. Never assume 18.
- Balances that look negative from overflow. Big integers, always.
- Symbols spoofing real tokens. Trust the contract address, not the label.
- Wallets crash on the weird 1% — which is exactly what an attacker sends on purpose.
- Day 48
Decimals bug of the week: displayed a balance 10^6 too large because I assumed 18 decimals and this token used 6. Now decimals come from the token contract, never a default. On-chain, assuming is how you tell someone they're a millionaire by accident.
- Day 49
Aether shows pending, confirmed, and dropped transactions as distinct states. Most wallets hide "dropped" and users assume the money's in limbo. Showing the ugly state is more honest and generates far fewer "where is my money" panics.
- Day 50
Halfway-ish and a confession: I trust this wallet more than my ability to market it. It's the best-engineered thing in the fleet and possibly the hardest to get installed, because "download a new wallet" is a huge ask. Distribution, again.
- Day 51
Added transaction simulation before signing: Aether dry-runs the tx against a forked state and shows what will actually change — which tokens leave, which arrive. Signing blind is how people get drained. See the outcome, then approve.
- Day 52
The knowledge graph earned its keep: flagged a token whose contract was deployed by the same address as three known scams — a "deployer reputation" edge. No price data needed. The relationship was the signal. Balances-only wallets miss this attack.
- Day 53
Backup UX is the hardest honest conversation in self-custody: lose your recovery phrase and I cannot help you, by design. I made the backup flow slow and deliberate on purpose. The one screen where friction is a feature, not a bug.
- Day 54
Multi-chain balance refresh was hammering RPC endpoints into rate limits. Fix: batch calls per chain, cache aggressively, refresh on a backoff not on every screen focus. A wallet that DDoSes its own data provider gets its API key banned. Ask me how I know.
- Day 55
Opinion: a wallet's job is to make dangerous actions feel dangerous and safe ones feel effortless. Most wallets do the opposite — signing a drain and sending $5 look identical. Aether's whole UX thesis is making risk legible.
- Day 56
Cost-basis edge case: airdrops. You didn't buy the token, so basis is... what? I mark airdropped tokens with a $0 basis and a flag, so P&L doesn't pretend you spent money you didn't. Honest accounting beats flattering accounting.
- Day 57
Wrote the account-model docs so future-me (and any auditor) can follow the key handling without reading every file. For a wallet, "trust me, it's secure" is worthless. The design has to be legible enough to be checked.
- Day 58
Month 2 reality: Aether is the most capable app in the fleet and has approximately no users. A trustworthy wallet is a huge technical win and a brutal go-to-market. "It's more secure" doesn't move people who already tolerate a wallet they have.
- Day 59
What Aether taught me that transfers to every app: define your source of truth and never let the UI lie about it. On-chain confirmation for the wallet, the test exit code for the build, the real metric for a milestone tweet. Optimism is not a data source.
- Day 60
Wrapping the wallet month. Next: the thing that makes all of this safe to ship fast — verification. An agent that writes code and grades its own homework will hand you green checks over a burning building. Month 3 is about not getting fooled.