Analysis of java projects exported with one click using the webase-front node console

Build the blockchain system and management platform respectivelyfisco and webase.

About us using java to developDApp (decentralized reference), interacting with the blockchain system, you can use:

1. The API provided by the webase front-end service to developers: After we build the fisco chain and build a webase-front service, we can provide it through the front service The API is directly used on Fisco to deploy, call contracts, obtain block heights, and other actions to interact with the blockchain system.

webase-front interface description: Interface description — WeBASE v1.5.5 documentation (webasedoc.readthedocs.io)

 2.Use the fisco-sdk officially provided by fisco for Java developers:By introducing its related methods to call, and the blockchain System interaction.

fisco-java-sdk Quick Start: Quick Start — FISCO BCOS v2 v2.9.0 Documentation (fisco-bcos-documentation.readthedocs.io)

Well,...but according to the official documentation, once our project grows, it will actually be relatively troublesome (not troublesome). Then we can use the webase-front node console to upload the contract and then upload the Java project corresponding to the contract. Export with one click.

As shown below:

This time we used webase-front to build it and the default built-in Asset contract for demonstration.

PS: To use fisco-sdk to develop Dapp, it is recommended to have a certain foundation in fisco and webase before trying it.

The first interaction using fisco-jdk, you can take a look at this, which quotes the installation of IDEA, Maven, and Java for Linux:fisco Java-sdk quick start case-CSDN Blog

where dreams begin

After the project is exported, it is a boot project. The package management tool is gradle. I am used to using Maven, so I create a new Maven project and transplant the package to my own project.

pom.xml

My jdk is 14. After testing jdk 11, 8, and 14, 14 will not report an error, corresponding to fisco-sdk 2.9.2

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>fiscoDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>14</java.version>
        <spring-boot.version>2.6.13</spring-boot.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 单元测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <!-- fisco bcos -->
        <dependency>
            <groupId>org.fisco-bcos.java-sdk</groupId>
            <artifactId>fisco-bcos-java-sdk</artifactId>
            <version>2.9.2</version>
            <!-- 2.7.2 version, I think  do not match jdk-14 -->
            <exclusions>
                <exclusion>
                    <artifactId>*</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
 



    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

        </plugins>
    </build>


</project>

General overview of project structure 

The first red box:

contracts: directory where contracts are stored, useless.

The second red box:

After coming into contact with java web, you should know everything.

The third red box:

abi: Abi used to interact with the contract; bin: Binary file generated after the contract is compiled;  conf: Directory used to store certificates.

 Next, we will start from the second red box and explain the main learning contents from top to bottom:

 config

SystemConfig

package org.example.demo.config;

import java.lang.String;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.context.annotation.Configuration;

/**
 * 自动配置类 对应 配置文件信息(网络/群组/证书文件。。。)
 */
@Data
@Configuration
@ConfigurationProperties(
    prefix = "system"
)
public class SystemConfig {
  private String peers;

  private int groupId = 1;

  private String certPath;

  private String hexPrivateKey;

  @NestedConfigurationProperty
  private ContractConfig contract;
}

 The automatic assembly class of boot automatically reads the custom configuration information in application.properties/yaml/yml when the boot project is started. And, we can get it in the spring container.

Corresponding configuration information:

application.properties

# 搭建区块链第一个节点(node0)的,ip:port
system.peers=127.0.0.1:20200
# 合约所属群组id
system.groupId=1
# 证书所放的目录
system.certPath=conf
# 可选: 私钥文件
system.hexPrivateKey=19eb7fd7a47a487265c6c109d560929deaee8e378fd4990dcce7cebd8a34f195
#可选: 合约地址
system.contract.assetAddress=0x385dfad96f483042686273d5fda5c379b111bb20


server.port=8088
server.session.timeout=60
banner.charset=UTF-8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

ContractConfig

@Data
public class ContractConfig {
  private String assetAddress;
}

Automatically configure the classes required by the class, create the corresponding objects, and fill the addresses into the corresponding fields.​ 

PS: The attribute name must correspond to the configuration field.

SdkBeanConfig

package org.example.demo.config;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.config.ConfigOption;
import org.fisco.bcos.sdk.config.exceptions.ConfigException;
import org.fisco.bcos.sdk.config.model.ConfigProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 *  读取我们配置类的信息,初始化Client
 **/
@Configuration
@Slf4j
public class SdkBeanConfig {

    @Autowired
    private SystemConfig config;

    /**
     * 读取配置信息,初始化client并返回
     */
    @Bean
    public Client client() throws Exception {
        String certPaths = this.config.getCertPath();
        String[] possibilities = certPaths.split(",|;");
        for(String certPath: possibilities ) {
            try{
                ConfigProperty property = new ConfigProperty();
                configNetwork(property); // concat network
                configCryptoMaterial(property,certPath); // concat cerpath

                ConfigOption configOption = new ConfigOption(property);
                Client client = new BcosSDK(configOption).getClient(config.getGroupId());

                BigInteger blockNumber = client.getBlockNumber().getBlockNumber();
                log.error("Chain connect successful. Current block number {}", blockNumber);

                configCryptoKeyPair(client);
                log.error("is Gm:{}, address:{}", client.getCryptoSuite().cryptoTypeConfig == 1, client.getCryptoSuite().getCryptoKeyPair().getAddress());
                return client;
            }
            catch (Exception ex) {
                log.error(ex.getMessage());
                try{
                    Thread.sleep(5000);
                }catch (Exception e) {}
            }
        }
        throw new ConfigException("Failed to connect to peers:" + config.getPeers());
    }

    /** 
     * 设置 network
     * @param configProperty 
     */
    public void configNetwork(ConfigProperty configProperty) {
        String peerStr = config.getPeers();
        List<String> peers = Arrays.stream(peerStr.split(",")).collect(Collectors.toList());
        Map<String, Object> networkConfig = new HashMap<>();
        networkConfig.put("peers", peers);

        configProperty.setNetwork(networkConfig);
    }

    /**
     * 设置 证书
     * @param configProperty 
     * @param certPath
     */
    public void configCryptoMaterial(ConfigProperty configProperty,String certPath) {
        Map<String, Object> cryptoMaterials = new HashMap<>();
        cryptoMaterials.put("certPath", certPath);
        configProperty.setCryptoMaterial(cryptoMaterials);
       
        
    }

    /**
     * 设置密钥
     * @param client 
     */
    public void configCryptoKeyPair(Client client) {
        if (config.getHexPrivateKey() == null || config.getHexPrivateKey().isEmpty()){
            client.getCryptoSuite().setCryptoKeyPair(client.getCryptoSuite().createKeyPair());
            return;
        }
        String privateKey;
        if (!config.getHexPrivateKey().contains(",")) {
            privateKey = config.getHexPrivateKey();
        } else {
            String[] list = config.getHexPrivateKey().split(",");
            privateKey = list[0];
        }
        if (privateKey.startsWith("0x") || privateKey.startsWith("0X")) {
            privateKey = privateKey.substring(2);
            config.setHexPrivateKey(privateKey);
        }
        client.getCryptoSuite().setCryptoKeyPair(client.getCryptoSuite().createKeyPair(privateKey));
    }
}

We read the configuration information in SystemConfig, encapsulated it into the ConfigProperty object, and encapsulated it into the ConfigOption object, through the following code

 Client client = new BcosSDK(configOption).getClient(config.getGroupId());

After obtaining a Client, we can interact with Fisco by calling the Client method, and obtain the block height, etc.

 service

AssetService

package org.example.demo.service;

import java.lang.Exception;
import java.lang.String;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.demo.model.bo.AssetBalancesInputBO;
import org.example.demo.model.bo.AssetIssueInputBO;
import org.example.demo.model.bo.AssetSendInputBO;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 *  对应合约的Service,方法 -> 合约变量 和 合约函数
 *  发送交易 获取 响应
 */
@Service
@NoArgsConstructor
@Data
public class AssetService {
  public static final String ABI = org.example.demo.utils.IOUtil.readResourceAsString("abi/Asset.abi");

  public static final String BINARY = org.example.demo.utils.IOUtil.readResourceAsString("bin/ecc/Asset.bin");

  public static final String SM_BINARY = org.example.demo.utils.IOUtil.readResourceAsString("bin/ecc/Asset.bin");

  @Value("${system.contract.assetAddress}")
  private String address;

  @Autowired
  private Client client;

  AssembleTransactionProcessor txProcessor;

  @PostConstruct
  public void init() throws Exception {
    this.txProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(this.client, this.client.getCryptoSuite().getCryptoKeyPair());
  }

  public TransactionResponse issue(AssetIssueInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "issue", input.toArgs());
  }

  public TransactionResponse send(AssetSendInputBO input) throws Exception {
    return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "send", input.toArgs());
  }

  public CallResponse balances(AssetBalancesInputBO input) throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "balances", input.toArgs());
  }

  public CallResponse issuer() throws Exception {
    return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "issuer", Arrays.asList());
  }
}

AssertService is a service class generated based on fisco-sdk encapsulation by webase-front following the business layer rules. Through this service class, we can interact with the contract.

Looking at the code, we all called this method AssembleTransactionProcessor object,

1. Calling the contract function calls this method.

The method parameters are: The contract address of the calling function, the contract abi, the function name of the called contract function, and the function parameter list

2. To get the status variable, call this method.

The method parameters are:The address of the caller, the contract address of the calling function, the contract abi, the function name of the called contract function, and the function parameter list

 

 raw

Asset

package org.example.demo.raw;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.Address;
import org.fisco.bcos.sdk.abi.datatypes.Event;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.contract.precompiled.crud.TableCRUDService;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.eventsub.EventCallback;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

/**
 * 这里就是我们能跟区块链系统中的合约对应交互的java类
 * 发送交易 获取凭证
 *
 * 这两个最终执行逻辑是同一个类上的不同方法
 */
@SuppressWarnings("unchecked")
public class Asset extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061044f806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631d1438481461006757806327e235e3146100be578063867904b414610115578063d0679d3414610162575b600080fd5b34801561007357600080fd5b5061007c6101af565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100ca57600080fd5b506100ff600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506101d4565b6040518082815260200191505060405180910390f35b34801561012157600080fd5b50610160600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506101ec565b005b34801561016e57600080fd5b506101ad600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610299565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561024757610295565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b5050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156102e55761041f565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507f3990db2d31862302a685e8086b5755072a6e2b5b780af1ee81ece35ee3cd3345338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15b50505600a165627a7a723058204e0edbb0e9bfd782dfaee2a435005414f5f84d50f4ead01144060672399fe6720029"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"constant\":true,\"inputs\":[],\"name\":\"issuer\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"issue\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"send\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Sent\",\"type\":\"event\"}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    // 调用合约对应的函数名 和状态变量名
    public static final String FUNC_ISSUER = "issuer";

    public static final String FUNC_BALANCES = "balances";

    public static final String FUNC_ISSUE = "issue";

    public static final String FUNC_SEND = "send";

    public static final Event SENT_EVENT = new Event("Sent", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Address>() {}, new TypeReference<Uint256>() {}));


    /**
     * 下面 load函数本质上和这个一样都是根据现有合约地址加载,以调用
     * @param contractAddress
     * @param client
     * @param credential
     */
    protected Asset(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public String issuer() throws ContractException {
        final Function function = new Function(FUNC_ISSUER, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public BigInteger balances(String param0) throws ContractException {
        final Function function = new Function(FUNC_BALANCES, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(param0)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    /**
     * 无回调函数的对应和合约调用
     * 
     * @param receiver
     * @param amount
     * @return  TransactionReceipt 交易凭证
     */
    public TransactionReceipt issue(String receiver, BigInteger amount) {
        final Function function = new Function(
                FUNC_ISSUE, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    /**
     * 调用合约函数,并传入一个回调函数
     *
     * @param receiver
     * @param amount
     * @param callback
     */
    public void issue(String receiver, BigInteger amount, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_ISSUE, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
                asyncExecuteTransaction(function, callback);
    }

    /**
     * 获取Issue合约函数的交易签名
     * @param receiver
     * @param amount
     * @return
     */
    public String getSignedTransactionForIssue(String receiver, BigInteger amount) {
        final Function function = new Function(
                FUNC_ISSUE, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }


    /**
     * 获取 IssurInpt输入的参数
     * @param transactionReceipt
     * @return 元组(封装输入的数据)
     */
    public Tuple2<String, BigInteger> getIssueInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_ISSUE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());

        return new Tuple2<String, BigInteger>(

                (String) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue()
                );
    }



    public TransactionReceipt send(String receiver, BigInteger amount) {
        final Function function = new Function(
                FUNC_SEND, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void send(String receiver, BigInteger amount, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_SEND, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
                asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForSend(String receiver, BigInteger amount) {
        final Function function = new Function(
                FUNC_SEND, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple2<String, BigInteger> getSendInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_SEND, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<String, BigInteger>(

                (String) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue()
                );
    }

    public List<SentEventResponse> getSentEvents(TransactionReceipt transactionReceipt) {
        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(SENT_EVENT, transactionReceipt);
        ArrayList<SentEventResponse> responses = new ArrayList<SentEventResponse>(valueList.size());
        for (Contract.EventValuesWithLog eventValues : valueList) {
            SentEventResponse typedResponse = new SentEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.from = (String) eventValues.getNonIndexedValues().get(0).getValue();
            typedResponse.to = (String) eventValues.getNonIndexedValues().get(1).getValue();
            typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribeSentEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(SENT_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribeSentEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(SENT_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }
    /**
     * 加载已有的合约地址,返回一个已有的Contract对象
     * @param contractAddress
     * @param client
     * @param credential
     * @return
     */
    public static Asset load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new Asset(contractAddress, client, credential);
    }

    /**
     * 通过此方法,我们可以部署合约,产生一个新的Contract对象
     * @param client
     * @param credential
     * @return
     * @throws ContractException
     */
    public static Asset deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(Asset.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }

    public static class SentEventResponse {
        public TransactionReceipt.Logs log;

        public String from;

        public String to;

        public BigInteger amount;
    }
}

In fact, comparing the above-mentioned methods of encapsulating calls on AssetService and Asset, we find that they end up calling different methods on a type of object. So just take a look.

AssembleTransactionProcessor is encapsulated and called by the AssetService layer.

TransactionProcessor is encapsulated and called by the Aseet layer.

or、bin、conf

  • abi: The directory where the contract abi is stored. A rule that defines an external call contract is essentially a json file through which the outside world can interact with the contract.
  • bin: bin file storage directory. After the contract is compiled, the resulting binary file will be used to deploy the contract.
  • conf: The directory where the fisco certificate is stored.

test file

package org.example.demo;





import org.example.demo.model.bo.AssetBalancesInputBO;
import org.example.demo.model.bo.AssetIssueInputBO;
import org.example.demo.model.bo.AssetSendInputBO;
import org.example.demo.raw.Asset;
import org.example.demo.service.AssetService;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.math.BigInteger;

@SpringBootTest
public class AssetTest {

   @Autowired
   private AssetService assetService;

    @Test
    public void testAssetService() throws Exception {
        String testAddress1 = "0xb537616a39a710d7590716c4422977953518c555";
        String testAddress2 = "0x7700375543650bd19b716bb2a1d5bf609177ba39";
        // 初始化
        assetService.init();
        // 调用issue
        AssetIssueInputBO input = new AssetIssueInputBO();
        input.setReceiver(testAddress1);
        input.setAmount(new BigInteger("2"));
        TransactionResponse issue = assetService.issue(input);
        System.out.println(issue.getReturnMessage());
        // 调用send
        AssetSendInputBO send = new AssetSendInputBO();
        send.setAmount(new BigInteger("1"));
        send.setReceiver(testAddress2);
        TransactionResponse send1 = assetService.send(send);
        System.out.println(send1.getReturnMessage());

        // 调用balances
        AssetBalancesInputBO balancesBo = new AssetBalancesInputBO();
        balancesBo.setArg0("0xb537616a39a710d7590716c4422977953518c555"); // 因为balances是一个map,因此我们需要传入一个用户地址,用来获取balance
        CallResponse balances = assetService.balances(balancesBo);
        System.out.println(1);



    }

    @Autowired
    private Client client;

    @Test
    public void testAsset() throws ContractException {
        String receiver = "0x7700375543650bd19b716bb2a1d5bf609177ba39";
        BigInteger amount = new BigInteger("2");

        CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().getCryptoKeyPair();
        // 1.部署新合约
        Asset newInstance = Asset.deploy(client, cryptoKeyPair);
        // 2.实现TransactionCallback类
        TransactionCallback transactionCallback = new TransactionCallback() { //
            @Override
            // 这代码有问题,反正成功调用,这代码就是不调用
            public void onResponse(TransactionReceipt receipt) {
                System.out.println("我被调用了");

//                String newAddress = receipt.getContractAddress();
//                Asset load = Asset.load(newAddress, client, cryptoKeyPair);// 加载返回新合约的地址
//                TransactionReceipt issue = load.issue(receiver, amount);
            }
        };
        // 3.调用issue方法
       newInstance.issue(receiver, amount,transactionCallback);
       System.out.println(1);
        TransactionReceipt transactionReceipt = newInstance.issue(receiver, amount);
        // 4.获取issue方法的输入参数
        Tuple2<String, BigInteger> issueInput = newInstance.getIssueInput(transactionReceipt);


    }

}

Guess you like

Origin blog.csdn.net/Qhx20040819/article/details/133930422