使用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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章