Realization
This experiment write-up focuses on documentation of my learnings from a deep dive on Wallet Management (mostly the creating, importing, and connecting of wallets to Dub - Anupam has covered signing and Robert has covered key storage). Feel free to read on if you’re curious, but the below TL;DR should hit the gist of it :)
TL;DR: I thought Wallet Management would be very simple (we had a working prototype of creating, importing, and as of last week, connecting wallets) however there are many nuances to Wallet Management. Dub should have best-in-class Wallet Management and we can accomplish this by simply supporting a few open standards (from some quick research, there are zero wallets that fully adhere to the standards set by BIP-32, BIP-39, and BIP-44).
Feature Overview
Create Wallet
BIP-32: Hierarchical Deterministic Wallets, an open standard first introduced as a Bitcoin Improvement Proposal, has been largely adopted by Ethereum wallet clients for creating (and in a select few cases, importing) Hierarchical Deterministic Wallets (HDWs) and the wallets in their derivation trees.
In general, generating a public/private key pair (the core of a wallet / Ethereum account) is trivial (literally takes less than a millisecond). However, to support HDWs as described in BIP-32, there are quite a few additional steps with both the technical implementation the and interface design.
Below is a basic outline of what Dub should support when creating a wallet and important notes for each case.
Create a new Hierarchical Deterministic Wallet (HDW)
Generates a new BIP-39 Mnemonic (and subsequently a BIP-39 Seed). This can be used to derive a master node and an entire tree of sub-wallets (see below).
Most wallet clients (MetaMask, Rainbow) do not support the ability to generate new HDW trees. This is a commonly cited pain point for users of those clients. Dub should support this functionality and build this into the core of our wallet management system.
Create an account in an HDW
Creating an account derives a new address, public key, and private key from the master seed of an HDW tree. Per BIP-44, Dub should prevent a creation of an account if a previous account does not have a transaction history (meaning none of its addresses have been used before)
MetaMask and Rainbow also lack the functionality to create new accounts in an HDW tree. Dub should support this functionality for an improved wallet management experience.
Create an address in an account in an HDW
Creating an address derives a new address, public key, and private key from an account branch of an HDW tree. Dub should warn when the user is trying to exceed the gap limit (currently set to 20) on an external chain by generating a new address
Create an address with a custom path in an HDW
Theoretically, users could derive an address, public key, and private key from any valid path of an HDW tree.
BIP-44: Multi-Account Hierarchy for Deterministic Wallets defines the following 5 levels in a BIP-32 path as:
- m / purpose’ / coin_type’ / account’ / change / address_index
(apostrophe indicates that BIP-32 hardened derivation is used)
In the above example of deriving basic accounts and addresses for an Ethereum HDW, the following path is used:
- m / 44’ / 60’ / account’ / change’ / address_index
(purpose is 44 as defined in BIP-43: Purpose Field for Deterministic Wallets:, coin_type for Ethereum is 60 as defined in SLIP-0044: Registered coin types for BIP-0044)
Dub should allow the creation of wallets from custom path derivations with caution as there is no open standard for application level interoperability for wallets derived from a custom path, however, with proper warning there are many possible ways to leverage deep HDW trees for convenience, security, and utility. There’s clear value in further exploration of this, however our most immediate thought is to use these trees for discrete key management across different dApps where we could spin up a new, ‘isolated’ wallet account for each dApp or tab that you visit while not requiring you to store any additional private keys than the master key that you are presumably already storing.
Import Wallets
Import from mnemonic
Dub should support importing a wallet using mnemonics from multiple languages and of multiple formats (12 word, 24 word, etc.).
Import from seed (private key)
Dub should support importing a wallet using a seed.
Account Discovery
Dub should follow BIP-44 for Account Discovery when a mnemonic or seed is imported. It should import any active accounts and associated active addresses.
Dub should follow the address gap of 20 (check 20 wallets for transaction history before giving up). MetaMask does seem to support this however Rainbow does not (they use an address gap of 1).
Connect Wallets
Connect Wallet with WalletConnect
Dub should support WalletConnectV2 and allow connection via a QR code or via a copy-pasteable link. Dub should also support WalletConnectV1 for backwards compatibility (though this should be lowly prioritized as WalletConnectV1 will supposedly be deprecated on March 1st, 2023).
Connect Hardware Wallet
I did not get to prototype this in my research this past week so I don’t know too many details here, but Dub should support connecting a Ledger wallet (and ideally Trezor too).
Use Wallets
Regardless of the creation, import, or connection type, Dub should support all standard wallet transaction types
I yield to Anupam for implementation of this, however Anupam and I collaborated to create a protocol that should allow for us to enable seamless support for all wallets.
Follow Wallets
Follow a wallet to see its tokens and activity
This is pretty standard across wallet clients. Dub should be creative in its implementation of this functionality as it’s a relatively underexplored area for differentiation and value creation.
Process
Primary Challenges
Supporting Open Standards
There was only one viable package that supported BIP-32, BIP-39, and BIP-44 - web3swift. We made the decision to use this package as our primary (and hopefully sole) Web3 package. Thank you Anupam for your flexibility in refactoring your code to implement this new package.
This package is currently the most starred Web3 package for Swift and has a few other favorable security advantages compared to the other packages we have been using, so we feel hopeful that this package should solve our Web3 needs for the near future.
Learnings
Leveraging Open Standards
In order to have the flexibility, speed, and depth of data needed to deliver best-in-class ENS support, we’ll need to leverage The Graph, an indexing protocol, to index and query subsets of on-chain data (like ENS, Uniswap, etc.).
Next Steps
More Prototyping
I’m currently only about 50% of the way through prototyping the above functionality, so I need to continue to prototype and build the above functionality. This is all pretty high priority, primarily so that we can unlock Wallet Connect integration for Dub. I’ll be working with Anupam to help push this over the line over the coming weeks.