here is a sample script to send an ERC20 Transfer and get tx hash:
package main
import (
"os"
"fmt"
"math/big"
"context"
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/crypto"
)
const (
CHAIN_ID int64 = 1234
)
var (
RPC_URL string
token_addr common.Address
)
func main() {
RPC_URL = os.Getenv("RPC_URL")
eclient, err := ethclient.Dial(RPC_URL)
if err!=nil {
fmt.Printf("Can't connect to ETH RPC: %v\n",err)
os.Exit(1)
}
if len(os.Args) != 5 {
fmt.Printf("Usage: \n\t\t%v [priv_key] [token_addr] [dest_addr] [amount]\n\n\t\tSends erc20 tokens to another address using transfer() function\n",os.Args[0])
os.Exit(1)
}
var copts = new(bind.CallOpts)
from_pkey_str := os.Args[1]
if len(from_pkey_str) != 64 {
fmt.Printf("Sender's private key is not 66 characters long\n")
os.Exit(1)
}
contract_addr := common.HexToAddress(os.Args[2])
dst_addr := common.HexToAddress(os.Args[3])
amount_str := os.Args[4]
tok_amount := big.NewInt(0)
_,success := tok_amount.SetString(amount_str,10)
if !success {
fmt.Printf("Incorrect amount provided on the command line")
os.Exit(1)
}
erc20_token,err := NewERC20(contract_addr,eclient)
if err!=nil {
fmt.Printf("Failed to instantiate ERC20 contract: %v\n",err)
os.Exit(1)
}
symbol,err:=erc20_token.Symbol(copts)
if err!=nil {
fmt.Printf("Error during call: %v\n",err)
}
fmt.Printf("Symbol: %v\n",symbol)
from_PrivateKey, err := crypto.HexToECDSA(from_pkey_str)
if err != nil {
fmt.Sprintf("Error making private key: %v\n",err)
os.Exit(1)
}
from_publicKey := from_PrivateKey.Public()
from_publicKeyECDSA, ok := from_publicKey.(*ecdsa.PublicKey)
if !ok {
fmt.Printf("Couldn't derive public key for Sender")
os.Exit(1)
}
from_address := crypto.PubkeyToAddress(*from_publicKeyECDSA)
from_nonce, err := eclient.PendingNonceAt(context.Background(), from_address)
if err != nil {
fmt.Printf("Error getting account's nonce: %v\n",err)
os.Exit(1)
}
gasPrice, err := eclient.SuggestGasPrice(context.Background())
if err != nil {
fmt.Printf("Error getting suggested gas price: %v\n",err)
os.Exit(1)
}
big_chain_id := big.NewInt(CHAIN_ID)
txopts := bind.NewKeyedTransactor(from_PrivateKey)
txopts.Nonce = big.NewInt(int64(from_nonce))
txopts.Value = big.NewInt(0) // in wei
txopts.GasLimit = uint64(10000000) // in units
txopts.GasPrice = gasPrice
signfunc := func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
signer := types.NewEIP155Signer(big_chain_id)
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), from_PrivateKey)
if err != nil {
fmt.Printf("Error signing: %v\n",err)
os.Exit(1)
return nil,nil
}
return tx.WithSignature(signer, signature)
}
txopts.Signer = signfunc
tx,err := erc20_token.Transfer(txopts,dst_addr,tok_amount)
if err!=nil {
fmt.Printf("Error sending tx: %v\n",err)
os.Exit(1)
}
fmt.Printf("Tx hash = %v\n",tx.Hash().String())
}
the ERC20 is the standard ERC20 contract, you can generate it with these commands:
abigen --abi token.abi --pkg main --type Token --out token.go
abigen
command is in cmd/abigen
in go-ethereum
sources and must be compiled with go build .
command