main.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package main
  2. import (
  3. "bufio"
  4. "context"
  5. "crypto/ecdsa"
  6. "fmt"
  7. "log"
  8. "math/big"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. "github.com/ethereum/go-ethereum/ethclient"
  14. )
  15. const (
  16. keyFileName = "keys.txt"
  17. nodeURLTxtName = "nodeURL.txt"
  18. )
  19. func main() {
  20. // 1. 读取 nodeURL.txt
  21. nodeURLs, err := readLinesNoBlank(nodeURLTxtName)
  22. if err != nil {
  23. log.Fatalf("读取%s失败: %v", nodeURLTxtName, err)
  24. }
  25. if len(nodeURLs) == 0 {
  26. log.Fatalf("%s 文件为空,请填入至少一个节点URL(每行一个)后重试。", nodeURLTxtName)
  27. }
  28. // 2. 展示节点列表,提示选择
  29. fmt.Println("可用网络节点列表:")
  30. for i, url := range nodeURLs {
  31. fmt.Printf(" %d. %s\n", i+1, url)
  32. }
  33. fmt.Printf("请输入要使用的节点编号 (1-%d): ", len(nodeURLs))
  34. var urlIndex int
  35. reader := bufio.NewReader(os.Stdin)
  36. for {
  37. fmt.Printf("请输入要使用的节点编号 (1-%d): ", len(nodeURLs))
  38. line, err := reader.ReadString('\n')
  39. if err != nil {
  40. fmt.Println("读取输入失败,请重试。")
  41. continue
  42. }
  43. line = strings.TrimSpace(line)
  44. // 检查line是否只包含数字
  45. num, err := strconv.Atoi(line)
  46. if err != nil || num < 1 || num > len(nodeURLs) {
  47. fmt.Printf("输入无效,请输入 1 到 %d 之间的数字。\n", len(nodeURLs))
  48. continue
  49. }
  50. urlIndex = num - 1
  51. break
  52. }
  53. nodeURL := nodeURLs[urlIndex]
  54. fmt.Printf("当前使用节点: %s\n", nodeURL)
  55. // 检查keys.txt是否存在
  56. if _, err := os.Stat(keyFileName); os.IsNotExist(err) {
  57. file, err := os.Create(keyFileName)
  58. if err != nil {
  59. log.Fatalf("创建%s失败: %v", keyFileName, err)
  60. }
  61. defer file.Close()
  62. fmt.Printf("没有%s文件,已创建,请填入你的key,每行一个,然后重新运行本程序。\n", keyFileName)
  63. return
  64. }
  65. // 读取keys.txt
  66. myKeyArr, err := readLinesNoBlank(keyFileName)
  67. if err != nil {
  68. log.Fatalf("打开%s失败: %v", keyFileName, err)
  69. }
  70. if len(myKeyArr) == 0 {
  71. fmt.Printf("%s 为空,请至少填入一个私钥(每行一个),然后重新运行本程序。\n", keyFileName)
  72. return
  73. }
  74. // 连接以太坊节点
  75. client, err := ethclient.Dial(nodeURL)
  76. if err != nil {
  77. log.Fatalf("连接节点失败: %v", err)
  78. }
  79. // 查询每个key对应地址的余额
  80. for i, key := range myKeyArr {
  81. privateKey, err := crypto.HexToECDSA(key)
  82. if err != nil {
  83. fmt.Printf("钱包 %d: 私钥解析失败,跳过。错误:%v\n\n", i+1, err)
  84. continue // 跳过无效私钥
  85. }
  86. publicKey := privateKey.Public()
  87. publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
  88. if !ok {
  89. fmt.Printf("钱包 %d: 公钥转化失败,跳过。\n\n", i+1)
  90. continue
  91. }
  92. address := crypto.PubkeyToAddress(*publicKeyECDSA)
  93. fmt.Printf("钱包 %d , 钱包地址: %s\n", i+1, address.Hex())
  94. balance, err := client.BalanceAt(context.Background(), address, nil)
  95. if err != nil {
  96. fmt.Printf("钱包 %d: 查询余额失败,跳过。错误:%v\n\n", i+1, err)
  97. continue
  98. }
  99. nonce, err := client.PendingNonceAt(context.Background(), address)
  100. if err != nil {
  101. fmt.Printf("钱包 %d: 查询Nonce失败,跳过。错误:%v\n\n", i+1, err)
  102. continue
  103. }
  104. fmt.Printf("余额(wei): %s\n", balance.String())
  105. etherValue := new(big.Float).Quo(new(big.Float).SetInt(balance), big.NewFloat(1e18))
  106. fmt.Printf("余额(Token): %f\n", etherValue)
  107. fmt.Printf("Nonce: %d\n\n", nonce)
  108. }
  109. }
  110. // 读取文件每行,过滤空行和首尾空白
  111. func readLinesNoBlank(filename string) ([]string, error) {
  112. file, err := os.Open(filename)
  113. if err != nil {
  114. return nil, err
  115. }
  116. defer file.Close()
  117. var lines []string
  118. scanner := bufio.NewScanner(file)
  119. for scanner.Scan() {
  120. line := strings.TrimSpace(scanner.Text())
  121. if line != "" {
  122. lines = append(lines, line)
  123. }
  124. }
  125. return lines, scanner.Err()
  126. }