@circle-fin/bridge-kit 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,478 @@
1
+ # Bridge Kit
2
+
3
+ <div align="center">
4
+
5
+ [![npm version](https://badge.fury.io/js/@circle-fin%2Fbridge-kit.svg)](https://badge.fury.io/js/@circle-fin%2Fbridge-kit)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue.svg)](https://www.typescriptlang.org/)
7
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
8
+ [![Discord](https://img.shields.io/discord/473781666251538452?label=Discord&logo=discord)](https://discord.com/invite/buildoncircle)
9
+
10
+ **A strongly-typed SDK for seamless cross-chain stablecoin bridging**
11
+
12
+ _Making cross-chain stablecoin (USDC, and soon more tokens) transfers as simple as a single function call_
13
+
14
+ </div>
15
+
16
+ ## Table of Contents
17
+
18
+ - [Bridge Kit](#bridge-kit)
19
+ - [Table of Contents](#table-of-contents)
20
+ - [Overview](#overview)
21
+ - [Why Bridge Kit?](#why-bridge-kit)
22
+ - [Architecture Flow](#architecture-flow)
23
+ - [Installation](#installation)
24
+ - [Adapters](#adapters)
25
+ - [Quick Start](#quick-start)
26
+ - [πŸš€ Easiest Setup: Single Adapter, Multiple Chains](#-easiest-setup-single-adapter-multiple-chains)
27
+ - [🎯 Send to Different Address](#-send-to-different-address)
28
+ - [🏭 Production Setup: Custom RPC Providers](#-production-setup-custom-rpc-providers)
29
+ - [🌐 Browser/Wallet Provider Support](#-browserwallet-provider-support)
30
+ - [πŸ”§ Advanced Setup: Full Control](#-advanced-setup-full-control)
31
+ - [πŸ“Š Cost Estimation](#-cost-estimation)
32
+ - [Configuration](#configuration)
33
+ - [Bridge Configuration Types](#bridge-configuration-types)
34
+ - [1. **AdapterContext** - Your Transfer Endpoint](#1-adaptercontext---your-transfer-endpoint)
35
+ - [2. **BridgeDestination** - Where Funds Go](#2-bridgedestination---where-funds-go)
36
+ - [3. **BridgeConfig** - Transfer Settings](#3-bridgeconfig---transfer-settings)
37
+ - [Complete Example with All Options](#complete-example-with-all-options)
38
+ - [Bridge Speed Configuration](#bridge-speed-configuration)
39
+ - [Error Handling](#error-handling)
40
+ - [Examples](#examples)
41
+ - [Basic Bridge Operation](#basic-bridge-operation)
42
+ - [EVM to Non-EVM Bridge (EVM ↔ Solana)](#evm-to-non-evm-bridge-evm--solana)
43
+ - [Third-Party Recipient](#third-party-recipient)
44
+ - [Event Monitoring](#event-monitoring)
45
+ - [API Reference](#api-reference)
46
+ - [Core Methods](#core-methods)
47
+ - [Bridge Parameters](#bridge-parameters)
48
+ - [Development](#development)
49
+ - [Building](#building)
50
+ - [Testing](#testing)
51
+ - [Local Development](#local-development)
52
+ - [Contributing](#contributing)
53
+ - [Quick Contribution Steps](#quick-contribution-steps)
54
+ - [Community \& Support](#community--support)
55
+ - [License](#license)
56
+
57
+ ## Overview
58
+
59
+ The Stablecoin Kit ecosystem is Circle’s open-source effort to streamline stablecoin development with SDKs that are easy to use correctly and hard to misuse. Kits are cross-framework (viem, ethers, @solana/web3) and integrate cleanly into any stack. They’re opinionated with sensible defaults, but offer escape hatches for full control. A pluggable architecture makes implementation flexible, and all kits are interoperable, so they can be composed to suit a wide range of use cases.
60
+
61
+ The Bridge Kit enables cross-chain stablecoin transfers via a type-safe, developer-friendly interface with robust runtime validation. The Kit can have any bridging provider plugged in, by implementing your own BridgingProvider, but comes by default with full CCTPv2 support
62
+
63
+ ### Why Bridge Kit?
64
+
65
+ - **πŸŒ‰ Bridge-first design**: All abstractions revolve around _source_ ↔ _destination_ chain pairs
66
+ - **⚑ Zero-config defaults**: Built-in reliable RPC endpoints - start building right away
67
+ - **πŸ”§ Bring your own infrastructure**: Seamlessly integrate with your existing setup when needed
68
+ - **πŸ”’ Production-ready security**: Leverages Circle's CCTPv2 with deterministic quotes and finality tracking
69
+ - **πŸš€ Developer experience**: Complete TypeScript support, comprehensive validation, and instant connectivity
70
+ - **🌍 Cross-chain bridging**: The Bridge Kit supports **34 chains** with **544 total bridge routes** through Circle's CCTPv2
71
+ - **Mainnet (17 chains)**: Arbitrum, Avalanche, Base, Codex, Ethereum, HyperEVM, Ink, Linea, OP Mainnet, Plume, Polygon PoS, Sei, Solana, Sonic, Unichain, World Chain, XDC
72
+ - **Testnet (17 chains)**: Arbitrum Sepolia, Avalanche Fuji, Base Sepolia, Codex Testnet, Ethereum Sepolia, HyperEVM Testnet, Ink Testnet, Linea Sepolia, OP Sepolia, Plume Testnet, Polygon PoS Amoy, Sei Testnet, Solana Devnet, Sonic Testnet, Unichain Sepolia, World Chain Sepolia, XDC Apothem
73
+ - **🎯 Flexible adapters**: Supporting EVM (Viem, Ethers) and Solana (@solana/web3)
74
+ - **βš™οΈ Configurable bridge speeds**: FAST/SLOW options with fee optimization
75
+ - **πŸ“‘ Real-time event monitoring**: Track progress throughout the transfer lifecycle
76
+ - **πŸ›‘οΈ Robust error handling**: Graceful partial success recovery
77
+ - **✈️ Pre-flight validation**: Verify transfers with cost estimation before execution
78
+
79
+ ## Architecture Flow
80
+
81
+ The Bridge Kit follows a three-layer architecture designed for flexibility and type safety:
82
+
83
+ ```text
84
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
85
+ β”‚ Bridge Kit │────│ Provider │────│ Adapter β”‚
86
+ β”‚ (Orchestrator) β”‚ β”‚ (Protocol) β”‚ β”‚ (Blockchain) β”‚
87
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
88
+ ```
89
+
90
+ 1. **Adapter**: Handles blockchain-specific operations (wallets, transactions, gas) and enables you to use whatever framework you're comfortable with (viem, ethers, @solana/web3, and more coming soon)
91
+ 2. **Provider**: Implements bridging protocols (currently CCTPv2)
92
+ 3. **BridgeKit**: Orchestrates adapters and providers with auto-routing and validation
93
+
94
+ This separation ensures that each component has a single responsibility while maintaining seamless integration across the entire cross-chain bridging lifecycle.
95
+
96
+ ## Installation
97
+
98
+ ```bash
99
+ npm install @circle-fin/bridge-kit
100
+ # or
101
+ yarn add @circle-fin/bridge-kit
102
+ ```
103
+
104
+ ### Adapters
105
+
106
+ Choose the appropriate adapter for your target chains:
107
+
108
+ ```bash
109
+ # For EVM chains (Ethereum, Base, Arbitrum, etc.)
110
+ npm install @circle-fin/adapter-viem-v2 viem
111
+ # or
112
+ yarn add @circle-fin/adapter-viem-v2 viem
113
+
114
+ # For EVM chains using Ethers.js
115
+ npm install @circle-fin/adapter-ethers-v6
116
+ # or
117
+ yarn add @circle-fin/adapter-ethers-v6
118
+
119
+ # For Solana
120
+ npm install @circle-fin/adapter-solana @solana/web3.js @solana/spl-token
121
+ # or
122
+ yarn add @circle-fin/adapter-solana @solana/web3.js @solana/spl-token
123
+ ```
124
+
125
+ ## Quick Start
126
+
127
+ ### πŸš€ Easiest Setup: Single Adapter, Multiple Chains
128
+
129
+ **Best for**: Getting started quickly, simple transfers using one wallet across chains
130
+
131
+ The factory methods make it incredibly easy to get started with **built-in reliable RPC endpoints**. No need to research providers or configure endpoints - just start building! Create **one adapter** and use it across different chains!
132
+
133
+ ```typescript
134
+ import { BridgeKit } from '@circle-fin/bridge-kit'
135
+ import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
136
+
137
+ // Initialize the kit
138
+ const kit = new BridgeKit()
139
+
140
+ // Create ONE adapter that works across all chains!
141
+ const adapter = createAdapterFromPrivateKey({
142
+ privateKey: process.env.PRIVATE_KEY as string,
143
+ })
144
+
145
+ const result = await kit.bridge({
146
+ from: { adapter, chain: 'Ethereum' },
147
+ to: { adapter, chain: 'Base' },
148
+ amount: '10.50',
149
+ })
150
+ ```
151
+
152
+ **✨ Key Feature**: All supported chains include reliable default RPC endpoints.
153
+
154
+ ### 🎯 Send to Different Address
155
+
156
+ **Best for**: Sending funds to someone else's wallet, custodial services
157
+
158
+ Use `BridgeDestinationWithAddress` when the recipient is different from your adapter's address:
159
+
160
+ ```typescript
161
+ // Send to a different address on the destination chain
162
+ const result = await kit.bridge({
163
+ from: { adapter, chain: 'Ethereum' },
164
+ to: {
165
+ adapter,
166
+ chain: 'Base',
167
+ recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
168
+ },
169
+ amount: '10.50',
170
+ })
171
+
172
+ // Or use a different adapter for the destination chain
173
+ const baseAdapter = createAdapterFromPrivateKey({
174
+ privateKey: process.env.PRIVATE_KEY as string,
175
+ })
176
+
177
+ const resultWithDifferentAdapter = await kit.bridge({
178
+ from: { adapter, chain: 'Ethereum' },
179
+ to: {
180
+ adapter: baseAdapter,
181
+ chain: 'Base',
182
+ recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
183
+ },
184
+ amount: '10.50',
185
+ })
186
+ ```
187
+
188
+ ### 🏭 Production Setup: Custom RPC Providers
189
+
190
+ **Best for**: Production applications, better reliability, custom configuration
191
+
192
+ ```typescript
193
+ import { createPublicClient, http } from 'viem'
194
+
195
+ // Production-ready setup with custom RPC endpoints
196
+ const adapter = createAdapterFromPrivateKey({
197
+ privateKey: process.env.PRIVATE_KEY as string,
198
+ getPublicClient: ({ chain }) =>
199
+ createPublicClient({
200
+ chain,
201
+ transport: http(
202
+ `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
203
+ {
204
+ retryCount: 3,
205
+ timeout: 10000,
206
+ },
207
+ ),
208
+ }),
209
+ })
210
+
211
+ // Same simple usage, but with production-grade RPC
212
+ const result = await kit.bridge({
213
+ from: { adapter, chain: 'Ethereum' },
214
+ to: { adapter, chain: 'Base' },
215
+ amount: '10.50',
216
+ })
217
+ ```
218
+
219
+ ### 🌐 Browser/Wallet Provider Support
220
+
221
+ **Best for**: Browser applications, wallet integrations, user-controlled transactions
222
+
223
+ ```typescript
224
+ import { createAdapterFromProvider } from '@circle-fin/adapter-viem-v2'
225
+
226
+ // Create adapters from browser wallet providers
227
+ const adapter = await createAdapterFromProvider({
228
+ provider: window.ethereum,
229
+ })
230
+
231
+ // Execute bridge operation
232
+ const result = await kit.bridge({
233
+ from: { adapter, chain: 'Ethereum' },
234
+ to: { adapter, chain: 'Base' },
235
+ amount: '10.50',
236
+ })
237
+ ```
238
+
239
+ ### πŸ”§ Advanced Setup: Full Control
240
+
241
+ **Best for**: Advanced users, custom client configuration, specific RPC requirements
242
+
243
+ ```typescript
244
+ import { BridgeKit } from '@circle-fin/bridge-kit'
245
+ import { Ethereum, Base } from '@circle-fin/bridge-kit/chains'
246
+ import { ViemAdapter } from '@circle-fin/adapter-viem-v2'
247
+ import { createPublicClient, createWalletClient, http } from 'viem'
248
+ import { privateKeyToAccount } from 'viem/accounts'
249
+
250
+ const account = privateKeyToAccount(process.env.PRIVATE_KEY as string)
251
+
252
+ // Chain-specific RPC URLs
253
+ const rpcUrls = {
254
+ [Ethereum.id]: 'https://eth-mainnet.alchemyapi.io/v2/YOUR_KEY',
255
+ [Base.id]: 'https://base-mainnet.g.alchemy.com/v2/YOUR_KEY',
256
+ }
257
+
258
+ // Create one multi-chain adapter with chain-specific RPC configuration
259
+ const adapter = new ViemAdapter(
260
+ {
261
+ getPublicClient: ({ chain }) =>
262
+ createPublicClient({
263
+ chain,
264
+ transport: http(rpcUrls[chain.id]),
265
+ }),
266
+ getWalletClient: ({ chain }) =>
267
+ createWalletClient({
268
+ account,
269
+ chain,
270
+ transport: http(rpcUrls[chain.id]),
271
+ }),
272
+ },
273
+ {
274
+ addressContext: 'user-controlled',
275
+ supportedChains: [Ethereum, Base], // Support multiple chains!
276
+ },
277
+ )
278
+
279
+ const kit = new BridgeKit()
280
+ // Execute bridge operation using the same adapter for both chains
281
+ const result = await kit.bridge({
282
+ from: { adapter, chain: 'Ethereum' },
283
+ to: { adapter, chain: 'Base' },
284
+ amount: '10.50',
285
+ })
286
+ ```
287
+
288
+ ### πŸ“Š Cost Estimation
289
+
290
+ **Best for**: Showing users fees upfront, budget planning
291
+
292
+ ```typescript
293
+ // Get cost estimate before bridging
294
+ const estimate = await kit.estimate({
295
+ from: { adapter, chain: 'Ethereum' },
296
+ to: { adapter, chain: 'Base' },
297
+ amount: '10.50',
298
+ })
299
+
300
+ console.log('Estimated fees:', estimate.fees)
301
+ console.log('Estimated gas:', estimate.gasFees)
302
+ ```
303
+
304
+ ## Configuration
305
+
306
+ ### Bridge Configuration Types
307
+
308
+ The Bridge Kit supports different configuration patterns to match your use case:
309
+
310
+ #### 1. **AdapterContext** - Your Transfer Endpoint
311
+
312
+ ```typescript
313
+ // Create chain-agnostic adapter
314
+ const adapter = createAdapterFromPrivateKey({...})
315
+
316
+ // Always specify chain explicitly for clarity
317
+ const adapterContext = { adapter, chain: 'Ethereum' }
318
+ ```
319
+
320
+ #### 2. **BridgeDestination** - Where Funds Go
321
+
322
+ ```typescript
323
+ // Same as AdapterContext (adapter receives the funds)
324
+ const destination = { adapter, chain: 'Base' }
325
+
326
+ // Or with explicit recipient address
327
+ const destination = {
328
+ adapter,
329
+ chain: 'Base',
330
+ recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
331
+ }
332
+ ```
333
+
334
+ #### 3. **BridgeConfig** - Transfer Settings
335
+
336
+ ```typescript
337
+ // FAST: Optimized for speed with higher fees
338
+ // SLOW: Optimized for lower fees with longer processing time
339
+ const config = { transferSpeed: 'FAST' }
340
+ ```
341
+
342
+ ### Bridge Speed Configuration
343
+
344
+ ```typescript
345
+ // Fast transfer (higher fees, faster completion)
346
+ const result = await kit.bridge({
347
+ from: { adapter, chain: 'Ethereum' },
348
+ to: { adapter, chain: 'Base' },
349
+ amount: '100.0',
350
+ config: { transferSpeed: 'FAST' },
351
+ })
352
+
353
+ // Slow transfer (lower fees, slower completion)
354
+ const result = await kit.bridge({
355
+ from: { adapter, chain: 'Ethereum' },
356
+ to: { adapter, chain: 'Base' },
357
+ amount: '100.0',
358
+ config: { transferSpeed: 'SLOW' },
359
+ })
360
+ ```
361
+
362
+ ## Error Handling
363
+
364
+ The kit uses a thoughtful error handling approach:
365
+
366
+ - **Hard errors** (thrown): Validation, configuration, and authentication errors
367
+ - **Soft errors** (returned): Recoverable issues like insufficient balance or network errors
368
+
369
+ ```typescript
370
+ import { BridgeKit } from '@circle-fin/bridge-kit'
371
+ import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
372
+
373
+ const kit = new BridgeKit()
374
+ const adapter = createAdapterFromPrivateKey({
375
+ privateKey: process.env.PRIVATE_KEY as string,
376
+ })
377
+
378
+ const params = {
379
+ from: { adapter, chain: 'Ethereum' },
380
+ to: { adapter, chain: 'Base' },
381
+ amount: '100.0',
382
+ }
383
+
384
+ const result = await kit.bridge(params)
385
+
386
+ if (result.state === 'success') {
387
+ console.log('Bridge successful!')
388
+ } else {
389
+ // Handle partial completion with recovery information
390
+ console.log(
391
+ 'Successful steps:',
392
+ result.steps.filter((s) => s.state === 'success'),
393
+ )
394
+ }
395
+ ```
396
+
397
+ ## API Reference
398
+
399
+ ### Core Methods
400
+
401
+ - `kit.bridge(params)` - Execute cross-chain bridge operation
402
+ - `kit.estimate(params)` - Get cost estimates before bridging
403
+ - `kit.supportsRoute(source, destination, token)` - Check route support
404
+ - `kit.on(event, handler)` - Listen to bridge events
405
+ - `kit.off(event, handler)` - Removes the listener from bridge events
406
+
407
+ ### Bridge Parameters
408
+
409
+ ```typescript
410
+ interface BridgeParams {
411
+ from: AdapterContext // Source wallet and chain
412
+ to: BridgeDestination // Destination wallet/address and chain
413
+ amount: string // Amount to transfer (e.g., '10.50')
414
+ token?: 'USDC' // Optional, defaults to 'USDC'
415
+ config?: BridgeConfig // Optional bridge configuration (e.g., transfer speed). If omitted, defaults will be used
416
+ }
417
+
418
+ // AdapterContext: Your blockchain connection (always explicit)
419
+ type AdapterContext = { adapter: Adapter; chain: ChainIdentifier }
420
+
421
+ // BridgeDestination: Where funds go
422
+ type BridgeDestination =
423
+ | AdapterContext
424
+ | {
425
+ adapter: Adapter // Adapter for the destination chain
426
+ chain: ChainIdentifier // Chain identifier
427
+ recipientAddress: string // Custom recipient address
428
+ }
429
+ ```
430
+
431
+ ## Development
432
+
433
+ ### Building
434
+
435
+ ```bash
436
+ # From the root of the monorepo
437
+ nx build @circle-fin/bridge-kit
438
+ ```
439
+
440
+ ### Testing
441
+
442
+ ```bash
443
+ # From the root of the monorepo
444
+ nx test @circle-fin/bridge-kit
445
+ ```
446
+
447
+ ### Local Development
448
+
449
+ ```bash
450
+ # Install dependencies
451
+ yarn install
452
+
453
+ # Build the project
454
+ nx build @circle-fin/bridge-kit
455
+
456
+ # Run tests
457
+ nx test @circle-fin/bridge-kit
458
+ ```
459
+
460
+ ## Community & Support
461
+
462
+ - **πŸ’¬ Discord**: [Join our community](https://discord.com/invite/buildoncircle)
463
+
464
+ ## License
465
+
466
+ This project is licensed under the Apache 2.0 License. Contact [support](https://help.circle.com/s/submit-ticket) for details.
467
+
468
+ ---
469
+
470
+ <div align="center">
471
+
472
+ **Ready to start bridging?**
473
+
474
+ [Join Discord](https://discord.com/invite/buildoncircle)
475
+
476
+ _Built with ❀️ by Circle_
477
+
478
+ </div>