Magician-ContractsTools是一个用于调用智能合约的工具包,你可以非常容易地在Java程序中调用智能合约进行查询和写入操作。

有三个内置的标准合约模板,分别是ERC20、ERC721和ERC1155,如果你需要调用这三个合约中的标准函数,可以帮助你非常快速地完成工作。除了内置的合同模板外,如果你需要调用自定义的合同函数也是很容易的。

一、导入依赖

<dependency><groupId>com.github.yuyenews</groupId><artifactId>Magician-ContractsTools</artifactId><version>1.0.0</version></dependency><!-- This is the logging package, you must have it or the console will not see anything, any logging package that can bridge with slf4j is supported --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-jdk14</artifactId><version>1.7.12</version></dependency>

二、合约查询 以及 写入

String privateKey = ""; // 私钥Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-1-s1.binance.org:8545/")); // 链的RPC地址String contractAddress = "";EthContractUtil ethContractUtil = EthContractUtil.builder(web3j);// 查询List<Type> result = ethContractUtil.select(contractAddress, // 合约地址EthAbiCodecTool.getInputData("balanceOf", // 要调用的方法名称new Address(toAddress) // 方法的参数,如果有多个,可以继续传入下一个参数),// 要调用的方法的inputDatanew TypeReference<Uint256>() {} // 方法的返回类型,如果有多个返回值,可以继续传入下一个参数);// 往合约里写入数据// gasPrice,gasLimit 两个参数,如果想用默认值可以不传,或者传null// 如果不传的话,两个参数都必须不传,要传就一起传, 如果设置为null的话,可以一个为null,一个有值SendResultModel sendResultModel = ethContractUtil.sendRawTransaction(senderAddress, // 调用者的地址contractAddress, // 合约地址privateKey, // senderAddress的私钥new BigInteger("1200000"), // gasPrice,如果想用默认值 可以直接传null,或者不传这个参数new BigInteger("800000"), // gasLimit,如果想用默认值 可以直接传null,或者不传这个参数EthAbiCodecTool.getInputData("transfer", // 要调用的方法名称new Address(toAddress), // 方法的参数,如果有多个,可以继续传入下一个参数new Uint256(new BigInteger("1000000000000000000")) // 方法的参数,如果有多个,可以继续传入下一个参数) // 要调用的方法的inputData);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果

三、调用ERC20合约

查询

提供合约地址查询view方法,比如totalSupply总量,balanceOf余额,allowance授权等信息。

Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545"));String contractAddress = "";ERC20Contract erc20Contract = ERC20Contract.builder(web3j, contractAddress);// 调用合约的 totalSupply 函数BigInteger total = erc20Contract.totalSupply();// 调用合约的 balanceOf 函数BigInteger amount = erc20Contract.balanceOf("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84");// 调用合约的 allowance 函数BigInteger amount = erc20Contract.allowance("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", "0x552115849813d334C58f2757037F68E2963C4c5e");
写入

可以发起transfertransferFrom等函数,可自定义gasPricegasLimit等参数值。交易发起成功后可查询交易结果。

Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545"));String contractAddress = "";ERC20Contract erc20Contract = ERC20Contract.builder(web3j, contractAddress);// 调用合约的 transfer 函数SendResultModel sendResultModel = erc20Contract.transfer("0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人new BigInteger("1000000000000000000"), // 转账金额"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用合约的 transferFrom 函数SendResultModel sendResultModel = erc20Contract.transferFrom("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 转账付款人"0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人new BigInteger("1000000000000000000"), // 转账金额"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用合约的 approve 函数SendResultModel sendResultModel = erc20Contract.approve("0x552115849813d334C58f2757037F68E2963C4c5e", // 被授权人new BigInteger("1000000000000000000"), // 授权金额"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果

四、调用ERC721合约

查询
Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545"));String contractAddress = "";ERC721Contract erc721Contract = ERC721Contract.builder(web3j, contractAddress);// 调用合约的 balanceOf 函数BigInteger amount = erc20Contract.balanceOf("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84");// 调用合约的 ownerOf 函数String ownerAddress = erc721Contract.ownerOf(new BigInteger("1002"));// 调用 isApprovedForAll 函数Boolean result = erc1155Contract.isApprovedForAll("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", "0x552115849813d334C58f2757037F68E2963C4c5e");// 调用 getApproved 函数String approvedAddress = erc721Contract.getApproved(new BigInteger("1002"));
写入
Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545"));String contractAddress = "";ERC721Contract erc721Contract = ERC721Contract.builder(web3j, contractAddress);// 调用 approve 函数SendResultModel sendResultModel = erc721Contract.approve("0x552115849813d334C58f2757037F68E2963C4c5e", // 被授权人new BigInteger("1002"), // 授权的tokenId"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用合约的 transferFrom 函数SendResultModel sendResultModel = erc20Contract.transferFrom("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 转账付款人"0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人new BigInteger("1002"), // tokenId"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用合约的 safeTransferFrom 函数(没有data参数的那个)SendResultModel sendResultModel = erc20Contract.safeTransferFrom("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 转账付款人"0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人new BigInteger("1002"), // tokenId"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用合约的 safeTransferFrom 函数(有data参数的那个)SendResultModel sendResultModel = erc20Contract.safeTransferFrom("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 转账付款人"0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人new BigInteger("1002"), // tokenIdnew byte[0], // data"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用 setApprovalForAll 函数SendResultModel sendResultModel = erc1155Contract.setApprovalForAll("0x552115849813d334C58f2757037F68E2963C4c5e", // 被授权人true, // 是否授权全部"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果

五、调用ERC1155合约

查询
Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545"));String contractAddress = "";ERC1155Contract erc1155Contract = ERC1155Contract.builder(web3j, contractAddress);// 调用 balanceOf 函数BigInteger amount = erc1155Contract.balanceOf("0x552115849813d334C58f2757037F68E2963C4c5e", new BigInteger("0"));// 调用 balanceOfBatch 函数List<String> address = new ArrayList<>();address.add("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84");address.add("0x552115849813d334C58f2757037F68E2963C4c5e");List<BigInteger> tokenId = new ArrayList<>();tokenId.add(new BigInteger("0"));tokenId.add(new BigInteger("0"));List<BigInteger> amounts = erc1155Contract.balanceOfBatch(address, tokenId);// 调用 isApprovedForAll 函数Boolean result = erc1155Contract.isApprovedForAll("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", "0x552115849813d334C58f2757037F68E2963C4c5e");
写入
Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545"));String contractAddress = "";ERC1155Contract erc1155Contract = ERC1155Contract.builder(web3j, contractAddress);// 调用 setApprovalForAll 函数SendResultModel sendResultModel = erc1155Contract.setApprovalForAll("0x552115849813d334C58f2757037F68E2963C4c5e", // 被授权人true, // 是否授权全部"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用 safeTransferFrom 函数SendResultModel sendResultModel = erc1155Contract.safeTransferFrom("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 转账付款人"0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人new BigInteger("1002"), // tokenIdnew BigInteger("1"), // 数量new byte[0], // data"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果// 调用 safeBatchTransferFrom 函数List<BigInteger> tokenIds = new ArrayList<>();tokenIds.add(new BigInteger("1002"));tokenIds.add(new BigInteger("1003"));List<BigInteger> amounts = new ArrayList<>();amounts.add(new BigInteger("1"));amounts.add(new BigInteger("10"));SendResultModel sendResultModel = erc1155Contract.safeBatchTransferFrom("0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 转账付款人"0x552115849813d334C58f2757037F68E2963C4c5e", // 转账接收人tokenIds, // tokenId 集合amounts, // 数量 集合new byte[0], // data"0xb4e32492E9725c3215F1662Cf28Db1862ed1EE84", // 调用者的地址"", // 调用者的私钥null, // gasPrice,如果传null,自动使用默认值null // gasLimit,如果传null,自动使用默认值);sendResultModel.getEthSendTransaction(); // 发送交易后的结果sendResultModel.getEthGetTransactionReceipt(); // 交易成功上链后的结果

六、InputData 编解码

// 编码String inputData = EthAbiCodecTool.getInputData("transfer", // 方法名new Address(toAddress), // 参数1new Uint256(new BigInteger("1000000000000000000")) // 参数2,如果还有其他参数,可以继续传入下一个);// 解码List<Type> result = EthAbiCodecTool.decoderInputData("0x" + inputData.substring(10), // 去除方法签名的inputDatanew TypeReference<Address>() {}, // 被编码的方法的参数1 类型new TypeReference<Uint256>() {} // 被编码的方法的参数2 类型, 如果还有其他参数,可以继续传入下一个);for(Type type : result){System.out.println(type.getValue());}// 获取方法签名,其实就是inputData的前十位String functionCode = EthAbiCodecTool.getFunAbiCode("transfer", // 方法名new Address(toAddress), // 参数1,值随意传,反正我们要的方法签名,不是完整的inputDatanew Uint256(new BigInteger("1000000000000000000")) // 参数2,值随意传,反正我们要的方法签名,不是完整的inputData,如果还有其他参数,可以继续传入下一个);

七、主链币查询以及转账

提供地址的私钥可以完成对该钱包的余额查询和发起转账等操作。

String privateKey = ""; // 私钥Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-1-s1.binance.org:8545/")); // 链的RPC地址// 这种方式是单例的EthHelper ethHelper =MagicianWeb3.getEthBuilder().getEth(web3j);// 如果你想创建多个EthHelper对象,可以用这种方式EthHelper ethHelper = EthHelper.builder(web3j);// 余额查询BigInteger balance = ethHelper.balanceOf(fromAddress);// 转账TransactionReceipt transactionReceipt = ethHelper.transfer(toAddress,privateKey, BigDecimal.valueOf(1),Convert.Unit.ETHER);