zoukankan      html  css  js  c++  java
  • 开发指南:BUMO 资产发行 JAVA 开发指南

    BUMO 资产发行 JAVA 开发指南

    场景描述

    某资方在buchain上发行资产代码为GLA、名称为Global、总发行量为10亿的数字资产,具体信息如下:

    字段 是否必填 示例 描述
    name Global 资产名称
    code GLA 资产代码
    totalSupply 1000000000 资产总发行量
    decimals 8 资产精度
    description   资产描述
    icon   资产ICON
    version 1.0 协议版本号

    注意

    • code: 推荐使用大写简拼。
    • decimals: 小数位在0~8的范围,0表示无小数位。
    • totalSupply: 范围是0~2^63-1。0表示不固定Token的上限。 假如发行一笔数量是10000, 精度为8的ATP 10 Token,此时totalSupply = 10 ^ 8 * 10000, 结果是1000000000000
    • icon: base64位编码,图标文件大小是32k以内,推荐200*200像素。
    • version: 协议版本,目前填写1.0。

    资产发行开发流程

    本文以Java语言为例,新创建一个资产发行方(简称为“资方”)并发行10亿GLA资产。

    note : 示例中的[资方账户地址]请替换为资方待发行资产的账户地址,[资方账户私钥]请替换为资方待发行资产的账户私钥。

    创建SDK实例

    创建实例并设置url(部署的某节点的IP和端口)。

     String url = "http://seed1.bumotest.io:26002";
     SDK sdk = SDK.getInstance(url);
    

    在BuChain网络里,每个区块产生时间是10秒,每个交易只需要一次确认即可得到交易终态。

    环境说明如下:

    网络环境 IP Port 区块链浏览器
    主网 seed1.bumo.io 16002 https://explorer.bumo.io
    测试 seed1.bumotest.io 26002 https://explorer.bumotest.io

    创建资方账户

    创建资方账户的具体代码示例如下:

    public static AccountCreateResult createAccount() {
        AccountCreateResponse response = sdk.getAccountService().create();
        if (response.getErrorCode() != 0) {
            return null;
        }
        return response.getResult();
    }
    

    创建账户的返回值如下:

     AccountCreateResult
         address:  buQYszjqVYdhcPT56GZcKHVh4i7xtx6amr2g
         privateKey:  privbUAYxPLLyaxvU3EMkSTfuEDTWxAYvyCasUcCgUxDihtNXQL4oHJx
         publicKey: b001724ed9475ca4c8893329924c7dceae66c61d8577ab2c2c3b29376e143137c20a4bbed176
    

    注意: 通过以上方式创建的账户是未被激活的账户。

    激活资方账户

    账户未被激活时需要通过已被激活(已上链)的账户进行激活。已被激活的资方账户请跳过本节内容。

    注意

    • 主网环境:账户激活可以通过小布口袋(钱包)给该资方账户转50.03BU(用于支付资产发行时需要的交易费用),即可激活该账户。

    • 测试环境:通过访问水龙头,将待激活(或充值)的账户地址输入到编辑框中,点击"Confirm",就完成了激活(或充值)。

    获取资方账户的序列号

    每个账户都维护着自己的序列号,该序列号从1开始,依次递增,一个序列号标志着一个该账户的交易。

    获取资方账号序列号的代码如下:

     public long getAccountNonce() {
        long nonce = 0;
    
        // Init request
        String accountAddress = [资方账户地址];
        AccountGetNonceRequest request = new AccountGetNonceRequest();
        request.setAddress(accountAddress);
    
        // Call getNonce
        AccountGetNonceResponse response = sdk.getAccountService().getNonce(request);
        if (0 == response.getErrorCode()) {
        nonce = response.getResult().getNonce();
        } else {
        System.out.println("error: " + response.getErrorDesc());
        }
        return nonce;
     }
    

    获取资方账号序列号的返回值如下:

     nonce: 28
    

    组装发行资产操作

    一个交易可由多个操作组成,每个操作都指向一个具体的交易内容。

    发行资产则需要两个操作: 资产发行操作(AssetIssueOperation)和设置资产信息操作(AccountSetMetadataOperation)。

    组装发行资产操作的具体代码如下:

        public BaseOperation[] buildOperations() {
        // The account address to issue apt1.0 token
        String issuerAddress = [资方账户地址];
        // The token name
        String name = "Global";
        // The token code
        String code = "GLA";
        // The apt token version
        String version = "1.0";
        // The apt token icon
        String icon = "";
        // The token total supply number
        Long totalSupply = 1000000000L;
        // The token now supply number
        Long nowSupply = 1000000000L;
        // The token description
        String description = "GLA TOKEN";
        // The token decimals
        Integer decimals = 0;
        
        // Build asset issuance operation
        AssetIssueOperation assetIssueOperation = new AssetIssueOperation();
        assetIssueOperation.setSourceAddress(issuerAddress);
        assetIssueOperation.setCode(code);
        assetIssueOperation.setAmount(nowSupply);
        
        // If this is an atp 1.0 token, you must set metadata like this
        JSONObject atp10Json = new JSONObject();
        atp10Json.put("name", name);
        atp10Json.put("code", code);
        atp10Json.put("description", description);
        atp10Json.put("decimals", decimals);
        atp10Json.put("totalSupply", totalSupply);
        atp10Json.put("icon", icon);
        atp10Json.put("version", version);
        
        String key = "asset_property_" + code;
        String value = atp10Json.toJSONString();
        // Build setMetadata
        AccountSetMetadataOperation accountSetMetadataOperation = new AccountSetMetadataOperation();
        accountSetMetadataOperation.setSourceAddress(issuerAddress);
        accountSetMetadataOperation.setKey(key);
        accountSetMetadataOperation.setValue(value);
        
        BaseOperation[] operations = {assetIssueOperation, accountSetMetadataOperation};
        return operations;
        }
    

    序列化交易

    序列化交易以便网络传输。

    注意

    • feeLimit: 本次交易发起方最多支付本次交易的交易费用,发行资产操作请填写50.03BU
    • nonce: 本次交易发起方的交易序列号,该值由当前账户的nonce值加1得到。

    序列化交易的具体代码如下,示例中的参数 nonce 是调用 getAccountNonce 得到的账户序列号,参数 operations 是调用 buildOperations 得到发行资产的操作。

     public String seralizeTransaction(Long nonce,  BaseOperation[] operations) {
         String transactionBlob = null;
    
        // The account address to issue atp1.0 token
        String senderAddresss = [资方账户地址];
        // The gasPrice is fixed at 1000L, the unit is MO
        Long gasPrice = 1000L;
        // Set up the maximum cost 50.03BU
        Long feeLimit = ToBaseUnit.BU2MO("50.03");
        // Nonce should add 1
        nonce += 1;
    
        // Build transaction  Blob
        TransactionBuildBlobRequest transactionBuildBlobRequest = new TransactionBuildBlobRequest();
        transactionBuildBlobRequest.setSourceAddress(senderAddresss);
        transactionBuildBlobRequest.setNonce(nonce);
        transactionBuildBlobRequest.setFeeLimit(feeLimit);
        transactionBuildBlobRequest.setGasPrice(gasPrice);
        for (int i = 0; i < operations.length; i++) {
            transactionBuildBlobRequest.addOperation(operations[i]);
        }
        TransactionBuildBlobResponse transactionBuildBlobResponse = sdk.getTransactionService().buildBlob(transactionBuildBlobRequest);
        if (transactionBuildBlobResponse.getErrorCode() == 0) {
            transactionBlob = transactionBuildBlobResponse. getResult().getTransactionBlob();
        } else {
            System.out.println("error: " + transactionBuildBlobResponse.getErrorDesc());
        }
        return transactionBlob;
     }
    

    序列化交易的返回值如下:

     transactionBlob: 0A2462755173757248314D34726A4C6B666A7A6B7852394B584A366A537532723978424E4577101C18C0F1CED11220E8073A350802122462755173757248314D34726A4C6B666A7A6B7852394B584A366A537532723978424E45772A0B0A03474C41108094EBDC033AB6010804122462755173757248314D34726A4C6B666A7A6B7852394B584A366A537532723978424E45773A8B010A1261737365745F70726F70657274795F474C4112757B22636F6465223A22474C41222C22746F74616C537570706C79223A313030303030303030302C22646563696D616C73223A302C226E616D65223A22474C41222C2269636F6E223A22222C226465736372697074696F6E223A22474C4120544F4B454E222C2276657273696F6E223A22312E30227D
    

    签名交易

    所有的交易都需要经过签名后,才是有效的。签名结果包括签名数据和公钥。

    签名交易的具体代码如下,示例中的参数transactionBlob是调用seralizeTransaction得到的序列化交易字符串。

     public Signature[] signTransaction(String transactionBlob) {
        Signature[] signatures = null;
        // The account private key to issue atp1.0 token
        String senderPrivateKey = [资方账户私钥];
    
        // Sign transaction BLob
        TransactionSignRequest transactionSignRequest = new TransactionSignRequest();
        transactionSignRequest.setBlob(transactionBlob);
        transactionSignRequest.addPrivateKey(senderPrivateKey);
        TransactionSignResponse transactionSignResponse = sdk.getTransactionService().sign(transactionSignRequest);
        if (transactionSignResponse.getErrorCode() == 0) {
            signatures = transactionSignResponse.getResult().getSignatures();
        } else {
            System.out.println("error: " + transactionSignResponse.getErrorDesc());
        }
        return signatures;
     }
    

    签名交易的返回值如下:

     signData: 6CEA42B11253BD49E7F1A0A90EB16448C6BC35E8684588DAB8C5D77B5E771BD5C7E1718942B32F9BDE14551866C00FEBA832D92F88755226434413F98E5A990C
     publicKey: b00179b4adb1d3188aa1b98d6977a837bd4afdbb4813ac65472074fe3a491979bf256ba63895
    

    发送交易

    将序列化的交易和签名发送到BuChain。

    发送交易具体代码如下,示例中的参数transactionBlob是调用seralizeTransaction得到的序列化交易字符串,signatures是调用signTransaction得到的签名数据。

     public String submitTransaction(String transactionBlob, Signature[] signatures) {
        String  hash = null;
        
        // Submit transaction
        TransactionSubmitRequest transactionSubmitRequest = new TransactionSubmitRequest();
        transactionSubmitRequest.setTransactionBlob(transactionBlob);
        transactionSubmitRequest.setSignatures(signatures);
        TransactionSubmitResponse transactionSubmitResponse = sdk.getTransactionService().submit(transactionSubmitRequest);
        if (0 == transactionSubmitResponse.getErrorCode()) {
            hash = transactionSubmitResponse.getResult().getHash();
        } else {
            System.out.println("error: " + transactionSubmitResponse.getErrorDesc());
        }
        return  hash ;
     }
    

    发送交易的返回值如下:

     hash:  031fa9a7da6cf8777cdd55df782713d4d05e2465146a697832011b058c0a0cd8
    

    查询交易是否执行成功

    注意: 发送交易返回的结果只是交易是否提交成功的结果,而交易是否执行成功的结果需要执行如下查询操作, 具体有两种方法:

    区块链浏览器查询

    在BUMO区块链浏览器中查询上面的hash,主网测试网,操作如下图:

    查询结果如下:

    调用接口查询

    调用接口查询的代码如下,示例中的参数txHash是调用submitTransaction得到的交易哈希(交易的惟一标识)。

     public int checkTransactionStatus(String txHash) {
        // Init request
        TransactionGetInfoRequest request = new TransactionGetInfoRequest();
        request.setHash(txHash);
    
        // Call getInfo
        TransactionGetInfoResponse response = sdk.getTransactionService().getInfo(request);
        int errorCode = response.getErrorCode();
        if (errorCode == 0){
            TransactionHistory transactionHistory = response.getResult().getTransactions()[0];
            errorCode = transactionHistory.getErrorCode();
        }
    
        return errorCode;
     }
    

    返回值:

    错误码 描述
    0 Successful operation
    1 Inner service defect
    2 Parameters error
    3 Objects already exist, such as repeated transactions
    4 Objects do not exist, such as null account, transactions and blocks etc.
    5 Transactions expired. It means the transaction has been removed from the buffer, but it still has probability to be executed.
    7 Math calculation is overflown
    20 The expression returns false. It means the TX failed to be executed currently, but it still has probability to be executed in the following blocks .
    21 The syntax of the expression returns are false. It means that the TX must fail.
    90 Invalid public key
    91 Invalid private key
    92 Invalid assets
    93 The weight of the signature does not match the threshold of the operation.
    94 Invalid address
    97 Absent operation of TX
    98 Over 100 operations in a single transaction
    99 Invalid sequence or nonce of TX
    100 Low reserve in the account
    101 Sender and receiver accounts are the same
    102 The target account already exists
    103 Accounts do not exist
    104 Low reserve in the account
    105 Amount of assets exceeds the limitation ( int64 )
    106 Insufficient initial reserve for account creation
    111 Low transaction fee
    114 TX buffer is full
    120 Invalid weight
    121 Invalid threshold
    144 Invalid data version of metadata
    146 exceeds upper limitation
    151 Failure in contract execution
    152 Failure in syntax analysis
    153 The depth of contract recursion exceeds upper limitation
    154 the TX submitted from the contract exceeds upper limitation
    155 Contract expired
    160 Fail to insert the TX into buffer
    11060 BlockNumber must bigger than 0
    11007 Failed to connect to the network
    12001 Request parameter cannot be null
    20000 System error
  • 相关阅读:
    2020杭电HDU-6863多校第八场Isomorphic Strings(Hash+学到的新东西)
    CodeForces 1395C-Boboniu and Bit Operations(位运算-暴力)
    洛谷P2585&ZJOI 2006-三色二叉树(树的染色-树形DP)
    洛谷P2016-战略游戏(树的最小点覆盖-树形DP)
    洛谷P2015-二叉苹果树(树形DP)
    洛谷P1352-没有上司的舞会(树形DP)
    CSUSTOJ 4004-你真的会吃零食吗?(打表)
    在线支付--支付宝
    使用rabbitmq rpc 模式
    在kubernetes 集群运行 odoo
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13313230.html
Copyright © 2011-2022 走看看