使用Go语言实现TronLink钱包功能-完整指南
使用Go语言实现TronLink钱包功能-完整指南
本文将详细介绍如何使用Go语言实现类似TronLink钱包的核心功能,包括账户创建、TRX转账、TRC20代币操作等。所有代码均为原创实现,适合区块链开发者和Go语言爱好者学习参考。
什么是TronLink钱包?
TronLink是波场(TRON)区块链上最受欢迎的钱包之一,它允许用户安全地存储、发送和接收TRX及TRC20代币,并与DApp交互。我们将使用Go语言实现其核心功能。
开发环境准备
在开始之前,请确保已安装:
-Go1.16+
-Git
-一个代码编辑器(如VSCode)
项目结构
tron-wallet-go/
├──cmd/
│└──main.go
├──internal/
│├──wallet/
││├──account.go
││├──transaction.go
││└──trc20.go
│└──utils/
│└──crypto.go
├──go.mod
└──go.sum
核心代码实现
1.账户管理(account.go)
packagewallet
import(
"crypto/ecdsa"
"encoding/hex"
"fmt"
"log"
"github.com/btcsuite/btcd/btcec"
"github.com/ethereum/go-ethereum/crypto"
"github.com/fbsobreira/gotron-sdk/pkg/address"
"github.com/fbsobreira/gotron-sdk/pkg/common"
)
//Account表示一个波场钱包账户
typeAccountstruct{
PrivateKeyecdsa.PrivateKey
Addressstring
}
//NewAccount创建一个新的波场账户
funcNewAccount()(Account,error){
privateKey,err:=crypto.GenerateKey()
iferr!=nil{
returnnil,fmt.Errorf("生成私钥失败:%v",err)
}
return&Account{
PrivateKey:privateKey,
Address:getAddressFromPrivateKey(privateKey),
},nil
}
//FromPrivateKey从私钥字符串导入账户
funcFromPrivateKey(privateKeyHexstring)(Account,error){
privateKeyBytes,err:=hex.DecodeString(privateKeyHex)
iferr!=nil{
returnnil,fmt.Errorf("解码私钥失败:%v",err)
}
privateKey,_:=btcec.PrivKeyFromBytes(btcec.S256(),privateKeyBytes)
ecdsaPrivateKey:=privateKey.ToECDSA()
return&Account{
PrivateKey:ecdsaPrivateKey,
Address:getAddressFromPrivateKey(ecdsaPrivateKey),
},nil
}
//getAddressFromPrivateKey从私钥获取波场地址
funcgetAddressFromPrivateKey(privateKeyecdsa.PrivateKey)string{
pubKey:=privateKey.PublicKey
pubKeyBytes:=crypto.FromECDSAPub(&pubKey)
//波场地址以41开头
tronPubKey:=append([]byte{0x41},crypto.Keccak256(pubKeyBytes[1:])[12:]...)
returnaddress.Address(tronPubKey).String()
}
//GetPrivateKeyHex获取16进制格式的私钥
func(aAccount)GetPrivateKeyHex()string{
returnhex.EncodeToString(crypto.FromECDSA(a.PrivateKey))
}
//ValidateAddress验证波场地址是否有效
funcValidateAddress(addrstring)bool{
_,err:=address.Base58ToAddress(addr)
returnerr==nil
}
2.TRX转账(transaction.go)
packagewallet
import(
"context"
"fmt"
"math/big"
"time"
"github.com/fbsobreira/gotron-sdk/pkg/client"
"github.com/fbsobreira/gotron-sdk/pkg/proto/api"
"github.com/fbsobreira/gotron-sdk/pkg/proto/core"
"google.golang.org/grpc"
)
const(
trxDecimals=6
grpcTimeout=10time.Second
)
//TronClient封装波场GRPC客户端
typeTronClientstruct{
client.GrpcClient
}
//NewTronClient创建新的波场客户端连接
funcNewTronClient(endpointstring)(TronClient,error){
conn:=client.NewGrpcClient(endpoint)
iferr:=conn.Start(grpc.WithInsecure());err!=nil{
returnnil,fmt.Errorf("连接波场节点失败:%v",err)
}
return&TronClient{conn},nil
}
//SendTRX发送TRX交易
func(tcTronClient)SendTRX(fromAccount,toAddressstring,amountfloat64)(string,error){
//验证接收地址
if!ValidateAddress(toAddress){
return"",fmt.Errorf("无效的接收地址")
}
//转换金额为sun单位(1TRX=1,000,000sun)
amountSun:=big.NewInt(int64(amount1e6))
ctx,cancel:=context.WithTimeout(context.Background(),grpcTimeout)
defercancel()
//创建交易
tx,err:=tc.Transfer(from.Address,toAddress,amountSun.Uint64())
iferr!=nil{
return"",fmt.Errorf("创建交易失败:%v",err)
}
//签名交易
signedTx,err:=tc.SignTransaction(tx,from.PrivateKey)
iferr!=nil{
return"",fmt.Errorf("签名交易失败:%v",err)
}
//广播交易
result,err:=tc.Broadcast(ctx,signedTx)
iferr!=nil{
return"",fmt.Errorf("广播交易失败:%v",err)
}
ifresult.Code!=api.Return_SUCCESS{
return"",fmt.Errorf("交易失败:%s",result.String())
}
returnhex.EncodeToString(tx.GetTxid()),nil
}
//GetBalance获取TRX余额
func(tcTronClient)GetBalance(addressstring)(float64,error){
ctx,cancel:=context.WithTimeout(context.Background(),grpcTimeout)
defercancel()
acc,err:=tc.GetAccount(address)
iferr!=nil{
return0,fmt.Errorf("获取账户信息失败:%v",err)
}
returnfloat64(acc.Balance)/1e6,nil
}
//SignTransaction签名交易
func(tcTronClient)SignTransaction(txcore.Transaction,privKeyecdsa.PrivateKey)(core.Transaction,error){
returnclient.SignTransaction(tx,privKey)
}
3.TRC20代币操作(trc20.go)
packagewallet
import(
"context"
"encoding/hex"
"fmt"
"math/big"
"strings"
"time"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/fbsobreira/gotron-sdk/pkg/client"
"github.com/fbsobreira/gotron-sdk/pkg/proto/api"
"github.com/fbsobreira/gotron-sdk/pkg/proto/core"
"google.golang.org/grpc"
)
//TRC20Contract表示TRC20代币合约
typeTRC20Contractstruct{
ContractAddressstring
Decimalsint
Symbolstring
clientTronClient
}
//NewTRC20Contract创建TRC20合约实例
funcNewTRC20Contract(clientTronClient,contractAddressstring)(TRC20Contract,error){
contract:=&TRC20Contract{
ContractAddress:contractAddress,
client:client,
}
//获取代币信息
decimals,err:=contract.GetDecimals()
iferr!=nil{
returnnil,fmt.Errorf("获取代币精度失败:%v",err)
}
contract.Decimals=int(decimals)
symbol,err:=contract.GetSymbol()
iferr!=nil{
returnnil,fmt.Errorf("获取代币符号失败:%v",err)
}
contract.Symbol=symbol
returncontract,nil
}
//GetSymbol获取代币符号
func(cTRC20Contract)GetSymbol()(string,error){
data,err:=packFunctionCall("symbol()",nil)
iferr!=nil{
return"",err
}
result,err:=c.triggerConstantContract(data)
iferr!=nil{
return"",err
}
//解码结果
varsymbolstring
outputs:=[]interface{}{&symbol}
err=unpackFunctionResult("symbol()",result,outputs)
iferr!=nil{
return"",err
}
returnsymbol,nil
}
//GetDecimals获取代币精度
func(cTRC20Contract)GetDecimals()(uint8,error){
data,err:=packFunctionCall("decimals()",nil)
iferr!=nil{
return0,err
}
result,err:=c.triggerConstantContract(data)
iferr!=nil{
return0,err
}
//解码结果
vardecimalsuint8
outputs:=[]interface{}{&decimals}
err=unpackFunctionResult("decimals()",result,outputs)
iferr!=nil{
return0,err
}
returndecimals,nil
}
//GetBalance获取代币余额
func(cTRC20Contract)GetBalance(addressstring)(big.Int,error){
method:="balanceOf(address)"
params:=[]interface{}{common.HexToAddress(address)}
data,err:=packFunctionCall(method,params)
iferr!=nil{
returnnil,err
}
result,err:=c.triggerConstantContract(data)
iferr!=nil{
returnnil,err
}
//解码结果
balance:=new(big.Int)
outputs:=[]interface{}{balance}
err=unpackFunctionResult(method,result,outputs)
iferr!=nil{
returnnil,err
}
returnbalance,nil
}
//Transfer发送TRC20代币
func(cTRC20Contract)Transfer(fromAccount,toAddressstring,amountbig.Int)(string,error){
method:="transfer(address,uint256)"
params:=[]interface{}{
common.HexToAddress(toAddress),
amount,
}
data,err:=packFunctionCall(method,params)
iferr!=nil{
return"",err
}
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()
//创建触发智能合约交易
tx,err:=c.client.TriggerConstantContract(
from.Address,
c.ContractAddress,
data,
)
iferr!=nil{
return"",fmt.Errorf("创建交易失败:%v",err)
}
//签名交易
signedTx,err:=c.client.SignTransaction(tx,from.PrivateKey)
iferr!=nil{
return"",fmt.Errorf("签名交易失败:%v",err)
}
//广播交易
result,err:=c.client.Broadcast(ctx,signedTx)
iferr!=nil{
return"",fmt.Errorf("广播交易失败:%v",err)
}
ifresult.Code!=api.Return_SUCCESS{
return"",fmt.Errorf("交易失败:%s",result.String())
}
returnhex.EncodeToString(tx.GetTxid()),nil
}
//triggerConstantContract调用合约的constant方法
func(cTRC20Contract)triggerConstantContract(data[]byte)([]byte,error){
ctx,cancel:=context.WithTimeout(context.Background(),10time.Second)
defercancel()
result,err:=c.client.TriggerConstantContract(
"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",//使用任意地址
c.ContractAddress,
data,
)
iferr!=nil{
returnnil,err
}
ifresult.ConstantResult==nil||len(result.ConstantResult)==0{
returnnil,fmt.Errorf("没有返回数据")
}
returnresult.ConstantResult[0],nil
}
//packFunctionCall打包函数调用数据
funcpackFunctionCall(methodstring,params[]interface{})([]byte,error){
abi,err:=abi.JSON(strings.NewReader(trc20ABI))
iferr!=nil{
returnnil,err
}
returnabi.Pack(method,params...)
}
//unpackFunctionResult解包函数返回数据
funcunpackFunctionResult(methodstring,data[]byte,outputs[]interface{})error{
abi,err:=abi.JSON(strings.NewReader(trc20ABI))
iferr!=nil{
returnerr
}
returnabi.UnpackIntoInterface(outputs[0],method,data)
}
//TRC20ABI定义
consttrc20ABI=`[{
"constant":true,
"inputs":[],
"name":"symbol",
"outputs":[{"name":"","type":"string"}],
"payable":false,
"stateMutability":"view",
"type":"function"
},{
"constant":true,
"inputs":[],
"name":"decimals",
"outputs":[{"name":"","type":"uint8"}],
"payable":false,
"stateMutability":"view",
"type":"function"
},{
"constant":true,
"inputs":[{"name":"_owner","type":"address"}],
"name":"balanceOf",
"outputs":[{"name":"balance","type":"uint256"}],
"payable":false,
"stateMutability":"view",
"type":"function"
},{
"constant":false,
"inputs":[
{"name":"_to","type":"address"},
{"name":"_value","type":"uint256"}
],
"name":"transfer",
"outputs":[{"name":"","type":"bool"}],
"payable":false,
"stateMutability":"nonpayable",
"type":"function"
}]`
4.主程序(main.go)
packagemain
import(
"fmt"
"log"
"math/big"
"os"
"github.com/urfave/cli/v2"
"tron-wallet-go/internal/wallet"
)
funcmain(){
app:=&cli.App{
Name:"TronWalletCLI",
Usage:"Acommand-lineinterfaceforTronwalletoperations",
Commands:[]cli.Command{
{
Name:"create",
Usage:"CreateanewTronwallet",
Action:func(ccli.Context)error{
account,err:=wallet.NewAccount()
iferr!=nil{
returnerr
}
fmt.Println("NewTronwalletcreated:")
fmt.Printf("Address:%s\n",account.Address)
fmt.Printf("PrivateKey:%s\n",account.GetPrivateKeyHex())
fmt.Println("\nIMPORTANT:Keepyourprivatekeysecureandnevershareitwithanyone!")
returnnil
},
},
{
Name:"balance",
Usage:"CheckTRXorTRC20tokenbalance",
Flags:[]cli.Flag{
&cli.StringFlag{
Name:"address",
Usage:"Tronaddresstocheckbalance",
Required:true,
},
&cli.StringFlag{
Name:"contract",
Usage:"TRC20contractaddress(fortokenbalance)",
},
},
Action:func(ccli.Context)error{
address:=c.String("address")
contractAddress:=c.String("contract")
client,err:=wallet.NewTronClient("grpc.trongrid.io:50051")
iferr!=nil{
returnerr
}
ifcontractAddress==""{
//TRXbalance
balance,err:=client.GetBalance(address)
iferr!=nil{
returnerr
}
fmt.Printf("TRXBalance:%.6f\n",balance)
}else{
//TRC20tokenbalance
contract,err:=wallet.NewTRC20Contract(client,contractAddress)
iferr!=nil{
returnerr
}
balance,err:=contract.GetBalance(address)
iferr!=nil{
returnerr
}
decimals:=big.NewInt(10)
decimals.Exp(decimals,big.NewInt(int64(contract.Decimals)),nil)
balanceFloat:=new(big.Float).SetInt(balance)
decimalsFloat:=new(big.Float).SetInt(decimals)
balanceFloat.Quo(balanceFloat,decimalsFloat)
fmt.Printf("%sBalance:%s\n",contract.Symbol,balanceFloat.String())
}
returnnil
},
},
{
Name:"send",
Usage:"SendTRXorTRC20tokens",
Flags:[]cli.Flag{
&cli.StringFlag{
Name:"from",
Usage:"Senderprivatekey",
Required:true,
},
&cli.StringFlag{
Name:"to",
Usage:"Recipientaddress",
Required:true,
},
&cli.Float64Flag{
Name:"amount",
Usage:"Amounttosend",
Required:true,
},
&cli.StringFlag{
Name:"contract",
Usage:"TRC20contractaddress(fortokentransfer)",
},
},
Action:func(ccli.Context)error{
fromKey:=c.String("from")
toAddress:=c.String("to")
amount:=c.Float64("amount")
contractAddress:=c.String("contract")
//从私钥导入账户
account,err:=wallet.FromPrivateKey(fromKey)
转载请注明出处: TronLink官网下载-TRON-TRX-波场-波比-波币-波宝|官网-钱包-苹果APP|安卓-APP-下载
本文的链接地址: https://tianjinfa.org/post/3076
扫描二维码,在手机上阅读
文章作者:
文章标题:使用Go语言实现TronLink钱包功能-完整指南
文章链接:https://tianjinfa.org/post/3076
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明来自 !
文章标题:使用Go语言实现TronLink钱包功能-完整指南
文章链接:https://tianjinfa.org/post/3076
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明来自 !
打赏
如果觉得文章对您有用,请随意打赏。
您的支持是我们继续创作的动力!
微信扫一扫
支付宝扫一扫
您可能对以下文章感兴趣
-
使用JavaScript开发TRONLink钱包集成指南
7小时前
-
你好!😊你想聊些什么呢?有什么我可以帮你的吗?
8小时前
-
你好!😊你想问什么呢?有什么我可以帮你的吗?
8小时前
-
TronLink钱包集成指南:使用JavaScript连接TRON区块链
12小时前
-
TronLink钱包Web版实现(无MySQL)
6小时前
-
TronLink钱包HTML5实现教程
7小时前
-
TronLink钱包集成开发指南
7小时前
-
TronLink钱包集成开发指南
7小时前
-
使用Go语言构建TronLink风格的钱包应用
7小时前
-
TronLink钱包简易实现(PHP+CSS+JS+HTML5+JSON)
7小时前