@circle-fin/provider-cctp-v2 1.3.0 → 1.4.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/CHANGELOG.md +34 -0
- package/README.md +93 -9
- package/index.cjs +4526 -2150
- package/index.d.ts +1590 -222
- package/index.mjs +4525 -2151
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -313,7 +313,7 @@ type ChainDefinitionWithCCTPv2 = ChainDefinition & {
|
|
|
313
313
|
* - A Blockchain enum value (e.g., Blockchain.Ethereum)
|
|
314
314
|
* - A string literal of the blockchain value (e.g., "Ethereum")
|
|
315
315
|
*/
|
|
316
|
-
type ChainIdentifier = ChainDefinition | Blockchain | `${Blockchain}`;
|
|
316
|
+
type ChainIdentifier$1 = ChainDefinition | Blockchain | `${Blockchain}`;
|
|
317
317
|
interface CCTPSplitConfig {
|
|
318
318
|
type: 'split';
|
|
319
319
|
tokenMessenger: string;
|
|
@@ -357,6 +357,22 @@ interface CCTPConfig {
|
|
|
357
357
|
* The contracts required for CCTP.
|
|
358
358
|
*/
|
|
359
359
|
contracts: CCTPContracts;
|
|
360
|
+
/**
|
|
361
|
+
* Indicates whether the chain supports forwarder for source and destination.
|
|
362
|
+
* @example
|
|
363
|
+
* ```typescript
|
|
364
|
+
* const chainWithForwarderSupported: ChainDefinition = {
|
|
365
|
+
* forwarderSupported: {
|
|
366
|
+
* source: true,
|
|
367
|
+
* destination: true,
|
|
368
|
+
* },
|
|
369
|
+
* }
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
forwarderSupported: {
|
|
373
|
+
source: boolean;
|
|
374
|
+
destination: boolean;
|
|
375
|
+
};
|
|
360
376
|
}
|
|
361
377
|
/**
|
|
362
378
|
* Available kit contract types for enhanced chain functionality.
|
|
@@ -913,7 +929,7 @@ type OperationContext<TAdapterCapabilities extends AdapterCapabilities = Adapter
|
|
|
913
929
|
/**
|
|
914
930
|
* The blockchain network to use for this operation.
|
|
915
931
|
*/
|
|
916
|
-
chain: ChainIdentifier;
|
|
932
|
+
chain: ChainIdentifier$1;
|
|
917
933
|
} & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
|
|
918
934
|
/**
|
|
919
935
|
* Fully resolved context for an adapter operation, with concrete chain and address.
|
|
@@ -1322,6 +1338,99 @@ interface CCTPv2ActionMap {
|
|
|
1322
1338
|
*/
|
|
1323
1339
|
permitParams?: PermitParams;
|
|
1324
1340
|
};
|
|
1341
|
+
/**
|
|
1342
|
+
* Initiate a cross-chain USDC transfer using a custom bridge contract with hook data for CCTP forwarding.
|
|
1343
|
+
*
|
|
1344
|
+
* This action combines the custom bridge functionality with CCTP forwarding hookData.
|
|
1345
|
+
* It uses either `bridgeWithPreapprovalAndHook` or `bridgeWithPermitAndHook` contract
|
|
1346
|
+
* functions depending on whether permit parameters are provided.
|
|
1347
|
+
*
|
|
1348
|
+
* @remarks
|
|
1349
|
+
* When CCTP forwarding is enabled with custom burn, Circle's relay infrastructure will:
|
|
1350
|
+
* 1. Watch for the burn transaction with forwarding hookData
|
|
1351
|
+
* 2. Fetch the attestation automatically
|
|
1352
|
+
* 3. Submit the destination mint transaction on behalf of the user
|
|
1353
|
+
* 4. Deduct the relay fee from the minted USDC
|
|
1354
|
+
*
|
|
1355
|
+
* The hookData must be formatted with the CCTP forwarding magic bytes prefix
|
|
1356
|
+
* followed by version and length fields. Use the `buildForwardingHookData`
|
|
1357
|
+
* utility to construct properly formatted hookData.
|
|
1358
|
+
*
|
|
1359
|
+
* @example
|
|
1360
|
+
* ```typescript
|
|
1361
|
+
* import { buildForwardingHookData } from '@core/utils'
|
|
1362
|
+
* import { hasCustomContractSupport } from '@core/chains'
|
|
1363
|
+
*
|
|
1364
|
+
* if (hasCustomContractSupport(sourceChain, 'bridge')) {
|
|
1365
|
+
* await adapter.action('cctp.v2.customBurnWithHook', {
|
|
1366
|
+
* amount: BigInt('1000000'),
|
|
1367
|
+
* mintRecipient: '0x...',
|
|
1368
|
+
* maxFee: BigInt('50000'),
|
|
1369
|
+
* minFinalityThreshold: 1000,
|
|
1370
|
+
* fromChain: ethereum,
|
|
1371
|
+
* toChain: base,
|
|
1372
|
+
* hookData: buildForwardingHookData()
|
|
1373
|
+
* })
|
|
1374
|
+
* }
|
|
1375
|
+
* ```
|
|
1376
|
+
*/
|
|
1377
|
+
customBurnWithHook: CCTPv2ActionMap['customBurn'] & {
|
|
1378
|
+
/**
|
|
1379
|
+
* Hex-encoded hook data for CCTP forwarding.
|
|
1380
|
+
*
|
|
1381
|
+
* The hookData signals to Circle's Orbit relayer that forwarding is requested.
|
|
1382
|
+
* Must be formatted with the CCTP forwarding magic bytes prefix ("cctp-forward"
|
|
1383
|
+
* right-padded to 24 bytes) followed by uint32 version and uint32 length fields.
|
|
1384
|
+
*
|
|
1385
|
+
* Use the `buildForwardingHookData` utility to construct properly formatted hookData.
|
|
1386
|
+
*/
|
|
1387
|
+
hookData: string;
|
|
1388
|
+
};
|
|
1389
|
+
/**
|
|
1390
|
+
* Initiate a cross-chain USDC transfer with hook data for CCTP forwarding.
|
|
1391
|
+
*
|
|
1392
|
+
* This action extends the standard `depositForBurn` with an additional `hookData`
|
|
1393
|
+
* parameter that signals to Circle's Orbit relayer that the user wants automated
|
|
1394
|
+
* attestation fetching and destination mint execution.
|
|
1395
|
+
*
|
|
1396
|
+
* @remarks
|
|
1397
|
+
* When CCTP forwarding is enabled, Circle's relay infrastructure will:
|
|
1398
|
+
* 1. Watch for the burn transaction with forwarding hookData
|
|
1399
|
+
* 2. Fetch the attestation automatically
|
|
1400
|
+
* 3. Submit the destination mint transaction on behalf of the user
|
|
1401
|
+
* 4. Deduct the relay fee from the minted USDC
|
|
1402
|
+
*
|
|
1403
|
+
* The hookData must be formatted with the CCTP forwarding magic bytes prefix
|
|
1404
|
+
* followed by version and length fields. Use the `buildForwardingHookData`
|
|
1405
|
+
* utility to construct properly formatted hookData.
|
|
1406
|
+
*
|
|
1407
|
+
* @example
|
|
1408
|
+
* ```typescript
|
|
1409
|
+
* import { buildForwardingHookData } from '@core/utils'
|
|
1410
|
+
*
|
|
1411
|
+
* await adapter.action('cctp.v2.depositForBurnWithHook', {
|
|
1412
|
+
* amount: BigInt('1000000'),
|
|
1413
|
+
* mintRecipient: '0x...',
|
|
1414
|
+
* maxFee: BigInt('50000'), // Must cover burn fee + forwarding fee
|
|
1415
|
+
* minFinalityThreshold: 1000,
|
|
1416
|
+
* fromChain: ethereum,
|
|
1417
|
+
* toChain: base,
|
|
1418
|
+
* hookData: buildForwardingHookData()
|
|
1419
|
+
* })
|
|
1420
|
+
* ```
|
|
1421
|
+
*/
|
|
1422
|
+
depositForBurnWithHook: CCTPv2ActionMap['depositForBurn'] & {
|
|
1423
|
+
/**
|
|
1424
|
+
* Hex-encoded hook data for CCTP forwarding.
|
|
1425
|
+
*
|
|
1426
|
+
* The hookData signals to Circle's Orbit relayer that forwarding is requested.
|
|
1427
|
+
* Must be formatted with the CCTP forwarding magic bytes prefix ("cctp-forward"
|
|
1428
|
+
* right-padded to 24 bytes) followed by uint32 version and uint32 length fields.
|
|
1429
|
+
*
|
|
1430
|
+
* Use the `buildForwardingHookData` utility to construct properly formatted hookData.
|
|
1431
|
+
*/
|
|
1432
|
+
hookData: string;
|
|
1433
|
+
};
|
|
1325
1434
|
}
|
|
1326
1435
|
|
|
1327
1436
|
/**
|
|
@@ -2441,238 +2550,1328 @@ declare class Actionable<AllActions> {
|
|
|
2441
2550
|
}
|
|
2442
2551
|
|
|
2443
2552
|
/**
|
|
2444
|
-
*
|
|
2553
|
+
* Module augmentation to register known token symbols.
|
|
2445
2554
|
*
|
|
2446
|
-
*
|
|
2447
|
-
*
|
|
2448
|
-
|
|
2449
|
-
declare enum TransferSpeed {
|
|
2450
|
-
/** Fast burn mode - reduces transfer time but may have different fee implications */
|
|
2451
|
-
FAST = "FAST",
|
|
2452
|
-
/** Standard burn mode - normal transfer time with standard fees */
|
|
2453
|
-
SLOW = "SLOW"
|
|
2454
|
-
}
|
|
2455
|
-
/**
|
|
2456
|
-
* Context object representing a wallet and signing authority on a specific blockchain network.
|
|
2555
|
+
* @remarks
|
|
2556
|
+
* This file augments the `TokenSymbolRegistry` interface to provide
|
|
2557
|
+
* type-safe autocomplete for built-in tokens.
|
|
2457
2558
|
*
|
|
2458
|
-
*
|
|
2459
|
-
*
|
|
2460
|
-
* transfer operations.
|
|
2559
|
+
* When imported, TypeScript will recognize 'USDC' as a valid
|
|
2560
|
+
* `TokenSymbol` value with autocomplete support.
|
|
2461
2561
|
*
|
|
2462
|
-
*
|
|
2463
|
-
*
|
|
2464
|
-
* in minting or withdrawal scenarios, the signing adapter may authorize a transaction that credits
|
|
2465
|
-
* funds to a different recipient address. This context is essential for cross-chain operations,
|
|
2466
|
-
* ensuring that both the address and the associated adapter are correctly paired with the intended
|
|
2467
|
-
* blockchain, but not necessarily with each other.
|
|
2562
|
+
* Other packages or applications can create their own augmentations
|
|
2563
|
+
* to add additional tokens.
|
|
2468
2564
|
*
|
|
2469
2565
|
* @example
|
|
2470
2566
|
* ```typescript
|
|
2471
|
-
* import
|
|
2472
|
-
* import { adapter, blockchain } from './setup'
|
|
2567
|
+
* import '@core/tokens' // Automatically includes this augmentation
|
|
2473
2568
|
*
|
|
2474
|
-
* const
|
|
2475
|
-
* adapter,
|
|
2476
|
-
* address: '0x1234...abcd',
|
|
2477
|
-
* chain: blockchain,
|
|
2478
|
-
* }
|
|
2569
|
+
* const symbol: TokenSymbol = 'USDC' // ✓ Autocomplete shows USDC
|
|
2479
2570
|
* ```
|
|
2480
2571
|
*/
|
|
2481
|
-
|
|
2482
|
-
/**
|
|
2483
|
-
* The chain definition type to use for the wallet context.
|
|
2484
|
-
*
|
|
2485
|
-
* @defaultValue ChainDefinition
|
|
2486
|
-
*/
|
|
2487
|
-
TChainDefinition extends ChainDefinition = ChainDefinition> {
|
|
2572
|
+
declare module './types' {
|
|
2488
2573
|
/**
|
|
2489
|
-
*
|
|
2490
|
-
*
|
|
2491
|
-
* Responsible for authorizing transactions and signing messages on behalf of the wallet or
|
|
2492
|
-
* for a different recipient, depending on the use case.
|
|
2493
|
-
*/
|
|
2494
|
-
adapter: Adapter<TAdapterCapabilities>;
|
|
2495
|
-
/**
|
|
2496
|
-
* The wallet or contract address.
|
|
2574
|
+
* Module augmentation: Adds known token symbols as valid keys
|
|
2575
|
+
* to the TokenSymbolRegistry interface.
|
|
2497
2576
|
*
|
|
2498
|
-
*
|
|
2499
|
-
* own address in scenarios such as relayed transactions or third-party minting.
|
|
2500
|
-
*/
|
|
2501
|
-
address: string;
|
|
2502
|
-
/**
|
|
2503
|
-
* The blockchain network where the wallet or contract address resides.
|
|
2504
|
-
*
|
|
2505
|
-
* Determines the context and format for the address and adapter.
|
|
2577
|
+
* Keys are explicitly listed to ensure IDE autocomplete works properly.
|
|
2506
2578
|
*/
|
|
2507
|
-
|
|
2579
|
+
interface TokenSymbolRegistry {
|
|
2580
|
+
USDC: true;
|
|
2581
|
+
}
|
|
2508
2582
|
}
|
|
2583
|
+
|
|
2509
2584
|
/**
|
|
2510
|
-
*
|
|
2585
|
+
* Module augmentation to register Blockchain enum values as ChainIdentifiers.
|
|
2511
2586
|
*
|
|
2512
|
-
*
|
|
2513
|
-
*
|
|
2514
|
-
*
|
|
2515
|
-
* recipient address specifies where the minted funds should be sent.
|
|
2587
|
+
* @remarks
|
|
2588
|
+
* This file augments the `ChainRegistry` interface to provide type-safe
|
|
2589
|
+
* autocomplete for all `Blockchain` enum values from `@core/chains`.
|
|
2516
2590
|
*
|
|
2517
|
-
*
|
|
2518
|
-
*
|
|
2591
|
+
* When this augmentation is imported (via `@core/tokens`), TypeScript will
|
|
2592
|
+
* recognize all blockchain identifiers as valid `ChainIdentifier` values
|
|
2593
|
+
* with IDE autocomplete support.
|
|
2594
|
+
*
|
|
2595
|
+
* The `Blockchain` enum values are converted to their string representations,
|
|
2596
|
+
* enabling both enum values and string literals to be accepted as chain identifiers.
|
|
2519
2597
|
*
|
|
2520
2598
|
* @example
|
|
2521
2599
|
* ```typescript
|
|
2522
|
-
* import
|
|
2523
|
-
* import {
|
|
2600
|
+
* import { Blockchain } from '@core/chains'
|
|
2601
|
+
* import type { ChainIdentifier } from '@core/tokens'
|
|
2524
2602
|
*
|
|
2525
|
-
* //
|
|
2526
|
-
* const
|
|
2527
|
-
* adapter,
|
|
2528
|
-
* address: '0x1234...abcd', // Signer address
|
|
2529
|
-
* chain: blockchain,
|
|
2530
|
-
* recipientAddress: '0x9876...fedc' // Custom recipient
|
|
2531
|
-
* }
|
|
2532
|
-
* ```
|
|
2533
|
-
*/
|
|
2534
|
-
interface DestinationWalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
|
|
2535
|
-
/**
|
|
2536
|
-
* The chain definition type to use for the wallet context.
|
|
2603
|
+
* // Using enum value
|
|
2604
|
+
* const chain1: ChainIdentifier = Blockchain.Ethereum
|
|
2537
2605
|
*
|
|
2538
|
-
*
|
|
2606
|
+
* // Using string literal (with autocomplete!)
|
|
2607
|
+
* const chain2: ChainIdentifier = 'Base'
|
|
2608
|
+
*
|
|
2609
|
+
* // Arbitrary strings also work (escape hatch for custom chains)
|
|
2610
|
+
* const chain3: ChainIdentifier = 'my-custom-chain'
|
|
2611
|
+
* ```
|
|
2539
2612
|
*/
|
|
2540
|
-
|
|
2613
|
+
|
|
2614
|
+
declare module './types' {
|
|
2541
2615
|
/**
|
|
2542
|
-
*
|
|
2616
|
+
* Module augmentation: Adds all Blockchain enum values as valid keys
|
|
2617
|
+
* to the ChainRegistry interface for type-safe chain identifier support.
|
|
2543
2618
|
*
|
|
2544
|
-
*
|
|
2545
|
-
*
|
|
2546
|
-
*
|
|
2619
|
+
* This ensures both enum property access (e.g., Blockchain.Ethereum) and plain
|
|
2620
|
+
* string literals (e.g., 'Ethereum') are accepted by TypeScript as chain keys,
|
|
2621
|
+
* providing robust autocomplete and error checking.
|
|
2547
2622
|
*
|
|
2548
|
-
*
|
|
2623
|
+
* NOTE:
|
|
2624
|
+
* - This interface intentionally has no body. It merges a mapped Record type
|
|
2625
|
+
* into ChainRegistry solely for type augmentation.
|
|
2626
|
+
* - This empty-body construct is a necessary TypeScript idiom for module
|
|
2627
|
+
* augmentation with Record types—directly listing mapped keys is not
|
|
2628
|
+
* feasible in interface extensions.
|
|
2629
|
+
*
|
|
2630
|
+
* eslint-disable-next-line directives below suppress linter complaints about
|
|
2631
|
+
* the empty interface/mapping, which are benign and required for this pattern.
|
|
2549
2632
|
*/
|
|
2550
|
-
|
|
2633
|
+
interface ChainRegistry extends Record<`${Blockchain}`, true> {
|
|
2634
|
+
}
|
|
2551
2635
|
}
|
|
2636
|
+
|
|
2552
2637
|
/**
|
|
2553
|
-
*
|
|
2638
|
+
* Creates a union type that preserves IDE autocomplete for known literals
|
|
2639
|
+
* while still accepting any string at runtime.
|
|
2640
|
+
*
|
|
2641
|
+
* @remarks
|
|
2642
|
+
* This pattern uses `Record<never, never>` (an empty record type) to prevent
|
|
2643
|
+
* TypeScript from widening string literals to just `string`. This gives us
|
|
2644
|
+
* the best of both worlds: autocomplete for known values and flexibility
|
|
2645
|
+
* for arbitrary strings.
|
|
2646
|
+
*
|
|
2647
|
+
* @typeParam T - The known string literal union to preserve.
|
|
2554
2648
|
*/
|
|
2555
|
-
|
|
2649
|
+
type LiteralUnion<T extends string> = T | (string & Record<never, never>);
|
|
2556
2650
|
/**
|
|
2557
|
-
*
|
|
2651
|
+
* Registry for known chain identifiers (augmentation target).
|
|
2558
2652
|
*
|
|
2559
|
-
* @
|
|
2653
|
+
* @remarks
|
|
2654
|
+
* This empty interface exists solely for module augmentation. Extend it to
|
|
2655
|
+
* register chain identifiers for type-safe token definitions.
|
|
2656
|
+
*
|
|
2657
|
+
* **Why an interface?** TypeScript only allows module augmentation on
|
|
2658
|
+
* interfaces, not type aliases.
|
|
2659
|
+
*
|
|
2660
|
+
* **Note:** This is NOT the EVM "chain ID" (numeric like 1 for Ethereum).
|
|
2661
|
+
* It's a human-readable identifier like "Ethereum", "Solana", "Base".
|
|
2662
|
+
*
|
|
2663
|
+
* **Usage**
|
|
2664
|
+
*
|
|
2665
|
+
* Without augmentation, `ChainIdentifier` defaults to `string`.
|
|
2666
|
+
* With `@core/chains` imported, you get autocomplete for all `Blockchain` values.
|
|
2667
|
+
*
|
|
2668
|
+
* **Custom Chains**
|
|
2669
|
+
*
|
|
2670
|
+
* ```typescript
|
|
2671
|
+
* declare module '@core/tokens' {
|
|
2672
|
+
* interface ChainRegistry {
|
|
2673
|
+
* MyChain: true
|
|
2674
|
+
* MyTestnet: true
|
|
2675
|
+
* }
|
|
2676
|
+
* }
|
|
2677
|
+
* // Now ChainIdentifier includes 'MyChain' | 'MyTestnet' | ...
|
|
2678
|
+
* ```
|
|
2679
|
+
*
|
|
2680
|
+
* The value (`true`) is a placeholder—only the keys matter.
|
|
2681
|
+
*
|
|
2682
|
+
* NOTE: The eslint-disable below suppresses warnings about empty interfaces.
|
|
2683
|
+
* This is intentional—the interface exists solely as an augmentation target.
|
|
2560
2684
|
*/
|
|
2561
|
-
|
|
2562
|
-
/** The source adapter containing wallet and chain information */
|
|
2563
|
-
source: WalletContext<TFromCapabilities, TChainDefinition>;
|
|
2564
|
-
/** The destination adapter containing wallet and chain information */
|
|
2565
|
-
destination: DestinationWalletContext<TToCapabilities, TChainDefinition>;
|
|
2566
|
-
/** The amount to transfer (as a string to avoid precision issues) */
|
|
2567
|
-
amount: string;
|
|
2568
|
-
/** The token to transfer (currently only USDC is supported) */
|
|
2569
|
-
token: 'USDC';
|
|
2570
|
-
/** Bridge configuration (e.g., fast burn settings) */
|
|
2571
|
-
config: BridgeConfig;
|
|
2685
|
+
interface ChainRegistry {
|
|
2572
2686
|
}
|
|
2573
2687
|
/**
|
|
2574
|
-
*
|
|
2688
|
+
* Union of all registered chain identifiers.
|
|
2575
2689
|
*
|
|
2576
2690
|
* @remarks
|
|
2577
|
-
*
|
|
2578
|
-
*
|
|
2691
|
+
* Derived from `ChainRegistry` keys:
|
|
2692
|
+
* - Without augmentation: `string`
|
|
2693
|
+
* - With `@core/chains`: `'Ethereum' | 'Solana' | ...` plus any string
|
|
2694
|
+
*
|
|
2695
|
+
* Uses `LiteralUnion` to preserve IDE autocomplete while allowing
|
|
2696
|
+
* arbitrary strings at runtime.
|
|
2579
2697
|
*
|
|
2580
2698
|
* @example
|
|
2581
2699
|
* ```typescript
|
|
2582
|
-
* const
|
|
2583
|
-
*
|
|
2584
|
-
* state: 'success',
|
|
2585
|
-
* txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
2586
|
-
* explorerUrl: 'https://etherscan.io/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
2587
|
-
* }
|
|
2700
|
+
* const chain: ChainIdentifier = 'Ethereum' // Autocomplete works
|
|
2701
|
+
* const custom: ChainIdentifier = 'my-chain' // Also valid
|
|
2588
2702
|
* ```
|
|
2589
2703
|
*/
|
|
2590
|
-
|
|
2591
|
-
/** Human-readable name of the step (e.g., "Approve", "Burn", "Mint") */
|
|
2592
|
-
name: string;
|
|
2593
|
-
/** The state of the step */
|
|
2594
|
-
state: 'pending' | 'success' | 'error' | 'noop';
|
|
2595
|
-
/** Optional transaction hash for this step (if applicable) */
|
|
2596
|
-
txHash?: string;
|
|
2597
|
-
/** Optional explorer URL for viewing this transaction on a block explorer */
|
|
2598
|
-
explorerUrl?: string;
|
|
2599
|
-
/** Optional data for the step */
|
|
2600
|
-
data?: unknown;
|
|
2601
|
-
/** Optional human-readable error message */
|
|
2602
|
-
errorMessage?: string;
|
|
2603
|
-
/** Optional raw error object (can be Viem/Ethers/Chain error) */
|
|
2604
|
-
error?: unknown;
|
|
2605
|
-
}
|
|
2704
|
+
type ChainIdentifier = keyof ChainRegistry extends never ? string : LiteralUnion<Extract<keyof ChainRegistry, string>>;
|
|
2606
2705
|
/**
|
|
2607
|
-
*
|
|
2706
|
+
* Maps chain identifiers to their token locators.
|
|
2608
2707
|
*
|
|
2609
|
-
*
|
|
2610
|
-
*
|
|
2611
|
-
*
|
|
2708
|
+
* @remarks
|
|
2709
|
+
* The key is a chain identifier (type-safe when `KnownChainIdentifiers` is
|
|
2710
|
+
* augmented). This enables a single token definition to work across chains.
|
|
2711
|
+
*
|
|
2712
|
+
* When `@core/chains` is imported, you get autocomplete for known chains
|
|
2713
|
+
* like `Ethereum`, `Base`, `Solana`, etc.
|
|
2612
2714
|
*
|
|
2613
2715
|
* @example
|
|
2614
2716
|
* ```typescript
|
|
2615
|
-
*
|
|
2616
|
-
*
|
|
2617
|
-
*
|
|
2717
|
+
* import { Blockchain } from '@core/chains'
|
|
2718
|
+
*
|
|
2719
|
+
* const usdcLocators: ChainLocatorMap = {
|
|
2720
|
+
* [Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
2721
|
+
* [Blockchain.Solana]: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
2722
|
+
* [Blockchain.Base]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
2723
|
+
* }
|
|
2724
|
+
*
|
|
2725
|
+
* // Or with string keys (always works)
|
|
2726
|
+
* const locators: ChainLocatorMap = {
|
|
2727
|
+
* 'ethereum': '0xa0b86991...',
|
|
2728
|
+
* 'my-custom-chain': '0x1234...',
|
|
2729
|
+
* }
|
|
2618
2730
|
* ```
|
|
2619
2731
|
*/
|
|
2620
|
-
|
|
2621
|
-
/** The amount that was transferred (as a string to avoid precision issues) */
|
|
2622
|
-
amount: string;
|
|
2623
|
-
/** The token that was transferred (currently only USDC is supported) */
|
|
2624
|
-
token: 'USDC';
|
|
2625
|
-
/** The state of the transfer */
|
|
2626
|
-
state: 'pending' | 'success' | 'error';
|
|
2627
|
-
/** The bridge configuration that was used for this operation */
|
|
2628
|
-
config?: BridgeConfig;
|
|
2629
|
-
/** The provider that was used for this operation */
|
|
2630
|
-
provider: string;
|
|
2631
|
-
/** Information about the source chain and address */
|
|
2632
|
-
source: {
|
|
2633
|
-
/** The source wallet/contract address */
|
|
2634
|
-
address: string;
|
|
2635
|
-
/** The source blockchain network */
|
|
2636
|
-
chain: ChainDefinition;
|
|
2637
|
-
};
|
|
2638
|
-
/** Information about the destination chain and address */
|
|
2639
|
-
destination: {
|
|
2640
|
-
/** The destination wallet/contract address */
|
|
2641
|
-
address: string;
|
|
2642
|
-
/** The destination blockchain network */
|
|
2643
|
-
chain: ChainDefinition;
|
|
2644
|
-
/**
|
|
2645
|
-
* Optional custom recipient address for minted funds.
|
|
2646
|
-
*
|
|
2647
|
-
* When provided during the bridge operation, minted tokens are sent to this
|
|
2648
|
-
* address instead of the destination address. This field is preserved in the
|
|
2649
|
-
* result for retry operations to maintain consistency with the original burn.
|
|
2650
|
-
*/
|
|
2651
|
-
recipientAddress?: string;
|
|
2652
|
-
};
|
|
2653
|
-
/** Array of steps that were executed during the bridge process */
|
|
2654
|
-
steps: BridgeStep[];
|
|
2655
|
-
}
|
|
2732
|
+
type ChainLocatorMap = Record<ChainIdentifier, string>;
|
|
2656
2733
|
/**
|
|
2657
|
-
*
|
|
2734
|
+
* Complete definition of a token including metadata and chain locators.
|
|
2658
2735
|
*
|
|
2659
|
-
*
|
|
2660
|
-
*
|
|
2661
|
-
* It
|
|
2662
|
-
* provide a complete view of the transfer being estimated.
|
|
2736
|
+
* @remarks
|
|
2737
|
+
* This is the canonical representation of a token in the registry.
|
|
2738
|
+
* It includes the symbol, decimals, and chain-specific locators.
|
|
2663
2739
|
*
|
|
2664
2740
|
* @example
|
|
2665
2741
|
* ```typescript
|
|
2666
|
-
* const
|
|
2667
|
-
*
|
|
2668
|
-
*
|
|
2669
|
-
*
|
|
2670
|
-
*
|
|
2742
|
+
* const usdc: TokenDefinition = {
|
|
2743
|
+
* symbol: 'USDC',
|
|
2744
|
+
* decimals: 6,
|
|
2745
|
+
* locators: {
|
|
2746
|
+
* [Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
2747
|
+
* [Blockchain.Solana]: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
2748
|
+
* },
|
|
2749
|
+
* }
|
|
2671
2750
|
* ```
|
|
2672
2751
|
*/
|
|
2673
|
-
interface
|
|
2674
|
-
/**
|
|
2675
|
-
|
|
2752
|
+
interface TokenDefinition {
|
|
2753
|
+
/**
|
|
2754
|
+
* The token symbol (e.g., "USDC", "EURC").
|
|
2755
|
+
*/
|
|
2756
|
+
readonly symbol: string;
|
|
2757
|
+
/**
|
|
2758
|
+
* The number of decimal places for the token.
|
|
2759
|
+
* @example 6 for USDC, 18 for most ERC20 tokens
|
|
2760
|
+
*/
|
|
2761
|
+
readonly decimals: number;
|
|
2762
|
+
/**
|
|
2763
|
+
* Chain-specific locators for the token.
|
|
2764
|
+
* Keys are chain identifiers, values are the token address/locator on that chain.
|
|
2765
|
+
* Not all chains need to be present - tokens may only exist on a subset of chains.
|
|
2766
|
+
*/
|
|
2767
|
+
readonly locators: Partial<ChainLocatorMap>;
|
|
2768
|
+
}
|
|
2769
|
+
/**
|
|
2770
|
+
* A raw token locator selector with explicit decimals.
|
|
2771
|
+
*
|
|
2772
|
+
* @remarks
|
|
2773
|
+
* Use this form when working with arbitrary tokens not in the registry.
|
|
2774
|
+
* The `locator` is the chain-specific address, and `decimals` is required
|
|
2775
|
+
* unless using lenient mode.
|
|
2776
|
+
*
|
|
2777
|
+
* @example
|
|
2778
|
+
* ```typescript
|
|
2779
|
+
* // Selecting a custom token by address
|
|
2780
|
+
* const selector: RawTokenSelector = {
|
|
2781
|
+
* locator: '0x1234567890abcdef1234567890abcdef12345678',
|
|
2782
|
+
* decimals: 18,
|
|
2783
|
+
* }
|
|
2784
|
+
* ```
|
|
2785
|
+
*/
|
|
2786
|
+
interface RawTokenSelector {
|
|
2787
|
+
/**
|
|
2788
|
+
* The chain-specific token locator (address, program ID, etc.).
|
|
2789
|
+
*/
|
|
2790
|
+
readonly locator: string;
|
|
2791
|
+
/**
|
|
2792
|
+
* The number of decimal places.
|
|
2793
|
+
* Required in strict mode, optional in lenient mode.
|
|
2794
|
+
*/
|
|
2795
|
+
readonly decimals?: number;
|
|
2796
|
+
}
|
|
2797
|
+
/**
|
|
2798
|
+
* Registry for known token symbols (augmentation target).
|
|
2799
|
+
*
|
|
2800
|
+
* @remarks
|
|
2801
|
+
* This empty interface exists solely for module augmentation. Extend it to
|
|
2802
|
+
* register token symbols for type-safe selection.
|
|
2803
|
+
*
|
|
2804
|
+
* **Why an interface?** TypeScript only allows module augmentation on
|
|
2805
|
+
* interfaces, not type aliases.
|
|
2806
|
+
*
|
|
2807
|
+
* **Usage**
|
|
2808
|
+
*
|
|
2809
|
+
* Without augmentation, `TokenSymbol` defaults to `string`.
|
|
2810
|
+
*
|
|
2811
|
+
* ```typescript
|
|
2812
|
+
* declare module '@core/tokens' {
|
|
2813
|
+
* interface TokenSymbolRegistry {
|
|
2814
|
+
* USDC: true
|
|
2815
|
+
* EURC: true
|
|
2816
|
+
* }
|
|
2817
|
+
* }
|
|
2818
|
+
* // Now TokenSymbol includes 'USDC' | 'EURC' | ...
|
|
2819
|
+
* ```
|
|
2820
|
+
*
|
|
2821
|
+
* NOTE: The eslint-disable below suppresses warnings about empty interfaces.
|
|
2822
|
+
* This is intentional—the interface exists solely as an augmentation target.
|
|
2823
|
+
*/
|
|
2824
|
+
interface TokenSymbolRegistry {
|
|
2825
|
+
}
|
|
2826
|
+
/**
|
|
2827
|
+
* Union type of all registered token symbols.
|
|
2828
|
+
*
|
|
2829
|
+
* @remarks
|
|
2830
|
+
* This type is derived from the keys of `TokenSymbolRegistry`:
|
|
2831
|
+
* - **Without augmentation** — Simply `string` (any value)
|
|
2832
|
+
* - **With augmentation** — `'USDC' | 'USDT' | ...` plus any string
|
|
2833
|
+
*
|
|
2834
|
+
* Uses `LiteralUnion` to preserve autocomplete for known values while
|
|
2835
|
+
* still accepting any string at runtime.
|
|
2836
|
+
*
|
|
2837
|
+
* @example
|
|
2838
|
+
* ```typescript
|
|
2839
|
+
* // With symbols.augment imported - autocomplete works
|
|
2840
|
+
* const symbol: TokenSymbol = 'USDC'
|
|
2841
|
+
*
|
|
2842
|
+
* // Custom strings still accepted
|
|
2843
|
+
* const symbol: TokenSymbol = 'MY_TOKEN'
|
|
2844
|
+
* ```
|
|
2845
|
+
*/
|
|
2846
|
+
type TokenSymbol = keyof TokenSymbolRegistry extends never ? string : LiteralUnion<Extract<keyof TokenSymbolRegistry, string>>;
|
|
2847
|
+
/**
|
|
2848
|
+
* Selector for identifying a token.
|
|
2849
|
+
*
|
|
2850
|
+
* @remarks
|
|
2851
|
+
* Can be one of:
|
|
2852
|
+
* - A symbol string (e.g., "USDC") - resolves from registry
|
|
2853
|
+
* - A raw locator object with explicit decimals - for arbitrary tokens
|
|
2854
|
+
*
|
|
2855
|
+
* Using a symbol is preferred when the token is in the registry, as it
|
|
2856
|
+
* automatically resolves decimals and the correct chain address.
|
|
2857
|
+
*
|
|
2858
|
+
* @example
|
|
2859
|
+
* ```typescript
|
|
2860
|
+
* // By symbol (preferred for known tokens)
|
|
2861
|
+
* const selector1: TokenSelector = 'USDC'
|
|
2862
|
+
*
|
|
2863
|
+
* // By raw locator (for arbitrary tokens)
|
|
2864
|
+
* const selector2: TokenSelector = {
|
|
2865
|
+
* locator: '0x1234...',
|
|
2866
|
+
* decimals: 18,
|
|
2867
|
+
* }
|
|
2868
|
+
* ```
|
|
2869
|
+
*/
|
|
2870
|
+
type TokenSelector = TokenSymbol | RawTokenSelector;
|
|
2871
|
+
/**
|
|
2872
|
+
* The resolved token information after registry lookup.
|
|
2873
|
+
*
|
|
2874
|
+
* @remarks
|
|
2875
|
+
* This is the result of resolving a `TokenSelector` against a chain.
|
|
2876
|
+
* It always contains the locator and decimals, and optionally the symbol
|
|
2877
|
+
* if the token was resolved from the registry.
|
|
2878
|
+
*/
|
|
2879
|
+
interface ResolvedToken {
|
|
2880
|
+
/**
|
|
2881
|
+
* The token symbol, if known.
|
|
2882
|
+
* Present when resolved from registry, absent for raw locators.
|
|
2883
|
+
*/
|
|
2884
|
+
readonly symbol?: string;
|
|
2885
|
+
/**
|
|
2886
|
+
* The number of decimal places for the token.
|
|
2887
|
+
*/
|
|
2888
|
+
readonly decimals: number;
|
|
2889
|
+
/**
|
|
2890
|
+
* The chain-specific token locator (address, program ID, etc.).
|
|
2891
|
+
*/
|
|
2892
|
+
readonly locator: string;
|
|
2893
|
+
}
|
|
2894
|
+
/**
|
|
2895
|
+
* Interface for the token registry.
|
|
2896
|
+
*
|
|
2897
|
+
* @remarks
|
|
2898
|
+
* The registry is the sole source of truth for token information.
|
|
2899
|
+
* It supports both symbol-based and raw locator-based token selection.
|
|
2900
|
+
*
|
|
2901
|
+
* @example
|
|
2902
|
+
* ```typescript
|
|
2903
|
+
* import { createTokenRegistry } from '@core/tokens'
|
|
2904
|
+
*
|
|
2905
|
+
* // Create registry (includes built-in tokens like USDC)
|
|
2906
|
+
* const registry = createTokenRegistry()
|
|
2907
|
+
*
|
|
2908
|
+
* // Resolve by symbol
|
|
2909
|
+
* const usdc = registry.resolve('USDC', 'Ethereum')
|
|
2910
|
+
* console.log(usdc.locator) // '0xa0b86991...'
|
|
2911
|
+
*
|
|
2912
|
+
* // Resolve raw locator
|
|
2913
|
+
* const custom = registry.resolve({ locator: '0x...', decimals: 18 }, 'Ethereum')
|
|
2914
|
+
* ```
|
|
2915
|
+
*/
|
|
2916
|
+
interface TokenRegistry {
|
|
2917
|
+
/**
|
|
2918
|
+
* Resolve a token selector to concrete token information for a chain.
|
|
2919
|
+
*
|
|
2920
|
+
* @param selector - The token to resolve (symbol or raw locator).
|
|
2921
|
+
* @param chainId - The chain identifier to resolve for.
|
|
2922
|
+
* @returns The resolved token information.
|
|
2923
|
+
* @throws When the token cannot be resolved (unknown symbol, missing decimals, etc.).
|
|
2924
|
+
*/
|
|
2925
|
+
resolve(selector: TokenSelector, chainId: ChainIdentifier): ResolvedToken;
|
|
2926
|
+
/**
|
|
2927
|
+
* Get a token definition by symbol.
|
|
2928
|
+
*
|
|
2929
|
+
* @param symbol - The token symbol (e.g., "USDC").
|
|
2930
|
+
* @returns The token definition, or undefined if not found.
|
|
2931
|
+
*/
|
|
2932
|
+
get(symbol: string): TokenDefinition | undefined;
|
|
2933
|
+
/**
|
|
2934
|
+
* Check if a symbol is registered.
|
|
2935
|
+
*
|
|
2936
|
+
* @param symbol - The token symbol to check.
|
|
2937
|
+
* @returns True if the symbol is in the registry.
|
|
2938
|
+
*/
|
|
2939
|
+
has(symbol: string): boolean;
|
|
2940
|
+
/**
|
|
2941
|
+
* Get all registered token symbols.
|
|
2942
|
+
*
|
|
2943
|
+
* @returns An array of registered symbol strings.
|
|
2944
|
+
*/
|
|
2945
|
+
symbols(): string[];
|
|
2946
|
+
/**
|
|
2947
|
+
* Get all registered token definitions.
|
|
2948
|
+
*
|
|
2949
|
+
* @returns An array of all TokenDefinition objects in the registry.
|
|
2950
|
+
*/
|
|
2951
|
+
entries(): TokenDefinition[];
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
/**
|
|
2955
|
+
* Structured fields that can be attached to log entries.
|
|
2956
|
+
*/
|
|
2957
|
+
type LogFields = Record<string, unknown>;
|
|
2958
|
+
/**
|
|
2959
|
+
* Logger interface providing structured logging with child scoping.
|
|
2960
|
+
*
|
|
2961
|
+
* @remarks
|
|
2962
|
+
* This interface defines a minimal, framework-agnostic logging contract.
|
|
2963
|
+
* The underlying implementation uses pino for transport handling (console,
|
|
2964
|
+
* file, remote, JSON, pretty, etc.) but consumers only interact with this
|
|
2965
|
+
* stable interface.
|
|
2966
|
+
*
|
|
2967
|
+
* @example
|
|
2968
|
+
* ```typescript
|
|
2969
|
+
* import { createLogger } from '@core/runtime'
|
|
2970
|
+
*
|
|
2971
|
+
* const logger = createLogger({ level: 'debug' })
|
|
2972
|
+
*
|
|
2973
|
+
* // Simple message
|
|
2974
|
+
* logger.info('Server started')
|
|
2975
|
+
*
|
|
2976
|
+
* // Message with structured fields
|
|
2977
|
+
* logger.info('Request received', { method: 'POST', path: '/api/transfer' })
|
|
2978
|
+
*
|
|
2979
|
+
* // Create child logger with context
|
|
2980
|
+
* const requestLogger = logger.child({ requestId: 'abc-123' })
|
|
2981
|
+
* requestLogger.debug('Processing transfer')
|
|
2982
|
+
* // Output includes: requestId in all subsequent logs
|
|
2983
|
+
* ```
|
|
2984
|
+
*/
|
|
2985
|
+
interface Logger {
|
|
2986
|
+
/**
|
|
2987
|
+
* Log a debug-level message.
|
|
2988
|
+
* @param message - The log message.
|
|
2989
|
+
* @param fields - Optional structured fields.
|
|
2990
|
+
* @returns void
|
|
2991
|
+
*/
|
|
2992
|
+
debug(message: string, fields?: LogFields): void;
|
|
2993
|
+
/**
|
|
2994
|
+
* Log an info-level message.
|
|
2995
|
+
* @param message - The log message.
|
|
2996
|
+
* @param fields - Optional structured fields.
|
|
2997
|
+
* @returns void
|
|
2998
|
+
*/
|
|
2999
|
+
info(message: string, fields?: LogFields): void;
|
|
3000
|
+
/**
|
|
3001
|
+
* Log a warning-level message.
|
|
3002
|
+
* @param message - The log message.
|
|
3003
|
+
* @param fields - Optional structured fields.
|
|
3004
|
+
* @returns void
|
|
3005
|
+
*/
|
|
3006
|
+
warn(message: string, fields?: LogFields): void;
|
|
3007
|
+
/**
|
|
3008
|
+
* Log an error-level message.
|
|
3009
|
+
* @param message - The log message.
|
|
3010
|
+
* @param fields - Optional structured fields.
|
|
3011
|
+
* @returns void
|
|
3012
|
+
*/
|
|
3013
|
+
error(message: string, fields?: LogFields): void;
|
|
3014
|
+
/**
|
|
3015
|
+
* Create a child logger with additional contextual bindings.
|
|
3016
|
+
*
|
|
3017
|
+
* @param tags - Key-value pairs to add to the child logger's context.
|
|
3018
|
+
* Undefined values are filtered out automatically.
|
|
3019
|
+
* @returns A new Logger instance with merged bindings.
|
|
3020
|
+
*
|
|
3021
|
+
* @example
|
|
3022
|
+
* ```typescript
|
|
3023
|
+
* const requestLogger = logger.child({ requestId: 'req-123' })
|
|
3024
|
+
* const userLogger = requestLogger.child({ userId: 'user-456' })
|
|
3025
|
+
* // All logs from userLogger include both requestId and userId
|
|
3026
|
+
* ```
|
|
3027
|
+
*/
|
|
3028
|
+
child(tags: LogFields): Logger;
|
|
3029
|
+
}
|
|
3030
|
+
|
|
3031
|
+
/**
|
|
3032
|
+
* Handler function for event subscriptions.
|
|
3033
|
+
*/
|
|
3034
|
+
type EventHandler = (event: Event) => void | Promise<void>;
|
|
3035
|
+
/**
|
|
3036
|
+
* Event bus for publishing and subscribing to events.
|
|
3037
|
+
*
|
|
3038
|
+
* @remarks
|
|
3039
|
+
* Supports wildcard topic subscriptions:
|
|
3040
|
+
* - `*` matches exactly one segment
|
|
3041
|
+
* - `**` matches zero or more segments
|
|
3042
|
+
*
|
|
3043
|
+
* @example
|
|
3044
|
+
* ```typescript
|
|
3045
|
+
* const bus = createEventBus()
|
|
3046
|
+
*
|
|
3047
|
+
* // Subscribe to all events
|
|
3048
|
+
* bus.on((event) => console.log(event))
|
|
3049
|
+
*
|
|
3050
|
+
* // Subscribe to specific topic
|
|
3051
|
+
* bus.on('tx.wait.started', (event) => console.log(event))
|
|
3052
|
+
*
|
|
3053
|
+
* // Subscribe with wildcard
|
|
3054
|
+
* bus.on('tx.wait.*', (event) => console.log(event))
|
|
3055
|
+
* bus.on('tx.**', (event) => console.log(event))
|
|
3056
|
+
*
|
|
3057
|
+
* // Emit events
|
|
3058
|
+
* bus.emit({ name: 'tx.wait.started', data: { txId: '0x123' } })
|
|
3059
|
+
* ```
|
|
3060
|
+
*/
|
|
3061
|
+
interface EventBus {
|
|
3062
|
+
/**
|
|
3063
|
+
* Emit an event to all matching subscribers.
|
|
3064
|
+
*
|
|
3065
|
+
* @param event - The event to emit.
|
|
3066
|
+
* @remarks
|
|
3067
|
+
* Synchronous and never throws. Handler errors are isolated.
|
|
3068
|
+
*/
|
|
3069
|
+
emit(event: Event): void;
|
|
3070
|
+
/**
|
|
3071
|
+
* Create a child event bus with scoped tags.
|
|
3072
|
+
*
|
|
3073
|
+
* @param tags - Tags to merge into all emitted events.
|
|
3074
|
+
* @returns A new EventBus with merged tags.
|
|
3075
|
+
*/
|
|
3076
|
+
child(tags: Tags): EventBus;
|
|
3077
|
+
/**
|
|
3078
|
+
* Subscribe to all events.
|
|
3079
|
+
*
|
|
3080
|
+
* @param handler - Function called for every event.
|
|
3081
|
+
* @returns Unsubscribe function.
|
|
3082
|
+
*/
|
|
3083
|
+
on(handler: EventHandler): () => void;
|
|
3084
|
+
/**
|
|
3085
|
+
* Subscribe to events matching a pattern.
|
|
3086
|
+
*
|
|
3087
|
+
* @param pattern - Topic pattern (supports `*` and `**` wildcards).
|
|
3088
|
+
* @param handler - Function called for matching events.
|
|
3089
|
+
* @returns Unsubscribe function.
|
|
3090
|
+
*
|
|
3091
|
+
* @remarks
|
|
3092
|
+
* Wildcard semantics:
|
|
3093
|
+
* - `*` matches exactly one segment (no dots)
|
|
3094
|
+
* - `**` matches zero or more segments (only valid at end)
|
|
3095
|
+
*
|
|
3096
|
+
* @example
|
|
3097
|
+
* ```typescript
|
|
3098
|
+
* bus.on('*', handler) // matches 'tx', 'user' (single segment only)
|
|
3099
|
+
* bus.on('tx.wait.*', handler) // matches tx.wait.started, tx.wait.failed
|
|
3100
|
+
* bus.on('tx.wait.**', handler) // matches tx.wait, tx.wait.started, tx.wait.foo.bar
|
|
3101
|
+
* bus.on('**', handler) // matches all events
|
|
3102
|
+
* ```
|
|
3103
|
+
*/
|
|
3104
|
+
on(pattern: string, handler: EventHandler): () => void;
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
/**
|
|
3108
|
+
* Metrics type definitions for the Runtime module.
|
|
3109
|
+
*
|
|
3110
|
+
* @remarks
|
|
3111
|
+
* Define a minimal, pluggable metrics interface that can be backed by any
|
|
3112
|
+
* metrics library (hot-shots, dd-trace, prom-client, etc.).
|
|
3113
|
+
*
|
|
3114
|
+
* The interface supports:
|
|
3115
|
+
* - Counters for monotonically increasing values
|
|
3116
|
+
* - Histograms for distributions (latencies, sizes)
|
|
3117
|
+
* - Timers as a convenience wrapper for timing operations
|
|
3118
|
+
* - Label scoping via `child()` for dimensional metrics
|
|
3119
|
+
*
|
|
3120
|
+
* @example
|
|
3121
|
+
* ```typescript
|
|
3122
|
+
* // Basic usage
|
|
3123
|
+
* metrics.counter('requests.total').inc({ method: 'POST' })
|
|
3124
|
+
* metrics.histogram('request.duration').observe({ status: 200 }, 42.5)
|
|
3125
|
+
*
|
|
3126
|
+
* // Timer convenience
|
|
3127
|
+
* const stop = metrics.timer('db.query').start({ table: 'users' })
|
|
3128
|
+
* await query()
|
|
3129
|
+
* stop() // Records duration automatically
|
|
3130
|
+
*
|
|
3131
|
+
* // Scoping adds base labels to all metrics
|
|
3132
|
+
* const scoped = metrics.child({ service: 'bridge', env: 'prod' })
|
|
3133
|
+
* scoped.counter('transfers').inc() // Includes service + env labels
|
|
3134
|
+
* ```
|
|
3135
|
+
*/
|
|
3136
|
+
/**
|
|
3137
|
+
* Labels for dimensional metrics.
|
|
3138
|
+
*
|
|
3139
|
+
* @remarks
|
|
3140
|
+
* Labels (also called tags in some systems) are key-value pairs that
|
|
3141
|
+
* provide dimensions for metric aggregation and filtering.
|
|
3142
|
+
* Values must be primitives for serialization compatibility.
|
|
3143
|
+
*
|
|
3144
|
+
* @example
|
|
3145
|
+
* ```typescript
|
|
3146
|
+
* const labels: MetricLabels = {
|
|
3147
|
+
* chain: 'Ethereum',
|
|
3148
|
+
* status: 'success',
|
|
3149
|
+
* retries: 3,
|
|
3150
|
+
* cached: true,
|
|
3151
|
+
* }
|
|
3152
|
+
* ```
|
|
3153
|
+
*/
|
|
3154
|
+
type MetricLabels = Record<string, string | number | boolean>;
|
|
3155
|
+
/**
|
|
3156
|
+
* A counter metric for monotonically increasing values.
|
|
3157
|
+
*
|
|
3158
|
+
* @remarks
|
|
3159
|
+
* Use counters for values that only go up: request counts, error counts,
|
|
3160
|
+
* bytes processed, etc. The value resets only on process restart.
|
|
3161
|
+
*
|
|
3162
|
+
* @see {@link Metrics.counter} to obtain a Counter instance.
|
|
3163
|
+
*
|
|
3164
|
+
* @example
|
|
3165
|
+
* ```typescript
|
|
3166
|
+
* const counter = metrics.counter('http.requests')
|
|
3167
|
+
*
|
|
3168
|
+
* // Increment by 1
|
|
3169
|
+
* counter.inc()
|
|
3170
|
+
* counter.inc({ method: 'GET' })
|
|
3171
|
+
*
|
|
3172
|
+
* // Increment by specific value
|
|
3173
|
+
* counter.inc(5)
|
|
3174
|
+
* counter.inc({ method: 'POST' }, 3)
|
|
3175
|
+
* ```
|
|
3176
|
+
*/
|
|
3177
|
+
interface Counter {
|
|
3178
|
+
/**
|
|
3179
|
+
* Increment the counter value.
|
|
3180
|
+
*
|
|
3181
|
+
* @param labelsOrValue - The labels object or increment value.
|
|
3182
|
+
* When a number, increments by that amount with no labels.
|
|
3183
|
+
* When an object, uses as labels with optional value in second param.
|
|
3184
|
+
* @param value - The increment value when first arg is labels. Default: 1.
|
|
3185
|
+
* @returns void
|
|
3186
|
+
*
|
|
3187
|
+
* @example
|
|
3188
|
+
* ```typescript
|
|
3189
|
+
* counter.inc() // +1, no labels
|
|
3190
|
+
* counter.inc(5) // +5, no labels
|
|
3191
|
+
* counter.inc({ method: 'GET' }) // +1, with labels
|
|
3192
|
+
* counter.inc({ method: 'POST' }, 3) // +3, with labels
|
|
3193
|
+
* ```
|
|
3194
|
+
*/
|
|
3195
|
+
inc(labelsOrValue?: MetricLabels | number, value?: number): void;
|
|
3196
|
+
}
|
|
3197
|
+
/**
|
|
3198
|
+
* A histogram metric for recording value distributions.
|
|
3199
|
+
*
|
|
3200
|
+
* @remarks
|
|
3201
|
+
* Use histograms for values that vary and need percentile analysis:
|
|
3202
|
+
* request durations, response sizes, queue depths, etc.
|
|
3203
|
+
*
|
|
3204
|
+
* @see {@link Metrics.histogram} to obtain a Histogram instance.
|
|
3205
|
+
*
|
|
3206
|
+
* @example
|
|
3207
|
+
* ```typescript
|
|
3208
|
+
* const histogram = metrics.histogram('http.duration')
|
|
3209
|
+
*
|
|
3210
|
+
* // Record a value
|
|
3211
|
+
* histogram.observe(42.5)
|
|
3212
|
+
* histogram.observe({ status: 200 }, 42.5)
|
|
3213
|
+
* ```
|
|
3214
|
+
*/
|
|
3215
|
+
interface Histogram {
|
|
3216
|
+
/**
|
|
3217
|
+
* Record an observation value.
|
|
3218
|
+
*
|
|
3219
|
+
* @param labelsOrValue - The labels object or observed value.
|
|
3220
|
+
* When a number, records that value with no labels.
|
|
3221
|
+
* When an object, uses as labels with value in second param.
|
|
3222
|
+
* @param value - The observed value when first arg is labels. Default: 0.
|
|
3223
|
+
* @returns void
|
|
3224
|
+
*
|
|
3225
|
+
* @example
|
|
3226
|
+
* ```typescript
|
|
3227
|
+
* histogram.observe(42.5) // Value only
|
|
3228
|
+
* histogram.observe({ status: 200 }, 42.5) // With labels
|
|
3229
|
+
* ```
|
|
3230
|
+
*/
|
|
3231
|
+
observe(labelsOrValue?: MetricLabels | number, value?: number): void;
|
|
3232
|
+
}
|
|
3233
|
+
/**
|
|
3234
|
+
* A timer metric for measuring operation durations.
|
|
3235
|
+
*
|
|
3236
|
+
* @remarks
|
|
3237
|
+
* Timers provide a convenience wrapper that automatically records durations
|
|
3238
|
+
* to an underlying histogram. Call `start()` to begin timing and the
|
|
3239
|
+
* returned function to stop and record the elapsed time in milliseconds.
|
|
3240
|
+
*
|
|
3241
|
+
* @see {@link Metrics.timer} to obtain a Timer instance.
|
|
3242
|
+
*
|
|
3243
|
+
* @example
|
|
3244
|
+
* ```typescript
|
|
3245
|
+
* const timer = metrics.timer('db.query')
|
|
3246
|
+
*
|
|
3247
|
+
* // Start timing
|
|
3248
|
+
* const stop = timer.start({ table: 'users' })
|
|
3249
|
+
* await performQuery()
|
|
3250
|
+
* stop() // Records duration in milliseconds
|
|
3251
|
+
* ```
|
|
3252
|
+
*/
|
|
3253
|
+
interface Timer {
|
|
3254
|
+
/**
|
|
3255
|
+
* Start timing an operation.
|
|
3256
|
+
*
|
|
3257
|
+
* @param labels - The optional labels for the timing observation.
|
|
3258
|
+
* @returns A stop function that records the duration when called.
|
|
3259
|
+
*
|
|
3260
|
+
* @example
|
|
3261
|
+
* ```typescript
|
|
3262
|
+
* const stop = timer.start({ operation: 'fetch' })
|
|
3263
|
+
* await fetchData()
|
|
3264
|
+
* stop() // Records elapsed time
|
|
3265
|
+
* ```
|
|
3266
|
+
*/
|
|
3267
|
+
start(labels?: MetricLabels): () => void;
|
|
3268
|
+
}
|
|
3269
|
+
/**
|
|
3270
|
+
* Main metrics interface for instrumentation.
|
|
3271
|
+
*
|
|
3272
|
+
* @remarks
|
|
3273
|
+
* This interface is designed to be thin and pluggable. Implementations
|
|
3274
|
+
* can delegate to any metrics library:
|
|
3275
|
+
*
|
|
3276
|
+
* - **hot-shots**: StatsD/DogStatsD client
|
|
3277
|
+
* - **dd-trace**: Datadog APM
|
|
3278
|
+
* - **prom-client**: Prometheus
|
|
3279
|
+
* - **opentelemetry-js**: OpenTelemetry
|
|
3280
|
+
*
|
|
3281
|
+
* The `child()` method creates a scoped metrics instance that automatically
|
|
3282
|
+
* includes base labels on all metric operations.
|
|
3283
|
+
*
|
|
3284
|
+
* @see {@link createMockMetrics} for testing.
|
|
3285
|
+
* @see {@link noopMetrics} for a no-op implementation.
|
|
3286
|
+
*
|
|
3287
|
+
* @example
|
|
3288
|
+
* ```typescript
|
|
3289
|
+
* // Create a scoped metrics instance
|
|
3290
|
+
* const appMetrics = metrics.child({
|
|
3291
|
+
* service: 'stablecoin-kit',
|
|
3292
|
+
* version: '1.0.0',
|
|
3293
|
+
* })
|
|
3294
|
+
*
|
|
3295
|
+
* // All metrics include service + version labels
|
|
3296
|
+
* appMetrics.counter('transfers.initiated').inc({ chain: 'ethereum' })
|
|
3297
|
+
* ```
|
|
3298
|
+
*/
|
|
3299
|
+
interface Metrics {
|
|
3300
|
+
/**
|
|
3301
|
+
* Get or create a counter metric by name.
|
|
3302
|
+
*
|
|
3303
|
+
* @param name - The metric name (e.g., 'http.requests.total').
|
|
3304
|
+
* @returns A Counter instance for the given name.
|
|
3305
|
+
*
|
|
3306
|
+
* @example
|
|
3307
|
+
* ```typescript
|
|
3308
|
+
* const counter = metrics.counter('requests.total')
|
|
3309
|
+
* counter.inc({ method: 'GET' })
|
|
3310
|
+
* ```
|
|
3311
|
+
*/
|
|
3312
|
+
counter(name: string): Counter;
|
|
3313
|
+
/**
|
|
3314
|
+
* Get or create a histogram metric by name.
|
|
3315
|
+
*
|
|
3316
|
+
* @param name - The metric name (e.g., 'http.request.duration').
|
|
3317
|
+
* @returns A Histogram instance for the given name.
|
|
3318
|
+
*
|
|
3319
|
+
* @example
|
|
3320
|
+
* ```typescript
|
|
3321
|
+
* const histogram = metrics.histogram('request.duration')
|
|
3322
|
+
* histogram.observe({ status: 200 }, 42.5)
|
|
3323
|
+
* ```
|
|
3324
|
+
*/
|
|
3325
|
+
histogram(name: string): Histogram;
|
|
3326
|
+
/**
|
|
3327
|
+
* Get or create a timer metric by name.
|
|
3328
|
+
*
|
|
3329
|
+
* @param name - The metric name (e.g., 'db.query.duration').
|
|
3330
|
+
* @returns A Timer instance for the given name.
|
|
3331
|
+
*
|
|
3332
|
+
* @example
|
|
3333
|
+
* ```typescript
|
|
3334
|
+
* const stop = metrics.timer('db.query').start()
|
|
3335
|
+
* await query()
|
|
3336
|
+
* stop()
|
|
3337
|
+
* ```
|
|
3338
|
+
*/
|
|
3339
|
+
timer(name: string): Timer;
|
|
3340
|
+
/**
|
|
3341
|
+
* Create a child metrics instance with scoped labels.
|
|
3342
|
+
*
|
|
3343
|
+
* @param labels - The base labels to include on all metric operations.
|
|
3344
|
+
* @returns A new Metrics instance with merged labels.
|
|
3345
|
+
*
|
|
3346
|
+
* @remarks
|
|
3347
|
+
* Labels from the child are merged with any labels passed to individual
|
|
3348
|
+
* metric operations. Call-site labels take precedence for the same key.
|
|
3349
|
+
*
|
|
3350
|
+
* @example
|
|
3351
|
+
* ```typescript
|
|
3352
|
+
* const scoped = metrics.child({ chain: 'Ethereum' })
|
|
3353
|
+
* scoped.counter('transfers').inc({ status: 'success' })
|
|
3354
|
+
* // Labels: { chain: 'Ethereum', status: 'success' }
|
|
3355
|
+
* ```
|
|
3356
|
+
*/
|
|
3357
|
+
child(labels: MetricLabels): Metrics;
|
|
3358
|
+
}
|
|
3359
|
+
|
|
3360
|
+
/**
|
|
3361
|
+
* Core type definitions for the runtime package.
|
|
3362
|
+
*
|
|
3363
|
+
* @remarks
|
|
3364
|
+
* This module defines the foundational types used throughout the SDK:
|
|
3365
|
+
*
|
|
3366
|
+
* - {@link Runtime} - Complete runtime with all services (clock, logger, metrics, events)
|
|
3367
|
+
* - {@link ExecutionContext} - Context for middleware with observability surface
|
|
3368
|
+
* - {@link Clock}, {@link Tags}, {@link Event} - Supporting types
|
|
3369
|
+
*
|
|
3370
|
+
* **Naming Convention**
|
|
3371
|
+
*
|
|
3372
|
+
* | Input Type | Resolved Type | Description |
|
|
3373
|
+
* |------------|---------------|-------------|
|
|
3374
|
+
* | `Partial<Runtime>` | `Runtime` | Runtime services |
|
|
3375
|
+
* | `OperationMeta` | `OperationContext` | WHAT - operation target |
|
|
3376
|
+
* | `InvocationMeta` | `InvocationContext` | WHO/HOW - call chain |
|
|
3377
|
+
*
|
|
3378
|
+
* @packageDocumentation
|
|
3379
|
+
*/
|
|
3380
|
+
|
|
3381
|
+
/**
|
|
3382
|
+
* Clock interface for time operations.
|
|
3383
|
+
*
|
|
3384
|
+
* @remarks
|
|
3385
|
+
* Abstracting time allows tests to control timing without real delays.
|
|
3386
|
+
* Production code uses {@link defaultClock}, tests use mock implementations.
|
|
3387
|
+
*
|
|
3388
|
+
* @example
|
|
3389
|
+
* ```typescript
|
|
3390
|
+
* import { defaultClock, type Clock } from '@core/runtime'
|
|
3391
|
+
*
|
|
3392
|
+
* const start = defaultClock.now()
|
|
3393
|
+
* // ... do work ...
|
|
3394
|
+
* const elapsed = defaultClock.since(start)
|
|
3395
|
+
* ```
|
|
3396
|
+
*/
|
|
3397
|
+
interface Clock {
|
|
3398
|
+
/**
|
|
3399
|
+
* Return the current timestamp in milliseconds since Unix epoch.
|
|
3400
|
+
*
|
|
3401
|
+
* @returns Current time in milliseconds.
|
|
3402
|
+
*/
|
|
3403
|
+
now(): number;
|
|
3404
|
+
/**
|
|
3405
|
+
* Calculate elapsed time since a given timestamp.
|
|
3406
|
+
*
|
|
3407
|
+
* @param start - The start timestamp in milliseconds.
|
|
3408
|
+
* @returns Elapsed time in milliseconds (`now() - start`).
|
|
3409
|
+
*/
|
|
3410
|
+
since: (start: number) => number;
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* Contextual metadata tags for logging and metrics.
|
|
3414
|
+
*
|
|
3415
|
+
* @remarks
|
|
3416
|
+
* Tags are key-value pairs attached to log entries and metrics.
|
|
3417
|
+
* Values can be primitives or undefined (undefined values are filtered out).
|
|
3418
|
+
*
|
|
3419
|
+
* Common tags include:
|
|
3420
|
+
* - `opId` - Operation identifier for correlation
|
|
3421
|
+
* - `chain` - Blockchain network name
|
|
3422
|
+
* - `phase` - Current pipeline phase
|
|
3423
|
+
*
|
|
3424
|
+
* @example
|
|
3425
|
+
* ```typescript
|
|
3426
|
+
* import type { Tags } from '@core/runtime'
|
|
3427
|
+
*
|
|
3428
|
+
* const tags: Tags = {
|
|
3429
|
+
* opId: 'op-abc123',
|
|
3430
|
+
* chain: 'Ethereum',
|
|
3431
|
+
* phase: 'validate',
|
|
3432
|
+
* optional: undefined, // Will be filtered out
|
|
3433
|
+
* }
|
|
3434
|
+
* ```
|
|
3435
|
+
*/
|
|
3436
|
+
type Tags = Record<string, string | number | boolean | undefined>;
|
|
3437
|
+
/**
|
|
3438
|
+
* A structured event emitted by the runtime.
|
|
3439
|
+
*
|
|
3440
|
+
* @remarks
|
|
3441
|
+
* Events provide a standardized way to capture lifecycle moments,
|
|
3442
|
+
* actions, and state changes throughout the SDK.
|
|
3443
|
+
*/
|
|
3444
|
+
interface Event {
|
|
3445
|
+
/** The event name/identifier. */
|
|
3446
|
+
name: string;
|
|
3447
|
+
/** Log level for the event. */
|
|
3448
|
+
level?: 'debug' | 'info' | 'warn' | 'error';
|
|
3449
|
+
/** Timestamp (epoch ms) when the event occurred. */
|
|
3450
|
+
at?: number;
|
|
3451
|
+
/** Contextual tags for filtering/categorization. */
|
|
3452
|
+
tags?: Tags;
|
|
3453
|
+
/** Arbitrary payload data associated with the event. */
|
|
3454
|
+
data?: unknown;
|
|
3455
|
+
}
|
|
3456
|
+
/**
|
|
3457
|
+
* Complete runtime with all services guaranteed present.
|
|
3458
|
+
*
|
|
3459
|
+
* @remarks
|
|
3460
|
+
* The runtime is the container for all cross-cutting concerns: logging,
|
|
3461
|
+
* timing, events, and metrics. All services are guaranteed to be available.
|
|
3462
|
+
*
|
|
3463
|
+
* **Creating a Runtime**
|
|
3464
|
+
*
|
|
3465
|
+
* Use {@link createRuntime} to create a fully-configured runtime:
|
|
3466
|
+
* ```typescript
|
|
3467
|
+
* import { createRuntime } from '@core/runtime'
|
|
3468
|
+
*
|
|
3469
|
+
* const runtime = createRuntime()
|
|
3470
|
+
* runtime.logger.info('Hello')
|
|
3471
|
+
* runtime.metrics.counter('requests').inc()
|
|
3472
|
+
* ```
|
|
3473
|
+
*
|
|
3474
|
+
* **Partial Runtime Input**
|
|
3475
|
+
*
|
|
3476
|
+
* When accepting runtime configuration as input, use `Partial<Runtime>`:
|
|
3477
|
+
* ```typescript
|
|
3478
|
+
* function myFunction(options: { runtime?: Partial<Runtime> }) {
|
|
3479
|
+
* const runtime = createRuntime(options.runtime)
|
|
3480
|
+
* // ...
|
|
3481
|
+
* }
|
|
3482
|
+
* ```
|
|
3483
|
+
*
|
|
3484
|
+
* @example
|
|
3485
|
+
* ```typescript
|
|
3486
|
+
* import { createRuntime, type Runtime } from '@core/runtime'
|
|
3487
|
+
*
|
|
3488
|
+
* const runtime: Runtime = createRuntime()
|
|
3489
|
+
*
|
|
3490
|
+
* // All services are guaranteed present
|
|
3491
|
+
* runtime.logger.info('Processing request')
|
|
3492
|
+
* runtime.metrics.counter('requests').inc()
|
|
3493
|
+
* runtime.events.emit({ name: 'request.received' })
|
|
3494
|
+
* const now = runtime.clock.now()
|
|
3495
|
+
* ```
|
|
3496
|
+
*/
|
|
3497
|
+
interface Runtime {
|
|
3498
|
+
/**
|
|
3499
|
+
* Clock for time operations.
|
|
3500
|
+
*
|
|
3501
|
+
* @remarks
|
|
3502
|
+
* Provides the current timestamp. Use {@link defaultClock} for production
|
|
3503
|
+
* or custom clocks for deterministic testing.
|
|
3504
|
+
*/
|
|
3505
|
+
clock: Clock;
|
|
3506
|
+
/**
|
|
3507
|
+
* Logger for structured logging.
|
|
3508
|
+
*
|
|
3509
|
+
* @remarks
|
|
3510
|
+
* Provides debug, info, warn, error methods with structured data support.
|
|
3511
|
+
*/
|
|
3512
|
+
logger: Logger;
|
|
3513
|
+
/**
|
|
3514
|
+
* Metrics collector for observability.
|
|
3515
|
+
*
|
|
3516
|
+
* @remarks
|
|
3517
|
+
* Provides counters, histograms, and timers for application metrics.
|
|
3518
|
+
*/
|
|
3519
|
+
metrics: Metrics;
|
|
3520
|
+
/**
|
|
3521
|
+
* Event bus for pub/sub events.
|
|
3522
|
+
*
|
|
3523
|
+
* @remarks
|
|
3524
|
+
* Enables decoupled event emission and subscription across the SDK.
|
|
3525
|
+
*/
|
|
3526
|
+
events: EventBus;
|
|
3527
|
+
}
|
|
3528
|
+
/**
|
|
3529
|
+
* A component in the call chain.
|
|
3530
|
+
*
|
|
3531
|
+
* @remarks
|
|
3532
|
+
* Each caller identifies itself with a type (app, kit, provider, adapter)
|
|
3533
|
+
* and a name/version. This enables proper attribution in logs, metrics, and traces.
|
|
3534
|
+
*
|
|
3535
|
+
* @example
|
|
3536
|
+
* ```typescript
|
|
3537
|
+
* import type { Caller } from '@core/runtime'
|
|
3538
|
+
*
|
|
3539
|
+
* const appCaller: Caller = { type: 'app', name: 'MyDApp', version: '1.0.0' }
|
|
3540
|
+
* const kitCaller: Caller = { type: 'kit', name: 'BridgeKit', version: '2.0.0' }
|
|
3541
|
+
* ```
|
|
3542
|
+
*/
|
|
3543
|
+
interface Caller {
|
|
3544
|
+
/**
|
|
3545
|
+
* Type of component in the call hierarchy.
|
|
3546
|
+
*
|
|
3547
|
+
* @remarks
|
|
3548
|
+
* Common types: `app`, `kit`, `provider`, `adapter`
|
|
3549
|
+
*/
|
|
3550
|
+
readonly type: string;
|
|
3551
|
+
/** Name of the component (e.g., 'BridgeKit', 'cctp-v2'). */
|
|
3552
|
+
readonly name: string;
|
|
3553
|
+
/** Version of the component (e.g., '1.0.0'). */
|
|
3554
|
+
readonly version?: string | undefined;
|
|
3555
|
+
}
|
|
3556
|
+
/**
|
|
3557
|
+
* User input for invocation metadata.
|
|
3558
|
+
*
|
|
3559
|
+
* @remarks
|
|
3560
|
+
* Defines **WHO** called and **HOW** to observe: trace correlation, runtime override,
|
|
3561
|
+
* and caller chain. This is the user-facing input type, resolved to `InvocationContext`.
|
|
3562
|
+
*
|
|
3563
|
+
* Passed as the optional invocation argument to actions and primitives.
|
|
3564
|
+
*
|
|
3565
|
+
* @example
|
|
3566
|
+
* ```typescript
|
|
3567
|
+
* import type { InvocationMeta } from '@core/runtime'
|
|
3568
|
+
*
|
|
3569
|
+
* // Minimal - just traceId
|
|
3570
|
+
* const meta: InvocationMeta = { traceId: 'abc-123' }
|
|
3571
|
+
*
|
|
3572
|
+
* // Full - with runtime override and caller chain
|
|
3573
|
+
* const meta: InvocationMeta = {
|
|
3574
|
+
* traceId: 'abc-123',
|
|
3575
|
+
* runtime: myRuntime,
|
|
3576
|
+
* callers: [
|
|
3577
|
+
* { type: 'app', name: 'MyDApp', version: '1.0.0' },
|
|
3578
|
+
* ],
|
|
3579
|
+
* }
|
|
3580
|
+
* ```
|
|
3581
|
+
*/
|
|
3582
|
+
interface InvocationMeta {
|
|
3583
|
+
/**
|
|
3584
|
+
* Trace ID for distributed tracing correlation.
|
|
3585
|
+
*
|
|
3586
|
+
* @remarks
|
|
3587
|
+
* If not provided, generated automatically.
|
|
3588
|
+
*/
|
|
3589
|
+
readonly traceId?: string | undefined;
|
|
3590
|
+
/**
|
|
3591
|
+
* Runtime override (complete replacement).
|
|
3592
|
+
*
|
|
3593
|
+
* @remarks
|
|
3594
|
+
* When provided, this runtime completely replaces the default runtime.
|
|
3595
|
+
* Must be a complete Runtime instance (e.g., from `createRuntime()`).
|
|
3596
|
+
* If not provided, the default runtime is used.
|
|
3597
|
+
*/
|
|
3598
|
+
readonly runtime?: Runtime | undefined;
|
|
3599
|
+
/**
|
|
3600
|
+
* Token registry override (complete replacement).
|
|
3601
|
+
*
|
|
3602
|
+
* @remarks
|
|
3603
|
+
* When provided, this registry completely replaces the default token registry.
|
|
3604
|
+
* Enables kits to pass their token registry to adapters.
|
|
3605
|
+
* If not provided, the default token registry is used.
|
|
3606
|
+
*/
|
|
3607
|
+
readonly tokens?: TokenRegistry | undefined;
|
|
3608
|
+
/**
|
|
3609
|
+
* Call chain - each caller appends itself.
|
|
3610
|
+
*
|
|
3611
|
+
* @remarks
|
|
3612
|
+
* Ordered from outermost (first) to innermost (last).
|
|
3613
|
+
* Example: [app, kit, provider]
|
|
3614
|
+
*/
|
|
3615
|
+
readonly callers?: readonly Caller[] | undefined;
|
|
3616
|
+
}
|
|
3617
|
+
|
|
3618
|
+
/**
|
|
3619
|
+
* Transfer speed options for cross-chain operations.
|
|
3620
|
+
*
|
|
3621
|
+
* Defines the available speed modes for CCTPv2 transfers, affecting
|
|
3622
|
+
* both transfer time and potential fee implications.
|
|
3623
|
+
*/
|
|
3624
|
+
declare enum TransferSpeed {
|
|
3625
|
+
/** Fast burn mode - reduces transfer time but may have different fee implications */
|
|
3626
|
+
FAST = "FAST",
|
|
3627
|
+
/** Standard burn mode - normal transfer time with standard fees */
|
|
3628
|
+
SLOW = "SLOW"
|
|
3629
|
+
}
|
|
3630
|
+
/**
|
|
3631
|
+
* Context object representing a wallet and signing authority on a specific blockchain network.
|
|
3632
|
+
*
|
|
3633
|
+
* Combines a wallet or contract address, the blockchain it resides on, and the adapter (signer)
|
|
3634
|
+
* responsible for authorizing transactions. Used to specify the source or destination in cross-chain
|
|
3635
|
+
* transfer operations.
|
|
3636
|
+
*
|
|
3637
|
+
* @remarks
|
|
3638
|
+
* The `adapter` (signer) and `address` do not always have to belong to the same entity. For example,
|
|
3639
|
+
* in minting or withdrawal scenarios, the signing adapter may authorize a transaction that credits
|
|
3640
|
+
* funds to a different recipient address. This context is essential for cross-chain operations,
|
|
3641
|
+
* ensuring that both the address and the associated adapter are correctly paired with the intended
|
|
3642
|
+
* blockchain, but not necessarily with each other.
|
|
3643
|
+
*
|
|
3644
|
+
* @example
|
|
3645
|
+
* ```typescript
|
|
3646
|
+
* import type { WalletContext } from '@core/provider'
|
|
3647
|
+
* import { adapter, blockchain } from './setup'
|
|
3648
|
+
*
|
|
3649
|
+
* const wallet: WalletContext = {
|
|
3650
|
+
* adapter,
|
|
3651
|
+
* address: '0x1234...abcd',
|
|
3652
|
+
* chain: blockchain,
|
|
3653
|
+
* }
|
|
3654
|
+
* ```
|
|
3655
|
+
*/
|
|
3656
|
+
interface WalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
|
|
3657
|
+
/**
|
|
3658
|
+
* The chain definition type to use for the wallet context.
|
|
3659
|
+
*
|
|
3660
|
+
* @defaultValue ChainDefinition
|
|
3661
|
+
*/
|
|
3662
|
+
TChainDefinition extends ChainDefinition = ChainDefinition> {
|
|
3663
|
+
/**
|
|
3664
|
+
* The adapter (signer) for the wallet on the specified chain.
|
|
3665
|
+
*
|
|
3666
|
+
* Responsible for authorizing transactions and signing messages on behalf of the wallet or
|
|
3667
|
+
* for a different recipient, depending on the use case.
|
|
3668
|
+
*/
|
|
3669
|
+
adapter: Adapter<TAdapterCapabilities>;
|
|
3670
|
+
/**
|
|
3671
|
+
* The wallet or contract address.
|
|
3672
|
+
*
|
|
3673
|
+
* Must be a valid address format for the specified blockchain. May differ from the adapter's
|
|
3674
|
+
* own address in scenarios such as relayed transactions or third-party minting.
|
|
3675
|
+
*/
|
|
3676
|
+
address: string;
|
|
3677
|
+
/**
|
|
3678
|
+
* The blockchain network where the wallet or contract address resides.
|
|
3679
|
+
*
|
|
3680
|
+
* Determines the context and format for the address and adapter.
|
|
3681
|
+
*/
|
|
3682
|
+
chain: TChainDefinition;
|
|
3683
|
+
}
|
|
3684
|
+
/**
|
|
3685
|
+
* Wallet context for bridge destinations with optional custom recipient.
|
|
3686
|
+
*
|
|
3687
|
+
* Extends WalletContext to support scenarios where the recipient address
|
|
3688
|
+
* differs from the signer address (e.g., bridging to a third-party wallet).
|
|
3689
|
+
* The signer address is used for transaction authorization, while the
|
|
3690
|
+
* recipient address specifies where the minted funds should be sent.
|
|
3691
|
+
*
|
|
3692
|
+
* @typeParam TAdapterCapabilities - The adapter capabilities type to use for the wallet context.
|
|
3693
|
+
* @typeParam TChainDefinition - The chain definition type to use for the wallet context.
|
|
3694
|
+
*
|
|
3695
|
+
* @example
|
|
3696
|
+
* ```typescript
|
|
3697
|
+
* import type { DestinationWalletContext } from '@core/provider'
|
|
3698
|
+
* import { adapter, blockchain } from './setup'
|
|
3699
|
+
*
|
|
3700
|
+
* // Bridge to a custom recipient address
|
|
3701
|
+
* const destination: DestinationWalletContext = {
|
|
3702
|
+
* adapter,
|
|
3703
|
+
* address: '0x1234...abcd', // Signer address
|
|
3704
|
+
* chain: blockchain,
|
|
3705
|
+
* recipientAddress: '0x9876...fedc' // Custom recipient
|
|
3706
|
+
* }
|
|
3707
|
+
* ```
|
|
3708
|
+
*/
|
|
3709
|
+
interface DestinationWalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
|
|
3710
|
+
/**
|
|
3711
|
+
* The chain definition type to use for the wallet context.
|
|
3712
|
+
*
|
|
3713
|
+
* @defaultValue ChainDefinition
|
|
3714
|
+
*/
|
|
3715
|
+
TChainDefinition extends ChainDefinition = ChainDefinition> extends WalletContext<TAdapterCapabilities, TChainDefinition> {
|
|
3716
|
+
/**
|
|
3717
|
+
* Optional custom recipient address for minted funds.
|
|
3718
|
+
*
|
|
3719
|
+
* When provided, minted tokens will be sent to this address instead of
|
|
3720
|
+
* the address specified in the wallet context. The wallet context address
|
|
3721
|
+
* is still used for transaction signing and authorization.
|
|
3722
|
+
*
|
|
3723
|
+
* Must be a valid address format for the specified blockchain.
|
|
3724
|
+
*/
|
|
3725
|
+
recipientAddress?: string;
|
|
3726
|
+
}
|
|
3727
|
+
/**
|
|
3728
|
+
* Parameters for executing a cross-chain bridge operation.
|
|
3729
|
+
*/
|
|
3730
|
+
interface BridgeParams<TFromCapabilities extends AdapterCapabilities = AdapterCapabilities, TToCapabilities extends AdapterCapabilities = AdapterCapabilities,
|
|
3731
|
+
/**
|
|
3732
|
+
* The chain definition type to use for the wallet context.
|
|
3733
|
+
*
|
|
3734
|
+
* @defaultValue ChainDefinition
|
|
3735
|
+
*/
|
|
3736
|
+
TChainDefinition extends ChainDefinition = ChainDefinition> {
|
|
3737
|
+
/** The source adapter containing wallet and chain information */
|
|
3738
|
+
source: WalletContext<TFromCapabilities, TChainDefinition>;
|
|
3739
|
+
/** The destination adapter containing wallet and chain information */
|
|
3740
|
+
destination: DestinationWalletContext<TToCapabilities, TChainDefinition>;
|
|
3741
|
+
/** The amount to transfer (as a string to avoid precision issues) */
|
|
3742
|
+
amount: string;
|
|
3743
|
+
/** The token to transfer (currently only USDC is supported) */
|
|
3744
|
+
token: 'USDC';
|
|
3745
|
+
/** Bridge configuration (e.g., fast burn settings) */
|
|
3746
|
+
config: BridgeConfig;
|
|
3747
|
+
/**
|
|
3748
|
+
* Optional invocation metadata for tracing and correlation.
|
|
3749
|
+
*
|
|
3750
|
+
* When provided, the `traceId` is used to correlate all events emitted during
|
|
3751
|
+
* the bridge operation. If not provided, an OpenTelemetry-compatible traceId
|
|
3752
|
+
* will be auto-generated.
|
|
3753
|
+
*/
|
|
3754
|
+
invocationMeta?: InvocationMeta;
|
|
3755
|
+
}
|
|
3756
|
+
/**
|
|
3757
|
+
* A step in the bridge process.
|
|
3758
|
+
*
|
|
3759
|
+
* @remarks
|
|
3760
|
+
* This interface represents a single step in the bridge process,
|
|
3761
|
+
* such as approval, burn, or mint.
|
|
3762
|
+
*
|
|
3763
|
+
* @example
|
|
3764
|
+
* ```typescript
|
|
3765
|
+
* const step: BridgeStep = {
|
|
3766
|
+
* name: 'Approve',
|
|
3767
|
+
* state: 'success',
|
|
3768
|
+
* txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
3769
|
+
* explorerUrl: 'https://etherscan.io/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
|
|
3770
|
+
* }
|
|
3771
|
+
* ```
|
|
3772
|
+
*/
|
|
3773
|
+
interface BridgeStep {
|
|
3774
|
+
/** Human-readable name of the step (e.g., "Approve", "Burn", "Mint") */
|
|
3775
|
+
name: string;
|
|
3776
|
+
/** The state of the step */
|
|
3777
|
+
state: 'pending' | 'success' | 'error' | 'noop';
|
|
3778
|
+
/** Optional transaction hash for this step (if applicable) */
|
|
3779
|
+
txHash?: string;
|
|
3780
|
+
/** Optional explorer URL for viewing this transaction on a block explorer */
|
|
3781
|
+
explorerUrl?: string;
|
|
3782
|
+
/** Optional data for the step */
|
|
3783
|
+
data?: unknown;
|
|
3784
|
+
/**
|
|
3785
|
+
* Whether this step was executed via Circle's Forwarder (relay service).
|
|
3786
|
+
* Only applicable for mint steps.
|
|
3787
|
+
*
|
|
3788
|
+
* - `true`: The mint was handled by Circle's Orbit relayer
|
|
3789
|
+
* - `false`: The user submitted the mint transaction directly
|
|
3790
|
+
* - `undefined`: Not applicable (non-mint steps)
|
|
3791
|
+
*/
|
|
3792
|
+
forwarded?: boolean;
|
|
3793
|
+
/** Optional human-readable error message */
|
|
3794
|
+
errorMessage?: string;
|
|
3795
|
+
/** Optional raw error object (can be Viem/Ethers/Chain error) */
|
|
3796
|
+
error?: unknown;
|
|
3797
|
+
}
|
|
3798
|
+
/**
|
|
3799
|
+
* Result object returned after a successful cross-chain bridge operation.
|
|
3800
|
+
*
|
|
3801
|
+
* This interface contains all the details about a completed bridge, including
|
|
3802
|
+
* the bridge parameters, source and destination information,
|
|
3803
|
+
* and the sequence of steps that were executed.
|
|
3804
|
+
*
|
|
3805
|
+
* @example
|
|
3806
|
+
* ```typescript
|
|
3807
|
+
* const result: BridgeResult = await provider.bridge(source, dest, '100')
|
|
3808
|
+
* console.log(`Transferred ${result.amount} ${result.token}`)
|
|
3809
|
+
* console.log(`Steps executed: ${result.steps.length}`)
|
|
3810
|
+
* ```
|
|
3811
|
+
*/
|
|
3812
|
+
interface BridgeResult {
|
|
3813
|
+
/** The amount that was transferred (as a string to avoid precision issues) */
|
|
3814
|
+
amount: string;
|
|
3815
|
+
/** The token that was transferred (currently only USDC is supported) */
|
|
3816
|
+
token: 'USDC';
|
|
3817
|
+
/** The state of the transfer */
|
|
3818
|
+
state: 'pending' | 'success' | 'error';
|
|
3819
|
+
/** The bridge configuration that was used for this operation */
|
|
3820
|
+
config?: BridgeConfig;
|
|
3821
|
+
/** The provider that was used for this operation */
|
|
3822
|
+
provider: string;
|
|
3823
|
+
/** Information about the source chain and address */
|
|
3824
|
+
source: {
|
|
3825
|
+
/** The source wallet/contract address */
|
|
3826
|
+
address: string;
|
|
3827
|
+
/** The source blockchain network */
|
|
3828
|
+
chain: ChainDefinition;
|
|
3829
|
+
};
|
|
3830
|
+
/** Information about the destination chain and address */
|
|
3831
|
+
destination: {
|
|
3832
|
+
/** The destination wallet/contract address */
|
|
3833
|
+
address: string;
|
|
3834
|
+
/** The destination blockchain network */
|
|
3835
|
+
chain: ChainDefinition;
|
|
3836
|
+
/**
|
|
3837
|
+
* Optional custom recipient address for minted funds.
|
|
3838
|
+
*
|
|
3839
|
+
* When provided during the bridge operation, minted tokens are sent to this
|
|
3840
|
+
* address instead of the destination address. This field is preserved in the
|
|
3841
|
+
* result for retry operations to maintain consistency with the original burn.
|
|
3842
|
+
*/
|
|
3843
|
+
recipientAddress?: string;
|
|
3844
|
+
/**
|
|
3845
|
+
* Whether Circle's Forwarder was used for this bridge operation.
|
|
3846
|
+
*
|
|
3847
|
+
* When true, the mint transaction was handled by Circle's Orbit relayer
|
|
3848
|
+
* instead of requiring the user to submit it manually.
|
|
3849
|
+
*/
|
|
3850
|
+
useForwarder?: boolean;
|
|
3851
|
+
};
|
|
3852
|
+
/** Array of steps that were executed during the bridge process */
|
|
3853
|
+
steps: BridgeStep[];
|
|
3854
|
+
}
|
|
3855
|
+
/**
|
|
3856
|
+
* Cost estimation result for a cross-chain transfer operation.
|
|
3857
|
+
*
|
|
3858
|
+
* This interface provides detailed information about the expected costs
|
|
3859
|
+
* for a transfer, including gas fees on different chains and protocol fees.
|
|
3860
|
+
* It also includes the input context (token, amount, source, destination) to
|
|
3861
|
+
* provide a complete view of the transfer being estimated.
|
|
3862
|
+
*
|
|
3863
|
+
* @example
|
|
3864
|
+
* ```typescript
|
|
3865
|
+
* const estimate: EstimateResult = await provider.estimate(source, dest, '100')
|
|
3866
|
+
* console.log('Estimating transfer of', estimate.amount, estimate.token)
|
|
3867
|
+
* console.log('From', estimate.source.chain.name, 'to', estimate.destination.chain.name)
|
|
3868
|
+
* console.log('Total gas fees:', estimate.gasFees.length)
|
|
3869
|
+
* console.log('Protocol fees:', estimate.fees.length)
|
|
3870
|
+
* ```
|
|
3871
|
+
*/
|
|
3872
|
+
interface EstimateResult {
|
|
3873
|
+
/** The token being transferred */
|
|
3874
|
+
token: 'USDC';
|
|
2676
3875
|
/** The amount being transferred */
|
|
2677
3876
|
amount: string;
|
|
2678
3877
|
/** Information about the source chain and address */
|
|
@@ -2706,8 +3905,8 @@ interface EstimateResult {
|
|
|
2706
3905
|
}[];
|
|
2707
3906
|
/** Array of protocol and service fees for the transfer */
|
|
2708
3907
|
fees: {
|
|
2709
|
-
/** The type of fee -
|
|
2710
|
-
type: 'kit' | 'provider';
|
|
3908
|
+
/** The type of fee - from the bridge kit, provider (CCTP), or forwarder (Circle Orbit relayer) */
|
|
3909
|
+
type: 'kit' | 'provider' | 'forwarder';
|
|
2711
3910
|
/** The token in which the fee is charged (currently only USDC) */
|
|
2712
3911
|
token: 'USDC';
|
|
2713
3912
|
/** The fee amount (as a string to avoid precision issues) */
|
|
@@ -2857,19 +4056,38 @@ interface CustomFee {
|
|
|
2857
4056
|
* have access to both the source and destination chain information needed for
|
|
2858
4057
|
* validation and execution.
|
|
2859
4058
|
*
|
|
4059
|
+
* The destination adapter (`to`) is optional to support forwarder-only destinations
|
|
4060
|
+
* where Circle's Orbit relayer handles the mint transaction without requiring a
|
|
4061
|
+
* destination adapter. When `to` is undefined, the retry operation relies on
|
|
4062
|
+
* IRIS API confirmation instead of on-chain transaction confirmation.
|
|
4063
|
+
*
|
|
2860
4064
|
* @example
|
|
2861
4065
|
* ```typescript
|
|
4066
|
+
* // Standard retry with both adapters
|
|
2862
4067
|
* const retryContext: RetryContext = {
|
|
2863
|
-
* from:
|
|
2864
|
-
* to:
|
|
4068
|
+
* from: sourceAdapter,
|
|
4069
|
+
* to: destAdapter
|
|
4070
|
+
* }
|
|
4071
|
+
*
|
|
4072
|
+
* // Forwarder-only retry (no destination adapter)
|
|
4073
|
+
* const forwarderRetryContext: RetryContext = {
|
|
4074
|
+
* from: sourceAdapter,
|
|
4075
|
+
* to: undefined // Forwarder handles mint
|
|
2865
4076
|
* }
|
|
2866
4077
|
* ```
|
|
2867
4078
|
*/
|
|
2868
4079
|
interface RetryContext<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
|
|
2869
4080
|
/** The source adapter context for the retry operation */
|
|
2870
4081
|
from: Adapter<TFromAdapterCapabilities>;
|
|
2871
|
-
/**
|
|
2872
|
-
|
|
4082
|
+
/**
|
|
4083
|
+
* The destination adapter context for the retry operation.
|
|
4084
|
+
*
|
|
4085
|
+
* Optional for forwarder-only destinations where Circle's Orbit relayer
|
|
4086
|
+
* handles the mint transaction. When undefined, the retry operation relies
|
|
4087
|
+
* on IRIS API confirmation (`forwardState === 'CONFIRMED'`) instead of
|
|
4088
|
+
* on-chain transaction confirmation via the adapter.
|
|
4089
|
+
*/
|
|
4090
|
+
to?: Adapter<TToAdapterCapabilities>;
|
|
2873
4091
|
}
|
|
2874
4092
|
/**
|
|
2875
4093
|
* Result of analyzing bridge steps to determine retry feasibility and continuation point.
|
|
@@ -2966,6 +4184,7 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
|
|
|
2966
4184
|
* @param source - The source chain definition
|
|
2967
4185
|
* @param destination - The destination chain definition
|
|
2968
4186
|
* @param token - The token to transfer (currently only USDC is supported)
|
|
4187
|
+
* @param useForwarder - When `true`, also checks that the route supports forwarding
|
|
2969
4188
|
* @returns `true` if the provider supports this route, `false` otherwise
|
|
2970
4189
|
*
|
|
2971
4190
|
* @example
|
|
@@ -2977,7 +4196,7 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
|
|
|
2977
4196
|
* }
|
|
2978
4197
|
* ```
|
|
2979
4198
|
*/
|
|
2980
|
-
abstract supportsRoute(source: ChainDefinition, destination: ChainDefinition, token: 'USDC'): boolean;
|
|
4199
|
+
abstract supportsRoute(source: ChainDefinition, destination: ChainDefinition, token: 'USDC', useForwarder?: boolean): boolean;
|
|
2981
4200
|
/**
|
|
2982
4201
|
* Executes a cross-chain bridge operation between the specified source and destination chains.
|
|
2983
4202
|
*
|
|
@@ -3098,6 +4317,8 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
|
|
|
3098
4317
|
*
|
|
3099
4318
|
* @param result - The failed bridge result to retry
|
|
3100
4319
|
* @param context - The retry context containing source and destination adapter contexts
|
|
4320
|
+
* @param invocationMeta - Optional invocation metadata for tracing and correlation.
|
|
4321
|
+
* When provided, enables custom traceId, runtime overrides, and caller chain tracking.
|
|
3101
4322
|
* @returns Promise resolving to the retry bridge result
|
|
3102
4323
|
* @throws {Error} If retry is not supported by this provider
|
|
3103
4324
|
*
|
|
@@ -3113,7 +4334,7 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
|
|
|
3113
4334
|
* }
|
|
3114
4335
|
* ```
|
|
3115
4336
|
*/
|
|
3116
|
-
retry<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(result: BridgeResult, context: RetryContext<TFromAdapterCapabilities, TToAdapterCapabilities
|
|
4337
|
+
retry<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(result: BridgeResult, context: RetryContext<TFromAdapterCapabilities, TToAdapterCapabilities>, invocationMeta?: InvocationMeta): Promise<BridgeResult>;
|
|
3117
4338
|
/**
|
|
3118
4339
|
* Analyzes bridge steps to determine retry feasibility and continuation point.
|
|
3119
4340
|
*
|
|
@@ -3286,6 +4507,21 @@ interface AttestationMessage {
|
|
|
3286
4507
|
* The delay reason if the attestation is delayed.
|
|
3287
4508
|
*/
|
|
3288
4509
|
delayReason?: string | null;
|
|
4510
|
+
/**
|
|
4511
|
+
* Forwarding state from Circle's relayer.
|
|
4512
|
+
* Only present when useForwarder was enabled during burn.
|
|
4513
|
+
* @description
|
|
4514
|
+
* - 'PENDING': Relayer is processing the mint
|
|
4515
|
+
* - 'CONFIRMED': Relayer has submitted the mint tx (waiting for finality)
|
|
4516
|
+
* - 'COMPLETE': Relayer has successfully completed the mint tx with finality
|
|
4517
|
+
* - 'FAILED': Relayer failed to process the mint (user may need manual mint)
|
|
4518
|
+
*/
|
|
4519
|
+
forwardState?: 'PENDING' | 'CONFIRMED' | 'COMPLETE' | 'FAILED' | null;
|
|
4520
|
+
/**
|
|
4521
|
+
* Transaction hash of the mint tx submitted by Circle's relayer.
|
|
4522
|
+
* Only present when forwardState is 'CONFIRMED' or 'COMPLETE'.
|
|
4523
|
+
*/
|
|
4524
|
+
forwardTxHash?: string | null;
|
|
3289
4525
|
}
|
|
3290
4526
|
|
|
3291
4527
|
/**
|
|
@@ -3319,6 +4555,66 @@ type BridgeFetchAttestationStep = BridgeStep &
|
|
|
3319
4555
|
data?: undefined;
|
|
3320
4556
|
});
|
|
3321
4557
|
|
|
4558
|
+
/**
|
|
4559
|
+
* Forwarder-only destination for CCTP v2 transfers without an adapter.
|
|
4560
|
+
*
|
|
4561
|
+
* Used when Circle's Forwarder handles the mint transaction and no destination
|
|
4562
|
+
* adapter is available. Requires both `useForwarder: true` and a `recipientAddress`.
|
|
4563
|
+
*
|
|
4564
|
+
* When using this destination type:
|
|
4565
|
+
* - The mint step completes when the IRIS API confirms `forwardState === 'CONFIRMED'`
|
|
4566
|
+
* - No on-chain transaction confirmation is performed (no adapter available)
|
|
4567
|
+
* - The mint step's `data` field will be undefined (no transaction receipt)
|
|
4568
|
+
*/
|
|
4569
|
+
interface CCTPV2ForwarderOnlyDestination<TChainDefinition extends ChainDefinitionWithCCTPv2 = ChainDefinitionWithCCTPv2> {
|
|
4570
|
+
/** The destination chain where USDC will be minted */
|
|
4571
|
+
chain: TChainDefinition;
|
|
4572
|
+
/** The recipient address that will receive the minted USDC */
|
|
4573
|
+
recipientAddress: string;
|
|
4574
|
+
/** Must be true for forwarder-only destinations */
|
|
4575
|
+
useForwarder: true;
|
|
4576
|
+
/** The resolved address (same as recipientAddress for forwarder-only) */
|
|
4577
|
+
address?: string;
|
|
4578
|
+
}
|
|
4579
|
+
/**
|
|
4580
|
+
* Destination context for CCTP v2 transfers with optional forwarder support.
|
|
4581
|
+
*
|
|
4582
|
+
* Supports two modes:
|
|
4583
|
+
* 1. **With adapter**: Standard destination where user or forwarder submits mint transaction.
|
|
4584
|
+
* The adapter is used for chain validation and transaction confirmation.
|
|
4585
|
+
* 2. **Forwarder-only**: No adapter provided. Circle's Orbit relayer handles the mint
|
|
4586
|
+
* and confirmation is based on IRIS API response only.
|
|
4587
|
+
*
|
|
4588
|
+
* @example
|
|
4589
|
+
* ```typescript
|
|
4590
|
+
* // With adapter (standard or forwarder-assisted)
|
|
4591
|
+
* const dest1: CCTPV2DestinationContext = {
|
|
4592
|
+
* adapter,
|
|
4593
|
+
* chain: BaseSepolia,
|
|
4594
|
+
* address: '0x...',
|
|
4595
|
+
* useForwarder: true // optional
|
|
4596
|
+
* }
|
|
4597
|
+
*
|
|
4598
|
+
* // Forwarder-only (no adapter)
|
|
4599
|
+
* const dest2: CCTPV2DestinationContext = {
|
|
4600
|
+
* chain: BaseSepolia,
|
|
4601
|
+
* recipientAddress: '0x...',
|
|
4602
|
+
* useForwarder: true
|
|
4603
|
+
* }
|
|
4604
|
+
* ```
|
|
4605
|
+
*/
|
|
4606
|
+
type CCTPV2DestinationContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainDefinition extends ChainDefinitionWithCCTPv2 = ChainDefinitionWithCCTPv2> = (DestinationWalletContext<TAdapterCapabilities, TChainDefinition> & {
|
|
4607
|
+
/**
|
|
4608
|
+
* Enable Circle's Forwarder to handle the mint transaction.
|
|
4609
|
+
*
|
|
4610
|
+
* When true, Circle's Orbit relayer will fetch the attestation and submit
|
|
4611
|
+
* the mint transaction on the user's behalf. The relay fee is deducted from
|
|
4612
|
+
* the minted USDC at mint time.
|
|
4613
|
+
*
|
|
4614
|
+
* @defaultValue false
|
|
4615
|
+
*/
|
|
4616
|
+
useForwarder?: boolean;
|
|
4617
|
+
}) | CCTPV2ForwarderOnlyDestination<TChainDefinition>;
|
|
3322
4618
|
/**
|
|
3323
4619
|
* CCTPv2 bridge parameters.
|
|
3324
4620
|
*
|
|
@@ -3332,31 +4628,56 @@ type CCTPV2BridgeParams<TFromAdapterCapabilities extends AdapterCapabilities = A
|
|
|
3332
4628
|
*/
|
|
3333
4629
|
source: WalletContext<TFromAdapterCapabilities, ChainDefinitionWithCCTPv2>;
|
|
3334
4630
|
/**
|
|
3335
|
-
* The destination wallet context containing the chain definition
|
|
4631
|
+
* The destination wallet context containing the chain definition, wallet address,
|
|
4632
|
+
* and optional forwarder configuration.
|
|
3336
4633
|
*/
|
|
3337
|
-
destination:
|
|
4634
|
+
destination: CCTPV2DestinationContext<TToAdapterCapabilities>;
|
|
3338
4635
|
/**
|
|
3339
4636
|
* The bridge configuration for the CCTPv2 transfer.
|
|
3340
4637
|
*/
|
|
3341
4638
|
config: BridgeConfig;
|
|
3342
4639
|
};
|
|
4640
|
+
/**
|
|
4641
|
+
* Base payload structure for CCTP v2 action events.
|
|
4642
|
+
*
|
|
4643
|
+
* @remarks
|
|
4644
|
+
* All CCTP v2 actions share these common fields for protocol identification
|
|
4645
|
+
* and tracing support.
|
|
4646
|
+
*/
|
|
4647
|
+
interface CCTPV2ActionBase {
|
|
4648
|
+
/** The protocol identifier */
|
|
4649
|
+
protocol: 'cctp';
|
|
4650
|
+
/** The protocol version */
|
|
4651
|
+
version: 'v2';
|
|
4652
|
+
/**
|
|
4653
|
+
* Optional trace ID for end-to-end correlation.
|
|
4654
|
+
*
|
|
4655
|
+
* When provided, this ID links all events in a single bridge operation, enabling
|
|
4656
|
+
* integration with distributed tracing systems (OpenTelemetry, Datadog, etc.).
|
|
4657
|
+
*
|
|
4658
|
+
* Format: 32-character hex string or custom string (user-provided via invocation context).
|
|
4659
|
+
*/
|
|
4660
|
+
traceId?: string;
|
|
4661
|
+
}
|
|
3343
4662
|
/**
|
|
3344
4663
|
* Action types supported by the CCTP v2 provider.
|
|
3345
4664
|
*
|
|
3346
4665
|
* @remarks
|
|
3347
4666
|
* This interface defines the structure of actions that can be dispatched during
|
|
3348
|
-
* CCTP v2 transfer operations. Each action includes protocol metadata
|
|
3349
|
-
* `values` field containing the full bridge step
|
|
4667
|
+
* CCTP v2 transfer operations. Each action includes protocol metadata, an optional
|
|
4668
|
+
* `traceId` for correlation, and a `values` field containing the full bridge step
|
|
4669
|
+
* with transaction details.
|
|
3350
4670
|
*
|
|
3351
4671
|
* All transaction-based steps (approve, burn, mint) include `txHash` and
|
|
3352
4672
|
* `explorerUrl` fields for direct links to block explorers.
|
|
3353
4673
|
*
|
|
3354
4674
|
* @example
|
|
3355
4675
|
* ```typescript
|
|
3356
|
-
* // Action structure received by event listeners
|
|
4676
|
+
* // Action structure received by event listeners (with traceId)
|
|
3357
4677
|
* const burnAction: CCTPV2Actions['burn'] = {
|
|
3358
4678
|
* protocol: 'cctp',
|
|
3359
4679
|
* version: 'v2',
|
|
4680
|
+
* traceId: '550e8400-e29b-41d4-a716-446655440000', // optional
|
|
3360
4681
|
* method: 'burn',
|
|
3361
4682
|
* values: {
|
|
3362
4683
|
* name: 'burn',
|
|
@@ -3373,9 +4694,7 @@ interface CCTPV2Actions {
|
|
|
3373
4694
|
* Approval action for CCTP v2 transfers.
|
|
3374
4695
|
* Used to approve token spending before initiating a burn operation.
|
|
3375
4696
|
*/
|
|
3376
|
-
approve: {
|
|
3377
|
-
protocol: 'cctp';
|
|
3378
|
-
version: 'v2';
|
|
4697
|
+
approve: CCTPV2ActionBase & {
|
|
3379
4698
|
method: 'approve';
|
|
3380
4699
|
values: BridgeStep;
|
|
3381
4700
|
};
|
|
@@ -3383,9 +4702,7 @@ interface CCTPV2Actions {
|
|
|
3383
4702
|
* Burn action for CCTP v2 transfers.
|
|
3384
4703
|
* Used to burn tokens on the source chain to initiate a cross-chain transfer.
|
|
3385
4704
|
*/
|
|
3386
|
-
burn: {
|
|
3387
|
-
protocol: 'cctp';
|
|
3388
|
-
version: 'v2';
|
|
4705
|
+
burn: CCTPV2ActionBase & {
|
|
3389
4706
|
method: 'burn';
|
|
3390
4707
|
values: BridgeStep;
|
|
3391
4708
|
};
|
|
@@ -3393,9 +4710,7 @@ interface CCTPV2Actions {
|
|
|
3393
4710
|
* Attestation action for CCTP v2 transfers.
|
|
3394
4711
|
* Used to fetch the attestation message for the source wallet.
|
|
3395
4712
|
*/
|
|
3396
|
-
fetchAttestation: {
|
|
3397
|
-
protocol: 'cctp';
|
|
3398
|
-
version: 'v2';
|
|
4713
|
+
fetchAttestation: CCTPV2ActionBase & {
|
|
3399
4714
|
method: 'fetchAttestation';
|
|
3400
4715
|
values: BridgeFetchAttestationStep;
|
|
3401
4716
|
};
|
|
@@ -3403,9 +4718,7 @@ interface CCTPV2Actions {
|
|
|
3403
4718
|
* Mint action for CCTP v2 transfers.
|
|
3404
4719
|
* Used to mint tokens on the destination chain after a successful burn.
|
|
3405
4720
|
*/
|
|
3406
|
-
mint: {
|
|
3407
|
-
protocol: 'cctp';
|
|
3408
|
-
version: 'v2';
|
|
4721
|
+
mint: CCTPV2ActionBase & {
|
|
3409
4722
|
method: 'mint';
|
|
3410
4723
|
values: BridgeStep;
|
|
3411
4724
|
};
|
|
@@ -3413,9 +4726,7 @@ interface CCTPV2Actions {
|
|
|
3413
4726
|
* Re-attestation action for CCTP v2 transfers.
|
|
3414
4727
|
* Used to request a fresh attestation when the original has expired.
|
|
3415
4728
|
*/
|
|
3416
|
-
reAttest: {
|
|
3417
|
-
protocol: 'cctp';
|
|
3418
|
-
version: 'v2';
|
|
4729
|
+
reAttest: CCTPV2ActionBase & {
|
|
3419
4730
|
method: 'reAttest';
|
|
3420
4731
|
values: BridgeFetchAttestationStep;
|
|
3421
4732
|
};
|
|
@@ -3607,7 +4918,7 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3607
4918
|
* const retryResult = await provider.retry(failedResult, retryContext)
|
|
3608
4919
|
* ```
|
|
3609
4920
|
*/
|
|
3610
|
-
retry<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(result: BridgeResult, context: RetryContext<TFromAdapterCapabilities, TToAdapterCapabilities
|
|
4921
|
+
retry<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(result: BridgeResult, context: RetryContext<TFromAdapterCapabilities, TToAdapterCapabilities>, invocationMeta?: InvocationMeta): Promise<BridgeResult>;
|
|
3611
4922
|
/**
|
|
3612
4923
|
* Estimate the cost and fees for a CCTP v2 cross-chain bridge operation.
|
|
3613
4924
|
*
|
|
@@ -3616,7 +4927,9 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3616
4927
|
* chains, as well as any applicable protocol fees.
|
|
3617
4928
|
*
|
|
3618
4929
|
* @param params - The bridge parameters containing source, destination, amount, and optional config.
|
|
4930
|
+
* Supports optional `invocation` for tracing and correlation.
|
|
3619
4931
|
* @returns Promise resolving to detailed cost breakdown including:
|
|
4932
|
+
* - `traceId`: Correlation ID from invocation context (if provided)
|
|
3620
4933
|
* - `gasFees`: Array of gas estimates for each step (Approve, Burn, Mint)
|
|
3621
4934
|
* - Gas amounts in native token smallest units (wei for ETH, lamports for SOL, etc.)
|
|
3622
4935
|
* - `fees`: Array of protocol and kit fees
|
|
@@ -3627,16 +4940,29 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3627
4940
|
*
|
|
3628
4941
|
* @example
|
|
3629
4942
|
* ```typescript
|
|
4943
|
+
* import {
|
|
4944
|
+
* resolveInvocationContext,
|
|
4945
|
+
* createRuntime,
|
|
4946
|
+
* } from '\@core/runtime'
|
|
4947
|
+
* import { createTokenRegistry } from '\@core/tokens'
|
|
4948
|
+
*
|
|
4949
|
+
* const defaults = {
|
|
4950
|
+
* runtime: createRuntime(),
|
|
4951
|
+
* tokens: createTokenRegistry(),
|
|
4952
|
+
* }
|
|
4953
|
+
*
|
|
3630
4954
|
* const estimate = await provider.estimate({
|
|
3631
4955
|
* source: { adapter: sourceAdapter, chain: 'Ethereum' },
|
|
3632
4956
|
* destination: { adapter: destAdapter, chain: 'Base' },
|
|
3633
4957
|
* amount: '10.50',
|
|
3634
|
-
* token: 'USDC'
|
|
4958
|
+
* token: 'USDC',
|
|
4959
|
+
* invocationMeta: {
|
|
4960
|
+
* callers: [{ type: 'app', name: 'MyDApp', version: '1.0.0' }],
|
|
4961
|
+
* },
|
|
3635
4962
|
* })
|
|
3636
4963
|
*
|
|
3637
|
-
* console.log('Total
|
|
3638
|
-
* console.log('
|
|
3639
|
-
* console.log('Destination gas:', estimate.destinationGas)
|
|
4964
|
+
* console.log('Total gas fees:', estimate.gasFees.length)
|
|
4965
|
+
* console.log('Protocol fees:', estimate.fees.length)
|
|
3640
4966
|
* ```
|
|
3641
4967
|
*/
|
|
3642
4968
|
estimate<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(params: CCTPV2BridgeParams<TFromAdapterCapabilities, TToAdapterCapabilities>): Promise<EstimateResult>;
|
|
@@ -3655,7 +4981,8 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3655
4981
|
*/
|
|
3656
4982
|
private addGasFeeEstimate;
|
|
3657
4983
|
/**
|
|
3658
|
-
* Helper method to add provider fee estimates to the result.
|
|
4984
|
+
* Helper method to add provider and forwarder fee estimates to the result.
|
|
4985
|
+
* Only adds fee entries when the fee is greater than 0.
|
|
3659
4986
|
*/
|
|
3660
4987
|
private addProviderFeeEstimate;
|
|
3661
4988
|
/**
|
|
@@ -3832,10 +5159,14 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3832
5159
|
*
|
|
3833
5160
|
* This method validates that both chains have CCTP v2 contracts deployed and configured.
|
|
3834
5161
|
* It uses the `isCCTPV2Supported` guard function to check each chain individually.
|
|
5162
|
+
* When `useForwarder` is `true`, additionally checks that the source chain supports
|
|
5163
|
+
* forwarding as source and the destination chain supports forwarding as destination.
|
|
3835
5164
|
*
|
|
3836
5165
|
* @param source - The source chain definition to check for CCTP v2 support
|
|
3837
5166
|
* @param destination - The destination chain definition to check for CCTP v2 support
|
|
3838
|
-
* @
|
|
5167
|
+
* @param token - The token to transfer (currently only USDC is supported)
|
|
5168
|
+
* @param useForwarder - When `true`, also checks that the route supports forwarding
|
|
5169
|
+
* @returns `true` if both chains support CCTP v2 (and forwarding if requested), `false` otherwise
|
|
3839
5170
|
*
|
|
3840
5171
|
* @example
|
|
3841
5172
|
* ```typescript
|
|
@@ -3844,19 +5175,30 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3844
5175
|
*
|
|
3845
5176
|
* if (canTransfer) {
|
|
3846
5177
|
* console.log('CCTP v2 transfer is supported between these chains')
|
|
3847
|
-
* }
|
|
3848
|
-
*
|
|
5178
|
+
* }
|
|
5179
|
+
*
|
|
5180
|
+
* const canForward = provider.supportsRoute(Ethereum, Base, 'USDC', true)
|
|
5181
|
+
*
|
|
5182
|
+
* if (canForward) {
|
|
5183
|
+
* console.log('CCTP v2 transfer with forwarding is supported')
|
|
3849
5184
|
* }
|
|
3850
5185
|
* ```
|
|
3851
5186
|
*/
|
|
3852
|
-
supportsRoute(source: ChainDefinition, destination: ChainDefinition, token: 'USDC'): boolean;
|
|
5187
|
+
supportsRoute(source: ChainDefinition, destination: ChainDefinition, token: 'USDC', useForwarder?: boolean): boolean;
|
|
3853
5188
|
/**
|
|
3854
5189
|
* Determines the appropriate maximum fee for a cross-chain bridge operation.
|
|
3855
5190
|
*
|
|
3856
|
-
*
|
|
3857
|
-
* and fast bridge burn fee, or uses a provided maxFee if specified.
|
|
5191
|
+
* The fee calculation depends on transfer speed and forwarding settings:
|
|
3858
5192
|
*
|
|
3859
|
-
*
|
|
5193
|
+
* | Transfer Speed | useForwarder | maxFee provided | Behavior |
|
|
5194
|
+
* |----------------|--------------|-----------------|----------|
|
|
5195
|
+
* | SLOW | false | N/A | maxFee = 0 |
|
|
5196
|
+
* | SLOW | true | No | maxFee = forwardingFee |
|
|
5197
|
+
* | SLOW | true | Yes | maxFee = config.maxFee |
|
|
5198
|
+
* | FAST | false | No | maxFee = calculatedBurnFee |
|
|
5199
|
+
* | FAST | false | Yes | maxFee = config.maxFee |
|
|
5200
|
+
* | FAST | true | No | maxFee = calculatedBurnFee + forwardingFee |
|
|
5201
|
+
* | FAST | true | Yes | maxFee = config.maxFee |
|
|
3860
5202
|
*
|
|
3861
5203
|
* @param params - The bridge parameters object containing:
|
|
3862
5204
|
* - `source`: The source wallet context with chain definition and adapter
|
|
@@ -3882,7 +5224,10 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
3882
5224
|
* console.log('Max fee:', maxFee)
|
|
3883
5225
|
* ```
|
|
3884
5226
|
*/
|
|
3885
|
-
getMaxFee<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(params: BridgeParams<TFromAdapterCapabilities, TToAdapterCapabilities>): Promise<
|
|
5227
|
+
getMaxFee<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(params: BridgeParams<TFromAdapterCapabilities, TToAdapterCapabilities>): Promise<{
|
|
5228
|
+
providerFee: bigint;
|
|
5229
|
+
forwarderFee: bigint;
|
|
5230
|
+
}>;
|
|
3886
5231
|
/**
|
|
3887
5232
|
* Prepares a CCTP v2 burn operation to initiate a cross-chain bridge operation.
|
|
3888
5233
|
*
|
|
@@ -3971,6 +5316,29 @@ rawAddress: string,
|
|
|
3971
5316
|
/** The USDC mint address (ignored for EVM chains, required base58 address for Solana) */
|
|
3972
5317
|
mintAddress: string) => Promise<string>;
|
|
3973
5318
|
|
|
5319
|
+
/**
|
|
5320
|
+
* Validates and converts a fee value to bigint.
|
|
5321
|
+
*
|
|
5322
|
+
* This utility performs:
|
|
5323
|
+
* 1. Conversion from string or number to bigint
|
|
5324
|
+
* 2. Validation that the value is non-negative
|
|
5325
|
+
*
|
|
5326
|
+
* @param value - The fee value to validate and convert (string or number)
|
|
5327
|
+
* @param fieldName - The name of the field for error messages
|
|
5328
|
+
* @returns The validated fee as a bigint
|
|
5329
|
+
* @throws {KitError} If the value cannot be converted to bigint or is negative
|
|
5330
|
+
*
|
|
5331
|
+
* @example
|
|
5332
|
+
* ```typescript
|
|
5333
|
+
* const fee = validateAndConvertFee('1000000', 'minimumFee')
|
|
5334
|
+
* console.log(fee) // 1000000n
|
|
5335
|
+
*
|
|
5336
|
+
* const fee2 = validateAndConvertFee(500, 'forwardingFee')
|
|
5337
|
+
* console.log(fee2) // 500n
|
|
5338
|
+
* ```
|
|
5339
|
+
*/
|
|
5340
|
+
declare function validateAndConvertFee(value: number | string, fieldName: string): bigint;
|
|
5341
|
+
|
|
3974
5342
|
/** A block number value that can be provided as bigint, number, or string. */
|
|
3975
5343
|
type BlockNumberInput = bigint | number | string | undefined;
|
|
3976
5344
|
/**
|
|
@@ -4068,5 +5436,5 @@ declare const getBlocksUntilExpiry: (attestation: AttestationMessage, currentBlo
|
|
|
4068
5436
|
*/
|
|
4069
5437
|
declare const isMintFailureRelatedToAttestation: (error: unknown) => boolean;
|
|
4070
5438
|
|
|
4071
|
-
export { CCTPV2BridgingProvider, getBlocksUntilExpiry, getMintRecipientAccount, isAttestationExpired, isMintFailureRelatedToAttestation };
|
|
5439
|
+
export { CCTPV2BridgingProvider, getBlocksUntilExpiry, getMintRecipientAccount, isAttestationExpired, isMintFailureRelatedToAttestation, validateAndConvertFee };
|
|
4072
5440
|
export type { CCTPV2Config };
|