@@ -96,86 +96,106 @@ console.log(`Order submitted with ID: ${id}`);
9696
9797### On-Chain Operations
9898
99- The SDK provides helpers for common on-chain operations:
99+ The SDK exports ABIs and constants for on-chain operations. Use viem directly for contract interactions :
100100
101- #### Bridging with Passage
102-
103- Enter Signet from the host chain:
101+ #### Permit2 Approvals
104102
105103``` typescript
106- import { enter , enterToken , MAINNET } from " @signet-sh/sdk" ;
107- import { createWalletClient , http } from " viem" ;
108- import { mainnet } from " viem/chains" ;
104+ import { PERMIT2_ADDRESS } from " @signet-sh/sdk" ;
105+ import { erc20Abi , maxUint256 } from " viem" ;
109106
110- const client = createWalletClient ({
111- account ,
112- chain: mainnet ,
113- transport: http (),
107+ // Approve Permit2 to spend your tokens (one-time per token)
108+ await walletClient .writeContract ({
109+ address: tokenAddress ,
110+ abi: erc20Abi ,
111+ functionName: " approve" ,
112+ args: [PERMIT2_ADDRESS , maxUint256 ],
114113});
115114
116- // Bridge native ETH
117- const hash = await enter (client , {
118- passage: MAINNET .hostPassage ,
119- recipient: " 0x..." ,
120- amount: 1000000000000000000n , // 1 ETH
115+ // Check current allowance
116+ const allowance = await publicClient .readContract ({
117+ address: tokenAddress ,
118+ abi: erc20Abi ,
119+ functionName: " allowance" ,
120+ args: [ownerAddress , PERMIT2_ADDRESS ],
121+ });
122+ ```
123+
124+ For tokens like USDT that require resetting allowance to zero before setting a new value, use ` ensurePermit2Approval ` :
125+
126+ ``` typescript
127+ import { ensurePermit2Approval } from " @signet-sh/sdk" ;
128+
129+ // Handles USDT-style tokens automatically
130+ const { approved, txHash } = await ensurePermit2Approval (
131+ walletClient ,
132+ publicClient ,
133+ {
134+ token: usdtAddress ,
135+ owner: account .address ,
136+ amount: 1000000n ,
137+ }
138+ );
139+ ```
140+
141+ #### Bridging with Passage
142+
143+ ``` typescript
144+ import { passageAbi , MAINNET } from " @signet-sh/sdk" ;
145+
146+ // Bridge native ETH to Signet
147+ await walletClient .writeContract ({
148+ address: MAINNET .hostPassage ,
149+ abi: passageAbi ,
150+ functionName: " enter" ,
151+ args: [recipientAddress ],
152+ value: 1000000000000000000n , // 1 ETH
121153});
122154
123- // Bridge ERC20 tokens (requires prior approval)
124- const hash = await enterToken (client , {
125- passage: MAINNET .hostPassage ,
126- rollupChainId: MAINNET .rollupChainId ,
127- recipient: " 0x..." ,
128- token: " 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" , // USDC
129- amount: 1000000n , // 1 USDC
155+ // Bridge ERC20 tokens to Signet (requires prior token approval to Passage)
156+ await walletClient .writeContract ({
157+ address: MAINNET .hostPassage ,
158+ abi: passageAbi ,
159+ functionName: " enterToken" ,
160+ args: [MAINNET .rollupChainId , recipientAddress , tokenAddress , amount ],
130161});
131162```
132163
133164#### WETH Wrapping
134165
135- Convert between ETH and WETH:
136-
137166``` typescript
138- import { wrapEth , unwrapEth , getTokenAddress , MAINNET } from " @signet-sh/sdk" ;
167+ import { wethAbi , getTokenAddress , MAINNET } from " @signet-sh/sdk" ;
139168
140169const wethAddress = getTokenAddress (" WETH" , MAINNET .hostChainId , MAINNET )! ;
141170
142171// Wrap ETH → WETH
143- await wrapEth (client , { weth: wethAddress , amount: 1000000000000000000n });
172+ await walletClient .writeContract ({
173+ address: wethAddress ,
174+ abi: wethAbi ,
175+ functionName: " deposit" ,
176+ value: 1000000000000000000n , // 1 ETH
177+ });
144178
145179// Unwrap WETH → ETH
146- await unwrapEth (client , { weth: wethAddress , amount: 1000000000000000000n });
180+ await walletClient .writeContract ({
181+ address: wethAddress ,
182+ abi: wethAbi ,
183+ functionName: " withdraw" ,
184+ args: [1000000000000000000n ], // 1 WETH
185+ });
147186```
148187
149- #### Permit2 Approvals
150-
151- Manage ERC20 approvals for Permit2:
188+ #### Reading Output Witness
152189
153190``` typescript
154- import {
155- getPermit2Allowance ,
156- approvePermit2 ,
157- ensurePermit2Approval ,
158- } from " @signet-sh/sdk" ;
191+ import { rollupOrdersAbi , MAINNET } from " @signet-sh/sdk" ;
159192
160- // Check current allowance
161- const allowance = await getPermit2Allowance (publicClient , {
162- token: usdcAddress ,
163- owner: account .address ,
193+ const { witnessHash, witnessTypeString } = await publicClient .readContract ({
194+ address: MAINNET .rollupOrders ,
195+ abi: rollupOrdersAbi ,
196+ functionName: " outputWitness" ,
197+ args: [outputs ],
164198});
165-
166- // Approve Permit2 (max by default)
167- await approvePermit2 (walletClient , { token: usdcAddress });
168-
169- // Smart approval - handles USDT-style tokens that require reset to zero
170- const { approved, txHash } = await ensurePermit2Approval (
171- walletClient ,
172- publicClient ,
173- {
174- token: usdtAddress ,
175- owner: account .address ,
176- amount: 1000000n ,
177- }
178- );
179199```
180200
181201### Chain Configurations
@@ -199,10 +219,8 @@ console.log(PARMIGIANA.rollupChainId); // 88888n
199219import { MAINNET , PARMIGIANA } from " @signet-sh/sdk/constants" ;
200220import { UnsignedOrder } from " @signet-sh/sdk/signing" ;
201221import type { SignedOrder } from " @signet-sh/sdk/types" ;
202- import { rollupOrdersAbi } from " @signet-sh/sdk/abi" ;
222+ import { rollupOrdersAbi , passageAbi , wethAbi } from " @signet-sh/sdk/abi" ;
203223import { createTxCacheClient } from " @signet-sh/sdk/client" ;
204- import { enter , enterToken } from " @signet-sh/sdk/passage" ;
205- import { wrapEth , unwrapEth } from " @signet-sh/sdk/weth" ;
206224import { ensurePermit2Approval } from " @signet-sh/sdk/permit2" ;
207225```
208226
@@ -379,12 +397,6 @@ const balances = await Promise.all(
379397- ` serializeEthBundle(bundle) ` - Serialize bundle for JSON-RPC
380398- ` serializeCallBundle(bundle) ` - Serialize call bundle for JSON-RPC
381399- ` createTxCacheClient(url) ` - Create a tx-cache client for bundle submission
382- - ` enter(client, params) ` - Bridge native ETH to Signet via Passage
383- - ` enterToken(client, params) ` - Bridge ERC20 tokens to Signet via Passage
384- - ` wrapEth(client, params) ` - Wrap native ETH into WETH
385- - ` unwrapEth(client, params) ` - Unwrap WETH back to native ETH
386- - ` getPermit2Allowance(client, params) ` - Get ERC20 allowance for Permit2
387- - ` approvePermit2(client, params) ` - Approve Permit2 to spend ERC20
388400- ` ensurePermit2Approval(walletClient, publicClient, params) ` - Smart Permit2 approval with USDT handling
389401- ` getTokenDecimals(symbol, config?) ` - Get token decimals with chain-specific overrides
390402- ` needsWethWrap(symbol, direction, flow) ` - Check if ETH needs wrapping for operation
@@ -407,6 +419,13 @@ const balances = await Promise.all(
407419- ` MAINNET ` - Mainnet chain configuration
408420- ` PARMIGIANA ` - Parmigiana testnet configuration
409421
422+ ### ABIs
423+
424+ - ` passageAbi ` - Passage bridge contract ABI
425+ - ` wethAbi ` - WETH contract ABI
426+ - ` rollupOrdersAbi ` - Rollup orders contract ABI
427+ - ` permit2Abi ` - Permit2 contract ABI
428+
410429## Compatibility
411430
412431This SDK produces signed orders that are byte-for-byte compatible with the Rust ` signet-types ` crate. The order hash computation matches exactly, ensuring interoperability between TypeScript and Rust implementations.
0 commit comments