Skip to content

Instantly share code, notes, and snippets.

@rac-sri
Last active March 8, 2024 12:26
Show Gist options
  • Save rac-sri/a324c1240536adaba8295709b3146de8 to your computer and use it in GitHub Desktop.
Save rac-sri/a324c1240536adaba8295709b3146de8 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"crypto/ecdsa"
"encoding/hex"
"fmt"
"log"
"math/big"
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/holiman/uint256"
"github.com/joho/godotenv"
)
const TO_ADDRESS = "<Tx Destination Address>"
func main() {
if err := loadEnv(); err != nil {
log.Fatal("Error loading .env file:", err)
}
client, err := ethclient.DialContext(context.Background(), os.Getenv("NODE_URL"))
if err != nil {
log.Fatalf("Failed to connect to the Ethereum client: %v", err)
}
privateKey, err := getECDSAPrivateKey(os.Getenv("PRIVATE_KEY"))
if err != nil {
log.Fatalf("Error getting private key: %v", err)
}
nonce, chainID, tip, maxFeePerGas, err := prepareTransactionParams(client, privateKey)
if err != nil {
log.Fatal(err)
}
blobTx, err := createBlobTx(chainID, nonce, tip, maxFeePerGas)
if err != nil {
log.Fatal("Failed to create blob transaction:", err)
}
sendTransaction(client, blobTx, privateKey)
}
func loadEnv() error {
return godotenv.Load()
}
func prepareTransactionParams(client *ethclient.Client, privateKey *ecdsa.PrivateKey) (uint64, *big.Int, *big.Int, *uint256.Int, error) {
publicKey := privateKey.PublicKey
fromAddress := crypto.PubkeyToAddress(publicKey)
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
if err != nil {
return 0, nil, nil, nil, fmt.Errorf("error getting nonce: %v", err)
}
suggestedTip, err := client.SuggestGasTipCap(context.Background())
if err != nil {
return 0, nil, nil, nil, fmt.Errorf("error suggesting gas tip cap: %v", err)
}
header, err := client.HeaderByNumber(context.Background(), nil) // nil for latest block
if err != nil {
return 0, nil, nil, nil, fmt.Errorf("error fetching latest block header: %v", err)
}
maxFeePerGas := new(big.Int).Add(header.BaseFee, suggestedTip)
chainID, err := client.NetworkID(context.Background())
if err != nil {
return 0, nil, nil, nil, fmt.Errorf("error fetching chain id: %v", err)
}
return nonce, chainID, suggestedTip, uint256.MustFromBig(maxFeePerGas), nil
}
func createBlobTx(chainID *big.Int, nonce uint64, tip *big.Int, maxFeePerGas *uint256.Int) (*types.Transaction, error) {
emptyBlob := kzg4844.Blob{} // can change the blob data here
emptyBlobCommit, err := kzg4844.BlobToCommitment(emptyBlob)
if err != nil {
log.Fatal("Failed to create commitment", "err", err)
}
emptyBlobProof, err := kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
if err != nil {
log.Fatal("Failed to create proof", "err", err)
}
sidecar := types.BlobTxSidecar{
Blobs: []kzg4844.Blob{emptyBlob},
Commitments: []kzg4844.Commitment{emptyBlobCommit},
Proofs: []kzg4844.Proof{emptyBlobProof},
}
return types.NewTx(&types.BlobTx{
ChainID: uint256.MustFromBig(chainID),
Nonce: nonce,
GasTipCap: uint256.MustFromBig(tip),
GasFeeCap: maxFeePerGas,
Gas: 2500000,
To: common.HexToAddress(TO_ADDRESS),
Value: uint256.NewInt(0),
Data: []byte{}, // update: this is the input data to your destination address
BlobFeeCap: uint256.NewInt(3e10),
BlobHashes: sidecar.BlobHashes(),
Sidecar: &sidecar,
}), nil
}
func getECDSAPrivateKey(privateKeyHex string) (*ecdsa.PrivateKey, error) {
privateKeyBytes, err := hex.DecodeString(privateKeyHex)
if err != nil {
return nil, fmt.Errorf("failed to decode hex string: %v", err)
}
return crypto.ToECDSA(privateKeyBytes)
}
func sendTransaction(client *ethclient.Client, tx *types.Transaction, privateKey *ecdsa.PrivateKey) {
signedTx, err := types.SignTx(tx, types.NewCancunSigner(tx.ChainId()), privateKey)
if err != nil {
log.Fatalf("Error signing transaction: %v", err)
}
err = client.SendTransaction(context.Background(), signedTx)
if err != nil {
log.Fatalf("Failed to send transaction: %v", err)
} else {
log.Printf("Successfully sent transaction. txhash= %s", signedTx.Hash().Hex())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment