Part 1: How to create an iOS app with Tezos smart contract interaction

Marek Fořt
Ackee
Published in
4 min readFeb 26, 2020

Tezos smart contracts have matured a lot — and it’s time to use them in iOS apps, closer to the users’ hands. 😉 Throughout this tutorial we will write a smart contract using and then move to Xcode and get a hands-on experience with interacting with our contract in Swift using generated code from . Note that this tutorial will touch on the most important parts of RateMyTeam app and is not a complete step-by-step tutorial.

Overview of our Contract

Firstly, let me give you a brief of overview about what our contract should do and what’s the problem it solves. Every year, our company divides a set amount of money for Christmas bonuses. To make this process more transparent, we can leverage Tezos! In our contract we want to define three main groups: candidates, voters and a manager address. Candidates will be the different teams in our company — design team, iOS team, etc. Voters will have a limited amount of votes which they can then use to vote for the various teams. Manager account will then have an option to end the voting — at that point the current balance of the contract will be divided and sent to the account of the given teams depending on how many votes they have received during the voting process.

Let’s get started

For reference, you can find the smart contract . Our first step will be initializing the contract with a given initial storage. There are multiple properties that we want to hold in our smart contract:

  • name: Name of our smart contract, will be displayed in iOS app for better navigation
  • manager: Will have the ability to end the contract
  • ballot: This type will be a little bit more complicated. It will be a sp.TMap where the key will be the address of the candidate. As a value we will hold a sp.TRecord with candidateName and numberOfVotes. candidateName will be for differentiating between different teams, numberOfVotes will help us with keeping track of the current number of votes the given candidate has received.
  • voters: This will be sp.TMap where key will be sp.address and the value will be sp.TInt representing the amount of votes the voter has left
  • totalNumberOfVotes: A total number of casted votes - will help us with

So, our final initialization looks like this:

Vote function

Let’s implement a vote function now. We will define a new @sp.entry_point vote that will accept a map where key will be a sp.TAddress of the candidate and value will be sp.TInt representing number of votes that the voter wants to cast for the candidate. For example contract.vote(votes = {addr1: 2}) would mean casting to votes to addr1.

During step #1 we verify that the voting has not ended (for obvious reasons).

During step #2 we want to make sure that the sp.sender is, indeed, a voter (thus eligible to vote).

Then we go through all the votes for different candidates and account them into our ballot. We check that the voter has a sufficient number of votes available, add the votes to the candidate and totalNumberOfVotes and subtract the votes from the total number of votes available to the voter.

End function

The second part of our contract will be concerned with ending the contract. Our contract can be ended only by a manager account. Once the voting has ended, all of the contract’s balance will be distributed to the candidates (divided by the votes they have received). This leads to the following code:

Let’s go through this code again to see what it does. In #1 we verify that the account that is ending the contract is a manager and that the contract has not already ended (to ensure that the contract cannot be ended multiple times which does not make sense). Then we go through all the candidates ( self.data.ballot.keys()).

For each candidate we make sure that it has more than one vote. If that’s true, we send the appropriate amount of tez to the candidate’s address. Unfortunately, division of tez is not a trivial operation in smartpy. To achieve our desired result, we need to use it is defined as follows: sp.splitTokens. In smartpy's reference manual sp.split_tokens(m, quantity, totalQuantity): Computes m * quantity / totalQuantity. After some simple conversion, our sp.send(candidate, sp.split_tokens(sp.balance, sp.as_nat(self.data.ballot[candidate].numberOfVotes), sp.as_nat(self.data.totalNumberOfVotes)))translates to sending balance * numberOfVoters / totalNumberOfVotes. After doing that for each candidate, our balance should be zero and we can end the contract.

Final Notes

Apart from that, you can see that our final code also includes tests — you should *always* test your contract (after all, you want to make sure it works well before using it in the real world). Explaining how exactly the tests work is out of scope for this tutorial. However, you can find a detailed tutorial on this topic at . In the next part of this tutorial, we will see how we can interact with our created contract in our SwiftUI app. See you there!

Originally published at https://www.ackee.cz on February 26, 2020.

--

--