| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- package main
- import (
- "bufio"
- "context"
- "crypto/ecdsa"
- "fmt"
- "log"
- "math/big"
- "os"
- "strconv"
- "strings"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethclient"
- )
- const (
- keyFileName = "keys.txt"
- nodeURLTxtName = "nodeURL.txt"
- )
- func main() {
- // 1. 读取 nodeURL.txt
- nodeURLs, err := readLinesNoBlank(nodeURLTxtName)
- if err != nil {
- log.Fatalf("读取%s失败: %v", nodeURLTxtName, err)
- }
- if len(nodeURLs) == 0 {
- log.Fatalf("%s 文件为空,请填入至少一个节点URL(每行一个)后重试。", nodeURLTxtName)
- }
- // 2. 展示节点列表,提示选择
- fmt.Println("可用网络节点列表:")
- for i, url := range nodeURLs {
- fmt.Printf(" %d. %s\n", i+1, url)
- }
- fmt.Printf("请输入要使用的节点编号 (1-%d): ", len(nodeURLs))
- var urlIndex int
- reader := bufio.NewReader(os.Stdin)
- for {
- fmt.Printf("请输入要使用的节点编号 (1-%d): ", len(nodeURLs))
- line, err := reader.ReadString('\n')
- if err != nil {
- fmt.Println("读取输入失败,请重试。")
- continue
- }
- line = strings.TrimSpace(line)
- // 检查line是否只包含数字
- num, err := strconv.Atoi(line)
- if err != nil || num < 1 || num > len(nodeURLs) {
- fmt.Printf("输入无效,请输入 1 到 %d 之间的数字。\n", len(nodeURLs))
- continue
- }
- urlIndex = num - 1
- break
- }
- nodeURL := nodeURLs[urlIndex]
- fmt.Printf("当前使用节点: %s\n", nodeURL)
- // 检查keys.txt是否存在
- if _, err := os.Stat(keyFileName); os.IsNotExist(err) {
- file, err := os.Create(keyFileName)
- if err != nil {
- log.Fatalf("创建%s失败: %v", keyFileName, err)
- }
- defer file.Close()
- fmt.Printf("没有%s文件,已创建,请填入你的key,每行一个,然后重新运行本程序。\n", keyFileName)
- return
- }
- // 读取keys.txt
- myKeyArr, err := readLinesNoBlank(keyFileName)
- if err != nil {
- log.Fatalf("打开%s失败: %v", keyFileName, err)
- }
- if len(myKeyArr) == 0 {
- fmt.Printf("%s 为空,请至少填入一个私钥(每行一个),然后重新运行本程序。\n", keyFileName)
- return
- }
- // 连接以太坊节点
- client, err := ethclient.Dial(nodeURL)
- if err != nil {
- log.Fatalf("连接节点失败: %v", err)
- }
- // 查询每个key对应地址的余额
- for i, key := range myKeyArr {
- privateKey, err := crypto.HexToECDSA(key)
- if err != nil {
- fmt.Printf("钱包 %d: 私钥解析失败,跳过。错误:%v\n\n", i+1, err)
- continue // 跳过无效私钥
- }
- publicKey := privateKey.Public()
- publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
- if !ok {
- fmt.Printf("钱包 %d: 公钥转化失败,跳过。\n\n", i+1)
- continue
- }
- address := crypto.PubkeyToAddress(*publicKeyECDSA)
- fmt.Printf("钱包 %d , 钱包地址: %s\n", i+1, address.Hex())
- balance, err := client.BalanceAt(context.Background(), address, nil)
- if err != nil {
- fmt.Printf("钱包 %d: 查询余额失败,跳过。错误:%v\n\n", i+1, err)
- continue
- }
- nonce, err := client.PendingNonceAt(context.Background(), address)
- if err != nil {
- fmt.Printf("钱包 %d: 查询Nonce失败,跳过。错误:%v\n\n", i+1, err)
- continue
- }
- fmt.Printf("余额(wei): %s\n", balance.String())
- etherValue := new(big.Float).Quo(new(big.Float).SetInt(balance), big.NewFloat(1e18))
- fmt.Printf("余额(Token): %f\n", etherValue)
- fmt.Printf("Nonce: %d\n\n", nonce)
- }
- }
- // 读取文件每行,过滤空行和首尾空白
- func readLinesNoBlank(filename string) ([]string, error) {
- file, err := os.Open(filename)
- if err != nil {
- return nil, err
- }
- defer file.Close()
- var lines []string
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
- if line != "" {
- lines = append(lines, line)
- }
- }
- return lines, scanner.Err()
- }
|