Updated 2020-02-13

Create a Signed Transaction using Web3.js

You can use the example Javascript scripts to create and send raw transactions in the private network created by the Private Network Example.

Update the JSON-RPC endpoint in the following examples to the endpoint for the private network displayed after running the ./run.sh script.

Private keys

Do not use the accounts in the examples on mainnet or any public network except for testing. The private keys are displayed which means the accounts are not secure.

All accounts and private keys in the examples are from the dev.json genesis file in the /besu/ethereum/core/src/main/resources directory.

In production environments avoid exposing your private keys by creating signed transactions offline, or use EthSigner to isolate your private keys and sign transactions with eth_sendTransaction.

Example Javascript scripts

1. Requirements

2. Create Directory

mkdir example_scripts

3. Copy Files

Copy the following files to the example_scripts directory:

4. Retrieve Dependencies

cd example_scripts
npm install

5. Send Ether

The following is the example JavaScript script that displays a signed raw transaction string to send Ether.

Send Ether example : create_value_raw_transaction.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
const Web3 = require('web3')
const ethTx = require('ethereumjs-tx')
const readline = require('readline');

async function askQuestion(query) {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });

    return new Promise(resolve => rl.question(query, ans => {
        rl.close();
        resolve(ans);
    }))
}

const args = process.argv.slice(2);

// web3 initialization - must point to the HTTP JSON-RPC endpoint
var provider = args[0] || 'http://localhost:8545';
console.log("******************************************");
console.log("Using provider : " + provider);
console.log("******************************************");
var web3 = new Web3(new Web3.providers.HttpProvider(provider))
web3.transactionConfirmationBlocks = 1;
// Sender address and private key
// Second acccount in dev.json genesis file
// Exclude 0x at the beginning of the private key
const addressFrom = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'
const privKey = Buffer.from('c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', 'hex')

// Receiver address and value to transfer
// Third account in dev.json genesis file
const addressTo = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'
const valueInEther = 2

// Get the address transaction count in order to specify the correct nonce
web3.eth.getTransactionCount(addressFrom, "pending").then((txnCount) => {
  // Create the transaction object
  var txObject = {
      nonce: web3.utils.numberToHex(txnCount),
      gasPrice: web3.utils.numberToHex(1000),
      gasLimit: web3.utils.numberToHex(21000),
      to: addressTo,
      value: web3.utils.numberToHex(web3.utils.toWei(valueInEther.toString(), 'ether'))
  };

  // Sign the transaction with the private key
  var tx = new ethTx(txObject);
  tx.sign(privKey)

  //Convert to raw transaction string
  var serializedTx = tx.serialize();
  var rawTxHex = '0x' + serializedTx.toString('hex');

  // log raw transaction data to the console so you can send it manually
  console.log("Raw transaction data: " + rawTxHex);

  // but also ask you if you want to send this transaction directly using web3
  (async() => {
    const ans = await askQuestion("******************************************\n\
Do you want to send the signed value transaction now ? (Y/N):");
    if("y" == ans || "Y" == ans){
      // Send the signed transaction using web3
      web3.eth.sendSignedTransaction(rawTxHex)
        .on('receipt', receipt => { console.log('Receipt: ', receipt); })
        .catch(error => { console.log('Error: ', error.message); });
      console.log("******************************************");
      console.log("Value transaction sent, waiting for receipt.");
      console.log("******************************************");
    }else{
      console.log("******************************************");
      console.log("You can for instance send this transaction manually with the following command:");
      console.log("curl -X POST --data '{\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":[\"" + rawTxHex + "\"],\"id\":1}'", provider);
    }
  })();

})
.catch(error => { console.log('Error: ', error.message); });

Run the create_value_raw_transaction.js script:

node create_value_raw_transaction.js <YOUR JSON-RPC HTTP ENDPOINT>
node create_value_raw_transaction.js http://localhost:8545

Tip

The default JSON-RPC HTTP endpoint for create_value_raw_transaction.js is http://localhost:8545. If Besu is listening on http://localhost:8545, you can run the command without specifying the endpoint.

A signed raw transaction string is displayed.

You can send the raw transaction yourself or let the script send it using the web3.js library.

If sending it yourself, the cURL command is displayed and can be copied and pasted. Otherwise, the script sends it and the transaction receipt is displayed.

6. Create A Smart Contract

The following is the example JavaScript script that displays a signed raw transaction string to create a contract.

Create a contract example : create_contract_raw_transaction.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
const Web3 = require('web3')
const ethTx = require('ethereumjs-tx')
const readline = require('readline');

async function askQuestion(query) {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });

    return new Promise(resolve => rl.question(query, ans => {
        rl.close();
        resolve(ans);
    }))
}

const args = process.argv.slice(2);

// web3 initialization - must point to the HTTP JSON-RPC endpoint
var provider = args[0] || 'http://localhost:8545';
console.log("******************************************");
console.log("Using provider : " + provider);
console.log("******************************************");
var web3 = new Web3(new Web3.providers.HttpProvider(provider))
web3.transactionConfirmationBlocks = 1;
// Sender address and private key
// Second acccount in dev.json genesis file
// Exclude 0x at the beginning of the private key
const addressFrom = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'
const privKey = Buffer.from('c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', 'hex')

// hexadecimal encoded compiled contract code
const contractData = '0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633fa4f24514604e57806355241077146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a6565b005b60005481565b80600081905550505600a165627a7a723058202bdbba2e694dba8fff33d9d0976df580f57bff0a40e25a46c398f8063b4c00360029'

// Get the address transaction count in order to specify the correct nonce
web3.eth.getTransactionCount(addressFrom, "pending").then((txnCount) => {
  // Create the contract creation transaction object
  var txObject = {
     nonce: web3.utils.toHex(txnCount),
     gasPrice: web3.utils.toHex(1000),
     gasLimit: web3.utils.toHex(126165),
     data: contractData
  };

  // Sign the transaction with the private key
  var tx = new ethTx(txObject);
  tx.sign(privKey)

  //Convert to raw transaction string
  var serializedTx = tx.serialize();
  var rawTxHex = '0x' + serializedTx.toString('hex');

  // log raw transaction data to the console so you can send it manually
  console.log("Raw transaction data: " + rawTxHex);

  // but also ask you if you want to send this transaction directly using web3
  (async() => {
    const ans = await askQuestion("******************************************\n\
Do you want to send the signed contract creation transaction now ? (Y/N):");
    if("y" == ans || "Y" == ans){
      // Send the signed transaction using web3
      web3.eth.sendSignedTransaction(rawTxHex)
        .on('receipt', receipt => { console.log('Receipt: ', receipt); })
        .catch(error => { console.log('Error: ', error.message); });
      console.log("******************************************");
      console.log("Contract transaction sent, waiting for receipt.");
      console.log("******************************************");
    }else{
      console.log("******************************************");
      console.log("You can for instance send this transaction manually with the following command:");
      console.log("curl -X POST --data '{\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":[\"" + rawTxHex + "\"],\"id\":1}'", provider);
    }
  })();

})
.catch(error => { console.log('Error: ', error.message); });

Run the create_contract_raw_transaction.js script:

node create_contract_raw_transaction.js <YOUR JSON-RPC HTTP ENDPOINT>
node create_contract_raw_transaction.js http://localhost:8545

Tip

The default JSON-RPC HTTP endpoint for create_contract_raw_transaction.js is http://localhost:8545. If using http://localhost:8545, run node create_contract_raw_transaction.js.

A signed raw transaction string is displayed.

You can send the raw transaction yourself or let the script send it using the web3.js library.

If sending it yourself, the cURL command is displayed and can be copied and pasted. Otherwise, the script sends it and the transaction receipt is displayed.