WEB3DEV

Cover image for Cunhando um NFT em um aplicativo Android ( Parte 2 )
Adriano P. Araujo
Adriano P. Araujo

Posted on

Cunhando um NFT em um aplicativo Android ( Parte 2 )

6. Configure a configuração

Crie um projeto android em branco. Dentro do diretório inicial, crie um arquivo chamado apikey.properties. Em seguida, adicionaremos os valores obtidos nas etapas anteriores.


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

Para uma recapitulação:

  • Obtivemos o WALLET_ADDRESS pegando a primeira chave pública após executar o comando ganache.

  • Adquirimos o CONTRACT_ADDRESS após rodarmos o truffle migrate --network development e pegamos o endereço do contrato da seção 1_deploy_contract.js.

  • Obtivemos as SEMENTES após executarmos o comando ganache e assim, a semente gerada.

Dentro do build.gradle ( module ), em dependências, adicione a biblioteca web3j.


//Adiciona suporte para web3j

    implementation 'org.web3j:core:4.8.7-android' 

Enter fullscreen mode Exit fullscreen mode

Adicione as configurações dentro da seção defaultConfig do arquivo build.gradle.


// Carrega a configuração do arquivo apikey.properties 

 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

Não se esqueça de adicionar permissões de internet dentro do arquivo AndroidManifest.xml adicionando a linha abaixo a tag <application.


<uses-permission android:name="android.permission.INTERNET" />

Enter fullscreen mode Exit fullscreen mode

7). Desenvolva o invólucro android

Usando a biblioteca web3j, podemos converter nosso arquivo solidity em um arquivo java para poder chamar os métodos que escrevemos no arquivo solidity.


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

Depois de executar este comando com sucesso, um novo arquivo java LemurNFT.java será gerado. Coloque o arquivo perto do arquivo MainActivity.kt.

8). Crie a interface do usuário

A interface do usuário é bem simples, temos um botão chamado MINT. Quando o botão é clicado, ele executa a função mintNFT no arquivo MainActivity.kt.


<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

O arquivo activity_main.xml inteiro se parece com isso:


<?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

O aplicativo deve ficar assim:

Descrição da imagem

9). Adicionando variáveis globais

No seu arquivo MainActivity.kt adicione as seguintes variáveis como sendo globais.


// dentro de qualquer código da sua aplicação

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

Este código carrega todos os arquivos de configuração do nosso arquivo apikey.properties e do arquivo BuildConfig.

Também temos uma variável de credenciais que será inicializada posteriormente e que é globalmente acessível por qualquer função.

10). Carregue as credenciais

Dentro do arquivo MainActivity.kt adicione a seguinte linha de código.


/***

*Cria as credenciais à partir de uma semente 

 */

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

Isso gera um par de chaves (uma chave pública e outra privada), para assinar nossas transações.

11). Carregue as credenciais

Dentro do arquivo MainActivity.kt adicione a seguinte linha de código.


/***

*Crie as credenciais à partir de uma semente 

 */

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

Isso gera um par de chaves (uma chave pública e outra privada), para assinar nossas transações.

12). Mostrar a resposta

Precisamos mostrar a resposta depois de postar a transação na blockchain. Com isso, usaremos um alerta de notificação. Adicione o seguinte código ao arquivo MainActivity.kt.


/**

 * Exibe a resposta como um alerta de notificação.

 */

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

A função pega uma sequência e a exibe em um alerta de notificação .

13). Cunhe um NFT

Aqui, a função mintNft está vinculada a um botão na interface principal do usuário. Depois que o botão é clicado:

  • As credenciais serão carregadas da função loadCredentials ( ).

  • Uma nova instância de web3j será criada, a qual será usada para se conectar ao nó.

  • Em seguida, carregamos o contrato inteligente, que é o contrato LemurNFT e fornecemos o endereço do contrato, a conexão WebSocket, as credenciais e o gas para as transações.

  • Em seguida, chamamos a função de contrato inteligente para cunhar um NFT, fornecendo o endereço da carteira para cunhar um NFT e o tokenURI.

  • Em seguida, efetuamos logout da resposta usando Log.e  e também exibimos a resposta através de um alerta de notificação.


/**

 *  Cunha um nft quando o botão mint é clicado.

 */

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

O MainActivity.kt ficará assim:


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() {



   // dentro de qualquer parte do código da sua aplicação

    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)

    }



    /**

     * Cunha um nft quando o botão mint é clicado.



     */

    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;

    }



    /**

     * Exibe a resposta como um alerta de notificação.

.

     */

    private fun showResponse(response: String){



        val duration  = Toast.LENGTH_LONG;

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

        toast.show();



    }



    /**

     * Cria uma instância web socket  web3j à partir do  url web socket.

     */

    private fun createWeb3j(): Web3j {

        val webSocketService = WebSocketService(webSocketUrl, true)

        try {

            webSocketService.connect()

        } catch (e: ConnectException) {

            e.printStackTrace()

        }

        return Web3j.build(webSocketService)

    }



    /***

     * Cria as credenciais à partir de uma semente .

     */

    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

Quando você clica no botão mint, depois de compilar e executar o aplicativo, um alerta de notificação deve aparecer com um recibo de transação.

14). Conclusão

Parabéns, você conseguiu criar um contrato inteligente NFT e interagir com ele a partir de um aplicativo Android.


Este artigo foi escrito por Peter Okwara e traduzido por Adriano P. de Araujo. O original em inglês pode ser encontrado aqui.

Top comments (0)