EVM
接口使用流程示例
说明:为了更好的理解接口的使用,本示例将从创建账户、编译合约、部署合约、调用合约和返回值解析这个大致流程作介绍。
创建账户
首先初始化HyperchainAPI
例如:
HyperchainAPI hyperchain = new HyperchainAPI();
空参构造方式直接使用默认配置文件内容。
创建账户可创建国密、非国密类型账户,返回账户公私钥json字符串,然后使用Account类型封装参数。
例如:
String accountJson = HyperchainAPI.newAccountRawSM2();
Account account = new Account(accountJson);
编译合约
创建合约文件,合约可分为Solidity和Java合约两种.
首先编写合约文件,使用Utils的readFile(String path)读入合约文件内容,可上传编译合约,但是推荐在本地编译好合约后在部署。
远程编译获取编译结果:
String contract = Utils.readFile("/Users/Desktop/Accumulator.sol");
CompileReturn compile = hyperchain.compileContract(contract);
然后获取合约的bin和abi,本地编译Solidity合约也需获得bin和abi(本地编译需要solc编译器,可以使用npm install -g solc安装)。
List<String> listBin = compile.getBin();
List<String> listAbi = compile.getAbi();
//获取bin
String bin = listBin.get(0);
//获取abi
String abi =listAbi.get(0);
Java合约则在本地编译,然后使用Utils的getTargetBinFromPath(String path) 将编译后的Java合约转为bin。
部署合约
根据合约的构造函数是否有参数,实例化合约部署使用不同的方法。对于有参数的构造函数,使用FuncParamReal将构造参数封装,在根据合约构造参数有无调用不同的实例化合约部署方法。
例如:
Transcation transaction = new Transaction(account.getAddress(), bin, false, funcParamReal,VMType.EVM);
//签名
transaction.signWithSM2(accountJson, "");
其中VMType默认使用EVM,若为Java合约,则需显式声明使用JVM。实例化部署后,使用
ReceiptReturn receiptReturn = hyperchain.deployContract(transaction);
部署合约。
部署完成后可查看部署结果:
//部署合约交易哈希
String txHash = receiptReturn.getTxHash();
int code = receiptReturn.getCode();
//合约地址
String contractAddress = receiptReturn.getContractAddress();
调用合约
调用合约需要封装方法名和参数,Solodity合约使用FunctionEncode
的static encodeFunction(String functionName, FuncParamReal... funcParams)
封装,Java合约使用FunctionEncode
的static encodeFunctionJava(String functionName, String... funcParams)
封装,返回编码后的String,在实例化调用合约交易,之后调用合约方法,获得hash。
例如:
FuncParamReal param1 = new FuncParamReal("uint32", new BigInteger("3"));
FuncParamReal param2 = new FuncParamReal("uint32", new BigInteger("2"));
//参数封装
String payloadWithParmas = FunctionEncode.encodeFunction("add", param1, param2);
Transaction transactionWithParmas = new Transaction(account.getAddress(), contractAddress, payloadWithParmas, false, VMType.EVM);
transactionWithParmas.signWithSM2(accountJson, "");
//调用
ReceiptReturn receiptReturn = hyperchain.invokeContract(transactionWithParmas);
返回值解析
得到返回值结果后,获得状态码可以判断是否调用成功,若调用成功,解析返回值可看到调用之后的结果。
例如:
if (!receiptReturn.isSuccess()) {
//error
}
//状态码
code = receiptReturnWithParams.getCode();
//未解码结果
String rawReturnWithParams = receiptReturn.getRet();
//解码
String decodedResultWithParams = FunctionDecode.resultDecode("add", abi, rawReturnWithParams);
完整示例(Solidity合约)
/**
* 一个简单的完整流程测试Demo - 合约构造函数无入参(创建账户、编译合约、部署合约、调用合约、返回值解析)
*/
//模拟日志打印
private void log(String s) {
System.out.println("HyperchainAPITest ====== " + s);
}
HyperchainAPI hyperchain = new HyperchainAPI();
//创建账户
String accountJson = HyperchainAPI.newAccountRawSM2();
Account account = new Account(accountJson);
log("创建账户 accountJson :" + accountJson);
//读取合约
String contract = Utils.readFile("solidity.source/Accumulator.sol");
//编译合约
CompileReturn compile = hyperchain.compileContract(contract);
List<String> listBin = compile.getBin();
log("listBin :" + listBin);
List<String> listAbi = compile.getAbi();
log("listAbi :" + listAbi);
//获取bin
String bin = listBin.get(0);
log("bin :" + bin);
//获取abi
String abi = listAbi.get(0);
log("abi :" + abi);
//封装交易
Transaction transaction = new Transaction(account.getAddress(), bin, false);
//签名
transaction.signWithSM2(accountJson, "");
//部署合约
ReceiptReturn receiptReturn = hyperchain.deployContract(transaction);
//查询部署结果
int code = receiptReturn.getRawcode();
log("部署结果:" + code);
String contractAddress = receiptReturn.getContractAddress();
log("合约地址:" + contractAddress);
//调用合约(有参数):计算 3 + 2
FuncParamReal param1 = new FuncParamReal("uint32", new BigInteger("3"));
FuncParamReal param2 = new FuncParamReal("uint32", new BigInteger("2"));
//方法编码
String payloadWithParams = FunctionEncode.encodeFunction("add", param1, param2);
//实例化调用合约
Transaction transactionWithParmas = new Transaction(account.getAddress(), contractAddress, payloadWithParams, false);
transactionWithParmas.signWithSM2(accountJson, "");
//同步调用合约
ReceiptReturn receiptReturnWithParams = hyperchain.invokeContract(transactionWithParmas);
//获取与解析返回值
String rawReturnWithParams;
if (!receiptReturnWithParams.isSuccess()) {
log("合约方法调用失败,code:" + receiptReturn.getCode());
}
code = receiptReturnWithParams.getRawcode();
log("调用合约结果状态:" + code);
rawReturnWithParams = receiptReturnWithParams.getRet();
log("调用合约结果(未解码):" + rawReturnWithParams);
String decodedResultWithParams = FunctionDecode.resultDecode("add", abi, rawReturnWithParams);
log("调用合约结果(解码后)" + decodedResultWithParams);
//调用合约(无参数):查看返回值
String payloadWithoutParams = FunctionEncode.encodeFunction("getSum");
Transaction transaction1 = new Transaction(account.getAddress(), contractAddress, payloadWithoutParams, false);
transaction1.signWithSM2(accountJson, "");
ReceiptReturn receiptReturnWithoutParams = hyperchain.invokeContract(transaction1);
String rawReturnWithoutParams = receiptReturnWithoutParams.getRet();
log("调用合约结果(未解码):" + rawReturnWithoutParams);
String decodedResult = FunctionDecode.resultDecode("getSum", abi, rawReturnWithoutParams);
log("调用合约结果(解码后)" + decodedResult);
完整示例(Java合约)
/**
* 一个简单的完整流程测试Demo - 合约构造函数无入参(创建账户、编译合约、部署合约、调用合约、返回值解析)
*/
//模拟日志打印
private void log(String s) {
System.out.println("HyperchainAPITest ====== " + s);
}
HyperchainAPI hyperchain = new HyperchainAPI();
//创建账户
String accountJson = HyperchainAPI.newAccountRawSM2();
Account account = new Account(accountJson);
log("创建账户 accountJson :" + accountJson);
//编译合约(本地编译)
String homePath = System.getenv("HOME");
String sdkPath = homePath + "/.m2/repository";
String sourceDir = "src/test/resources/javaContractExample/source1";
String destDir = "src/test/resources/javaContractExample/contract01";
String contractPath = HyperchainAPI.compileContractJava(sdkPath, sourceDir, destDir);
log("合约编译输出路径 contractPath : " + contractPath);
//编译成功后,在编译路径,即destDir下,创建contract.properties文件,在文件//中输入两个配置,分别为contract.name和main.class,其中contract.name配置//为你创建的合约名称,main.class配置为合约主类的全类名。
//例如:
//contract.name=AccountSum
//main.class=cn.hyperchain.jcee.contract.examples.sb.src.AccountSum
//部署Java合约
String target = Utils.getTargetBinFromPath("javaContractExample/contract01");
Transaction transaction = new Transaction(account.getAddress(), target, false, VMType.JVM);
transaction.signWithSM2(accountJson, "");
ReceiptReturn receiptReturn = hyperchain.deployContract(transaction);
//查询部署结果
int code = receiptReturn.getRawcode();
log("部署结果:" + code);
String contractAddress = receiptReturn.getContractAddress();
log("合约地址:" + contractAddress);
//调用合约
String input = FunctionEncode.encodeFunctionJava("invoke", "issue", "a", "100");
Transaction transaction2 = new Transaction(account.getAddress(), contractAddress, input, false, VMType.JVM);
transaction2.signWithSM2(accountJson, "");
ReceiptReturn invokeReceipt = hyperchain.invokeContract(transaction2);
if (! invokeReceipt.isSuccess()) {
log("调用错误");
}
log("调用状态 code : " + invokeReceipt.getRawcode());
log("调用结果 " + invokeReceipt.getRet());