Last active
March 8, 2024 12:26
-
-
Save rac-sri/a324c1240536adaba8295709b3146de8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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