ETH原生交易構建,可手動設置手續費

ETH原生交易構建,可手動設置手續費

第一種交易方式(無法設置手續費)

這種方式比較簡單,不需要一大堆雜七雜八的參數,直接通過私鑰完成即可:

/**
     * 以太坊交易
     *
     * @param fromAddress 轉賬地址
     * @param password    密碼 userId
     * @param toAddress   收款方地址
     * @param amount      轉賬金額,單位:eth
     * @return 交易哈希
     * @throws Exception
     */
    public static String tx(String fromAddress, String password, String toAddress, BigDecimal amount) throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/df37be688d544933a573b47c1f0ea159"));
        String privateKey = EthService.exportPrivateKey(password, fromAddress);
        Credentials credentials = Credentials.create(privateKey);
        TransactionReceipt transactionReceipt = Transfer.sendFunds(web3j, credentials, toAddress, amount, Convert.Unit.ETHER).send();
        return transactionReceipt.getTransactionHash();
    }

//獲取私鑰  keystorePath是keystore文件所在路徑
public static String exportPrivateKey(String password, String keystorePath) throws Exception {
        Credentials credentials = WalletUtils.loadCredentials(password, keystorePath);
        BigInteger privateKey = credentials.getEcKeyPair().getPrivateKey();
        return privateKey.toString(16);
    }

第二種交易方式(可以設置手續費)

第二種方式,通過私鑰簽名的方式完成交易。需要進行手動獲取nonce,手動設置手續費等操作,相對第一種方式麻煩一些,但是執行速度更快,效率更高。第一種轉賬方式的本質,其實和第二種轉賬方式是一樣的,只不過是在底層幫我們把這些操作封裝好了。

   /**
     * 構建eth原始交易
     *
     * @return 交易hash
     */
    private String transaction(String fromAddress, String password, String toAddress, BigDecimal amount) throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/df37be688d544933a573b47c1f0ea159"));
        BigInteger nonce;
        EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(fromAddress, DefaultBlockParameterName.PENDING).send();
        if (ethGetTransactionCount == null) {
            return null;
        }
        nonce = ethGetTransactionCount.getTransactionCount();
        //設置手續費 礦工可接受範圍之內
        BigInteger gasPrice = Convert.toWei(new BigDecimal(PropertiesUtil.getProperty("eth.gasPrice", "3")),
                Convert.Unit.GWEI).toBigInteger();
        BigInteger gasLimit = new BigInteger(PropertiesUtil.getProperty("eth.gasLimit", "21000"));
        toAddress = toAddress.toLowerCase();
        BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();
        String data = "";
        byte chainId = ChainId.MAINNET; //主網id
        //獲取私鑰進行交易簽名
        String privateKey = EthService.exportPrivateKey(password, fromAddress);
        if (org.apache.commons.lang3.StringUtils.isBlank(privateKey)) {
            return null;
        }
        String signedData = signTransaction(nonce, gasPrice, gasLimit, toAddress, value, data, chainId, privateKey);
        if (signedData != null) {
            EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(signedData).send();
            String hash = ethSendTransaction.getTransactionHash();
            if (hash != null) {
                logger.info("eth交易成功,hash={}", hash);
                return hash;
            }
        }
        return null;
    }

   /**
     * eth交易簽名
     *
     * @return 簽名信息
     */
    private String signTransaction(BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, String to,
                                   BigInteger value, String data, byte chainId, String privateKey) {
        byte[] signedMessage;
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, to, value, data);
        if (privateKey.startsWith("0x")) {
            privateKey = privateKey.substring(2);
        }
        ECKeyPair ecKeyPair = ECKeyPair.create(new BigInteger(privateKey, 16));
        Credentials credentials = Credentials.create(ecKeyPair);
        if (chainId > ChainId.NONE) {
            signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials);
        } else {
            signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        }
        String hexValue = Numeric.toHexString(signedMessage);
        logger.info("eth交易簽名信息={}", hexValue);
        return hexValue;
    }
  • 說明:手續費 = gasUsed * gasPrice
    如果想要手動設置手續費,gasLimit一定要寫死21000,這是最低值,設置成了21000意味着每次gasUsed都是21000,不會改變。所以只需要修改gasPrice就相當於設置了手續費。

以上代碼複製過去就可以直接使用啦,如果對你有幫助,就點個贊吧 ^ . ^

說明:此處是通過調用infura的節點進行操作的,token可自行去官網免費獲取,兩種方式本地測試均沒有問題。也可以自己同步eth區塊,搭建rpc節點進行調用。這樣就沒有使用限制啦!

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