//私钥,要转往的地址,数量(ether),代币地址,请求的以太坊节点地址(https://mainnet.infura.io),gasprice
func SignTokenTx(privateKey, toAddress, value, tokenAddress, ethNet , gas string) (string, error) {
client, err := ethclient.Dial(ethNet)
if err != nil {
log.Println("set ethclient failed!", err)
return "", err
}
privKey, err := crypto.HexToECDSA(privateKey)
if err != nil {
log.Println("hextoECDSA privateKey failed!", err)
return "", err
}
pubKey := privKey.Public()
publicKeyECDSA, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
log.Println("cannot assert type: publicKey is not of type *ecdsa.PublicKey", err)
return "", err
}
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
nn, err := client.PendingNonceAt(context.Background(), fromAddress)
if err != nil {
log.Println(err)
return "", err
}
//单位转换ether=>Wei
valuef, err := strconv.ParseFloat(value, 64)
if err != nil {
log.Println("is not a number")
}
valueWei, isOk := new(big.Int).SetString(fmt.Sprintf("%.0f", valuef*1000000000000000000), 10)
if !isOk {
log.Println("float to bigInt failed!")
}
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
log.Println("set the gasPrice failed!", err)
return "", err
}
toAddr := common.HexToAddress(toAddress)
tokenAddr := common.HexToAddress(tokenAddress)
transferFnSignature := []byte("transfer(address,uint256)")
hash := sha3.NewLegacyKeccak256()
hash.Write(transferFnSignature)
methodID := hash.Sum(nil)[:4]
paddedToAddress := common.LeftPadBytes(toAddr.Bytes(), 32)
paddedValue := common.LeftPadBytes(valueWei.Bytes(), 32)
var data []byte
data = append(data, methodID...)
data = append(data, paddedToAddress...)
data = append(data, paddedValue...)
gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{
To: &toAddr,
Data: data,
})
if err != nil {
log.Println("set the gasLimit failed!", err)
return "", err
}
gasF, err := strconv.ParseFloat(gas, 64)
if err != nil {
return "", err
}
gasPrice, isSuccess := new(big.Int).SetString(fmt.Sprintf("%.0f", gasF*1000000000000000), 10)
if !isSuccess {
return "", err
}
gasLimitInt := new(big.Int).SetInt64(int64(gasLimit))
gasPrice = gasPrice.Div(gasPrice, gasLimitInt)
ethValue := big.NewInt(0)
//需要覆盖前面的交易时
//nn = uint64(44)
gasLimit = uint64(90000)
tx := types.NewTransaction(nn, tokenAddr, ethValue, gasLimit, gasPrice, data)
chainID, err := client.NetworkID(context.Background())
if err != nil {
log.Println("sign the tx failed!", err)
}
signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privKey)
if err != nil {
log.Println("sign the tx failed!", err)
}
/*var buff bytes.Buffer
if err := signedTx.EncodeRLP(&buff); err != nil {
return "", err
}
sTx := fmt.Sprintf("0x%x", buff.Bytes())*/
err = client.SendTransaction(context.Background(), signedTx)
if err != nil {
log.Println("client send tx failed!", err)
return "", err
}
//log.Printf("tx sent: %s\n", signedTx.Hash().Hex())
return signedTx.Hash().Hex(), nil
//return sTx, nil
}