January 5, 2021 Adem Bilican No comments

How to run an Elastos full node on a Raspberry Pi

The following tutorial applies to a Raspberry Pi 4 running Ubuntu server, check this page to read more about Ubuntu server on RPi. We are going to build the ela and ela-cli binaries to run them on the RPi, for more information you can check the official GitHub repository of the Elastos node. Let’s start by building the binaries. Run the following commands on your RPi once connected to it (via SSH or direct access).

1 – Install go

sudo apt-get install golang-go

2 – Configure the different paths as follow

mkdir $HOME/dev
export GOPATH=$HOME/dev
export GOBIN=$GOPATH/bin
export PATH=$GOBIN:$PATH

3 – Clone the GitHub repository and checkout the latest tag (currently v0.5.1)

git clone https://github.com/elastos/Elastos.ELA.git
cd Elastos.ELA
git checkout tags/v0.5.1

4 – Build the binaries with the make command

make

The make command will build the ela and ela-cli binaries. To check that everything is in order, just run:

./ela --version
./ela-cli --version

Now that we built the ela and ela-cli binaries we are going to run an Elastos full node on the RPi, to do so:

5 – Create a new wallet

./ela-cli wallet create -p $PASSWORD

Replace $PASSWORD by your own password. This command will generate a new wallet and store your secure information to the keystore.dat file

6 – Start the node

echo $PASSWORD | nohup ./ela > /dev/null 2>output & 

Again, don’t forget to replace $PASSWORD by your own password you used above. And that’s it!

Congrats, you just started running an Elastos full node on your Raspberry Pi 😉 You can now use the REST API or JSON RPC to get more information about your node👍

Stay tuned for more Elastos on RPi related content. If you are interested in the topic, I am also building the Elabox, a plug-and-play hardware to run several Elastos services without any effort.

March 25, 2020 Adem Bilican 4 comments

Accepting Stripe payments (3D Secure ready) in React Native (iOS with Native Modules)

TL;DR you can already access the finished project on GitHub
Mobile app: https://github.com/ademcan/react-native-stripe
Back-end: https://github.com/ademcan/stripe-backend
This tutorial is also available as a video format on YouTube.

I was planning this blogpost since quite some time, and I thought now was the perfect time as some people were asking about it on Twitter. Stripe is a great platform to accept payments for your project. However, there is not official React Native library (they released a React library recently tho). Some people mentioned using Tipsi (https://github.com/tipsi/tipsi-stripe) but it hasn’t been updated for a while and is not an official library. Today, we are going to create a UI in React Native and use the official Stripe iOS SDK to accept payments in our mobile app. We will have to deal with some JavaScript and a tiny bit of Objective-C (no worries, just a tiny bit). Let’s get started!

The fist thing to do (if you haven’t already) is to have a Stripe account and create a new project. Then, go to the Developer > API keys settings and save your private and secret key somewhere, we are going to use them later. For our payment system to work we also need a back-end and we will use ExpressJS to implement a simple REST API. Without further ado, let’s do it 👍

1. Create a new React Native project

Skip this step if you already have a RN project. I will create a new one especially for this tutorial, so that we can also refer to it with its name. Open your command line tool and run:

npx react-native init StripeRN
cd StripeRN

2. Install Stripe iOS SDK

The Stripe iOS SDK is distributed via cocoapods, to install it open the ios/Podfile file and add the following line in the list of Pods:

pod 'Stripe'

Close the file and run the following commands on your command line:

cd ios
pod install

We now installed Stripe in our RN project 👌

3. Configure Stripe SDK

To configure the Stripe SDK we need to instantiate it via the AppDelegate.m file, to do so open the Xcode project ios/StripeRN.xcworkspace
and add the following line to your AppDelegate.m file:
1 – at the top of the file

#import <Stripe/Stripe.h>

2 – and the following lines just before the return YES; statement

self.rootViewController = rootViewController;
[Stripe setDefaultPublishableKey:@"pk_test_XXXXXXXXXX"]; // use your own pk_test Stripe key here

3 – don’t forget to update the pk_test key to your own.

Your AppDelegate.m file should look like below:

In addition add the following line to AppDelegate.h just before the @end statement

@property (nonatomic, strong) UIViewController *rootViewController;

Your AppDelegate.h should look like below:

If you are wondering why we need to declare the rootView UIViewController it’s to support the 3D Secure system. To read more about the 3D Secure system you can check the official Stripe documentation about authentication using 3D Secure.

4. Create an empty UIViewController for 3D Secure

To accept cards with the 3D Secure system we need to create a new UIViewController to take control of the validation flow. To do so create a new CheckoutViewController.m and CheckoutViewController.h files in XCode and add the following code:

5. Create the payment UI in React Native

We are going to create a simple UI to grab all the required information to process card payment. Open your App.js file and copy paste the following code to it:

5. Create Native Module to access the Stripe SDK from our React Native code

To be able to access the Stripe SDK from React Native we need to create a Native Module. To do so create a new StripeBridge.m and StripeBridge.h files in XCode and update their content to:

We created our StripeBridge Native Module and can access it via React Native by pressing the Pay button. The Native Module only contains one single function to accept payment. You can check the Stripe iOS SDK documentation for more parameters and customization. The idea is to pass the information we collected from the user in our React Native UI (JavaScript) to the iOS SDK via a bridge. The StripeBridge can then process the information received to finalize a payment (or call the 3D secure view if needed). Some simple conversions are required for the month and year (L12 and L13) values as they are passed as NSString and need to be converted to NSNumber.

6. Create a nodeJS back-end to take care of PaymentIntents

To be able to succesfully charge a customer you need to create a back-end solution to generate a PaymentIntent. Stripe requires a PaymentIntent in addition to the credit card information to validate a payment. For that purpose we will create a simple ExpressJS back-end following one of my previous blogpost: Creating a simple back-end with ExpressJS
Once done, we need to install the stripe package, run

yarn add stripe

We then need to update the index.js file and add an endpoint to return a PaymentIntent to our mobile app. Update your index.js as follow:

Don’t forget to update the stripe_sk on L24 to your own secret key and the amount you want to collect on L30. Every time the mobile app will connect to the /createStripePaymentIntent endpoint a new PaymentIntent will be returned. The PaymentIntent in addition to the credit card information will be used by the iOS SDK to confirm a payment.

6. Run the app

To test our code we need to run the app, open your terminal and run

react-native start

On Xcode, choose your simulator and press Run. You should see your app running 😍

Well done! You can now try the integration with a list of test cards provided by Stripe and see how the app reacts to different scenarios

Don’t hesitate to share if you enjoyed this tutorial 😎


We can work together

January 8, 2020 Adem Bilican No comments

Creating a simple back-end with ExpressJS

Today’s topic is ExpressJS, a web framework for NodeJS. You can use ExpressJS if you need any back-end program, for example for a web-app or a REST API. In this article, I will take you through the installation of ExpressJS and the creation of a very simple project.

1. Creating an empty nodeJS project

Let’s start with the installation. Open your terminal and create a new directory:

mkdir back-end
cd back-end

We then need to initialize a new node project, we will use the yarn package manager (you can also use npm of course)

yarn init

Answer the questions to finalize the initialization of the node project. You will see a new package.json file in your directory, that’s a good sign!

2. Installing the required packages

Now, let’s install the libraries we need:

  • nodemon: to help us automatically refresh and restart the server on any file change, very helpful to avoid stopping and restarting the server manually every time!
  • express: the NodeJS web framework
  • cors: to provide the required Middleware for Express to allow the CORS mechanism (to put in simple words: cors allows the communication between different servers)
  • body-parser: middleware to parse the request body object and give access to it via req.body
  • morgan: logger for nodeJS

Run the following commands to install all the packages:

yarn global add nodemon
yarn add express
yarn add cors
yarn add body-parser
yarn add morgan

Next, we will create the index.js file that will be called on npm start.

3. Implementing index.js

Run the following command on your terminal to create an empty index.js file

touch index.js

Add the following code to your index.js file (I have added more information as comments in the code)

// import all the required packages
const express = require("express");
const app = express();
const cors = require("cors");
const bodyParser = require("body-parser");
const logger = require("morgan");
// define port number
const port = process.env.PORT || 3001;

// instantiate express with the correct parameters
app.use(logger('dev'));
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// create a Router
const router = express.Router();

// example of a GET method that returns a simple "Hello World"
router.get('/', (req, res) => {
  res.send( "HELLO WORLD" );
});

// define the router to use
app.use('/', router);

// start express
app.listen(port, function() {
    console.log("Runnning on " + port);
});

module.exports = app;

4. Starting our server

Finally, start your webserver by running

nodemon index.js

You can now access the page returned by your web-server via the following URL:
localhost:3001
You should see the “Hello World” text returned by your server! Well done!
Now it’s time to add more routes to your Router with the following functions:

router.get('/', (req, res) => { });
router.post('/', (req, res) => { });

Have fun 😉


We can work together

Photo by unsplash-logoTaylor Vick on Unsplash

June 25, 2019 Adem Bilican No comments

What happened to Saturn’s sixth moon last week?

TLDR; be sure that your node is using the additional storage to write the blockchain data there

As Enter Elastos we are running 3 Elastos supernodes (Titan, Ganymede and Callisto). To have a better overview of the ecosystem and be ready in case of issue we decided to use different approaches to run the different supernodes. There are 3 approaches available to run a supernode: docker, debian packages and binaries. Titan was running the node based on the binary approach. Yesterday, our server was complaining about not having enough space which resulted in the supernode going down and its status changing to inactive. Although an additional 100 GB of SSD was mounted, the system wasn’t using it. So, what happened?

If your run a supernode with the debian package approach, the blockchain data is written to the /data folder, and that’s where our additional SSD was mounted. However, if you use the binary approach, the data is saved to a relative path from where you run the node and not seeing the additional storage (if you have mounted it to /data).

What should you do in such situation?

1. If you are using the debian package approach

1.1. Format (before running the node) and mount the additional SSD to /data. Your SSD should be called /dev/xvdb, you can check with the following command:

lsblk

If you see /dev/xvdb in the list just continue the steps as follow, otherwise adapt the name of your additional storage in the following commands.

sudo mkdir /data
sudo mkfs -t xfs /dev/xvdb
sudo mount /dev/xvdb /data

1.2. Follow the automated script installation procedure

2. If you are using the binary approach

2.1. Format (before running the node) and mount the additional SSD to /home/ubuntu/supernode as an example. Your SSD should be called /dev/xvdb, you can check with the following command:

lsblk

If you see /dev/xvdb in the list just continue the steps as follow, otherwise adapt the name of your additional storage in the following commands. In the example below we will be running the node from the /home/ubuntu/supernode.

sudo mkdir /home/ubuntu/supernode
sudo mkfs -t xfs /dev/xvdb
sudo mount /dev/xvdb /home/ubuntu/supernode

2.2. Follow the binary supernode procedure from your /home/ubuntu/supernode folder

3. How to solve the issue

If your supernode was already running and you are facing the same issue, here is what to do:
1. Stop all the running service (ela, did, token and carrier)
2. Mount your additional storage and move all the data there
3. Restart all the services from the new location
4. Create a new activation transaction

./ela-cli wallet buildtx activate --nodepublickey $YOUR_NODE_PUBLIC_KEY

5. Send the activation transaction

 
./ela-cli wallet sendtx -f ready_to_send.txn --rpcuser $YOUR_RPC_USERNAME --rpcpassword $YOUR_RPC_PASSWORD

You should see your supernode coming back to life in a few minutes!

My main mistake here was not to check where the data was written to. As the REST API was working properly and the node was running fine I didn’t check the data/chain folder where the blockcahin is saved to. I just guessed it was all fine, it wasn’t, but now it is 🙂
I would like to thank Song (@songsjun) and his amazing team/colleagues that took their time to help me on a Sunday, as well as KP (@pachhaisaab) for putting all this information online and sharing his knowledge with the community. I am also somehow happy that this issue happened now (no penalty period) so that we are aware of it in case it happens to any other supernode.

May 11, 2019 Adem Bilican No comments

How to deal with the keyboard appearance in React Native?

Photo by unsplash-logoVincent Yee on Unsplash

    Controlling the appearance of the keyboard is a big headache for mobile app developers. The keyboard should appear smoothly and fit in the user interface without blocking any element. Several solutions exist in React Native to deal with that issue: one can use the KeyboardAvoidingView component or one of the several npm packages that are doing the work for you. Finally, it is also possible to manually take care of the user interface adaptation to the keyboard appearance.
    In this tutorial, we will create a simple view that requires user input (thus keyboard appearance) and that will adapt its component sizes/positions based on the keyboard visibility. We will create a simple view asking the user to fill in the 12 secret words to access a cryptocurrency wallet, the mnemonic. Once the user has provided the mnemonic, the keyboard will disappear and the view components will adapt to their new positions/sizes.
So let’s get started.

1. Create a new React Native app

    Open your terminal and run the following command to create a new React Native project:

react-native init enterMnemonicView

2. The code

    Contrary to the other tutorials, I am giving the whole code here at once first and we’ll go to the details below. Go to your newly created React Native project and open the App.js file, remove its content and add the one below:

import React from 'react';
import {
  Text, View, TextInput, Image, Keyboard, LayoutAnimation, ImageBackground, TouchableHighlight, StyleSheet,
} from 'react-native';

export default class ImportWallet extends React.Component {

  // state
  state = {
    counter: 1,
    word1: '',
    word2: '',
    word3: '',
    word4: '',
    word5: '',
    word6: '',
    word7: '',
    word8: '',
    word9: '',
    word10: '',
    word11: '',
    word12: '',
    topHeight: 150,
    complete: false,
    marginTop: 100,
    marginBottom: 30,
  }

  keyboardDidShowListener = {}
  keyboardDidHideListener = {}

  // add listeners on componentWillMount()
  componentWillMount () {
    Keyboard.addListener('keyboardDidShow', (e) => this.keyboardDidShow(e));
    Keyboard.addListener('keyboardDidHide', (e) => this.keyboardDidHide(e));
  }

  // remove listeners on componentWillUnmont()
  componentWillUnmount () {
    this.keyboardDidShowListener.remove()
    this.keyboardDidHideListener.remove()
  }

  // fired when keybord appears
  keyboardDidShow (e) {
    let newSize = e.endCoordinates.height
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
    this.setState({
      marginTopMenu: 0,
      marginTop: 50,
      topHeight: 100,
      marginBottom: newSize
    })
  }

  // fired when keyboard disappears
  keyboardDidHide (e) {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
    this.setState({
      marginTopMenu: 100, 
      marginTop: 100,
      topHeight: 150,
    })
  } 

  // will check the user input and create a new block when the user presses the [space] button
  _onMnemonicChange = (text) => {
    const lastChar = text[text.length - 1];
    // check for [space]
    if (lastChar === ' ') {
      this.textInput.clear()
      // update the state accordingly
      switch (this.state.counter) {
        case 1:
          this.setState({ word1: text, counter: this.state.counter + 1 });
          break;
        case 2:
          this.setState({ word2: text, counter: this.state.counter + 1 });
          break;
        case 3:
          this.setState({ word3: text, counter: this.state.counter + 1 });
          break;
        case 4:
          this.setState({ word4: text, counter: this.state.counter + 1 });
          break;
        case 5:
          this.setState({ word5: text, counter: this.state.counter + 1 });
          break;
        case 6:
          this.setState({ word6: text, counter: this.state.counter + 1 });
          break;
        case 7:
          this.setState({ word7: text, counter: this.state.counter + 1 });
          break;
        case 8:
          this.setState({ word8: text, counter: this.state.counter + 1 });
          break;
        case 9:
          this.setState({ word9: text, counter: this.state.counter + 1 });
          break;
        case 10:
          this.setState({ word10: text, counter: this.state.counter + 1 });
          break;
        case 11:
          this.setState({ word11: text, counter: this.state.counter + 1 });
          break;
        case 12:
          this.setState({word12: text, counter: this.state.counter + 1 , complete: true});
          break;
        default:
          break;
      }
    }
  }

  // render
  render() {
    return (
      <ImageBackground source={require('./resources/images/main_background.png')} style={{flex:1, height:this.state.topHeight }}>
        <View style={{height: 100, width: 360, borderRadius: 10, borderColor: 'black', alignSelf: 'center', marginTop: this.state.marginTop, backgroundColor: 'white', shadowColor: '#000000', shadowRadius: 10, shadowOpacity: 1.0, justifyContent: 'center' }}>
          <Text style={{textAlign: 'center', fontSize: 24}}>ENTER MNEMONIC</Text>
        </View>

        <View style={{flex:1,  marginTop: this.state.marginTopMenu}}>

          <View style={{flexDirection:'row'}}>
            {this.state.word1 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word1}</Text>
              </View>
              :
              <View ></View>
            }

            {this.state.word2 != '' ?
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word2}</Text>
              </View>
              :
              <View></View>
            }

            {this.state.word3 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word3}</Text>
              </View>
              :
              <View></View>
            }
          </View>

          <View style={{flexDirection:'row', height:70}}>
            {this.state.word4 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word4}</Text>
              </View>
              :
              <View></View>
            }

            {this.state.word5 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word5}</Text>
              </View>
              :
              <View></View>
            }

            {this.state.word6 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word6}</Text>
              </View>
              :
              <View></View>
            }  
          </View>

          <View style={{flexDirection:'row', height:70 }}>
            {this.state.word7 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word7}</Text>
              </View>
              :
              <View></View>
            }

            {this.state.word8 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word8}</Text>
              </View>
              :
              <View></View>
            }

            {this.state.word9 != '' ? 
              <View style={styles.mnemonic_word}>
                <Text style={{color:'white'}}>{this.state.word9}</Text>
              </View>
              :
              <View></View>
            }
            </View>

            <View style={{flexDirection:'row', height:70}}>

              {this.state.word10 != '' ? 
                <View style={styles.mnemonic_word}>
                  <Text style={{color:'white'}}>{this.state.word10}</Text>
                </View>
                :
                null
              }

              {this.state.word11 != '' ? 
                <View style={styles.mnemonic_word}>
                  <Text style={{color:'white'}}>{this.state.word11}</Text>
                </View>
                :
                null
              }

              {this.state.word12 != '' ? 
                <View style={styles.mnemonic_word}>
                  <Text style={{color:'white'}}>{this.state.word12}</Text>
                </View>
                :
                null
              }
            </View>

          <View style={{flex:1, flexDirection:'row', alignItems:'flex-end'}}>
          {this.state.complete ? 
            <View style={{flex:1, bottom:50}}>
              <TouchableHighlight onPress={() => this.props.navigation.navigate("ProvidePwd") } underlayColor='#172D39' style={styles.action_button_above}>  
                <Text style={styles.button_text}>IMPORT</Text>
              </TouchableHighlight>

              <TouchableHighlight onPress={() => this.props.navigation.navigate("ProvidePwd") } underlayColor='#172D39' style={styles.action_button_second}> 
                <Text style={styles.button_text_second}>CLEAR</Text>
              </TouchableHighlight>
            </View>
          : 
            <View style={{flex:1, height:100, marginBottom: this.state.marginBottom}}>  
              <TextInput ref={input => { this.textInput = input }} onChangeText={ (text) => this._onMnemonicChange(text) } autoCapitalize='none'  style={{ marginTop: 10, backgroundColor: 'white', height: 70, borderColor: 'black', borderWidth:1, borderRadius:30}}/>
            </View>
          }
          </View>

        </View>
        </ImageBackground>
    );
  }
}


// styling
const styles = StyleSheet.create({
  action_button_above: {
    justifyContent: 'center',
    alignSelf: 'center',
    width: 270,
    height: 60,
    backgroundColor: '#172D39',
    borderRadius: 30,
    marginBottom: 20,
  },
  action_button_second: {
    justifyContent: 'center',
    alignSelf: 'center',
    width: 270,
    height: 60,
    backgroundColor: 'white',
    borderColor: '#172D39',
    borderWidth: 1,
    borderRadius: 30,
    marginBottom: 20,
  },
  button_text: {
    color: 'white',
    textAlign: 'center',
    fontSize: 24,
  },
  button_text_second: {
    color: '#172D39',
    textAlign: 'center',
    fontSize: 24,
  },
  mnemonic_word: {
    flex: 1,
    height: 50,
    alignItems: 'center',
    justifyContent: 'center',
    marginLeft: 10,
    marginRight: 10,
    backgroundColor: '#6C5D81',
    borderRadius: 10,
    marginTop: 20
  },
});

3. Explanation

3.a. Show/hide keyboard listerners

    The first part of the code is taking care of the keyboard appearance. The code needs to be aware of the keyboard visibility to adapt the view accordingly, that’s why we need to instantiate and implement our listeners.
We instantiate our listeners and tell React Native to take care of them at mount and unmount as follow:

keyboardDidShowListener = {}
keyboardDidHideListener = {}

// add listeners on componentWillMount()
componentWillMount () {
  Keyboard.addListener('keyboardDidShow', (e) => this.keyboardDidShow(e));
  Keyboard.addListener('keyboardDidHide', (e) => this.keyboardDidHide(e));
}

// remove listeners on componentWillUnmont()
componentWillUnmount () {
  this.keyboardDidShowListener.remove()
  this.keyboardDidHideListener.remove()
}
3.a. Adapting the view on keyboard show/hide

    We can now check when the keyboard appears/disappears and therefore control the interface according to the visibility of the keyboard. On the render() function we adapted our main View to have some position related values defined in the local state (see L.119 for an example), so that we can play with them. We can now change these values according to the visibility of the keyboard using this.setState() function.

// fired when keybord appears
keyboardDidShow (e) {
  let newSize = e.endCoordinates.height
  LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
  // adapt component positions by updating the local state values
  this.setState({
    marginTopMenu: 0,
    marginTop: 50,
    topHeight: 100,
    marginBottom: newSize
  })
}

// fired when keyboard disappears
keyboardDidHide (e) {
  LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
  // adapt component positions by updating the local state values
  this.setState({
    marginTopMenu: 100, 
    marginTop: 100,
    topHeight: 150,
  })
}

In the end the whole process looks like the image below:

The whole source code is also available on GitHub.

Sources:
React Native’s LayoutAnimation is Awesome
Avoiding the Keyboard in React Native
Let’s Get Moving: An Introduction to React Native Animations — Part 1

February 15, 2019 Adem Bilican No comments

How to add a linter to your React Native project

The definition of linting on Wikipedia is pretty clear :”Lint, or a linter, is a tool that analyzes source code to flag programming errors, bugs, stylistic errors, and suspicious constructs”.

Clean code

Photo by unsplash-logoJames Pond on Unsplash

By using a linter in your React Native project you’ll be able to catch code errors early on and correct them before it’s too late. For a React Native project, we will rely on ESLint, and this is how we are going to do it:

1. Install the linter plugin for your IDE

I am using VSCode and a great Linter plugin is ESLint. There are usually several plugin alternatives for the most common IDEs, go and grab your favorite.

2. Install ESLint

The eslint package is the tool that will check for errors in our code. Open the command line, switch to your React Native project folder and run:

npm install eslint --save-dev

3. Install the Babel parser

We need the Babel parser to allow ESLint to check for code written using the ES7 syntax, Flow or TypeScript types.

npm install babel-eslint --save-dev

4. Get a list of rules for ESLint

For ESLint to properly work we need to configure ESLint with a list of rules. You can write the instructions yourself but there are already existing solutions, so we will just pick one of them.
Here are a few:
Airbnb JavaScript Style Guide() {
ESLint-plugin-React
ESLint plugin for React Native
We will continue with the esling-plugin-react-native. To install it, run:

npm install eslint-plugin-react-native --save-dev

5. Add the .eslintrc file to your project

To configure ESLint we need to create a .eslintrc file at the root of the project. Open your text editor and add the following to your .eslintrc file:

{
    "plugins": [
        "react-native"
    ],
    "extends": [
        "eslint:recommended",
        "plugin:react-native/all"
    ],
    "parser": "babel-eslint",
    "env": {
        "react-native/react-native": true
    },
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        }
    },
    "rules":{
        "react-native/no-unused-styles": 2,
        "react-native/split-platform-components": 2,
        "react-native/no-inline-styles": 2,
        "react-native/no-color-literals": 2,
        "react-native/no-raw-text": 2
    }
}

As soon as you save your .eslintrc file, you should see a lot of errors showing up in your code. No worries, these are probably some styling or import related issues, go ahead and fix them. You can now enjoy you clean code😉


We can work together

Share this post on social media:

February 11, 2019 Adem Bilican No comments

Write and compile your first Dapp using Solidity and Node.js

There are already several tutorials of that kind available on the Internet. However, I couldn’t follow any of them from the begining to the end without issues, so here is my own tutorial about how to write and compile your very first smart contract for the Ethereum blockchain. This first article is all about the Dapp code and compiling, a second article about how to deploy our app on the network will follow.

A smart contract corresponds to code instructions that are supposed to run on the network. In the case of Ethereum, a runtime environment called EVM (Ethereum Virtual Machine) takes care of running smart contracts. The instructions of the smart contract are written using the Solidity programming language. There are 2 essential steps to successfully run a smart contract on the network: compiling and deploying. Compiling the smart contract will generate a bitcode that can be later deployed on the network. So, let’s get ready to write our first smart contract!

Required tools

The only tools that you need to follow this tutorial are Node.js and npm installed in your machine.

1. Initialize a new node project

Open your terminal and create a new package.json using the npm command line tool:

npm init helloWorldContract

Confirm all the steps by pressing Enter or adapt the answers if needed. This will create a new package.json file containing all the information provided above.

2. Install solc

The npm solc package is a JavaScript library for the solidity compiler. We will use the solc package to compile our smart contract so that it is ready to be deployed on the network.

npm i solc

3. Write the smart contract

The next step is to write our smart contract. There are several essential points to write a smart contract properly:

  1. a smart contract always starts with the “pragma solidity ^0.5.2;” definition, where 0.5.2 is the version of the Solidity compiler
  2. a smart contract is defined by the “contract” keyword followed by its name
  3. a list of variables and functions defines what the smart contract is meant to do

Copy paste the code below to your text editor and save the file as Hello.sol

pragma solidity ^0.5.2;
contract HelloWorld {
    uint256 counter = 5;
    function increment() public {  
        counter++;
    }
    function decrement() public { 
        counter--;
    }
}

In this example we declared a counter variable of type uint256 and initialized it to 5. We then defined 2 functions in our smart contract; the first one to increment our counter and the second one to decrement it.

4. Write the compiler code

We now need to write the JavaScript code that will compile our smart contract. Create a new file, save it as compileSol.js and add the following code to it

const path = require('path');
const fs = require('fs');
const solc = require('solc');

const helloPath = path.resolve(__dirname, 'Hello.sol');
const hellosol = fs.readFileSync(helloPath, 'UTF-8');

var input = {
	language: 'Solidity',
	sources: {
		'hello.sol': {content : hellosol}
    },
    settings: {
		outputSelection: {
			'*': {
				'*': [ '*' ]
			}
		}
	}
};

var output = JSON.parse(solc.compile(JSON.stringify(input)))
for (var contractName in output.contracts['hello.sol']) {
	console.log(contractName + ': ' + output.contracts['hello.sol'][contractName].evm.bytecode.object)
}

5. Compile

Run the compiler code on your terminal as below

node compileSol.js

The terminal will show you the generated bitcode corresponding to our HelloWorld smart contractas below:

HelloWorld: 6080604052600560005534801561001557600080fd5b5060b7806100246000396000f3fe6080604052348015600f57600080fd5b5060043610604f576000357c0100000000000000000000000000000000000000000000000000000000900480634f2be91f1460545780636deebae314605c575b600080fd5b605a6064565b005b60626077565b005b6000808154809291906001019190505550565b60008081548092919060019003919050555056fea165627a7a7230582010eb14dc210d8b3d190848ce79ded65e30d7502c032655c7889d2fa7d35d3f1d0029

This is what we will need to publish our smart contract to the network. I will explain more in details about how to publish the contract on the network in the next blogpost of the series.


We can work together

Share this post on social media:

November 9, 2018 Adem Bilican 2 comments

How to create a react-native bridge library for iOS

React-Native allows user to create bridges to access native code from JavaScript. Once you have created your own bridges you might want to share them with the community. This article will explain in a few simple steps how to do so.

1. Create a new project with react-native-create-library

Open your terminal and run

react-native-create-library --package-identifier org.domain --platforms android,ios native-bridge

This will create a new project name react-native-native-bridge with all the required files in there.

2. Implement your bridge

Open the Xcode project located in the react-native-native-bridge/ios folder and edit the RNNativeBridge.m file to add your bridge functions accordingly. Here is a simple example that will return “Hello from Xcode!” when called in React-Native

RCT_EXPORT_METHOD(greetings: (RCTResponseSenderBlock)callback){
    callback(@[[NSNull null], @"Hello from Xcode!" ]);
}

If you are not familiar with native modules, go check the great documentation here.

3. Create a new npm package and publish it

Now that our hyper sophisticated bridge library is ready😉, we will propose it as an npm package on npmjs. You first need to create a new account on npmjs if you don’t have one yet. You can run

npm whoami

to check if you are logged in or not. If not, just run

npm adduser

and follow the instructions. Update the package.json file accordingly and run

npm publish

The new package will now be available to the community via the npm command and you can also see it at https://npmjs.com/package/react-native-native-bridge. You can refer to the documentation if you need any help.

4. Create a new React-Native demo app and use the package

Let’s create a new React Native project to test the npm package. Open your terminal and run

react-native init nativeBridgeTest

Install the react-native-native-bridge package and link it

npm install react-native-native-bridge
react-native link react-native-native-bridge

Open the App.js file of your React Native project and edit as follow

import RNNative Bridge from react-native-native-bridge
...
// create a new function in the App class
greetings = () => {
    RNNativeBridge.greetings( (err, res) => {
        console.log(res); 
    });
}
...
// Add a button in the render() function that will call the native function when clicked
<Button title="Greetings" onPress={this.greetings} />

This should print “Hello from Xcode!” in the logs.

Sources:
Creating a React Native Bridge Library


We can work together

Share this post on social media:

August 3, 2018 Adem Bilican No comments

How to convert a NSData hexstring to a NSString in Objective-C

At the QRL we are dealing a lot with hexstrings. Several of our API functions return results in hexstring format and it is sometimes important to be able to reuse them for another call. Here is how to convert a hexstring you received as NSData object (and looks like <24501f40 6cf57975 676b6d34 95d4cd7d 14541ddd 4d44fa4a f08e6faf 9d15252b>) to a string (in our case “24501f406cf57975676b6d3495d4cd7d14541ddd4d44fa4af08e6faf9d15252b”):

NSData *data = YOUR_NSDATA_HEXSTRING;
// we first need to get the length of our hexstring
// data.lenght returns the lenght in bytes, so we *2 to get as hexstring
NSUInteger capacity = data.length * 2;
// Create a new NSMutableString with the correct lenght
NSMutableString *mutableString = [NSMutableString stringWithCapacity:capacity];
// get the bytes of data to be able to loop through it
const unsigned char *buf = (const unsigned char*) [data bytes];

NSInteger t;
for (t=0; t<data.length; ++t) {
  NSLog(@"GLYPH at t : %c", buf[t]);
  NSLog(@"DECIMAL at t  : %lu", (NSUInteger)buf[t]);
  // "%02X" will append a 0 if the value is less than 2 digits (i.e. 4 becomes 04)
  [mutableString appendFormat:@"%02X", (NSUInteger)buf[t]];
}
NSLog(@"Hexstring: %@", mutableString);
// save as NSString
NSString * hexstring =mutableString;

You can check the decimal, hex and corresponding glyph here.

sources
SO question
String Format Specifiers [Apple dev]
Bits and Bytes

July 3, 2018 Adem Bilican 18 comments

How to call native Java functions from JavaScript for a React Native app (Android)

React Native is a great framework to develop mobile apps for iOS and Android with the help of JavaScript. However, at some point of your project you might need to call native functions. In React Native, invoking a native function is called bridging. In this article, I will explain how to implement a bridge communication between Java and JavaScript for your React Native based Android app.

1. Create a new react-native project or open an existing one

To create a new react-native project, open your terminal and enter the following command:

react-native init HelloWorld

This will create a new react-native app called HelloWorld with the corresponding android/ and ios/ folders containing your mobile app’s codes for the different platforms.

2. Open the project on Android Studio

Launch Android Studio and select File -> New -> Import Project… then select the HelloWorld/android folder to import to Android Studio. Your Android Studio Project window should look like this :

3. Create a new Java module

The first step to be able to use Java native code from react-native is to create a new Java module that extends the ReactContextBaseJavaModule class. To do so on the 1:Project pane of Android Studio right click on the com.helloworld folder and select New -> Java Class as shown below.

In the new window enter the following information and click OK:

Important note: in this tutorial, we will be using a callback so that your Java function can send some parameters back to JavaScript. Alternatively, one could also use a Promise (see here) or nothing at all if the main point is just to call a Java class without information going back and forth.
The newly create HelloWorldModule.java will open. You can remove the content of the file and add the following code:

package com.helloworld;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.uimanager.IllegalViewOperationException;

public class HelloWorldModule extends ReactContextBaseJavaModule {

    public HelloWorldModule(ReactApplicationContext reactContext) {
        super(reactContext); //required by React Native
    }

    @Override
    //getName is required to define the name of the module represented in JavaScript
    public String getName() { 
        return "HelloWorld";
    }

    @ReactMethod
    public void sayHi(Callback errorCallback, Callback successCallback) {
        try {
            System.out.println("Greetings from Java");
            successCallback.invoke("Callback : Greetings from Java");
        } catch (IllegalViewOperationException e) {
            errorCallback.invoke(e.getMessage());
        }
    }
}

4. Register the new Java module

Once your module is implemented, you need to register it. For the registration, you will need to create a new package. Create a new Java Class as you did earlier and call it HelloWorldPackage. Copy and paste the following code to your HelloWorldPackage.java file.

package com.helloworld;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.helloworld.HelloWorldModule;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class HelloWorldPackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        //this is where you register the module
        modules.add(new HelloWorldModule(reactContext));
        return modules;
    }
}

5. Register the new Java package

Finally, you need to properly register the new package. Open the MainApplication.java and modify it as follow

package com.helloworld;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new HelloWorldPackage()
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

We are simply adding the new HelloWorldPackage() code at line 26, the rest is unchanged.

6. Edit JavaScript code

It is now time to implement the JavaScript side of the app. We will create a simple TouchableOpacity element and call the native Java function on press of this element. Open the HelloWorld/App.js file with your favorite text editor and change it as below:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  TouchableOpacity,
  View
} from 'react-native';

// We are importing the native Java module here
import {NativeModules} from 'react-native';
var HelloWorld = NativeModules.HelloWorld;

type Props = {};
export default class App extends Component<Props> {

  // async function to call the Java native method
  async sayHiFromJava() {
    HelloWorld.sayHi( (err) => {console.log(err)}, (msg) => {console.log(msg)} );
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={ this.sayHiFromJava }>
              <Text>Invoke native Java code</Text>
         </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  }
});

7. Start the Android Virtual Device and run the app

On Android Studio click the small AVD manager icon () and start (or create a new one if you don’t have any existing one) your AVD. Then on your terminal enter the following command:

react-native run-android

You should see the following on your Android emulator

8. Invoke the sayHi() Java function from JavaScript

Open the 6:Logcat window of Android Studio to see the Logs and press the “Invoke native java code” button in the emulator. This action will call the native Java function and should indicate the following output in your logs:

I hope this tutorial was clear, let me know how it went for you in the comments😊

Sources:
https://facebook.github.io/react-native/docs/native-modules-android
https://blog.botreetechnologies.com/how-to-build-a-react-native-android-bridge-4166e114a990
https://www.dailydrip.com/topics/react-native/drips/using-android-native-modules.html


We can work together

Share this post on social media: