[JAVA] [Ethereum] So führen Sie einen Vertrag mit web3j-Teil 2 aus

Artikelinhalt

Der folgende Artikel beschreibt, wie Sie einen Vertrag mit Web3j ausführen. In diesem Artikel erstellen Sie eine Java-Klasse für Vertragsoperationen und führen den Vertrag über diese Klasse aus.

So führen Sie einen Vertrag mit web3j aus

Mit dieser Methode erhöht sich mit zunehmender Anzahl von Verträgen die Anzahl von Java-Klassen um die Anzahl von Verträgen, deren Verwaltung kompliziert sein kann. Daher beschreiben wir die Ausführung durch Angabe der Vertragsadresse und des Funktionsnamens.

Umgebung

Mustervertrag

Der Vertrag stellt ERC20-Token mit Openzeppelin aus. Der Inhalt besteht darin, eine Klasse zu erstellen, die ERC20.sol erbt, und nur den Konstruktor vorzubereiten.

MyToken.sol


pragma solidity ^0.4.24;

import "node_modules/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {

    string public name = "OrgToken"; //Token-Name
    string public symbol = "ORG"; //Einheitennotation des Tokens
    uint public decimals = 18; //Anzahl der Nachkommastellen
    
    address public account = msg.sender;
    uint256 public _totalS = 10000000000000;

    constructor () public {
        super._mint(account, _totalS);
    }

    function balanceOf(address target) public view returns (uint256) {
        return super.balanceOf(target);
    }
}

Java-Klasse für Vertragsoperationen

Als nächstes kommt eine Java-Klasse, die ziemlich grob ist. Die Grundidee kann ausgeführt werden, wenn Sie die Vertragsadresse, den Funktionsnamen, die Argumente und den Rückgabewert kennen. Es ist gemacht.

MyTokenExec.Java


import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Uint;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Numeric;

public class MyContractExec {

    public static final Admin web3j = Admin.build(new HttpService("http://127.0.0.1:8545"));

    private static final String CONTRACT_ADDRESS = "0x715d4c293482e6f72e1cbb3b22a10fbdae3bd7b0";

    public static final String OWNER_ADDRESS = "0x945cd603a6754cb13c3d61d8fe240990f86f9f8a";
    public static final String TO_ADDRESS = "0x66b4e7be902300f9a15d900822bbd8803be87391";

    public static void main(String args[]) {

        MyContractExec exec = new MyContractExec();

        List<?> result = null;
        try {
            List<Type> inputParam = new ArrayList<>();

            //Kein Argument / Rückgabewert uint256
            result = exec.execFunction("totalSupply", inputParam, ResultType.INT);
            System.out.println("Total Supply : " + ((Uint)result.get(0)).getValue());

            // FROM_ADRESSE und ZU_Saldobestätigung der ADRESSE
            confirmBalance(OWNER_ADDRESS, TO_ADDRESS);

            //Mit Argument (Adresse,uint256) / Rückgabewert bool
            inputParam = new ArrayList<>();
            inputParam.add(new Address(TO_ADDRESS));
            inputParam.add(new Uint(BigInteger.valueOf(123456)));
            result = sendSignedTransaction(credentials, "transfer", inputParam, ResultType.BOOL);
            System.out.println( ((Bool)result.get(0)).getValue() );

            confirmBalance(OWNER_ADDRESS, TO_ADDRESS);

        }catch(IOException e) {
            e.printStackTrace();
        }
    }

    public static void confirmBalance(String ... args) throws IOException{

        MyContractExec exec = new MyContractExec();

        List<?> result = null;
        int i = 0;
        for(String address :args) {
            List<Type> inputParam = new ArrayList<>();
            //Mit Argument (Adresse) / Rückgabewert uint256
            inputParam.add(new Address(address));
            result = exec.execFunction("balanceOf", inputParam, ResultType.INT);
            System.out.println("Balance of ADDRESS[" + i + "] : " +  ((Uint)result.get(0)).getValue() );
            i++;
        }
    }

    /**
     *Ausführung einer Funktion, die keine Transaktion generiert (keine Wertaktualisierung)
     * @param functionName
     * @return
     * @throws IOException
     */
    public List<?> execFunction(String functionName, List<Type> args, ResultType type) throws IOException{

        Function function = new Function(
                functionName, args, Arrays.<TypeReference<?>>asList( getTypeReference(type) ));

        String encodedFunction = FunctionEncoder.encode(function);
        EthCall ethCall = web3j.ethCall(
                Transaction.createEthCallTransaction(
                        OWNER_ADDRESS, CONTRACT_ADDRESS, encodedFunction),
                DefaultBlockParameterName.LATEST)
                .send();

        String value = ethCall.getValue();
        return FunctionReturnDecoder.decode(value, function.getOutputParameters());
    }

    /**
     *Ausführung der Funktion, bei der die Transaktion stattfindet (Wert wird aktualisiert)
     * @param credentials
     * @param functionName
     * @param args
     * @param type
     * @return
     */
    public static List<?> sendSignedTransaction(Credentials credentials, String functionName, List<Type> args, ResultType type){

        Function function = new Function(
                functionName, args, Arrays.<TypeReference<?>>asList( getTypeReference(type) ));

        String encodedFunction = FunctionEncoder.encode(function);

        try {
            //Holen Sie sich Nonce-Wert
            EthGetTransactionCount ethTransactionCount =
                web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.PENDING).send();
            BigInteger nonce = ethTransactionCount.getTransactionCount();

            //Transaktionsgenerierung
            RawTransaction rawTransaction = RawTransaction.createTransaction(
                    nonce,
                    BigInteger.valueOf(1000),
                    BigInteger.valueOf(4700000),
                    CONTRACT_ADDRESS,
                    encodedFunction);

            //Unterschrift
            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
            String hexValue = Numeric.toHexString(signedMessage);

            //send
            EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();

            //Fehlerbestätigung
            if(ethSendTransaction.getError() != null){
               System.out.println(ethSendTransaction.getError().getMessage());
            }else {
                String value = ethSendTransaction.getResult();
                return FunctionReturnDecoder.decode(value, function.getOutputParameters());
            }
        }catch(IOException | ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static TypeReference<?> getTypeReference(ResultType type){

        TypeReference<?> typeReference = null;
        switch(type) {
        case ADDRESS:
            typeReference = new TypeReference<Address>() {};
            break;
        case BOOL:
            typeReference = new TypeReference<Bool>() {};
            break;
        case STRING:
            typeReference = new TypeReference<Utf8String>() {};
            break;
        case INT:
            typeReference = new TypeReference<Uint>() {};
            break;
        default:
            break;
        }
        return typeReference;
    }
}

ResultType.java


public enum ResultType {
	ADDRESS,
	BOOL,
	STRING,
	INT
}

Was Sie mit der Hauptmethode machen, ist einfach. Überprüfen Sie die Anzahl der ausgegebenen Token, überprüfen Sie den Kontostand und senden Sie Geld. Bestätigen Sie abschließend den Kontostand erneut.

Mit anderen Worten, wenn man sich auf die Schaffung eines Vertrags konzentriert, ist dies wie folgt.

  1. Funktionsausführung ohne Aktualisierung der Werte
  2. Funktionsausführung mit Wertaktualisierung

1. Funktionsausführung ohne Aktualisierung der Werte

Die erste ist die Ausführung einer Funktion, die den Wert nicht aktualisiert. In ERC20.sol gibt es "Gesamtangebot" und "Saldo von". Der Code lautet wie folgt.

MyTokenExec.java


    public List<?> execFunction(String functionName, List<Type> args, ResultType type) throws IOException{

        Function function = new Function(
                functionName, args, Arrays.<TypeReference<?>>asList( getTypeReference(type) ));

        String encodedFunction = FunctionEncoder.encode(function);
        EthCall ethCall = web3j.ethCall(
                Transaction.createEthCallTransaction(
                        OWNER_ADDRESS, CONTRACT_ADDRESS, encodedFunction),
                DefaultBlockParameterName.LATEST)
                .send();

        String value = ethCall.getValue();
        return FunctionReturnDecoder.decode(value, function.getOutputParameters());
    }

Was machst du

  1. Erstellen Sie eine Instanz von Function
  2. Binarisierungsfunktion
  3. Senden Sie über das Ethereum-Netzwerk
  4. Konvertieren Sie das zurückgegebene Ergebnis in Binär

In diesem Beispielcode gibt das Argument "execFunction" an, was der Aufrufer vom Rückgabetyp zurückgeben möchte. ResultType definiert, welche Klasse der in Solidität festgelegte Typ in Java als Aufzählungstyp behandelt wird. Ich versuche, die Klasse zurückzugeben, die dem Rückgabewert in der Methode "getTypeReference" entspricht.

Schließlich wird der als Binärdaten zurückgegebene Wert dekodiert und an den Aufrufer zurückgegeben.

2. Funktionsausführung mit Wertaktualisierung

Als nächstes folgt ein Funktionsaufruf mit einer Wertaktualisierung. Das ist ganz anders.

MyTokenExec.java


    public static List<?> sendSignedTransaction(Credentials credentials, String functionName, List<Type> args, ResultType type){

        Function function = new Function(
                functionName, args, Arrays.<TypeReference<?>>asList( getTypeReference(type) ));

        String encodedFunction = FunctionEncoder.encode(function);

        try {
            //Holen Sie sich Nonce-Wert
            EthGetTransactionCount ethTransactionCount =
                web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.PENDING).send();
            BigInteger nonce = ethTransactionCount.getTransactionCount();

            //Transaktionsgenerierung
            RawTransaction rawTransaction = RawTransaction.createTransaction(
                    nonce,
                    BigInteger.valueOf(1000),    //GAS
                    BigInteger.valueOf(4700000), //GASLimit
                    CONTRACT_ADDRESS,
                    encodedFunction);

            //Unterschrift
            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
            String hexValue = Numeric.toHexString(signedMessage);

            //send
            EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();

            //Fehlerbestätigung
            if(ethSendTransaction.getError() != null){
               System.out.println(ethSendTransaction.getError().getMessage());
            }else {
                String value = ethSendTransaction.getResult();
                return FunctionReturnDecoder.decode(value, function.getOutputParameters());
            }
        }catch(IOException | ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

Was machst du

  1. Erstellen Sie eine Funktionsinstanz
  2. Funktionsbinarisierung
  3. Holen Sie sich Nonce-Wert
  4. Transaktion generieren
  5. Unterschreiben
  6. Transaktion senden
  7. Überprüfen Sie das Ergebnis

Eine Transaktion wird generiert, weil eine Wertaktualisierung vorliegt, und die Aktualisierung wird bestätigt, wenn sie in den Block aufgenommen wird. Daher unterscheidet sich die aufrufende Methode erheblich von der Funktion, die den Wert nicht aktualisiert.

Impressionen

Ich persönlich mag es, intuitiv eine Klasse für jeden Vertrag zu erstellen, aber wenn Sie einen Mechanismus erstellen, um einen Vertrag aufzurufen und einen Wert zu erhalten, können Sie einen Code erstellen, der sehr vielseitig ist. Korrekt.

Recommended Posts

[Ethereum] So führen Sie einen Vertrag mit web3j-Teil 2 aus
So sortieren Sie eine Liste mit Comparator
Ausführen einer Methode und Verspotten mit JUnit
[Rails] So erstellen Sie ein Diagramm mit lazy_high_charts
So löschen Sie einen Controller usw. mit einem Befehl
So konvertieren Sie einen Soliditätsvertrag in eine Java-Vertragsklasse
So generieren Sie einen Primärschlüssel mit @GeneratedValue
So löschen Sie benutzerdefinierte Adapterelemente mithilfe eines benutzerdefinierten Modells
[Java] Wie man Aufgaben regelmäßig ausführt
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
Wie hinterlasse ich einen Kommentar?
So fügen Sie ein Video ein
So erstellen Sie eine Methode
So autorisieren Sie mit graphql-ruby
So geben Sie Array-Werte ohne Verwendung einer for-Anweisung aus
So verbinden Sie eine Tabelle ohne DBFlute und SQL
So registrieren Sie sich mit Tomcat als Kunde in Square
So erstellen Sie einen Java-Container
Wie unterschreibe ich Minecraft MOD?
So erstellen Sie einen JDBC-Treiber
[Swift] So senden Sie eine Benachrichtigung
So erstellen Sie einen Begrüßungsbildschirm
So erstellen Sie ein Jenkins-Plug-In
Wie erstelle ich ein Maven-Projekt?
So erstellen Sie ein Java-Array
Wie man Ruby's irb ausführt (interaktiver Ruby)
So erstellen Sie CloudStack mit Docker
So erstellen Sie eine JAR-Datei und eine War-Datei mit dem Befehl jar
So erstellen Sie mit SPRING INITIALIZR einen Hinadan für ein Spring Boot-Projekt
[Rails 6] So erstellen Sie mit cocoon einen dynamischen Formular-Eingabebildschirm
Wie man einen revolutionären Diamanten mit Java für Aussage macht wwww
So erstellen Sie eine Java-Kalenderzusammenfassung
Ein Memorandum zur Verwendung von Eclipse
Zurückgeben eines Werts vom Modell an den Controller mithilfe des [Swift5] -Protokolls
So implementieren Sie eine Diashow mit Slick in Rails (einzeln und mehrfach nacheinander)
[Rails] So laden Sie Bilder mit Carrierwave hoch
So erstellen Sie eine Abfrage mithilfe von Variablen in GraphQL [Verwenden von Ruby on Rails]
[Basic] So schreiben Sie ein Dockerfile Selbstlernend ②
So fügen Sie ein Video in Rails ein
[Java] So berechnen Sie das Alter mit LocalDate
So fügen Sie einen neuen Hash / Array hinzu
[Einführung in Java] So schreiben Sie ein Java-Programm
So erstellen Sie ein Maven-Repository für 2020
Wie erstelle ich einen Discord Bot (Java)
[Java] Wie man mit der String-Klasse an die Spitze eines bestimmten Strings kommt
[Swift5] So erstellen Sie einen Begrüßungsbildschirm
[Rails] So erstellen Sie eine Teilvorlage
[Swift5] So implementieren Sie Animationen mit "lottie-ios"
So implementieren Sie die Image-Veröffentlichung mithilfe von Schienen
So veröffentlichen Sie eine Bibliothek in jCenter
[SpringBoot] So schreiben Sie einen Controller-Test