Create an Ethereum Wallet in iOS — Part 1

Calvin Chang
Coinmonks
Published in
6 min readJul 1, 2020

--

Photo by Launchpresso on Unsplash

Nowadays, blockchain becomes more and more popular, lots of startups, applications spring up in this decade. Traditional banks are trying to involve blockchain technology and beware of losing marketing opportunities.

Before start creating an Ethereum Wallet, it’s better to have the knowledge about the basic workflow of Ethereum, POW/POS, smart contract, etc. Here are some references that can help you catch up.

The mechanism in the blockchain system has some different concept, for instance, account creation, you don’t have to upload your account information to any server, all you need is generate the key and store in your local machine. Once you add the record to the ledger, your account information will sync to the decentralized distribution system. All you need is this key, use for query all the records.

I will do the following things in this article, hope can help some iOS engineer dive into the world of blockchain.

Accounts

Load existing account

  1. Entering a hex-string of the account private key
  2. Entering a 12-word mnemonic phrase

Generate, delete and export the account

Balances

Displays ETH, DAI and USDC balance

For the reference, you can check the existing wallet, such as MetaMask, it’s can help you understand how it works quicker.

In addition, I will use the Rinkeby test network for this demo. Rinkeby is the test chain which bases on Ethereum. There are several Ethereum testnet you can play with, such as Ropsten, Kovan, Görli, etc.

Project Setup

This project setup with Swift 5.1 and use Cocoapods as the package manager, if you want you can always change to Carthage, most of the blockchain libraries are support Carthage also.

Library

The following library is used in this project:

Web3Swift

There are several similar libraries which also provide the ability to access Ethereum account, such as

Trust Wallet Core is such a nice library, which also provides the nice and readable document for it!

Generate the account

First of all, let’s generate the account:

func createAccount(name: String) throws -> Web3Wallet {guard let mnemonicsString = try BIP39.generateMnemonics(bitsOfEntropy: bitsOfEntropy) 
else { throw Web3ServiceError.noMnemonics }
guard let keystore = try BIP32Keystore(mnemonics: mnemonicsString, password: password, mnemonicsPassword: "", language: .english)
else { throw Web3ServiceError.noKeyStore }
guard let address = keystore.addresses?.first?.address
else { throw Web3ServiceError.noAddress }
let keyData = try JSONEncoder().encode(keystore.keystoreParams)let mnemonics = mnemonicsString.split(separator: " ").map(String.init)return Web3Wallet(address: address, data: keyData, name: name, type: .hd(mnemonics: mnemonics))}

BIP39 is the most common seed phrase standard, seed phrase include the list of words which store all the information needed to recover the blockchain funds, for more details you can check this article:

There have two kinds of Wallet, standard and HD (Hierarchical Deterministic) wallet. For easy understanding, in the standard wallet, users have to keep the private key to pair to the public key then access the wallet. HD wallet is the new age digital wallet that can generate a hierarchical tree-like structure of private/public addresses automatically.

In short, in this demo, the HD wallet is the wallet which has mnemonics and standard one has the private key.

Here is the Wallet model I’m used:

struct Web3Wallet: Equatable {let address: Stringlet data: Datalet name: Stringlet type: WalletType}enum WalletType: Equatable {case normalcase hd(mnemonics: [String])}

First, I generate the mnemonics and get the Keystore from it, there has address and

Create the account/wallet actually just generate the private key or mnemonics, it doesn’t need to upload to anywhere.

However, it means you have to keep the private key or mnemonics well and cautiously, once you miss it, the account can never be restored 😟. Also, if someone gets your key, he/she can access your account whatever they like and you can’t ask help from anyone.

Import the account

Next, we can restore the account by mnemonics or private key, depends on which wallet you want to restore.

By private key:

func importAccount(by privateKey: String, name: String) throws -> Web3Wallet {let formattedKey = privateKey.trimmingCharacters(in: .whitespacesAndNewlines)guard let dataKey = Data.fromHex(formattedKey), let keystore = try EthereumKeystoreV3(privateKey: dataKey, password: password)
else { throw Web3ServiceError.noKeyStore }
guard let address = keystore.addresses?.first?.address
else { throw Web3ServiceError.noAddress }
let keyData = try JSONEncoder().encode(keystore.keystoreParams)return Web3Wallet(address: address, data: keyData, name: name, type: .normal)}

By mnemonics:

func importAccount(by mnemonics: [String], name: String) throws -> Web3Wallet {let mnemonicsString = mnemonics.joined(separator: " ")guard let keystore = try BIP32Keystore(mnemonics: mnemonicsString, password: password, mnemonicsPassword: "", language: .english) 
else { throw Web3ServiceError.noKeyStore }
guard let address = keystore.addresses?.first?.address
else { throw Web3ServiceError.noAddress }
let keyData = try JSONEncoder().encode(keystore.keystoreParams)return Web3Wallet(address: address, data: keyData, name: name, type: .hd(mnemonics: mnemonics))}

As I mentioned before, the HD wallet can only import by mnemonics.

The standard wallets use the private key to create the Keystore and the HD wallet use mnemonics to generate the Keystore to access the wallet information.

Export the account

according to the different kinds of wallets, the exported data is different. The HD wallet, the user will be received the mnemonics for future usage, and the standard wallet is private key instead.

func exportAccount(wallet: Web3Wallet) throws -> ExportedType {let keyStoreManager = try fetchKeyStoreManager(wallet: wallet)guard let ethereumAddress = EthereumAddress(wallet.address) 
else { throw Web3ServiceError.noAddress }
let key = try keyStoreManager.UNSAFE_getPrivateKeyData(password: password, account: ethereumAddress).toHexString()switch wallet.type { case .normal: return .privateKey(key: key) case .hd(let mnemonics): return .mnemonics(mnemonics: mnemonics, key: key) }}

Here is the Export type I’m used:

enum ExportedType {case privateKey(key: String)case mnemonics(mnemonics: [String], key: String)}

Break down the code, first of all, we need to fetch the Keystore manager depend on wallet type :

func fetchKeyStoreManager(wallet: Web3Wallet) throws -> KeystoreManager {switch wallet.type {case .normal:guard let keystore = EthereumKeystoreV3(wallet.data) else { throw Web3ServiceError.noKeyStore }return KeystoreManager([keystore])case .hd:guard let keystore = BIP32Keystore(wallet.data) else { throw Web3ServiceError.noKeyStore }return KeystoreManager([keystore])}}

Standard one needs the EthereumKeystore and the HD wallet needs BIP32Keystore, then use this Keystore and the address to get the private key.

Theoretically, it’s impossible to recover a phrase from a private key. In this demo, the mnemonics are stored in a safe local database, the better approach is to ask the user to enter the Pincode and encrypt the seed phrase using users Pincode and save it in the Keystore.

Delete the account

Actually, there is no way to delete account information once it has the record in the chain, that is one of the main purposes of blockchain —

Unalterable

What I do here, just simply delete the address I stored for this account and if user want to access this account again, has to import it again 😅

Here is all the content for part 1, in part two, I will demo how to get the Ether, DAI, and USDC balance from Ethereum test net.

Hope this article can help the iOS Engineer who is the beginner of blockchain to join this cool and amazing technology 🤩

In this article may still have some incorrect place, welcome to correct or discuss with me!

If you think this article is helpful, don’t forget to give me some claps.

Happy coding, enjoy the block-chain technology 🙂

If you would like to reach out, feel free to contact me through
Twitter or Linkedin

Also Read: Best Bitcoin Hardware Wallets

--

--

Calvin Chang
Coinmonks

The developer, the alcohol lover, the forever learner and the crazy explorer.