BTC转账功能开发-java版

BTC转账功能开发

一、准备工作

1、下载metamask钱包插件

根据提示使用助记词生成账户,这里可以看到用户可以保留助记词,但是不保留私钥,或者keystore的json文件。可以生成一个账户

2、创建账户

针对于java和以太坊之间操作,一般有两种生成账户的方法:

  • 使用metamask插件运用助记词创建账户的方法

  • 用代码生成账户的方法,该方法有一个好处就是我们能够掌握账户的私钥(keystore的json文件)

    • maven配置

      <dependency>
                  <groupId>org.bitcoinj</groupId>
                  <artifactId>bitcoinj-core</artifactId>
                  <version>0.14.7</version>
              </dependency>
      
              <dependency>
                  <groupId>org.web3j</groupId>
                  <artifactId>core</artifactId>
                  <version>3.6.0</version>
              </dependency>
      
    • 代码实现

      /**
           * path路径
           */
          private final static ImmutableList<ChildNumber> BIP44_ETH_ACCOUNT_ZERO_PATH =
                  ImmutableList.of(new ChildNumber(44, true), new ChildNumber(60, true),
                          ChildNumber.ZERO_HARDENED, ChildNumber.ZERO);
      
      
      
          /**
           * 创建钱包
           * @throws MnemonicException.MnemonicLengthException
           */
          private static void createWallet()  throws MnemonicException.MnemonicLengthException {
              SecureRandom secureRandom = new SecureRandom();
              byte[] entropy = new byte[DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS / 8];
              secureRandom.nextBytes(entropy);
      
              //生成12位助记词
              List<String> str = MnemonicCode.INSTANCE.toMnemonic(entropy);
      
              //使用助记词生成钱包种子
              byte[] seed = MnemonicCode.toSeed(str, "");
              DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
              DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(masterPrivateKey);
              DeterministicKey deterministicKey = deterministicHierarchy
                      .deriveChild(BIP44_ETH_ACCOUNT_ZERO_PATH, false, true, new ChildNumber(0));
              byte[] bytes = deterministicKey.getPrivKeyBytes();
              ECKeyPair keyPair = ECKeyPair.create(bytes);
              //通过公钥生成钱包地址
              String address = Keys.getAddress(keyPair.getPublicKey());
      
              System.out.println();
              System.out.println("助记词:");
              System.out.println(str);
              System.out.println();
              System.out.println("地址:");
              System.out.println("0x"+address);
              System.out.println();
              System.out.println("私钥:");
              System.out.println("0x"+keyPair.getPrivateKey().toString(16));
              System.out.println();
              System.out.println("公钥:");
              System.out.println(keyPair.getPublicKey().toString(16));
          }
      
          public static void main(String[] args) throws Exception {
              //创建钱包
              createWallet();
          }
      
    • 导入钱包

      • 保存上述打印东西
      • 打开小狐狸钱包,导入私钥

3、领取测试币

领取测试币地址5ETH:https://faucet.dimensions.network/

二、ETH转账交易

1、创建自己的以太坊节点地址

参考区块链同学给我的地址:https://docs.infura.io/infura/networks/ethereum/json-rpc-methods/eth_sendtransaction

先注册=》创建项目=〉进入自己的项目

选择项目属性

复制自己的测试网节点地址(下拉到自己的测试网地址)

2、代码编写

实现ETH转账

/**
     * 连接web3 节点
     */
    private final static Web3j web3j = Web3j.build(new HttpService("https://rinkeby.infura.io/v3/第一步的那个项目编号"));

/**
     * ETH转账
     * @throws IOException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void signETHTransaction() throws IOException, ExecutionException, InterruptedException {

        //发送方地址
        String from = "0xe12A0E286C94747E9D8a67e18FBDF35D6B58C5B6";
        //转账数量
        String amount = "0.05";
        //接收者地址
        String to = "0x336185cc47e81422d8ff26fb9a7a9c4138ce3d2a";
        //发送方私钥
        String privateKey = "****";
        //查询地址交易编号
        BigInteger nonce = web3j.ethGetTransactionCount(from, DefaultBlockParameterName.PENDING).send().getTransactionCount();
        //支付的矿工费
        BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();

        BigInteger gasLimit = new BigInteger("210000");

        BigInteger amountWei = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();
        //签名交易
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, to, amountWei, "");
        Credentials credentials = Credentials.create(privateKey);
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        //广播交易
        String hash =  web3j.ethSendRawTransaction(Numeric.toHexString(signMessage)).sendAsync().get().getTransactionHash();

        System.out.println("hash:"+hash);

    }

运行结果:

转账结果

转账之前:

转账后:

3、代币查询

由于没有ETH的代币,所以找区块链的同学转了点币安测试网的代币

代币余额查询

/**
     * 连接web3 节点
     */
    private final static Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s2.binance.org:8545/项目编号"));
private static final BigDecimal WEI = new BigDecimal(10000);
/**
* 获取ERC-20 token指定地址余额
*/
public static void getbscGetBalance() throws ExecutionException, InterruptedException {
        String methodName = "balanceOf";
        List<Type> inputParameters = new ArrayList<>();
        List<TypeReference<?>> outputParameters = new ArrayList<>();
        Address fromAddress = new Address("发送方地址");
        inputParameters.add(fromAddress);

        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("发送方地址", "合约地址", data);

        EthCall ethCall;
        BigDecimal balanceValue = BigDecimal.ZERO;
        try {
            ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
            List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
            BigInteger value = BigInteger.valueOf(0);
            if(results != null && results.size()>0){
                value = (BigInteger)results.get(0).getValue();
            }
            balanceValue = new BigDecimal(value).divide(WEI, 6, RoundingMode.HALF_DOWN);
            System.out.println(balanceValue.toBigInteger());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

查询余额结果

4、代币转账

转账代码实现:

/**
     * ETH代币转账
     * @throws IOException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void signTokenTransaction() throws IOException, ExecutionException, InterruptedException {

        //发送方地址
        String from = "0xe12A0E286C94747E9D8a67e18FBDF35D6B58C5B6";
        //转账数量
        String amount = "5";
        //接收者地址
        String to = "0x336185cC47e81422D8fF26fB9A7a9c4138Ce3D2A";
        //发送方私钥
        String privateKey = "****";
        //代币合约地址
        String coinAddress = "合约地址";
        //查询地址交易编号
        BigInteger nonce = web3j.ethGetTransactionCount(from, DefaultBlockParameterName.PENDING).send().getTransactionCount();
        //支付的矿工费
        BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
        BigInteger gasLimit = new BigInteger("210000");

        Credentials credentials = Credentials.create(privateKey);
        BigInteger amountWei = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();

        //封装转账交易
        Function function = new Function(
                "transfer",
                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(to),
                        new org.web3j.abi.datatypes.generated.Uint256(amountWei)),
                Collections.<TypeReference<?>>emptyList());
        String data = FunctionEncoder.encode(function);
        //签名交易
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, coinAddress, data);
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        //广播交易
        String hash = web3j.ethSendRawTransaction(Numeric.toHexString(signMessage)).sendAsync().get().getTransactionHash();
        System.out.println("hash:"+hash);
    }

执行结果

转账结果

转账之前

转账之后:

posted @ 2022-05-07 17:31  小学程序员  阅读(1065)  评论(0编辑  收藏  举报