使用示例
下文将以LiteSDK为例,教您如何使用Hyperchain构建一个区块链应用demo。
准备工作
Java环境
如果您还没有搭建本地Java环境,请先下载安装JDK:下载,选择适合您平台的版本。
Java IDE
如果您还没有合适的Java IDE,请先下载安装,如IntelliJ IDEA:下载
创建项目
如果您已经完成了准备工作,Java开发环境配置完毕,则开始创建项目。
1. 新建一个Maven项目
此处以groupId
和artifactId
是demo
为例。
2. 获取依赖
查看LiteSDK最新版本jar包:地址
在项目中添加相关的依赖:
Maven
Gradle
STB
grape
Ivy
<dependency> <groupId>cn.hyperchain</groupId> <artifactId>litesdk</artifactId> <version>1.0.0</version></dependency
// https://mvnrepository.com/artifact/cn.hyperchain/litesdkcompile group: 'cn.hyperchain', name: 'litesdk', version: '1.0.0'
// https://mvnrepository.com/artifact/cn.hyperchain/litesdklibraryDependencies += "cn.hyperchain" % "litesdk" % "1.0.0"
// https://mvnrepository.com/artifact/cn.hyperchain/litesdk@Grapes( @Grab(group='cn.hyperchain', module='litesdk', version='1.0.0'))
<dependency org="cn.hyperchain" name="litesdk" rev="1.0.0"/>
完成以上步骤即可得到LiteSDK进行使用。
3. 将certs文件夹添加到项目src/main/resources
中,供后续使用。
编写合约
平台目前支持使用Java语言进行智能合约的开发,此处以HVM为例。
下面是一个模拟银行的智能合约。本例中申明了银行相关的属性银行名bankName, 银行编号bankNum以及银行状态字段isInvalid等。除此之外,合约中还存储了一个adrress字段修饰的合约所有者地址,该地址用户判别合约调用者和合约的关系,理论上可以限制只有合约调用者才能够进行合约函数的编写。
//合约主体类SBank.java
public class SBank extends BaseContract implements ISBank {
//注解标记数据持久化
@StoreField
public HyperMap<String, Integer> accounts = new HyperMap<String, Integer>();
public SBank() {
}
@Override
public void onInit() {
this.accounts.put("AAA", 1000000000);
this.accounts.put("BBB", 1000000000);
this.accounts.put("CCC", 1000000000);
this.accounts.put("DDD", 1000000000);
}
@Override
public boolean transfer(String from, String to, int value) {
int fromBalance = this.accounts.get(from);
int toBalance;
if (!this.accounts.containsKey(from) || fromBalance < value) {
return false;
}
// if to account not exist, create
if (!this.accounts.containsKey(to)) {
toBalance = 0;
} else {
toBalance = this.accounts.get(to);
}
// do transaction
this.accounts.put(from, fromBalance - value);
this.accounts.put(to, toBalance + value);
return true;
}
@Override
public boolean deposit(String from, int value) {
// if to account not exist, create
if (!this.accounts.containsKey(from)) {
this.accounts.put(from, 0);
}
this.accounts.put(from, this.accounts.get(from) + value);
return true;
}
}
//ISBank.java
public interface ISBank extends BaseContractInterface {
boolean transfer(String from, String to, int val);
boolean deposit(String from, int val);
}
//invoke bean: InvokeBank.java
public class InvokeBank implements BaseInvoke<Boolean, ISBank> {
public String from;
public String to;
public int value;
// 必须有一个无参默认构造方法
public InvokeBank() {
}
public InvokeBank(String from, String to, int value) {
this.from = from;
this.to = to;
this.value = value;
}
@Override
public Boolean invoke(ISBank obj) {
boolean a = obj.transfer(from, to, value);
return a;
}
}
本例使用了一个map的结构进行用户及其资产的映射关系的维护,deposit函数实现了用户存款的业务,transfer实现了简单的用户之间的资产转账的业务。至此模拟银行合约的编写结束,接下来继续阐述如何对该合约进行编译、部署和调用。
先将合约SBank.java、ISBank.java打成一个jar包,在pom.xml文件中需配置Main-Class为SBank.java(合约主体类),打好的jar包放到resources文件夹中(也可放入其他路径)。
部署调用合约
下面是利用 LiteSDK 进行 SBank 部署、调用的例子:
public class TestSBank {
//合约jar包路径
String jarPath = "/Users/dong/IdeaProjects/hyperchain/contractRes/hvm-bench-test/hypermap/target/sbank.jar";
String defaultURL = "localhost:8081";
@Test
public void testSBank() throws Exception {
InputStream is = FileUtil.readFileAsStream(jarPath);
DefaultHttpProvider defaultHttpProvider = new DefaultHttpProvider.Builder().setUrl(defaultURL).build();
ProviderManager providerManager = ProviderManager.createManager(defaultHttpProvider);
ContractService contractService = ServiceManager.getContractService(providerManager);
AccountService accountService = ServiceManager.getAccountService(providerManager);
Account account = accountService.genAccount(Algo.ECRAW);
//部署合约
Transaction transaction = new Transaction.HVMBuilder(account.getAddress()).deploy(is).build();
transaction.sign(account);
ReceiptResponse receiptResponse = contractService.deploy(transaction).send().polling();
//获取合约地址
String contractAddress = receiptResponse.getContractAddress();
System.out.println("contract address: " + contractAddress);
//调用合约
Transaction transaction1 = new
//创建指定invoke bean的交易
Transaction.HVMBuilder(account.getAddress()).invoke(contractAddress, new InvokeBank("AAA", "BBB", 100)).build();
transaction1.sign(account);
ReceiptResponse receiptResponse1 = contractService.invoke(transaction1).send().polling();
//对交易执行结果进行解码
String decodeHVM = Decoder.decodeHVM(receiptResponse1.getRet(), String.class);
System.out.println("decode: " + decodeHVM);
}
如上所示,首先需要实例化一个HttpProvider的实例,然后创建账户,接着使用该实例去进行合约部署和调用。交易发送之后只能返回一个交易哈希,需要通过该哈希去查询交易的结果,如部署合约中的拿到的交易回执中的合约地址。合约地址和invoke bean是调用合约的一个必须选项。在进行方法调用之前首先需要将需要调用的invoke bean进行编码。
在本例中,执行的实际合约如下:
- 部署合约:在部署过程中创建了AAA、BBB、CCC、DDD四个账户,分别设置余额1000000000
- 调用合约:AAA账户向BBB账户中转入100,并返回成功或失败的状态