123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- package tron2
- import (
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "math/big"
- "net/http"
- "strconv"
- "strings"
- "time"
- "github.com/JFJun/trx-sign-go/grpcs"
- "github.com/JFJun/trx-sign-go/sign"
- "github.com/btcsuite/btcd/btcec"
- addr "github.com/fbsobreira/gotron-sdk/pkg/address"
- "github.com/fbsobreira/gotron-sdk/pkg/client"
- "github.com/fbsobreira/gotron-sdk/pkg/common"
- "github.com/fbsobreira/gotron-sdk/pkg/proto/core"
- "github.com/google/uuid"
- "github.com/sirupsen/logrus"
- "github.com/spf13/viper"
- "google.golang.org/grpc"
- )
- type GenAddressInfo struct {
- Seed string
- Addr string
- PrvKey string
- }
- func GenAddressBySeed() (*GenAddressInfo, error) {
- uuid := uuid.New()
- seed := uuid.String()
- seed = strings.Replace(seed, "-", "", -1)
- if len(seed) != 32 {
- return nil, fmt.Errorf("seed len=[%d] is not equal 32", len(seed))
- }
- priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), []byte(seed))
- if priv == nil {
- return nil, errors.New("priv is nil ptr")
- }
- a := addr.PubkeyToAddress(priv.ToECDSA().PublicKey)
- addrInfo := GenAddressInfo{
- Seed: seed,
- Addr: a.String(),
- PrvKey: priv.D.Text(16),
- }
- return &addrInfo, nil
- }
- type txInfoItem struct {
- TransactionID string `json:"transaction_id"`
- BlockTimestamp int64 `json:"block_timestamp"`
- From string `json:"from"`
- To string `json:"to"`
- Type string `json:"type"`
- Value string `json:"value"`
- }
- var rpcClient *grpcs.Client
- func getClient() (*grpcs.Client, error) {
- if rpcClient != nil {
- return rpcClient, nil
- }
- grpcHost := viper.GetString("tron.grpcHost")
- if grpcHost == "" {
- grpcHost = "grpc.trongrid.io:50051"
- }
- c := new(grpcs.Client)
- //c.node = node
- c.GRPC = client.NewGrpcClient(grpcHost)
- err := c.GRPC.Start(grpc.WithInsecure())
- if err != nil {
- return nil, fmt.Errorf("grpc client start error: %v", err)
- }
- // c, err := grpcs.NewClient(grpcHost)
- // if err != nil {
- // logrus.Error(err)
- // return nil, err
- // }
- rpcClient = c
- return c, err
- }
- func TransferTrx(from string, to string, amount int64, key string) (bool, string) {
- c, err := getClient()
- if err != nil {
- fmt.Println(err)
- }
- tx, err := c.Transfer(from, to, amount)
- if err != nil {
- fmt.Println(err)
- return false, ""
- }
- signTx, err := sign.SignTransaction(tx.Transaction, key)
- if err != nil {
- fmt.Println(err)
- return false, ""
- }
- err = c.BroadcastTransaction(signTx)
- if err != nil {
- fmt.Println(err)
- return false, ""
- }
- return true, common.BytesToHexString(tx.GetTxid())
- }
- func TransferTrc20(contractAddress string, from string, to string, amount int64, key string) (bool, string, *core.Transaction) {
- if len(key) != 64 {
- logrus.Error("key not valid:", len(key), "!=64")
- return false, "", nil
- }
- // grpcHost := viper.GetString("tron.grpcHost")
- c, err := getClient()
- if err != nil {
- logrus.Error(err)
- return false, "", nil
- }
- amountBig := big.NewInt(amount)
- tx, err := c.TransferTrc20(from, to, contractAddress, amountBig, 10000000)
- if err != nil {
- logrus.Error(err)
- return false, "", nil
- }
- signTx, err := sign.SignTransaction(tx.Transaction, key)
- if err != nil {
- logrus.Error(err)
- return false, "", nil
- }
- // err = c.BroadcastTransaction(signTx)
- // if err != nil {
- // fmt.Println(err)
- // return false, nil
- // }
- return true, common.BytesToHexString(tx.GetTxid()), signTx
- }
- func BroadcastTransaction(signTx *core.Transaction) error {
- c, err := getClient()
- if err != nil {
- logrus.Error(err)
- return err
- }
- return c.BroadcastTransaction(signTx)
- }
- func GetBalance(addr string) (int64, error) {
- c, err := getClient()
- if err != nil {
- return 0, err
- }
- acc, err := c.GetTrxBalance(addr)
- if err != nil {
- return 0, err
- }
- // d, _ := json.Marshal(acc)
- // fmt.Println(string(d))
- return acc.GetBalance(), nil
- }
- func GetTrc20BalanceByHash(hash string) (int64, error) {
- type HashInfoResp struct {
- Block int64 `json:"block"`
- Confirmed bool `json:"confirmed"`
- Revert bool `json:"revert"`
- ContractRet string `json:"contractRet"`
- ContractData struct {
- Amount int `json:"amount"`
- OwnerAddress string `json:"owner_address"`
- ToAddress string `json:"to_address"`
- } `json:"contractData"`
- Trc20TransferInfo []struct {
- IconURL string `json:"icon_url"`
- Symbol string `json:"symbol"`
- Level string `json:"level"`
- Decimals int `json:"decimals"`
- Name string `json:"name"`
- ToAddress string `json:"to_address"`
- ContractAddress string `json:"contract_address"`
- Type string `json:"type"`
- Vip bool `json:"vip"`
- TokenType string `json:"tokenType"`
- FromAddress string `json:"from_address"`
- AmountStr string `json:"amount_str"`
- } `json:"trc20TransferInfo"`
- }
- reqUrl := "https://apilist.tronscan.org/api/transaction-info?hash=" + hash + "&t=" + fmt.Sprintf("%d", time.Now().Unix())
- logrus.Info("req url:", reqUrl)
- res, err := http.Get(reqUrl)
- if err != nil {
- logrus.Error(err)
- return 0, err
- }
- body, err := ioutil.ReadAll(res.Body)
- if err != nil {
- logrus.Error(err)
- return 0, err
- }
- defer res.Body.Close()
- hashResp := HashInfoResp{}
- err = json.Unmarshal(body, &hashResp)
- if err != nil {
- logrus.Error(err, string(body))
- return 0, err
- }
- if hashResp.Block == 0 {
- logrus.Error("block id未生效:", string(body))
- return 0, errors.New("not valid")
- }
- if hashResp.ContractRet != "SUCCESS" {
- return 0, errors.New("transfer failed")
- }
- if !hashResp.Confirmed {
- return 0, errors.New("not confirm")
- }
- if len(hashResp.Trc20TransferInfo) != 1 {
- return 0, errors.New("data not valid")
- }
- val, err := strconv.ParseInt(hashResp.Trc20TransferInfo[0].AmountStr, 10, 64)
- if err != nil {
- return 0, err
- }
- return val, nil
- }
- func GetTrc20Balance(addr string, contractAddress string) (int64, error) {
- c, err := getClient()
- if err != nil {
- return 0, err
- }
- amount, err := c.GetTrc20Balance(addr, contractAddress)
- if err != nil {
- return 0, err
- }
- val, err := strconv.ParseInt(amount.String(), 10, 64)
- if err != nil {
- return 0, err
- }
- return val, nil
- }
- func IsTransactionSucc_(txid string) (bool, error) {
- c, err := getClient()
- if err != nil {
- logrus.Error(err)
- return false, err
- }
- txInfo, err := c.GRPC.GetTransactionByID(txid)
- if err != nil {
- logrus.Error(err)
- return false, err
- }
- if len(txInfo.Ret) == 0 {
- //半小时也没有,认为失败
- if txInfo.GetRawData().Timestamp-time.Now().Unix() > 30*60 {
- return false, nil
- }
- logrus.Error("len(txInfo.Ret) == 0")
- return false, errors.New("no result")
- }
- if txInfo.Ret[0].ContractRet == core.Transaction_Result_DEFAULT {
- return false, errors.New("wait contract result")
- }
- return txInfo.Ret[0].Ret == core.Transaction_Result_SUCESS && txInfo.Ret[0].ContractRet == core.Transaction_Result_SUCCESS,
- nil
- }
- func IsTransactionSucc(hash string) (bool, error) {
- c, err := getClient()
- if err != nil {
- logrus.Error(err)
- return false, err
- }
- body, err := c.GRPC.GetTransactionInfoByID(hash)
- if err != nil {
- logrus.Error(err)
- return false, err
- }
- switch body.Receipt.GetResult().String() {
- case "SUCCESS":
- return true, nil
- case "REVERT":
- return false, nil
- default:
- return false, errors.New("no result")
- }
- }
- func CheckToComtainSince(addr string, val int64, since int64) (bool, string, error) {
- fp := ""
- for {
- his, retfp, err := GetTxHistoryByAddr(addr, fp, 20)
- if err != nil {
- fmt.Println(err)
- return false, "", err
- }
- if len(his) == 0 {
- break
- }
- for _, info := range his {
- if info.BlockTimestamp < since {
- continue
- }
- value, err := strconv.ParseInt(info.Value, 10, 64)
- if err != nil {
- fmt.Println(err)
- continue
- }
- if value != val {
- continue
- }
- return true, info.From, nil
- }
- if retfp == "" {
- break
- }
- fp = retfp
- }
- return false, "", nil
- }
- func GetTxHistoryByAddr(addr string, fingerprint string, limit int) ([]txInfoItem, string, error) {
- apiHost := viper.GetString("tron.apiHost")
- contractAddr := viper.GetString("contractaddr")
- if contractAddr == "" {
- logrus.Fatal("contractaddr is empty")
- return nil, "", errors.New("contractaddr is empty")
- }
- reqUrl := fmt.Sprintf(`https://%s/v1/accounts/%s/transactions/trc20?limit=%d&contract_address=%s&only_confirmed=true&only_to=true&order_by=block_timestamp,desc`,
- apiHost, addr, limit, contractAddr)
- logrus.Info("reqUrl:", reqUrl)
- if fingerprint != "" {
- reqUrl = reqUrl + "&fingerprint=" + fingerprint
- }
- resp, err := http.Get(reqUrl)
- if err != nil {
- logrus.Error(err, " ", reqUrl)
- return nil, "", err
- }
- type Meta struct {
- Fingerprint string `json:"fingerprint"`
- }
- type DataInfo struct {
- Data []txInfoItem `json:"data"`
- Meta Meta `json:"meta"`
- }
- dataInfo := DataInfo{}
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- logrus.Error(err, " ", reqUrl)
- return nil, "", err
- }
- defer resp.Body.Close()
- err = json.Unmarshal(body, &dataInfo)
- if err != nil {
- logrus.Error(err, " ", reqUrl)
- return nil, "", err
- }
- if dataInfo.Data == nil {
- return nil, "", errors.New(string(body))
- }
- resultList := make([]txInfoItem, 0)
- for _, item := range dataInfo.Data {
- if item.Type != "Transfer" {
- continue
- }
- resultList = append(resultList, item)
- }
- return resultList, dataInfo.Meta.Fingerprint, nil
- }
|