@circle-fin/adapter-ethers-v6 0.0.2-alpha.6 → 0.0.2-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +437 -159
  2. package/index.cjs.js +8462 -6226
  3. package/index.d.ts +1081 -285
  4. package/index.mjs +8461 -6226
  5. package/package.json +2 -2
package/README.md CHANGED
@@ -8,31 +8,44 @@
8
8
 
9
9
  **Type-safe EVM blockchain adapter powered by Ethers v6**
10
10
 
11
- _Seamlessly interact with 12+ EVM networks using a single, strongly-typed interface_
11
+ _Seamlessly interact with 16+ EVM networks using a single, strongly-typed interface_
12
12
 
13
13
  </div>
14
14
 
15
15
  ## Table of Contents
16
16
 
17
- - [Ethers v6 Adapter](#ethers-v6-adapter)
18
- - [Overview](#overview)
19
- - [Why Ethers v6 Adapter?](#why-ethers-v6-adapter)
20
- - [Installation](#installation)
21
- - [Quick Start](#quick-start)
22
- - [🚀 Easy Setup with Factory Methods (Recommended)](#-easy-setup-with-factory-methods-recommended)
23
- - [🏭 Production Considerations](#-production-considerations)
24
- - [Usage Examples](#usage-examples)
25
- - [Basic Usage with Factory Methods](#basic-usage-with-factory-methods)
26
- - [Manual Setup with Ethers Clients](#manual-setup-with-ethers-clients)
27
- - [Multi-Chain Setup](#multi-chain-setup)
28
- - [Methods](#methods)
29
- - [Development](#development)
30
- - [Contributing](#contributing)
31
- - [License](#license)
17
+ - [Overview](#overview)
18
+ - [Why Ethers v6 Adapter?](#why-ethers-v6-adapter)
19
+ - [When to Use This Adapter](#when-to-use-this-adapter)
20
+ - [Installation](#installation)
21
+ - [Quick Start](#quick-start)
22
+ - [Zero-Config Setup (Recommended)](#zero-config-setup-recommended)
23
+ - [Production Setup](#production-setup)
24
+ - [Browser Wallet Setup](#browser-wallet-setup)
25
+ - [OperationContext Pattern](#operationcontext-pattern)
26
+ - [Why OperationContext?](#why-operationcontext)
27
+ - [Basic Usage](#basic-usage)
28
+ - [Multi-Chain Operations](#multi-chain-operations)
29
+ - [Address Context Guide](#address-context-guide)
30
+ - [User-Controlled (Recommended)](#user-controlled-recommended)
31
+ - [Developer-Controlled (Advanced)](#developer-controlled-advanced)
32
+ - [Decision Matrix](#decision-matrix)
33
+ - [Usage Examples](#usage-examples)
34
+ - [Contract Interactions](#contract-interactions)
35
+ - [EIP-712 Signatures](#eip-712-signatures)
36
+ - [Cross-Chain Bridging](#cross-chain-bridging)
37
+ - [API Reference](#api-reference)
38
+ - [Factory Functions](#factory-functions)
39
+ - [Core Methods](#core-methods)
40
+ - [Token Operations](#token-operations)
41
+ - [Migration Guide](#migration-guide)
42
+ - [Supported Chains](#supported-chains)
43
+ - [Development](#development)
44
+ - [License](#license)
32
45
 
33
46
  ## Overview
34
47
 
35
- The Ethers v6 Adapter is a strongly-typed implementation of the [`Adapter`](https://github.com/circlefin/stablecoin-kits-private/blob/main/core/adapter/README.md) interface for **EVM-compatible blockchains**. Built on top of the popular [Ethers v6](https://docs.ethers.org/v6/) library, it provides type-safe blockchain interactions through a unified interface that's designed to work seamlessly with the [Bridging Kit](https://github.com/circlefin/stablecoin-kits-private/tree/main/kits/bridging-kit) for cross-chain USDC transfers between Solana and EVM networks, as well as any future kits for additional stablecoin operations. It can be used by any Kit built using the Stablecoin Kits architecture and/or any providers plugged into those kits.
48
+ The Ethers v6 Adapter is a strongly-typed implementation of the `Adapter` interface for **EVM-compatible blockchains**. Built on top of the popular [Ethers v6](https://docs.ethers.org/v6/) library, it provides type-safe blockchain interactions through a unified interface that's designed to work seamlessly with the [Bridging Kit](https://www.npmjs.com/package/@circle-fin/bridging-kit) for cross-chain USDC transfers between Solana and EVM networks, as well as any future kits for additional stablecoin operations. It can be used by any Kit built using the Stablecoin Kits architecture and/or any providers plugged into those kits.
36
49
 
37
50
  ### Why Ethers v6 Adapter?
38
51
 
@@ -43,24 +56,22 @@ The Ethers v6 Adapter is a strongly-typed implementation of the [`Adapter`](http
43
56
  - **🔄 Transaction lifecycle** - Complete prepare/estimate/execute workflow
44
57
  - **🌉 Cross-chain ready** - Seamlessly bridge USDC between EVM chains and Solana
45
58
 
46
- ### When and How Should I Use The Ethers v6 Adapter?
59
+ ### When to Use This Adapter
47
60
 
48
- #### I'm a developer using a kit
61
+ #### For Kit Users
49
62
 
50
- If you're using one of the kits to perform actions such as bridging from chain 'A' to chain 'B', you only need to instantiate the adapter for your chain and pass it to the kit.
51
-
52
- ##### Example
63
+ If you're using the Bridging Kit or other Stablecoin Kits for cross-chain operations, you only need to instantiate one adapter and pass it to the kit. The same adapter works across all supported chains.
53
64
 
54
65
  ```typescript
66
+ // Single adapter instance for multi-chain operations
55
67
  const adapter = createAdapterFromPrivateKey({
56
68
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
57
- defaultChain: 'Ethereum',
58
69
  })
59
70
  ```
60
71
 
61
- #### I'm a developer making a Kit Provider
72
+ #### For Kit Provider Developers
62
73
 
63
- If you are making a provider for other Kit users to plug in to the kit, e.g. a `BridgingProvider`, and you'll need to interact with diff chains, then you'll need to use the abstracted `Adapter` methods to execute on chain.
74
+ If you're building a provider (e.g., a custom `BridgingProvider` implementation), you'll use the adapter's abstracted methods to interact with different chains. The OperationContext pattern makes multi-chain operations seamless.
64
75
 
65
76
  ## Installation
66
77
 
@@ -72,238 +83,508 @@ yarn add @circle-fin/adapter-ethers-v6 ethers
72
83
 
73
84
  ## Quick Start
74
85
 
75
- ### 🚀 Easy Setup with Factory Methods (Recommended)
86
+ ### Zero-Config Setup (Recommended)
76
87
 
77
- The simplest way to get started is with our factory methods. You can create just **one adapter** and use it across different chains!
88
+ The simplest way to get started with lazy initialization. Default configuration handles adapter setup automatically.
78
89
 
79
90
  ```typescript
80
91
  import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
81
92
 
82
- // Create ONE adapter that can work across chains!
93
+ // Minimal configuration with lazy initialization
83
94
  const adapter = createAdapterFromPrivateKey({
84
95
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
85
- defaultChain: 'Ethereum',
96
+ // Defaults applied:
97
+ // - addressContext: 'user-controlled'
98
+ // - supportedChains: all EVM chains (~34 networks)
99
+ // - Lazy initialization: wallet connects to chain on first operation
86
100
  })
87
101
 
88
- // Ready to use with Bridging Kit!
89
- const address = await adapter.getAddress()
90
- console.log('Connected address:', address)
102
+ // Chain specified per operation via OperationContext
103
+ const prepared = await adapter.prepare(
104
+ {
105
+ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
106
+ abi: usdcAbi,
107
+ functionName: 'transfer',
108
+ args: ['0xrecipient', '1000000'],
109
+ },
110
+ { chain: 'Ethereum' }, // Chain specified in context
111
+ )
112
+
113
+ const txHash = await prepared.execute()
91
114
  ```
92
115
 
93
- ### 🏭 Production Considerations
116
+ ### Production Setup
94
117
 
95
- > **⚠️ Important for Production**: The factory methods use Ethers's default public RPC endpoints, which may have rate limits and lower reliability. For production applications, we strongly recommend using dedicated RPC providers like Alchemy, Infura, or QuickNode.
118
+ For production use, provide custom RPC endpoints for better reliability and performance:
96
119
 
97
120
  ```typescript
98
121
  import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
99
122
  import { JsonRpcProvider } from 'ethers'
123
+ import { Ethereum, Base, Polygon } from '@core/chains'
100
124
 
101
- // Production-ready setup with custom RPC endpoints
125
+ // Production-ready with custom RPC endpoints and lazy initialization
102
126
  const adapter = createAdapterFromPrivateKey({
103
127
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
104
- defaultChain: 'Ethereum',
105
- getProvider: ({ chain }) =>
106
- new JsonRpcProvider(
107
- `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
108
- ),
128
+ // Custom RPC provider with explicit chain mapping
129
+ getProvider: ({ chain }) => {
130
+ // Map chain names to RPC endpoints
131
+ // Customize this mapping based on your RPC provider
132
+ const rpcEndpoints: Record<string, string> = {
133
+ Ethereum: `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
134
+ Base: `https://base-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
135
+ Polygon: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
136
+ }
137
+
138
+ const endpoint = rpcEndpoints[chain.name]
139
+ if (!endpoint) {
140
+ throw new Error(`RPC endpoint not configured for chain: ${chain.name}`)
141
+ }
142
+
143
+ return new JsonRpcProvider(endpoint, chain.chainId)
144
+ },
145
+ // Optionally restrict to specific chains
146
+ capabilities: {
147
+ supportedChains: [Ethereum, Base, Polygon],
148
+ },
109
149
  })
110
150
  ```
111
151
 
112
- ### 🌐 Browser Support with Wallet Providers
152
+ > **⚠️ Production Note**: Default factory methods use public RPC endpoints which may have rate limits. For production, use dedicated providers like Alchemy, Infura, or QuickNode.
153
+
154
+ ### Browser Wallet Setup
113
155
 
114
- For browser environments with wallet providers like MetaMask:
156
+ For browser environments with MetaMask or WalletConnect:
115
157
 
116
158
  ```typescript
117
159
  import { createAdapterFromProvider } from '@circle-fin/adapter-ethers-v6'
118
160
 
119
- // Create an adapter from a browser wallet
161
+ // Minimal browser wallet configuration
120
162
  const adapter = await createAdapterFromProvider({
121
163
  provider: window.ethereum,
122
- chain: 'Ethereum', // Required: specify the intended chain
123
- getProvider: ({ chain }) =>
124
- new JsonRpcProvider(
125
- `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
126
- ),
164
+ // Default capabilities applied automatically
127
165
  })
166
+
167
+ // User will be prompted to connect wallet
168
+ // Address is automatically resolved from connected wallet
169
+ const prepared = await adapter.prepare(
170
+ {
171
+ address: '0xcontract',
172
+ abi: contractAbi,
173
+ functionName: 'approve',
174
+ args: ['0xspender', '1000000'],
175
+ },
176
+ { chain: 'Polygon' },
177
+ )
128
178
  ```
129
179
 
130
- ### 🔧 Advanced Manual Setup
180
+ ## OperationContext Pattern
181
+
182
+ ### Why OperationContext?
183
+
184
+ The OperationContext pattern is the modern approach for multi-chain operations. Instead of locking an adapter to a single chain, you specify the chain per operation. This enables powerful patterns like using a single adapter for cross-chain bridging.
185
+
186
+ **Benefits:**
187
+
188
+ - ✅ **One adapter, many chains** - No need to create separate adapters for each network
189
+ - ✅ **Explicit is better** - Chain is always clear in your code
190
+ - ✅ **Type-safe** - Full TypeScript support with compile-time checks
191
+ - ✅ **Eliminates ambiguity** - No confusion about which chain is being used
192
+
193
+ ### Basic Usage
131
194
 
132
- For advanced use cases requiring custom RPC endpoints:
195
+ Every operation accepts an `OperationContext` parameter that specifies the chain:
133
196
 
134
197
  ```typescript
135
- import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
136
- import { JsonRpcProvider, Wallet } from 'ethers'
198
+ import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
137
199
 
138
- // Use your existing Ethers setup
139
- const provider = new JsonRpcProvider('https://your-custom-rpc.com')
140
- const wallet = new Wallet(process.env.PRIVATE_KEY, provider)
200
+ // Create adapter without specifying a chain - true lazy initialization
201
+ const adapter = createAdapterFromPrivateKey({
202
+ privateKey: process.env.PRIVATE_KEY as `0x${string}`,
203
+ })
204
+
205
+ // Chain specified explicitly in every operation
206
+ const prepared = await adapter.prepare(
207
+ {
208
+ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
209
+ abi: usdcAbi,
210
+ functionName: 'transfer',
211
+ args: ['0xrecipient', '1000000'],
212
+ },
213
+ { chain: 'Ethereum' },
214
+ )
215
+
216
+ const gas = await prepared.estimate()
217
+ const txHash = await prepared.execute()
218
+ ```
141
219
 
142
- // Create the adapter
143
- const adapter = new EthersAdapter({
144
- provider,
145
- wallet,
220
+ ### Multi-Chain Operations
221
+
222
+ Use a single adapter instance for operations across multiple chains:
223
+
224
+ ```typescript
225
+ // Create adapter once for use across multiple chains
226
+ const adapter = createAdapterFromPrivateKey({
227
+ privateKey: process.env.PRIVATE_KEY as `0x${string}`,
146
228
  })
229
+
230
+ // Transfer USDC on Ethereum
231
+ const ethPrepared = await adapter.prepare(
232
+ {
233
+ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
234
+ abi: usdcAbi,
235
+ functionName: 'transfer',
236
+ args: ['0xrecipient', '1000000'],
237
+ },
238
+ { chain: 'Ethereum' },
239
+ )
240
+
241
+ // Transfer USDC on Base using the same adapter
242
+ const basePrepared = await adapter.prepare(
243
+ {
244
+ address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
245
+ abi: usdcAbi,
246
+ functionName: 'transfer',
247
+ args: ['0xrecipient', '1000000'],
248
+ },
249
+ { chain: 'Base' },
250
+ )
251
+
252
+ // Execute both transfers
253
+ await ethPrepared.execute()
254
+ await basePrepared.execute()
147
255
  ```
148
256
 
149
- ## Features
257
+ ## Address Context Guide
150
258
 
151
- - **Full EVM compatibility** - Works with any Ethereum-compatible blockchain
152
- - ✅ **Ethers v6 integration** - Uses your existing `JsonRpcProvider` and `Wallet`
153
- - ✅ **Transaction lifecycle** - Complete prepare/estimate/execute workflow
154
- - ✅ **Type safety** - Full TypeScript support with strict mode
155
- - ✅ **Cross-chain ready** - Seamlessly bridge USDC between Solana and EVM chains
259
+ The adapter supports two address control patterns. Choose the one that fits your use case.
156
260
 
157
- ## Usage Examples
261
+ ### User-Controlled (Recommended)
158
262
 
159
- ### Basic Usage with Factory Methods
263
+ **Best for:** Private key wallets, browser wallets (MetaMask), hardware wallets
160
264
 
161
- ```typescript
162
- import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
163
- import { BridgingKit } from '@circle-fin/bridging-kit'
265
+ **How it works:** Address is automatically resolved from the connected signer/wallet. You don't need to specify it in the OperationContext.
266
+
267
+ **When to use:**
164
268
 
165
- // Create ONE adapter that can work across chains - so simple!
269
+ - Building a dApp where users connect their wallets
270
+ - ✅ Using a private key for backend automation
271
+ - ✅ Single wallet signing all transactions
272
+ - ✅ Server-side scripts with one identity
273
+
274
+ ```typescript
275
+ // User-controlled adapter (default for factory functions)
166
276
  const adapter = createAdapterFromPrivateKey({
167
277
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
168
- defaultChain: 'Ethereum',
278
+ // addressContext: 'user-controlled' is the default
169
279
  })
170
280
 
171
- // Use directly with Bridging Kit - same adapter, different chains!
172
- const kit = new BridgingKit()
173
- const result = await kit.bridge({
174
- from: { adapter }, // Uses default chain (Ethereum)
175
- to: { adapter, chain: 'Base' }, // Same adapter, different chain
176
- amount: '10.50',
177
- })
281
+ // Address automatically resolved from private key/wallet
282
+ const prepared = await adapter.prepare(
283
+ {
284
+ address: '0xcontract',
285
+ abi: contractAbi,
286
+ functionName: 'approve',
287
+ args: ['0xspender', '1000000'],
288
+ },
289
+ { chain: 'Polygon' }, // No address needed in context for user-controlled
290
+ )
178
291
  ```
179
292
 
180
- ### Manual Setup with Ethers
293
+ ### Developer-Controlled (Advanced)
294
+
295
+ **Best for:** Custody solutions, multi-entity systems, enterprise applications
296
+
297
+ **How it works:** Address must be explicitly provided in the OperationContext for each operation.
298
+
299
+ **When to use:**
300
+
301
+ - ✅ Building a custody solution managing multiple client wallets
302
+ - ✅ Enterprise system where different users have different signing keys
303
+ - ✅ Multi-sig or delegated signing infrastructure
304
+ - ✅ Systems where address varies per transaction
181
305
 
182
306
  ```typescript
183
307
  import { EthersAdapter } from '@circle-fin/adapter-ethers-v6'
184
- import { BridgingKit } from '@circle-fin/bridging-kit'
185
- import { JsonRpcProvider, Wallet } from 'ethers'
308
+ import { Ethereum, Base } from '@core/chains'
309
+
310
+ // Developer-controlled adapter (manual constructor)
311
+ const adapter = new EthersAdapter(
312
+ {
313
+ getProvider: ({ chain }) => new JsonRpcProvider('https://...'),
314
+ signer: wallet,
315
+ },
316
+ {
317
+ addressContext: 'developer-controlled', // ← Explicit address required
318
+ supportedChains: [Ethereum, Base],
319
+ },
320
+ )
321
+
322
+ // Address must be provided in context for developer-controlled adapters
323
+ const prepared = await adapter.prepare(
324
+ {
325
+ address: '0xcontract',
326
+ abi: contractAbi,
327
+ functionName: 'approve',
328
+ args: ['0xspender', '1000000'],
329
+ },
330
+ {
331
+ chain: 'Ethereum',
332
+ address: '0x1234...', // Required for developer-controlled
333
+ },
334
+ )
335
+ ```
336
+
337
+ ## Usage Examples
186
338
 
187
- const provider = new JsonRpcProvider('https://your-custom-rpc.com')
188
- const wallet = new Wallet(process.env.PRIVATE_KEY!, provider)
339
+ ### Contract Interactions
189
340
 
190
- const adapter = new EthersAdapter({ provider, wallet })
341
+ **Transfer USDC** across different chains with the same adapter:
191
342
 
192
- const destinationAdapter = new EthersAdapter({
193
- provider: new JsonRpcProvider('https://another-rpc.com'),
194
- wallet: new Wallet(
195
- process.env.PRIVATE_KEY!,
196
- new JsonRpcProvider('https://another-rpc.com'),
197
- ),
343
+ ```typescript
344
+ import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
345
+ import { parseAbi } from 'ethers'
346
+
347
+ // Create adapter with lazy initialization
348
+ const adapter = createAdapterFromPrivateKey({
349
+ privateKey: process.env.PRIVATE_KEY as `0x${string}`,
198
350
  })
199
351
 
200
- const kit = new BridgingKit()
201
- const result = await kit.bridge({
202
- from: { adapter },
203
- to: { adapter: destinationAdapter },
204
- amount: '10.50',
352
+ const usdcAbi = parseAbi([
353
+ 'function transfer(address to, uint256 amount) returns (bool)',
354
+ ])
355
+
356
+ // Transfer on Ethereum - chain specified in operation
357
+ const ethPrepared = await adapter.prepare(
358
+ {
359
+ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
360
+ abi: usdcAbi,
361
+ functionName: 'transfer',
362
+ args: ['0xrecipient', '1000000'], // 1 USDC (6 decimals)
363
+ },
364
+ { chain: 'Ethereum' },
365
+ )
366
+
367
+ // Estimate and execute
368
+ const gas = await ethPrepared.estimate()
369
+ console.log('Estimated gas:', gas.gas)
370
+
371
+ const txHash = await ethPrepared.execute()
372
+ console.log('Transaction hash:', txHash)
373
+ ```
374
+
375
+ ### EIP-712 Signatures
376
+
377
+ **Sign permit approvals** for gasless token approvals:
378
+
379
+ ```typescript
380
+ import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
381
+
382
+ const adapter = createAdapterFromPrivateKey({
383
+ privateKey: process.env.PRIVATE_KEY as `0x${string}`,
205
384
  })
385
+
386
+ // Sign ERC-2612 permit (gasless USDC approval)
387
+ const signature = await adapter.signTypedData(
388
+ {
389
+ domain: {
390
+ name: 'USD Coin',
391
+ version: '2',
392
+ chainId: 1,
393
+ verifyingContract: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
394
+ },
395
+ types: {
396
+ Permit: [
397
+ { name: 'owner', type: 'address' },
398
+ { name: 'spender', type: 'address' },
399
+ { name: 'value', type: 'uint256' },
400
+ { name: 'nonce', type: 'uint256' },
401
+ { name: 'deadline', type: 'uint256' },
402
+ ],
403
+ },
404
+ primaryType: 'Permit',
405
+ message: {
406
+ owner: '0xowner',
407
+ spender: '0xspender',
408
+ value: '1000000',
409
+ nonce: '0',
410
+ deadline: '1735689600',
411
+ },
412
+ },
413
+ { chain: 'Ethereum' }, // Chain must be specified
414
+ )
415
+
416
+ console.log('Permit signature:', signature)
417
+ // Use signature for gasless approval
206
418
  ```
207
419
 
208
- ### Multi-Chain Setup
420
+ ### Cross-Chain Bridging
421
+
422
+ **Bridge USDC** using the Bridging Kit with OperationContext:
209
423
 
210
424
  ```typescript
211
425
  import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
212
426
  import { BridgingKit } from '@circle-fin/bridging-kit'
213
427
 
214
- const kit = new BridgingKit()
215
-
216
- // Create ONE adapter that can work across ANY supported chain
428
+ // Create adapter for multi-chain operations
217
429
  const adapter = createAdapterFromPrivateKey({
218
430
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
219
- defaultChain: 'Ethereum', // This is just the default
220
431
  })
221
432
 
222
- // Use for cross-chain bridging by specifying different chains
433
+ const kit = new BridgingKit()
434
+
435
+ // Bridge from Ethereum to Base using the same adapter
223
436
  const result = await kit.bridge({
224
- from: { adapter }, // Ethereum (from defaultChain)
225
- to: { adapter, chain: 'Base' }, // Base (explicitly specified)
226
- amount: '10.50',
437
+ from: { adapter, chain: 'Ethereum' },
438
+ to: { adapter, chain: 'Base' },
439
+ amount: '100.50',
227
440
  token: 'USDC',
228
441
  })
229
442
 
230
- // Or bridge between any other supported chains
231
- const anotherResult = await kit.bridge({
232
- from: { adapter, chain: 'Arbitrum' },
233
- to: { adapter, chain: 'Polygon' },
234
- amount: '25.00',
235
- token: 'USDC',
443
+ console.log('Bridge transaction:', result.transactionHash)
444
+ ```
445
+
446
+ ## API Reference
447
+
448
+ ### Factory Functions
449
+
450
+ #### `createAdapterFromPrivateKey(params)`
451
+
452
+ Creates an adapter from a private key for server-side use.
453
+
454
+ **Parameters:**
455
+
456
+ - `privateKey` - 32-byte hex string with `0x` prefix
457
+ - `getProvider?` - Optional custom provider function
458
+ - `capabilities?` - Optional partial capabilities (defaults: user-controlled + all EVM chains)
459
+
460
+ **Returns:** `EthersAdapter` instance with lazy initialization
461
+
462
+ **Note:** No chain required at creation time. The adapter connects to chains lazily on first operation.
463
+
464
+ ```typescript
465
+ const adapter = createAdapterFromPrivateKey({
466
+ privateKey: '0x...',
236
467
  })
237
468
  ```
238
469
 
239
- > **💡 Pro Tip**: With the single adapter pattern, you create one adapter and can use it for bridging between any supported EVM chains. Just specify the desired chain in the bridge parameters!
470
+ #### `createAdapterFromProvider(params)`
240
471
 
241
- ## Supported Chains
472
+ Creates an adapter from a browser wallet provider (MetaMask, WalletConnect, etc.).
242
473
 
243
- Works with all EVM-compatible chains supported by Ethers v6 and the Bridging Kit:
474
+ **Parameters:**
244
475
 
245
- **Ethereum**, **Base**, **Arbitrum**, **Avalanche**, **Polygon**, **Optimism**, **Linea**, **Sonic**, **Unichain**, **World Chain**, **Codex**, and their respective testnets.
476
+ - `provider` - EIP-1193 compatible provider
477
+ - `getProvider?` - Optional custom provider function
478
+ - `capabilities?` - Optional partial capabilities (defaults: user-controlled + all EVM chains)
246
479
 
247
- ## API Reference
480
+ **Returns:** `Promise<EthersAdapter>` instance
481
+
482
+ ```typescript
483
+ const adapter = await createAdapterFromProvider({
484
+ provider: window.ethereum,
485
+ })
486
+ ```
487
+
488
+ ### Core Methods
489
+
490
+ #### `prepare(params, ctx)`
491
+
492
+ Prepares a contract function call for estimation and execution.
248
493
 
249
- ### Constructor Options
494
+ **Parameters:**
495
+
496
+ - `params` - Contract call parameters (address, abi, functionName, args)
497
+ - `ctx` - **Required** OperationContext with chain specification
498
+
499
+ **Returns:** `Promise<PreparedChainRequest>` with `estimate()` and `execute()` methods
250
500
 
251
501
  ```typescript
252
- interface EthersAdapterOptions {
253
- getProvider: (params: { chain: ChainDefinition }) => Provider
254
- signer: Signer
255
- }
502
+ const prepared = await adapter.prepare(
503
+ {
504
+ address: '0xcontract',
505
+ abi: contractAbi,
506
+ functionName: 'transfer',
507
+ args: ['0xto', '1000000'],
508
+ },
509
+ { chain: 'Ethereum' }, // Required
510
+ )
256
511
  ```
257
512
 
258
- ### Methods
513
+ #### `signTypedData(typedData, ctx)`
514
+
515
+ Signs EIP-712 typed data for permits, meta-transactions, etc.
516
+
517
+ **Parameters:**
259
518
 
260
- - `getAddress()` - Get the connected wallet address
261
- - `getChain()` - Get chain information
262
- - `prepare()` - Prepare transactions for execution
263
- - `estimate()` - Estimate transaction costs
264
- - `execute()` - Execute prepared transactions
265
- - `waitForTransaction()` - Wait for transaction confirmation
266
- - `calculateTransactionFee()` - Calculate transaction fees with optional buffer
267
- - `readContract()` - Read contract functions with comprehensive validation
519
+ - `typedData` - EIP-712 structured data
520
+ - `ctx` - **Required** OperationContext with chain specification
268
521
 
269
- You can see the implementation of each of these methods in the Ethers v6 Adapter's [main implementation file](./src/adapter/adapter.ts).
522
+ **Returns:** `Promise<string>` - Signature as hex string
270
523
 
271
- ### Token Operations via Actions
524
+ ```typescript
525
+ const signature = await adapter.signTypedData(permitData, {
526
+ chain: 'Ethereum',
527
+ })
528
+ ```
272
529
 
273
- For token balance and allowance operations, this adapter uses the standardized action-based system inherited from `EvmAdapter`:
530
+ #### `waitForTransaction(txHash, config?)`
274
531
 
275
- - **`token.balanceOf`** - Get balance for any ERC-20 token
276
- - **`token.allowance`** - Get allowance for any ERC-20 token
277
- - **`usdc.balanceOf`** - Get USDC balance (uses `token.balanceOf` with USDC address)
278
- - **`usdc.allowance`** - Get USDC allowance (uses `token.allowance` with USDC address)
532
+ Waits for transaction confirmation.
279
533
 
280
- These actions provide type-safe, validated interfaces and use the adapter's `readContract()` method internally.
534
+ **Parameters:**
281
535
 
282
- ## Integration with Stablecoin Kits
536
+ - `txHash` - Transaction hash to wait for
537
+ - `config?` - Optional wait configuration (confirmations, timeout)
283
538
 
284
- This adapter is designed to work seamlessly across the Stablecoin Kits ecosystem. Here's an example with the [Bridging Kit](https://github.com/circlefin/stablecoin-kits-private/tree/main/kits/bridging-kit):
539
+ **Returns:** `Promise<TransactionReceipt>`
285
540
 
286
541
  ```typescript
287
- import { BridgingKit } from '@circle-fin/bridging-kit'
288
- import { createAdapterFromPrivateKey } from '@circle-fin/adapter-ethers-v6'
542
+ const receipt = await adapter.waitForTransaction('0x...')
543
+ ```
289
544
 
290
- const kit = new BridgingKit()
545
+ #### `getAddress(chain?)`
291
546
 
292
- // Create ONE adapter that works across all EVM chains - incredibly simple!
293
- const adapter = createAdapterFromPrivateKey({
294
- privateKey: process.env.PRIVATE_KEY as `0x${string}`,
295
- defaultChain: 'Ethereum',
547
+ Gets the connected wallet address. Chain parameter is provided automatically by OperationContext resolution.
548
+
549
+ **Returns:** `Promise<string>` - Wallet address
550
+
551
+ #### `getChain()`
552
+
553
+ **Deprecated** - Use OperationContext pattern instead. Gets the current chain definition.
554
+
555
+ **Returns:** `Promise<ChainDefinition>`
556
+
557
+ ### Token Operations
558
+
559
+ Built-in token operations using the action system:
560
+
561
+ ```typescript
562
+ // Get USDC balance
563
+ const balance = await adapter.actions.usdc.balanceOf({
564
+ address: '0xwallet',
565
+ chain: 'Ethereum',
296
566
  })
297
567
 
298
- // Ready for cross-chain bridging between any supported chains!
299
- await kit.bridge({
300
- from: { adapter }, // Uses default chain (Ethereum)
301
- to: { adapter, chain: 'Base' }, // Same adapter, different chain
302
- amount: '50.0',
568
+ // Get token allowance
569
+ const allowance = await adapter.actions.token.allowance({
570
+ tokenAddress: '0xtoken',
571
+ owner: '0xowner',
572
+ spender: '0xspender',
573
+ chain: 'Base',
303
574
  })
304
575
  ```
305
576
 
306
- **For Production Use**: Remember to provide custom RPC endpoints using the `getProvider` parameter for better reliability and performance!
577
+ ## Supported Chains & Routes
578
+
579
+ The Ethers v6 adapter supports **34 EVM-compatible chains** across mainnet and testnet environments through Circle's CCTP v2 protocol:
580
+
581
+ ### Mainnet Chains (17 chains)
582
+
583
+ **Arbitrum**, **Avalanche**, **Base**, **Celo**, **Codex**, **Ethereum**, **HyperEVM**, **Ink**, **Linea**, **OP Mainnet**, **Plume**, **Polygon PoS**, **Sonic**, **Unichain**, **World Chain**, **XDC**, **ZKSync Era**
584
+
585
+ ### Testnet Chains (17 chains)
586
+
587
+ **Arbitrum Sepolia**, **Avalanche Fuji**, **Base Sepolia**, **Celo Alfajores**, **Codex Testnet**, **Ethereum Sepolia**, **HyperEVM Testnet**, **Ink Testnet**, **Linea Sepolia**, **OP Sepolia**, **Plume Testnet**, **Polygon PoS Amoy**, **Sonic Testnet**, **Unichain Sepolia**, **World Chain Sepolia**, **XDC Apothem**, **ZKSync Era Sepolia**
307
588
 
308
589
  ## Development
309
590
 
@@ -317,13 +598,9 @@ nx build @circle-fin/adapter-ethers-v6
317
598
  nx test @circle-fin/adapter-ethers-v6
318
599
  ```
319
600
 
320
- ## Contributing
321
-
322
- We welcome contributions! Please see our [Contributing Guide](https://github.com/circlefin/stablecoin-kits-private/blob/main/CONTRIBUTING.md) for details.
323
-
324
601
  ## License
325
602
 
326
- This project is licensed under the Apache 2.0 License - see the [LICENSE](https://github.com/circlefin/stablecoin-kits-private/blob/main/LICENSE) file for details.
603
+ This project is licensed under the Apache 2.0 License. Contact [support](https://help.circle.com/s/submit-ticket) for details.
327
604
 
328
605
  ---
329
606
 
@@ -331,7 +608,8 @@ This project is licensed under the Apache 2.0 License - see the [LICENSE](https:
331
608
 
332
609
  **Ready to integrate?**
333
610
 
334
- [View Stablecoin Kits](https://github.com/circlefin/stablecoin-kits-private) • [Join Discord](https://discord.com/invite/buildoncircle) • [Report Issues](https://github.com/circlefin/stablecoin-kits-private/issues)
611
+ [Join Discord](https://discord.com/invite/buildoncircle) •
612
+ [Visit our Help-Desk](https://help.circle.com/s/submit-ticket)
335
613
 
336
614
  _Built with ❤️ by Circle_
337
615