Minting an NFT on an android app (Part 2)
Tags: android, web3, blockchain, ipfs
Published: 2022-12-02 13:35:52

## 6. Set up the config 

Create a new blank android project. Within the home directory, create a file called _apikey.properties_. We will then add the values obtained from the previous steps.  

```console
WALLET_ADDRESS="0x42703e1F2CCB08583088D96d71d4549Be08b52a7" 
CONTRACT_ADDRESS="0x129Ff5b9D7C128527F3Be5ca5fb4F2E7A991482d" 
WEB_SOCKET_URL="[wss://550b-105-163-1-231.ngrok.io](https://550b-105-163-1-231.ngrok.io)"
SEED="truth manual elephant border predict castle payment suspect mimic insect wish acoustic"
TOKEN_URI=""
```

For a recap:
* We obtained the **WALLET_ADDRESS** by taking the first public key after running the *ganache* command.
* We obtained the **CONTRACT_ADDRESS** after running `truffle migrate --network development` and taking the **contract address** from the _1_deploy_contract_.js section.
* We obtained the **SEED** after running the **ganache** command and obtaining the seed generated.

  
Within the [_build.gradle_](https://github.com/peterokwara/lemur-nft/blob/7d660142b9a2815857a3a081724918825cf0f731/android/app/build.gradle#L49) (module) under dependencies, add the _web3j _library.
```
// Add support for web3j
    implementation 'org.web3j:core:4.8.7-android' 
```

Add the configurations within the [defaultConfig](https://github.com/peterokwara/lemur-nft/blob/7d660142b9a2815857a3a081724918825cf0f731/android/app/build.gradle#L24) section of the _build.gradle_ file.
```
 // Load configuration from the apikey.properties file
 buildConfigField("String", "WALLET_ADDRESS", apikeyProperties['WALLET_ADDRESS'])
 buildConfigField("String", "CONTRACT_ADDRESS", apikeyProperties['CONTRACT_ADDRESS'])
 buildConfigField("String", "WEB_SOCKET_URL", apikeyProperties['WEB_SOCKET_URL'])
 buildConfigField("String", "SEED", apikeyProperties['SEED'])
 buildConfigField("String", "TOKEN_URI", apikeyProperties['TOKEN_URI'])
```

Do not forget to add internet permissions within the [_AndroidManifest.xml_](https://github.com/peterokwara/lemur-nft/blob/7d660142b9a2815857a3a081724918825cf0f731/android/app/src/main/AndroidManifest.xml#L4) file by adding the line below to the `<application` tag.
```xml
<uses-permission android:name="android.permission.INTERNET" />
```

## 7. Develop the android wrapper

Using the _web3j _library, we can convert our solidity file into a java so that we can call the methods we have written in the solidity file.

```console
web3j generate truffle --truffle-json .\build\contracts\lemurNFT.json -o ..\android\app\src\main\java\ -p com.example.lemur
```

After running this command successfully, a new java file [_LemurNFT.java_](https://github.com/peterokwara/lemur-nft/blob/master/android/app/src/main/java/com/example/lemur/LemurNFT.java) will be generated.  Place the file close to the _MainActivity.kt_ file.


## 8. Create the UI

The user interface is pretty simple, we have a button called **MINT**. When the button is clicked, it runs the _mintNFT _function in the _MainActivity.kt_ file.

```xml
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="mintNft"
    android:text="@string/button_text"
    tools:layout_editor_absoluteX="161dp"
    tools:layout_editor_absoluteY="407dp" />
```
The whole [_activity_main.xml_](https://github.com/peterokwara/lemur-nft/blob/master/android/app/src/main/res/layout/activity_main.xml) file looks like this:
```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="LemurNFT"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="mintNft"
        android:text="@string/button_text"
        tools:layout_editor_absoluteX="161dp"
        tools:layout_editor_absoluteY="407dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

The app should look like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7uawrgio2ui1dqyprqd.jpg)

## 9. Adding global variables

In your _MainActivity.kt_ add the following variables as global.
```kotlin
// inside of any of your application's code
var walletAddress: String = BuildConfig.WALLET_ADDRESS;
var contractAddress: String = BuildConfig.CONTRACT_ADDRESS;
var webSocketUrl: String = BuildConfig.WEB_SOCKET_URL;
var seed: String = BuildConfig.SEED;
var tokenUri: String = BuildConfig.TOKEN_URI;
private lateinit var credentials: Credentials;
```
This code loads all the configuration files from our _apikey.properties _file and the BuildConfig file.

We also have a credentials variable that will be initialized later on, and that is globally accessible by any function.

## 10. Load the credentials

Within the _MainActivity.kt_ file add the following line of code.
```kotlin
/***
 * Create credentials from a seed.
 */
fun loadCredentials(){
    val masterKeypair = Bip32ECKeyPair.generateKeyPair(MnemonicUtils.generateSeed(seed, ""))
    val path = intArrayOf(44 or HARDENED_BIT, 60 or HARDENED_BIT, HARDENED_BIT, 0, 0)
    val x = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path)
    this.credentials = Credentials.create(x)
}
```
This generates a keypair (a public and private key) to sign our transactions.

## 11. Load the credentials

Within the MainActivity.kt file add the following line of code.
```kotlin
/***
 * Create credentials from a seed.
 */
fun loadCredentials(){
    val masterKeypair = Bip32ECKeyPair.generateKeyPair(MnemonicUtils.generateSeed(seed, ""))
    val path = intArrayOf(44 or HARDENED_BIT, 60 or HARDENED_BIT, HARDENED_BIT, 0, 0)
    val x = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path)
    this.credentials = Credentials.create(x)
}
```
This generates a keypair (a public and private key) to sign our transactions.

## 12. Show the response

We need to show the response after posting the transaction to the blockchain. With this, we will use a toast notification. Add the following code to the MainActivity.kt file.
```kotlin
/**
 * Display the response as a toast notification.
 */
private fun showResponse(response: String){

    val duration  = Toast.LENGTH_LONG;
    val toast = Toast.makeText(applicationContext, response, duration);
    toast.show();

}
```
The function takes in a string and displays it in a toast notification.

## 13. Mint an NFT

Here the mintNft function is tied to a button in the main user interface. Once the button is clicked:

* The credentials will be loaded from the *loadCredentials()* function. 
* A new instance of *web3j* instance will be created which will be used to connect to the node.
* We then load the smart contract which is the *LemurNFT* contract and provide the contract address, the WebSocket connection, the credentials, and the gas for the transactions.
* We then call the smart contract function to mint an NFT, providing the wallet address to mint an NFT to, and the *tokenURI*.
* We then log out the response using *Log.e *and* *also display the response through a toast notification.

```kotlin
/**
 * Mint an nft when the mint button is clicked.
 */
fun mintNft(view: View) {
    try {
        loadCredentials();
        val web3j: Web3j = createWeb3j()

        val nft: LemurNFT = LemurNFT.load(contractAddress, web3j, credentials, DefaultGasProvider())
        val transactionReceipt: TransactionReceipt = nft.mintNFT(walletAddress, tokenUri).send()

        Log.e("Response", transactionReceipt.toString());
        showResponse(transactionReceipt.toString());

    } catch (e: Exception){
        e.printStackTrace();
    }
    return;
}
```

The [MainActivity.kt](https://github.com/peterokwara/lemur-nft/blob/master/android/app/src/main/java/com/example/lemur/MainActivity.kt) will then look like this:

```kotlin
package com.example.lemur

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import org.web3j.crypto.Bip32ECKeyPair
import org.web3j.crypto.Bip32ECKeyPair.HARDENED_BIT
import org.web3j.crypto.Credentials
import org.web3j.crypto.MnemonicUtils
import org.web3j.protocol.Web3j
import org.web3j.protocol.core.DefaultBlockParameterName
import org.web3j.protocol.core.methods.response.EthGetBalance
import org.web3j.protocol.core.methods.response.TransactionReceipt
import org.web3j.protocol.websocket.WebSocketService
import org.web3j.tx.gas.DefaultGasProvider
import java.math.BigInteger
import java.net.ConnectException


class MainActivity : AppCompatActivity() {

    // inside of any of your application's code
    var walletAddress: String = BuildConfig.WALLET_ADDRESS;
    var contractAddress: String = BuildConfig.CONTRACT_ADDRESS;
    var webSocketUrl: String = BuildConfig.WEB_SOCKET_URL;
    var seed: String = BuildConfig.SEED;
    var tokenUri: String = BuildConfig.TOKEN_URI;
    private lateinit var credentials: Credentials;


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    /**
     * Mint an nft when the mint button is clicked.
     */
    fun mintNft(view: View) {
        try {
            loadCredentials();
            val web3j: Web3j = createWeb3j()

            val nft: LemurNFT = LemurNFT.load(contractAddress, web3j, credentials, DefaultGasProvider())
            val transactionReceipt: TransactionReceipt = nft.mintNFT(walletAddress, tokenUri).send()

            Log.e("Response", transactionReceipt.toString());
            showResponse(transactionReceipt.toString());

        } catch (e: Exception){
            e.printStackTrace();
        }
        return;
    }

    /**
     * Display the response as a toast notification.
     */
    private fun showResponse(response: String){

        val duration  = Toast.LENGTH_LONG;
        val toast = Toast.makeText(applicationContext, response, duration);
        toast.show();

    }

    /**
     * Create a web3j web socket instance from the web socket url.
     */
    private fun createWeb3j(): Web3j {
        val webSocketService = WebSocketService(webSocketUrl, true)
        try {
            webSocketService.connect()
        } catch (e: ConnectException) {
            e.printStackTrace()
        }
        return Web3j.build(webSocketService)
    }

    /***
     * Create credentials from a seed.
     */
    private fun loadCredentials(){
        val masterKeypair = Bip32ECKeyPair.generateKeyPair(MnemonicUtils.generateSeed(seed, ""))
        val path = intArrayOf(44 or HARDENED_BIT, 60 or HARDENED_BIT, HARDENED_BIT, 0, 0)
        val x = Bip32ECKeyPair.deriveKeyPair(masterKeypair, path)
        this.credentials = Credentials.create(x)
    }

}
```
When you click on the mint button, once you compile and run the application, a toast notification should show up with a transaction receipt.

## 14. Conclusion

Congratulations, you have been able to create an NFT smart contract and interact with it from an android app.