└── main.go /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "crypto/ecdsa" 6 | "fmt" 7 | "log" 8 | "math/big" 9 | 10 | "github.com/ethereum/go-ethereum" 11 | "github.com/ethereum/go-ethereum/common" 12 | "github.com/ethereum/go-ethereum/common/hexutil" 13 | "github.com/ethereum/go-ethereum/core/types" 14 | "github.com/ethereum/go-ethereum/crypto" 15 | "github.com/ethereum/go-ethereum/crypto/sha3" 16 | "github.com/ethereum/go-ethereum/ethclient" 17 | ) 18 | 19 | func main() { 20 | client, err := ethclient.Dial("http://127.0.0.1:9545") 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | 25 | privateKey, err := crypto.HexToECDSA("...") 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | 30 | publicKey := privateKey.Public() 31 | publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) 32 | if !ok { 33 | log.Fatal("error casting public key to ECDSA") 34 | } 35 | 36 | fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) 37 | nonce, err := client.PendingNonceAt(context.Background(), fromAddress) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | 42 | value := big.NewInt(0) // in wei (0 eth) 43 | gasPrice, err := client.SuggestGasPrice(context.Background()) 44 | if err != nil { 45 | log.Fatal(err) 46 | } 47 | 48 | toAddress := common.HexToAddress("...") 49 | tokenAddress := common.HexToAddress("...") 50 | 51 | transferFnSignature := []byte("transfer(address,uint256)") 52 | hash := sha3.NewKeccak256() 53 | hash.Write(transferFnSignature) 54 | methodID := hash.Sum(nil)[:4] 55 | fmt.Printf("Method ID: %s\n", hexutil.Encode(methodID)) 56 | 57 | paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32) 58 | fmt.Printf("To address: %s\n", hexutil.Encode(paddedAddress)) 59 | 60 | amount := new(big.Int) 61 | amount.SetString("1000000000000000000000", 10) // 1000 tokens 62 | paddedAmount := common.LeftPadBytes(amount.Bytes(), 32) 63 | fmt.Printf("Token amount: %s", hexutil.Encode(paddedAmount)) 64 | 65 | var data []byte 66 | data = append(data, methodID...) 67 | data = append(data, paddedAddress...) 68 | data = append(data, paddedAmount...) 69 | 70 | gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ 71 | To: &toAddress, 72 | Data: data, 73 | }) 74 | if err != nil { 75 | log.Fatal(err) 76 | } 77 | fmt.Printf("Gas limit: %d", gasLimit) 78 | 79 | tx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data) 80 | signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, privateKey) 81 | if err != nil { 82 | log.Fatal(err) 83 | } 84 | 85 | err = client.SendTransaction(context.Background(), signedTx) 86 | if err != nil { 87 | log.Fatal(err) 88 | } 89 | 90 | fmt.Printf("Tokens sent at TX: %s", signedTx.Hash().Hex()) 91 | } 92 | --------------------------------------------------------------------------------