DEV Community

Cover image for Minting an NFT on an android app (Part 2)
Peter Okwara
Peter Okwara

Posted on • Edited on

Minting an NFT on an android app (Part 2)

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.

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="" 
Enter fullscreen mode Exit fullscreen mode

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 (module) under dependencies, add the _web3j _library.

// Add support for web3j implementation 'org.web3j:core:4.8.7-android' 
Enter fullscreen mode Exit fullscreen mode

Add the configurations within the defaultConfig 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']) 
Enter fullscreen mode Exit fullscreen mode

Do not forget to add internet permissions within the AndroidManifest.xml file by adding the line below to the <application tag.

<uses-permission android:name="android.permission.INTERNET" /> 
Enter fullscreen mode Exit fullscreen mode

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.

web3j generate truffle --truffle-json .\build\contracts\lemurNFT.json -o ..\android\app\src\main\java\ -p com.example.lemur 
Enter fullscreen mode Exit fullscreen mode

After running this command successfully, a new java file 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.

<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" /> 
Enter fullscreen mode Exit fullscreen mode

The whole activity_main.xml file looks like this:

<?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> 
Enter fullscreen mode Exit fullscreen mode

The app should look like this:

Image description

9. Adding global variables

In your MainActivity.kt add the following variables as global.

// 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; 
Enter fullscreen mode Exit fullscreen mode

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.

/*** * 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) } 
Enter fullscreen mode Exit fullscreen mode

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.

/*** * 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) } 
Enter fullscreen mode Exit fullscreen mode

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.

/** * 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(); } 
Enter fullscreen mode Exit fullscreen mode

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.
/** * 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; } 
Enter fullscreen mode Exit fullscreen mode

The MainActivity.kt will then look like this:

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) } } 
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)