区块链|以太坊(ETH)简单的交易

最近在学习eth的交易,简单记录一下。
1.创建一个属于自己的以太坊链地址 方式1:我们可以通过https://infura.io/来申请一个自己的地址,当然目前官方人员不建议使用这个。因为以太坊提出的理念是去中心化,每个节点都可以当作中心节点。
当然这个是比较方便的,不需要自己去搭建节点了。
区块链|以太坊(ETH)简单的交易
文章图片

目前在国内这个网站的注册是被墙了的,没法注册。
方式2:搭建自己的以太坊私有链。

  1. 需要安装geth,得有go环境的支持。
    以Mac环境为例:参考官网的提示,
    执行一下两个命令:
brew tap ethereum/ethereumbrew install ethereum

然后
geth

可以看看是否安装成功。
2. 创建JSON文件genesis.json 初始化私有链。
{ "config": { "chainId": 1000000, "homesteadBlock": 0, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0 }, "nonce": "0x0000000000000042", "maxhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "difficulty": "0x200", "gasLimit": "0xffffffff", "coinbase": "0x0000000000000000000000000000000000000000", "stmestamp": "0x00", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "alloc": {} }

具体每个参数的意思可以去百度下。
  1. 初始化网络:
    创建一个数据存储文件夹,然后使用以下命令初始化网络。
geth init "/Users/admin/genesis.json" --datadir "/Users/admin/eth"

  1. 启动私有链(运行节点环境)
geth --datadir "/Users/admin/eth" --rpc --rpcapi "eth,web3,miner,admin,personal,net" --allow-insecure-unlock --rpccorsdomain "*" --nodiscover --networkid 1000000

然后我们就可以使用命令玩以下挖矿什么的,当然都是弄着玩的,不是真就这么多钱。。。
2. 使用Web3j来开发简单的交易 引入maven
org.web3j core 4.5.17 com.squareup.okhttp3 okhttp 4.4.1 com.squareup.okio okio 2.2.0

【区块链|以太坊(ETH)简单的交易】还有一些别的配置,自己看着加。
基本的钱包代码:
import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.databind.node.BigIntegerNode; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.web3j.crypto.*; import org.web3j.protocol.Web3j; import org.web3j.protocol.Web3jService; import org.web3j.protocol.core.DefaultBlockParameter; import org.web3j.protocol.core.DefaultBlockParameterName; import org.web3j.protocol.core.methods.response.*; import org.web3j.protocol.http.HttpService; import org.web3j.tx.Contract; import org.web3j.tx.Transfer; import org.web3j.tx.gas.DefaultGasProvider; import org.web3j.utils.Convert; import org.web3j.utils.Numeric; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; public class EthWallet { private static Logger logger = LoggerFactory.getLogger(EthWallet.class); private Web3j web3j; //默认 GAS public final static Long GAS_LIMIT = 100L; public void init(String url) throws Exception { if (web3j == null) { Web3jService web3jService = new HttpService(url); web3j = Web3j.build(web3jService); } } /** * 生成钱包: * 公钥、私钥、地址 */ public static Map, String> createWallet() throws Exception { ECKeyPair ecKeyPair = Keys.createEcKeyPair(); String privateKey = ecKeyPair.getPrivateKey().toString(16); String publicKey = ecKeyPair.getPublicKey().toString(16); String address = Keys.getAddress(ecKeyPair.getPublicKey()); Map, String> result = new HashMap, String>(); result.put("privateKey", privateKey); result.put("publicKey", publicKey); result.put("address", "0x" + address); return result; } /** * 最终将交易信息发送到链上 * @return */ public EthSendTransaction sendRawTransaction(String from, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, String to, BigInteger value, String privateKey) throws IOException { String hashValue = https://www.it610.com/article/signTransaction(from, nonce, gasPrice, gasLimit, to, value, privateKey); EthSendTransaction transactionHash = web3j.ethSendRawTransaction(hashValue).send(); if (transactionHash.hasError()) { logger.error("transactionHash error -> code :{} \nmessage:{} \n data:{}", transactionHash.getError().getCode(), transactionHash.getError().getMessage(), transactionHash.getError().getData()); return null; } // 这个就是TXHash 可以通过这个查询交易状态 String txHash = transactionHash.getTransactionHash(); System.out.println(txHash); return transactionHash; }/** * 签名 * from:发送方 * nonce:nonce值 * gasPrice:gas价格 一般以GWei(1 ETH = 1000000000 GWei)2.32gwei,可以在https://ethstats.net/上面查询到。 * gasLimit:最多gas总量 * to:接收方 * value:发送的金额 * privateKey: 私钥 */ public static String signTransaction(String from, BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, String to, BigInteger value, String privateKey) { logger.info("=======================signTransaction=========================="); logger.info("nonce:" + nonce); logger.info("gasPrice:" + gasPrice); logger.info("gasLimit:" + gasLimit); logger.info("to:" + to); logger.info("value:" + value); logger.info("privateKey:" + privateKey); logger.info("from:" + from); if (privateKey.startsWith("0x")) { privateKey = privateKey.substring(2); } ECKeyPair ecKeyPair = ECKeyPair.create(new BigInteger(privateKey, 16)); Credentials credentials = Credentials.create(ecKeyPair); byte[] signedMessage; RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, to, value, ""); signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); String hexValue = https://www.it610.com/article/Numeric.toHexString(signedMessage); logger.info("signedData : " + hexValue); //String signData = https://www.it610.com/article/signTransactionTo(nonce, gasPrice, gasLimit, to, value,"", credentials); logger.info("=======================signTransaction(end)======================="); return hexValue; }/** * 签名获取hex 进行广播交易 */ public static String signTransactionTo(BigInteger nonce, BigInteger gasPrice, BigInteger gasLimit, String to, BigInteger value, String data, Credentials credentials) throws IOException { byte[] signedMessage; RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, to, value, data); signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); String hexValue = https://www.it610.com/article/Numeric.toHexString(signedMessage); logger.info("signedData : " + hexValue); return hexValue; } /** * 根据txHash检查交易结果信息 * @param txHash */ protected void check(String txHash) { try { EthGetTransactionReceipt ethGetTransactionReceipt = web3j.ethGetTransactionReceipt(txHash).send(); TransactionReceipt result = ethGetTransactionReceipt.getResult(); if (result != null) { if (result.isStatusOK()) { System.out.println("TxHash:"+txHash+"交易结果:"+JSON.toJSONString(result)); // 交易成功 // 可以获取到交易信息 } else { // 交易失败 // 错误信息 String errorMsg = String.format( "Transaction has failed with status: %s. " + "Gas used: %d. (not-enough gas?)", result.getStatus(), result.getGasUsed()); System.out.println("error:"+errorMsg); } } } catch (IOException e) { e.printStackTrace(); } }public static BigDecimal fromEthtoWei(BigDecimal eth) { return Convert.toWei(eth, Convert.Unit.ETHER); }public static BigDecimal fromGWeitoWei(BigDecimal gwei) { return Convert.toWei(gwei, Convert.Unit.GWEI); }/** * 区块高度 *获取 nonce * @return */ public BigInteger getBlockHeight() { EthGetTransactionCount ethGetTransactionCount = null; try { ethGetTransactionCount = web3j.ethGetTransactionCount( "0x206989b8cfea5c7ee222d0f31f8fb9e5a9954cf8", DefaultBlockParameterName.LATEST).sendAsync().get(); BigInteger nonce = ethGetTransactionCount.getTransactionCount(); return nonce; } catch (InterruptedException e) { logger.error("getBlockHeight[error]:e={}",e); return null; } catch (ExecutionException e) { logger.error("getBlockHeight[error]:e={}",e); return null; } }/** * 区块处理 * @param height */ public boolean parseBlock(BigInteger height) { DefaultBlockParameter param = DefaultBlockParameter.valueOf(height); try { EthBlock eblock = web3j.ethGetBlockByNumber(param, true).send(); if (!eblock.hasError()) { EthBlock.Block block = eblock.getBlock(); //需要检查确认数 if (block == null) { //连接失败 return false; } List trans = block.getTransactions(); Date tranTm = new Date(block.getTimestamp().longValue() * 1000); if (trans != null && trans.size() > 0) { String ethAddress = "0x206989b8cfea5c7ee222d0f31f8fb9e5a9954cf8"; for (EthBlock.TransactionResult tranResult : trans) { parserTranscation(tranResult, ethAddress, tranTm); } } } return true; } catch (Exception e) { e.printStackTrace(); return false; } } private void parserTranscation(EthBlock.TransactionResult transaction, String userAddrees, Date tranTm) throws IllegalAccessException { EthBlock.TransactionObject tran = transaction.get(); String toaddr = tran.getTo(); String input = tran.getInput(); String txid = tran.getHash(); if (StringUtils.isEmpty(toaddr)) { return; } /** * 以太坊交易 */ if (tran.getValue().doubleValue() > 0) { double value = https://www.it610.com/article/webTogether(tran.getValue()); if (value>= 0.1) { System.out.println("toaddr:"+toaddr); System.out.println("input:"+input); System.out.println("txid:"+txid); //记录 //ethRechargeParse(toaddr, userAddrees, txid, value, tranTm); } } }private double webTogether(BigInteger value) throws IllegalAccessException { return BigDecimalUtil.div(value.doubleValue(), Math.pow(10, 18), 6); }public static void main(String[] args) throws Exception { //test: // {"privateKey":"773810272562159579d8584512d0c8b1967b7b43480c6d206f823180019bb18d", // "address":"0x206989b8cfea5c7ee222d0f31f8fb9e5a9954cf8", // "publicKey":"9a04044a7e0f2f2513b8e9b4e42fe4b54e40177405773d67346420d1651c4f55c38185244d2a413198cfd92b73ae5b1515cadbce9a091bfbcbafcc998e046e02"} //Map result = createWallet(); //System.out.println(JSON.toJSONString(result)); EthWallet ethWallet = new EthWallet(); //ethWallet.init("https://mainnet.infura.io/v3/03a06ac61e0740ed8934ca4bc13c8cf1"); ethWallet.init("http://localhost:8545"); //token2:https://rinkeby.infura.io/zmd7VgRt9go0x6qlJ2Mk System.out.println(ethWallet.getBlockHeight()); BigInteger price = DefaultGasProvider.GAS_PRICE; BigInteger gasLimt = DefaultGasProvider.GAS_LIMIT; //to: 0x2f9bfd0c6e84dec524a038c109aed6d8fa687365 String privateKey = "773810272562159579d8584512d0c8b1967b7b43480c6d206f823180019bb18d"; //BigDecimal wei = new BigDecimal("2.1"); //ethWallet.sendRawTransaction("0xcb7c37f96416ca865a5e6e57f8f2feb66e34a0d0",ethWallet.getBlockHeight(), //price,gasLimt,"0x206989b8cfea5c7ee222d0f31f8fb9e5a9954cf8",BigInteger.valueOf(1l),privateKey); ethWallet.check("0x988fb969714533873e0d9ab3b435a22ff46ea8a640ecef6f50150a48aa8486dc"); ethWallet.parseBlock(ethWallet.getBlockHeight()); } }

    推荐阅读