How to Create iOS App Calling Ethereum Smart Contracts
Ethereum smart contracts have a wide variety of use cases, but until now it has been quite difficult to call them from your iOS app. Well, that has changed! Just by using Ethereum iOS Dev Kit and EtherKit, you can get started in no time. At the end of this tutorial you will be able to call any public contract function that is defined in its ABI (Application Binary Interface).
Let’s Get Started
For this project we will be using Xcode 10.0 and ContractCodegen 0.1. We also recommend to use iOS MVVM Project Template, but to keep this tutorial simple, we will use normal iOS project structure.
First of all we will create a new iOS project and call it for example EthereumContracts. Download our example contract abi.json file here[link to abi.json here]. When the download succeeds, drag the file to your Xcode project. Your Xcode project should now look like this:
In the next part of this tutorial we will download ContractCodegen from our Ethereum iOS Dev Kit. For this I will use Cocoapods which will automatically download the necessary dependencies as well, but there are other methods available, described at Ethereum iOS Dev Kit Github.
In your project root directory create Podfile and insert this code:
Open Terminal and paste this command:
When this command finishes, close our EthereumContracts project and in Finder open
Great! Now let’s generate Swift code to interact with our smart contract 🤓
Generating Swift Code
Firstly, make sure that you are in your project root directory. If you are, we can generate our Swift code quite simply, just by using this command:
Pods/ContractCodegen/ContractCodegen/bin/contractgen HelloContract EthereumContracts/abi.json -x EthereumContracts.xcodeproj -o EthereumContracts/GeneraredContracts
When the command asks you which target to use, it’s quite simple, use the only one, that is option number one 😎
And voilá, if you got the message “Code generation: ✅”, you have created your first Swift code for Ethereum smart contract 🚀
You should now see a group Generated Contracts and two files in it —
HelloContract.swift. The first one helps with invocating individual methods that are defined in the contract files (in our case it is HelloContract) and is the same for all generated contracts.
And to the fun part — actually using our generated code to call our contract.
Navigate to our
ViewController and at the top of the file write:
Now we need to declare which geth network we will use to communicate with the smart contract. In order to do that let’s define a property in
let query = EtherQuery(URL(string: “https://rinkeby.infura.io/v3/9f1a1e0782ab40c8b39fe189615714d0")!, connectionMode: .http)
You can use any URL you want, the one you see in the string is just one we provided for you.
Then we will continue in our
viewDidLoad() function and create our keys:
Whoah! What is all this? Well, it’s quite simple, really.
Firstly, we create mnemonic sentence — this sentence is used to create your private and public keys, as well as addresses. To create your own, which we obviously recommend, you can for example use MyCrypto wallet that you can download from here.
HDKey.Private.create then creates our master node from which all other public and private keys, as well as addresses, are derived.
As you can see, the compiler now shows us this warning:
When we look at the function of
HDKey.Private.create, we can see it has a completion parameter
Result<HDKey.Private, EtherKitError>) -> Void. This is because creating our account is an async operation and so we will need to start calling our smart contract after this function is completed.
In order to keep our code simple and readable, we will create a new function from which we will call our contract:
Now we call this function from the completion that I mentioned earlier like this:
Be patient, we are getting closer to the final result 💫
Calling our Contract
Head to the
testContract() function we have created earlier. Firstly, we need to find one of our created keys stored in our storage using key paths (the code below simply goes through a tree to a specific location):
And to the final part of the code, we’re almost there!
OK, let’s see what this does.
testContractAddress points to our created smart contract address. To use your own replace the string with a desired hex code.
The rest of the code is the call itself. I think it is pretty self-descriptive, but we will go through it, just to be clear.
We find all of our HelloContract functions and declare which contract address we want to use with
query.helloContract(at: testContractAddress). Then we choose one of the functions, in this example I have chosen function
testString that has
String as an input (this value will be used by our smart contract). After that we send this data by
send. Key value is the one we have found in our storage earlier, amount declares how much Ethereum we want to send (as you can see, we use typealias for
UInt256 for better readability).
send then returns
SignalProducer. If you do not know what that is, read more about it at ReactiveSwift documentation.
If the call succeeds, it returns
Hash type. That is just a hash of the transaction we have sent.
Let’s see if it works!
Try to run the application and if you see in the output a hash and a string “Test greetings succeeded!”, you have just called your first smart contract function using Swift! 🌟
There is one more thing that should be said. There are two types of smart functions —
non-payable. This difference is taken care of by the generated smart contract code, so the only difference you will see in your code between these two types is that when calling
non-payable function, the paramater
amount will be omitted (since no Ethereum should be sent). Quite simple, huh? 🤔
If you want to check out the whole project, you can download it here.
We have covered quite a lot of ground, so if you are interested in how all of this works or help with the further development, here are some links to get you started:
Ledger — Documentation of how keys and their generation work (including mnemonic sentence)