跳到主要内容

1. 功能介绍

本文档详细说明BubiChain Java SDK常用接口文档, 使开发者更方便地操作和查询BubiChain区块链。

2. 准备工作

2.1. 环境要求

JDK要求8或更高版本。

3. 安装

需要以下两步来完成,下面以4.1.1版本为例说明。

首先在Maven的配置文件中添加 BubiChain 的以下远程仓库

<repository>
<id>releases</id>
<url>http://maven.bubidev.cn/content/repositories/releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>

在pom.xml的配置文件中添加相应版本的依赖包

<dependency>
<groupId>cn.bubi.sdk</groupId>
<artifactId>bubichain-sdk</artifactId>
<version>4.1.1</version>
</dependency>

调用SDK的接口getInstance来生成SDK实例,如下:

String url = "http://seed1-node.bubi.cn";
SDK sdk = SDK.getInstance(url);

调用Keypair.generator接口生成账户,具体调用如下:

Keypair keypair = Keypair.generator();
System.out.println(keypair.getPrivateKey());
System.out.println(keypair.getPublicKey());
System.out.println(keypair.getAddress());

至此,链信息以及账户信息准备完成,接下来就可以进行更加深入的操作了。

4. 使用说明

如何使用sdk发送交易,分为以下几步。

4.1. 实例化SDK

String url = "http://seed1-node.bubi.cn";
SDK sdk = SDK.getInstance(url);

4.2. 获取账户nonce值

nonce用于防止重放攻击并确保交易顺序。每个账户都有一个与之相关的nonce值,表示该账户已发送的交易数量。每发送一笔交易,nonce值会递增1。这意味着每笔交易都有一个唯一的nonce值,从而避免同一交易被多次执行。还可以确保交易按照特定的顺序被处理。调用如下:

// 初始化请求参数
String senderAddress = "adxSa4oENoQCc66JRouZu1rKu4RWjgS69YD4S";
AccountGetNonceRequest getNonceRequest = new AccountGetNonceRequest();
getNonceRequest.setAddress(senderAddress);

// 调用getNonce接口
AccountGetNonceResponse getNonceResponse = sdk.getAccountService().getNonce(getNonceRequest);

// 赋值nonce
if (getNonceResponse.getErrorCode() == 0) {
AccountGetNonceResult result = getNonceResponse.getResult();
System.out.println("nonce: " + result.getNonce());
}
else {
System.out.println("error" + getNonceResponse.getErrorDesc());
}

4.3. 构建操作

操作是指在交易中做的动作,详细信息请参阅SDK接口/操作结构,例如,转移Gas操作,接口调用如下:

String senderAddress = "adxSa4oENoQCc66JRouZu1rKu4RWjgS69YD4S";
String destAddress = "adxSgTxU1awVzNUeR8xcnd3K75XKU8ziNHcWW";
Long eaAmount = ToBaseUnit.ToUGas("10.9");

GasSendOperation operation = new GasSendOperation();
operation.setSourceAddress(senderAddress);
operation.setDestAddress(destAddress);
operation.setAmount(eaAmount);

4.4. 序列化交易

该接口用于序列化交易,并生成交易Blob串,便于网络传输。其中nonce和operation是上面接口得到的,调用如下:

// 初始化变量
String senderAddress = "adxSa4oENoQCc66JRouZu1rKu4RWjgS69YD4S";
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");

// 初始化请求参数
TransactionBuildBlobRequest buildBlobRequest = new TransactionBuildBlobRequest();
buildBlobRequest.setSourceAddress(senderAddress);
buildBlobRequest.setNonce(nonce + 1);
buildBlobRequest.setFeeLimit(feeLimit);
buildBlobRequest.setGasPrice(gasPrice);
buildBlobRequest.addOperation(operation);

// 调用buildBlob接口
TransactionBuildBlobResponse buildBlobResponse = sdk.getTransactionService().buildBlob(buildBlobRequest);
if (buildBlobResponse.getErrorCode() == 0) {
TransactionBuildBlobResult result = buildBlobResponse.getResult();
System.out.println("txHash: " + result.getHash() + ", blob: " + result.getTransactionBlob());
} else {
System.out.println("error: " + buildBlobResponse.getErrorDesc());
}

4.5. 签名交易

该接口用于交易发起者使用其账户私钥对交易进行签名。其中transactionBlob是上面接口得到的,调用如下:

// 初始化请求参数
String senderPrivateKey = "privbwAQyE2vWwzt9NuC8vecqpZm7DS8kfiMPsKPcrTatUkmkxkVhfaf";
String []signerPrivateKeyArr = {senderPrivateKey};
TransactionSignRequest signRequest = new TransactionSignRequest();
signRequest.setBlob(transactionBlob);
for (int i = 0; i < signerPrivateKeyArr.length; i++) {
signRequest.addPrivateKey(signerPrivateKeyArr[i]);
}

// 调用sign接口
TransactionSignResponse signResponse = sdk.getTransactionService().sign(signRequest);
if (signResponse.getErrorCode() == 0) {
TransactionSignResult result = signResponse.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + signResponse.getErrorDesc());
}

4.6. 提交交易

该接口用于向BubiChain区块链发送交易请求,触发交易的执行。其中transactionBlob和signResult是上面接口得到的,调用如下:

// 初始化请求参数
TransactionSubmitRequest submitRequest = new TransactionSubmitRequest();
submitRequest.setTransactionBlob(transactionBlob);
submitRequest.setSignatures(signResult.getSignatures());

// 调用submit接口
TransactionSubmitResponse response = sdk.getTransactionService().submit(submitRequest);
if (0 == response.getErrorCode()) {
System.out.println("交易广播成功,hash=" + response.getResult().getHash());
} else {
System.out.println("error: " + response.getErrorDesc());
}

4.7. 查询交易结果

根据提交交易获取到的返回值hash字段进行查询。

 public void getTransactionInfo() {
TransactionGetInfoRequest request = new TransactionGetInfoRequest();
request.setHash("0d67997af3777b977deb648082c8288b4ba46b09d910d016f0942bcd853ad518");
TransactionGetInfoResponse response = sdk.getTransactionService().getInfo(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
}

5. SDK接口

5.1. 交易服务

交易服务提供交易相关的接口,目前有5个接口:buildBlob、evaluateFee、sign、submit、getInfo。

  • buildBlob

接口说明

该接口用于序列化交易,生成交易Blob串,便于网络传输

调用方法

TransactionBuildBlobResponse buildBlob(TransactionBuildBlobRequest);

请求参数

参数类型描述
sourceAddressString必填,发起该操作的源账户地址
nonceLong必填,待发起的交易序列号,函数里+1,大小限制[1, Long.MAX_VALUE]
gasPriceLong必填,交易费用单价,按字节收费,单位UGas,1 Gas = 10^8 UGas,大小限制[1000, Long.MAX_VALUE]
feeLimitLong必填,交易要求的最低的手续费,单位UGas,1 Gas = 10^8 UGas,大小限制[1, Long.MAX_VALUE]
operationBaseOperation[]必填,待提交的操作列表,不能为空
ceilLedgerSeqlong选填,距离当前区块高度指定差值的区块内执行的限制,当区块超出当时区块高度与所设差值的和后,交易执行失败。必须大于等于0,是0时不限制
metadataString选填,备注

响应数据

字段名称类型描述
transactionBlobStringTransaction序列化后的16进制字符串
hashString交易hash

示例

// 初始化变量
String senderAddresss = "adxSYQ8iMyZ7Dkj1oX1kjGMV55WXvoPKcLEK3";
String destAddress = "adxSgTxU1awVzNUeR8xcnd3K75XKU8ziNHcWW";
Long eaAmount = ToBaseUnit.ToUGas("10.9");
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");
Long nonce = 1L;

// 构建sendGas操作
GasSendOperation operation = new GasSendOperation();
operation.setSourceAddress(senderAddresss);
operation.setDestAddress(destAddress);
operation.setAmount(eaAmount);

// 初始化请求参数
TransactionBuildBlobRequest request = new TransactionBuildBlobRequest();
request.setSourceAddress(senderAddresss);
request.setNonce(nonce);
request.setFeeLimit(feeLimit);
request.setGasPrice(gasPrice);
request.addOperation(operation);

// 调用buildBlob接口
String transactionBlob = null;
TransactionBuildBlobResponse response = sdk.getTransactionService().buildBlob(request);
if (response.getErrorCode() == 0) {
TransactionBuildBlobResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • evaluateFee

接口说明

该接口实现交易的费用评估。

调用方法

TransactionEvaluateFeeResponse evaluateFee (TransactionEvaluateFeeRequest);

请求参数

参数类型描述
sourceAddressString必填,发起该操作的源账户地址
nonceLong必填,待发起的交易序列号,大小限制[1, Long.MAX_VALUE]
operationBaseOperation[]必填,待提交的操作列表,不能为空
signtureNumberInteger选填,待签名者的数量,默认是1,大小限制[1, Integer.MAX_VALUE]
ceilLedgerSeqLong选填,距离当前区块高度指定差值的区块内执行的限制,当区块超出当时区块高度与所设差值的和后,交易执行失败。必须大于等于0,是0时不限制
metadataString选填,备注

响应数据

参数类型描述
txsTestTx[]评估交易集

示例

// 初始化变量
String senderAddresss = "adxSa4oENoQCc66JRouZu1rKu4RWjgS69YD4S";
String destAddress = "adxSYQ8iMyZ7Dkj1oX1kjGMV55WXvoPKcLEK3";
Long eaAmount = ToBaseUnit.ToUGas("10.9");
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");
Long nonce = 51L;

// 构建sendGas操作
GasSendOperation gasSendOperation = new GasSendOperation();
gasSendOperation.setSourceAddress(senderAddresss);
gasSendOperation.setDestAddress(destAddress);
gasSendOperation.setAmount(eaAmount);

// 初始化评估交易请求参数
TransactionEvaluateFeeRequest request = new TransactionEvaluateFeeRequest();
request.addOperation(gasSendOperation);
request.setSourceAddress(senderAddresss);
request.setNonce(nonce);
request.setSignatureNumber(1);
request.setMetadata(HexFormat.byteToHex("evaluate fees".getBytes()));

// 调用evaluateFee接口
TransactionEvaluateFeeResponse response = sdk.getTransactionService().evaluateFee(request);
if (response.getErrorCode() == 0) {
TransactionEvaluateFeeResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • sign

接口说明

该接口用于实现交易的签名

调用方法

TransactionSignResponse sign(TransactionSignRequest);

请求参数

参数类型描述
blobString必填,待签名的交易Blob
privateKeysString[]必填,私钥列表

响应数据

参数类型描述
signaturesSignature[]签名后的数据列表

示例

// 初始化请求参数
String issuePrivateKey = "privbwAQyE2vWwzt9NuC8vecqpZm7DS8kfiMPsKPcrTatUkmkxkVhfaf";
String []signerPrivateKeyArr = {issuePrivateKey};
String transactionBlob = "0A246275516E6E5545425245773268423670574847507A77616E5837643238786B364B566370102118C0843D20E8073A56080712246275516E6E5545425245773268423670574847507A77616E5837643238786B364B566370522C0A24627551426A4A443142534A376E7A41627A6454656E416870466A6D7852564545746D78481080A9E08704";
TransactionSignRequest request = new TransactionSignRequest();
request.setBlob(transactionBlob);
for (int i = 0; i < signerPrivateKeyArr.length; i++) {
request.addPrivateKey(signerPrivateKeyArr[i]);
}
TransactionSignResponse response = sdk.getTransactionService().sign(request);
if(0 == response.getErrorCode()){
System.out.println(JSON.toJSONString(response.getResult(), true));
}else{
System.out.println("error: " + response.getErrorDesc());
}
  • submit

接口说明

该接口用于实现交易的提交。

调用方法

TransactionSubmitResponse submit(TransactionSubmitRequest);

请求参数

参数类型描述
blobString必填,交易blob
signatureSignature[]必填,签名列表

响应数据

参数类型描述
hashString交易hash

示例

// 初始化请求参数
String transactionBlob = "0A246275516E6E5545425245773268423670574847507A77616E5837643238786B364B566370102118C0843D20E8073A56080712246275516E6E5545425245773268423670574847507A77616E5837643238786B364B566370522C0A24627551426A4A443142534A376E7A41627A6454656E416870466A6D7852564545746D78481080A9E08704";
Signature signature = new Signature();
signature.setSignData("D2B5E3045F2C1B7D363D4F58C1858C30ABBBB0F41E4B2E18AF680553CA9C3689078E215C097086E47A4393BCA715C7A5D2C180D8750F35C6798944F79CC5000A");
signature.setPublicKey("b0011765082a9352e04678ef38d38046dc01306edef676547456c0c23e270aaed7ffe9e31477");
TransactionSubmitRequest request = new TransactionSubmitRequest();
request.setTransactionBlob(transactionBlob);
request.addSignature(signature);

// 调用submit接口
TransactionSubmitResponse response = sdk.getTransactionService().submit(request);
if (0 == response.getErrorCode()) { // 交易提交成功
System.out.println(JSON.toJSONString(response.getResult(), true));
} else{
System.out.println("error: " + response.getErrorDesc());
}
  • getInfo

接口说明

该接口用于实现根据交易hash查询交易。

调用方法

TransactionGetInfoResponse getInfo (TransactionGetInfoRequest);

请求参数

参数类型描述
hashString交易hash

响应数据

参数类型描述
totalCountLong返回的总交易数
transactionsTransactionHistory[]交易内容

示例

// 初始化请求参数
String txHash = "1653f54fbba1134f7e35acee49592a7c29384da10f2f629c9a214f6e54747705";
TransactionGetInfoRequest request = new TransactionGetInfoRequest();
request.setHash(txHash);

// 调用getInfo接口
TransactionGetInfoResponse response = sdk.getTransactionService().getInfo(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

5.2. 操作结构

操作是指在交易在要做的事情,在构建操作之前,需要构建操作。目前操作有10种,分别是 AccountActivateOperation、AccountSetMetadataOperation、 AccountSetPrivilegeOperation、 AssetIssueOperation、 AssetSendOperation、 GasSendOperation、 ContractCreateOperation、 ContractInvokeByAssetOperation、 ContractInvokeByGasOperation、 LogCreateOperation。

BaseOperation

BaseOperation是buildBlob接口中所有操作的基类。

成员变量类型描述
sourceAddressString选填,操作源账户地址
metadataString选填,备注
  • AccountActivateOperation

功能

该操作用于激活账户。AccountActivateOperation继承于BaseOperation。

费用

FeeLimit目前固定是0.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
destAddressString必填,目标账户地址
initBalanceLong必填,初始化资产,单位UGas,1 Gas = 10^8 UGas, 大小(0, Long.MAX_VALUE]
metadataString选填,备注
  • AccountSetMetadataOperation

功能

该操作用于设置账户metadata。AccountSetMetadataOperation继承于BaseOperation。

费用

FeeLimit目前固定是0.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
keyString必填,metadata的关键词,长度限制[1, 1024]
valueString必填,metadata的内容,长度限制[0, 256000]
versionLong选填,metadata的版本
deleteFlagBoolean选填,是否删除metadata
metadataString选填,备注
  • AccountSetPrivilegeOperation

功能

该操作用于设置账户权限。AccountSetPrivilegeOperation继承于BaseOperation。

费用

feeLimit目前固定是0.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
masterWeightString选填,账户自身权重,大小限制[0, (Integer.MAX_VALUE * 2L + 1)]
signersSigner[]选填,签名者权重列表
txThresholdString选填,交易门限,大小限制[0, Long.MAX_VALUE]
typeThresholdTypeThreshold[]选填,指定类型交易门限
metadataString选填,备注
  • AssetIssueOperation

功能

该操作用于发行资产。AssetIssueOperation继承于BaseOperation。

费用

FeeLimit目前固定是50.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
codeString必填,资产编码,长度限制[1, 64]
assetAmountLong必填,资产发行数量,大小限制[0, Long.MAX_VALUE]
metadataString选填,备注
  • AssetSendOperation

注意:若目标账户未激活,必须先调用激活账户操作。

功能

该操作用于转移资产。AssetSendOperation继承于BaseOperation。

费用

FeeLimit目前固定是0.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
destAddressString必填,目标账户地址
codeString必填,资产编码,长度限制[1, 64]
issuerString必填,资产发行账户地址
assetAmountLong必填,资产数量,大小限制[0, Long.MAX_VALUE]
metadataString选填,备注
  • GasSendOperation

注意:若目标账户未激活,该操作也可使目标账户激活。

功能

该操作用于转移Gas。GasSendOperation继承于BaseOperation。

费用

FeeLimit目前固定是0.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
destAddressString必填,目标账户地址
gasAmountLong必填,资产发行数量,大小限制[0, Long.MAX_VALUE]
metadataString选填,备注
  • ContractCreateOperation

功能

该操作用于创建合约。ContractCreateOperation继承于BaseOperation。

费用

FeeLimit目前固定是10.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
initBalanceLong必填,给合约账户的初始化资产,单位UGas,1 Gas = 10^8 UGas, 大小限制[1, Long.MAX_VALUE]
typeInteger选填,合约的语种,默认是0
payloadString必填,对应语种的合约代码
initInputString选填,合约代码中init方法的入参
metadataString选填,备注
  • ContractInvokeByAssetOperation

注意:若合约账户不存在,必须先创建合约账户。

功能

该操作用于转移资产并触发合约。ContractInvokeByAssetOperation继承于BaseOperation。

费用

FeeLimit要根据合约中执行交易来做添加手续费,首先发起交易手续费目前是0.01Gas,然后合约中的交易也需要交易发起者添加相应交易的手续费。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
contractAddressString必填,合约账户地址
codeString选填,资产编码,长度限制[0, 64];当为空时,仅触发合约;
issuerString选填,资产发行账户地址,当null时,仅触发合约
assetAmountLong选填,资产数量,大小限制[0, Long.MAX_VALUE],当是0时,仅触发合约
inputString选填,待触发的合约的main()入参
metadataString选填,备注
  • ContractInvokeByGasOperation

注意:若目标账户非合约账户且未激活,该操作也可使目标账户激活。

功能

该操作用于转移Gas并触发合约。ContractInvokeByGasOperation继承于BaseOperation。

费用

FeeLimit要根据合约中执行交易来做添加手续费,首先发起交易手续费目前是0.01Gas,然后合约中的交易也需要交易发起者添加相应交易的手续费。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
contractAddressString必填,合约账户地址
gasAmountLong选填,资产发行数量,大小限制[0, Long.MAX_VALUE],当0时仅触发合约
inputString选填,待触发的合约的main()入参
metadataString选填,备注
  • LogCreateOperation

功能

该操作用于记录日志。LogCreateOperation继承于BaseOperation。

费用

FeeLimit目前固定是0.01 Gas。

成员

成员变量类型描述
sourceAddressString选填,操作源账户地址
topicString必填,日志主题,长度限制[1, 128]
datasList必填,日志内容,每个字符串长度限制[1, 1024]
metadataString选填,备注

5.3. 账户服务

账户服务提供账户相关的接口,包括6个接口: checkValid、getInfo、getNonce、getBalance、getAssets、getMetadata。

  • checkValid

接口说明

该接口用于检查区块链账户地址的有效性

调用方法

AccounCheckValidResponse checkValid(AccountCheckValidRequest)

请求参数

参数类型描述
addressString必填,待检查的区块链账户地址

响应数据

参数类型描述
isValidBoolean是否有效

示例

// 初始化请求参数
String address = "adxSdV6qWfyhJAmzrPbv3btsPPT6aFrqBku3C";
AccountCheckValidRequest request = new AccountCheckValidRequest();
request.setAddress(address);

// 调用checkValid
AccountCheckValidResponse response = sdk.getAccountService().checkValid(request);
if(0 == response.getErrorCode()) {
System.out.println(response.getResult().isValid());
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getInfo-Account

接口说明

该接口用于获取指定的账户信息

调用方法

AccountGetInfoResponse GetInfo(AccountGetInfoRequest);

请求参数

参数类型描述
addressString必填,待检查的区块链账户地址

响应数据

参数类型描述
addressString账户地址
balanceLong账户余额,单位UGas,1 Gas = 10^8 UGas, 必须大于0
nonceLong账户交易序列号,必须大于0
privPriv账户权限

示例

// 初始化请求参数
String accountAddress = "adxSdV6qWfyhJAmzrPbv3btsPPT6aFrqBku3C";
AccountGetInfoRequest request = new AccountGetInfoRequest();
request.setAddress(accountAddress);

// 调用getInfo接口
AccountGetInfoResponse response = sdk.getAccountService().getInfo(request);
if (response.getErrorCode() == 0) {
AccountGetInfoResult result = response.getResult();
System.out.println("账户信息: \n" + JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

接口说明

该接口用于获取指定账户的nonce值

调用方法

AccountGetNonceResponse getNonce(AccountGetNonceRequest);

请求参数

参数类型描述
addressString必填,待查询的区块链账户地址

响应数据

参数类型描述
nonceLong账户交易序列号

示例

// 初始化请求参数
String accountAddress = "adxSk9MTT6aGoMxjAxuEGt1agRvWWnng25RF2";
AccountGetNonceRequest request = new AccountGetNonceRequest();
request.setAddress(accountAddress);

// 调用getNonce接口
AccountGetNonceResponse response = sdk.getAccountService().getNonce(request);
if(0 == response.getErrorCode()){
System.out.println("账户nonce:" + response.getResult().getNonce());
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getBalance

接口说明

该接口用于获取指定账户的Gas的余额

调用方法

AccountGetBalanceResponse getBalance(AccountGetBalanceRequest);

请求参数

参数类型描述
addressString必填,待查询的区块链账户地址

响应数据

参数类型描述
balanceLongGas的余额,单位UGas,1 Gas = 10^8 UGas

示例

// 初始化请求参数
String accountAddress = "adxSk9MTT6aGoMxjAxuEGt1agRvWWnng25RF2";
AccountGetBalanceRequest request = new AccountGetBalanceRequest();
request.setAddress(accountAddress);

// 调用getBalance接口
AccountGetBalanceResponse response = sdk.getAccountService().getBalance(request);
if(0 == response.getErrorCode()){
AccountGetBalanceResult result = response.getResult();
System.out.println("Gas余额:" + ToBaseUnit.ToUGas(result.getBalance().toString()) + " Gas");
} else {
System.out.println("error: " + response.getErrorDesc());
}

接口说明

该接口用于获取指定账户的所有资产信息

调用方法

AccountGetAssets getAssets(AccountGetAssetsRequest);

请求参数

参数类型描述
addressString必填,待查询的账户地址

响应数据

参数类型描述
assetAssetInfo[]账户资产

示例

// 初始化请求参数
AccountGetAssetsRequest request = new AccountGetAssetsRequest();
request.setAddress("adxSmZHjDopQam2y5ntvHhGk4XEkiXc9MnFWZ");

// 调用getAssets接口
AccountGetAssetsResponse response = sdk.getAccountService().getAssets(request);
if (response.getErrorCode() == 0) {
AccountGetAssetsResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getMetadata

接口说明

该接口用于获取指定账户的metadata信息

调用方法

AccountGetMetadataResponse getMetadata(AccountGetMetadataRequest);

请求参数

参数类型描述
addressString必填,待查询的账户地址
keyString选填,metadata关键字,长度限制[1, 1024]

响应数据

参数类型描述
metadataMetadataInfo账户

示例

// 初始化请求参数
String accountAddress = "adxSmZHjDopQam2y5ntvHhGk4XEkiXc9MnFWZ";
AccountGetMetadataRequest request = new AccountGetMetadataRequest();
request.setAddress(accountAddress);
request.setKey("20180704");

// 调用getMetadata接口
AccountGetMetadataResponse response = sdk.getAccountService().getMetadata(request);
if (response.getErrorCode() == 0) {
AccountGetMetadataResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

5.4. 资产服务

账户服务提供资产相关的接口,目前有1个接口:getInfo

  • getInfo-Asset

接口说明

该接口用于获取指定账户的指定资产信息

调用方法

AssetGetInfoResponse getInfo(AssetGetInfoRequest);

请求参数

参数类型描述
addressString必填,待查询的账户地址
codeString必填,资产编码,长度限制[1, 64]
issuerString必填,资产发行账户地址

响应数据

参数类型描述
assetAssetInfo[]账户资产

示例

// 初始化请求参数
AssetGetInfoRequest request = new AssetGetInfoRequest();
request.setAddress("adxSmZHjDopQam2y5ntvHhGk4XEkiXc9MnFWZ");
request.setIssuer("adxSdV6qWfyhJAmzrPbv3btsPPT6aFrqBku3C");
request.setCode("HNC");

// 调用getInfo消息
AssetGetInfoResponse response = sdk.getAssetService().getInfo(request);
if (response.getErrorCode() == 0) {
AssetGetInfoResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

5.5. 合约服务

合约服务提供合约相关的接口,目前有4个接口:checkValid、getInfo、getAddress、call

  • checkValid-Contract

接口说明

该接口用于检测合约账户的有效性

调用方法

ContractCheckValidResponse checkValid(ContractCheckValidRequest)

请求参数

参数类型描述
contractAddressString待检测的合约账户地址

响应数据

参数类型描述
isValidBoolean是否有效

示例

// 初始化请求参数
ContractCheckValidRequest request = new ContractCheckValidRequest();
request.setContractAddress("adxSYQ8iMyZ7Dkj1oX1kjGMV55WXvoPKcLEK3");

// 调用checkValid接口
ContractCheckValidResponse response = sdk.getContractService().checkValid(request);
if (response.getErrorCode() == 0) {
ContractCheckValidResult result = response.getResult();
System.out.println(result.getValid());
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getInfo-Contract

接口说明

该接口用于查询合约代码

调用方法

ContractGetInfoResponse getInfo (ContractGetInfoRequest);

请求参数

参数类型描述
contractAddressString待查询的合约账户地址

响应数据

参数类型描述
contractContractInfo合约信息

示例

// 初始化请求参数
ContractGetInfoRequest request = new ContractGetInfoRequest();
request.setContractAddress("adxSYQ8iMyZ7Dkj1oX1kjGMV55WXvoPKcLEK3");

// 调用getInfo接口
ContractGetInfoResponse response = sdk.getContractService().getInfo(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getAddress

接口说明

该接口用于查询合约地址

调用方法

ContractGetAddressResponse getInfo (ContractGetAddressRequest);

请求参数

参数类型描述
hashString创建合约交易的hash

响应数据

参数类型描述
contractAddressListList合约地址列表

示例

// 初始化请求参数
ContractGetAddressRequest request = new ContractGetAddressRequest();
request.setHash("44246c5ba1b8b835a5cbc29bdc9454cdb9a9d049870e41227f2dcfbcf7a07689");

// 调用getAddress接口
ContractGetAddressResponse response = sdk.getContractService().getAddress(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

接口说明

该接口用于调试合约代码

调用方法

ContractCallesponse call(ContractCallRequest);

请求参数

参数类型描述
sourceAddressString选填,合约触发账户地址
contractAddressString选填,合约账户地址,与code不能同时为空
codeString选填,合约代码,与contractAddress不能同时为空,长度限制[1, 64]
inputString选填,合约入参
contractBalanceString选填,赋予合约的初始 Gas 余额, 单位UGas,1 Gas = 10^8 UGas, 大小限制[1, Long.MAX_VALUE]
optTypeInteger必填,0: 调用合约的读写接口 init, 1: 调用合约的读写接口 main, 2 :调用只读接口 query
feeLimitLong交易要求的最低手续费, 大小限制[1, Long.MAX_VALUE]
gasPriceLong交易费用单价,按字节收费,大小限制[1000, Long.MAX_VALUE]

响应数据

参数类型描述
logsJSONObject日志信息
queryRetsJSONArray查询结果集
statContractStat合约资源占用信息
txsTransactionEnvs[]交易集

示例

// 初始化请求参数
ContractCallRequest request = new ContractCallRequest();
request.setCode("\"use strict\";log(undefined);function query() { getBalance(thisAddress); }");
request.setFeeLimit(1000000000L);
request.setOptType(2);

// 调用call接口
ContractCallResponse response = sdk.getContractService().call(request);
if (response.getErrorCode() == 0) {
ContractCallResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

5.6. 区块服务

区块服务主要是区块相关的接口,目前有11个接口:getNumber、checkStatus、getTransactions、getInfo、getLatestInfo、getValidators、getLatestValidators、getReward、getLatestReward、getFees、getLatestFees。

接口说明

该接口用于查询最新的区块高度。

调用方法

BlockGetNumberResponse getNumber();

响应数据

参数类型描述
blockNumberLong最新的区块高度,对应底层字段seq

示例

// 调用getNumber接口
BlockGetNumberResponse response = sdk.getBlockService().getNumber();
if(0 == response.getErrorCode()){
System.out.println(JSON.toJSONString(response.getResult(), true));
}else{
System.out.println("error: " + response.getErrorDesc());
}
  • checkStatus

接口说明

该接口用于检查本地节点区块是否同步完成。

调用方法

BlockCheckStatusResponse checkStatus();

响应数据

参数类型描述
isSynchronousBoolean区块是否同步

示例

// 调用checkStatus
BlockCheckStatusResponse response = sdk.getBlockService().checkStatus();
if(0 == response.getErrorCode()){
System.out.println(JSON.toJSONString(response.getResult(), true));
}else{
System.out.println("error: " + response.getErrorDesc());
}
  • getTransactions

接口说明

该接口用于查询指定区块高度下的所有交易。

调用方法

BlockGetTransactionsResponse getTransactions(BlockGetTransactionsRequest);

请求参数

参数类型描述
blockNumberLong必填,待查询的区块高度,必须大于0

响应数据

参数类型描述
totalCountLong返回的总交易数
transactionsTransactionHistory[]交易内容

示例

// 初始化请求参数
Long blockNumber = 617247L;// 第617247区块
BlockGetTransactionsRequest request = new BlockGetTransactionsRequest();
request.setBlockNumber(blockNumber);

// 调用getTransactions接口
BlockGetTransactionsResponse response = sdk.getBlockService().getTransactions(request);
if(0 == response.getErrorCode()){
System.out.println(JSON.toJSONString(response.getResult(), true));
}else{
System.out.println("error: " + response.getErrorDesc());
}
  • getInfo-Block

接口说明

该接口用于获取区块信息。

调用方法

BlockGetInfoResponse getInfo(BlockGetInfoRequest);

请求参数

参数类型描述
blockNumberLong必填,待查询的区块高度

响应数据

参数类型描述
closeTimeLong区块关闭时间
numberLong区块高度
txCountLong交易总量
versionString区块版本

示例

// 初始化请求参数
BlockGetInfoRequest request = new BlockGetInfoRequest();
request.setBlockNumber(629743L);

// 调用getInfo接口
BlockGetInfoResponse response = sdk.getBlockService().getInfo(request);
if (response.getErrorCode() == 0) {
BlockGetInfoResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getLatestInfo

接口说明

该接口用于获取最新区块信息。

调用方法

BlockGetLatestInfoResponse getLatestInfo();

响应数据

参数类型描述
closeTimeLong区块关闭时间
numberLong区块高度,对应底层字段seq
txCountLong交易总量
versionString区块版本

示例

// 调用getLatestInfo接口
BlockGetLatestInfoResponse response = sdk.getBlockService().getLatestInfo();
if (response.getErrorCode() == 0) {
BlockGetLatestInfoResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getValidators

接口说明

该接口用于获取指定区块中所有验证节点数。

调用方法

BlockGetValidatorsResponse getValidators(BlockGetValidatorsRequest);

请求参数

参数类型描述
blockNumberLong必填,待查询的区块高度,必须大于0

响应数据

参数类型描述
validatorsValidatorInfo[]验证节点列表

示例

// 初始化请求参数
BlockGetValidatorsRequest request = new BlockGetValidatorsRequest();
request.setBlockNumber(629743L);

// 调用getValidators接口
BlockGetValidatorsResponse response = sdk.getBlockService().getValidators(request);
if (response.getErrorCode() == 0) {
BlockGetValidatorsResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getLatestValidators

接口说明

该接口用于获取最新区块中所有验证节点数。

调用方法

BlockGetLatestValidatorsResponse getLatestValidators();

响应数据

参数类型描述
validatorsValidatorInfo[]验证节点列表

示例

// 调用getLatestValidators接口
BlockGetLatestValidatorsResponse response = sdk.getBlockService().getLatestValidators();
if (response.getErrorCode() == 0) {
BlockGetLatestValidatorsResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

接口说明

该接口用于获取指定区块中的区块奖励和验证节点奖励。

调用方法

BlockGetRewardResponse getReward(BlockGetRewardRequest);

请求参数

参数类型描述
blockNumberLong必填,待查询的区块高度,必须大于0

响应数据

参数类型描述
blockRewardLong区块奖励数
validatorsRewardValidatorReward[]验证节点奖励情况

示例

// 初始化请求参数
BlockGetRewardRequest request = new BlockGetRewardRequest();
request.setBlockNumber(629743L);

// 调用getReward接口
BlockGetRewardResponse response = sdk.getBlockService().getReward(request);
if (response.getErrorCode() == 0) {
BlockGetRewardResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getLatestReward

接口说明

获取最新区块中的区块奖励和验证节点奖励。

调用方法

BlockGetLatestRewardResponse getLatestReward();

响应数据

参数类型描述
blockRewardLong区块奖励数
validatorsRewardValidatorReward[]验证节点奖励情况

示例

// 调用getLatestReward接口
BlockGetLatestRewardResponse response = sdk.getBlockService().getLatestReward();
if (response.getErrorCode() == 0) {
BlockGetLatestRewardResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

接口说明

获取指定区块中的账户最低资产限制和费用单价,按字节收费。

调用方法

BlockGetFeesResponse getFees(BlockGetFeesRequest);

请求参数

参数类型描述
blockNumberLong必填,待查询的区块高度,必须大于0

响应数据

参数类型描述
feesFees费用

示例

// 初始化请求参数
BlockGetFeesRequest request = new BlockGetFeesRequest();
request.setBlockNumber(629743L);

// 调用getFees接口
BlockGetFeesResponse response = sdk.getBlockService().getFees(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
  • getLatestFees

接口说明

该接口用于获取最新区块中的账户最低资产限制和费用单价,按字节收费。

调用方法

BlockGetLatestFeesResponse getLatestFees();

响应数据

参数类型描述
feesFees费用

示例

// 调用getLatestFees接口
BlockGetLatestFeesResponse response = sdk.getBlockService().getLatestFees();
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}

6. 场景示例代码

6.1. 生成账户

package cn.bubi.sdk.example;

import com.alibaba.fastjson.JSON;
import cn.bubi.SDK;
import cn.bubi.common.ToBaseUnit;
import cn.bubi.crypto.Keypair;
import cn.bubi.model.request.TransactionBuildBlobRequest;
import cn.bubi.model.request.TransactionSignRequest;
import cn.bubi.model.request.TransactionSubmitRequest;
import cn.bubi.model.request.operation.AccountActivateOperation;
import cn.bubi.model.request.operation.BaseOperation;
import cn.bubi.model.response.TransactionBuildBlobResponse;
import cn.bubi.model.response.TransactionSignResponse;
import cn.bubi.model.response.TransactionSubmitResponse;
import cn.bubi.model.response.result.TransactionBuildBlobResult;
import org.testng.annotations.Test;

import java.util.ArrayList;
import java.util.List;

public class BatchCreateBuchainAccountDemo {
SDK sdk = SDK.getInstance("http://node.bubidev.cn");
/**
* 批量创建账户
*
* 注意:一次最多100个创建账户的操作,该操作是原子性的。每个初始化账户推荐给0.02Gas,交易费用100个操作的情况下建议feeLimist为0.1Gas
*/
@Test
public void createBuchainAccount(){
// 推荐人账户地址
String refereeAddress = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
// 推荐人账户私钥
String refereePrivateKey = "privbw1Uup9Qif12uysm9LyCby3HC5s6m7FMBzU4Ac64NVZ2tvB4f8wB";

// 推荐人账户nonce
// TODO 需要查询当前推荐人的nonce值
Long refereeNonce = null;
AccountGetNonceRequest getNonceRequest = new AccountGetNonceRequest();
getNonceRequest.setAddress(refereeAddress);

// 调用getNonce接口
AccountGetNonceResponse getNonceResponse = sdk.getAccountService().getNonce(getNonceRequest);

// 赋值nonce
if (getNonceResponse.getErrorCode() == 0) {
AccountGetNonceResult result = getNonceResponse.getResult();
refereeNonce = result.getNonce()+1;

}

// The fixed write 1000L, the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 0.01Gas
Long feeLimit = ToBaseUnit.ToUGas("0.1");

// 每个账户初始化0.02Gas
Long initBalance = ToBaseUnit.ToUGas("0.02");
List<AccountActivateOperation> accountActivateOperationList = new ArrayList<AccountActivateOperation>();
Keypair keypair;
// 注意:交易里最多100个操作
for (int i = 0; i < 100; i++) {
keypair = Keypair.generator();
AccountActivateOperation operation = new AccountActivateOperation();
operation.setSourceAddress(refereeAddress);
operation.setDestAddress(keypair.getAddress());
operation.setInitBalance(initBalance);
accountActivateOperationList.add(operation);
System.out.println("第" + i + " " + JSON.toJSONString(keypair));
}

// 提交交易(广播交易),生成的hash,需要通过hash再次查询交易来确认最终状态。
String hash = submitTransaction(refereePrivateKey,refereeAddress,accountActivateOperationList,refereeNonce, gasPrice, feeLimit, "");
if(hash != null){
System.out.println("tx hash:" + hash);
}else{
System.out.println("操作失败");
}
}

/**
* @param submiterPrivateKey The account private key to start transaction
* @param submiterAddresss The account address to start transaction
* @param operations operations
* @param submiterNonce initiation account's Nonce
* @param gasPrice Gas price
* @param feeLimit fee limit
* @return java.lang.String transaction hash
*/
private String submitTransaction(String submiterPrivateKey, String submiterAddresss, List<AccountActivateOperation> operations, Long submiterNonce, Long gasPrice, Long feeLimit, String transMetadata) {
// 1. Build transaction
TransactionBuildBlobRequest transactionBuildBlobRequest = new TransactionBuildBlobRequest();
transactionBuildBlobRequest.setSourceAddress(submiterAddresss);
transactionBuildBlobRequest.setNonce(submiterNonce);
transactionBuildBlobRequest.setFeeLimit(feeLimit);
transactionBuildBlobRequest.setGasPrice(gasPrice);
for (BaseOperation opt: operations
) {
transactionBuildBlobRequest.addOperation(opt);
}
transactionBuildBlobRequest.setMetadata(transMetadata);

// 2. Build transaction BLob
String transactionBlob;
TransactionBuildBlobResponse transactionBuildBlobResponse = sdk.getTransactionService().buildBlob(transactionBuildBlobRequest);
if (transactionBuildBlobResponse.getErrorCode() != 0) {
System.out.println("error: " + transactionBuildBlobResponse.getErrorDesc());
return null;
}
TransactionBuildBlobResult transactionBuildBlobResult = transactionBuildBlobResponse.getResult();
transactionBlob = transactionBuildBlobResult.getTransactionBlob();

// 3. Sign transaction BLob
String[] signerPrivateKeyArr = {submiterPrivateKey};
TransactionSignRequest transactionSignRequest = new TransactionSignRequest();
transactionSignRequest.setBlob(transactionBlob);
for (String s : signerPrivateKeyArr) {
transactionSignRequest.addPrivateKey(s);
}
TransactionSignResponse transactionSignResponse = sdk.getTransactionService().sign(transactionSignRequest);
if (transactionSignResponse.getErrorCode() != 0) {
System.out.println("error: " + transactionSignResponse.getErrorDesc());
return null;
}

// 4. Broadcast transaction
String Hash = null;
TransactionSubmitRequest transactionSubmitRequest = new TransactionSubmitRequest();
transactionSubmitRequest.setTransactionBlob(transactionBlob);
transactionSubmitRequest.setSignatures(transactionSignResponse.getResult().getSignatures());
TransactionSubmitResponse transactionSubmitResponse = sdk.getTransactionService().submit(transactionSubmitRequest);
if (0 == transactionSubmitResponse.getErrorCode()) {
Hash = transactionSubmitResponse.getResult().getHash();
} else {
System.out.println(JSON.toJSONString(transactionSubmitResponse, true));
}
return Hash;
}


}

6.2. 激活账户

public void activateAccount() {
// The account private key to activate a new account
String activatePrivateKey = "privbyQCRp7DLqKtRFCqKQJr81TurTqG6UKXMMtGAmPG3abcM9XHjWvq";
Long initBalance = ToBaseUnit.ToUGas("1000");
// The fixed write 1000L, the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 0.01Gas
Long feeLimit = ToBaseUnit.ToUGas("0.01");
// Transaction initiation account's nonce + 1
Long nonce = 8L;

// Generate a new account to be activated
Keypair keypair = Keypair.generator();
System.out.println(JSON.toJSONString(keypair, true));
String destAccount = keypair.getAddress();

// 1. Get the account address to send this transaction
String activateAddresss = getAddressByPrivateKey(activatePrivateKey);

// 2. Build activateAccount
AccountActivateOperation operation = new AccountActivateOperation();
operation.setSourceAddress(activateAddresss);
operation.setDestAddress(destAccount);
operation.setInitBalance(initBalance);
operation.setMetadata("activate account");

String[] signerPrivateKeyArr = {activatePrivateKey};
// Record txhash for subsequent confirmation of the real result of the transaction.
// After recommending five blocks, call again through txhash `Get the transaction information
// from the transaction Hash'(see example: getTxByHash ()) to confirm the final result of the transaction
String txHash = submitTransaction(signerPrivateKeyArr, activateAddresss, operation, nonce, gasPrice, feeLimit);
if (txHash != null) {
System.out.println("hash: " + txHash);
}
}

6.3. 部署合约

import com.alibaba.fastjson.JSONObject;
import cn.bubi.SDK;
import cn.bubi.common.ToBaseUnit;
import cn.bubi.model.request.*;
import cn.bubi.model.request.operation.BaseOperation;
import cn.bubi.model.request.operation.ContractCreateOperation;
import cn.bubi.model.response.*;
import cn.bubi.model.response.result.data.Signature;
import cn.bubi.model.response.result.data.TransactionHistory;
import org.junit.Test;

/**
* @Author riven
*/
public class CreateContractDemo {
public SDK sdk = SDK.getInstance("http://192.168.6.123:19333");
public String accountAddress = "adxSYmvoQXGc831Swotbah5udGZWoqQjSZpmY";
public String privateKey = "privbtacCSANUxPn8sXU358Wz3HfXArvmcy7aT9SDdrbPEkYJVGpinUG";
public String contract = "'use strict';\n function _saveObj(key, value){\n Chain.store(key, JSON.stringify(value));\n }\n function queryData(params) {\n let hash= params.hash;\n let data = JSON.parse(Chain.load(hash));\n Utils.assert(data !== false, '10000,The data hashnot existed');\n return data;\n }\n function store(params){\n Utils.assert(params.hash!== undefined, '10003,The hashparams error');\n let hash= params.hash;\n let data = JSON.parse(Chain.load(hash));\n Utils.assert(data === false, '10001,The data hashis already existed');\n let dataJson = {};\n dataJson = params.data;\n Chain.store(hash,JSON.stringify(dataJson));\n }\n function init(input){\n return;\n }\n function main(input_str){\n let input = JSON.parse(input_str);\n if(input.method === 'store'){\n store(input.params);\n }\n else{\n throw '<Main interface passes an invalid operation type>';\n }\n }\n function query(input_str){\n let input = JSON.parse(input_str);\n let object ={};\n if(input.method === 'queryData'){\n object = queryData(input.params);\n }\n else{\n throw '<unidentified operation type>';\n }\n return JSON.stringify(object);\n }";
@Test
public void createContract() {
BaseOperation[] baseOperations = buildOperations();
long accountNonce = getAccountNonce();
System.out.println("accountNonce:"+accountNonce);
String transactionBlob = seralizeTransaction(accountNonce, baseOperations);
Signature[] signatures = signTransaction(transactionBlob);
String hash = submitTransaction(transactionBlob, signatures);
System.out.println("hash:"+hash);
int errorCode = checkTransactionStatus(hash);
System.out.println("errorCode:"+errorCode);

}
public long getAccountNonce() {
long nonce = 0;

// Init request

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

public BaseOperation[] buildOperations() {
// The account address to issue apt1.0 token
String createContractAddress = accountAddress;
// Contract account initialization Gas,the unit is UGas,and 1 Gas = 10^8 UGas
Long initBalance = ToBaseUnit.ToUGas("0.01");
// The token name
String name = "Contract Global";
// The token code
String symbol = "CGO";
// The token total supply, which includes the dicimals.
// If decimals is 8 and you want to issue 10 tokens now, the nowSupply must be 10 * 10 ^ 8, like below.
String totalSupply = "1000000000";
// The token decimals
Integer decimals = 8;
// Contract code
String payload = contract;

// Init initInput
JSONObject initInput = new JSONObject();
JSONObject params = new JSONObject();
params.put("name", name);
params.put("symbol", symbol);
params.put("decimals", decimals);
params.put("totalSupply", totalSupply);
initInput.put("params", params);

// Build create contract operation
ContractCreateOperation contractCreateOperation = new ContractCreateOperation();
contractCreateOperation.setSourceAddress(createContractAddress);
contractCreateOperation.setInitBalance(initBalance);
contractCreateOperation.setPayload(payload);
contractCreateOperation.setInitInput(initInput.toJSONString());
contractCreateOperation.setMetadata("create ctp 1.0 contract");

return new BaseOperation[]{ contractCreateOperation };
}

public String seralizeTransaction(Long nonce, BaseOperation[] operations) {
String transactionBlob = null;

// The account address to create contract and issue ctp 1.0 token
String senderAddresss = accountAddress;
// The gasPrice is fixed at 1000L, the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 10.08Gas
Long feeLimit = ToBaseUnit.ToUGas("10.08");
// 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 (BaseOperation operation : operations) {
transactionBuildBlobRequest.addOperation(operation);
}
TransactionBuildBlobResponse transactionBuildBlobResponse = sdk.getTransactionService().buildBlob(transactionBuildBlobRequest);
if (transactionBuildBlobResponse.getErrorCode() == 0) {
transactionBlob = transactionBuildBlobResponse. getResult().getTransactionBlob();
} else {
System.out.println("error: " + transactionBuildBlobResponse.getErrorDesc());
}
return transactionBlob;
}

public Signature[] signTransaction(String transactionBlob) {
Signature[] signatures = null;
// The account private key to issue atp1.0 token
String senderPrivateKey = privateKey;

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

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


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

}

6.4. 调用合约

package cn.bubi.sdk.example;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cn.bubi.SDK;
import cn.bubi.common.ToBaseUnit;
import cn.bubi.encryption.key.PrivateKey;
import cn.bubi.model.request.*;
import cn.bubi.model.request.operation.BaseOperation;
import cn.bubi.model.request.operation.ContractCreateOperation;
import cn.bubi.model.request.operation.ContractInvokeByAssetOperation;
import cn.bubi.model.request.operation.ContractInvokeByGasOperation;
import cn.bubi.model.response.*;
import cn.bubi.model.response.result.ContractCallResult;
import cn.bubi.model.response.result.ContractCheckValidResult;
import cn.bubi.model.response.result.TransactionBuildBlobResult;
import org.testng.annotations.Test;

/**
* @Author riven
*/
public class ContractDemo {
SDK sdk = SDK.getInstance("http://node.bubidev.cn");

/**
* Check whether the contract is valid
*/
@Test
public void checkContractValid() {
// Init request
ContractCheckValidRequest request = new ContractCheckValidRequest();
request.setContractAddress("adxSqKcX8wGCMKhzNUBoDWfbeQaMhfnGdtyG2");

// Call checkValid
ContractCheckValidResponse response = sdk.getContractService().checkValid(request);
if (response.getErrorCode() == 0) {
ContractCheckValidResult result = response.getResult();
System.out.println(result.getValid());
} else {
System.out.println("error: " + response.getErrorDesc());
}
}

/**
* Get contract info
*/
@Test
public void getContractInfo() {
// Init request
ContractGetInfoRequest request = new ContractGetInfoRequest();
request.setContractAddress("adxSqKcX8wGCMKhzNUBoDWfbeQaMhfnGdtyG2");

// Call getInfo
ContractGetInfoResponse response = sdk.getContractService().getInfo(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
}

/**
* Get contract address
*/
@Test
public void getContractAddress() {
// Init request
String hash = "44246c5ba1b8b835a5cbc29bdc9454cdb9a9d049870e41227f2dcfbcf7a07689";
ContractGetAddressRequest request = new ContractGetAddressRequest();
request.setHash(hash);

// Call getAddress
ContractGetAddressResponse response = sdk.getContractService().getAddress(request);
if (response.getErrorCode() == 0) {
System.out.println(JSON.toJSONString(response.getResult(), true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
}

/**
* call contract
*/
@Test
public void callContract() {
// Init variable
// Contract address
String contractAddress = "adxSqKcX8wGCMKhzNUBoDWfbeQaMhfnGdtyG2";
// Spender address
String spender = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
// Amount
String amount = "1000000";

// Init input
JSONObject input = new JSONObject();
input.put("method", "approve");
JSONObject params = new JSONObject();
params.put("spender", spender);
params.put("value", amount);
input.put("params", params);

// Init request
ContractCallRequest request = new ContractCallRequest();
request.setContractAddress(contractAddress);
request.setFeeLimit(1000000000L);
request.setOptType(1);
request.setInput(input.toJSONString());

// Call call
ContractCallResponse response = sdk.getContractService().call(request);
if (response.getErrorCode() == 0) {
ContractCallResult result = response.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + response.getErrorDesc());
}
}

/**
* 创建合约
*/
@Test
public void createContract() {
// The account private key to create contract
String createPrivateKey = "privbUdwf6xV1d5Jvkcakuz8T8nfFn4U7d5s55VUbwmi79DPxqNWSD1n";
// Contract account initialization Gas,the unit is UGas,and 1 Gas = 10^8 UGas
Long initBalance = 100000000L;//ToBaseUnit.ToUGas("0.1");
// Contract code
String payload = "\n \"use strict\";\n function init(bar)\n {\n /*init whatever you want*/\n return;\n }\n \n function main(input)\n {\n let para = JSON.parse(input);\n if (para.do_foo)\n {\n let x = {\n 'hello' : 'world'\n };\n }\n }\n \n function query(input)\n { \n return input;\n }\n ";
// The fixed write 1000L ,the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 10.01Gas
Long feeLimit = 1015076000L;//ToBaseUnit.ToUGas("10.01");
// Transaction initiation account's Nonce + 1
Long nonce = 18L;
// Contract init function entry
String initInput = "";

// 1. Get the account address to send this transaction
String createAddresss = getAddressByPrivateKey(createPrivateKey);

// 2. Build activateAccount operation
ContractCreateOperation operation = new ContractCreateOperation();
operation.setSourceAddress(createAddresss);
operation.setInitBalance(initBalance);
operation.setPayload(payload);
operation.setInitInput(initInput);
operation.setMetadata("create contract");

// Record txhash for subsequent confirmation of the real result of the transaction.
// After recommending five blocks, call again through txhash `Get the transaction information
// from the transaction Hash'(see example: getTxByHash ()) to confirm the final result of the transaction
String txHash = submitTransaction(createPrivateKey, createAddresss, operation, nonce, gasPrice, feeLimit);
if (txHash != null) {
System.out.println("hash: " + txHash);
}
}

/**
* Send asset and trigger contract
*/
@Test
public void invokeContractByAsset() {
// Init variable
// The account private key to invoke contract
String invokePrivateKey = "privby8cFTi4ugxc95qJMF5PvCz6PvQAxhUXAZoqFENUKRE19tM1Vbii";
// The account to receive the assets
String destAddress = "adxScpCtbeLP2KGRaCkbtrmz8iB5mu6DQcW3r";
// The asset code to be sent
String assetCode = "TST";
// The account address to issue asset
String assetIssuer = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
// 0 means that the contract is only triggered
Long amount = 0L;
// The fixed write 1000L, the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 0.01Gas
Long feeLimit = ToBaseUnit.ToUGas("0.01");
// Transaction initiation account's Nonce + 1
Long nonce = 57L;
// Contract main function entry
String input = "";

// 1. Get the account address to send this transaction
String invokeAddresss = getAddressByPrivateKey(invokePrivateKey);

// 2. Build sendAsset operation
ContractInvokeByAssetOperation operation = new ContractInvokeByAssetOperation();
operation.setSourceAddress(invokeAddresss);
operation.setContractAddress(destAddress);
operation.setCode(assetCode);
operation.setIssuer(assetIssuer);
operation.setAssetAmount(amount);
operation.setInput(input);
operation.setMetadata("send token");

// Record txhash for subsequent confirmation of the real result of the transaction.
// After recommending five blocks, call again through txhash `Get the transaction information
// from the transaction Hash'(see example: getTxByHash ()) to confirm the final result of the transaction
String txHash = submitTransaction(invokePrivateKey, invokeAddresss, operation, nonce, gasPrice, feeLimit);
if (txHash != null) {
System.out.println("hash: " + txHash);
}
}

/**
* Send Gas and trigger contract
*/
@Test
public void invokeContractByGas() {
// Init variable
// The account private key to invoke contract
String invokePrivateKey = "privby8cFTi4ugxc95qJMF5PvCz6PvQAxhUXAZoqFENUKRE19tM1Vbii";
// The account to receive the Gas
String destAddress = "adxSqKcX8wGCMKhzNUBoDWfbeQaMhfnGdtyG2";
// 0 means that the contract is only triggered
Long amount = 0L;
// The fixed write 1000L, the unit is UGas
Long gasPrice = 1000L;
// Set up the maximum cost 0.01Gas
Long feeLimit = ToBaseUnit.ToUGas("0.01");
// Transaction initiation account's Nonce + 1
Long nonce = 58L;
// Contract main function entry
String input = "";

// 1. Get the account address to send this transaction
String invokeAddresss = getAddressByPrivateKey(invokePrivateKey);

// 2. Build sendAsset operation
ContractInvokeByGasOperation operation = new ContractInvokeByGasOperation();
operation.setSourceAddress(invokeAddresss);
operation.setContractAddress(destAddress);
operation.setBuAmount(amount);
operation.setInput(input);

// Record txhash for subsequent confirmation of the real result of the transaction.
// After recommending five blocks, call again through txhash `Get the transaction information
// from the transaction Hash'(see example: getTxByHash ()) to confirm the final result of the transaction
String txHash = submitTransaction(invokePrivateKey, invokeAddresss, operation, nonce, gasPrice, feeLimit);
if (txHash != null) {
System.out.println("hash: " + txHash);
}
}

/**
* @param senderPrivateKey The account private key to start transaction
* @param senderAddresss The account address to start transaction
* @param operation operation
* @param senderNonce Transaction initiation account's Nonce
* @param gasPrice Gas price
* @param feeLimit fee limit
* @return java.lang.String transaction hash
* @author riven
*/
private String submitTransaction(String senderPrivateKey, String senderAddresss, BaseOperation operation, Long senderNonce, Long gasPrice, Long feeLimit) {
// 3. Build transaction
TransactionBuildBlobRequest transactionBuildBlobRequest = new TransactionBuildBlobRequest();
transactionBuildBlobRequest.setSourceAddress(senderAddresss);
transactionBuildBlobRequest.setNonce(senderNonce);
transactionBuildBlobRequest.setFeeLimit(feeLimit);
transactionBuildBlobRequest.setGasPrice(gasPrice);
transactionBuildBlobRequest.addOperation(operation);
// transactionBuildBlobRequest.setMetadata("abc");

// 4. Build transaction BLob
String transactionBlob;
TransactionBuildBlobResponse transactionBuildBlobResponse = sdk.getTransactionService().buildBlob(transactionBuildBlobRequest);
if (transactionBuildBlobResponse.getErrorCode() != 0) {
System.out.println("error: " + transactionBuildBlobResponse.getErrorDesc());
return null;
}
TransactionBuildBlobResult transactionBuildBlobResult = transactionBuildBlobResponse.getResult();
String txHash = transactionBuildBlobResult.getHash();
transactionBlob = transactionBuildBlobResult.getTransactionBlob();

// 5. Sign transaction BLob
String[] signerPrivateKeyArr = {senderPrivateKey};
TransactionSignRequest transactionSignRequest = new TransactionSignRequest();
transactionSignRequest.setBlob(transactionBlob);
for (String s : signerPrivateKeyArr) {
transactionSignRequest.addPrivateKey(s);
}
TransactionSignResponse transactionSignResponse = sdk.getTransactionService().sign(transactionSignRequest);
if (transactionSignResponse.getErrorCode() != 0) {
System.out.println("error: " + transactionSignResponse.getErrorDesc());
return null;
}

// 6. Broadcast
TransactionSubmitRequest transactionSubmitRequest = new TransactionSubmitRequest();
transactionSubmitRequest.setTransactionBlob(transactionBlob);
transactionSubmitRequest.setSignatures(transactionSignResponse.getResult().getSignatures());
TransactionSubmitResponse transactionSubmitResponse = sdk.getTransactionService().submit(transactionSubmitRequest);
if (0 == transactionSubmitResponse.getErrorCode()) {
System.out.println("Success,hash=" + transactionSubmitResponse.getResult().getHash());
} else {
System.out.println("Failure,hash=" + transactionSubmitResponse.getResult().getHash() + "");
System.out.println(JSON.toJSONString(transactionSubmitResponse, true));
}
return txHash;
}

/**
* @param privatekey private key
* @return java.lang.String Account address
* @author riven
*/
private String getAddressByPrivateKey(String privatekey) {
String publicKey = PrivateKey.getEncPublicKey(privatekey);
return PrivateKey.getEncAddress(publicKey);
}
}

6.5. 交易

package cn.bubi.sdk.example;

import com.alibaba.fastjson.JSON;
import cn.bubi.SDK;
import cn.bubi.common.ToBaseUnit;
import cn.bubi.model.request.AccountGetNonceRequest;
import cn.bubi.model.request.TransactionBuildBlobRequest;
import cn.bubi.model.request.TransactionSignRequest;
import cn.bubi.model.request.TransactionSubmitRequest;
import cn.bubi.model.request.operation.GasSendOperation;
import cn.bubi.model.response.AccountGetNonceResponse;
import cn.bubi.model.response.TransactionBuildBlobResponse;
import cn.bubi.model.response.TransactionSignResponse;
import cn.bubi.model.response.TransactionSubmitResponse;
import cn.bubi.model.response.result.AccountGetNonceResult;
import cn.bubi.model.response.result.TransactionBuildBlobResult;
import cn.bubi.model.response.result.TransactionSignResult;
import org.testng.annotations.Test;

/**
* @Author riven
*/
public class submitTransactionDemo {
SDK sdk = SDK.getInstance("http://node.bubidev.cn");

/*
* Get account nonce to start transaction
*/
@Test
public void getAccountNonce() {
// Init request
String senderAddress = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
AccountGetNonceRequest getNonceRequest = new AccountGetNonceRequest();
getNonceRequest.setAddress(senderAddress);

// Call getNonce
AccountGetNonceResponse getNonceResponse = sdk.getAccountService().getNonce(getNonceRequest);

// Get nonce
if (getNonceResponse.getErrorCode() == 0) {
AccountGetNonceResult result = getNonceResponse.getResult();
System.out.println("nonce: " + result.getNonce());
} else {
System.out.println("error" + getNonceResponse.getErrorDesc());
}
}

/*
* Build operation
*/
@Test
public void buildOperation() {
String senderAddress = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
String destAddress = "adxScpCtbeLP2KGRaCkbtrmz8iB5mu6DQcW3r";
Long amount = ToBaseUnit.ToUGas("10.9");

GasSendOperation operation = new GasSendOperation();
operation.setSourceAddress(senderAddress);
operation.setDestAddress(destAddress);
operation.setAmount(amount);

System.out.println(JSON.toJSONString(operation, true));
}

/*
* Build transaction blob
*/
@Test
public void buildTransactionBlob() {
// Get the nonce above getAccountNonce interface
String senderAddress = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
AccountGetNonceRequest getNonceRequest = new AccountGetNonceRequest();
getNonceRequest.setAddress(senderAddress);
AccountGetNonceResponse getNonceResponse = sdk.getAccountService().getNonce(getNonceRequest);
Long nonce;
if (getNonceResponse.getErrorCode() == 0) {
AccountGetNonceResult result = getNonceResponse.getResult();
nonce = result.getNonce();
} else {
System.out.println("error" + getNonceResponse.getErrorDesc());
return;
}

// Get the operation above buildOperation interface
String destAddress = "adxScpCtbeLP2KGRaCkbtrmz8iB5mu6DQcW3r";
Long amount = ToBaseUnit.ToUGas("10.9");
GasSendOperation operation = new GasSendOperation();
operation.setSourceAddress(senderAddress);
operation.setDestAddress(destAddress);
operation.setAmount(amount);

// Init variable
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");
// Init request
TransactionBuildBlobRequest buildBlobRequest = new TransactionBuildBlobRequest();
buildBlobRequest.setSourceAddress(senderAddress);
buildBlobRequest.setNonce(nonce + 1);
buildBlobRequest.setFeeLimit(feeLimit);
buildBlobRequest.setGasPrice(gasPrice);
buildBlobRequest.addOperation(operation);
// Build buildBlob
TransactionBuildBlobResponse buildBlobResponse = sdk.getTransactionService().buildBlob(buildBlobRequest);
if (buildBlobResponse.getErrorCode() == 0) {
TransactionBuildBlobResult result = buildBlobResponse.getResult();
System.out.println("txHash: " + result.getHash() + ", blob: " + result.getTransactionBlob());
} else {
System.out.println("error: " + buildBlobResponse.getErrorDesc());
}
}

/*
* Sign transaction
*/
@Test
public void signTransaction() {
// Get the nonce above getAccountNonce interface
String senderAddress = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
AccountGetNonceRequest getNonceRequest = new AccountGetNonceRequest();
getNonceRequest.setAddress(senderAddress);
AccountGetNonceResponse getNonceResponse = sdk.getAccountService().getNonce(getNonceRequest);
Long nonce;
if (getNonceResponse.getErrorCode() == 0) {
AccountGetNonceResult result = getNonceResponse.getResult();
nonce = result.getNonce();
} else {
System.out.println("error" + getNonceResponse.getErrorDesc());
return;
}

// Get the operation above buildOperation interface
String destAddress = "adxScpCtbeLP2KGRaCkbtrmz8iB5mu6DQcW3r";
Long amount = ToBaseUnit.ToUGas("10.9");
GasSendOperation operation = new GasSendOperation();
operation.setSourceAddress(senderAddress);
operation.setDestAddress(destAddress);
operation.setAmount(amount);

// Get the transaction blob above buildTransactionBlob interface
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");
TransactionBuildBlobRequest buildBlobRequest = new TransactionBuildBlobRequest();
buildBlobRequest.setSourceAddress(senderAddress);
buildBlobRequest.setNonce(nonce + 1);
buildBlobRequest.setFeeLimit(feeLimit);
buildBlobRequest.setGasPrice(gasPrice);
buildBlobRequest.addOperation(operation);
String transactionBlob;
TransactionBuildBlobResponse buildBlobResponse = sdk.getTransactionService().buildBlob(buildBlobRequest);
if (buildBlobResponse.getErrorCode() == 0) {
TransactionBuildBlobResult result = buildBlobResponse.getResult();
transactionBlob = result.getTransactionBlob();
} else {
System.out.println("error: " + buildBlobResponse.getErrorDesc());
return;
}

// Init request
String senderPrivateKey = "privbyQCRp7DLqKtRFCqKQJr81TurTqG6UKXMMtGAmPG3abcM9XHjWvq";
String[] signerPrivateKeyArr = {senderPrivateKey};
TransactionSignRequest signRequest = new TransactionSignRequest();
signRequest.setBlob(transactionBlob);
for (String s : signerPrivateKeyArr) {
signRequest.addPrivateKey(s);
}
// Call sign
TransactionSignResponse signResponse = sdk.getTransactionService().sign(signRequest);
if (signResponse.getErrorCode() == 0) {
TransactionSignResult result = signResponse.getResult();
System.out.println(JSON.toJSONString(result, true));
} else {
System.out.println("error: " + signResponse.getErrorDesc());
}
}

/*
* Broadcast transaction
*/
@Test
public void broadcastTransaction() {
// Get the nonce above getAccountNonce interface
String senderAddress = "adxSYvndiFG4zpbLGugX3j93fDn9nWZfWp8Gd";
AccountGetNonceRequest getNonceRequest = new AccountGetNonceRequest();
getNonceRequest.setAddress(senderAddress);
AccountGetNonceResponse getNonceResponse = sdk.getAccountService().getNonce(getNonceRequest);
Long nonce;
if (getNonceResponse.getErrorCode() == 0) {
AccountGetNonceResult result = getNonceResponse.getResult();
nonce = result.getNonce();
} else {
System.out.println("error" + getNonceResponse.getErrorDesc());
return;
}

// Get the operation above buildOperation interface
String destAddress = "adxScpCtbeLP2KGRaCkbtrmz8iB5mu6DQcW3r";
Long amount = ToBaseUnit.ToUGas("10.9");
GasSendOperation operation = new GasSendOperation();
operation.setSourceAddress(senderAddress);
operation.setDestAddress(destAddress);
operation.setAmount(amount);

// Get the transaction blob above buildTransactionBlob interface
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");
TransactionBuildBlobRequest buildBlobRequest = new TransactionBuildBlobRequest();
buildBlobRequest.setSourceAddress(senderAddress);
buildBlobRequest.setNonce(nonce + 1);
buildBlobRequest.setFeeLimit(feeLimit);
buildBlobRequest.setGasPrice(gasPrice);
buildBlobRequest.addOperation(operation);
String transactionBlob;
TransactionBuildBlobResponse buildBlobResponse = sdk.getTransactionService().buildBlob(buildBlobRequest);
if (buildBlobResponse.getErrorCode() == 0) {
TransactionBuildBlobResult result = buildBlobResponse.getResult();
transactionBlob = result.getTransactionBlob();
} else {
System.out.println("error: " + buildBlobResponse.getErrorDesc());
return;
}

// Get sign result above signTransaction interface
String senderPrivateKey = "privbyQCRp7DLqKtRFCqKQJr81TurTqG6UKXMMtGAmPG3abcM9XHjWvq";
String[] signerPrivateKeyArr = {senderPrivateKey};
TransactionSignRequest signRequest = new TransactionSignRequest();
signRequest.setBlob(transactionBlob);
for (String s : signerPrivateKeyArr) {
signRequest.addPrivateKey(s);
}
TransactionSignResult signResult;
TransactionSignResponse signResponse = sdk.getTransactionService().sign(signRequest);
if (signResponse.getErrorCode() == 0) {
signResult = signResponse.getResult();
} else {
System.out.println("error: " + signResponse.getErrorDesc());
return;
}

// Init request
TransactionSubmitRequest submitRequest = new TransactionSubmitRequest();
submitRequest.setTransactionBlob(transactionBlob);
submitRequest.setSignatures(signResult.getSignatures());
// Call submit
TransactionSubmitResponse response = sdk.getTransactionService().submit(submitRequest);
if (0 == response.getErrorCode()) {
System.out.println("Success,hash=" + response.getResult().getHash());
} else {
System.out.println("error: " + response.getErrorDesc());
}
}
}

6.6. 交易查询

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

7. 错误码

异常错误码描述
ACCOUNT_CREATE_ERROR11001Failed to create the account
INVALID_SOURCGasDDRESS_ERROR11002Invalid sourceAddress
INVALID_DESTADDRESS_ERROR11003Invalid destAddress
INVALID_INITBALANCE_ERROR11004InitBalance must be between 1 and Long.MAX_VALUE
SOURCGasDDRESS_EQUAL_DESTADDRESS_ERROR11005SourceAddress cannot be equal to destAddress
INVALID_ADDRESS_ERROR11006Invalid address
CONNECTNETWORK_ERROR11007Failed to connect to the network
INVALID_ISSUE_AMOUNT_ERROR11008Amount of the token to be issued must be between 1 and Long.MAX_VALUE
NO_ASSET_ERROR11009The account does not have the asset
NO_METADATA_ERROR11010The account does not have the metadata
INVALID_DATAKEY_ERROR11011The length of key must be between 1 and 1024
INVALID_DATAVALUE_ERROR11012The length of value must be between 0 and 256000
INVALID_DATAVERSION_ERROR11013The version must be equal to or greater than 0
INVALID_MASTERWEIGHT_ERROR11015MasterWeight must be between 0 and (Integer.MAX_VALUE * 2L + 1)
INVALID_SIGNER_ADDRESS_ERROR11016Invalid signer address
INVALID_SIGNER_WEIGHT_ERROR11017Signer weight must be between 0 and (Integer.MAX_VALUE * 2L + 1)
INVALID_TX_THRESHOLD_ERROR11018TxThreshold must be between 0 and Long.MAX_VALUE
INVALID_OPERATION_TYPE_ERROR11019Operation type must be between 1 and 100
INVALID_TYPE_THRESHOLD_ERROR11020TypeThreshold must be between 0 and Long.MAX_VALUE
INVALID_ASSET_CODE_ERROR11023The length of key must be between 1 and 64
INVALID_ASSET_AMOUNT_ERROR11024AssetAmount must be between 0 and Long.MAX_VALUE
INVALID_GAS_AMOUNT_ERROR11026GasAmount must be between 0 and Long.MAX_VALUE
INVALID_ISSUER_ADDRESS_ERROR11027Invalid issuer address
NO_SUCH_TOKEN_ERROR11030No such token
INVALID_TOKEN_NAME_ERROR11031The length of token name must be between 1 and 1024
INVALID_TOKEN_SIMBOL_ERROR11032The length of symbol must be between 1 and 1024
INVALID_TOKEN_DECIMALS_ERROR11033Decimals must be between 0 and 8
INVALID_TOKEN_TOTALSUPPLY_ERROR11034TotalSupply must be between 1 and Long.MAX_VALUE
INVALID_TOKENOWNER_ERRPR11035Invalid token owner
INVALID_CONTRACTADDRESS_ERROR11037Invalid contract address
CONTRACTADDRESS_NOT_CONTRACTACCOUNT_ERROR11038contractAddress is not a contract account
INVALID_TOKEN_AMOUNT_ERROR11039TokenAmount must be between 1 and Long.MAX_VALUE
SOURCGasDDRESS_EQUAL_CONTRACTADDRESS_ERROR11040SourceAddress cannot be equal to contractAddress
INVALID_FROMADDRESS_ERROR11041Invalid fromAddress
FROMADDRESS_EQUAL_DESTADDRESS_ERROR11042FromAddress cannot be equal to destAddress
INVALID_SPENDER_ERROR11043Invalid spender
PAYLOAD_EMPTY_ERROR11044Payload cannot be empty
INVALID_LOG_TOPIC_ERROR11045The length of a log topic must be between 1 and 128
INVALID_LOG_DATA_ERROR11046The length of one piece of log data must be between 1 and1024
INVALID_CONTRACT_TYPE_ERROR11047Invalid contract type
INVALID_NONCE_ERROR11048Nonce must be between 1 and Long.MAX_VALUE
INVALID_GASPRICE_ERROR11049GasPrice must be between 1000 and Long.MAX_VALUE
INVALID_FEELIMIT_ERROR11050FeeLimit must be between 1 and Long.MAX_VALUE
OPERATIONS_EMPTY_ERROR11051Operations cannot be empty
INVALID_CEILLEDGERSEQ_ERROR11052CeilLedgerSeq must be equal to or greater than 0
OPERATIONS_ONE_ERROR11053One of the operations cannot be resolved
INVALID_SIGNATURENUMBER_ERROR11054SignagureNumber must be between 1 and Integer.MAX_VALUE
INVALID_HASH_ERROR11055Invalid transaction hash
INVALID_BLOB_ERROR11056Invalid blob
PRIVATEKEY_NULL_ERROR11057PrivateKeys cannot be empty
PRIVATEKEY_ONE_ERROR11058One of privateKeys is invalid
SIGNDATA_NULL_ERROR11059SignData cannot be empty
INVALID_BLOCKNUMBER_ERROR11060BlockNumber must be bigger than 0
PUBLICKEY_NULL_ERROR11061PublicKey cannot be empty
URL_EMPTY_ERROR11062Url cannot be empty
CONTRACTADDRESS_CODE_BOTH_NULL_ERROR11063ContractAddress and code cannot be empty at the same time
INVALID_OPTTYPE_ERROR11064OptType must be between 0 and 2
GET_ALLOWANCE_ERROR11065Failed to get allowance
GET_TOKEN_INFO_ERROR11066Failed to get token info
SIGNATURE_EMPTY_ERROR11067The signatures cannot be empty
REQUEST_NULL_ERROR12001Request parameter cannot be null
CONNECTN_BLOCKCHAIN_ERROR19999Failed to connect to the blockchain
SYSTEM_ERROR20000System error

8. 常见问题

待收集