How to Send a Private Transaction on Ethereum
In this tutorial, we will learn how to send a private transaction on Ethereum.
When transactions are sent to the blockchain, they are distributed across the entire network. Transactions that have not been mined yet are classified as "pending" transactions. You can learn more about the various transactions states, here. Pending transactions live in the and are visible to the entire network, which makes them prone to front-running and other forms of arbitrage.
In order to protect your transactions, you can send them through a private endpoint, eth_sendPrivateTransaction, which skips the public mempool and is sent directly to miners. This endpoint is powered by Flashbots, a leading web3 organization focusing on protecting developers against these types of arbitrage opportunities (better known as Miner Extractable Value, or MEV).
This tutorial will teach you how to use this endpoint to protect your transactions.
3 Steps to Send a Private Transaction
- Create free Alchemy account
- Create an Alchemy App
- Make a sendPrivateTransaction API call via the Alchemy SD
Create free Alchemy account
We'll use Alchemy to send our private transaction to Ethereum. You can create an account for free here.
After creating a new account successfully, we will be redirected to our dashboard, where we can create an App by clicking on the Create App
button as shown below.
Next, we will input the following app information:
- Name: Transaction App
- Description: Feel free to put anything here.
- Chain: Ethereum
- Network: Mainnet
Click on the View Key
button as shown below, which will open a popup with our app's HTTP and Websocket URLs. In this tutorial, we will be using the Api Key. Save this for later.
Make sendPrivateTransaction call via the Alchemy SDK
Now that we've got everything set up, we'll look at how to send private transactions using eth_sendPrivateTransaction over the Alchemy SDK
1. Create a new project directory and cd
into it
cd
into itCreate a new project directory from the command line (terminal for macs) and navigate into it:
mkdir sendtx-example
cd sendtx-example
2. Install the Alchemy SDK and dotenv
Run the following command in your project directory:
npm install alchemy-sdk dotenv
3. Create the .env file
We'll use a .env
file to safely store our API key and private key.
.env
We make a .env file to securely store private environmental variables in our local machine that we may access from other files (some of which we can make public).
If you want to check out how
dotenv
actually works in the context of a conventional NodeJS server file, check out this helpful video!
Create a .env file (make sure the file is literally just named .env
, nothing more) in your project directory and add the following (replacing your-api-key
and your-private-key
, keeping both within the quotation marks):
- To find your Alchemy API Key, use the instructions shared above.
- To find your private key using Metamask, check out this guide.
API_KEY = "your-api-key"
PRIVATE_KEY = "your-private-key"
4. Create sendPrivateTx.js
file
sendPrivateTx.js
fileGreat, now that we have our sensitive data protected in a .env
file, let's start coding. For our send transaction example, we'll be sending Ethereum to a test wallet.
Create a sendTx.js
file, which is where we will configure and send our example transaction, and add the following lines of code to it:
// Setup: npm install alchemy-sdk
// Github: https://github.com/alchemyplatform/alchemy-sdk-js
import { Alchemy, Network, Wallet, Utils } from "alchemy-sdk";
import dotenv from "dotenv";
dotenv.config();
const { API_KEY, PRIVATE_KEY } = process.env;
const settings = {
apiKey: API_KEY,
network: Network.ETH_MAINNET, // Replace with your network.
};
const alchemy = new Alchemy(settings);
let wallet = new Wallet(PRIVATE_KEY);
const nonce = await alchemy.core.getTransactionCount(wallet.address, "latest");
let exampleTx = {
to: "0x4b9007B0BcE78cfB634032ec31Ed56adB464287b",
value: 10,
gasLimit: "21000",
maxFeePerGas: Utils.parseUnits('20', 'gwei'),
nonce: nonce,
type: 2,
chainId: 5,
};
let rawTransaction = await wallet.signTransaction(exampleTx);
const signedTx = await alchemy.transact.sendPrivateTransaction(
rawTransaction,
(await alchemy.core.getBlockNumber()) + 1
);
console.log(signedTx);
Now, before we jump into running this code, let's talk about some of the components here.
Wallet
: This object stores your private key, and can be accessed to sign a transaction with your private key or to return your public address.nonce
: The nonce specification is used to keep track of the number of transactions sent from your address. We need this for security purposes and to prevent replay attacks. To get the number of transactions sent from your address we use eth_getTransactionCounttransaction
: The transaction object has a few aspects we need to specifyto
: This is the address we want to send Eth to. In this case, we are sending Eth to a test wallet.gasLimit
: This is the maximum amount of gas you are willing to consume on a transaction. Standard limit is 21000 units.value
: This is the amount we wish to send, specified in wei where 10^18 wei = 1 ETHmaxFeePerGas
: This is the total amount you are willing to pay per gas for the transaction to execute. Since EIP 1559, this field or themaxPriorityFeePerGas
field is required. Specified in wei, where 10^18 wei = 1 ETHnonce
: see above nonce definition. Nonce starts counting from zero.- [OPTIONAL]
data
: Used for sending additional information with your transfer, or calling a smart contract, not required for balance transfers, check out the note below.
rawTransaction
: To sign our transaction object we will use thesignTransaction
method of our wallet, generating a raw "signed" transaction.sendPrivateTransaction
: Once we have a signed transaction, we can send it off via Alchemy's servers to be included in a subsequent block by usingsendPrivateTransaction
request.
A Note on
data
There are two main types of transactions that can be sent in Ethereum.
- Balance transfer: Send eth from one address to another. No
data
field is required, however, if you'd like to send additional information alongside your transaction, you can include that information in HEX format in this field.
- For example, let's say we wanted to write the hash of an IPFS document to the Ethereum chain in order to give it an immutable timestamp. Our data field should then look like
data: toHex(‘IPFS hash‘)
. And now anyone can query the chain and see when that document was added.- Smart contact transaction: Execute some smart contract code on the chain. In this case, the
data
field should contain the smart function you wish to execute, alongside any parameters.
- For a practical example, check out Step 8 in this Hello World Smart Contract.
5. Run the code using node sendPrivateTx.js
node sendPrivateTx.js
Navigate back to your terminal or command line and run:
node sendPrivateTx.js
From there you can view your transaction on Etherscan by clicking on the icon circled in red!
Yippieeee! You just sent your first private transaction using Alchemy 🎉
Once you complete this tutorial, let us know how your experience was or if you have any feedback by tagging us on Twitter @alchemyplatform!
_For feedback and suggestions about this guide, please message Deric on Alchemy's Discord! _
_Not sure what to do next? As a final test of your skills, get your hands dirty with some solidity programming by implementing our Hello World Smart Contract tutorial.
Updated over 2 years ago