Why web3.swift?
We faced a problem when we started building Argent 12 months ago: there were no web3 libraries available in Swift (in fact, the closest solution came to running web3.js via WebKit). This mattered as the Argent mobile wallet is Ethereum-based and we interact directly with nodes using the standardized Ethereum JSON-RPC interface.
The solution? We built web3.swift. We’re delighted to share it with the wider community.
It builds on our active use of, and contributions to, the web3.js (Javascript) and web3j (Java) libraries. We’re seeking to learn from them what features and approaches work best on each platform.
Writing software in different languages often entails different approaches to data management and application logic, and as such we’ve structured web3.swift to make building decentralized apps (Dapps) on mobile as familiar as possible.
Main features
Our web3.swift library provides functionality for core interactions with the Ethereum blockchain. You can create accounts, call functions and perform transactions against smart contracts.
The primary benefit, however, is our dual support for working with contract code (ABI’s) via JSON or statically typed Swift structs. You may wish to use either route depending on the complexity of your product and team coding style.
We’ve made security a paramount concern with this library, especially given the trust users will place in it when handling private keys. For this reason, we’re using only minimal dependencies (BigInt) and well-proven cryptographic C libraries bundled with web3.swift.
We’ve also included support for working with ERC20 tokens (view the source code for an example of developing statically typed models) and Ethereum Name Service (via dynamic JSON).
Working with ABI contracts
To illustrate how to work with web3.swift, here’s a real-world example on the Ropsten test network.
Let’s use this HelloWorld Kittens smart contract ABI example, which stores a list of kittens and their corresponding names. We can look up how many kittens have a certain name (howManyKittensCalled), or create a new kitten with a name (createKitten). The interface is described as:
Firstly, we install via CocoaPods and import web3 to gain access to the main classes and functions. We create an instance of EthereumClient to connect to the blockchain, using any node which supports the JSON-RPC proxy. For testing we usually use Infura:
Please ignore the use of explicit bangs (!) and lack of error handling. Whilst bad practice it makes providing example code easier!
Now, let’s set up the contract code. The above ABI example we’ve saved as Contract.json, and can use to create an instance of EthereumJSONContract:
Here, we’re referencing the deployed contract on the Ropsten test network.
After this, we can call the ABI methods easily to look up data from the blockchain. To see how many kittens are called “fred”, we can do the following:
We should find that the number of kittens returned is > 1 at the time of writing this. Note the use of ABIDecoder to decode the single value response to UInt64, as found in the original ABI.
Statically typed structs
If we’re building a more complex app, we may wish to create Swift structs to represent the ABI methods. This allows us to work with strictly typed data structures to create a native interface to our smart contract.
Here are example structs for the same function request & response:
As shown, we have modeled our function into two separate structs conforming to ABIFunction and ABIResponse. The serialization and deserialization of data will look familiar to anyone who has used the native Codable protocol.
To get the above code to work, you will have to import BigInt, which is a dependency of web3.swift. BigInt is a third-party library that provides support for 256-bit integers, which is not a foundation type in Swift.
We can now execute the function like so:
Manipulating the Blockchain
What about manipulating data on the blockchain? We now want to create a new kitten, but to do so we’ll need an Ethereum account (public/private key-pair) and load it with some Ether to pay the transaction (gas) cost.
This can be done via the above approach, setting gas price and gas limit, and calling function.execute with an EthereumAccount object. I’ll provide a full example in a follow-up post.
What’s next
There’s a couple of missing features we’ll be looking to add as we build out this library, such as batch transaction support & bloom filters for searching logs. We’re also looking to automatically generate Swift structs for a given ABI JSON interface via Sourcery. We hope the community will contribute to making this the main library for building iOS apps on Ethereum.
We’re working hard at Argent to create the very best products. We see web3.swift as one of our core components. It’s still in its early days but we hope it has a bright future ahead.
Contribute to Web3.swift on Github