• 关于利用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

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <groupId>org.examplegroupId>
    7. <artifactId>fiscoDemoartifactId>
    8. <version>1.0-SNAPSHOTversion>
    9. <properties>
    10. <java.version>14java.version>
    11. <spring-boot.version>2.6.13spring-boot.version>
    12. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    13. <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
    14. properties>
    15. <dependencies>
    16. <dependency>
    17. <groupId>org.springframework.bootgroupId>
    18. <artifactId>spring-boot-starter-webartifactId>
    19. dependency>
    20. <dependency>
    21. <groupId>org.springframework.bootgroupId>
    22. <artifactId>spring-boot-starter-testartifactId>
    23. <scope>testscope>
    24. dependency>
    25. <dependency>
    26. <groupId>org.projectlombokgroupId>
    27. <artifactId>lombokartifactId>
    28. dependency>
    29. <dependency>
    30. <groupId>org.slf4jgroupId>
    31. <artifactId>slf4j-apiartifactId>
    32. <version>1.7.36version>
    33. dependency>
    34. <dependency>
    35. <groupId>org.fisco-bcos.java-sdkgroupId>
    36. <artifactId>fisco-bcos-java-sdkartifactId>
    37. <version>2.9.2version>
    38. <exclusions>
    39. <exclusion>
    40. <artifactId>*artifactId>
    41. <groupId>org.slf4jgroupId>
    42. exclusion>
    43. exclusions>
    44. dependency>
    45. dependencies>
    46. <dependencyManagement>
    47. <dependencies>
    48. <dependency>
    49. <groupId>org.springframework.bootgroupId>
    50. <artifactId>spring-boot-dependenciesartifactId>
    51. <version>${spring-boot.version}version>
    52. <type>pomtype>
    53. <scope>importscope>
    54. dependency>
    55. dependencies>
    56. dependencyManagement>
    57. <build>
    58. <plugins>
    59. <plugin>
    60. <groupId>org.apache.maven.pluginsgroupId>
    61. <artifactId>maven-compiler-pluginartifactId>
    62. <version>3.8.1version>
    63. <configuration>
    64. <source>1.8source>
    65. <target>1.8target>
    66. <encoding>UTF-8encoding>
    67. configuration>
    68. plugin>
    69. plugins>
    70. build>
    71. project>

    项目结构大体概览图 

    第一个红框:

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

    第二个红框:

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

    第三个红框:

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

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

     config

    SystemConfig

    1. package org.example.demo.config;
    2. import java.lang.String;
    3. import lombok.Data;
    4. import org.springframework.boot.context.properties.ConfigurationProperties;
    5. import org.springframework.boot.context.properties.NestedConfigurationProperty;
    6. import org.springframework.context.annotation.Configuration;
    7. /**
    8. * 自动配置类 对应 配置文件信息(网络/群组/证书文件。。。)
    9. */
    10. @Data
    11. @Configuration
    12. @ConfigurationProperties(
    13. prefix = "system"
    14. )
    15. public class SystemConfig {
    16. private String peers;
    17. private int groupId = 1;
    18. private String certPath;
    19. private String hexPrivateKey;
    20. @NestedConfigurationProperty
    21. private ContractConfig contract;
    22. }

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

    对应的配置信息:

    application.properties

    1. # 搭建区块链第一个节点(node0)的,ip:port
    2. system.peers=127.0.0.1:20200
    3. # 合约所属群组id
    4. system.groupId=1
    5. # 证书所放的目录
    6. system.certPath=conf
    7. # 可选: 私钥文件
    8. system.hexPrivateKey=19eb7fd7a47a487265c6c109d560929deaee8e378fd4990dcce7cebd8a34f195
    9. #可选: 合约地址
    10. system.contract.assetAddress=0x385dfad96f483042686273d5fda5c379b111bb20
    11. server.port=8088
    12. server.session.timeout=60
    13. banner.charset=UTF-8
    14. spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
    15. spring.jackson.time-zone=GMT+8

    ContractConfig

    1. @Data
    2. public class ContractConfig {
    3. private String assetAddress;
    4. }

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

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

    SdkBeanConfig

    1. package org.example.demo.config;
    2. import java.math.BigInteger;
    3. import java.util.Arrays;
    4. import java.util.HashMap;
    5. import java.util.List;
    6. import java.util.Map;
    7. import java.util.stream.Collectors;
    8. import lombok.extern.slf4j.Slf4j;
    9. import org.fisco.bcos.sdk.BcosSDK;
    10. import org.fisco.bcos.sdk.client.Client;
    11. import org.fisco.bcos.sdk.config.ConfigOption;
    12. import org.fisco.bcos.sdk.config.exceptions.ConfigException;
    13. import org.fisco.bcos.sdk.config.model.ConfigProperty;
    14. import org.springframework.beans.factory.annotation.Autowired;
    15. import org.springframework.context.annotation.Bean;
    16. import org.springframework.context.annotation.Configuration;
    17. /**
    18. * 读取我们配置类的信息,初始化Client
    19. **/
    20. @Configuration
    21. @Slf4j
    22. public class SdkBeanConfig {
    23. @Autowired
    24. private SystemConfig config;
    25. /**
    26. * 读取配置信息,初始化client并返回
    27. */
    28. @Bean
    29. public Client client() throws Exception {
    30. String certPaths = this.config.getCertPath();
    31. String[] possibilities = certPaths.split(",|;");
    32. for(String certPath: possibilities ) {
    33. try{
    34. ConfigProperty property = new ConfigProperty();
    35. configNetwork(property); // concat network
    36. configCryptoMaterial(property,certPath); // concat cerpath
    37. ConfigOption configOption = new ConfigOption(property);
    38. Client client = new BcosSDK(configOption).getClient(config.getGroupId());
    39. BigInteger blockNumber = client.getBlockNumber().getBlockNumber();
    40. log.error("Chain connect successful. Current block number {}", blockNumber);
    41. configCryptoKeyPair(client);
    42. log.error("is Gm:{}, address:{}", client.getCryptoSuite().cryptoTypeConfig == 1, client.getCryptoSuite().getCryptoKeyPair().getAddress());
    43. return client;
    44. }
    45. catch (Exception ex) {
    46. log.error(ex.getMessage());
    47. try{
    48. Thread.sleep(5000);
    49. }catch (Exception e) {}
    50. }
    51. }
    52. throw new ConfigException("Failed to connect to peers:" + config.getPeers());
    53. }
    54. /**
    55. * 设置 network
    56. * @param configProperty
    57. */
    58. public void configNetwork(ConfigProperty configProperty) {
    59. String peerStr = config.getPeers();
    60. List peers = Arrays.stream(peerStr.split(",")).collect(Collectors.toList());
    61. Map networkConfig = new HashMap<>();
    62. networkConfig.put("peers", peers);
    63. configProperty.setNetwork(networkConfig);
    64. }
    65. /**
    66. * 设置 证书
    67. * @param configProperty
    68. * @param certPath
    69. */
    70. public void configCryptoMaterial(ConfigProperty configProperty,String certPath) {
    71. Map cryptoMaterials = new HashMap<>();
    72. cryptoMaterials.put("certPath", certPath);
    73. configProperty.setCryptoMaterial(cryptoMaterials);
    74. }
    75. /**
    76. * 设置密钥
    77. * @param client
    78. */
    79. public void configCryptoKeyPair(Client client) {
    80. if (config.getHexPrivateKey() == null || config.getHexPrivateKey().isEmpty()){
    81. client.getCryptoSuite().setCryptoKeyPair(client.getCryptoSuite().createKeyPair());
    82. return;
    83. }
    84. String privateKey;
    85. if (!config.getHexPrivateKey().contains(",")) {
    86. privateKey = config.getHexPrivateKey();
    87. } else {
    88. String[] list = config.getHexPrivateKey().split(",");
    89. privateKey = list[0];
    90. }
    91. if (privateKey.startsWith("0x") || privateKey.startsWith("0X")) {
    92. privateKey = privateKey.substring(2);
    93. config.setHexPrivateKey(privateKey);
    94. }
    95. client.getCryptoSuite().setCryptoKeyPair(client.getCryptoSuite().createKeyPair(privateKey));
    96. }
    97. }

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

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

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

     service

    AssetService

    1. package org.example.demo.service;
    2. import java.lang.Exception;
    3. import java.lang.String;
    4. import java.util.Arrays;
    5. import javax.annotation.PostConstruct;
    6. import lombok.Data;
    7. import lombok.NoArgsConstructor;
    8. import org.example.demo.model.bo.AssetBalancesInputBO;
    9. import org.example.demo.model.bo.AssetIssueInputBO;
    10. import org.example.demo.model.bo.AssetSendInputBO;
    11. import org.fisco.bcos.sdk.client.Client;
    12. import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
    13. import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
    14. import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
    15. import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
    16. import org.springframework.beans.factory.annotation.Autowired;
    17. import org.springframework.beans.factory.annotation.Value;
    18. import org.springframework.stereotype.Service;
    19. /**
    20. * 对应合约的Service,方法 -> 合约变量 和 合约函数
    21. * 发送交易 获取 响应
    22. */
    23. @Service
    24. @NoArgsConstructor
    25. @Data
    26. public class AssetService {
    27. public static final String ABI = org.example.demo.utils.IOUtil.readResourceAsString("abi/Asset.abi");
    28. public static final String BINARY = org.example.demo.utils.IOUtil.readResourceAsString("bin/ecc/Asset.bin");
    29. public static final String SM_BINARY = org.example.demo.utils.IOUtil.readResourceAsString("bin/ecc/Asset.bin");
    30. @Value("${system.contract.assetAddress}")
    31. private String address;
    32. @Autowired
    33. private Client client;
    34. AssembleTransactionProcessor txProcessor;
    35. @PostConstruct
    36. public void init() throws Exception {
    37. this.txProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(this.client, this.client.getCryptoSuite().getCryptoKeyPair());
    38. }
    39. public TransactionResponse issue(AssetIssueInputBO input) throws Exception {
    40. return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "issue", input.toArgs());
    41. }
    42. public TransactionResponse send(AssetSendInputBO input) throws Exception {
    43. return this.txProcessor.sendTransactionAndGetResponse(this.address, ABI, "send", input.toArgs());
    44. }
    45. public CallResponse balances(AssetBalancesInputBO input) throws Exception {
    46. return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "balances", input.toArgs());
    47. }
    48. public CallResponse issuer() throws Exception {
    49. return this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.address, ABI, "issuer", Arrays.asList());
    50. }
    51. }

    AssertService就是webase-front遵循业务层规则,生成的基于fisco-sdk封装的service类。通过这个service类,我们能与合约进行交互。

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

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

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

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

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

     

     raw

    Asset

    1. package org.example.demo.raw;
    2. import java.math.BigInteger;
    3. import java.util.ArrayList;
    4. import java.util.Arrays;
    5. import java.util.Collections;
    6. import java.util.List;
    7. import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
    8. import org.fisco.bcos.sdk.abi.TypeReference;
    9. import org.fisco.bcos.sdk.abi.datatypes.Address;
    10. import org.fisco.bcos.sdk.abi.datatypes.Event;
    11. import org.fisco.bcos.sdk.abi.datatypes.Function;
    12. import org.fisco.bcos.sdk.abi.datatypes.Type;
    13. import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
    14. import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
    15. import org.fisco.bcos.sdk.client.Client;
    16. import org.fisco.bcos.sdk.contract.Contract;
    17. import org.fisco.bcos.sdk.contract.precompiled.crud.TableCRUDService;
    18. import org.fisco.bcos.sdk.crypto.CryptoSuite;
    19. import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
    20. import org.fisco.bcos.sdk.eventsub.EventCallback;
    21. import org.fisco.bcos.sdk.model.CryptoType;
    22. import org.fisco.bcos.sdk.model.TransactionReceipt;
    23. import org.fisco.bcos.sdk.model.callback.TransactionCallback;
    24. import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
    25. /**
    26. * 这里就是我们能跟区块链系统中的合约对应交互的java类
    27. * 发送交易 获取凭证
    28. *
    29. * 这两个最终执行逻辑是同一个类上的不同方法
    30. */
    31. @SuppressWarnings("unchecked")
    32. public class Asset extends Contract {
    33. public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061044f806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631d1438481461006757806327e235e3146100be578063867904b414610115578063d0679d3414610162575b600080fd5b34801561007357600080fd5b5061007c6101af565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100ca57600080fd5b506100ff600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506101d4565b6040518082815260200191505060405180910390f35b34801561012157600080fd5b50610160600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506101ec565b005b34801561016e57600080fd5b506101ad600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610299565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561024757610295565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b5050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156102e55761041f565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507f3990db2d31862302a685e8086b5755072a6e2b5b780af1ee81ece35ee3cd3345338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15b50505600a165627a7a723058204e0edbb0e9bfd782dfaee2a435005414f5f84d50f4ead01144060672399fe6720029"};
    34. public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);
    35. public static final String[] SM_BINARY_ARRAY = {};
    36. public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);
    37. 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\"}]"};
    38. public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);
    39. // 调用合约对应的函数名 和状态变量名
    40. public static final String FUNC_ISSUER = "issuer";
    41. public static final String FUNC_BALANCES = "balances";
    42. public static final String FUNC_ISSUE = "issue";
    43. public static final String FUNC_SEND = "send";
    44. public static final Event SENT_EVENT = new Event("Sent",
    45. Arrays.>asList(new TypeReference
      () {}, new TypeReference
      () {}, new TypeReference() {}));
    46. /**
    47. * 下面 load函数本质上和这个一样都是根据现有合约地址加载,以调用
    48. * @param contractAddress
    49. * @param client
    50. * @param credential
    51. */
    52. protected Asset(String contractAddress, Client client, CryptoKeyPair credential) {
    53. super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    54. }
    55. public static String getBinary(CryptoSuite cryptoSuite) {
    56. return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    57. }
    58. public String issuer() throws ContractException {
    59. final Function function = new Function(FUNC_ISSUER,
    60. Arrays.asList(),
    61. Arrays.>asList(new TypeReference
      () {}));
    62. return executeCallWithSingleValueReturn(function, String.class);
    63. }
    64. public BigInteger balances(String param0) throws ContractException {
    65. final Function function = new Function(FUNC_BALANCES,
    66. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(param0)),
    67. Arrays.>asList(new TypeReference() {}));
    68. return executeCallWithSingleValueReturn(function, BigInteger.class);
    69. }
    70. /**
    71. * 无回调函数的对应和合约调用
    72. *
    73. * @param receiver
    74. * @param amount
    75. * @return TransactionReceipt 交易凭证
    76. */
    77. public TransactionReceipt issue(String receiver, BigInteger amount) {
    78. final Function function = new Function(
    79. FUNC_ISSUE,
    80. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver),
    81. new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)),
    82. Collections.>emptyList());
    83. return executeTransaction(function);
    84. }
    85. /**
    86. * 调用合约函数,并传入一个回调函数
    87. *
    88. * @param receiver
    89. * @param amount
    90. * @param callback
    91. */
    92. public void issue(String receiver, BigInteger amount, TransactionCallback callback) {
    93. final Function function = new Function(
    94. FUNC_ISSUE,
    95. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver),
    96. new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)),
    97. Collections.>emptyList());
    98. asyncExecuteTransaction(function, callback);
    99. }
    100. /**
    101. * 获取Issue合约函数的交易签名
    102. * @param receiver
    103. * @param amount
    104. * @return
    105. */
    106. public String getSignedTransactionForIssue(String receiver, BigInteger amount) {
    107. final Function function = new Function(
    108. FUNC_ISSUE,
    109. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver),
    110. new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)),
    111. Collections.>emptyList());
    112. return createSignedTransaction(function);
    113. }
    114. /**
    115. * 获取 IssurInpt输入的参数
    116. * @param transactionReceipt
    117. * @return 元组(封装输入的数据)
    118. */
    119. public Tuple2 getIssueInput(TransactionReceipt transactionReceipt) {
    120. String data = transactionReceipt.getInput().substring(10);
    121. final Function function = new Function(FUNC_ISSUE,
    122. Arrays.asList(),
    123. Arrays.>asList(new TypeReference
      () {}, new TypeReference() {}));
    124. List results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
    125. return new Tuple2(
    126. (String) results.get(0).getValue(),
    127. (BigInteger) results.get(1).getValue()
    128. );
    129. }
    130. public TransactionReceipt send(String receiver, BigInteger amount) {
    131. final Function function = new Function(
    132. FUNC_SEND,
    133. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver),
    134. new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)),
    135. Collections.>emptyList());
    136. return executeTransaction(function);
    137. }
    138. public void send(String receiver, BigInteger amount, TransactionCallback callback) {
    139. final Function function = new Function(
    140. FUNC_SEND,
    141. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver),
    142. new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)),
    143. Collections.>emptyList());
    144. asyncExecuteTransaction(function, callback);
    145. }
    146. public String getSignedTransactionForSend(String receiver, BigInteger amount) {
    147. final Function function = new Function(
    148. FUNC_SEND,
    149. Arrays.asList(new org.fisco.bcos.sdk.abi.datatypes.Address(receiver),
    150. new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(amount)),
    151. Collections.>emptyList());
    152. return createSignedTransaction(function);
    153. }
    154. public Tuple2 getSendInput(TransactionReceipt transactionReceipt) {
    155. String data = transactionReceipt.getInput().substring(10);
    156. final Function function = new Function(FUNC_SEND,
    157. Arrays.asList(),
    158. Arrays.>asList(new TypeReference
      () {}, new TypeReference() {}));
    159. List results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
    160. return new Tuple2(
    161. (String) results.get(0).getValue(),
    162. (BigInteger) results.get(1).getValue()
    163. );
    164. }
    165. public List getSentEvents(TransactionReceipt transactionReceipt) {
    166. List valueList = extractEventParametersWithLog(SENT_EVENT, transactionReceipt);
    167. ArrayList responses = new ArrayList(valueList.size());
    168. for (Contract.EventValuesWithLog eventValues : valueList) {
    169. SentEventResponse typedResponse = new SentEventResponse();
    170. typedResponse.log = eventValues.getLog();
    171. typedResponse.from = (String) eventValues.getNonIndexedValues().get(0).getValue();
    172. typedResponse.to = (String) eventValues.getNonIndexedValues().get(1).getValue();
    173. typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue();
    174. responses.add(typedResponse);
    175. }
    176. return responses;
    177. }
    178. public void subscribeSentEvent(String fromBlock, String toBlock, List otherTopics, EventCallback callback) {
    179. String topic0 = eventEncoder.encode(SENT_EVENT);
    180. subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    181. }
    182. public void subscribeSentEvent(EventCallback callback) {
    183. String topic0 = eventEncoder.encode(SENT_EVENT);
    184. subscribeEvent(ABI,BINARY,topic0,callback);
    185. }
    186. /**
    187. * 加载已有的合约地址,返回一个已有的Contract对象
    188. * @param contractAddress
    189. * @param client
    190. * @param credential
    191. * @return
    192. */
    193. public static Asset load(String contractAddress, Client client, CryptoKeyPair credential) {
    194. return new Asset(contractAddress, client, credential);
    195. }
    196. /**
    197. * 通过此方法,我们可以部署合约,产生一个新的Contract对象
    198. * @param client
    199. * @param credential
    200. * @return
    201. * @throws ContractException
    202. */
    203. public static Asset deploy(Client client, CryptoKeyPair credential) throws ContractException {
    204. return deploy(Asset.class, client, credential, getBinary(client.getCryptoSuite()), "");
    205. }
    206. public static class SentEventResponse {
    207. public TransactionReceipt.Logs log;
    208. public String from;
    209. public String to;
    210. public BigInteger amount;
    211. }
    212. }

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

    AssembleTransactionProcessor 是AssetService层封装调用的。

    TransactionProcessor 是Aseet层封装调用的。

    abi、bin、conf

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

    测试文件

    1. package org.example.demo;
    2. import org.example.demo.model.bo.AssetBalancesInputBO;
    3. import org.example.demo.model.bo.AssetIssueInputBO;
    4. import org.example.demo.model.bo.AssetSendInputBO;
    5. import org.example.demo.raw.Asset;
    6. import org.example.demo.service.AssetService;
    7. import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
    8. import org.fisco.bcos.sdk.client.Client;
    9. import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
    10. import org.fisco.bcos.sdk.model.TransactionReceipt;
    11. import org.fisco.bcos.sdk.model.callback.TransactionCallback;
    12. import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
    13. import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
    14. import org.fisco.bcos.sdk.transaction.model.exception.ContractException;
    15. import org.junit.jupiter.api.Test;
    16. import org.springframework.beans.factory.annotation.Autowired;
    17. import org.springframework.boot.test.context.SpringBootTest;
    18. import java.math.BigInteger;
    19. @SpringBootTest
    20. public class AssetTest {
    21. @Autowired
    22. private AssetService assetService;
    23. @Test
    24. public void testAssetService() throws Exception {
    25. String testAddress1 = "0xb537616a39a710d7590716c4422977953518c555";
    26. String testAddress2 = "0x7700375543650bd19b716bb2a1d5bf609177ba39";
    27. // 初始化
    28. assetService.init();
    29. // 调用issue
    30. AssetIssueInputBO input = new AssetIssueInputBO();
    31. input.setReceiver(testAddress1);
    32. input.setAmount(new BigInteger("2"));
    33. TransactionResponse issue = assetService.issue(input);
    34. System.out.println(issue.getReturnMessage());
    35. // 调用send
    36. AssetSendInputBO send = new AssetSendInputBO();
    37. send.setAmount(new BigInteger("1"));
    38. send.setReceiver(testAddress2);
    39. TransactionResponse send1 = assetService.send(send);
    40. System.out.println(send1.getReturnMessage());
    41. // 调用balances
    42. AssetBalancesInputBO balancesBo = new AssetBalancesInputBO();
    43. balancesBo.setArg0("0xb537616a39a710d7590716c4422977953518c555"); // 因为balances是一个map,因此我们需要传入一个用户地址,用来获取balance
    44. CallResponse balances = assetService.balances(balancesBo);
    45. System.out.println(1);
    46. }
    47. @Autowired
    48. private Client client;
    49. @Test
    50. public void testAsset() throws ContractException {
    51. String receiver = "0x7700375543650bd19b716bb2a1d5bf609177ba39";
    52. BigInteger amount = new BigInteger("2");
    53. CryptoKeyPair cryptoKeyPair = client.getCryptoSuite().getCryptoKeyPair();
    54. // 1.部署新合约
    55. Asset newInstance = Asset.deploy(client, cryptoKeyPair);
    56. // 2.实现TransactionCallback类
    57. TransactionCallback transactionCallback = new TransactionCallback() { //
    58. @Override
    59. // 这代码有问题,反正成功调用,这代码就是不调用
    60. public void onResponse(TransactionReceipt receipt) {
    61. System.out.println("我被调用了");
    62. // String newAddress = receipt.getContractAddress();
    63. // Asset load = Asset.load(newAddress, client, cryptoKeyPair);// 加载返回新合约的地址
    64. // TransactionReceipt issue = load.issue(receiver, amount);
    65. }
    66. };
    67. // 3.调用issue方法
    68. newInstance.issue(receiver, amount,transactionCallback);
    69. System.out.println(1);
    70. TransactionReceipt transactionReceipt = newInstance.issue(receiver, amount);
    71. // 4.获取issue方法的输入参数
    72. Tuple2 issueInput = newInstance.getIssueInput(transactionReceipt);
    73. }
    74. }

  • 相关阅读:
    洛谷 P4956 [COCI2017-2018#6] Davor
    室分知识点整理版
    基于C#和OpenVINO在英特尔独立显卡上部署PP-TinyPose模型
    原装芯片现货,价格优惠,实单可谈
    科研Tetrazine-PEG-valine 四嗪-聚乙二醇-缬氨酸、色氨酸、鸟氨酸、精氨酸
    从阿里、头条面试回来,面试官最喜欢问的 Jvm 和 Redis 你了解多少?
    HTML+CSS详细知识点复习(上)
    ABP集成SqlSugar
    React16.8新增特性Hooks--概念理解
    HTTP响应详解
  • 原文地址:https://blog.csdn.net/Qhx20040819/article/details/133930422