From e944f4f7f4d7728df15b75c8b29fa846a6f93dba Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 19 Sep 2024 12:07:23 +0300 Subject: [PATCH 01/19] initial commit --- .../tutorials/sdk-estimate-costs.mdx | 204 +++++++++++------- 1 file changed, 130 insertions(+), 74 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 25b0f7894..8956dced5 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -1,17 +1,17 @@ --- title: Estimating Transaction Costs on OP Mainnet lang: en-US -description: Learn how to use the Optimism SDK to estimate the cost of a transaction on OP Mainnet. +description: Learn how to use the Viem/op-stack to estimate the cost of a transaction on OP Mainnet. --- -import { Callout, Steps } from 'nextra/components' +import { Callout, Steps, Tabs } from 'nextra/components' import { WipCallout } from '@/components/WipCallout' # Estimating Transaction Costs on OP Mainnet -In this tutorial, you'll learn how to use the [Optimism SDK](https://sdk.optimism.io) to estimate the cost of a transaction on OP Mainnet. +In this tutorial, you'll learn how to use the [Viem](https://viem.sh/op-stack/) to estimate the cost of a transaction on OP Mainnet. You'll learn how to estimate the [execution gas fee](/builders/app-developers/transactions/fees#execution-gas-fee) and the [L1 data fee](/builders/app-developers/transactions/fees#l1-data-fee) independently. You'll also learn how to estimate the total cost of the transaction all at once. @@ -19,50 +19,84 @@ You'll also learn how to estimate the total cost of the transaction all at once. Check out the full explainer on [OP Mainnet transaction fees](/builders/app-developers/transactions/fees) for more information on how OP Mainnet charges fees under the hood. -## Dependencies +## Prerequisites + +Before you begin, ensure you have the following: + +* Node.js (version 14 or later) +* An understanding of the [viem library](https://viem.sh/op-stack/) +* `pnpm` installed for managing packages. + +## Required Dependencies * [node](https://nodejs.org/en/) * [pnpm](https://pnpm.io/installation) +* [viem](https://viem.sh/op-stack/) -## Create a Demo Project +Install `pnpm` if you haven't already: + +```bash +npm install -g pnpm -You're going to use the Optimism SDK for this tutorial. -Since the Optimism SDK is a [Node.js](https://nodejs.org/en/) library, you'll need to create a Node.js project to use it. +``` + +## Create a Demo Project + {

Project Setup

} -{

Make a Project Folder

} + Let's create a new project and install the necessary dependencies. -```bash -mkdir op-sample-project -cd op-sample-project -``` + + {

Create a folder

} -{

Initialize the Project

} + ```bash + mkdir op-sample-project + cd op-sample-project + ``` -```bash -pnpm init -``` + {

Initialize the project

} -{

Install the Optimism SDK

} + ```bash + pnpm init + ``` -```bash -pnpm add @eth-optimism/sdk -``` + {

Install dependencies

} + + Install `viem`, and `dotenv` for managing environment variables. -{

Install ethers.js

} + ```bash + pnpm add viem dotenv + ``` +
-```bash -pnpm add ethers@^5 -``` + {

Configure Environment Variables

} + + You need a private key in order to sign transactions. + Create a `.env` file to securely store your environment variables + Set your private key as an environment variable with the `export` command. + Make sure this private key corresponds to an address that has ETH on Sepolia. + + ```bash + touch .env + ``` + + Add your wallet private key in the `.env` file. + You need a private key in order to sign transactions. + Make sure this private key corresponds to an address that has ETH on OP Sepolia. + + ```bash + RPC_URL=https://optimism-mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID + TUTORIAL_PRIVATE_KEY=0x... + ```
- -Want to create a new wallet for this tutorial? -If you have [`cast`](https://book.getfoundry.sh/getting-started/installation) installed you can run `cast wallet new` in your terminal to create a new wallet and get the private key. + + Never share your private key and avoid committing this file to version control. + ## Get ETH on OP Sepolia This tutorial explains how estimate transaction costs on OP Sepolia. @@ -72,19 +106,9 @@ You will need to get some ETH on OP Sepolia in order to run the code in this tut You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. -## Add a Private Key to Your Environment - -You need a private key in order to sign transactions. -Set your private key as an environment variable with the `export` command. -Make sure this private key corresponds to an address that has ETH on OP Sepolia. - -```bash -export TUTORIAL_PRIVATE_KEY=0x... -``` - ## Start the Node REPL -You're going to use the Node REPL to interact with the Optimism SDK. +You're going to use the Node REPL to interact with the Viem library. To start the Node REPL run the following command in your terminal: ```bash @@ -96,17 +120,23 @@ This will bring up a Node REPL prompt that allows you to run javascript code. ## Import Dependencies You need to import some dependencies into your Node REPL session. +With `viem`, we will create an account using the private key and create the RPC provider - -{

Import the Optimism SDK

} + -```js file=/public/tutorials/sdk-estimate-costs.js#L3 hash=26b2fdb17dd6c8326a54ec51f0769528 -``` +{

Import the Viem

} -{

Import ethers.js

} +```js -```js file=/public/tutorials/sdk-estimate-costs.js#L4 hash=69a65ef97862612e4978b8563e6dbe3a +// Import required modules +import { createPublicClient, http } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' +import { optimismSepolia } from 'viem/chains' +import { publicActionsL2 } from 'viem/op-stack' +import * as dotenv from 'dotenv'; +// Load environment variables +dotenv.config(); ```
@@ -116,59 +146,85 @@ You need to import some dependencies into your Node REPL session. You'll need a few variables throughout this tutorial. Let's set those up now. - - -{

Load your private key

} + + + To create the wallet instance, load your private key, using `privateKeyToAccount`. [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount#privatekeytoaccount) is a viem method used to sign transactions by passing a private key. -```js file=/public/tutorials/sdk-estimate-costs.js#L6 hash=755b77a7ffc7dfdc186f36c37d3d847a -``` + ```js + const account = privateKeyToAccount(process.env.PRIVATE_KEY); + ``` + -{

Create the RPC provider

} + + Set up our Viem Clients for the L1(Sepolia) and L2(optimismSepolia) -Here you're creating a standard Ethers RPC provider and wrapping it as an `L2Provider`, a class provided by the Optimism SDK. -This will add a few extra functions to the provider object that you'll use later in this tutorial. + ```js + const publicClient = createPublicClient({ + chain: optimismSepolia, + transport: http(process.env.RPC_URL), + }).extend(publicActionsL2()); + ``` -```js file=/public/tutorials/sdk-estimate-costs.js#L8 hash=1db780739476f924536f5fa58794b67f -``` + -{

Create the wallet instance

} - -```js file=/public/tutorials/sdk-estimate-costs.js#L9 hash=d315a1ba59b2ee3f43d178bab816e930 -``` - -
+ ## Estimate Transaction Costs -You're now going to use the Optimism SDK to estimate the cost of a transaction on OP Mainnet. +You're now going to estimate the cost of a transaction on OP Mainnet. Here you'll estimate the cost of a simple transaction that sends a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. {

Create the unsigned transaction

} -Ethers makes it easy to create unsigned transactions so you can estimate the cost of a transaction before you a user to sign it. +Viem makes it easy to create unsigned transactions so you can estimate the cost of a transaction before you sign it. Here you'll create an unsigned transaction that sends a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. -You can also create unsigned transactions that interact with contracts using [`Contract.populateTransaction`](https://docs.ethers.org/v5/api/contract/contract/#contract-populateTransaction). -```js file=/public/tutorials/sdk-estimate-costs.js#L11-L15 hash=22d44a7322d2d378e886a0ba5a0c6fec -``` + ```js + const tx = await publicClient.sendUnsignedTransaction({ + from: , + to: , + gasPrice: parseGwei('20'), + value: parseEther('1') + }) + ``` +{

Estimate Gas for a Transaction

} -{

Estimate the execution gas fee

} +Now that you have created an unsigned transaction that sends a small amount of ETH, we can estimate the gas for that transaction. We will use the `estimateGas` method from viem. -You can estimate the execution gas fee the same way you'd estimate the gas fee for any transaction on Ethereum. -Simply multiply the gas limit by the effective gas price. + ```js + const fromAddress = '0xYourAddress'; + const toAddress = '0xRecipientAddress'; + const value = 0.1n * 10n ** 18n; // 0.1 ETH in wei + + const gasEstimate = await client.estimateGas({ + from: fromAddress, + to: toAddress, + value: value, + }); + console.log(`Estimated Gas: ${gasEstimate}`); + ``` + + +{

Fetch Current Gas Price

} + +You can also fetch the current gas price on Op stack using the `getGasPrice` method from Viem. + + ```js + const gasPrice = await client.getGasPrice(); + console.log(`Current Gas Price: ${gasPrice}`); + ``` -```js file=/public/tutorials/sdk-estimate-costs.js#L18-L21 hash=8090c6513655722e1194d4d9f0f794af -``` {

Estimate the L1 data fee

} -You can estimate the L1 data fee with the [`estimateL1GasCost`](https://sdk.optimism.io/modules#estimateL1GasCost) function. -Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). -This function returns the current cost estimate in wei. +On Op stack, transactions also incur an L1 Data Fee (or calldata fee) because data is posted to Ethereum (Layer 1). +This fee depends on the size of the calldata used by the transaction. + +```js + -```js file=/public/tutorials/sdk-estimate-costs.js#L24-L25 hash=c5b1b1754aede507d071419fa051e3d7 ``` {

Estimate the total cost

} From 7ee6b5355b102decd7e0d61cb6d2ea0148f68f94 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 20 Sep 2024 20:21:31 +0300 Subject: [PATCH 02/19] Finished the estimating tx cost tut --- .../tutorials/sdk-estimate-costs.mdx | 121 +++++++++++------- words.txt | 1 - 2 files changed, 73 insertions(+), 49 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 8956dced5..64a7248cc 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -1,14 +1,12 @@ --- -title: Estimating Transaction Costs on OP Mainnet +title: Estimating Transaction Costs on OP Stack lang: en-US description: Learn how to use the Viem/op-stack to estimate the cost of a transaction on OP Mainnet. --- import { Callout, Steps, Tabs } from 'nextra/components' -import { WipCallout } from '@/components/WipCallout' - -# Estimating Transaction Costs on OP Mainnet +# Estimating Transaction Costs on OP Stack In this tutorial, you'll learn how to use the [Viem](https://viem.sh/op-stack/) to estimate the cost of a transaction on OP Mainnet. @@ -16,7 +14,7 @@ You'll learn how to estimate the [execution gas fee](/builders/app-developers/tr You'll also learn how to estimate the total cost of the transaction all at once. -Check out the full explainer on [OP Mainnet transaction fees](/builders/app-developers/transactions/fees) for more information on how OP Mainnet charges fees under the hood. +Check out the full explainer on [OP Stack transaction fees](/builders/app-developers/transactions/fees) for more information on how OP Mainnet charges fees under the hood. ## Prerequisites @@ -130,10 +128,10 @@ With `viem`, we will create an account using the private key and create the RPC ```js // Import required modules -import { createPublicClient, http } from 'viem' +import { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } from 'viem' import { privateKeyToAccount } from 'viem/accounts' import { optimismSepolia } from 'viem/chains' -import { publicActionsL2 } from 'viem/op-stack' +import { publicActionsL2, walletActionsL2 } from 'viem/op-stack' import * as dotenv from 'dotenv'; // Load environment variables dotenv.config(); @@ -146,7 +144,7 @@ dotenv.config(); You'll need a few variables throughout this tutorial. Let's set those up now. - + To create the wallet instance, load your private key, using `privateKeyToAccount`. [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount#privatekeytoaccount) is a viem method used to sign transactions by passing a private key. @@ -155,13 +153,25 @@ Let's set those up now. ``` + + Set up our Wallet Clients for L2(optimismSepolia) + + ```js + const walletClient = createWalletClient({ + chain: optimismSepolia, + transport: http(process.env.L2_RPC_URL), + }).extend(walletActionsL2()) + ``` + + + Set up our Viem Clients for the L1(Sepolia) and L2(optimismSepolia) ```js const publicClient = createPublicClient({ chain: optimismSepolia, - transport: http(process.env.RPC_URL), + transport: http(process.env.L2_RPC_URL), }).extend(publicActionsL2()); ``` @@ -172,95 +182,107 @@ Let's set those up now. ## Estimate Transaction Costs You're now going to estimate the cost of a transaction on OP Mainnet. -Here you'll estimate the cost of a simple transaction that sends a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. - -{

Create the unsigned transaction

} +{

Creating a Transaction in Viem

} -Viem makes it easy to create unsigned transactions so you can estimate the cost of a transaction before you sign it. -Here you'll create an unsigned transaction that sends a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. +Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. +Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. ```js - const tx = await publicClient.sendUnsignedTransaction({ - from: , - to: , - gasPrice: parseGwei('20'), - value: parseEther('1') - }) + const transaction = { + account, + to: '0x1000000000000000000000000000000000000000', + value: parseEther('0.1'), + gasPrice: parseGwei('20') + }; ``` -{

Estimate Gas for a Transaction

} +{

Estimate the execution gas fee

} + -Now that you have created an unsigned transaction that sends a small amount of ETH, we can estimate the gas for that transaction. We will use the `estimateGas` method from viem. +Now that you have prepared a transaction that sends a small amount of ETH, we can estimate the gas for that transaction by using the `estimateGas` method from viem. ```js - const fromAddress = '0xYourAddress'; - const toAddress = '0xRecipientAddress'; - const value = 0.1n * 10n ** 18n; // 0.1 ETH in wei - - const gasEstimate = await client.estimateGas({ - from: fromAddress, - to: toAddress, - value: value, - }); - console.log(`Estimated Gas: ${gasEstimate}`); + const gasLimit = await publicClient.estimateGas(transaction); + console.log(`Estimated Gas Limit: ${gasLimit}`); ``` + +{

Retrieve the current gas price

} -{

Fetch Current Gas Price

} +Retrieve the current gas price (effective gas price), Alternatively, given that you already set the gas price manually, you can use the `getGasPrice` method from viem. + + ```js + const effectiveGasPrice = await publicClient.getGasPrice(); + ``` +{

Calculate the execution gas fee

} -You can also fetch the current gas price on Op stack using the `getGasPrice` method from Viem. +To calculate the execution gas fee simply multiply the gas limit by the effective gas price. ```js - const gasPrice = await client.getGasPrice(); - console.log(`Current Gas Price: ${gasPrice}`); + const l2CostEstimate = gasLimit * effectiveGasPrice; + console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} wei`); ``` +
{

Estimate the L1 data fee

} -On Op stack, transactions also incur an L1 Data Fee (or calldata fee) because data is posted to Ethereum (Layer 1). -This fee depends on the size of the calldata used by the transaction. +You can estimate the L1 data fee with the [estimateL1GasCost](https://viem.sh/op-stack/actions/estimateL1Gas) function. +Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). +This function returns the current cost estimate in wei. + + ```js + const l1CostEstimate = await publicClient.estimateL1Gas(transaction) + console.log(`Estimated L1 data Fee: ${formatEther(l1CostEstimate)}`); + ``` -```js - -``` {

Estimate the total cost

} Once you've individually estimated the execution gas fee and the L1 data fee, you can sum these two values together to get the total cost of the transaction. -```js file=/public/tutorials/sdk-estimate-costs.js#L28-L29 hash=f7315f3dbf96423569a42c902eeee45c -``` + ```js + const totalSum = l2CostEstimate + l1CostEstimate; + console.log(`Estimated Total Cost: ${formatEther(totalSum)} `); + ``` {

Send the transaction

} Now that you've estimated the total cost of the transaction, go ahead and send it to the network. This will make it possible to see the actual cost of the transaction to compare to your estimate. -```js file=/public/tutorials/sdk-estimate-costs.js#L32-L34 hash=f0cc7ae37a28a884aa7f47f13b381681 +```js + const txHash = await walletClient.sendTransaction(transaction) ``` {

Check the actual execution gas fee

} Once you get back the transaction receipt, check the actual execution gas fee. -```js file=/public/tutorials/sdk-estimate-costs.js#L37-L38 hash=3b3ce48412906a44c1d2f6861a99c8a0 +```js +const l2CostActual = await publicClient.estimateL2Fee(txHash) + console.log(`l2CostActual gas fee: ${formatEther(l2CostActual)}`); ``` {

Check the actual L1 data fee

} You can also check the actual L1 data fee. -```js file=/public/tutorials/sdk-estimate-costs.js#L41-L42 hash=3438ad167823b837f3511759a06e73f3 +```js + const l1CostActual = await publicClient.estimateL1Fee(txHash) + console.log(`l1CostActual gas fee: ${formatEther(l1CostActual)}`); + ``` {

Check the actual total cost

} Sum these two together to get the actual total cost of the transaction. -```js file=/public/tutorials/sdk-estimate-costs.js#L45-L46 hash=d23b6db1b716cba154932fd3d261995e +```js + const totalActual = l2CostActual + l1CostActual; + console.log(`Total Actual Cost: ${formatEther(totalActual)}`); ``` {

Check the difference

} @@ -269,7 +291,10 @@ Finally, check the difference between the estimated total cost and the actual to This will give you a sense of how accurate your estimate was. Estimates will never be entirely accurate, but they should be close! -```js file=/public/tutorials/sdk-estimate-costs.js#L49-L50 hash=358adb5552c9f00484a6bb0580109fd8 +```js + const difference = totalSum - totalActual + console.log(`The difference - ${formatEther(difference)}`) + ```
diff --git a/words.txt b/words.txt index eec868c55..90467007b 100644 --- a/words.txt +++ b/words.txt @@ -101,7 +101,6 @@ EXTRADATA extradata Farcaster farcaster -Fastnode FDLIMIT fdlimit featureset From cefac45318b2d436143c39f60a4a72bfb3c6f691 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 20 Sep 2024 20:49:34 +0300 Subject: [PATCH 03/19] finish the tutorial --- .../tutorials/sdk-estimate-costs.mdx | 221 +++++++++--------- 1 file changed, 114 insertions(+), 107 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 64a7248cc..8777e5e50 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -8,13 +8,12 @@ import { Callout, Steps, Tabs } from 'nextra/components' # Estimating Transaction Costs on OP Stack - In this tutorial, you'll learn how to use the [Viem](https://viem.sh/op-stack/) to estimate the cost of a transaction on OP Mainnet. You'll learn how to estimate the [execution gas fee](/builders/app-developers/transactions/fees#execution-gas-fee) and the [L1 data fee](/builders/app-developers/transactions/fees#l1-data-fee) independently. You'll also learn how to estimate the total cost of the transaction all at once. -Check out the full explainer on [OP Stack transaction fees](/builders/app-developers/transactions/fees) for more information on how OP Mainnet charges fees under the hood. + Check out the full explainer on [OP Stack transaction fees](/builders/app-developers/transactions/fees) for more information on how OP Mainnet charges fees under the hood. ## Prerequisites @@ -60,7 +59,7 @@ npm install -g pnpm ``` {

Install dependencies

} - + Install `viem`, and `dotenv` for managing environment variables. ```bash @@ -68,7 +67,6 @@ npm install -g pnpm ```
- {

Configure Environment Variables

} You need a private key in order to sign transactions. @@ -80,28 +78,27 @@ npm install -g pnpm touch .env ``` - Add your wallet private key in the `.env` file. - You need a private key in order to sign transactions. - Make sure this private key corresponds to an address that has ETH on OP Sepolia. + Add your wallet private key in the `.env` file. + You need a private key in order to sign transactions. + Make sure this private key corresponds to an address that has ETH on OP Sepolia. - ```bash - RPC_URL=https://optimism-mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID - TUTORIAL_PRIVATE_KEY=0x... - ``` + ```bash + RPC_URL=https://optimism-mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID + TUTORIAL_PRIVATE_KEY=0x... + ```
Never share your private key and avoid committing this file to version control. - ## Get ETH on OP Sepolia This tutorial explains how estimate transaction costs on OP Sepolia. You will need to get some ETH on OP Sepolia in order to run the code in this tutorial. -You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. + You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. ## Start the Node REPL @@ -120,23 +117,20 @@ This will bring up a Node REPL prompt that allows you to run javascript code. You need to import some dependencies into your Node REPL session. With `viem`, we will create an account using the private key and create the RPC provider - - -{

Import the Viem

} - -```js - -// Import required modules -import { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } from 'viem' -import { privateKeyToAccount } from 'viem/accounts' -import { optimismSepolia } from 'viem/chains' -import { publicActionsL2, walletActionsL2 } from 'viem/op-stack' -import * as dotenv from 'dotenv'; -// Load environment variables -dotenv.config(); -``` - + {

Import the Viem

} + + ```js + + // Import required modules + import { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } from 'viem' + import { privateKeyToAccount } from 'viem/accounts' + import { optimismSepolia } from 'viem/chains' + import { publicActionsL2, walletActionsL2 } from 'viem/op-stack' + import * as dotenv from 'dotenv'; + // Load environment variables + dotenv.config(); + ```
## Set Session Variables @@ -153,7 +147,7 @@ Let's set those up now. ``` - + Set up our Wallet Clients for L2(optimismSepolia) ```js @@ -162,7 +156,6 @@ Let's set those up now. transport: http(process.env.L2_RPC_URL), }).extend(walletActionsL2()) ``` - @@ -174,127 +167,141 @@ Let's set those up now. transport: http(process.env.L2_RPC_URL), }).extend(publicActionsL2()); ``` - - ## Estimate Transaction Costs You're now going to estimate the cost of a transaction on OP Mainnet. - -{

Creating a Transaction in Viem

} - -Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. -Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. - - ```js - const transaction = { - account, - to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.1'), - gasPrice: parseGwei('20') - }; - ``` -{

Estimate the execution gas fee

} + + {

Creating a Transaction in Viem

} + + Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. + Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. + + ```js + const transaction = { + account, + to: '0x1000000000000000000000000000000000000000', + value: parseEther('0.1'), + gasPrice: parseGwei('20') + }; + ``` + {

Estimate the execution gas fee

} -Now that you have prepared a transaction that sends a small amount of ETH, we can estimate the gas for that transaction by using the `estimateGas` method from viem. + Now that you have prepared a transaction that sends a small amount of ETH, we can estimate the gas for that transaction by using the `estimateGas` method from viem. - ```js - const gasLimit = await publicClient.estimateGas(transaction); - console.log(`Estimated Gas Limit: ${gasLimit}`); - ``` - + ```js + const gasLimit = await publicClient.estimateGas(transaction); + console.log(`Estimated Gas Limit: ${gasLimit}`); + ``` -{

Retrieve the current gas price

} + + {

Retrieve the current gas price

} -Retrieve the current gas price (effective gas price), Alternatively, given that you already set the gas price manually, you can use the `getGasPrice` method from viem. + Retrieve the current gas price (effective gas price), Alternatively, given that you already set the gas price manually, you can use the `getGasPrice` method from viem. ```js const effectiveGasPrice = await publicClient.getGasPrice(); + console.log(`effective Gas Price, ${effectiveGasPrice}`); ``` -{

Calculate the execution gas fee

} -To calculate the execution gas fee simply multiply the gas limit by the effective gas price. + {

Calculate the execution gas fee

} + + To calculate the execution gas fee simply multiply the gas limit by the effective gas price. ```js const l2CostEstimate = gasLimit * effectiveGasPrice; - console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} wei`); + console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)}`); ``` +
-
- -{

Estimate the L1 data fee

} - -You can estimate the L1 data fee with the [estimateL1GasCost](https://viem.sh/op-stack/actions/estimateL1Gas) function. -Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). -This function returns the current cost estimate in wei. - - ```js - const l1CostEstimate = await publicClient.estimateL1Gas(transaction) - console.log(`Estimated L1 data Fee: ${formatEther(l1CostEstimate)}`); - ``` + {

Estimate the L1 data fee

} + You can estimate the L1 data fee with the [estimateL1GasCost](https://viem.sh/op-stack/actions/estimateL1Gas) function. + Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). + This function returns the current cost estimate in wei. + ```js + const l1CostEstimate = await publicClient.estimateL1Gas(transaction) + console.log(`Estimated L1 data Fee: ${formatEther(l1CostEstimate)}`); + ``` -{

Estimate the total cost

} + {

Estimate the total cost

} -Once you've individually estimated the execution gas fee and the L1 data fee, you can sum these two values together to get the total cost of the transaction. + Once you've individually estimated the execution gas fee and the L1 data fee, you can sum these two values together to get the total cost of the transaction. - ```js + ```js const totalSum = l2CostEstimate + l1CostEstimate; console.log(`Estimated Total Cost: ${formatEther(totalSum)} `); ``` -{

Send the transaction

} - -Now that you've estimated the total cost of the transaction, go ahead and send it to the network. -This will make it possible to see the actual cost of the transaction to compare to your estimate. + {

Send the transaction

} -```js - const txHash = await walletClient.sendTransaction(transaction) -``` + Now that you've estimated the total cost of the transaction, go ahead and send it to the network. + This will make it possible to see the actual cost of the transaction to compare to your estimate. -{

Check the actual execution gas fee

} + ```js + const txHash = await walletClient.sendTransaction(transaction) + console.log(`Transaction Hash: ${tx}`); + ``` -Once you get back the transaction receipt, check the actual execution gas fee. + {

Check the actual execution gas fee

} -```js -const l2CostActual = await publicClient.estimateL2Fee(txHash) - console.log(`l2CostActual gas fee: ${formatEther(l2CostActual)}`); -``` + Once you get back the transaction receipt, check the actual execution gas fee. + You can do so by accessing the `gasUsed` and `effectiveGasPrice` from the transaction receipt. + You can then multiply these values to get the actual L2 cost of the transaction -{

Check the actual L1 data fee

} + ```js + const receipt = await publicClient.getTransactionReceipt({ hash: txHash }); + console.log('Transaction receipt:', receipt); -You can also check the actual L1 data fee. + const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice; + console.log(`L2 Actual Cost: ${formatEther(l2CostActual)}`); + ``` -```js - const l1CostActual = await publicClient.estimateL1Fee(txHash) - console.log(`l1CostActual gas fee: ${formatEther(l1CostActual)}`); + {

Check the actual L1 data fee

} -``` + You can also check the actual L1 data fee. -{

Check the actual total cost

} + ```js + const l1CostActual = await publicClient.estimateL1Fee(txHash) + console.log(`l1CostActual gas fee: ${formatEther(l1CostActual)}`); -Sum these two together to get the actual total cost of the transaction. + ``` -```js - const totalActual = l2CostActual + l1CostActual; - console.log(`Total Actual Cost: ${formatEther(totalActual)}`); -``` + {

Check the actual total cost

} -{

Check the difference

} + Sum these two together to get the actual total cost of the transaction. -Finally, check the difference between the estimated total cost and the actual total cost. -This will give you a sense of how accurate your estimate was. -Estimates will never be entirely accurate, but they should be close! + ```js + const totalActual = l2CostActual + l1CostActual; + console.log(`Total Actual Cost: ${formatEther(totalActual)}`); + ``` -```js - const difference = totalSum - totalActual - console.log(`The difference - ${formatEther(difference)}`) + {

Check the difference

} -``` + Finally, check the difference between the estimated total cost and the actual total cost. + This will give you a sense of how accurate your estimate was. + Estimates will never be entirely accurate, but they should be close! + ```js + const difference = totalSum - totalActual + console.log(`The difference - ${formatEther(difference)}`) + ```
+ + +Estimates will never be entirely accurate due to network conditions and gas price fluctuations, but they should be close to the actual costs. + + +## Next Steps + +* Always estimate before sending: Estimating costs before sending a transaction helps prevent unexpected fees and failed transactions. +* Account for gas price volatility: Gas prices can change rapidly. Consider adding a buffer to your estimates or implementing a gas price oracle for more accurate pricing. +* Optimize transaction data: Minimize the amount of data in your transactions to reduce L1 data fees. +* Monitor network conditions: Keep an eye on network congestion and adjust your estimates accordingly. +* Use appropriate gas limits: Setting too low a gas limit can cause transactions to fail, while setting it too high can result in unnecessary costs. +* Implement retry mechanisms: If a transaction fails due to underestimated gas, implement a retry mechanism with adjusted gas parameters. From 354d2a74c56ad1482afe02cd3e91e823e99907a8 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 20 Sep 2024 21:35:52 +0300 Subject: [PATCH 04/19] push full code snippet --- public/tutorials/sdk-estimate-costs.js | 107 ++++++++++++++++--------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index f223f0026..a4fb2509b 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -1,52 +1,81 @@ -(async () => { +import { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' +import { optimismSepolia } from 'viem/chains' +import { publicActionsL2, walletActionsL2 } from 'viem/op-stack' +import * as dotenv from 'dotenv' -const optimism = require("@eth-optimism/sdk") -const ethers = require("ethers") +// Load environment variables +dotenv.config() -const privateKey = process.env.TUTORIAL_PRIVATE_KEY +// Set up the account +const account = privateKeyToAccount(process.env.PRIVATE_KEY) -const provider = optimism.asL2Provider(new ethers.providers.StaticJsonRpcProvider("https://sepolia.optimism.io")) -const wallet = new ethers.Wallet(privateKey, provider) +// Set up the public client +const publicClient = createPublicClient({ + chain: optimismSepolia, + transport: http(process.env.L2_RPC_URL), +}).extend(publicActionsL2()) -const tx = await wallet.populateTransaction({ - to: '0x1000000000000000000000000000000000000000', - value: ethers.utils.parseEther('0.00069420'), - gasPrice: await provider.getGasPrice(), -}) +// Set up the wallet client +const walletClient = createWalletClient({ + chain: optimismSepolia, + transport: http(process.env.L2_RPC_URL), +}).extend(walletActionsL2()) -console.log('Estimating L2 cost...') -const gasLimit = tx.gasLimit -const gasPrice = tx.maxFeePerGas -const l2CostEstimate = gasLimit.mul(gasPrice) -console.log(ethers.utils.formatEther(l2CostEstimate)) +async function estimateTransactionCosts() { + try { + // Prepare the transaction + const transaction = { + account, + to: '0x1000000000000000000000000000000000000000', + value: parseEther('0.1'), + gasPrice: parseGwei('20') + } -console.log('Estimating L1 cost...') -const l1CostEstimate = await provider.estimateL1GasCost(tx) -console.log(ethers.utils.formatEther(l1CostEstimate)) + // Estimate gas limit + const gasLimit = await publicClient.estimateGas(transaction) + console.log(`Estimated Gas Limit: ${gasLimit}`) -console.log('Summing total cost...') -const totalSum = l2CostEstimate.add(l1CostEstimate) -console.log(ethers.utils.formatEther(totalSum)) + // Get current gas price + const effectiveGasPrice = await publicClient.getGasPrice() + console.log(`Effective Gas Price: ${formatEther(effectiveGasPrice)} ETH`) -console.log('Sending transaction...') -const res = await wallet.sendTransaction(tx) -const receipt = await res.wait() -console.log(receipt.transactionHash) + // Calculate execution gas fee + const l2CostEstimate = gasLimit * effectiveGasPrice + console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} ETH`) -console.log('Actual L2 cost:') -const l2CostActual = receipt.gasUsed.mul(receipt.effectiveGasPrice) -console.log(ethers.utils.formatEther(l2CostActual)) + // Estimate L1 data fee + const l1CostEstimate = await publicClient.estimateL1Gas(transaction) + console.log(`Estimated L1 Data Fee: ${formatEther(l1CostEstimate)} ETH`) -console.log('Actual L1 cost:') -const l1CostActual = receipt.l1Fee -console.log(ethers.utils.formatEther(l1CostActual)) + // Calculate total estimated cost + const totalEstimate = l2CostEstimate + l1CostEstimate + console.log(`Estimated Total Cost: ${formatEther(totalEstimate)} ETH`) -console.log('Actual total cost:') -const totalActual = l2CostActual.add(l1CostActual) -console.log(ethers.utils.formatEther(totalActual)) + // Send the transaction + const txHash = await walletClient.sendTransaction(transaction) + console.log(`Transaction Hash: ${txHash}`) -console.log('Difference:') -const difference = totalActual.sub(totalSum).abs() -console.log(ethers.utils.formatEther(difference)) + // Wait for the transaction to be mined + const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }) -})() + // Calculate actual costs + const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice + console.log(`Actual Execution Gas Fee: ${formatEther(l2CostActual)} ETH`) + + const l1CostActual = await publicClient.estimateL1Fee({ hash: txHash }) + console.log(`Actual L1 Data Fee: ${formatEther(l1CostActual)} ETH`) + + const totalActual = l2CostActual + l1CostActual + console.log(`Actual Total Cost: ${formatEther(totalActual)} ETH`) + + // Compare estimated vs actual costs + const difference = totalEstimate - totalActual + console.log(`Estimation Difference: ${formatEther(difference)} ETH`) + + } catch (error) { + console.error('Error:', error) + } +} + +estimateTransactionCosts() \ No newline at end of file From d09716789daefdfa5b803dba9a8e9fad6a816936 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Tue, 24 Sep 2024 14:36:04 +0300 Subject: [PATCH 05/19] updated header --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 8777e5e50..78f9aef19 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -115,10 +115,9 @@ This will bring up a Node REPL prompt that allows you to run javascript code. ## Import Dependencies You need to import some dependencies into your Node REPL session. -With `viem`, we will create an account using the private key and create the RPC provider - {

Import the Viem

} + {

Import the necessary packages

} ```js From 9ec6760bf86c0c8549cf299ae56f7d02e629ede2 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Tue, 24 Sep 2024 14:55:50 +0300 Subject: [PATCH 06/19] update description --- .../builders/app-developers/tutorials/sdk-estimate-costs.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 78f9aef19..614303f54 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -45,11 +45,12 @@ npm install -g pnpm Let's create a new project and install the necessary dependencies. - {

Create a folder

} + {

Create a folder and new file

} ```bash mkdir op-sample-project cd op-sample-project + touch estimate-costs.js ``` {

Initialize the project

} @@ -119,6 +120,8 @@ You need to import some dependencies into your Node REPL session. {

Import the necessary packages

} + In your project directory and add the following code in `estimate-costs.js`: + ```js // Import required modules From 5606494c85b0956d60eb297ba74343912d9b9868 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Tue, 24 Sep 2024 15:21:14 +0100 Subject: [PATCH 07/19] updated codebase --- .../tutorials/sdk-estimate-costs.mdx | 14 +++++++++++--- public/tutorials/sdk-estimate-costs.js | 10 ++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 614303f54..f93e98172 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -145,10 +145,18 @@ Let's set those up now. To create the wallet instance, load your private key, using `privateKeyToAccount`. [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount#privatekeytoaccount) is a viem method used to sign transactions by passing a private key. ```js + if (!process.env.PRIVATE_KEY) { + throw new Error('Error: PRIVATE_KEY is not defined in the environment variables.') + } const account = privateKeyToAccount(process.env.PRIVATE_KEY); ```
+ + To ensure that `process.env.PRIVATE_KEY` is defined before using it. If they are undefined, we add a check to provide a error messages when the environment variable is missing. + + + Set up our Wallet Clients for L2(optimismSepolia) @@ -227,7 +235,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. This function returns the current cost estimate in wei. ```js - const l1CostEstimate = await publicClient.estimateL1Gas(transaction) + const l1CostEstimate = await publicClient.estimateL1Fee(transaction) console.log(`Estimated L1 data Fee: ${formatEther(l1CostEstimate)}`); ``` @@ -290,8 +298,8 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Estimates will never be entirely accurate, but they should be close! ```js - const difference = totalSum - totalActual - console.log(`The difference - ${formatEther(difference)}`) + const difference = totalEstimate >= totalActual ? totalEstimate - totalActual : totalActual - totalEstimate + console.log(`Estimation Difference: ${formatEther(difference)} ETH`) ``` diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index a4fb2509b..784533937 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -8,6 +8,12 @@ import * as dotenv from 'dotenv' dotenv.config() // Set up the account +if (!process.env.PRIVATE_KEY) { + throw new Error('Error: PRIVATE_KEY is not defined in the environment variables.') + } + if (!process.env.L2_RPC_URL) { + throw new Error('Error: L2_RPC_URL is not defined in the environment variables.') + } const account = privateKeyToAccount(process.env.PRIVATE_KEY) // Set up the public client @@ -45,7 +51,7 @@ async function estimateTransactionCosts() { console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} ETH`) // Estimate L1 data fee - const l1CostEstimate = await publicClient.estimateL1Gas(transaction) + const l1CostEstimate = await publicClient.estimateL1Fee(transaction) console.log(`Estimated L1 Data Fee: ${formatEther(l1CostEstimate)} ETH`) // Calculate total estimated cost @@ -70,7 +76,7 @@ async function estimateTransactionCosts() { console.log(`Actual Total Cost: ${formatEther(totalActual)} ETH`) // Compare estimated vs actual costs - const difference = totalEstimate - totalActual + const difference = totalEstimate >= totalActual ? totalEstimate - totalActual : totalActual - totalEstimate console.log(`Estimation Difference: ${formatEther(difference)} ETH`) } catch (error) { From 70bf529e097c31ab3eb70d0eaa9f755c9b50b507 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Tue, 24 Sep 2024 15:23:32 +0100 Subject: [PATCH 08/19] updated amount --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 2 +- public/tutorials/sdk-estimate-costs.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index f93e98172..54118b7b3 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -194,7 +194,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. const transaction = { account, to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.1'), + value: parseEther('0.005'), gasPrice: parseGwei('20') }; ``` diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index 784533937..0f0fbce23 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -34,7 +34,7 @@ async function estimateTransactionCosts() { const transaction = { account, to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.1'), + value: parseEther('0.005'), gasPrice: parseGwei('20') } From 8427f6221c0815ee7093d98c6674f329e5b9d962 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 2 Oct 2024 23:49:28 +0100 Subject: [PATCH 09/19] Updated codebase --- .../tutorials/sdk-estimate-costs.mdx | 204 +++++++----------- public/tutorials/sdk-estimate-costs.js | 36 ++-- words.txt | 1 + 3 files changed, 98 insertions(+), 143 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 54118b7b3..83b7593c5 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -16,176 +16,137 @@ You'll also learn how to estimate the total cost of the transaction all at once. Check out the full explainer on [OP Stack transaction fees](/builders/app-developers/transactions/fees) for more information on how OP Mainnet charges fees under the hood. -## Prerequisites +## Supported Networks -Before you begin, ensure you have the following: +Viem supports any of the [Superchain networks](/chain/networks). +The OP Stack networks are included in Viem by default. +If you want to use a network that isn't included by default, you can add it to Viem's chain configurations. -* Node.js (version 14 or later) -* An understanding of the [viem library](https://viem.sh/op-stack/) -* `pnpm` installed for managing packages. - -## Required Dependencies +## Dependencies * [node](https://nodejs.org/en/) * [pnpm](https://pnpm.io/installation) -* [viem](https://viem.sh/op-stack/) - -Install `pnpm` if you haven't already: - -```bash -npm install -g pnpm - -``` ## Create a Demo Project - - {

Project Setup

} - - Let's create a new project and install the necessary dependencies. - - - {

Create a folder and new file

} - - ```bash - mkdir op-sample-project - cd op-sample-project - touch estimate-costs.js - ``` - - {

Initialize the project

} - - ```bash - pnpm init - ``` - - {

Install dependencies

} - - Install `viem`, and `dotenv` for managing environment variables. +You're going to use Viem for this tutorial. +Since Viem is a [Node.js](https://nodejs.org/en/) library, you'll need to create a Node.js project to use it. - ```bash - pnpm add viem dotenv - ``` -
+ + {

Make a Project Folder

} - {

Configure Environment Variables

} + ```bash + mkdir op-sample-project + cd op-sample-project + ``` - You need a private key in order to sign transactions. - Create a `.env` file to securely store your environment variables - Set your private key as an environment variable with the `export` command. - Make sure this private key corresponds to an address that has ETH on Sepolia. + {

Initialize the Project

} ```bash - touch .env + pnpm init ``` - Add your wallet private key in the `.env` file. - You need a private key in order to sign transactions. - Make sure this private key corresponds to an address that has ETH on OP Sepolia. + {

Install the viem library

} ```bash - RPC_URL=https://optimism-mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID - TUTORIAL_PRIVATE_KEY=0x... + pnpm add viem ```
- - Never share your private key and avoid committing this file to version control. + + Want to create a new wallet for this tutorial? + If you have [`cast`](https://book.getfoundry.sh/getting-started/installation) installed you can run `cast wallet new` in your terminal to create a new wallet and get the private key. -## Get ETH on OP Sepolia +## Get ETH on Sepolia -This tutorial explains how estimate transaction costs on OP Sepolia. -You will need to get some ETH on OP Sepolia in order to run the code in this tutorial. +This tutorial explains how to bridge ETH from Sepolia to OP Sepolia. +You will need to get some ETH on Sepolia to follow along. - You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. + You can use [this faucet](https://sepoliafaucet.com) to get ETH on Sepolia. +## Add a Private Key to Your Environment + +You need a private key in order to sign transactions. +Set your private key as an environment variable with the export command. +Make sure this private key corresponds to an address that has ETH on Sepolia. + +```bash +export TUTORIAL_PRIVATE_KEY=0x... +``` + ## Start the Node REPL -You're going to use the Node REPL to interact with the Viem library. +You're going to use the Node REPL to interact with Viem. To start the Node REPL run the following command in your terminal: ```bash node ``` -This will bring up a Node REPL prompt that allows you to run javascript code. - -## Import Dependencies +This will bring up a Node REPL prompt that allows you to run JavaScript code. -You need to import some dependencies into your Node REPL session. - - {

Import the necessary packages

} +## Get ETH on OP Sepolia - In your project directory and add the following code in `estimate-costs.js`: +This tutorial explains how estimate transaction costs on OP Sepolia. +You will need to get some ETH on OP Sepolia in order to run the code in this tutorial. - ```js + + You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. + - // Import required modules - import { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } from 'viem' - import { privateKeyToAccount } from 'viem/accounts' - import { optimismSepolia } from 'viem/chains' - import { publicActionsL2, walletActionsL2 } from 'viem/op-stack' - import * as dotenv from 'dotenv'; - // Load environment variables - dotenv.config(); - ``` -
+This will bring up a Node REPL prompt that allows you to run javascript code. ## Set Session Variables You'll need a few variables throughout this tutorial. Let's set those up now. - - - To create the wallet instance, load your private key, using `privateKeyToAccount`. [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount#privatekeytoaccount) is a viem method used to sign transactions by passing a private key. + - ```js - if (!process.env.PRIVATE_KEY) { - throw new Error('Error: PRIVATE_KEY is not defined in the environment variables.') - } - const account = privateKeyToAccount(process.env.PRIVATE_KEY); - ``` - +{

Import Viem and other necessary modules

} - - To ensure that `process.env.PRIVATE_KEY` is defined before using it. If they are undefined, we add a check to provide a error messages when the environment variable is missing. - +```js +const { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } = require('viem'); +const { privateKeyToAccount } = require('viem/accounts'); +const { optimismSepolia } = require('viem/chains'); +const { publicActionsL2, walletActionsL2 } = require('viem/op-stack'); +``` - - Set up our Wallet Clients for L2(optimismSepolia) +{

Set up the account

} - ```js - const walletClient = createWalletClient({ - chain: optimismSepolia, - transport: http(process.env.L2_RPC_URL), - }).extend(walletActionsL2()) - ``` -
+```js +const account = privateKeyToAccount(process.env.TUTORIAL_PRIVATE_KEY); +``` +{

Create the public client

} - - Set up our Viem Clients for the L1(Sepolia) and L2(optimismSepolia) +```js +const publicClientL2 = createPublicClient({ + chain: optimismSepolia, + transport: http("https://sepolia.optimism.io"), +}).extend(publicActionsL2()); +``` - ```js - const publicClient = createPublicClient({ - chain: optimismSepolia, - transport: http(process.env.L2_RPC_URL), - }).extend(publicActionsL2()); - ``` - -
+{

Create the wallet client

} + +```js +const walletClientL2 = createWalletClient({ + chain: optimismSepolia, + transport: http("https://sepolia.optimism.io"), +}).extend(walletActionsL2()); +``` +
## Estimate Transaction Costs You're now going to estimate the cost of a transaction on OP Mainnet. - {

Creating a Transaction in Viem

} + {

Define the transaction

} Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. @@ -198,13 +159,14 @@ You're now going to estimate the cost of a transaction on OP Mainnet. gasPrice: parseGwei('20') }; ``` + This transaction will send `0.005` ETH to the specified address with a gas price of 20 Gwei. {

Estimate the execution gas fee

} - Now that you have prepared a transaction that sends a small amount of ETH, we can estimate the gas for that transaction by using the `estimateGas` method from viem. + Now, let's estimate the gas limit for our transaction. ```js - const gasLimit = await publicClient.estimateGas(transaction); + const gasLimit = await publicClientL2.estimateGas(transaction); console.log(`Estimated Gas Limit: ${gasLimit}`); ``` @@ -214,7 +176,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Retrieve the current gas price (effective gas price), Alternatively, given that you already set the gas price manually, you can use the `getGasPrice` method from viem. ```js - const effectiveGasPrice = await publicClient.getGasPrice(); + const effectiveGasPrice = await publicClientL2.getGasPrice(); console.log(`effective Gas Price, ${effectiveGasPrice}`); ``` @@ -235,7 +197,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. This function returns the current cost estimate in wei. ```js - const l1CostEstimate = await publicClient.estimateL1Fee(transaction) + const l1CostEstimate = await publicClientL2.estimateL1Fee(transaction) console.log(`Estimated L1 data Fee: ${formatEther(l1CostEstimate)}`); ``` @@ -244,8 +206,8 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Once you've individually estimated the execution gas fee and the L1 data fee, you can sum these two values together to get the total cost of the transaction. ```js - const totalSum = l2CostEstimate + l1CostEstimate; - console.log(`Estimated Total Cost: ${formatEther(totalSum)} `); + const totalEstimate = l2CostEstimate + l1CostEstimate; + console.log(`Estimated Total Cost: ${formatEther(totalEstimate)} `); ``` {

Send the transaction

} @@ -254,8 +216,8 @@ You're now going to estimate the cost of a transaction on OP Mainnet. This will make it possible to see the actual cost of the transaction to compare to your estimate. ```js - const txHash = await walletClient.sendTransaction(transaction) - console.log(`Transaction Hash: ${tx}`); + const txHash = await walletClientL2.sendTransaction(transaction) + console.log(`Transaction Hash: ${txHash}`); ``` {

Check the actual execution gas fee

} @@ -265,7 +227,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. You can then multiply these values to get the actual L2 cost of the transaction ```js - const receipt = await publicClient.getTransactionReceipt({ hash: txHash }); + const receipt = await publicClientL2.getTransactionReceipt({ hash: txHash }); console.log('Transaction receipt:', receipt); const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice; @@ -277,7 +239,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. You can also check the actual L1 data fee. ```js - const l1CostActual = await publicClient.estimateL1Fee(txHash) + const l1CostActual = await publicClientL2.estimateL1Fee(txHash) console.log(`l1CostActual gas fee: ${formatEther(l1CostActual)}`); ``` diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index 0f0fbce23..95ab5e553 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -1,34 +1,26 @@ -import { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } from 'viem' -import { privateKeyToAccount } from 'viem/accounts' -import { optimismSepolia } from 'viem/chains' -import { publicActionsL2, walletActionsL2 } from 'viem/op-stack' -import * as dotenv from 'dotenv' - -// Load environment variables -dotenv.config() - -// Set up the account -if (!process.env.PRIVATE_KEY) { - throw new Error('Error: PRIVATE_KEY is not defined in the environment variables.') - } - if (!process.env.L2_RPC_URL) { - throw new Error('Error: L2_RPC_URL is not defined in the environment variables.') - } -const account = privateKeyToAccount(process.env.PRIVATE_KEY) +(async () => { + +const { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } = require('viem'); +const { privateKeyToAccount } = require('viem/accounts'); +const { optimismSepolia } = require('viem/chains'); +const { publicActionsL2, walletActionsL2 } = require('viem/op-stack'); + +const privateKey = process.env.TUTORIAL_PRIVATE_KEY + +const account = privateKeyToAccount(privateKey) // Set up the public client const publicClient = createPublicClient({ chain: optimismSepolia, - transport: http(process.env.L2_RPC_URL), + transport: http("https://sepolia.optimism.io"), }).extend(publicActionsL2()) // Set up the wallet client const walletClient = createWalletClient({ chain: optimismSepolia, - transport: http(process.env.L2_RPC_URL), + transport: http("https://sepolia.optimism.io"), }).extend(walletActionsL2()) -async function estimateTransactionCosts() { try { // Prepare the transaction const transaction = { @@ -82,6 +74,6 @@ async function estimateTransactionCosts() { } catch (error) { console.error('Error:', error) } -} -estimateTransactionCosts() \ No newline at end of file + +})() \ No newline at end of file diff --git a/words.txt b/words.txt index 90467007b..111fbfd7d 100644 --- a/words.txt +++ b/words.txt @@ -362,6 +362,7 @@ VHOSTS vhosts Viem viem +Viem's VMDEBUG vmdebug VMODULE From d88c7fbd47eb73b554e91a99646d04da891add78 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Thu, 3 Oct 2024 18:18:06 +0100 Subject: [PATCH 10/19] use file format system --- .../tutorials/sdk-estimate-costs.mdx | 97 ++++++------------- public/tutorials/sdk-estimate-costs.js | 75 ++++++-------- 2 files changed, 55 insertions(+), 117 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 83b7593c5..125205d4d 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -109,35 +109,22 @@ Let's set those up now. {

Import Viem and other necessary modules

} -```js - -const { createPublicClient, createWalletClient, http, parseEther, parseGwei, formatEther } = require('viem'); -const { privateKeyToAccount } = require('viem/accounts'); -const { optimismSepolia } = require('viem/chains'); -const { publicActionsL2, walletActionsL2 } = require('viem/op-stack'); +```js file=/public/tutorials/sdk-estimate-costs.js#L3-L6 hash=32ecaac58846bfe7e785e2cc35562120 ``` {

Set up the account

} -```js -const account = privateKeyToAccount(process.env.TUTORIAL_PRIVATE_KEY); +```js file=/public/tutorials/sdk-estimate-costs.js#L8-L9 hash=165490e75b825c786a937fba7b8e159d ``` + {

Create the public client

} -```js -const publicClientL2 = createPublicClient({ - chain: optimismSepolia, - transport: http("https://sepolia.optimism.io"), -}).extend(publicActionsL2()); +```js file=/public/tutorials/sdk-estimate-costs.js#L11-L14 hash=42293ff382c932f806beb7252803a848 ``` {

Create the wallet client

} -```js -const walletClientL2 = createWalletClient({ - chain: optimismSepolia, - transport: http("https://sepolia.optimism.io"), -}).extend(walletActionsL2()); +```js file=/public/tutorials/sdk-estimate-costs.js#L16-L19 hash=e7b6423850765242512e71589382791b ```
@@ -151,43 +138,31 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. - ```js - const transaction = { - account, - to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.005'), - gasPrice: parseGwei('20') - }; - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L21-L26 hash=583ee48142f33686188a7bf1cc312a1c +``` This transaction will send `0.005` ETH to the specified address with a gas price of 20 Gwei. {

Estimate the execution gas fee

} Now, let's estimate the gas limit for our transaction. - ```js - const gasLimit = await publicClientL2.estimateGas(transaction); - console.log(`Estimated Gas Limit: ${gasLimit}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L28-L29 hash=014939607bf2444d5f2e5a7babb02a46 +``` {

Retrieve the current gas price

} Retrieve the current gas price (effective gas price), Alternatively, given that you already set the gas price manually, you can use the `getGasPrice` method from viem. - ```js - const effectiveGasPrice = await publicClientL2.getGasPrice(); - console.log(`effective Gas Price, ${effectiveGasPrice}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L31-L32 hash=b43ae2cb1a7471de55858fbc7f7fe5a6 +``` {

Calculate the execution gas fee

} To calculate the execution gas fee simply multiply the gas limit by the effective gas price. - ```js - const l2CostEstimate = gasLimit * effectiveGasPrice; - console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L34-L35 hash=3e536e97b83458d3d3c7545b2c74ffd6 +```
{

Estimate the L1 data fee

} @@ -196,29 +171,23 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). This function returns the current cost estimate in wei. - ```js - const l1CostEstimate = await publicClientL2.estimateL1Fee(transaction) - console.log(`Estimated L1 data Fee: ${formatEther(l1CostEstimate)}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L37-L38 hash=b1ef73988e0876529a72b61d5822cbe1 +``` {

Estimate the total cost

} Once you've individually estimated the execution gas fee and the L1 data fee, you can sum these two values together to get the total cost of the transaction. - ```js - const totalEstimate = l2CostEstimate + l1CostEstimate; - console.log(`Estimated Total Cost: ${formatEther(totalEstimate)} `); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L40-L41 hash=8685f586913b87a5881cc6f917d0de50 +``` {

Send the transaction

} Now that you've estimated the total cost of the transaction, go ahead and send it to the network. This will make it possible to see the actual cost of the transaction to compare to your estimate. - ```js - const txHash = await walletClientL2.sendTransaction(transaction) - console.log(`Transaction Hash: ${txHash}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L43-L44 hash=a0a19fa7fc17165d934cc9f7af075464 +``` {

Check the actual execution gas fee

} @@ -226,32 +195,22 @@ You're now going to estimate the cost of a transaction on OP Mainnet. You can do so by accessing the `gasUsed` and `effectiveGasPrice` from the transaction receipt. You can then multiply these values to get the actual L2 cost of the transaction - ```js - const receipt = await publicClientL2.getTransactionReceipt({ hash: txHash }); - console.log('Transaction receipt:', receipt); - - const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice; - console.log(`L2 Actual Cost: ${formatEther(l2CostActual)}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L46-L49 hash=e128f21d2c994f42bdc7f5fb51eb127d +``` {

Check the actual L1 data fee

} You can also check the actual L1 data fee. - ```js - const l1CostActual = await publicClientL2.estimateL1Fee(txHash) - console.log(`l1CostActual gas fee: ${formatEther(l1CostActual)}`); - - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L51-L52 hash=ea1801a7618fa2a21f02a97717380f42 +``` {

Check the actual total cost

} Sum these two together to get the actual total cost of the transaction. - ```js - const totalActual = l2CostActual + l1CostActual; - console.log(`Total Actual Cost: ${formatEther(totalActual)}`); - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L54-L56 hash=6f7943da9d70654dc040b5561b3b360d +``` {

Check the difference

} @@ -259,10 +218,8 @@ You're now going to estimate the cost of a transaction on OP Mainnet. This will give you a sense of how accurate your estimate was. Estimates will never be entirely accurate, but they should be close! - ```js - const difference = totalEstimate >= totalActual ? totalEstimate - totalActual : totalActual - totalEstimate - console.log(`Estimation Difference: ${formatEther(difference)} ETH`) - ``` +```js file=/public/tutorials/sdk-estimate-costs.js#L57-L58 hash=20c8c60af1cc39e842b207cfd2dfa2cb +``` diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index 95ab5e553..15e2a7505 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -6,74 +6,55 @@ const { optimismSepolia } = require('viem/chains'); const { publicActionsL2, walletActionsL2 } = require('viem/op-stack'); const privateKey = process.env.TUTORIAL_PRIVATE_KEY - const account = privateKeyToAccount(privateKey) -// Set up the public client const publicClient = createPublicClient({ chain: optimismSepolia, transport: http("https://sepolia.optimism.io"), }).extend(publicActionsL2()) -// Set up the wallet client -const walletClient = createWalletClient({ +const walletClientL2 = createWalletClient({ chain: optimismSepolia, transport: http("https://sepolia.optimism.io"), }).extend(walletActionsL2()) - try { - // Prepare the transaction - const transaction = { - account, - to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.005'), - gasPrice: parseGwei('20') - } - - // Estimate gas limit - const gasLimit = await publicClient.estimateGas(transaction) - console.log(`Estimated Gas Limit: ${gasLimit}`) - - // Get current gas price - const effectiveGasPrice = await publicClient.getGasPrice() - console.log(`Effective Gas Price: ${formatEther(effectiveGasPrice)} ETH`) + const transaction = { + account, + to: '0x1000000000000000000000000000000000000000', + value: parseEther('0.005'), + gasPrice: parseGwei('20') + } - // Calculate execution gas fee - const l2CostEstimate = gasLimit * effectiveGasPrice - console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} ETH`) + const gasLimit = await publicClient.estimateGas(transaction) + console.log(`Estimated Gas Limit: ${gasLimit}`) - // Estimate L1 data fee - const l1CostEstimate = await publicClient.estimateL1Fee(transaction) - console.log(`Estimated L1 Data Fee: ${formatEther(l1CostEstimate)} ETH`) + const effectiveGasPrice = await publicClient.getGasPrice() + console.log(`Effective Gas Price: ${formatEther(effectiveGasPrice)} ETH`) - // Calculate total estimated cost - const totalEstimate = l2CostEstimate + l1CostEstimate - console.log(`Estimated Total Cost: ${formatEther(totalEstimate)} ETH`) + const l2CostEstimate = gasLimit * effectiveGasPrice + console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} ETH`) - // Send the transaction - const txHash = await walletClient.sendTransaction(transaction) - console.log(`Transaction Hash: ${txHash}`) + const l1CostEstimate = await publicClient.estimateL1Fee(transaction) + console.log(`Estimated L1 Data Fee: ${formatEther(l1CostEstimate)} ETH`) - // Wait for the transaction to be mined - const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }) + const totalEstimate = l2CostEstimate + l1CostEstimate + console.log(`Estimated Total Cost: ${formatEther(totalEstimate)} ETH`) - // Calculate actual costs - const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice - console.log(`Actual Execution Gas Fee: ${formatEther(l2CostActual)} ETH`) + const txHash = await walletClientL2.sendTransaction(transaction) + console.log(`Transaction Hash: ${txHash}`) - const l1CostActual = await publicClient.estimateL1Fee({ hash: txHash }) - console.log(`Actual L1 Data Fee: ${formatEther(l1CostActual)} ETH`) + const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }) - const totalActual = l2CostActual + l1CostActual - console.log(`Actual Total Cost: ${formatEther(totalActual)} ETH`) + const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice + console.log(`Actual Execution Gas Fee: ${formatEther(l2CostActual)} ETH`) - // Compare estimated vs actual costs - const difference = totalEstimate >= totalActual ? totalEstimate - totalActual : totalActual - totalEstimate - console.log(`Estimation Difference: ${formatEther(difference)} ETH`) + const l1CostActual = await publicClient.estimateL1Fee({ hash: txHash }) + console.log(`Actual L1 Data Fee: ${formatEther(l1CostActual)} ETH`) - } catch (error) { - console.error('Error:', error) - } + const totalActual = l2CostActual + l1CostActual + console.log(`Actual Total Cost: ${formatEther(totalActual)} ETH`) + const difference = totalEstimate >= totalActual ? totalEstimate - totalActual : totalActual - totalEstimate + console.log(`Estimation Difference: ${formatEther(difference)} ETH`) })() \ No newline at end of file From 62564df7019ff19300af31bc0a81fbd468f6932e Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 9 Oct 2024 21:40:59 +0100 Subject: [PATCH 11/19] Update pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx Co-authored-by: smartcontracts --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 125205d4d..74e3af0bc 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -46,7 +46,7 @@ Since Viem is a [Node.js](https://nodejs.org/en/) library, you'll need to create pnpm init ``` - {

Install the viem library

} + {

Install Viem

} ```bash pnpm add viem From 3861865d19a9b7589c2b68a0fd71a5a6e4329f5d Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 9 Oct 2024 21:41:09 +0100 Subject: [PATCH 12/19] Update pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx Co-authored-by: smartcontracts --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 74e3af0bc..33a02c63d 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -8,7 +8,7 @@ import { Callout, Steps, Tabs } from 'nextra/components' # Estimating Transaction Costs on OP Stack -In this tutorial, you'll learn how to use the [Viem](https://viem.sh/op-stack/) to estimate the cost of a transaction on OP Mainnet. +In this tutorial, you'll learn how to use [Viem](https://viem.sh/op-stack/) to estimate the cost of a transaction on OP Mainnet. You'll learn how to estimate the [execution gas fee](/builders/app-developers/transactions/fees#execution-gas-fee) and the [L1 data fee](/builders/app-developers/transactions/fees#l1-data-fee) independently. You'll also learn how to estimate the total cost of the transaction all at once. From 1eac1a96c7d35d51f4bc1565a3be6044c06452fb Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 9 Oct 2024 21:41:16 +0100 Subject: [PATCH 13/19] Update pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx Co-authored-by: smartcontracts --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 33a02c63d..42fb7e3f4 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -70,7 +70,7 @@ You will need to get some ETH on Sepolia to follow along. ## Add a Private Key to Your Environment You need a private key in order to sign transactions. -Set your private key as an environment variable with the export command. +Set your private key as an environment variable with the `export` command. Make sure this private key corresponds to an address that has ETH on Sepolia. ```bash From 6d12f4147666da91f105d496d8a77819a5768fd2 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 9 Oct 2024 21:41:41 +0100 Subject: [PATCH 14/19] Update pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx Co-authored-by: smartcontracts --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 42fb7e3f4..2c7cb5d56 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -1,7 +1,7 @@ --- title: Estimating Transaction Costs on OP Stack lang: en-US -description: Learn how to use the Viem/op-stack to estimate the cost of a transaction on OP Mainnet. +description: Learn how to use Viem to estimate the cost of a transaction on OP Mainnet. --- import { Callout, Steps, Tabs } from 'nextra/components' From 6d9f8be16518bd439c110d58a862070d9b5c5d23 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 9 Oct 2024 21:55:15 +0100 Subject: [PATCH 15/19] updated the codebase --- public/tutorials/sdk-estimate-costs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index 15e2a7505..4c7947d5f 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -34,7 +34,7 @@ const walletClientL2 = createWalletClient({ const l2CostEstimate = gasLimit * effectiveGasPrice console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} ETH`) - const l1CostEstimate = await publicClient.estimateL1Fee(transaction) + const l1CostEstimate = await publicClient.estimateL1Gas(transaction) console.log(`Estimated L1 Data Fee: ${formatEther(l1CostEstimate)} ETH`) const totalEstimate = l2CostEstimate + l1CostEstimate From ba9ec298ff043b544772fdd0b8897eabfea6e449 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 9 Oct 2024 22:02:57 +0100 Subject: [PATCH 16/19] updated codebase --- .../tutorials/sdk-estimate-costs.mdx | 25 ++++++++----------- public/tutorials/sdk-estimate-costs.js | 8 +++--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 2c7cb5d56..3412fa209 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -67,6 +67,15 @@ You will need to get some ETH on Sepolia to follow along. You can use [this faucet](https://sepoliafaucet.com) to get ETH on Sepolia.
+## Get ETH on OP Sepolia + +This tutorial explains how estimate transaction costs on OP Sepolia. +You will need to get some ETH on OP Sepolia in order to run the code in this tutorial. + + + You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. + + ## Add a Private Key to Your Environment You need a private key in order to sign transactions. @@ -88,18 +97,6 @@ node This will bring up a Node REPL prompt that allows you to run JavaScript code. - -## Get ETH on OP Sepolia - -This tutorial explains how estimate transaction costs on OP Sepolia. -You will need to get some ETH on OP Sepolia in order to run the code in this tutorial. - - - You can use the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=docs) to get ETH on OP Sepolia. - - -This will bring up a Node REPL prompt that allows you to run javascript code. - ## Set Session Variables You'll need a few variables throughout this tutorial. @@ -138,7 +135,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. -```js file=/public/tutorials/sdk-estimate-costs.js#L21-L26 hash=583ee48142f33686188a7bf1cc312a1c +```js file=/public/tutorials/sdk-estimate-costs.js#L21-L26 hash=96e2f9bcece6c455f64c82e44bce1105 ``` This transaction will send `0.005` ETH to the specified address with a gas price of 20 Gwei. @@ -171,7 +168,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). This function returns the current cost estimate in wei. -```js file=/public/tutorials/sdk-estimate-costs.js#L37-L38 hash=b1ef73988e0876529a72b61d5822cbe1 +```js file=/public/tutorials/sdk-estimate-costs.js#L37-L38 hash=afbf520615c15f71a84eec2566c393aa ``` {

Estimate the total cost

} diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index 4c7947d5f..fc3f7383b 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -19,10 +19,10 @@ const walletClientL2 = createWalletClient({ }).extend(walletActionsL2()) const transaction = { - account, - to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.005'), - gasPrice: parseGwei('20') + account, + to: '0x1000000000000000000000000000000000000000', + value: parseEther('0.005'), + gasPrice: parseGwei('20') } const gasLimit = await publicClient.estimateGas(transaction) From 8717b9c881854c6b26d4897b3fd5e2beb8ff6d64 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Wed, 16 Oct 2024 21:25:29 +0100 Subject: [PATCH 17/19] Update pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx Co-authored-by: Zak Ayesh <44901995+ZakAyesh@users.noreply.github.com> --- pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 3412fa209..58a4c4405 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -164,7 +164,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. {

Estimate the L1 data fee

} - You can estimate the L1 data fee with the [estimateL1GasCost](https://viem.sh/op-stack/actions/estimateL1Gas) function. + You can estimate the L1 data fee with the [estimateL1GasCost on the Gas Price Oracle predeploy contract](https://viem.sh/op-stack/actions/estimateL1Gas) function. Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). This function returns the current cost estimate in wei. From 260d87213e40495a479344236eaa27694773d439 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Fri, 18 Oct 2024 14:44:15 +0100 Subject: [PATCH 18/19] updated the codebase --- .../tutorials/sdk-estimate-costs.mdx | 62 +++++-------------- public/tutorials/sdk-estimate-costs.js | 21 ++----- 2 files changed, 20 insertions(+), 63 deletions(-) diff --git a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx index 3412fa209..677890ed1 100644 --- a/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx +++ b/pages/builders/app-developers/tutorials/sdk-estimate-costs.mdx @@ -36,8 +36,8 @@ Since Viem is a [Node.js](https://nodejs.org/en/) library, you'll need to create {

Make a Project Folder

} ```bash - mkdir op-sample-project - cd op-sample-project + mkdir op-est-cost-tutorial + cd op-est-cost-tutorial ``` {

Initialize the Project

} @@ -127,55 +127,23 @@ Let's set those up now. ## Estimate Transaction Costs -You're now going to estimate the cost of a transaction on OP Mainnet. +You're now going to use the Viem to estimate the cost of a transaction on OP Mainnet. +Here you'll estimate the cost of a simple transaction that sends a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. - {

Define the transaction

} + {

Create the unsigned transaction

} - Viem makes it easy to prepare a transactions so you can estimate the cost of a transaction before you sign it. - Here you'll define an object with the required transaction fields and send a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. + Viem makes it easy to create unsigned transactions so you can estimate the cost of a transaction before you a user to sign it. + Here you'll create an unsigned transaction that sends a small amount of ETH from your address to the address `0x1000000000000000000000000000000000000000`. -```js file=/public/tutorials/sdk-estimate-costs.js#L21-L26 hash=96e2f9bcece6c455f64c82e44bce1105 -``` - This transaction will send `0.005` ETH to the specified address with a gas price of 20 Gwei. - - {

Estimate the execution gas fee

} - - Now, let's estimate the gas limit for our transaction. - -```js file=/public/tutorials/sdk-estimate-costs.js#L28-L29 hash=014939607bf2444d5f2e5a7babb02a46 -``` - - - {

Retrieve the current gas price

} - - Retrieve the current gas price (effective gas price), Alternatively, given that you already set the gas price manually, you can use the `getGasPrice` method from viem. - -```js file=/public/tutorials/sdk-estimate-costs.js#L31-L32 hash=b43ae2cb1a7471de55858fbc7f7fe5a6 -``` - - {

Calculate the execution gas fee

} - - To calculate the execution gas fee simply multiply the gas limit by the effective gas price. - -```js file=/public/tutorials/sdk-estimate-costs.js#L34-L35 hash=3e536e97b83458d3d3c7545b2c74ffd6 -``` -
- - {

Estimate the L1 data fee

} - - You can estimate the L1 data fee with the [estimateL1GasCost](https://viem.sh/op-stack/actions/estimateL1Gas) function. - Under the hood, this function is estimating the amount of Ethereum gas required to publish this transaction on Ethereum and multiplying it by the current Ethereum gas price (as tracked by the L2). - This function returns the current cost estimate in wei. - -```js file=/public/tutorials/sdk-estimate-costs.js#L37-L38 hash=afbf520615c15f71a84eec2566c393aa +```js file=/public/tutorials/sdk-estimate-costs.js#L21-L26 hash=d2f3fc3df8298253bd45a226dd171dcf ``` {

Estimate the total cost

} - Once you've individually estimated the execution gas fee and the L1 data fee, you can sum these two values together to get the total cost of the transaction. + With Viem you can estimate the total cost of a transaction using the [estimateTotalFee](https://viem.sh/op-stack/actions/estimateTotalFee) method. -```js file=/public/tutorials/sdk-estimate-costs.js#L40-L41 hash=8685f586913b87a5881cc6f917d0de50 +```js file=/public/tutorials/sdk-estimate-costs.js#L28-L29 hash=db562f050d0affe866e2114779656d3a ``` {

Send the transaction

} @@ -183,7 +151,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. Now that you've estimated the total cost of the transaction, go ahead and send it to the network. This will make it possible to see the actual cost of the transaction to compare to your estimate. -```js file=/public/tutorials/sdk-estimate-costs.js#L43-L44 hash=a0a19fa7fc17165d934cc9f7af075464 +```js file=/public/tutorials/sdk-estimate-costs.js#L31-L35 hash=419162648c0c6c0d5e82ca8f6d4942d5 ``` {

Check the actual execution gas fee

} @@ -192,21 +160,21 @@ You're now going to estimate the cost of a transaction on OP Mainnet. You can do so by accessing the `gasUsed` and `effectiveGasPrice` from the transaction receipt. You can then multiply these values to get the actual L2 cost of the transaction -```js file=/public/tutorials/sdk-estimate-costs.js#L46-L49 hash=e128f21d2c994f42bdc7f5fb51eb127d +```js file=/public/tutorials/sdk-estimate-costs.js#L37-L38 hash=57dba68f78481bea90e7629270a1f58b ``` {

Check the actual L1 data fee

} You can also check the actual L1 data fee. -```js file=/public/tutorials/sdk-estimate-costs.js#L51-L52 hash=ea1801a7618fa2a21f02a97717380f42 +```js file=/public/tutorials/sdk-estimate-costs.js#L40-L41 hash=e728708954c71fe52c55912dbe778042 ``` {

Check the actual total cost

} Sum these two together to get the actual total cost of the transaction. -```js file=/public/tutorials/sdk-estimate-costs.js#L54-L56 hash=6f7943da9d70654dc040b5561b3b360d +```js file=/public/tutorials/sdk-estimate-costs.js#L43-L44 hash=38a1eadb48d89d476ea51658514d23c0 ``` {

Check the difference

} @@ -215,7 +183,7 @@ You're now going to estimate the cost of a transaction on OP Mainnet. This will give you a sense of how accurate your estimate was. Estimates will never be entirely accurate, but they should be close! -```js file=/public/tutorials/sdk-estimate-costs.js#L57-L58 hash=20c8c60af1cc39e842b207cfd2dfa2cb +```js file=/public/tutorials/sdk-estimate-costs.js#L46-L47 hash=20c8c60af1cc39e842b207cfd2dfa2cb ```
diff --git a/public/tutorials/sdk-estimate-costs.js b/public/tutorials/sdk-estimate-costs.js index fc3f7383b..72507f96f 100644 --- a/public/tutorials/sdk-estimate-costs.js +++ b/public/tutorials/sdk-estimate-costs.js @@ -21,34 +21,23 @@ const walletClientL2 = createWalletClient({ const transaction = { account, to: '0x1000000000000000000000000000000000000000', - value: parseEther('0.005'), - gasPrice: parseGwei('20') + value: parseEther('0.00069420'), + gasPrice: await publicClient.getGasPrice() } - const gasLimit = await publicClient.estimateGas(transaction) - console.log(`Estimated Gas Limit: ${gasLimit}`) - - const effectiveGasPrice = await publicClient.getGasPrice() - console.log(`Effective Gas Price: ${formatEther(effectiveGasPrice)} ETH`) - - const l2CostEstimate = gasLimit * effectiveGasPrice - console.log(`Estimated Execution Gas Fee: ${formatEther(l2CostEstimate)} ETH`) - - const l1CostEstimate = await publicClient.estimateL1Gas(transaction) - console.log(`Estimated L1 Data Fee: ${formatEther(l1CostEstimate)} ETH`) - - const totalEstimate = l2CostEstimate + l1CostEstimate + const totalEstimate = await publicClient.estimateTotalFee(transaction) console.log(`Estimated Total Cost: ${formatEther(totalEstimate)} ETH`) const txHash = await walletClientL2.sendTransaction(transaction) console.log(`Transaction Hash: ${txHash}`) const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }) + console.log('receipt', receipt); const l2CostActual = receipt.gasUsed * receipt.effectiveGasPrice console.log(`Actual Execution Gas Fee: ${formatEther(l2CostActual)} ETH`) - const l1CostActual = await publicClient.estimateL1Fee({ hash: txHash }) + const l1CostActual = receipt.l1Fee console.log(`Actual L1 Data Fee: ${formatEther(l1CostActual)} ETH`) const totalActual = l2CostActual + l1CostActual From 0b7332035170d5cdd42949ea6078f72a878d0103 Mon Sep 17 00:00:00 2001 From: Blessing Krofegha Date: Mon, 21 Oct 2024 16:48:22 +0100 Subject: [PATCH 19/19] updated transaction page --- .../app-developers/transactions/estimates.mdx | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/pages/builders/app-developers/transactions/estimates.mdx b/pages/builders/app-developers/transactions/estimates.mdx index 6b7008b18..732de864c 100644 --- a/pages/builders/app-developers/transactions/estimates.mdx +++ b/pages/builders/app-developers/transactions/estimates.mdx @@ -41,38 +41,18 @@ This means you can feed your transaction to the [`eth_estimateGas`](https://ethe {

Estimate the max fee per gas

} -Like Ethereum, OP Mainnet uses an EIP-1559 style fee market to determine the current base fee per gas. +Like Ethereum, OP Mainnet uses an `EIP-1559` style fee market to determine the current base fee per gas. You can then additionally specify a priority fee (also known as a tip) to incentivize the Sequencer to include your transaction more quickly. Make sure to check out the guide on [Setting Transaction Gas Parameters on OP Mainnet](./parameters) to learn more about how to select an appropriate max fee per gas for your transaction. -{

Calculate the execution gas fee

} - -Once you've estimated the gas limit and the max fee per gas for your transaction, you can calculate the execution gas fee by multiplying these two values together. - -For instance, suppose that your transaction has a gas limit of `420000 gas`, a base fee of `0.05 gwei`, and a priority fee of `0.1 gwei`. -The execution gas fee for your transaction would be: - -```javascript -// Start with your parameters -gas_limit = 420000 -base_fee_per_gas = 0.05 gwei -priority_fee_per_gas = 0.1 gwei - -// Max fee per gas is the sum of the base fee and the priority fee -max_fee_per_gas = base_fee_per_gas + priority_fee_per_gas = 0.15 gwei - -// Execution gas fee is the product of the gas limit and the max fee per gas -execution_gas_fee = gas_limit * max_fee_per_gas = 420000 * 0.15 gwei = 0.000063 ETH -``` - ## L1 Data Fee -The Optimism SDK provides a convenient method for estimating the L1 data fee for a transaction. -Check out the tutorial on [Estimating Transaction Costs on OP Mainnet](/builders/app-developers/tutorials/sdk-estimate-costs) to learn how to use the Optimism SDK to estimate the L1 data fee for your transaction. -Keep reading if you'd like to learn how to estimate the L1 data fee without the Optimism SDK. +The Viem library provides a convenient method for estimating the L1 data fee for a transaction. +Check out the tutorial on [Estimating Transaction Costs on OP Mainnet](/builders/app-developers/tutorials/sdk-estimate-costs) to learn how to use the Viem library to estimate the L1 data fee for your transaction. +Keep reading if you'd like to learn how to estimate the L1 data fee without the Viem library. The L1 data fee is a fee paid to the Sequencer for the cost of publishing your transaction to Ethereum. @@ -116,8 +96,6 @@ Several tools are available to help you estimate the L1 Data Fee for your transa Selecting the right tool for your use case will depend on your specific needs. * [Viem](https://viem.sh/op-stack#getting-started-with-op-stack) provides first-class support for OP Stack chains, including OP Mainnet. You can use Viem to estimate gas costs and send cross-chain transactions (like transactions through the Standard Bridge system). It's strongly recommended to use Viem if you are able to do so as it will provide the best native support at the moment. -* If you are using Ethers v5, the [Optimism SDK](https://sdk.optimism.io/) provides methods for estimating the L1 Data Fee for your transactions and for sending cross-chain transactions. The Optimism SDK is designed to be used alongside Ethers v5 and does not yet support Ethers v6. -* If you are using Ethers v6, the [Optimistic Utilities Extension](https://github.com/ethers-io/ext-utils-optimism) provides methods for estimating the L1 Data Fee. The Ethers v6 extension does not yet support sending cross-chain transactions. Use Viem or the Optimism SDK if you need to send cross-chain transactions. ### Future Proofing