前言:感谢conflux开发群大佬,尤其是 孤独的开发者-acuilab,宇智波斑,pana ,曹宏宇等几位大佬的耐心交流。
本教程是用java-conflux-jdk 在conflux区块链进行智能合约的设计,部署,参数获取,交互等的教程,如果你已经熟悉了solidity智能合约,看完本文,可以让java后端与conflux区块链自由交互、添加智能合约、与智能合约交互、存储包括合约地址等区块链参数的完整一套行为了。
废话不多说:
chorme浏览器先下一个conflux protal钱包,然后创建有个账户有点CFX代币,testnet的也行,不然有的地方会报错或没参数写,听不懂执行就对了,看这里:https://www.bilibili.com/video/av541737286/
另外,即使是Dapp也一般需要一个服务器,nodejs+JavaScript开发的话,向用户发送前端用户数据即可上链,去中心化程度更高;java开发的话上链操作也是后台在做,去中心化程度降低,主要胜在java后端的应用相对比其他语言更普遍。所以用java还是js是很大的区别,建议先考虑清楚
先下载依赖包,建议用maven项目,在pom的dependencies中加入conflux包的引用
引用地址如下:
https://search.maven.org/search?q=conflux
点击版本号,跳转页面如下
https://search.maven.org/artifact/io.github.conflux-chain/conflux.web3j/1.0.4/jar
页面右侧Apache Maven框中代码复制进自己spring boot项目 pom的dependencies中刷新即可调用conflux包的引用
要发布合约当然要先写好合约,这里推荐conflux studio,测试地址测试币获取到编译合约生成字节码乃至字节码上链成合约一条龙,下载连接如下,注意一定下最新版,老版本bug太多(貌似新老都要先安装docker):
https://github.com/ObsidianLabs/ConfluxStudio/releases
然后不会的建议看下简单案例教程:
https://juejin.cn/post/6862234416941858830
这里的例子是js-conflux-sdk写DAPP的教程,不是java的,但是没关系,我看前一部分,即智能合约的编写和编译。
首先要用conflux studio编译(用remix编译其实一个道理,但是对新手studio感觉友好一点),就是左上角的锤子
编译过后会出现build-contracts中的json文件
ctrl+f搜索字段“bytecode”
一大串bytecode就是编译后的合约(别问deployedbytecode是啥,我也不知道)
然后打开你的java项目(我这里是springboot的test文件做测试)复制bytecode作为java调用的参数
直接上我的实际的java代码:
@Test
public void try_new_contract() throws Exception{
String privateKey = "0x0e3f7f3219dd154e1b4887123ccb8472ef35341cb3c1f86d08c42b43117d776d";
Cfx cfx = Cfx.create("https://test.confluxrpc.org/v2", 3, 1000);
Account account = Account.create(cfx, privateKey);
Account.Option opt = new Account.Option();
// opt要设置用户参数的id!!不然报错chainIdMismatch
opt.withChainId(1);
String smart_contract_file = "0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061083a806100606000396000f3fe6080604052600436106100555760003560e01c8063075461721461005a57806315a9b727146100b157806340c10f19146100f557806370a08231146101505780638735cc70146101b5578063d0679d34146101f9575b600080fd5b34801561006657600080fd5b5061006f610254565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100f3600480360360208110156100c757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610279565b005b34801561010157600080fd5b5061014e6004803603604081101561011857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506103ba565b005b34801561015c57600080fd5b5061019f6004803603602081101561017357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610489565b6040518082815260200191505060405180910390f35b6101f7600480360360208110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104d2565b005b34801561020557600080fd5b506102526004803603604081101561021c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610613565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060016040519080825280602002602001820160405280156102ab5781602001602082028038833980820191505090505b50905081816000815181106102bc57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073088800000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff166310128d3e826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561037957808201518184015260208101905061035e565b5050505090500192505050600060405180830381600087803b15801561039e57600080fd5b505af11580156103b2573d6000803e3d6000fd5b505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461041357600080fd5b789f4f2726179a224501d762422c946590d91000000000000000811061043857600080fd5b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060016040519080825280602002602001820160405280156105045781602001602082028038833980820191505090505b509050818160008151811061051557fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073088800000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff1663d2932db6826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b838110156105d25780820151818401526020810190506105b7565b5050505090500192505050600060405180830381600087803b1580156105f757600080fd5b505af115801561060b573d6000803e3d6000fd5b505050505050565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548111156106c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f496e73756666696369656e742062616c616e63652e000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507f3990db2d31862302a685e8086b5755072a6e2b5b780af1ee81ece35ee3cd3345338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505056fea265627a7a7231582020957a5d4d460f692efeb5b3f0a5813bb78842f7a7f7a437397f82f8546a82ab64736f6c63430005100032";
String deploye_hash = account.deploy(opt,smart_contract_file);
System.out.println(deploye_hash);
}
注意:
1)发布合约的私钥对应区块链账户有代币(测试网络也要免费先获取测试币)
2)创建cfx对象(理解为socket对象)注意连接的网络,这里是测试网
3)必须account option对象写入参数chainid!!!否则报错,哪怕其实参数已经再cfx对象写了,重写一遍
4)合约就是那串乱码,即图中“smart_contract_file”
5)返回位交易哈希,不是发布的合约地址
可能新手不知道rpc是啥
简单的说,可以下载curl,普通的网页请求返回一个网页,curl进行远程程序控制(rpc)解析你的请求,返回一个json字段,包含你要的信息。
举个例子,我们刚刚发布了合约,收到了合约布置哈希,但是我们不知道新的合约地址啊!!在和用java与合约交互的时候就没有定位,程序不知道和那个合约交互。
翻了两天源码,应该是有函数可以直接请求的(有函数痕迹),但是无奈没找到合适函数。于是用rpc获取。
https://developer.conflux-chain.org/docs/conflux-doc/docs/json_rpc/#cfx_gettransactionbyhash
我们想要的,看到一个函数“cfx_getTransactionByHash”
另外,注意curl访问地址和参数
访问rpc的url见下方网址:
https://github.com/conflux-fans/conflux-rpc-endpoints
访问端口见下方网址:
https://developer.conflux-chain.org/docs/conflux-doc/docs/json_rpc/#cfx_gettransactionbyhash
就是用简单方式尝试看这个接口是否可以访问。
下载curl请求器后,打开cmd,以我发布过的合约为例:
linux内核系统curl访问语句:
curl -X POST --data '{"jsonrpc":"2.0","method":"cfx_getTransactionByHash","params":["0xefcdb73434576d64aa5482632f2cc4a862ab831c872f30582f5c2ca8ee95207e"],"id":1}' -H "Content-Type: application/json" https://test.confluxrpc.org/v2:12537
windows要加转义字符,不然报错:
curl -X POST --data “{\"jsonrpc\":\"2.0\",\"method\":\"cfx_getTransactionByHash\",\"params\":[\"0xefcdb73434576d64aa5482632f2cc4a862ab831c872f30582f5c2ca8ee95207e\"],\"id\":1}" -H "Content-Type: application/json" https://test.confluxrpc.org/v2:12537
返回
{"blockHash":"0x1dada5a8d1afd0190dd27ac1c8441a7a42cc531f4acbc6e007268ba3038efc85","chainId":"0x1","contractCreated":"CFXTEST:TYPE.CONTRACT:ACCXFUN724PN2V46AUDTE3156P1DREP5VUTE8UZKGG","data":"合约字节码","epochHeight":"0x1469aef","from":"CFXTEST:TYPE.USER:AATN4YSG9NFE92FT1SVE2J84XN2M6EBJBYU075M5RG","gas":"0xc4e06","gasPrice":"0x1","hash":"0xefcdb73434576d64aa5482632f2cc4a862ab831c872f30582f5c2ca8ee95207e","nonce":"0x19","r":"0x522ab0f8a1be3cf99e2fad5822488fdd9cad72b7f562dcd98ad1d6badd1b224d","s":"0x168284eab39988614619c667b57528e1e024c1ac367ae647f6ecdaffd6ae6e42","status":"0x0","storageLimit":"0xc80","to":null,"transactionIndex":"0x0","v":"0x0","value":"0x0"}
可以看到确实返回了我们需要的合约地址“contractCreated:CFXTEST:TYPE.CONTRACT:ACCXFUN724PN2V46AUDTE3156P1DREP5VUTE8UZKGG”
这里我们使用okhttp3进行rpc请求,因为貌似有传言httpClient要被劝退了(?)
pom写入引用
<dependency>
<groupId>com.squareup.okhttp3groupId>
<artifactId>okhttpartifactId>
<version>4.9.1version>
dependency>
java代码(springboot 的测试文件测试):
@Test
public void try_okhttp_conflux() throws IOException {
// 请求体请求参数
String url = "https://test.confluxrpc.org/v2:12537";
String json ="{\"jsonrpc\":\"2.0\",\"method\":\"cfx_getTransactionByHash\",\"params\":[\"0xefcdb73434576d64aa5482632f2cc4a862ab831c872f30582f5c2ca8ee95207e\"],\"id\":1}";
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), json);
//请求
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
final Call call = client.newCall(request);
Response response = call.execute();
返回responce转为string,解析返回json string
String obj = response.body().string();
System.out.println(obj);
// 从返回json string中获取参数
JSONObject object_res=JSONObject.fromObject(obj);
System.out.println(object_res.getString("result"));
System.out.println(object_res.getJSONObject("result").getString("contractCreated"));
现在编写-布置了智能合约,那怎么交互呢?怎么调用合约函数呢?
如下网站有JDK开发者贴出的使用代码,可以在boot项目test中看情况复制以实验
https://github.com/Conflux-Chain/java-conflux-sdk
文档中的示范代码有些未说明的细节或小错误,包括:
1)测试-查看现有epoch中url参数错误,可能报错RPC链接错误,下文链接有很多url,对应不同网络,一般建议学习用test先
https://github.com/conflux-fans/conflux-rpc-endpoints
我用的链接:https://test.confluxrpc.org/v2
2)有些类不知道在哪里,介绍也比较模糊,建议IDE直接ctrl+方法or类名,比如 RawTransaction类,ctrl+调用其的test_addtrss ,看到函数原型,再点参数就可看到类原型
3)有个参数是“password”,这个 AccountManager.import(privateKey, password);需要密码,这里是 chorme钱包插件的开启密码
下方实验是用spring boot的测试,class挂上@component放入容器,函数挂上@test
// 出钱人
public static String confluxWalletAddress = "0x1d23e8060f646bad1b4bb9125a5d1e71f56cb32f";
@Test
void ConfluxBase_and_Transact() throws Exception {
// 确定基础参数 公钥私钥和密码,密码不能乱写!必须是浏览器conflux钱包插件的密码!!
int testNetId = 1;
// 出钱人私钥
String privateKey = "0x2e0d3e928841568bcfcc2eaa5bf2424321abe3ae6ac2bdfea6786b659e2e5d51";
String password = "c45521669";
// 出钱人公钥
String publickKey = "0x1d23e8060f646bad1b4bb9125a5d1e71f56cb32f";
// Address 封装的对象可以用 getABIAddress()获取被封装账号的公钥地址
Address test_address = new Address(publickKey, testNetId);
// initialize an accountManager
Cfx cfx = Cfx.create("http://testnet.cfxchain.xyz:12537/rpc/ ", 3, 1000);
AccountManager am = new AccountManager(testNetId);
// import private key
am.imports(privateKey, password);
// 整合一个账户信息,是条链,插件密码和公私钥
Account account = Account.unlock(cfx,am,test_address,password);
// 还有一种封印的account函数,详见上文jdk链接
// 尝试发送部分代币
// 1.建立交易信息 2.私钥签名 3.发送给本地或公用节点
// 交易值,前面10进制字符串,单位为drip!!=10^-18 个cfx
BigInteger value = new BigInteger("1000000", 10);
// 创建交易,参数发送者地址
TransactionBuilder txBuilder = new TransactionBuilder(test_address);
// 参数--链号!!容易遗忘,报bug:chainIdMissed
txBuilder.withChainId(testNetId);
// 参数 接收地址和链号
Address receiverAddress = new Address("0x173329e2a911b3849bf41e65c807ceaefa2b11d1",testNetId);
// 设置接收者的地址
txBuilder.withTo(receiverAddress);
// 交易值确认,类型为biginteger
txBuilder.withValue(value);
// 根据之前的交易信息实例化交易
RawTransaction rawTx = txBuilder.build(cfx);
// // 交易上传区块链,完成流程,收到确认区块地址哈希
//这种上传包括加密签名和发送
// SendTransactionResult result = account.send(rawTx);
// System.out.println(result.getTxHash());
// 也可以分开,先加密签名,再传送
String hexEncodedTx = account.sign(rawTx);
String txHash = cfx.sendRawTransaction(hexEncodedTx).sendAndGet();
System.out.println(txHash);
System.out.println("###############################");
}
不需要个人地址
@Test
void Call_contract_methods(){
// 建立链接
Cfx cfx = Cfx.create("https://testnet-rpc.conflux-chain.org.cn/v2",3, 1000);
// 建立合约链接对象!!地址0x8开头
ContractCall contract = new ContractCall(cfx, new Address("0x8284e5a2087628d3a278d2336cdc883d2a98b032", 1));
// passing method name and parameter to `contract.call`
// note: parameters should use web3j.abi.datatypes type
// 这里参数又几个要注意的地方
// 1.有的view函数没有参数需要输入,如下即可实现合约调用返回值
// call第一个参数是合约写的方法名,区分大小写,这里是显示合约布置者的函数,没有上传参数
String amount = contract.call("minter").sendAndGet();
System.out.print("contract minter: ");
System.out.println(amount);
// 2.有参数的view,这里函数balanceOf是指定用户信息查询余额函数,第二个或后面对应参数加上即可
// 所有参数参考 conflux.web3j.abi.datatypes,不建议java自带格式
// String amount = contract.call("balanceOf", new Address("0x1d23e8060f646bad1b4bb9125a5d1e71f56cb32f", 1).getABIAddress()).sendAndGet();
// BigInteger balance = DecodeUtil.decode(amount, Uint256.class);
// System.out.print("account balance: ");
// System.out.println(balance);
}
需要发动者个人私钥公钥
@Test
void Update_Contract_state() throws Exception {
// 调用者私钥
String privateKey = "0x2e0d3e928841568bcfcc2eaa5bf2424321abe3ae6ac2bdfea6786b659e2e5d51";
int netId = 1;
// 合约地址
Address contractAddress = new Address("0x8284e5a2087628d3a278d2336cdc883d2a98b032", netId);
// 调用者地址
Address recipient = new Address("0x1d23e8060f646bad1b4bb9125a5d1e71f56cb32f", netId);
Cfx cfx = Cfx.create("https://testnet-rpc.conflux-chain.org.cn/v2", 3, 1000);
// create account, then call contract's method
// 链接+私钥=调用者账户
Account account = Account.create(cfx, privateKey);
// 估计这里写入各种字段,以次调用多种方法
// 可以查看原型,发现可以定义update交易的gas
// build transaction option info: nonce, gas, gasPrice and etc
Account.Option opt = new Account.Option();
// opt要设置用户参数的id!!不然报错chainIdMismatch
opt.withChainId(1);
BigInteger amount = BigInteger.valueOf(100);
// 这里合约方法是给指定对象印发 amount 量的代币
// 第三个参数是合约方法名,其后是合约方法参数,有几个,是啥看自己的合约
String txHash = account.call(opt, contractAddress,
"mint", recipient.getABIAddress(), new Uint256(amount));
// 返回64位开头0x8的哈希交易地址
// 具体内容可以在 https://testnet.confluxscan.io/ 输入返回哈希搜到
System.out.println("tx hash: " + txHash);
}
以上,有问题加我qq,qq见csdn名
“may the flame guide thee”
“long may the sun shine!”