Ethers.js: How to send EIP-1559 transactions

Ethers is pretty cool and is able to send a eip-1559 transaction automatically without a need to do any extra configuration. It will use a maxPriorityFeePerGas of 1.5 Gwei by default, starting with v5.6.0.
Also, if you use a signer class that would know also how to manage the nonce for you (of course that if you want to always get the mined transactions count). Here’s a simple script that would send such a transaction:

    const { ethers } = require("ethers");

    async function main() {
      // Configuring the connection to an Ethereum node
      const network = process.env.ETHEREUM_NETWORK;
      const provider = new ethers.providers.InfuraProvider(
        network,
        process.env.INFURA_PROJECT_ID
      );
      // Creating a signing account from a private key
      const signer = new ethers.Wallet(process.env.SIGNER_PRIVATE_KEY, provider);

      // Creating and sending the transaction object
      const tx = await signer.sendTransaction({
        to: "<to_address_goes_here>",
        value: ethers.utils.parseUnits("0.001", "ether"),
      });
      console.log("Mining transaction...");
      console.log(`https://${network}.etherscan.io/tx/${tx.hash}`);
      // Waiting for the transaction to be mined
      const receipt = await tx.wait();
      // The transaction is now on chain!
      console.log(`Mined in block ${receipt.blockNumber}`);
    }

    require("dotenv").config();
    main();

However, if you want to manually control the tx object parameters here’s how the above script changes:

    const { ethers } = require("ethers");

    async function main() {
      // Configuring the connection to an Ethereum node
      const network = process.env.ETHEREUM_NETWORK;
      const provider = new ethers.providers.InfuraProvider(
        network,
        process.env.INFURA_PROJECT_ID
      );
      // Creating a signing account from a private key
      const signer = new ethers.Wallet(process.env.SIGNER_PRIVATE_KEY, provider);

      const limit = provider.estimateGas({
        from: signer.address,
        to: "<to_address_goes_here>",
        value: ethers.utils.parseUnits("0.001", "ether")
      });

      // Creating and sending the transaction object
      const tx = await signer.sendTransaction({
        to: "<to_address_goes_here>",
        value: ethers.utils.parseUnits("0.001", "ether"),
        gasLimit: limit,
        nonce: signer.getTransactionCount(),
        maxPriorityFeePerGas: ethers.utils.parseUnits("2", "gwei"),
        chainId: 3,
      });
      console.log("Mining transaction...");
      console.log(`https://${network}.etherscan.io/tx/${tx.hash}`);
      // Waiting for the transaction to be mined
      const receipt = await tx.wait();
      // The transaction is now on chain!
      console.log(`Mined in block ${receipt.blockNumber}`);

    }

    require("dotenv").config();
    main();