高旭亮 | 通过WeBASE-Front tool接口进行交易解析

作者:深职院高旭亮

本文会通过编写java程序来发送请求到WeBASE-Front的接口tool/decode来示范如何进行交易解析。

WeBASE-Front简介

来自WeBASE-Front官网:

WeBASE-Front是和FISCO BCOS节点配合使用的一个子系统,需要和节点统计部署,目前支持FISCO BCOS 2.0以上版本,可通过HTTP请求和节点进行通信,集成了web3sdk(JAVA-SDK),对接口进行了封装和抽象,具备可视化控制台,可以在控制台上查看交易和区块详情,开发智能合约,管理私钥,并对节点健康度进行监控和统计。

前期准备

  • 搭建一条FiscoBcos区块链

  • 编写HelloWorld合约:

  • pragma solidity ^0.4.4;
    contract HelloWorld {
        string  my_name = "Mike";
    
        function getName() public returns (string){
            return my_name;
        }
    
        function setName(string name) public{
            my_name = name;
        }
    }
    
  • 搭建WeBASE-Front平台(详见官方文档https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Front)

    通过访问https://webasedoc.readthedocs.io/zh_CN/latest/docs/WeBASE-Front/interface.html 获取详细的接口文档描述。

http://127.0.0.1:5002/WeBASE-Front/tool/decode

通过JAVA调用tool/decode接口

新建一个空maven项目

导入maven依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.79</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

示例代码

通过WeBASE-Front的tool/decode接口进行交易解析,建议先了解WeBASE-Front官方文档的接口描述

注意:

  • 代码中testDecodeInput()是解析调用合约setName方法时候的input,解析结果为调用时候传入的参数hello
  • 代码中testDecodeOutput()是解析调用合约getName方法时候的output
public class TestDecode {
    // WeBASE-Front接口地址,该接口用于执行交易
    private static final String URL = "http://127.0.0.1:5002/WeBASE-Front/tool/decode";
    // 合约ABI接口信息,为json格式
    private static final String CONTRACT_ABI = "[{\"constant\":false,\"inputs\":[],\"name\":\"getName\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]";

    public static void main(String[] args) {
        testDecodeInput();
        testDecodeOutput();
    }

    /**
     * 调用tool/decode接口解析input参数
     */
    private static void testDecodeInput() {
        // 新建一个对象用于承载数据,来自fastjson依赖,底层为Map,
        JSONObject jsonObj = new JSONObject();
        // 此处ABI原为json格式,因为JSONObject对象要序列化为json格式,避免重复序列化所以先将ABI转为java对象
        jsonObj.put("abiList", JSONArray.parseArray(CONTRACT_ABI));
        // 指定调用合约时候的方法
        jsonObj.put("methodName", "setName");
        // decodeType为1表示解析input输入的参数,为2表示解析output输出的参数
        jsonObj.put("decodeType", 1);
        // 当decodeType为1,需要传入input,此处使用编码后的"hello"字符串
        jsonObj.put("input", "0xc47f00270000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000");
        // 此处返回了json格式的数据,调用结束
        String responseStr = httpPost(URL, jsonObj.toJSONString());
        // 响应字符串hello,成功解码
        System.out.println(responseStr);
    }

    /**
     * 调用tool/decode接口解析output参数
     */
    private static void testDecodeOutput() {
        // 新建一个对象用于承载数据,来自fastjson依赖,底层为Map,
        JSONObject jsonObj = new JSONObject();
        // 此处ABI原为json格式,因为JSONObject对象要序列化为json格式,避免重复序列化所以先将ABI转为java对象
        jsonObj.put("abiList", JSONArray.parseArray(CONTRACT_ABI));
        // 指定调用合约时候的方法
        jsonObj.put("methodName", "getName");
        // decodeType为1表示解析input输入的参数,为2表示解析output输出的参数
        jsonObj.put("decodeType", 2);
        // 当decodeType为2,需要传入output
        jsonObj.put("output", "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000");
        //此处返回了json格式的数据,调用结束
        String responseStr = httpPost(URL, jsonObj.toJSONString());
        // 成功解码
        /*
        {
          "[hello]": [
            {
              "name": "",
              "type": "VALUE",
              "valueType": "STRING",
              "numericValue": null,
              "bytesValue": null,
              "bytesLength": 0,
              "addressValue": null,
              "boolValue": null,
              "dynamicBytesValue": null,
              "stringValue": {
                "value": "hello",
                "typeAsString": "string"
              },
              "listType": null,
              "listValues": null,
              "listLength": 0,
              "listValueType": null,
              "structFields": null,
              "dynamic": true
            }
          ]
        }
         */
        System.out.println(responseStr);
    }


    /**
     * 发送 post 请求
     *
     * @param url     请求地址
     * @param jsonStr 准备放入请求体的json字符串
     * @return 请求结果
     */
    private static String httpPost(String url, String jsonStr) {
        // 创建httpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 创建post请求方式实例
        HttpPost httpPost = new HttpPost(url);
        // 设置请求头 发送的是json数据格式
        httpPost.setHeader("Content-type", "application/json;charset=utf-8");
        // 设置参数---设置消息实体 也就是携带的数据
        StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
        // 设置编码格式
        entity.setContentEncoding("UTF-8");
        // 发送Json格式的数据请求
        entity.setContentType("application/json");
        // 把请求消息实体塞进去
        httpPost.setEntity(entity);
        // 执行http的post请求
        CloseableHttpResponse httpResponse;
        String result = null;
        try {
            httpResponse = httpClient.execute(httpPost);
            result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}