[GO]以太坊代币转账

以太坊代币转账

    • 代码

代码

//私钥,要转往的地址,数量(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
}

注:转载请注明出处https://blog.csdn.net/qq_22157427/article/details/89928522

你可能感兴趣的:(GO,区块链)