Skip to content

Commit 2c19ea4

Browse files
docs: add missing interop snippets (#91)
* chore: update bun in CI and run tests without interop * chore: fix docs workflow * chore: specify 0.4.40 mdbook-version * docs: add interop snippets * chore: use previous version of matter-labs/deploy-mdbooks * fix: try different mdbook-yapp version * fix: update mdbook-yapp to the latest 1.x.x version available * fix: formatting
1 parent 9a28e03 commit 2c19ea4

File tree

9 files changed

+899
-9
lines changed

9 files changed

+899
-9
lines changed

.github/workflows/ci-check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: Setup Bun
2121
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
2222
with:
23-
bun-version: '1.3.5'
23+
bun-version: '1.3.11'
2424

2525
- name: Install deps
2626
run: bun install

.github/workflows/ci-docs.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
pull_request:
88
paths:
99
- 'docs/**'
10-
- '.github/workflows/docs.yaml'
10+
- '.github/workflows/ci-docs.yaml'
1111
workflow_dispatch:
1212
inputs:
1313
ref:
@@ -55,7 +55,7 @@ jobs:
5555
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
5656

5757
- name: Install mdbook-yapp
58-
run: cargo install mdbook-yapp --locked
58+
run: cargo install mdbook-yapp --version 1.2.5 --locked
5959

6060
- name: Deploy mdBook to gh-pages
6161
uses: matter-labs/deploy-mdbooks@c72ae3825faeb7d20cbf3e67714f7253dd0ee7cb

.github/workflows/ci-release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ jobs:
102102
- name: Setup Bun
103103
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
104104
with:
105-
bun-version: '1.3.5'
105+
bun-version: '1.3.11'
106106

107107
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
108108
with:

.github/workflows/ci-scheduled-e2e.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Setup Bun
2626
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.0.2
2727
with:
28-
bun-version: '1.3.5'
28+
bun-version: '1.3.11'
2929

3030
- name: Install deps
3131
run: bun install --frozen-lockfile

.github/workflows/ci-test.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Setup Bun
2020
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
2121
with:
22-
bun-version: '1.3.5'
22+
bun-version: '1.3.11'
2323

2424
- name: Install deps
2525
run: bun install
@@ -50,7 +50,7 @@ jobs:
5050
- name: Setup Bun
5151
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.0.2
5252
with:
53-
bun-version: '1.3.5'
53+
bun-version: '1.3.11'
5454

5555
- name: Install deps
5656
run: bun install --frozen-lockfile
@@ -201,7 +201,7 @@ jobs:
201201
- name: Setup Bun
202202
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
203203
with:
204-
bun-version: '1.3.5'
204+
bun-version: '1.3.11'
205205

206206
- name: Install deps
207207
run: bun install
@@ -215,4 +215,4 @@ jobs:
215215
L2_RPC: http://localhost:3050
216216
PRIVATE_KEY: '0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110'
217217
run: |
218-
bun test ${{ matrix.suite }} --timeout 100000
218+
bun test ${{ matrix.suite }} --path-ignore-patterns='**/interop*' --timeout 100000
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { describe, it } from 'bun:test';
2+
3+
// ANCHOR: imports
4+
import { JsonRpcProvider, Wallet } from 'ethers';
5+
import { createEthersClient, createEthersSdk } from '../../../../src/adapters/ethers';
6+
7+
const L1_RPC = 'http://localhost:8545'; // e.g. https://sepolia.infura.io/v3/XXX
8+
const GW_RPC = 'http://localhost:3052'; // gateway chain RPC
9+
const SRC_L2_RPC = 'http://localhost:3050'; // source L2 RPC
10+
const DST_L2_RPC = 'http://localhost:3051'; // destination L2 RPC
11+
const PRIVATE_KEY = process.env.PRIVATE_KEY || '';
12+
const TOKEN_SRC_ADDRESS = process.env.TOKEN_SRC_ADDRESS || ''; // ERC-20 token on source L2
13+
// ANCHOR_END: imports
14+
15+
describe('ethers interop guide', () => {
16+
17+
it('sends ERC-20 across chains', async () => {
18+
await main();
19+
});
20+
21+
});
22+
23+
// ANCHOR: main
24+
async function main() {
25+
if (!PRIVATE_KEY) throw new Error('Set PRIVATE_KEY in env');
26+
27+
const l1 = new JsonRpcProvider(L1_RPC);
28+
const l2Src = new JsonRpcProvider(SRC_L2_RPC);
29+
const l2Dst = new JsonRpcProvider(DST_L2_RPC);
30+
31+
const signer = new Wallet(PRIVATE_KEY);
32+
const client = createEthersClient({ l1, l2: l2Src, signer });
33+
const sdk = createEthersSdk(client, {
34+
interop: { gwChain: GW_RPC },
35+
});
36+
37+
const me = (await signer.getAddress()) as `0x${string}`;
38+
const params = {
39+
actions: [
40+
{
41+
type: 'sendErc20' as const,
42+
token: TOKEN_SRC_ADDRESS as `0x${string}`,
43+
to: me,
44+
amount: 1_000_000n,
45+
},
46+
],
47+
};
48+
49+
// Send the interop bundle on source L2
50+
const handle = await sdk.interop.create(l2Dst, params);
51+
console.log('Source L2 tx:', handle.l2SrcTxHash);
52+
53+
// Wait until the bundle proof is available on destination
54+
const finalizationInfo = await sdk.interop.wait(l2Dst, handle, {
55+
pollMs: 5_000,
56+
timeoutMs: 30 * 60_000,
57+
});
58+
59+
// Execute the bundle on destination L2
60+
const result = await sdk.interop.finalize(l2Dst, finalizationInfo);
61+
console.log('Executed on destination:', result.dstExecTxHash);
62+
}
63+
// ANCHOR_END: main
64+
65+
// ANCHOR: quote
66+
const quote = await sdk.interop.quote(l2Dst, params);
67+
// {
68+
// route: 'direct' | 'indirect',
69+
// approvalsNeeded: [{ token, spender, amount }], // ERC-20 approval needed
70+
// totalActionValue: 0n,
71+
// bridgedTokenTotal: 1_000_000n,
72+
// interopFee: { token: '0x000...', amount: bigint },
73+
// l2Fee?: bigint
74+
// }
75+
// ANCHOR_END: quote
76+
77+
// ANCHOR: prepare
78+
const plan = await sdk.interop.prepare(l2Dst, params);
79+
// {
80+
// route: 'direct' | 'indirect',
81+
// summary: InteropQuote,
82+
// steps: [{ key, kind, description, tx: TransactionRequest }]
83+
// }
84+
// ANCHOR_END: prepare
85+
86+
// ANCHOR: create
87+
const handle = await sdk.interop.create(l2Dst, params);
88+
// {
89+
// kind: 'interop',
90+
// l2SrcTxHash: Hex, // tx hash on source L2
91+
// stepHashes: Record<string, Hex>,
92+
// plan: InteropPlan
93+
// }
94+
// ANCHOR_END: create
95+
96+
// ANCHOR: status
97+
const st = await sdk.interop.status(l2Dst, handle);
98+
// st.phase: 'SENT' | 'VERIFIED' | 'EXECUTED' | 'UNBUNDLED' | 'FAILED' | 'UNKNOWN'
99+
// ANCHOR_END: status
100+
101+
// ANCHOR: wait
102+
const finalizationInfo = await sdk.interop.wait(l2Dst, handle, {
103+
pollMs: 5_000, // how often to poll (ms), default 5000
104+
timeoutMs: 30 * 60_000, // max wait time (ms)
105+
});
106+
// Returns InteropFinalizationInfo once bundle proof is available on destination
107+
// ANCHOR_END: wait
108+
109+
// ANCHOR: finalize
110+
const result = await sdk.interop.finalize(l2Dst, finalizationInfo);
111+
// { bundleHash: Hex, dstExecTxHash: Hex }
112+
console.log('Executed on destination:', result.dstExecTxHash);
113+
// ANCHOR_END: finalize
114+
115+
// ANCHOR: try-catch-create
116+
try {
117+
const handle = await sdk.interop.create(l2Dst, params);
118+
const finalizationInfo = await sdk.interop.wait(l2Dst, handle);
119+
const result = await sdk.interop.finalize(l2Dst, finalizationInfo);
120+
console.log('dstExecTxHash:', result.dstExecTxHash);
121+
} catch (e) {
122+
console.error('Interop failed:', e);
123+
}
124+
// ANCHOR_END: try-catch-create
125+
126+
// ANCHOR: tryCreate
127+
const createResult = await sdk.interop.tryCreate(l2Dst, params);
128+
if (!createResult.ok) {
129+
console.error('Create failed:', createResult.error);
130+
return;
131+
}
132+
const handle = createResult.value;
133+
// ANCHOR_END: tryCreate

0 commit comments

Comments
 (0)