使用java实现以太坊并发发送交易

大家都知道使用web3j实现以太坊的功能。

查询了很多文章,对于全自动发送交易的文章少之又少,尤其是一个账户同时发送多笔交易的方式。(容易 nonce to low 的错误)

这里我简单说说我的思路。


基本知识:

  1. 以太坊发送交易需要带上nonce
  2. 如果nonce 小于已经成功发送交易的nonce那么就会交易失败
  3. 每次交易成功后,获得的nonce就会相比之前的交易nonce多1 (其实交易就是自增的)
  4. 如果nonce大于现有交易,那么当前nonce的交易会等待前面的交易完成

 

单钱包实现多笔交易同时发送:

  1.  如果是内部账户,可以使用自己维护nonce自增的方式
  2. 使用 DefaultBlockParameterName.PENDING方式 ,一般来说这种方式能获取pending 交易的nonce.从而实现交易nonce自增
String address = /* 发送交易的地址 */;
BigInteger nonce = web3j.ethGetTransactionCount(address , DefaultBlockParameterName.PENDING).send().getTransactionCount();

如果使用web3j封装的方法进行交易,你根本就不知道TxHash,而且很容易出现网络超时的错误。而且当你发送多笔交易后,你根本就不知道自己有没有给那个地址打过币。

所以自己维护TXHash是非常重要的,可以保证自己能正确的发送交易 。而且可以自己检查交易状态。

 

获取TXHash

普通以太交易获取TxHash的方式


    public EthSendTransaction ethSendTransaction(BigInteger gasPrice, Credentials credentials,String toAddress, BigInteger nonce, String hexData, BigInteger value) throws IOException {
        byte[] signedMessage = TransactionEncoder.signMessage(
                RawTransaction.createTransaction(
                        nonce,
                        gasPrice, gasLimit(),
                        toAddress,
                        value,
                        hexData == null ? "" : hexData
                ),
                credentials
        );
        String hexValue = Numeric.toHexString(signedMessage);
        EthSendTransaction transactionHash = web3j.ethSendRawTransaction(hexValue).send();
        // 交易发送失败
        // 会返回错误信息的
        // 其实web3j只是封装了以太坊的接口
        if (transactionHash.hasError()) {
            logger.error("transactionHash error -> code :{} \n  message:{} \n data:{}", transactionHash.getError().getCode(), transactionHash.getError().getMessage(), transactionHash.getError().getData());
            return null;
        }
        // 这个就是TXHash 可以通过这个查询交易状态
        String txHash = transactionHash.getTransactionHash()
        return transactionHash;
    }

代币发送方法


    protected EthSendTransaction sendErc20Transfer(Credentials credentials,String toAddress,BigInteger tokens, BigInteger gasPrice, BigInteger nonce) throws IOException {
        
        String erc20Address = /* 合约地址 */;

        // 看web3j生成的合约怎么实现的交易方法
        // 复制粘贴过来就可以了

        Function function = new Function(
                "transfer",
                Arrays.asList(new Address(toAddress), new Uint256(tokens)),
                Collections.emptyList());



        RawTransaction transaction = RawTransaction.createTransaction(
                nonce,
                gasPrice, gasLimit(),
                erc20Address ,
                BigInteger.ZERO,
                FunctionEncoder.encode(function));
        String hexValue = Numeric.toHexString(TransactionEncoder.signMessage(transaction, credentials));
        EthSendTransaction transactionHash = web3j.ethSendRawTransaction(hexValue).send();
        if (transactionHash.hasError()) {
            logger.error("transactionHash error -> code :{} \n  message:{} \n data:{}", transactionHash.getError().getCode(), transactionHash.getError().getMessage(), transactionHash.getError().getData());
            return null;
        }
        return transactionHash;
    }

检查TxHash


    protected void check(Transaction transaction) {
        
            try {
                EthGetTransactionReceipt ethGetTransactionReceipt = web3j.ethGetTransactionReceipt(transaction.getTxHash()).send();
                TransactionReceipt result = ethGetTransactionReceipt.getResult();
                if (result != null) {
                    if (result.isStatusOK()) {
                       
                        // 交易成功
                        // 可以获取到交易信息

                    } else {
                        
                        // 交易失败
                        // 错误信息
                         String errorMsg = String.format(
                                "Transaction has failed with status: %s. "
                                        + "Gas used: %d. (not-enough gas?)",
                                result.getStatus(),
                                result.getGasUsed())
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
       
    }

有了以上的这些,你就可以自己维护自己的交易。交易有无问题也可已直接上 https://etherscan.io/ 查询交易tx

分享个获取当前时间 安全gas 的api 免费接口 

https://ethgasstation.info/json/ethgasAPI.json

 

 

 

 

你可能感兴趣的:(以太坊,区块链,挖矿,web3j)