Skip to content

Commit c45a813

Browse files
authored
feat: migrate sdk to viem (#1)
1 parent 92f14cd commit c45a813

13 files changed

+520
-381
lines changed

.env.example

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
21
NEXT_PUBLIC_L1_CHAIN_ID=11155111
32
NEXT_PUBLIC_L1_CHAIN_NAME=Sepolia
43
NEXT_PUBLIC_L1_RPC_URL=
@@ -8,6 +7,8 @@ NEXT_PUBLIC_L2_CHAIN_NAME=Optimism Sepolia
87
NEXT_PUBLIC_L2_RPC_URL=
98
NEXT_PUBLIC_L2_EXPLORER_URL=https://sepolia-optimism.etherscan.io/
109
NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY=0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1
11-
NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY=0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef
1210
NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY=0x16Fc5058F25648194471939df75CF27A2fdC48BC
1311
NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY=0x4200000000000000000000000000000000000010
12+
NEXT_PUBLIC_DISPUTE_GAME_FACTORY_PROXY=0x05F9613aDB30026FFd634f38e5C4dFd30a197Fa1
13+
NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY= # deprecated
14+
NEXT_PUBLIC_L1_MULTICALL3_ADDRESS=0xcA11bde05977b3631167028862bE2a173976CA11

.github/workflows/docker-publish.yml

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Docker
2+
3+
# This workflow uses actions that are not certified by GitHub.
4+
# They are provided by a third-party and are governed by
5+
# separate terms of service, privacy policy, and support
6+
# documentation.
7+
8+
on:
9+
push:
10+
branches: [ "main" ]
11+
# Publish semver tags as releases.
12+
tags: [ 'v*.*.*' ]
13+
14+
env:
15+
# Use docker.io for Docker Hub if empty
16+
REGISTRY: docker.io
17+
# Remove the slash at the end of the username
18+
IMAGE_NAME: ${{ secrets.DOCKER_HUB_USERNAME }}/${{ github.event.repository.name }}
19+
20+
jobs:
21+
build:
22+
23+
runs-on: ubuntu-latest
24+
permissions:
25+
contents: read
26+
packages: write
27+
# This is used to complete the identity challenge
28+
# with sigstore/fulcio when running outside of PRs.
29+
id-token: write
30+
31+
steps:
32+
- name: Checkout repository
33+
uses: actions/checkout@v4
34+
35+
# Set up QEMU for multi-architecture support
36+
# https://github.com/docker/setup-qemu-action
37+
- name: Set up QEMU
38+
uses: docker/setup-qemu-action@v3
39+
40+
# Set up BuildKit Docker container builder to be able to build
41+
# multi-platform images and export cache
42+
# https://github.com/docker/setup-buildx-action
43+
- name: Set up Docker Buildx
44+
uses: docker/setup-buildx-action@v3
45+
46+
# Login against a Docker registry
47+
# https://github.com/docker/login-action
48+
- name: Log into Docker Hub
49+
uses: docker/login-action@v3
50+
with:
51+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
52+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
53+
54+
# Extract metadata (tags, labels) for Docker
55+
# https://github.com/docker/metadata-action
56+
- name: Extract Docker metadata
57+
id: meta
58+
uses: docker/metadata-action@v5
59+
with:
60+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
61+
tags: |
62+
type=raw,value=latest,enable={{is_default_branch}}
63+
type=ref,event=branch
64+
type=semver,pattern={{version}}
65+
type=sha
66+
67+
# Build and push Docker image with Buildx (don't push on PR)
68+
# https://github.com/docker/build-push-action
69+
- name: Build and push Docker image
70+
id: build-and-push
71+
uses: docker/build-push-action@v6
72+
with:
73+
push: true
74+
context: .
75+
tags: ${{ steps.meta.outputs.tags }}
76+
labels: ${{ steps.meta.outputs.labels }}
77+
cache-from: type=gha
78+
cache-to: type=gha,mode=max

Dockerfile

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Use an official Node runtime as the base image
2+
FROM node:20-alpine
3+
4+
# Set the working directory in the container
5+
WORKDIR /op-bridge
6+
7+
# Copy package.json and package-lock.json (or yarn.lock)
8+
COPY package.json yarn.lock ./
9+
10+
# Install dependencies
11+
RUN yarn install --frozen-lockfile
12+
13+
# Copy the rest of the application code
14+
COPY . .
15+
16+
# Install dependencies
17+
RUN yarn install
18+
19+
# Expose the port the app runs on
20+
EXPOSE 3000
21+
22+
# Set up entrypoint script
23+
COPY entrypoint.sh /entrypoint.sh
24+
25+
ENTRYPOINT ["/entrypoint.sh"]

README.md

+51-21
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,66 @@
1-
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
1+
# Tohma Devnet Bridge
22

3-
## Getting Started
3+
This repo implements a simple bridging interface for depositing to and withdrawing from Tohma L2 devnet.
44

5-
First, run the development server:
5+
## Installation and setup
6+
7+
### Define env vars
8+
9+
Clone `.env.example` to `.env` and set the environment variables for L1 and L2 chains.
610

711
```bash
8-
npm run dev
9-
# or
10-
yarn dev
11-
# or
12-
pnpm dev
13-
# or
14-
bun dev
12+
cp .env.example .env
1513
```
1614

17-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
15+
Note `NEXT_PUBLIC_L1_MULTICALL3_ADDRESS` is set in the next step.
1816

19-
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
17+
### Installing `multicall3`
2018

21-
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
19+
The `withdraw` call uses [`multicall3](https://github.com/mds1/multicall) to batch multiple methods in a single call.
2220

23-
## Learn More
21+
To deploy the contract, first install [Foundry](https://book.getfoundry.sh/cast/):
22+
23+
```bash
24+
curl -L https://foundry.paradigm.xyz | bash
25+
foundryup
26+
```
2427

25-
To learn more about Next.js, take a look at the following resources:
28+
Clone the `multicall3` repo and build the contract:
2629

27-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
30+
```
31+
git clone https://github.com/mds1/multicall.git
32+
cd multicall
33+
forge build
34+
```
2935

30-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
36+
Deploy the contract, specifying the L1 RPC URL and private key of the funded L1 deployer:
3137

32-
## Deploy on Vercel
38+
```bash
39+
forge create --rpc-url $L1_RPC_URL --private-key $PRIVATE_KEY Multicall3
40+
```
3341

34-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
42+
If the deployment was successful, you should see a similar output as the following:
3543

36-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
44+
```bash
45+
Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
46+
Deployed to: 0x4C4a2f8c81640e47606d3fd77B353E87Ba015584
47+
Transaction hash: 0xe51086815a32b04b776f1959a722298e95206d63d55dfe6e84d89b0aaa40cf61
48+
```
49+
50+
Set `NEXT_PUBLIC_L1_MULTICALL3_ADDRESS` in `.env` to the address of the deployed contract.
51+
52+
### Starting the bridging app.
53+
54+
Install dependencies and run the development server.
55+
56+
```bash
57+
yarn install
58+
yarn dev
59+
```
60+
61+
To build and run the app:
62+
63+
```bash
64+
yarn build
65+
yarn start
66+
```

app/config.ts

+54-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { http, createConfig } from "wagmi";
2-
import { sepolia, optimismSepolia } from "wagmi/chains";
32
import { defineChain } from "viem";
43

54
const NEXT_PUBLIC_L1_CHAIN_NAME = process.env
@@ -14,20 +13,18 @@ const NEXT_PUBLIC_L2_CHAIN_ID = process.env.NEXT_PUBLIC_L2_CHAIN_ID as string;
1413
const NEXT_PUBLIC_L2_RPC_URL = process.env.NEXT_PUBLIC_L2_RPC_URL as string;
1514
const NEXT_PUBLIC_L2_EXPLORER_URL = process.env
1615
.NEXT_PUBLIC_L2_EXPLORER_URL as string;
17-
const NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID = process.env
18-
.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID as string;
19-
const NEXT_PUBLIC_ADDRESS_MANAGER = process.env
20-
.NEXT_PUBLIC_ADDRESS_MANAGER as string;
2116
const NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY = process.env
2217
.NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY as string;
23-
const NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY = process.env
24-
.NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY as string;
2518
const NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY = process.env
2619
.NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY as string;
2720
const NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY = process.env
2821
.NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY as string;
2922
const NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY = process.env
3023
.NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY as string;
24+
const NEXT_PUBLIC_DISPUTE_GAME_FACTORY_PROXY = process.env
25+
.NEXT_PUBLIC_DISPUTE_GAME_FACTORY_PROXY as string;
26+
const NEXT_PUBLIC_L1_MULTICALL3_ADDRESS = process.env
27+
.NEXT_PUBLIC_L1_MULTICALL3_ADDRESS as string;
3128

3229
if (!NEXT_PUBLIC_L1_CHAIN_NAME) {
3330
throw new Error("NEXT_PUBLIC_L1_CHAIN_NAME is not set");
@@ -39,7 +36,7 @@ if (!NEXT_PUBLIC_L1_RPC_URL) {
3936
throw new Error("NEXT_PUBLIC_L1_RPC_URL is not set");
4037
}
4138
if (!NEXT_PUBLIC_L1_EXPLORER_URL) {
42-
throw new Error("NEXT_PUBLIC_L1_EXPLORER_URL is not set");
39+
console.warn("NEXT_PUBLIC_L1_EXPLORER_URL is not set");
4340
}
4441
if (!NEXT_PUBLIC_L2_CHAIN_NAME) {
4542
throw new Error("NEXT_PUBLIC_L2_CHAIN_NAME is not set");
@@ -51,25 +48,28 @@ if (!NEXT_PUBLIC_L2_RPC_URL) {
5148
throw new Error("NEXT_PUBLIC_L2_RPC_URL is not set");
5249
}
5350
if (!NEXT_PUBLIC_L2_EXPLORER_URL) {
54-
throw new Error("NEXT_PUBLIC_L2_EXPLORER_URL is not set");
55-
}
56-
if (!NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID) {
57-
throw new Error("NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID is not set");
51+
console.warn("NEXT_PUBLIC_L2_EXPLORER_URL is not set");
5852
}
5953
if (!NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY) {
6054
throw new Error("NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY is not set");
6155
}
62-
if (!NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY) {
63-
throw new Error("NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY is not set");
64-
}
6556
if (!NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY) {
6657
throw new Error("NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY is not set");
6758
}
6859
if (!NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY) {
6960
throw new Error("NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY is not set");
7061
}
62+
// if (!NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY) {
63+
// throw new Error("NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY is not set");
64+
// }
65+
// if (!NEXT_PUBLIC_DISPUTE_GAME_FACTORY_PROXY) {
66+
// throw new Error("NEXT_PUBLIC_DISPUTE_GAME_FACTORY_PROXY is not set");
67+
// }
68+
if (!NEXT_PUBLIC_L1_MULTICALL3_ADDRESS) {
69+
throw new Error("NEXT_PUBLIC_L1_MULTICALL3_ADDRESS is not set");
70+
}
7171

72-
export const l1Chain = defineChain({
72+
const l1Chain = defineChain({
7373
id: Number(NEXT_PUBLIC_L1_CHAIN_ID),
7474
name: NEXT_PUBLIC_L1_CHAIN_NAME,
7575
nativeCurrency: {
@@ -85,9 +85,14 @@ export const l1Chain = defineChain({
8585
blockExplorers: {
8686
default: { name: "Explorer", url: NEXT_PUBLIC_L1_EXPLORER_URL },
8787
},
88+
contracts: {
89+
multicall3: {
90+
address: NEXT_PUBLIC_L1_MULTICALL3_ADDRESS as `0x${string}`,
91+
},
92+
},
8893
});
8994

90-
export const l2Chain = defineChain({
95+
const l2Chain = defineChain({
9196
id: Number(NEXT_PUBLIC_L2_CHAIN_ID),
9297
name: NEXT_PUBLIC_L2_CHAIN_NAME,
9398
nativeCurrency: {
@@ -103,43 +108,52 @@ export const l2Chain = defineChain({
103108
blockExplorers: {
104109
default: { name: "Explorer", url: NEXT_PUBLIC_L2_EXPLORER_URL },
105110
},
111+
contracts: {
112+
portal: {
113+
[l1Chain.id]: {
114+
address: NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY as `0x${string}`,
115+
},
116+
},
117+
disputeGameFactory: {
118+
[l1Chain.id]: {
119+
address: NEXT_PUBLIC_DISPUTE_GAME_FACTORY_PROXY as `0x${string}`,
120+
},
121+
},
122+
l2OutputOracle: {
123+
[l1Chain.id]: {
124+
address: NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY as `0x${string}`,
125+
},
126+
},
127+
l1StandardBridge: {
128+
[l1Chain.id]: {
129+
address: NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY as `0x${string}`,
130+
},
131+
},
132+
l2StandardBridge: {
133+
[l1Chain.id]: {
134+
address: NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY as `0x${string}`,
135+
},
136+
},
137+
},
106138
});
107139

108-
export const chains = [l1Chain, l2Chain, optimismSepolia] as const;
140+
const chains = [l1Chain, l2Chain] as const;
109141

110-
export const config = createConfig({
142+
const config = createConfig({
111143
chains: chains,
112144
connectors: [],
113145
transports: {
114146
[l1Chain.id]: http(),
115147
[l2Chain.id]: http(),
116-
[optimismSepolia.id]: http(),
117148
},
118149
});
119150

120-
const zeroAddr = "0x".padEnd(42, "0");
121-
122-
export const opStackL1Contracts = {
123-
StateCommitmentChain: zeroAddr,
124-
CanonicalTransactionChain: zeroAddr,
125-
BondManager: zeroAddr,
126-
AddressManager: NEXT_PUBLIC_ADDRESS_MANAGER || zeroAddr,
127-
L1CrossDomainMessenger: NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY,
128-
L1StandardBridge: NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY,
129-
OptimismPortal: NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY,
130-
L2OutputOracle: NEXT_PUBLIC_L2_OUTPUT_ORACLE_PROXY || zeroAddr,
131-
};
132-
133151
export {
134-
NEXT_PUBLIC_L2_RPC_URL,
135152
NEXT_PUBLIC_L1_CHAIN_ID,
136153
NEXT_PUBLIC_L2_CHAIN_ID,
137154
NEXT_PUBLIC_L1_CHAIN_NAME,
138155
NEXT_PUBLIC_L2_CHAIN_NAME,
139-
NEXT_PUBLIC_L2_EXPLORER_URL,
140-
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID,
141-
NEXT_PUBLIC_L1_CROSS_DOMAIN_MESSANGER_PROXY,
142-
NEXT_PUBLIC_L1_STANDARD_BRIDGE_PROXY,
143-
NEXT_PUBLIC_L1_OPTIMISM_PORTAL_PROXY,
144-
NEXT_PUBLIC_L2_STANDARD_BRIDGE_PROXY,
156+
config,
157+
l1Chain,
158+
l2Chain,
145159
};

0 commit comments

Comments
 (0)