GoNetwork - Contribute Tools And Tutorials To The Developer Community

GoNetwork - On this occasion, we will discuss about tutorials and contributions for developer. ETHWaterloo represented the largest global Ethereum hackathon with participants coming from 32 countries. The 32 hour hack was judged by such notable names in the blockchain community including; Vitalik Buterin, Jeff Coleman, Brian Bondy, Joseph Lubin, Dmitry Buterin to name a few. Our submission Pocket won! We managed to produce a mobile-first bluetooth based tap and pay system using the Ethereum blockchain. We were the only native mobile product amongst the 400 participants.

Pocket by GoNetwork, named after pocket change, aims to solve a problem with financial literacy by implementing gamification, parental controls and transparency for youth leveraging the Ethereum blockchain. The offering allows parents to create assignable digital debit cards and claimable rewards for good behaviour such as decreased spending month to month and controlled spending across different categories (food,entertainment, etc.).

Our belief is in order for blockchain to reach consumer markets, mobile developers need to start adopting the technology. The goal of this and proceeding tutorials draws on our experience and should get mobile devs to a point of prototyping. As GoNetwork grows we will continue to contribute tools and tutorials to the developer community.

This tutorial is based on a hackathon entry i.e. no code audits; as such this is not production quality code. That being said, lets get started.

You’ll need the following tools installed, I list my version numbers alongside:

  • node v7.9.0 & npm 4.2.0
  • bower 1.8.2
  • react-native 0.49.3 and react-native-cli 2.0.1
  • xcode 8.2.1
  • testprc v4.1.3


TLDR; Of course you can just grab the code and skip all the details if you wish. The source can be found at: https://github.com/gonetwork-project/mobile-dev-tutorials.

We won't be running an Ethereum node on our mobile device, if you’re looking details for that, check out : https://github.com/ethereum/go-ethereum/wiki/Mobile:-Introduction.

Instead we will opt for methods inspired by status-im team and the work of https://github.com/alinz/react-native-webview-bridge.

Our goal for this tutorial will be creating a simple react-native iOS app that connects to a local test Ethereum node and returns a set of Accounts. Here’s a crude picture of our iOS code architecture:
My personal experience with create-react-native-app results in issues: https://github.com/facebook/react-native/issues/14246 , so I opt to use
react-native init tutorial_1
react-native run-ios //confirm we can build
Now that you confirmed your app runs and builds lets get a simple webpage that loads web3.js and connects to local ethereum test node going. From the root directory run
bower install web3
This creates a folder which packages web3.js and all its dependencies:
./bower_components
Create a directory ./html and a file called ./html/web3.html and copy and paste the code below:
<html>
<head>
<title>
Here are the accounts from test rpc
</title>
</head>
<body>
<div>
  <h1>Accounts from TestRPC</h1>
  <ul id="accounts">
  </ul>
</div>
<script type="text/javascript" src="../bower_components/web3/dist/web3.min.js"></script>
<script type="text/javascript">
  /**
 * Sample Web3html
 * https://github.com/facebook/react-native
 * @flow
 * Author: Amit Shah
 */
var provider =   new Web3.providers.HttpProvider("http://localhost:8545");
if (!('toJSON' in Error.prototype))
      Object.defineProperty(Error.prototype, 'toJSON', {
          value: function () {
              var alt = {};
Object.getOwnPropertyNames(this).forEach(function (key) {
                  alt[key] = this[key];
              }, this);
              alt['ERROR'] = 1;
              return alt;
          },
          configurable: true,
          writable: true
  });
  CallbackHandler = function(data){
    alert(JSON.stringify(data));
  }
// var web3 = new Web3(new Web3.providers.HttpProvider("http://192.168.0.16:8545"));
  var web3 = new Web3(provider);
  function GetAccounts(){
  if(web3){
      try
      {
        var accounts = web3.eth.accounts;
        return accounts;
      }catch(e){
        CallbackHandler(e);
      }
}else{
      CallbackHandler("ERROR, NO WEB3.JS CONTEXT");
    }
    return [];
  }
var accounts = GetAccounts();
  for(var i=0; i < accounts.length; i++){
    var node = document.createElement("LI");
    var textnode = document.createTextNode(accounts[i]);
    node.appendChild(textnode);
    document.getElementById("accounts").appendChild(node);
}
</script>
</body>
</html>
Lets test web3.html. Move to the command line and start testrpc. This starts a test Ethereum node with rpc enabled at http://localhost:8545. Now open chrome and navigate to web3.html. When the page loads you should see something like this:

Great, you have a very simple webpage that connects to your local Ethereum node. Now lets wire this to iOS. Lets first download and install the webview-bridge.
cd ./node_modules
git clone https://github.com/gonetwork-project/react-native-webview-bridge.git
cd..
react-native link
react-native run-ios 
If compilation fails you may have to clean and build the project from Xcode

Open Xcode, open $TUTORIAL_ROOT/ios/tutorial_1.xcodeproj

Run clean and build. After successful build, move back over to the command line and retry react-native run-ios. With successful compilation we can move on to updating App.js. Copy and paste the code from below and we will examine the various code blocks:
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */
import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  Button
} from 'react-native';
import WebViewBridge from 'react-native-webview-bridge';
const injectScript = `
  (function () {
    //https://stackoverflow.com/questions/18391212/is-it-not-possible-to-stringify-an-error-using-json-stringify
CallbackHandler=function(result){
        //marshall the data
        if(WebViewBridge){
          WebViewBridge.send(JSON.stringify(result));
        }
    }
    if (WebViewBridge) {
WebViewBridge.onMessage = function(message){
          try{
            if(message === "get_accounts"){
              var accounts = GetAccounts();
              CallbackHandler({result:accounts});
            }
          }catch(e){
            CallbackHandler(e);
          }
      }
    }
}());`;
//we will need this for futre work
var WVB_GLOBAL = null;
export default class App extends Component<{}> {
  onBridgeMessage(message) {
    try{
      if (this.refs['webviewbridge'] !== null) {
        var msg = JSON.parse(message);
        var accounts = msg.result;
        alert("react-native accounts array:"+accounts);
        }
    }catch(err){
}
  }
onButtonPress(){
    this.webviewbridge.sendToBridge("get_accounts");
}
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit App.js
        </Text>
        <WebViewBridge
              ref={(ref) => {this.webviewbridge = ref; WVB_GLOBAL = ref;}}
              onBridgeMessage={(m) => this.onBridgeMessage(m)}
              javaScriptEnabled={true}
              injectedJavaScript={injectScript}
              // If you run android, sorry you gotta deal with some local file stuff :()
              //source={() =>
              //   Platform.OS === 'ios' ? require('./html/web3.html') :
              //     { uri: 'file:///android_asset/path-to/the-linked-file.html' }}
              source={require('./html/web3.html')}
              style={styles.webview} />
        <Button
          onPress={() => this.onButtonPress()}
          title="Get Accounts"
          color="#841584"
          accessibilityLabel="Learn more about this purple button"
        />
</View>
);
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
   webview: {
    marginTop: 20,
    maxHeight: 200,
    width: 320,
    flex: 1
  },
});
Lets go through some interesting parts of this code. Firstly, we add the WebViewBridge into our render function:
<WebViewBridge
              ref={(ref) => {this.webviewbridge = ref; WVB_GLOBAL = ref;}}
              onBridgeMessage={(m) => this.onBridgeMessage(m)}
              javaScriptEnabled={true}
              injectedJavaScript={injectScript}
              // If you run android, sorry you gotta deal with some local file stuff :()
              //source={() =>
              //   Platform.OS === 'ios' ? require('./html/web3.html') :
              //     { uri: 'file:///android_asset/path-to/the-linked-file.html' }}
              source={require('./html/web3.html')}
              style={styles.webview} />
Interesting things to note:
  • We define a callback onBridgeMessage that will respond to information sent from web3.html
  • We define a property this.webviewbridge using react-natives ref props
  • We inject javascript with injectedJavascriptProperty. The javascript code will help us marshal messages between react-native and web3.html
  • We simply require('./html/web3.html') source. This has only been tested for iOS, android is known to have some issues referencing local files in a webview.

Lets take a look at injectScript

const injectScript = `
  (function () {
    //https://stackoverflow.com/questions/18391212/is-it-not-possible-to-stringify-an-error-using-json-stringify
CallbackHandler=function(result){
        //marshall the data
        if(WebViewBridge){
          WebViewBridge.send(JSON.stringify(result));
        }
    }
    if (WebViewBridge) {
WebViewBridge.onMessage = function(message){
          try{
            if(message === "get_accounts"){
              var accounts = GetAccounts();
              CallbackHandler({result:accounts});
            }
          }catch(e){
            CallbackHandler(e);
          }
      }
    }
}());`;
This script is appended to web3.html and redefines the CallbackHandler in web3.html. The redefined CallbackHandler will callJSON.stringifyon our account data before sending it back to react-native.

When that process happens, onBridgeMessage is invoked as a callback from react-native. If you press the “Get Accounts” button, you should see an alert modal pop up and list the very same accounts that were rendered in the web3.html test view.

And there you have it! You have just completed connecting to a local Ethereum node with react native. This is the very foundation of the next series of tutorials which will cover the following topics:
  • Creating and sending off-chain signed transactions
  • Creating and compiling contracts with truffle and interacting with them in react-native
  • Building a simple bluetooth tap-and-pay component
  • Stay Tuned and feel free to leave comments and feedback.

Important Information


Author: Bredd6767

Add your massage to every single people do comment here!

Click to comment