Signing Raw Transactions
The closest real world example of a raw transaction β€” probably a bank cheque
πŸ’Έ
​
Some ways we can utilize raw transactions include signing a transaction offline on a secure machine and then broadcasting it separately or to send a transaction at a later point of time.
You will need Node.js
installed and a valid Etherscan API Key.

1. Setting up a Node.js project

In a new folder, initiate a new Node.js project with the command npm init -y to accept all default project parameters.
A package.json file will be created for you, which contains all your packages and project information.

2. Integrating Ethers.js

We'll need to integrate a helpful JavaScript library known as Ethers.js that will help with interacting with the Ethereum blockchain.
We can do so using the command npm i ethers from a terminal within this project, which will add ethers as a dependency.
We'll then create a new file named transaction.js where we'll write the rest of the code in JavaScript and import ethers at the top of the file.
1
const ethers = require('ethers');
2
​
3
async function main() {
4
​
5
// rest of code goes here
6
​
7
}
8
​
9
main();
Copied!

3. Creating a wallet

One of the useful classes that Ethers.js provides is a Wallet, which represents a regular Ethereum address that you can use to store and send Ether.
We can initiate a new Wallet by specifying a private key which we can generate or grab one from an existing wallet like MetaMask.​
1
const ethers = require('ethers');
2
​
3
async function main() {
4
​
5
// defining the wallet private key
6
let privatekey = 'CE75F1A875F2DB7FB064F5DBD302B0C77FFEAA18CC4C314167A5111A04F79AFA';
7
let wallet = new ethers.Wallet(privatekey);
8
​
9
// print the wallet address
10
console.log('Using wallet address ' + wallet.address);
11
12
}
13
​
14
main();
Copied!

4. Crafting the transaction

A transactions is made up of several parameters that have to be defined, for this example we'll be making a simple ETH transfer.
If you are following this article on a testnet, feel free to get some testnet Ether​
to fund your address.
Parameter
Description
to
the address to send Ether to
value
the amount of Ether to send
gasLimit
the maximum units of gas to consume in this transaction, set to 21000 for basic Ether transfers
maxPriorityFeePerGas
the tip paid to miners, introduced in EIP-1559​
maxFeePerGas
the maximum price paid per unit of gas, introduced in EIP-1559​
nonce
the number of transactions sent from the address
type
set to 0x2, to denote EIP-1559 type transactions
chainId
the chain ID to send the transaction, for example 3 for Ropsten
The sample code to send 1 Ether to address 0xEeee7341f206302f2216e39D715B96D8C6901A1C on the Ropsteh testnet will be as follows.
1
const ethers = require('ethers');
2
​
3
async function main() {
4
​
5
let privatekey = 'CE75F1A875F2DB7FB064F5DBD302B0C77FFEAA18CC4C314167A5111A04F79AFA';
6
let wallet = new ethers.Wallet(privatekey);
7
​
8
console.log('Using wallet address ' + wallet.address);
9
​
10
let transaction = {
11
to: '0xa238b6008Bc2FBd9E386A5d4784511980cE504Cd',
12
value: ethers.utils.parseEther('1'),
13
gasLimit: '21000',
14
maxPriorityFeePerGas: ethers.utils.parseUnits('5', 'gwei'),
15
maxFeePerGas: ethers.utils.parseUnits('20', 'gwei'),
16
nonce: 1,
17
type: 2,
18
chainId: 3
19
};
20
​
21
}
22
​
23
main();
Copied!

5. Sign & serialize

After detailing the contents of the transaction, we'll need to sign it β€” using the wallet's private key we created in Step 3 to prove we are allowed to spend funds in the wallet address.
With the transaction signed, we have just one more step to serialize, or simply converting our transaction into a hexadecimal format.
1
const ethers = require('ethers');
2
​
3
async function main() {
4
​
5
let privatekey = 'CE75F1A875F2DB7FB064F5DBD302B0C77FFEAA18CC4C314167A5111A04F79AFA';
6
let wallet = new ethers.Wallet(privatekey);
7
​
8
console.log('Using wallet address ' + wallet.address);
9
​
10
let transaction = {
11
to: '0xa238b6008Bc2FBd9E386A5d4784511980cE504Cd',
12
value: ethers.utils.parseEther('1'),
13
gasLimit: '21000',
14
maxPriorityFeePerGas: ethers.utils.parseUnits('5', 'gwei'),
15
maxFeePerGas: ethers.utils.parseUnits('20', 'gwei'),
16
nonce: 1,
17
type: 2,
18
chainId: 3
19
};
20
​
21
// sign and serialize the transaction
22
let rawTransaction = await wallet.signTransaction(transaction).then(ethers.utils.serializeTransaction(transaction));
23
24
// print the raw transaction hash
25
console.log('Raw txhash string ' + rawTransaction);
26
​
27
}
28
​
29
main();
Copied!

6. Send via API

With the signed raw transaction, we can now pass it to the "eth_sendRawTransaction" endpoint to be broadcasted to the Ethereum network.
A successfully broadcasted transaction will return a transaction hash, which you can use the "eth_getTransactionbyHash" endpoint or look it up on Etherscan!
You can run this code using the command node transaction.js
1
const ethers = require('ethers');
2
const fetch = require('node-fetch');
3
​
4
async function main() {
5
​
6
let privatekey = 'CE75F1A875F2DB7FB064F5DBD302B0C77FFEAA18CC4C314167A5111A04F79AFA';
7
let wallet = new ethers.Wallet(privatekey);
8
​
9
console.log('Using wallet address ' + wallet.address);
10
​
11
let transaction = {
12
to: '0xa238b6008Bc2FBd9E386A5d4784511980cE504Cd',
13
value: ethers.utils.parseEther('1'),
14
gasLimit: '21000',
15
maxPriorityFeePerGas: ethers.utils.parseUnits('5', 'gwei'),
16
maxFeePerGas: ethers.utils.parseUnits('20', 'gwei'),
17
nonce: 1,
18
type: 2,
19
chainId: 3
20
};
21
​
22
let rawTransaction = await wallet.signTransaction(transaction).then(ethers.utils.serializeTransaction(transaction));
23
console.log('Raw txhash string ' + rawTransaction);
24
​
25
// pass the raw transaction hash to the "eth_sendRawTransaction" endpoint
26
let gethProxy = await fetch(`https://api-ropsten.etherscan.io/api?module=proxy&action=eth_sendRawTransaction&hex=${rawTransaction}&apikey=YourApiKeyToken`);
27
let response = await gethProxy.json();
28
29
// print the API response
30
console.log(response);
31
32
}
33
​
34
main();
Copied!

Wrapping Up

The full sample code for this tutorial is on Github, feel free to fork and extend the functionality of it !
πŸ€–
​
Last modified 1mo ago