This is a continuation of the Going Dutch Smart Contract project that I started on 2nd Sep 2017. It has been a month, which is probably the equivalent of a year if you count in blockchain-time. Geth has gone from 1.6.7 to 1.7.2 and after upgrading my setup, I had to let it run overnight (in fast mode!) to sync my node to the block again.
Objective
The objective of this project is to code a Dapp so that folks with a mobile device can record their share of supper expenses and view them. To do this, I let my Dapp run in Status. I wrote a blogpost about Status last week. Here’s the logic.
Logic
Mark and Jack returns in this project. Today, Mark whips out his phone, login to Status, and browses to the Go Dutch Dapp.
He sees that he has contributed $71.50 to the kitty till-date while Jack has only contributed a meager $16.50. Together, they have $65.20 in the kitty.
Mark’s feeling rich, so he contributes another $5.20. His Ethereum wallet pops up for him to confirm the transaction.
It takes a while for the Ethereum Blockchain to record this transaction. Record is updated, and Mark’s total contribution increases to $76.70 and total in the kitty increases to $70.40.
The buddies then goes out to party, and spent $10.25. One of them comes back to update the spend, and then confirms it.
It takes a while for the Ethereum Blockchain to record this transaction. Once done, it now says that the total in the kitty is $60.15.
Codes
The Dapp makes calls to the Smart Contract functions of godutch.sol. My codes are in my Github repository. index.html is self explanatory, but I will like to highlight some of the codes from app.js.
if (typeof web3 !== 'undefined') {
console.warn("Using web3 detected from external source like Metamask")
// Use Mist/Status/MetaMask's provider
window.web3 = new Web3(web3.currentProvider);
}
else {
console.warn("No web3 detected. Falling back to http://localhost:8545.");
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
Here, we check if the browser that is running this Dapp supports web3 – Ethereum JavaScript API. If you have installed Metamask, the Google Chrome plugin, or Mist, or Status (on the mobile), then it works. Or else, it falls back to use the Web3 provider on the server. If you have configured your geth node to run at, say, http://hello.com:8545, then that’s what it will use. You wouldn’t want to do this in a live deployment because you will then be paying your ETH to let others smart contracts.
//updates the contribution of each friend
function updateAllContributions(){
let friendNames = Object.keys(friends);
for (var i = 0; i < friendNames.length; i++) {
let name = friendNames[i];
Godutch.deployed().then(function(contractInstance) {
contractInstance.totalContrib(name).then(function(v) {
$("#" + friends[name]).html(parseFloat(v.toString())/100);
})
});
}
//already updated, so we can clear this message
$("#msg").html("");
}
This is the function to update contribution from every person in the contract. Notice that all we are doing here is calling the totalContrib function in godutch.sol by passing in the name of every person in the contract using a loop. Here’s the way it was called in truffle console.
godutch.deployed().then(function(contractInstance) {contractInstance.totalContrib('Jack').then(function(v) {console.log(v)})})
Solidity accepts only whole numbers, but Mark and I spend in dollars and cents. Thus every transaction that we make is divided by 100.
Here’s the function to find out what’s the total amount of money in the kitty.
//this updates the total amount of money there is in the kitty
function updateKitty(){
Godutch.deployed().then(function(contractInstance) {
contractInstance.whatIsOurPool().then(function(v) {
$("#kitty").html(parseFloat(v.toString())/100);
$("#msgspend").html("");
})
});
}
Here’s how a Solidity function call in truffle console would look like:
godutch.deployed().then(function(contractInstance) {contractInstance.whatIsOurPool().then(function(v) {console.log(v)})})
Here’s how to make a contribution.
Godutch.deployed().then(function(contractInstance) {
contractInstance.contribute(friendName, contribution*100, {gas: 140000, from: web3.eth.accounts[0]}).then(function(v) {
updateAllContributions();
updateKitty();
})
});
And here’s how it looks like when executed in truffle console:
godutch.deployed().then(function(contractInstance) {contractInstance.contribute('Mark', 140).then(function(v) {console.log(v)})})
I multiply contribution by 100 because Mark and I pay in dollars and cents but values must be stored without decimals in the Smart Contract. Notice also that I can set a gas price for this transaction. If I leave this out, it will use the gas price determined by the last few block’s median gas price.
And here’s how to spend.
Godutch.deployed().then(function(contractInstance) {
contractInstance.spend(spendamount*100, {gas: 140000, from: web3.eth.accounts[0]}).then(function(v) {
updateKitty();
})
});
This is how executing from the truffle console would have looked like
godutch.deployed().then(function(contractInstance) {contractInstance.spend(230).then(function(v) {console.log(v)})})
What’s Next?
This was a useful project to understand enough about Ethereum, Solidity and the Truffle Framework to develop something useful. There is a lot more to improve, for example:
- Tracking the person who logs in to use his account to make contribution instead of letting him select Mark or Jack as he wishes (although I am quite sure Mark wouldn’t pay for me).
- Allowing more friends to register themselves instead of hard-coding this smart contract and Dapp to serve only Mark and Jack.
- Build in the purchase of Go-Dutch tokens (e.g. 1 Go-Dutch = 1 SGD) so that a friend can use real money in the bank to purchase Go-Dutch tokens and use these Go-Dutch tokens as a record of how much money he has put into a common bank account.
- You can integrate this with e-banking too! OCBC now has a Pay Anyone API that lets you write programs to send money to anyone.
Special thanks to Mahesh for his post on Medium where this entire series of Ethereum projects got its inspiration from. Visit his tutorials at https://www.zastrin.com/ if you wish to do more!
Photo by Kyle Loftus on Unsplash