关于利用webase-front节点控制台一键导出的java项目解析

搭建区块链系统和管理平台分别用的的fisco、webase

关于我们在利用java开发DApp(去中心化引用),与区块链系统交互,可以用:

1.webase前置服务给开发者提供的api:我们在搭建好fisco链之后,在搭一个webase-front服务,我们就能通过front服务提供的api,间接在fisco上面,进行部署、调用合约、获取块高,等与区块链系统交互的行为。

webase-front接口说明: 接口说明 — WeBASE v1.5.5 文档 (webasedoc.readthedocs.io)

 2.利用fisco官方为Java开发者提供的 fisco-sdk:通过引入他调用相关的方法,与区块链系统交互。

fisco-java-sdk快速入门: 快速入门 — FISCO BCOS v2 v2.9.0 文档 (fisco-bcos-documentation.readthedocs.io)

嗯,...但是按照官方文档,一旦我们项目大起来,其实就相对比较麻烦了(也不麻烦),然后我们可以利用webase-front节点控制台,将合约上传后,将合约对应的Java项目一键导出。

如下图:

这次我们利用webase-front搭建好,默认自带的Asset合约,来进行演示。

PS: 利用fisco-sdk 开发Dapp,先建议看fisco、webase有一定的基础之后,再建议尝试。

利用fisco-jdk第一次交互,可以看看这个,里面引用了Linux的IDEA、Maven、Java的安装:fisco Java-sdk 快速入门案例-CSDN博客

梦开始的地方

项目导出后,是一个boot项目,包管理工具是gradle,我习惯用Maven,因此我新建一个Maven项目,并将包移植到我自己的项目里。

pom.xml

我的 jdk 是 14。测试了jdk 11、8、14  ,就14不会报错对应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>

项目结构大体概览图 

第一个红框:

contracts:存放合约的目录,没啥用。

第二个红框:

接触java web之后,应该都知道。

第三个红框:

abi:与合约交互用的abi; bin: 合约编译之后生成二进制文件;  conf: 存放证书用到的目录。

 接下来,我们从第2个红框开始,从上往下,依次讲解学习主要的目录:

 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;@NestedConfigurationPropertyprivate ContractConfig contract;
}

 boot的自动装配类,当boot项目启动时,自动读取application.properties/yaml/yml中的自定义配置信息。并且,我们可以在spring 容器中获取到他。

对应的配置信息:

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=0x385dfad96f483042686273d5fda5c379b111bb20server.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;
}

自动配置类所需要的类,创建对应的对象,将地址填充进去对应的字段。 

PS:属性名要对应配置字段。

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 {@Autowiredprivate SystemConfig config;/*** 读取配置信息,初始化client并返回*/@Beanpublic 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 networkconfigCryptoMaterial(property,certPath); // concat cerpathConfigOption 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));}
}

我们读取了SystemConfig中的配置信息,封装到ConfigProperty对象里,并又将其封装到ConfigOption这个对象里面,通过下面这段代码

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

获得了一个Client,通过调用Client的方法我们能与fisco交互,可以获取块高等..。

 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;@Autowiredprivate Client client;AssembleTransactionProcessor txProcessor;@PostConstructpublic 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就是webase-front遵循业务层规则,生成的基于fisco-sdk封装的service类。通过这个service类,我们能与合约进行交互。

看代码,我们都是调用了这个 AssembleTransactionProcessor对象的上方法,

1.调用合约函数,是调用了这个方法。

方法参数为: 调用函数的合约地址、合约abi、被调用合约函数的函数名、函数参数列表

2.获取状态变量,是调用这个方法。

方法参数为:调用者的地址、调用函数的合约地址、合约abi、被调用合约函数的函数名、函数参数列表

 

 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;}
}

其实对比上述AssetService和Asset上封装调用的方法,发现最终都是调用一类对象上的不同方法。因此,看看就可以了。

AssembleTransactionProcessor 是AssetService层封装调用的。

TransactionProcessor 是Aseet层封装调用的。

abi、bin、conf

  • abi:存放合约abi的目录。定义外部调用合约的一种规则,本质上就是json文件,通过他,外部能与合约进行交互。
  • bin:bin文件存放目录。合约编译之后,形成的二进制文件、我们部署合约需要用到他。
  • conf: 存放fisco证书的目录。

测试文件

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 {@Autowiredprivate AssetService assetService;@Testpublic void testAssetService() throws Exception {String testAddress1 = "0xb537616a39a710d7590716c4422977953518c555";String testAddress2 = "0x7700375543650bd19b716bb2a1d5bf609177ba39";// 初始化assetService.init();// 调用issueAssetIssueInputBO input = new AssetIssueInputBO();input.setReceiver(testAddress1);input.setAmount(new BigInteger("2"));TransactionResponse issue = assetService.issue(input);System.out.println(issue.getReturnMessage());// 调用sendAssetSendInputBO send = new AssetSendInputBO();send.setAmount(new BigInteger("1"));send.setReceiver(testAddress2);TransactionResponse send1 = assetService.send(send);System.out.println(send1.getReturnMessage());// 调用balancesAssetBalancesInputBO balancesBo = new AssetBalancesInputBO();balancesBo.setArg0("0xb537616a39a710d7590716c4422977953518c555"); // 因为balances是一个map,因此我们需要传入一个用户地址,用来获取balanceCallResponse balances = assetService.balances(balancesBo);System.out.println(1);}@Autowiredprivate Client client;@Testpublic 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);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/165102.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于FPGA的图像自适应阈值二值化算法实现,包括tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1Otsu方法 4.2 Adaptive Thresholding方法 4.3、FPGA实现过程 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 Vivado2019.2 matlab2022a 3.部分核心程序 timescale …

线性代数-Python-02:矩阵的基本运算 - 手写Matrix及numpy中的用法

文章目录 一、代码仓库二、矩阵的基本运算2.1 矩阵的加法2.2 矩阵的数量乘法2.3 矩阵和向量的乘法2.4 矩阵和矩阵的乘法2.5 矩阵的转置 三、手写Matrix代码Matrix.pymain_matrix.pymain_numpy_matrix.py 一、代码仓库 https://github.com/Chufeng-Jiang/Python-Linear-Algebra-…

计算机网络学习笔记(四):网络层(待更新)

目录 4.1 IP地址、子网划分、合并超网 4.1.1 IP地址、子网掩码、网关 4.1.2 IP地址的编址方法1&#xff1a;IP地址分类&#xff08;A~E类地址、保留的IP地址&#xff09; 4.1.4 IP地址的编址方法2&#xff1a;子网划分&#xff08;等长、变长&#xff09; 4.1.5 IP地址的编…

基于Python实现的一款轻量、强大、好用的视频处理软件,可缩视频、转码视频、倒放视频、合并片段、根据字幕裁切片段、自动配字幕等

Quick Cut 是一款轻量、强大、好用的视频处理软件。它是一个轻量的工具&#xff0c;而不是像 Davinci Resolve、Adobe Premiere 那样专业的、复杂的庞然大物。Quick Cut 可以满足普通人一般的视频处理需求&#xff1a;压缩视频、转码视频、倒放视频、合并片段、根据字幕裁切片段…

【LeetCode每日一题合集】2023.10.9-2023.10.15(贪心⭐位运算的应用:只出现一次的数字)

文章目录 2578. 最小和分割&#xff08;贪心&#xff09;2731. 移动机器人&#xff08;脑筋急转弯排序统计&#xff09;2512. 奖励最顶尖的 K 名学生&#xff08;哈希表排序&#xff09;&#xff08;练习Java语法&#xff09;代码风格1代码风格2 2562. 找出数组的串联值&#x…

【七:docken+jenkens部署】

一&#xff1a;腾讯云轻量服务器docker部署Jenkins https://blog.csdn.net/qq_35402057/article/details/123589493 步骤1&#xff1a;查询jenkins版本&#xff1a;docker search jenkins步骤2&#xff1a;拉取jenkins镜像 docker pull jenkins/jenkins:lts步骤3&#xff1a;…

网络安全中的人工智能:优点、缺点、机遇和危险

2022 年秋天&#xff0c;人工智能在商业领域爆发&#xff0c;引起了轰动&#xff0c;不久之后&#xff0c;似乎每个人都发现了 ChatGPT 和 DALL-E 等生成式 AI 系统的新的创新用途。世界各地的企业开始呼吁将其集成到他们的产品中&#xff0c;并寻找使用它来提高组织效率的方法…

MySQL --- 聚合查询 和 联合查询

聚合查询&#xff1a; 下文中的所有聚合查询的示例操作都是基于此表&#xff1a; 聚合函数 聚合函数都是行与行之间的运算。 count() select count(列名) from 表名; 统计该表中该列的行数&#xff0c;但是 null 值不会统计在内&#xff0c;但是如果写为 count(*) 那么 nu…

Redis性能滑坡:哈希表碰撞的不速之客【redis第二部分】

Redis性能滑坡&#xff1a;哈希表碰撞的不速之客 前言第一部分&#xff1a;Redis哈希表简介第二部分&#xff1a;哈希表冲突原因第三部分&#xff1a;Redis哈希函数第四部分&#xff1a;哈希表冲突的性能影响第五部分&#xff1a;解决冲突策略第六部分&#xff1a;redis是如何解…

偶数科技发布实时湖仓数据平台Skylab 5.3版本

近日&#xff0c; 偶数发布了最新的实时湖仓数据平台 Skylab 5.3 版本。Skylab包含七大产品&#xff0c;分别为云原生分布式数据库 OushuDB、数据分析与应用平台 Kepler、数据资产管理平台 Orbit、自动化机器学习平台 LittleBoy、数据工厂 Wasp、数据开发与调度平台 Flow、系统…

深入探讨 Golang 中的追加操作

通过实际示例探索 Golang 中的追加操作 简介 在 Golang 编程领域&#xff0c;append 操作是一种多才多艺的工具&#xff0c;使开发人员能够动态扩展切片、数组、文件和字符串。在这篇正式的博客文章中&#xff0c;我们将踏上一段旅程&#xff0c;深入探讨在 Golang 中进行追加…

Linux入门攻坚——4、shell编程初步、grep及正则表达式

bash的基础特性&#xff08;续&#xff09;&#xff1a; 1、提供了编程环境&#xff1a; 编程风格&#xff1a;过程式&#xff1a;以指令为中心&#xff0c;数据服务于执行&#xff1b;对象式&#xff1a;以数据为中心&#xff0c;指令服务于数据 shell编程&#xff0c;编译执…

墨迹天气商业版UTF-8模板,Discuz3.4灰白色风格(带教程)

1.版本支持&#xff1a;Discuzx3.4版本&#xff0c;Discuzx3.3版本&#xff0c;DiscuzX3.2版本。包括网站首页&#xff0c;论坛首页&#xff0c;论坛列表页&#xff0c;论坛内容页&#xff0c;论坛瀑布流,资讯列表页(支持多个)&#xff0c;产品列表页(支持多个)&#xff0c;关于…

Visual Components软件有哪些用途 衡祖仿真

Visual Components是一款用于制造业虚拟仿真的软件&#xff0c;主要用于工业自动化和制造领域。我们一起来看一下该软件有哪些功能吧&#xff01; 1、工厂仿真 Visual Components可以建立虚拟的工厂环境&#xff0c;模拟和优化生产流程。用户可以创建工厂布局、定义设备和机器人…

多年没有遇到如此流畅的面试了

美东一公司的面试&#xff0c;有多年没有遇到如此流畅的面试了。 本来说的面试时间是 30 分钟&#xff0c;这个还是第一轮处于电话面试那种&#xff0c;但是不知道为什么最后面试整个时间都延长到了快一个小时&#xff0c;貌似双方都还继续沟通下&#xff0c;有点意犹未尽的感觉…

【Java】正则表达式,校验数据格式的合法性。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 正则表达式 正则表达式&#xff1a; ①可以校…

“第四十五天” 数据结构基本概念

目前看的有关数据结构的课&#xff0c;估计这周就看完了&#xff0c;但感觉差很多&#xff0c;还是和c一样&#xff0c;这样过一下吧。但可能比较急&#xff0c;目前是打算争取寒假回家之前把四大件都先大致过一遍。 数据结构里面有很多新的定义和概念&#xff0c;学到现在&am…

R语言中fread怎么使用?

R语言中 fread 怎么用&#xff1f; 今天分享的笔记内容是数据读取神器fread&#xff0c;速度嘎嘎快。在R语言中&#xff0c;fread函数是data.table包中的一个功能强大的数据读取函数&#xff0c;可以用于快速读取大型数据文件&#xff0c;它比基本的read.table和read.csv函数更…

SELECT COUNT(*) 会造成全表扫描吗?

前言 SELECT COUNT(*)会不会导致全表扫描引起慢查询呢&#xff1f; SELECT COUNT(*) FROM SomeTable 网上有一种说法&#xff0c;针对无 where_clause 的 COUNT(*)&#xff0c;MySQL 是有优化的&#xff0c;优化器会选择成本最小的辅助索引查询计数&#xff0c;其实反而性能…

物联网_00_物理网介绍

1.物联网为什么会出现? 一句话-----追求更高品质的生活, 随着科技大爆炸, 人类当然会越来越追求衣来伸手饭来张口的懒惰高品质生活, 最早的物联网设备可以追溯到19世纪末的"在线可乐售卖机"和"特洛伊咖啡壶"(懒惰的技术人员为了能够实时看到物品的情况而设…