1、开始准备
1.1 学习门槛
-
熟悉Java的基本语法和使用
-
熟悉Java的IDE工具基本使用(Eclipse,IDEA)
-
熟悉Git版本管理的基本语法和使用
-
熟悉SpingBoot开发(本Demo提供的是基于Springboot的源码)
-
熟悉区块链的基本原理
-
HPB主网如何介入请前往https://www.hpb.io/client了解
1.2 环境准备
-
JDK1.8以上版本
-
Eclipse4.7或者以上
-
Eclipse安装了Git插件
-
Eclipse安装了Spring插件
-
HPB主网接入的JAVA SDK请前往这里地址下载:https://www.hpb.io/client
-
因为是maven工程,会从网络中下载工程依赖的jar宝,所以需要机器处于联网状态
1.3 源码地址
https://github.com/loglos/web3-hpb-test.git
2、开始实践
2.1 通过Eclipse Import 演示代码
-
打开Eclipse,通过菜单栏依次点击打开:File/Import/Git/Projects form Git/
-
选择通过Clone URI导入,在导入界面,输入源码的Github地址;
-
然后下一步,选择master主分支
-
然后下一步指定代码下载存放的路径
-
然后下一步,选择Import as general project
-
下一步,指定工程名称,默认是Github源码工程的名称,可以不修改,点击完成。
2.2 改变代码工程的属性
-
因为上传到Github的代码是不包括代码工程配置信息的,所以需要进行简单的调整。
-
源码工程是基于maven的类型,可以右键工程代码,选择“configure/convert to maven projects"。
-
转换成功后,系统就能识别为maven类型的工程了。
-
提醒:转换为maven工程后,很多依赖的jar包都是通过pom.xml来配置管理的,同时如果本地没安装过maven的本地仓库,第一次会默认从远程的拉取依赖jar包,速度比较慢,如果工程报错,需要多尝试几次。
2.3 源码关键配置信息说明
打开maven配置文件pom.xml
<!--
其他的配置不需要修改,这里说明下,引用的事HPB主网的JAVA版本SDK
-->
<dependency>
<groupId>io.hpb.web3</groupId>
<artifactId>web3-hpb</artifactId>
<version>1.0.0</version>
</dependency>
打开application.properties文件,配置文件可以根据需要进行修改,也可以不进行修改。 这里罗列了重要的几个配置属性进行说明。
#指定工程发布后访问名称
spring.application.name=HpbWeb3Test
#工程发布后的访问服务端口
server.port=9988
server.servlet.path=/
server.use-forward-headers=true
server.servlet.context-path=/HpbWeb3Test
server.servlet.application-display-name=hpb web3 test application
web3.admin-client=true
web3.httpTimeoutSeconds=600
#指定的连接HPB主网的RPC网址,这里是主网正式网的开放的RPC地址
#通过访问这个地址,可以进行通过Java操作RPC命令,直接和HPB主网进行交互。
web3.client-address=http://pub.node.hpb.io/
打开HpbWeb3Controller.java文件,这里是本次演示的具体代码,这里对关键代码进行下说明。
//注意这里,是引用了HPB主网提供的Java SDK包,里面封装了如何通过RPC方式与底层交互的方法
import io.hpb.web3.abi.datatypes.Address;
import io.hpb.web3.abi.datatypes.DynamicArray;
import io.hpb.web3.abi.datatypes.generated.Bytes32;
import io.hpb.web3.contract.HpbNodes;
import io.hpb.web3.crypto.Credentials;
import io.hpb.web3.crypto.RawTransaction;
import io.hpb.web3.crypto.WalletUtils;
import io.hpb.web3.protocol.admin.Admin;
import io.hpb.web3.protocol.core.DefaultBlockParameterName;
import io.hpb.web3.protocol.core.methods.response.HpbBlockNumber;
import io.hpb.web3.protocol.core.methods.response.HpbGetBalance;
import io.hpb.web3.protocol.core.methods.response.HpbGetTransactionCount;
import io.hpb.web3.protocol.core.methods.response.HpbGetTransactionReceipt;
import io.hpb.web3.protocol.core.methods.response.HpbSendTransaction;
import io.hpb.web3.protocol.core.methods.response.TransactionReceipt;
import io.hpb.web3.tuples.generated.Tuple4;
import io.hpb.web3.tx.ChainId;
import io.hpb.web3.tx.RawTransactionManager;
import io.hpb.web3.utils.Convert;
import io.hpb.web3.utils.Numeric;
import io.swagger.annotations.ApiOperation;
@RestController
@RequestMapping("/")
public class HpbWeb3Controller{
//输出日志
private static Log log = LogFactory.getLog(HpbWeb3Controller.class);
//超时时间
private final long WEB3J_TIMEOUT = 3;
//演示的HPB账号地址
private final String contractAddr = "0x7be6aa25600feed355b79b6a4e14dcdb0bd529cb";
//设置账号的余额单位为18GWEI
private final BigInteger gasPrice = Convert.toWei("18", Convert.Unit.GWEI).toBigInteger();
//设置默认的GasLimit
private final BigInteger gasLimit = new BigInteger("95000000");
@Autowired
private Admin admin;
@ApiOperation(value="通过根据交易hash查询交易收据",notes = "过根据交易hash查询交易收据"
+ " reqStrList [ 参数1:交易hash]")
@PostMapping("/QueryByHash")
public List<Object> QueryByHash(@RequestBody List<String> reqStrList)throws Exception{
List<Object> list=new ArrayList<Object>();
if(reqStrList!=null&&reqStrList.size()>0) {
String transactionHash = reqStrList.get(0);
//初始化封装的Java SDK包里的方法;通过初始化HpbGetTransactionReceipt,可以获得指定账号的交易数据
HpbGetTransactionReceipt receipt = admin.hpbGetTransactionReceipt(transactionHash).send();
if(!receipt.hasError()) {
TransactionReceipt transactionReceipt = receipt.getResult();
if(transactionReceipt.isStatusOK()) {
list.add(transactionReceipt);
}
}
}
return list;
}
@ApiOperation(value="获得当前区块号",notes = "获得当前区块号")
@PostMapping("/getCurrentBlock")
public List<Object> getCurrentBlock()throws Exception{
List<Object> list=new ArrayList<Object>();
//初始化封装的Java SDK包里的方法;通过HpbBlockNumber获取当前区块的对象内容
HpbBlockNumber blockNumber = admin.hpbBlockNumber().sendAsync().get(WEB3J_TIMEOUT, TimeUnit.MINUTES);
list.add(blockNumber);
return list;
}
@ApiOperation(value="获得当前账户的Nonce",notes = "获得当前账户的Nonce"
+ " reqStrList [ 参数1:账户地址;")
@PostMapping("/getCurrentNonce")
public List<Object> getCurrentNonce(@RequestBody List<String> reqStrList)throws Exception{
List<Object> list=new ArrayList<Object>();
if(reqStrList!=null&&reqStrList.size()>0) {
String address =reqStrList.get(0);
//初始化封装的Java SDK包里的方法;通过HpbGetTransactionCount获取当前账号Nonce
//Nonce是账户的随机数:在一个账户中的防止多重交易的用途。
HpbGetTransactionCount transactionCount = admin.hpbGetTransactionCount(address,
DefaultBlockParameterName.PENDING).sendAsync().get(WEB3J_TIMEOUT, TimeUnit.MINUTES);
BigInteger nonce = transactionCount.getTransactionCount();
log.info(nonce);
list.add(nonce);
}
return list;
}
@ApiOperation(value="获得当前账户的余额",notes = "获得当前账户的余额"
+ " reqStrList [ 参数1:账户地址; ]")
@PostMapping("/getBalance")
public List<Object> getBalance(@RequestBody List<String> reqStrList)throws Exception{
List<Object> list=new ArrayList<Object>();
if(reqStrList!=null&&reqStrList.size()>0) {
String address =reqStrList.get(0);
//初始化封装的Java SDK包里的方法;通过HpbGetBalance获取当前账号的余额。
HpbGetBalance balance = admin.hpbGetBalance(address, DefaultBlockParameterName.LATEST).send();
log.info(balance);
list.add(balance);
}
return list;
}
@ApiOperation(value="发送交易",notes = "发送交易"
+ " reqStrList [ 参数1:账户keystore地址; 参数2:密码; 参数3:接收账户地址;参数4:转账金额;]")
@PostMapping("/sendTransaction")
public List<Object> sendTransaction(@RequestBody List<String> reqStrList)throws Exception{
List<Object> list=new ArrayList<Object>();
if(reqStrList!=null&&reqStrList.size()>3) {
//获取指定账号的keystore
String keystore =reqStrList.get(0);
//获取用户输入发送交易的账号密码
String password =reqStrList.get(1);
//加载私钥对象
Credentials credentials = WalletUtils.loadCredentials(password, keystore);
//创建交易管理对象
RawTransactionManager transactionManager=new RawTransactionManager(admin, credentials, ChainId.MAINNET);
//获取nonce
HpbGetTransactionCount transactionCount = admin.hpbGetTransactionCount(credentials.getAddress(),
DefaultBlockParameterName.PENDING).sendAsync().get(WEB3J_TIMEOUT, TimeUnit.MINUTES);
BigInteger nonce = transactionCount.getTransactionCount();
//获取目标地址
String to =reqStrList.get(2);
//转账金额
String value =reqStrList.get(3);
//创建交易对象
RawTransaction rawTransaction = RawTransaction.createTransaction(
nonce,
gasPrice,
gasLimit,
to,
Convert.toWei(value, Convert.Unit.HPB).toBigInteger(),
"");
//签名并发送交易
HpbSendTransaction transaction = transactionManager.signAndSend(rawTransaction);
log.info(transaction.getTransactionHash());
list.add(transaction);
}
return list;
}
@ApiOperation(value="调用HpbNodes智能合约",notes = "调用HpbNodes智能合约"
+ " reqStrList [ 参数1:账户keystore地址; 参数2:密码]")
@PostMapping("/invokeHpbNodes")
public List<Object> invokeHpbNodes(@RequestBody List<String> reqStrList)throws Exception{
List<Object> list=new ArrayList<Object>();
if(reqStrList!=null&&reqStrList.size()>1) {
String keystore =reqStrList.get(0);
String password =reqStrList.get(1);
Credentials credentials = WalletUtils.loadCredentials(password, keystore);
RawTransactionManager transactionManager=new RawTransactionManager(admin, credentials, ChainId.MAINNET);
HpbNodes hpbNodes = HpbNodes.load(contractAddr, admin, transactionManager, gasPrice, gasLimit);
//调用智能合约
Tuple4<DynamicArray<Address>, DynamicArray<Bytes32>, DynamicArray<Bytes32>, DynamicArray<Bytes32>> send =
hpbNodes.getAllHpbNodes().send();
Bytes32 bytes32 = send.getValue2().getValue().get(1);
log.info(Numeric.toHexStringNoPrefix(bytes32.getValue()));
Bytes32 bytes321 = send.getValue3().getValue().get(1);
log.info(Numeric.toHexStringNoPrefix(bytes321.getValue()));
Bytes32 bytes322 = send.getValue3().getValue().get(1);
log.info(Numeric.toHexStringNoPrefix(bytes322.getValue()));
list.add(send);
}
return list;
}
}
2.4 运行程序和调试
2.4.1 发布程序
找到和选择好Web3HpbTestApplication类,右击”Run as /Spring Boot App" 启动成功后,系统会出现类似如下提示:
2019-01-09 10:49:18.538 HpbWeb3Test [main] INFO io.hpb.web3.Web3HpbTestApplication Caller+0 at org.springframework.boot.StartupInfoLogger.logStarting(StartupInfoLogger.java:50)
- Starting Web3HpbTestApplication on jason-hpbdeMBP with PID 46179 (/Users/hpb2017/git/web3-hpb-test/target/classes started by hpb2017 in /Users/hpb2017/git/web3-hpb-test)
2019-01-09 10:49:18.540 HpbWeb3Test [main] DEBUG io.hpb.web3.Web3HpbTestApplication Caller+0 at org.springframework.boot.StartupInfoLogger.logStarting(StartupInfoLogger.java:53)
- Running with Spring Boot v2.1.1.RELEASE, Spring v5.1.3.RELEASE
2019-01-09 10:49:18.542 HpbWeb3Test [main] INFO io.hpb.web3.Web3HpbTestApplication Caller+0 at org.springframework.boot.SpringApplication.logStartupProfileInfo(SpringApplication.java:675)
- No active profile set, falling back to default profiles: default
2019-01-09 10:49:20.818 HpbWeb3Test [main] INFO i.h.w.c.Web3AutoConfiguration Caller+0 at io.hpb.web3.configure.Web3AutoConfiguration.admin(Web3AutoConfiguration.java:51)
- Building admin service for endpoint: http://pub.node.hpb.io/
2019-01-09 10:49:21.406 HpbWeb3Test [main] INFO i.h.w.c.Web3AutoConfiguration Caller+0 at io.hpb.web3.configure.Web3AutoConfiguration.Web3(Web3AutoConfiguration.java:42)
- Building service for endpoint: http://pub.node.hpb.io/
2019-01-09 10:49:22.057 HpbWeb3Test [main] INFO io.hpb.web3.Web3HpbTestApplication Caller+0 at org.springframework.boot.StartupInfoLogger.logStarted(StartupInfoLogger.java:59)
- Started Web3HpbTestApplication in 3.943 seconds (JVM running for 5.429)
2.4.2 测试验证接口
Springboot的接口可以通过自带的swagger插件进行访问和测试。 打开本地访问地址:http://localhost:9988/HpbWeb3Test/swagger-ui.html#/ 会显示如目前系统开放的测试接口,然后选择点击“hpb-web-3-controller”,接入该接口的具体方法测试界面。 点击“/getBalance”方法,点击“Try it out”开启编辑模式,输入你要查询余额的HPB地址;然后点击“Execute”开始执行。 系统会显示执行的结果,注意这里获取的余额显示的是科学计数法。 其他的接口可以依次根据接口的内容进行测试。
关于我:蓝莲花(汪晓明),公众号:xm123798。HPB芯链(http://www.hpb.io)创始人。致力于推动区块链应用落地。
更多技术咨询 ![](https://i-blog.csdnimg.cn/blog_migrate/29270f140db23620b5a3661c2746c559.gif)
1.如果你想了解HPB钱包与中间件接口的技术文章,请访问:
注:按照CSDN的文章发布管理规范,对外部链接有一定的限制,如果您想了解更多HPB技术信息,欢迎在下方留言。