以太坊web3j开发常用代码片段整理

2021-08-09 16:35:22

获取账户的Nonce

public static BigInteger getNonce(Web3j web3j, String addr) {
 try {
     EthGetTransactionCount getNonce = web3j.ethGetTransactionCount(addr,DefaultBlockParameterName.PENDING).send();
      if (getNonce == null){
                throw new RuntimeException("net error");
            }
            return getNonce.getTransactionCount();
        } catch (IOException e) {
            throw new RuntimeException("net error");
        }
    }

获取ETH余额

public static BigDecimal getBalance(Web3j web3j, String address) {
        try {
            EthGetBalance ethGetBalance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST).send();
            return Convert.fromWei(new BigDecimal(ethGetBalance.getBalance()),Convert.Unit.ETHER);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

获取代币余额 方法一

public static BigInteger getTokenBalance(Web3j web3j, String fromAddress, String contractAddress) {
        String methodName = "balanceOf";
        List<Type> inputParameters = new ArrayList<>();
        List<TypeReference<?>> outputParameters = new ArrayList<>();
        Address address = new Address(fromAddress);
        inputParameters.add(address);

        TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
        };
        outputParameters.add(typeReference);
        Function function = new Function(methodName, inputParameters, outputParameters);
        String data = FunctionEncoder.encode(function);
        Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);

        EthCall ethCall;
        BigInteger balanceValue = BigInteger.ZERO;
        try {
            ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
            List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
            balanceValue = (BigInteger) results.get(0).getValue();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return balanceValue;
    }

获取代币余额 方法二 (仅支持主链上的代币)

String tokenBanceUrl =  "https://api.etherscan.io/api?module=account&action=tokenbalance"
     + "&contractaddress=0x5aA8D6dE8CBf23DAC734E6f904B93bD056B15b81"//Token合约地址
     + "&address=0xd4279e30e27f52ca60fac3cc9670c7b9b1eeefdc"//要查询额的账户余地址
     + "&tag=latest&apikey=YourApiKeyToken";

  String result = HttpRequestUtil.sendGet(tokenBanceUrl, "");
  TokenBalanceResult tokenBalanceResult = JSON.parseObject(result, TokenBalanceResult.class);
  System.out.println(tokenBalanceResult.toString());
  if (tokenBalanceResult.getStatus() == 1) {
   BigDecimal tokenCount = new BigDecimal(tokenBalanceResult.getResult())
     .divide(new BigDecimal(10).pow(FinalValue.TOKEN_DECIMALS));
   return tokenCount.floatValue();
  }

构造交易

// 构造eth交易
Transaction transaction = Transaction.createEtherTransaction(fromAddr, nonce, gasPrice, null, toAddr, value);
// 构造合约调用交易
Transaction transaction = Transaction.createFunctionCallTransaction(fromAddr, nonce, gasPrice, null, contractAddr, funcABI);

估算手续费上限

public static BigInteger getTransactionGasLimit(Web3j web3j, Transaction transaction) {
        try {
            EthEstimateGas ethEstimateGas = web3j.ethEstimateGas(transaction).send();
            if (ethEstimateGas.hasError()){
                throw new RuntimeException(ethEstimateGas.getError().getMessage());
            }
            return ethEstimateGas.getAmountUsed();
        } catch (IOException e) {
            throw new RuntimeException("net error");
        }
    }

转账ETH

public static String transferETH(Web3j web3j, String fromAddr, String privateKey, String toAddr, BigDecimal amount, String data){
        // 获得nonce
        BigInteger nonce = getNonce(web3j, fromAddr);
        // value 转换
        BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();

        // 构建交易
        Transaction transaction = Transaction.createEtherTransaction(fromAddr, nonce, gasPrice, null, toAddr, value);
        // 计算gasLimit
        BigInteger gasLimit = getTransactionGasLimit(web3j, transaction);

        // 查询调用者余额,检测余额是否充足
        BigDecimal ethBalance = getBalance(web3j, fromAddr);
        BigDecimal balance = Convert.toWei(ethBalance, Convert.Unit.ETHER);
        // balance < amount + gasLimit ??
        if (balance.compareTo(amount.add(new BigDecimal(gasLimit.toString()))) < 0) {
            throw new RuntimeException("余额不足,请核实");
        }

        return signAndSend(web3j, nonce, gasPrice, gasLimit, toAddr, value, data, chainId, privateKey);
    }

转账代币

public static String transferToken(Web3j web3j, String fromAddr, String privateKey, String toAddr, String contractAddr, long amount) {

        BigInteger nonce = getNonce(web3j, fromAddr);
        // 构建方法调用信息
        String method = "transfer";

        // 构建输入参数
        List<Type> inputArgs = new ArrayList<>();
        inputArgs.add(new Address(toAddr));
        inputArgs.add(new Uint256(BigDecimal.valueOf(amount).multiply(BigDecimal.TEN.pow(18)).toBigInteger()));

        // 合约返回值容器
        List<TypeReference<?>> outputArgs = new ArrayList<>();

        String funcABI = FunctionEncoder.encode(new Function(method, inputArgs, outputArgs));

        Transaction transaction = Transaction.createFunctionCallTransaction(fromAddr, nonce, gasPrice, null, contractAddr, funcABI);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, null, contractAddr, null, funcABI);

        BigInteger gasLimit = getTransactionGasLimit(web3j, transaction);

        // 获得余额
        BigDecimal ethBalance = getBalance(web3j, fromAddr);
        BigInteger tokenBalance = getTokenBalance(web3j, fromAddr, contractAddr);
        BigInteger balance = Convert.toWei(ethBalance, Convert.Unit.ETHER).toBigInteger();

        if (balance.compareTo(gasLimit) < 0) {
            throw new RuntimeException("手续费不足,请核实");
        }
        if (tokenBalance.compareTo(BigDecimal.valueOf(amount).toBigInteger()) < 0) {
            throw new RuntimeException("代币不足,请核实");
        }

        return signAndSend(web3j, nonce, gasPrice, gasLimit, contractAddr, BigInteger.ZERO, funcABI, chainId, privateKey);
    }

转账代币方法二

public static String transferToken2(String fromAddr,String toAddr,String amount) {
  String contractAddress = "0xa22c2217e785f7796c9e8826c6be55c2e481f9f5";
  Web3j web3j =MyWalletUtils.getWeb3j();
     Credentials credentials = MyWalletUtils.getCredentials();
     System.out.println("我的钱包地址:"+credentials.getAddress());
  try {
   EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
     fromAddr, DefaultBlockParameterName.LATEST).sendAsync().get();
     BigInteger nonce = ethGetTransactionCount.getTransactionCount();
     Function function = new Function(
             "transfer",
             Arrays.asList(new Address(toAddr), new Uint256(new BigInteger(amount))), 
             Arrays.asList(new TypeReference<Type>() {
             }));
     String encodedFunction = FunctionEncoder.encode(function);
     RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, Convert.toWei("18", Convert.Unit.GWEI).toBigInteger(),
             Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);
     byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
     String hexValue = Numeric.toHexString(signedMessage);
     System.out.println("transfer hexValue:" + hexValue);
     EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
     if (ethSendTransaction.hasError()) {
      System.out.println("transfer error:"+ ethSendTransaction.getError().getMessage());
      return ethSendTransaction.getError().getMessage();
     } else {
         String transactionHash = ethSendTransaction.getTransactionHash();
        return "";
     }
  } catch (Exception e) {
   e.printStackTrace();
   return e.getMessage();
  }
 }

对交易签名,并发送交易

public static String signAndSend(Web3j web3j, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, String to, BigInteger value, String data, byte chainId, String privateKey) {
        String txHash = "";
        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);

        byte[] signMessage;
        // 主网是1 responst测试网是3  具体查看ChainId
        if (chainId > ChainId.NONE){
            signMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials);
        } else {
            signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        }

        String signData = Numeric.toHexString(signMessage);
        if (!"".equals(signData)) {
            try {
                EthSendTransaction send = web3j.ethSendRawTransaction(signData).send();
                txHash = send.getTransactionHash();
                System.out.println(JSON.toJSONString(send));
            } catch (IOException e) {
                throw new RuntimeException("交易异常");
            }
        }
        return txHash;
    }

获取代理额度

public static BigInteger getAllowanceBalance(Web3j web3j, String fromAddr, String toAddr, String contractAddress) {
        String methodName = "allowance";
        List<Type> inputParameters = new ArrayList<>();
        inputParameters.add(new Address(fromAddr));
        inputParameters.add(new Address(toAddr));

        List<TypeReference<?>> outputs = new ArrayList<>();
        TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
        };
        outputs.add(typeReference);

        Function function = new Function(methodName, inputParameters, outputs);
        String data = FunctionEncoder.encode(function);
        Transaction transaction = Transaction.createEthCallTransaction(fromAddr, contractAddress, data);
        EthCall ethCall;
        BigInteger balanceValue = BigInteger.ZERO;
        try {
            ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
            List<Type> result = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
            balanceValue = (BigInteger) result.get(0).getValue();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return balanceValue;
    }

动态gas价格与限价

在使用智能合约时,你可能需要根据调用函数指定不同的gas价格和最大值。你可以通过为智能合约封装包创建自己的ContractGasProvider来实现这一点。

每一个生成的封装包都包含作为常量的所有智能合约方法名称,这有助于通过switch来进行编译时间匹配。

例如,使用Greeter合约:

Greeter greeter = new Greeter(...);
greeter.setGasProvider(new DefaultGasProvider() {
    @Override
    public BigInteger getGasPrice(String contractFunc) {
        switch (contractFunc) {
            case Greeter.FUNC_GREET: return BigInteger.valueOf(22_000_000_000L);
            case Greeter.FUNC_KILL: return BigInteger.valueOf(44_000_000_000L);
            default: throw new NotImplementedException();
        }
    }

    @Override
    public BigInteger getGasLimit(String contractFunc) {
        switch (contractFunc) {
            case Greeter.FUNC_GREET: return BigInteger.valueOf(4_300_000);
            case Greeter.FUNC_KILL: return BigInteger.valueOf(5_300_000);
            default: throw new NotImplementedException();
        }
    }
});

如何加快以太坊交易确认被打包的的速度---gasprice

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

结果

{
    "average":25, //平均值(Gwei*10的结果)
    "fastestWait":0.5,
    "fastWait":0.7,
    "fast":36,  //最快(Gwei*10的结果)
    "safeLowWait":1.2,
    "blockNum":6274955,
    "avgWait":1.2,
    "block_time":13.876288659793815,
    "speed":0.9481897143119544,
    "fastest":330,
    "safeLow":25    //安全最低值(Gwei*10的结果)
}
发送交易平均正常速度被打包gasprice,单位是wei
var average_gasprice_wei = average*10e8;
发送交易超快被打包的gasprice,单位是wei
var fast_gasprice_wei = fast*10e8;
发送交易最慢被打包的gasprice,单位是wei
var safeLow_gasprice_wei = safeLow*10e8;

转载自:https://www.jianshu.com/p/a63b0c86924d

当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »