github.com/fff-chain/go-fff@v0.0.0-20220726032732-1c84420b8a99/global_config/wallet/wallet.go (about)

     1  package wallet
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"github.com/fff-chain/go-fff/accounts/abi/bind"
     7  	"github.com/fff-chain/go-fff/common"
     8  	"github.com/fff-chain/go-fff/common/hexutil"
     9  	math2 "github.com/fff-chain/go-fff/common/math"
    10  	"github.com/fff-chain/go-fff/core/types"
    11  	"github.com/fff-chain/go-fff/crypto"
    12  	"github.com/fff-chain/go-fff/ethclient"
    13  	"github.com/fff-chain/go-fff/global_config"
    14  	"github.com/fff-chain/go-fff/global_config/token"
    15  	"log"
    16  	"math/big"
    17  	"time"
    18  )
    19  
    20  var WEI = math2.BigPow(10, 9)
    21  
    22  type Wallet struct {
    23  	CurrClient *ethclient.Client
    24  	RpcUrl     string
    25  	RpcUrl2    string
    26  }
    27  
    28  func Init(RpcUrl string, RpcUrl2 string) *Wallet {
    29  	newl := new(Wallet)
    30  	newl.RpcUrl = RpcUrl
    31  	newl.RpcUrl2 = RpcUrl2
    32  	client, err := ethclient.Dial(RpcUrl)
    33  	if err != nil || GetClientChainId(client) == 0 {
    34  		log.Println("无法连接", RpcUrl, err, "等待五秒后重连")
    35  		time.Sleep(time.Second * 5)
    36  		client, err := ethclient.Dial(RpcUrl2)
    37  		if err != nil || GetClientChainId(client) == 0 {
    38  			log.Println("无法连接", RpcUrl2, err, "等待五秒后重连")
    39  			time.Sleep(time.Second * 5)
    40  			return Init(RpcUrl, RpcUrl2)
    41  		} else {
    42  			newl.CurrClient = client
    43  			return newl
    44  		}
    45  	} else {
    46  		newl.CurrClient = client
    47  		return newl
    48  	}
    49  }
    50  func (this *Wallet) ReInit() {
    51  	for {
    52  		client, err := ethclient.Dial(this.RpcUrl)
    53  		if err != nil || GetClientChainId(client) == 0 {
    54  			log.Println("无法连接", this.RpcUrl, err, "等待五秒后重连")
    55  			time.Sleep(time.Second * 5)
    56  			client, err := ethclient.Dial(this.RpcUrl2)
    57  			if err != nil || GetClientChainId(client) == 0 {
    58  				log.Println("无法连接", this.RpcUrl2, err, "等待五秒后重连")
    59  				time.Sleep(time.Second * 5)
    60  			} else {
    61  				this.CurrClient = client
    62  				return
    63  			}
    64  		} else {
    65  			this.CurrClient = client
    66  			return
    67  		}
    68  	}
    69  
    70  }
    71  func GetClientChainId(c *ethclient.Client) int64 {
    72  	if c == nil {
    73  		return 0
    74  	}
    75  
    76  	chainIdInt, err := c.ChainID(context.Background())
    77  	if err != nil {
    78  		log.Println(err)
    79  		return 0
    80  	}
    81  	return chainIdInt.Int64()
    82  }
    83  func (this *Wallet) GetMiniBalance() float64 {
    84  	gasLimit := uint64(21000)
    85  
    86  	gasPrice, err2 := this.CurrClient.SuggestGasPrice(context.Background())
    87  
    88  	if err2 != nil {
    89  		gasPrice = big.NewInt(100)
    90  	}
    91  	count := new(big.Int).Mul(big.NewInt(int64(gasLimit)), gasPrice)
    92  	return global_config.WeiToEth(count)
    93  
    94  }
    95  func FloatToWei(f float64) *big.Int {
    96  
    97  	weiCount := 18
    98  
    99  	beth := math2.BigPow(10, int64(weiCount))
   100  
   101  	rs := new(big.Float).Mul(big.NewFloat(f), new(big.Float).SetInt(beth))
   102  
   103  	w := big.NewInt(0)
   104  
   105  	rs.Int(w)
   106  
   107  	return w
   108  
   109  }
   110  func NewAddress() (pri string, pub string) {
   111  	privateKey, err := crypto.GenerateKey()
   112  	if err != nil {
   113  		log.Println(err)
   114  		return "", ""
   115  	}
   116  	privateKeyBytes := crypto.FromECDSA(privateKey)
   117  	key := hexutil.Encode(privateKeyBytes)[2:]
   118  	return key, GetPublicAddressFromKey(key)
   119  }
   120  
   121  func GetPublicAddressFromKey(userKey string) string {
   122  	priKeyECD, err := crypto.HexToECDSA(userKey)
   123  	if err != nil {
   124  		log.Println("私钥异常")
   125  		return ""
   126  	}
   127  
   128  	publicKeyECDSA, ok := priKeyECD.Public().(*ecdsa.PublicKey)
   129  	if !ok {
   130  		log.Println("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
   131  		return ""
   132  	}
   133  	address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
   134  	if err != nil {
   135  		log.Println("私钥异常")
   136  		return ""
   137  	}
   138  
   139  	return address
   140  
   141  }
   142  func (this *Wallet) GetTokenBalance(tokenAddress string, own string) *big.Int {
   143  
   144  	transtBnB, err := token.NewBEP20TokenCaller(common.HexToAddress(tokenAddress), this.CurrClient)
   145  	if err != nil {
   146  		return nil
   147  	}
   148  	currBnb, err := transtBnB.BalanceOf(nil, common.HexToAddress(own))
   149  	if err != nil {
   150  		return nil
   151  	}
   152  	return currBnb
   153  
   154  }
   155  func (this *Wallet) TransferToken(pri string, tokenAddress string, toAddress string, count *big.Int) string {
   156  	transt, err := token.NewBEP20TokenTransactor(common.HexToAddress(tokenAddress), this.CurrClient)
   157  
   158  	if err == nil {
   159  		priKeyECD, err := crypto.HexToECDSA(pri)
   160  
   161  		if err != nil {
   162  			log.Println("私钥异常")
   163  			return ""
   164  		}
   165  		chianId, err := this.CurrClient.ChainID(context.Background())
   166  		if err != nil {
   167  			log.Println("节点chianId异常", err)
   168  			return ""
   169  		}
   170  		param, err := bind.NewKeyedTransactorWithChainID(priKeyECD, chianId)
   171  		if err != nil {
   172  			log.Println("节点Transactor异常", err)
   173  			return ""
   174  		}
   175  		param.GasPrice, err = this.CurrClient.SuggestGasPrice(context.Background())
   176  		if err != nil {
   177  			log.Println("GAS异常", err)
   178  		}
   179  
   180  		if param.GasPrice == nil {
   181  			param.GasPrice = big.NewInt(1000000000)
   182  		}
   183  
   184  		if param.GasPrice.Cmp(big.NewInt(1000000000)) < 0 {
   185  			param.GasPrice = big.NewInt(1000000000)
   186  		}
   187  		log.Println("当前gas:", param.GasPrice)
   188  
   189  		param.GasLimit = uint64(8000000)
   190  		nonce, err := this.CurrClient.PendingNonceAt(context.Background(), common.HexToAddress(GetPublicAddressFromKey(pri)))
   191  		if err != nil {
   192  			log.Println("节点异常")
   193  			return ""
   194  		}
   195  		param.Nonce = big.NewInt(int64(nonce))
   196  
   197  		ts, err := transt.Transfer(param, common.HexToAddress(toAddress), count) //转账代币
   198  
   199  		if err != nil {
   200  			log.Println("转账代币异常")
   201  			return ""
   202  		}
   203  		return ts.Hash().Hex()
   204  
   205  	} else {
   206  		log.Println("节点异常")
   207  		return ""
   208  	}
   209  }
   210  func (this *Wallet) Transfer(privateKey string, toAddress string, count *big.Int, transData string, gasP int64) string {
   211  
   212  	if this.CurrClient == nil {
   213  		return ""
   214  	}
   215  
   216  	priviteKey, err := crypto.HexToECDSA(privateKey)
   217  
   218  	publicAddress := GetPublicAddressFromKey(privateKey)
   219  
   220  	if len(publicAddress) == 0 {
   221  		return ""
   222  	}
   223  
   224  	if err != nil {
   225  		log.Println("chanid err", err)
   226  		return ""
   227  	}
   228  
   229  	nonce, err := this.CurrClient.PendingNonceAt(context.Background(), common.HexToAddress(publicAddress))
   230  	if err != nil {
   231  		log.Println("err", err)
   232  		return ""
   233  	}
   234  	gasLimit := uint64(21000)
   235  
   236  	gasPrice, err2 := this.CurrClient.SuggestGasPrice(context.Background())
   237  
   238  	if err2 != nil {
   239  		log.Println("err", err2)
   240  		return ""
   241  	}
   242  
   243  	if gasP > 0 {
   244  		gasPrice = new(big.Int).Mul(big.NewInt(int64(gasP)), math2.BigPow(10, 9))
   245  	}
   246  
   247  	count = new(big.Int).Sub(count, new(big.Int).Mul(big.NewInt(int64(gasLimit)), gasPrice))
   248  	data := []byte(transData)
   249  
   250  	newTrans := types.NewTransaction(nonce, common.HexToAddress(toAddress), count, gasLimit, gasPrice, data)
   251  
   252  	chainID, err := this.CurrClient.ChainID(context.Background())
   253  	if err != nil {
   254  		log.Println("chanid err", err)
   255  		return ""
   256  	}
   257  
   258  	signer := types.NewEIP155Signer(chainID)
   259  
   260  	signTx, err := types.SignTx(newTrans, signer, priviteKey)
   261  
   262  	if err != nil {
   263  		log.Println("sign err", err)
   264  		return ""
   265  	}
   266  
   267  	errTrans := this.CurrClient.SendTransaction(context.Background(), signTx)
   268  
   269  	if errTrans != nil {
   270  		log.Println("err", errTrans)
   271  
   272  		return ""
   273  	}
   274  	return signTx.Hash().String()
   275  }
   276  func (this *Wallet) GetBalance(address string) *big.Int {
   277  	if this.CurrClient == nil {
   278  		return nil
   279  	}
   280  	b, err := this.CurrClient.BalanceAt(context.Background(), common.HexToAddress(address), nil)
   281  
   282  	if err != nil || b == nil {
   283  		return nil
   284  	}
   285  	return b
   286  
   287  }
   288  func (this *Wallet) GetChainId() int64 {
   289  	chainID, err := this.CurrClient.NetworkID(context.Background())
   290  	if err != nil {
   291  		log.Println("chanid err", err)
   292  		return 0
   293  	}
   294  	return chainID.Int64()
   295  
   296  }
   297  func (this *Wallet) GetCurrGas() int64 {
   298  	if this.CurrClient == nil {
   299  		return 0
   300  	}
   301  
   302  	gasPrice, err2 := this.CurrClient.SuggestGasPrice(context.Background())
   303  	if err2 != nil {
   304  		log.Println(err2)
   305  		return 0
   306  	}
   307  	gasInt := new(big.Int).Quo(gasPrice, WEI)
   308  	return gasInt.Int64()
   309  
   310  }