loading

Loading

首页 TronLink官网

使用Go语言构建TronLink风格的钱包应用

字数: (11206)
阅读: (0)
0

使用Go语言构建TronLink风格的钱包应用

本文将详细介绍如何使用Go语言构建一个类似TronLink的钱包应用,包含私钥管理、交易签名、TRX和TRC20代币转账等核心功能。

一、TronLink钱包简介

TronLink是波场(TRON)区块链上最受欢迎的钱包之一,提供账户管理、资产转账、智能合约交互等功能。我们将使用Go语言实现其核心功能,创建一个轻量级命令行钱包。

二、项目架构设计

我们的钱包将包含以下核心模块:
1.密钥管理-生成和存储私钥
2.交易构建-创建TRX和TRC20转账交易
3.网络通信-与TRON节点交互
4.用户界面-命令行交互

三、核心代码实现

1.初始化项目

首先创建项目目录结构:

tron-wallet/
├──cmd/
│└──main.go
├──internal/
│├──crypto/
│├──wallet/
│└──tron/
├──go.mod
└──go.sum

初始化go.mod文件:

modulegithub.com/yourname/tron-wallet

go1.21

require(
github.com/btcsuite/btcd/btcec/v2v2.3.2
github.com/ethereum/go-ethereumv1.13.4
github.com/fatih/colorv1.16.0
github.com/shengdoushi/base58v1.0.0
github.com/tyler-smith/go-bip39v1.1.0
google.golang.org/grpcv1.59.0
google.golang.org/protobufv1.31.0
)

2.密钥管理实现

internal/crypto/keys.go:

packagecrypto

import(
"crypto/ecdsa"
"encoding/hex"
"errors"
"fmt"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/ethereum/go-ethereum/crypto"
"github.com/tyler-smith/go-bip39"
)

//GenerateMnemonic生成BIP39助记词
funcGenerateMnemonic()(string,error){
entropy,err:=bip39.NewEntropy(128)
iferr!=nil{
return"",err
}
returnbip39.NewMnemonic(entropy)
}

//MnemonicToPrivateKey从助记词派生私钥
funcMnemonicToPrivateKey(mnemonicstring)(ecdsa.PrivateKey,error){
if!bip39.IsMnemonicValid(mnemonic){
returnnil,errors.New("invalidmnemonic")
}

seed:=bip39.NewSeed(mnemonic,"")
privateKey,err:=crypto.ToECDSA(seed[:32])
iferr!=nil{
returnnil,err
}

returnprivateKey,nil
}

//PrivateKeyToAddress从私钥生成TRON地址
funcPrivateKeyToAddress(privateKeyecdsa.PrivateKey)(string,error){
publicKey:=privateKey.Public()
publicKeyECDSA,ok:=publicKey.(ecdsa.PublicKey)
if!ok{
return"",errors.New("errorcastingpublickeytoECDSA")
}

//TRON地址是公钥的Keccak-256哈希的最后20字节,前面加上0x41
pubBytes:=crypto.FromECDSAPub(publicKeyECDSA)
addressBytes:=crypto.Keccak256(pubBytes[1:])[12:]
addressBytes=append([]byte{0x41},addressBytes...)

returnEncodeBase58(addressBytes),nil
}

//EncodeBase58TRON使用的Base58编码
funcEncodeBase58(input[]byte)string{
constalphabet="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

varresult[]byte
x:=new(big.Int).SetBytes(input)

base:=big.NewInt(58)
zero:=big.NewInt(0)
mod:=new(big.Int)

forx.Cmp(zero)!=0{
x.DivMod(x,base,mod)
result=append(result,alphabet[mod.Int64()])
}

//反转结果
fori,j:=0,len(result)-1;i<j;i,j=i+1,j-1{
result[i],result[j]=result[j],result[i]
}

returnstring(result)
}

3.钱包核心实现

internal/wallet/wallet.go:

packagewallet

import(
"crypto/ecdsa"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"

"github.com/yourname/tron-wallet/internal/crypto"
)

typeWalletstruct{
PrivateKeyecdsa.PrivateKey
Addressstring
}

//NewWallet创建新钱包
funcNewWallet()(Wallet,error){
mnemonic,err:=crypto.GenerateMnemonic()
iferr!=nil{
returnnil,err
}

returnFromMnemonic(mnemonic)
}

//FromMnemonic从助记词恢复钱包
funcFromMnemonic(mnemonicstring)(Wallet,error){
privateKey,err:=crypto.MnemonicToPrivateKey(mnemonic)
iferr!=nil{
returnnil,err
}

address,err:=crypto.PrivateKeyToAddress(privateKey)
iferr!=nil{
returnnil,err
}

return&Wallet{
PrivateKey:privateKey,
Address:address,
},nil
}

//FromPrivateKey从私钥恢复钱包
funcFromPrivateKey(privateKeyHexstring)(Wallet,error){
privateKeyBytes,err:=hex.DecodeString(privateKeyHex)
iferr!=nil{
returnnil,err
}

privateKey,err:=crypto.ToECDSA(privateKeyBytes)
iferr!=nil{
returnnil,err
}

address,err:=crypto.PrivateKeyToAddress(privateKey)
iferr!=nil{
returnnil,err
}

return&Wallet{
PrivateKey:privateKey,
Address:address,
},nil
}

//SaveToFile将钱包保存到文件
func(wWallet)SaveToFile(pathstring)error{
privateKeyBytes:=crypto.FromECDSA(w.PrivateKey)
data:=map[string]string{
"privateKey":hex.EncodeToString(privateKeyBytes),
"address":w.Address,
}

jsonData,err:=json.MarshalIndent(data,"","")
iferr!=nil{
returnerr
}

iferr:=os.MkdirAll(filepath.Dir(path),0700);err!=nil{
returnerr
}

returnos.WriteFile(path,jsonData,0600)
}

//LoadFromFile从文件加载钱包
funcLoadFromFile(pathstring)(Wallet,error){
data,err:=os.ReadFile(path)
iferr!=nil{
returnnil,err
}

varwalletDatamap[string]string
iferr:=json.Unmarshal(data,&walletData);err!=nil{
returnnil,err
}

returnFromPrivateKey(walletData["privateKey"])
}

4.TRON网络交互

internal/tron/client.go:

packagetron

import(
"context"
"encoding/hex"
"errors"
"fmt"
"math/big"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/tronprotocol/grpc-gateway/api"
"github.com/tronprotocol/grpc-gateway/core"
)

typeClientstruct{
api.WalletClient
conngrpc.ClientConn
}

//NewClient创建TRONGRPC客户端
funcNewClient(nodeURLstring)(Client,error){
conn,err:=grpc.Dial(nodeURL,grpc.WithTransportCredentials(insecure.NewCredentials()))
iferr!=nil{
returnnil,err
}

return&Client{
WalletClient:api.NewWalletClient(conn),
conn:conn,
},nil
}

//Close关闭连接
func(cClient)Close()error{
returnc.conn.Close()
}

//GetAccount获取账户信息
func(cClient)GetAccount(addressstring)(core.Account,error){
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()

account:=&core.Account{
Address:common.Hex2Bytes(address),
}

returnc.GetAccount(ctx,account)
}

//GetNowBlock获取最新区块
func(cClient)GetNowBlock()(core.Block,error){
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()

returnc.GetNowBlock(ctx,&api.EmptyMessage{})
}

//CreateTransaction创建TRX转账交易
func(cClient)CreateTransaction(from,tostring,amountint64)(core.Transaction,error){
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()

transferContract:=&core.TransferContract{
OwnerAddress:common.Hex2Bytes(from),
ToAddress:common.Hex2Bytes(to),
Amount:amount,
}

returnc.CreateTransaction(ctx,transferContract)
}

//SignTransaction签名交易
funcSignTransaction(txcore.Transaction,privateKeyecdsa.PrivateKey)error{
rawData,err:=tx.GetRawData().Marshal()
iferr!=nil{
returnerr
}

hash:=crypto.Keccak256(rawData)
signature,err:=crypto.Sign(hash,privateKey)
iferr!=nil{
returnerr
}

tx.Signature=append(tx.Signature,signature)
returnnil
}

//BroadcastTransaction广播交易
func(cClient)BroadcastTransaction(txcore.Transaction)(api.Return,error){
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()

returnc.BroadcastTransaction(ctx,tx)
}

//GetTRC20Balance获取TRC20代币余额
func(cClient)GetTRC20Balance(contractAddress,ownerAddressstring)(big.Int,error){
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()

//TRC20balanceOf函数调用
data:="0x70a08231000000000000000000000000"+ownerAddress[2:]
trigger:=&core.TriggerSmartContract{
ContractAddress:common.Hex2Bytes(contractAddress),
OwnerAddress:common.Hex2Bytes(ownerAddress),
Data:common.Hex2Bytes(data),
}

result,err:=c.TriggerConstantContract(ctx,trigger)
iferr!=nil{
returnnil,err
}

if!result.GetResult().GetResult(){
returnnil,errors.New("contractcallfailed:"+string(result.GetResult().GetMessage()))
}

balance:=new(big.Int).SetBytes(result.GetConstantResult()[0])
returnbalance,nil
}

5.命令行界面

cmd/main.go:


packagemain

import(
"bufio"
"context"
"encoding/hex"
"fmt"
"log"
"os"
"strconv"
"strings"

"github.com/fatih/color"
"github.com/yourname/tron-wallet/internal/crypto"
"github.com/yourname/tron-wallet/internal/tron"
"github.com/yourname/tron-wallet/internal/wallet"
)

const(
walletFile="./wallet.json"
nodeURL="grpc.trongrid.io:50051"
)

funcmain(){
fmt.Println(color.GreenString("TRONWalletCLI"))
fmt.Println("---------------------")

varwwallet.Wallet
varerrerror

//检查钱包文件是否存在
if_,err:=os.Stat(walletFile);os.IsNotExist(err){
fmt.Println("Nowalletfound.Createanewone.")
w,err=createNewWallet()
iferr!=nil{
log.Fatal("Failedtocreatewallet:",err)
}
}else{
fmt.Println("Loadingexistingwallet...")
w,err=wallet.LoadFromFile(walletFile)
iferr!=nil{
log.Fatal("Failedtoloadwallet:",err)
}
}

fmt.Printf("Youraddress:%s\n",color.BlueString(w.Address))
fmt.Println()

//创建TRON客户端
client,err:=tron.NewClient(nodeURL)
iferr!=nil{
log.Fatal("FailedtoconnecttoTRONnode:",err)
}
deferclient.Close()

//主循环
reader:=bufio.NewReader(os.Stdin)
for{
printMenu()
fmt.Print(">")
input,_:=reader.ReadString('\n')
input=strings.TrimSpace(input)

switchinput{
case"1":
showAccountInfo(client,w.Address)
case"2":
sendTRX(client,w)
case"3":
checkTRC20Balance(client,w.Address)
case"4":
sendTRC20(client,w)
case"5":
showPrivateKey(w)
case"6":
fmt.Println("Exiting...")
return
default:
fmt.Println("Invalidoption")
}
}
}

funcprintMenu(){
fmt.Println("\nMenu:")
fmt.Println("1.Showaccountinfo")
fmt.Println("2.SendTRX")
fmt.Println("3.CheckTRC20balance")
fmt.Println("4.SendTRC20tokens")
fmt.Println("5.Showprivatekey")
fmt.Println("6.Exit")
}

funccreateNewWallet()(wallet.Wallet,error){
w,err:=wallet.NewWallet()
iferr!=nil{
returnnil,err
}

iferr:=w.SaveToFile(walletFile);err!=nil{
returnnil,err
}

fmt.Println("Newwalletcreatedsuccessfully!")
fmt.Println("Pleasebackupyourprivatekeyandmnemonicphrasesecurely.")
returnw,nil
}

funcshowAccountInfo(clienttron.Client,addressstring){
account,err:=client.GetAccount(address)
iferr!=nil{
fmt.Println("Failedtogetaccountinfo:",err)
return
}

fmt.Println("\nAccountInformation:")
fmt.Printf("Address:%s\n",color.BlueString(address))
fmt.Printf("Balance:%dTRX\n",account.GetBalance())
fmt.Printf("Bandwidth:%d\n",account.GetNetUsage())
fmt.Printf("Energy:%d\n",account.GetAccountResource().GetEnergyUsage())
}

funcsendTRX(clienttron.Client,wwallet.Wallet){
reader:=bufio.NewReader(os.Stdin)

fmt.Print("Recipientaddress:")
to,_:=reader.ReadString('\n')
to=strings.TrimSpace(to)

fmt.Print("Amount(TRX):")
amountStr,_:=reader.ReadString('\n')
amountStr=strings.TrimSpace(amountStr)

amount,err:=strconv.ParseInt(amountStr,10,64)
iferr!=nil{
fmt.Println("Invalidamount:",err)
return
}

//1TRX=1,000,000SUN
amountInSun:=amount1000000

tx,err:=client.CreateTransaction(w.Address,to,amountInSun)
iferr!=nil{
fmt.Println("Failedtocreatetransaction:",err)
return
}

iferr:=tron.SignTransaction(tx,w.PrivateKey);err!=nil{
fmt.Println("Failedtosigntransaction:",err)
return
}

result,err:=client.BroadcastTransaction(tx)
iferr!=nil{
fmt.Println("Failedtobroadcasttransaction:",err)
return
}

ifresult.GetResult(){
fmt.Println(color.GreenString("Transactionsentsuccessfully!"))
fmt.Printf("TxID:%s\n",hex.EncodeToString(tx.GetTxid()))
}else{
fmt.Println(color.RedString("Transactionfailed:"),result.GetMessage())
}
}

funccheckTRC20Balance(clienttron.Client,addressstring){
reader:=bufio.NewReader(os.Stdin)

fmt.Print("TRC20contractaddress:")
contractAddr,_:=reader.ReadString('\n')
contractAddr=strings.TrimSpace(contractAddr)

balance,err:=client.GetTRC20Balance(contractAddr,address)
iferr!=nil{
fmt.Println("Failedtogetbalance:",err)
return
}

fmt.Printf("Balance:%stokens\n",balance.String())
}

funcsendTRC20(clienttron.Client,wwallet.Wallet){
reader:=bufio.NewReader(os.Stdin)

fmt.Print("TRC20contractaddress:")
contractAddr,_:=reader.ReadString('\n')
contractAddr=strings.TrimSpace(contractAddr)

fmt.Print("Recipientaddress:")
to,_:=reader.ReadString('\n')
to=strings.TrimSpace(to)

fmt.Print("Amount(insmallestunit):")
amountStr,_:=reader.ReadString('\n')
amountStr=strings.TrimSpace(amountStr)

amount,ok:=new(big.Int).SetString(amountStr,10)
if!ok{
fmt.Println("Invalidamount")
return
}

//构建TRC20transfer函数调用数据
data

转载请注明出处: TronLink官网下载-TRON-TRX-波场-波比-波币-波宝|官网-钱包-苹果APP|安卓-APP-下载

本文的链接地址: https://tianjinfa.org/post/3129


扫描二维码,在手机上阅读


    TronLink TronLink 官网 TronLink 下载 TronLink 钱包 波场 TRON TRX 波币 波比 波宝 波场钱包 苹果 APP 下载 安卓 APP 下载 数字货币钱包 区块链钱包 去中心化钱包 数字资产管理 加密货币存储 波场生态 TRC-20 代币 TRC-10 代币 波场 DApp 波场智能合约 钱包安全 私钥管理 钱包备份 钱包恢复 多账户管理 代币转账 波场超级代表 波场节点 波场跨链 波场 DeFi 波场 NFT 波场测试网 波场开发者 钱包教程 新手入门 钱包使用指南 波场交易手续费 波场价格 波场行情 波场生态合作 波场应用 波场质押 波场挖矿 波场冷钱包 硬件钱包连接 波场钱包对比 波场钱包更新 波场链上数据 TronLink 官网下载 TronLink 安卓 APP TronLink 苹果 APP TRON 区块链 TRX 下载 TRX 交易 波场官方 波场钱包下载 波比钱包 波币官网 波宝钱包 APP 波宝钱包下载 波场 TRC20 代币 波场 TRC10 代币 波场 TRC721 代币 波场 DApp 浏览器 波场去中心化应用 TronLink 钱包安全 TronLink 钱包教程 TronLink 私钥管理 TronLink 多账户管理 TronLink 交易手续费 波场超级代表投票 波场去中心化存储 波场跨链交易 波场 DeFi 应用 波场 NFT 市场 波场质押挖矿 波场钱包备份 波场钱包恢复 波场硬件钱包连接 波场开发者工具 波场节点搭建 波场钱包使用指南 波场代币转账 波场钱包创建 波场钱包导入 波场 DApp 推荐 波场 TRX 价格走势 波场生态发展 TronLink 钱包更新 波场链上数据查询 波场钱包安全防护 波场钱包对比评测 TronLink钱包下载