Skip to content

Commit 5dec40d

Browse files
committed
updated tutorial to support CLI approach
1 parent 27d7848 commit 5dec40d

File tree

1 file changed

+135
-164
lines changed

1 file changed

+135
-164
lines changed

pages/builders/app-developers/tutorials/cross-dom-bridge-eth.mdx

Lines changed: 135 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,140 @@
11
---
2-
title: Bridging ETH to OP Mainnet With Viem
2+
title: Bridging ETH with Viem
33
lang: en-US
4-
description: Learn how to use viem to transfer ETH between Layer 1 (Ethereum or Sepolia) and Layer 2 (OP Mainnet or OP Sepolia).
4+
description: Learn how to use Viem to transfer ETH between Layer 1 (Ethereum or Sepolia) and Layer 2 (OP Mainnet or OP Sepolia).
55
---
66

7-
import { Callout, Steps, Tabs } from 'nextra/components'
7+
import { Callout, Steps } from 'nextra/components'
8+
89

910
# Bridging ETH to OP Mainnet With Viem
1011

11-
This tutorial explains how you can use the [Viem](https://viem.sh/op-stack/) to bridge ETH from L1 (Ethereum or Sepolia) to L2 (OP Mainnet or OP Sepolia).
12-
The `viem/op-stack` library is an easy way to add bridging functionality to your JavaScript-based application.
13-
It also provides some safety rails to prevent common mistakes that could cause ETH or ERC-20 tokens to be made inaccessible.
12+
This tutorial explains how you can use [Viem](https://viem.sh) to bridge ETH from L1 (Ethereum or Sepolia) to L2 (OP Mainnet or OP Sepolia).
13+
Viem is a TypeScript interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.
14+
It offers an easy way to add bridging functionality to your JavaScript-based application.
1415

16+
Behind the scenes, Viem uses the [Standard Bridge](/builders/app-developers/bridging/standard-bridge) contracts to transfer ETH and ERC-20 tokens.
1517
Make sure to check out the [Standard Bridge guide](/builders/app-developers/bridging/standard-bridge) if you want to learn more about how the bridge works under the hood.
1618

17-
## Prerequisites
19+
## Supported Networks
1820

19-
Before you begin, ensure you have the following:
21+
Viem supports any of the [Superchain networks](/chain/networks).
22+
The OP Stack networks are included in Viem by default.
23+
If you want to use a network that isn't included by default, you can add it to Viem's chain configurations.
2024

21-
* Familiarity with bridging concepts between L1 and L2.
22-
* An understanding of the [viem library](https://viem.sh/op-stack/)
23-
* [Node.js](https://nodejs.org/en/) (version 14 or later)
24-
* [pnpm](https://pnpm.io/installation) installed for managing packages.
25+
## Dependencies
2526

26-
Install `pnpm` if you haven't already:
27+
* [node](https://nodejs.org/en/)
28+
* [pnpm](https://pnpm.io/installation)
2729

28-
```bash
29-
npm install -g pnpm
30+
## Create a Demo Project
3031

31-
```
32+
You're going to use Viem for this tutorial.
33+
Since Viem is a [Node.js](https://nodejs.org/en/) library, you'll need to create a Node.js project to use it.
3234

3335
<Steps>
34-
{<h3>Project Setup</h3>}
36+
{<h3>Make a Project Folder</h3>}
3537

36-
Let's create a new project and install the necessary dependencies.
38+
```bash
39+
mkdir op-sample-project
40+
cd op-sample-project
41+
```
3742

38-
* Create a folder and a file
43+
{<h3>Initialize the Project</h3>}
3944

40-
```bash
41-
mkdir op-sample-project
42-
cd op-sample-project
43-
touch bridge-eth.js
44-
```
45+
```bash
46+
pnpm init
47+
```
4548

46-
* Initialize the project:
49+
{<h3>Install the Optimism SDK</h3>}
4750

48-
```bash
49-
pnpm init
50-
```
51+
```bash
52+
pnpm add @eth-optimism/sdk
53+
```
5154

52-
* Install dependencies: Install `viem`, and `dotenv` for managing environment variables.
55+
{<h3>Install ethers.js</h3>}
5356

54-
```bash
55-
pnpm add viem dotenv
56-
```
57+
```bash
58+
pnpm add ethers@^5
59+
```
5760

58-
{<h3>Configure Environment Variables</h3>}
61+
</Steps>
5962

60-
You need a private key in order to sign transactions.
61-
Create a `.env` file in your parent directory to securely store your environment variables
62-
Make sure this private key corresponds to an address that has ETH on Sepolia.
63+
<Callout type="info">
64+
Want to create a new wallet for this tutorial?
65+
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.
6366

64-
```bash
65-
touch .env
66-
```
67+
</Callout>
6768

68-
Add your Ethereum Layer 1 (L1) and Optimism Layer 2 (L2) RPC endpoints, and wallet private key in the `.env` file:
69+
## Get ETH on Sepolia
6970

70-
```bash
71-
L1_RPC_URL=https://rpc.ankr.com/eth_sepolia
72-
L2_RPC_URL=https://sepolia.optimism.io
73-
TUTORIAL_PRIVATE_KEY=0x...
74-
```
75-
</Steps>
71+
This tutorial explains how to bridge ETH from Sepolia to OP Sepolia.
72+
You will need to get some ETH on Sepolia to follow along.
7673

77-
<Callout type="warning">
78-
Never share your private key and avoid committing this file to version control.
74+
<Callout type="info">
75+
You can use [this faucet](https://sepoliafaucet.com) to get ETH on Sepolia.
7976
</Callout>
8077

81-
## Import Dependencies
78+
## Add a Private Key to Your Environment
8279

83-
{<h3>Import the necessary packages</h3>}
80+
You need a private key in order to sign transactions.
81+
Set your private key as an environment variable with the export command.
82+
Make sure this private key corresponds to an address that has ETH on Sepolia.
8483

85-
In the `bridge-eth.js` file, import the `viem` package at the top:
86-
87-
```js
88-
89-
// Import required modules
90-
import { createPublicClient, http, createWalletClient, parseEther } from 'viem';
91-
import { sepolia, optimismSepolia } from 'viem/chains';
92-
import { privateKeyToAccount } from 'viem/accounts'
93-
import { getL2TransactionHashes, publicActionsL2, walletActionsL1 } from 'viem/op-stack'
94-
import * as dotenv from 'dotenv';
95-
// Load environment variables
96-
dotenv.config();
84+
```bash
85+
export TUTORIAL_PRIVATE_KEY=0x...
9786
```
87+
## Start the Node REPL
9888

99-
## Set Session Variables
100-
101-
You'll need a few variables throughout this tutorial.
102-
Let's set those up now.
89+
You're going to use the Node REPL to interact with Viem.
90+
To start the Node REPL run the following command in your terminal:
10391

104-
<Tabs items={['Create an account', 'Create RPC providers', 'Wallet Clients']}>
105-
<Tabs.Tab>
106-
Create an account from the private key. [`privateKeyToAccount`](https://viem.sh/docs/accounts/local/privateKeyToAccount#privatekeytoaccount) is a viem method used to sign transactions by passing a private key.
107-
108-
Load your private key with `privateKeyToAccount`, after the imports above.
109-
110-
```js
111-
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
112-
```
113-
</Tabs.Tab>
114-
115-
<Tabs.Tab>
116-
Next, set up our viem clients for the L1(Sepolia) and L2(optimismSepolia)
117-
118-
<Steps>
119-
{<h3>L1 (Sepolia) publicClientL1 </h3>}
120-
121-
```js
122-
const publicClientL1 = createPublicClient({
123-
chain: sepolia,
124-
transport: http(process.env.L1_RPC_URL),
125-
});
126-
```
127-
128-
{<h3>L2 (optimismSepolia) publicClientL2</h3>}
129-
130-
```js
131-
const publicClientL2 = createPublicClient({
132-
chain: optimismSepolia,
133-
transport: http(process.env.L2_RPC_URL),
134-
}).extend(publicActionsL2());
135-
```
136-
</Steps>
137-
</Tabs.Tab>
138-
139-
<Tabs.Tab>
140-
Also set up wallet clients for L1 and L2.
92+
```bash
93+
node
94+
```
95+
This will bring up a Node REPL prompt that allows you to run JavaScript code.
14196

142-
<Steps>
143-
{<h3>L1 (Sepolia) walletClientL1</h3>}
97+
## Import Dependencies
14498

145-
```js
146-
const walletClientL1 = createWalletClient({
147-
account,
148-
chain: sepolia, /* or mainnet */
149-
transport: http(process.env.L1_RPC_URL),
150-
}).extend(walletActionsL1());
151-
```
99+
You need to import some dependencies into your Node REPL session.
152100

153-
{<h3>L2 (optimismSepolia) walletClientL2</h3>}
101+
```js
102+
const { createPublicClient, http, createWalletClient, parseEther } = require('viem');
103+
const { sepolia, optimismSepolia } = require('viem/chains');
104+
const { privateKeyToAccount } = require('viem/accounts');
105+
const { getL2TransactionHashes, publicActionsL2, walletActionsL1, walletActionsL2 } = require('viem/op-stack');
106+
107+
// Load private key from environment variable
108+
const PRIVATE_KEY = process.env.PRIVATE_KEY;
109+
const account = privateKeyToAccount(PRIVATE_KEY);
110+
111+
// Create L1 public client for reading from the Sepolia network
112+
const publicClientL1 = createPublicClient({
113+
chain: sepolia,
114+
transport: http("https://rpc.ankr.com/eth_sepolia"),
115+
});
116+
117+
// Create L1 wallet client for sending transactions on Sepolia
118+
const walletClientL1 = createWalletClient({
119+
account,
120+
chain: sepolia,
121+
transport: http("https://sepolia.optimism.io"),
122+
}).extend(walletActionsL1());
123+
124+
// Create L2 public client for interacting with OP Sepolia
125+
const publicClientL2 = createPublicClient({
126+
chain: optimismSepolia,
127+
transport: http("https://sepolia.optimism.io"),
128+
}).extend(publicActionsL2());
129+
130+
// Create L2 wallet client for sending transactions on OP Sepolia
131+
const walletClientL2 = createWalletClient({
132+
account,
133+
chain: optimismSepolia,
134+
transport: http("https://sepolia.optimism.io"),
135+
}).extend(walletActionsL2());
136+
```
154137

155-
```js
156-
const walletClientL2 = createWalletClient({
157-
chain: optimismSepolia,
158-
transport: http(process.env.L2_RPC_URL),
159-
}).extend(walletActionsL1());
160-
```
161-
</Steps>
162-
</Tabs.Tab>
163-
</Tabs>
164138

165139
## Get ETH on Sepolia
166140

@@ -179,11 +153,8 @@ Now that you have some ETH on L1 you can deposit that ETH into the `L1StandardBr
179153
See how much ETH you have on L1 so you can confirm that the deposit worked later on.
180154

181155
```js
182-
const checkBalances = async () => {
183156
const l1Balance = await publicClientL1.getBalance({ address: account.address });
184157
console.log(`L1 Balance: ${formatEther(l1Balance)} ETH`);
185-
};
186-
checkBalances();
187158
```
188159

189160
<Callout type="info">
@@ -244,41 +215,41 @@ Now that you have some ETH on L1 you can deposit that ETH into the `L1StandardBr
244215
</Tabs.Tab>
245216

246217
<Tabs.Tab>
247-
```javascript
248-
import { createPublicClient, http, createWalletClient, parseEther } from 'viem';
249-
import { sepolia, optimismSepolia } from "viem/chains";
250-
import { privateKeyToAccount } from 'viem/accounts';
251-
import { getL2TransactionHashes, publicActionsL2, walletActionsL1, walletActionsL2 } from 'viem/op-stack';
252-
253-
// Replace with your actual private key (Keep this secure!)
254-
const PRIVATE_KEY = '0x....'
255-
const account = privateKeyToAccount(PRIVATE_KEY);
256-
257-
// Create L1 public client for reading from the Sepolia network
258-
const publicClientL1 = createPublicClient({
259-
chain: sepolia,
260-
transport: http(process.env.L1_RPC_URL),
261-
});
262-
263-
// Create L1 wallet client for sending transactions on Sepolia
264-
const walletClientL1 = createWalletClient({
265-
account,
266-
chain: sepolia,
267-
transport: http(process.env.L1_RPC_URL),
268-
}).extend(walletActionsL1());
269-
270-
// Create L2 public client for interacting with OP Sepolia
271-
const publicClientL2 = createPublicClient({
272-
chain: optimismSepolia,
273-
transport: http(process.env.L1_RPC_URL),
274-
}).extend(publicActionsL2());
275-
276-
// Create L2 wallet client for sending transactions on OP Sepolia
277-
const walletClientL2 = createWalletClient({
278-
account,
279-
chain: optimismSepolia,
280-
transport: http(process.env.L1_RPC_URL),
281-
}).extend(walletActionsL2());
218+
```js
219+
const { createPublicClient, http, createWalletClient, parseEther } = require('viem');
220+
const { sepolia, optimismSepolia } = require('viem/chains');
221+
const { privateKeyToAccount } = require('viem/accounts');
222+
const { getL2TransactionHashes, publicActionsL2, walletActionsL1, walletActionsL2 } = require('viem/op-stack');
223+
224+
// Load private key from environment variable
225+
const PRIVATE_KEY = process.env.PRIVATE_KEY;
226+
const account = privateKeyToAccount(PRIVATE_KEY);
227+
228+
// Create L1 public client for reading from the Sepolia network
229+
const publicClientL1 = createPublicClient({
230+
chain: sepolia,
231+
transport: http("https://rpc.ankr.com/eth_sepolia"),
232+
});
233+
234+
// Create L1 wallet client for sending transactions on Sepolia
235+
const walletClientL1 = createWalletClient({
236+
account,
237+
chain: sepolia,
238+
transport: http("https://sepolia.optimism.io"),
239+
}).extend(walletActionsL1());
240+
241+
// Create L2 public client for interacting with OP Sepolia
242+
const publicClientL2 = createPublicClient({
243+
chain: optimismSepolia,
244+
transport: http("https://sepolia.optimism.io"),
245+
}).extend(publicActionsL2());
246+
247+
// Create L2 wallet client for sending transactions on OP Sepolia
248+
const walletClientL2 = createWalletClient({
249+
account,
250+
chain: optimismSepolia,
251+
transport: http("https://sepolia.optimism.io"),
252+
}).extend(walletActionsL2());
282253

283254
async function depositETH(amount) {
284255
try {
@@ -440,10 +411,10 @@ Now you're going to repeat the process in reverse to bridge some ETH from L2 to
440411

441412
<Tabs.Tab>
442413
```js
443-
import { createPublicClient, http, createWalletClient, parseEther } from 'viem';
444-
import { sepolia, optimismSepolia } from "viem/chains";
445-
import { privateKeyToAccount } from 'viem/accounts';
446-
import { getL2TransactionHashes, publicActionsL2, walletActionsL1, walletActionsL2 } from 'viem/op-stack';
414+
const { createPublicClient, http, createWalletClient, parseEther } = require('viem');
415+
const { sepolia, optimismSepolia } = require('viem/chains');
416+
const { privateKeyToAccount } = require('viem/accounts');
417+
const { getL2TransactionHashes, publicActionsL2, walletActionsL1, walletActionsL2 } = require('viem/op-stack');
447418

448419
// Replace with your actual private key (Keep this secure!)
449420
const PRIVATE_KEY = '0x....'

0 commit comments

Comments
 (0)