@circle-fin/app-kit 1.15.2 → 1.16.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +5 -2
  3. package/borrow.cjs +28028 -0
  4. package/borrow.cjs.map +1 -0
  5. package/borrow.d.cts +10723 -0
  6. package/borrow.d.mts +10723 -0
  7. package/borrow.d.ts +10723 -0
  8. package/borrow.mjs +28000 -0
  9. package/borrow.mjs.map +1 -0
  10. package/bridge.cjs +1942 -290
  11. package/bridge.d.cts +157 -12
  12. package/bridge.d.mts +157 -12
  13. package/bridge.d.ts +157 -12
  14. package/bridge.mjs +1942 -290
  15. package/chains.cjs +70 -3
  16. package/chains.d.cts +2 -0
  17. package/chains.d.mts +2 -0
  18. package/chains.d.ts +2 -0
  19. package/chains.mjs +70 -3
  20. package/context.cjs +1 -0
  21. package/context.d.cts +157 -12
  22. package/context.d.mts +157 -12
  23. package/context.d.ts +157 -12
  24. package/context.mjs +1 -0
  25. package/earn.cjs +5466 -3459
  26. package/earn.d.cts +1112 -983
  27. package/earn.d.mts +1112 -983
  28. package/earn.d.ts +1112 -983
  29. package/earn.mjs +5466 -3459
  30. package/estimateBridge.cjs +1940 -288
  31. package/estimateBridge.d.cts +157 -12
  32. package/estimateBridge.d.mts +157 -12
  33. package/estimateBridge.d.ts +157 -12
  34. package/estimateBridge.mjs +1940 -288
  35. package/estimateSwap.cjs +8497 -6831
  36. package/estimateSwap.d.cts +157 -12
  37. package/estimateSwap.d.mts +157 -12
  38. package/estimateSwap.d.ts +157 -12
  39. package/estimateSwap.mjs +8498 -6832
  40. package/index.cjs +30741 -18498
  41. package/index.d.cts +22724 -2322
  42. package/index.d.mts +22724 -2322
  43. package/index.d.ts +22724 -2322
  44. package/index.mjs +30682 -18492
  45. package/package.json +17 -7
  46. package/server.cjs +113 -22
  47. package/server.d.cts +10 -9
  48. package/server.d.mts +10 -9
  49. package/server.d.ts +10 -9
  50. package/server.mjs +113 -22
  51. package/swap.cjs +8497 -6831
  52. package/swap.d.cts +157 -12
  53. package/swap.d.mts +157 -12
  54. package/swap.d.ts +157 -12
  55. package/swap.mjs +8498 -6832
  56. package/unifiedBalance.cjs +457 -128
  57. package/unifiedBalance.d.cts +108 -11
  58. package/unifiedBalance.d.mts +108 -11
  59. package/unifiedBalance.d.ts +108 -11
  60. package/unifiedBalance.mjs +457 -128
package/earn.d.ts CHANGED
@@ -551,8 +551,23 @@ interface CCTPXChainConfig {
551
551
  * const contractType: KitContractType = 'bridge' // Valid
552
552
  * const invalidType: KitContractType = 'invalid' // TypeScript error
553
553
  * ```
554
- */
555
- type KitContractType = 'bridge' | 'adapter';
554
+ *
555
+ * @remarks
556
+ * `'senderPreservingBatcher'` carries a stricter requirement than the others,
557
+ * because setting it wrong fails silently rather than loudly. It must name a
558
+ * batching contract that preserves the calling EOA as `msg.sender` in every
559
+ * subcall — on Arc, the `Multicall3From` predeploy, which achieves that
560
+ * through the `CallFrom` precompile. The name is deliberately more specific
561
+ * than "batcher": the ubiquitous Multicall3 at
562
+ * `0xcA11bde05977b3631167028862bE2a173976CA11` has the same ABI and the same
563
+ * selectors but does **not** qualify, since each subcall would arrive as the
564
+ * Multicall3 contract, so a batched `approve` would grant an allowance from
565
+ * the batcher's own balance rather than from the user's — a field named just
566
+ * `batcher` would make that misconfiguration look valid. Leave
567
+ * `senderPreservingBatcher` unset on any chain lacking one; an unset field
568
+ * simply means callers fall back to submitting calls one at a time.
569
+ */
570
+ type KitContractType = 'bridge' | 'adapter' | 'senderPreservingBatcher';
556
571
  /**
557
572
  * Configuration for Gateway v1 contracts.
558
573
  *
@@ -1436,8 +1451,13 @@ type PreparedChainRequest = EvmPreparedChainRequest | SolanaPreparedChainRequest
1436
1451
  * Parameters for preparing an EVM contract execution.
1437
1452
  */
1438
1453
  type EvmPreparedChainRequestParams = {
1439
- /** The type of the prepared execution. */
1440
- type: 'evm';
1454
+ /**
1455
+ * The type of the prepared execution. Optional here because EVM is the
1456
+ * only chain type `Adapter.prepare()` implementations narrow their param
1457
+ * type to in practice — callers that only ever prepare EVM requests can
1458
+ * omit it rather than repeat a discriminator that never varies for them.
1459
+ */
1460
+ type?: 'evm';
1441
1461
  /** The ABI of the contract. */
1442
1462
  abi: Abi | string[];
1443
1463
  /** The address of the contract. */
@@ -2716,6 +2736,57 @@ interface EarnActionMap {
2716
2736
  readonly claimRewards: ExecuteEarnParams;
2717
2737
  }
2718
2738
 
2739
+ /** Permit standards accepted by Borrow Adapter executions. */
2740
+ declare enum BorrowPermitType {
2741
+ /** Tokens must be approved separately. */
2742
+ NONE = 0,
2743
+ /** EIP-2612 permit calldata accompanies the token input. */
2744
+ EIP2612 = 1
2745
+ }
2746
+ /** Token input forwarded by Borrow Kit to the Adapter Contract. */
2747
+ interface BorrowTokenInput {
2748
+ readonly permitType: BorrowPermitType;
2749
+ readonly token: `0x${string}`;
2750
+ readonly amount: bigint;
2751
+ readonly permitCalldata: `0x${string}`;
2752
+ }
2753
+ /** A single instruction in a Circle-signed Borrow execution. */
2754
+ interface BorrowInstruction {
2755
+ readonly target: `0x${string}`;
2756
+ readonly data: `0x${string}`;
2757
+ readonly value: string | bigint;
2758
+ readonly tokenIn: `0x${string}`;
2759
+ readonly amountToApprove: string | bigint;
2760
+ readonly tokenOut: `0x${string}`;
2761
+ readonly minTokenOut: string | bigint;
2762
+ }
2763
+ /** A token recipient in a Circle-signed Borrow execution. */
2764
+ interface BorrowTokenRecipient {
2765
+ readonly token: `0x${string}`;
2766
+ readonly beneficiary: `0x${string}`;
2767
+ }
2768
+ /** Circle-signed Borrow parameters forwarded to the Adapter Contract. */
2769
+ interface BorrowExecutionParams {
2770
+ readonly instructions: readonly BorrowInstruction[];
2771
+ readonly tokens: readonly BorrowTokenRecipient[];
2772
+ readonly execId: string | bigint;
2773
+ readonly deadline: string | bigint;
2774
+ readonly metadata: `0x${string}`;
2775
+ }
2776
+ /** Parameters for a service-signed Borrow Adapter execution. */
2777
+ interface ExecuteBorrowParams extends ActionParameters {
2778
+ readonly executeParams: BorrowExecutionParams;
2779
+ readonly tokenInputs: BorrowTokenInput[];
2780
+ readonly signature: `0x${string}`;
2781
+ }
2782
+ /** Borrow actions supported by EVM adapters. */
2783
+ interface BorrowActionMap {
2784
+ /** Execute a Circle-signed partial loan repayment. */
2785
+ readonly repay: ExecuteBorrowParams;
2786
+ /** Execute a Circle-signed borrow. */
2787
+ readonly execute: ExecuteBorrowParams;
2788
+ }
2789
+
2719
2790
  /**
2720
2791
  * Single instruction to execute within the Adapter Contract.
2721
2792
  *
@@ -3672,6 +3743,8 @@ interface NativeActionMap {
3672
3743
  * @see {@link ActionPayload} for extracting payload types
3673
3744
  */
3674
3745
  interface ActionMap {
3746
+ /** Borrow operations that execute service-signed payloads. */
3747
+ readonly borrow: BorrowActionMap;
3675
3748
  /** CCTP-specific operations with automatic address resolution. */
3676
3749
  readonly cctp: CCTPActionMap;
3677
3750
  /** CCTPx operations (CrossChainTokenService) for cross-chain transfers of registered tokens (Circle-issued or otherwise). */
@@ -3691,6 +3764,7 @@ interface ActionMap {
3691
3764
  /** Earn operations that execute service-signed payloads via the adapter contract. */
3692
3765
  readonly earn: EarnActionMap;
3693
3766
  }
3767
+
3694
3768
  /**
3695
3769
  * Determine if a type represents an action parameter object (leaf node).
3696
3770
  *
@@ -5578,1209 +5652,1274 @@ interface InvocationMeta {
5578
5652
  }
5579
5653
 
5580
5654
  /**
5581
- * Transfer speed options for cross-chain operations.
5655
+ * Type definitions for the Amount system.
5582
5656
  *
5583
- * Defines the available speed modes for CCTPv2 transfers, affecting
5584
- * both transfer time and potential fee implications.
5657
+ * @remarks
5658
+ * This module defines the core types for type-safe token amount handling.
5659
+ * Amounts are immutable value objects that carry the raw bigint value
5660
+ * and decimal precision. Token identity (symbol, address) is managed
5661
+ * separately by the token registry.
5662
+ *
5663
+ * @packageDocumentation
5585
5664
  */
5586
- declare enum TransferSpeed {
5587
- /** Fast burn mode - reduces transfer time but may have different fee implications */
5588
- FAST = "FAST",
5589
- /** Standard burn mode - normal transfer time with standard fees */
5590
- SLOW = "SLOW"
5591
- }
5592
5665
  /**
5593
- * Context object representing a wallet and signing authority on a specific blockchain network.
5594
- *
5595
- * Combines a wallet or contract address, the blockchain it resides on, and the adapter (signer)
5596
- * responsible for authorizing transactions. Used to specify the source or destination in cross-chain
5597
- * transfer operations.
5666
+ * An immutable token amount value.
5598
5667
  *
5599
5668
  * @remarks
5600
- * The `adapter` (signer) and `address` do not always have to belong to the same entity. For example,
5601
- * in minting or withdrawal scenarios, the signing adapter may authorize a transaction that credits
5602
- * funds to a different recipient address. This context is essential for cross-chain operations,
5603
- * ensuring that both the address and the associated adapter are correctly paired with the intended
5604
- * blockchain, but not necessarily with each other.
5669
+ * Amounts are pure numeric value objects containing the raw bigint value
5670
+ * (in smallest units) and decimal precision. They are immutable - all
5671
+ * math operations return new Amount instances.
5672
+ *
5673
+ * Token identity (symbol, contract address) is intentionally NOT included.
5674
+ * This separation ensures developers explicitly source token metadata from
5675
+ * the token registry, preventing incorrect symbol display.
5605
5676
  *
5606
5677
  * @example
5607
5678
  * ```typescript
5608
- * import type { WalletContext } from '@core/provider'
5609
- * import { adapter, blockchain } from './setup'
5610
- *
5611
- * const wallet: WalletContext = {
5612
- * adapter,
5613
- * address: '0x1234...abcd',
5614
- * chain: blockchain,
5679
+ * const amount: Amount = {
5680
+ * raw: 1_000_000n, // 1 token in smallest units (e.g., 1 USDC)
5681
+ * decimals: 6,
5615
5682
  * }
5616
5683
  * ```
5617
5684
  */
5618
- interface WalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
5619
- /**
5620
- * The chain definition type to use for the wallet context.
5621
- *
5622
- * @defaultValue ChainDefinition
5623
- */
5624
- TChainDefinition extends ChainDefinition = ChainDefinition> {
5625
- /**
5626
- * The adapter (signer) for the wallet on the specified chain.
5627
- *
5628
- * Responsible for authorizing transactions and signing messages on behalf of the wallet or
5629
- * for a different recipient, depending on the use case.
5630
- */
5631
- adapter: Adapter<TAdapterCapabilities>;
5685
+ interface Amount$1 {
5632
5686
  /**
5633
- * The wallet or contract address.
5634
- *
5635
- * Must be a valid address format for the specified blockchain. May differ from the adapter's
5636
- * own address in scenarios such as relayed transactions or third-party minting.
5687
+ * The raw value in smallest units (e.g., wei for ETH, micro-units for USDC).
5637
5688
  */
5638
- address: string;
5689
+ readonly raw: bigint;
5639
5690
  /**
5640
- * The blockchain network where the wallet or contract address resides.
5691
+ * Number of decimal places for this token.
5641
5692
  *
5642
- * Determines the context and format for the address and adapter.
5693
+ * @remarks
5694
+ * Common values:
5695
+ * - USDC/USDT: 6
5696
+ * - ETH/ERC-20: 18
5643
5697
  */
5644
- chain: TChainDefinition;
5698
+ readonly decimals: number;
5645
5699
  }
5646
5700
  /**
5647
- * Wallet context for bridge destinations with optional custom recipient.
5648
- *
5649
- * Extends WalletContext to support scenarios where the recipient address
5650
- * differs from the signer address (e.g., bridging to a third-party wallet).
5651
- * The signer address is used for transaction authorization, while the
5652
- * recipient address specifies where the minted funds should be sent.
5653
- *
5654
- * @typeParam TAdapterCapabilities - The adapter capabilities type to use for the wallet context.
5655
- * @typeParam TChainDefinition - The chain definition type to use for the wallet context.
5656
- *
5657
- * @example
5658
- * ```typescript
5659
- * import type { DestinationWalletContext } from '@core/provider'
5660
- * import { adapter, blockchain } from './setup'
5701
+ * Configuration for creating amounts.
5661
5702
  *
5662
- * // Bridge to a custom recipient address
5663
- * const destination: DestinationWalletContext = {
5664
- * adapter,
5665
- * address: '0x1234...abcd', // Signer address
5666
- * chain: blockchain,
5667
- * recipientAddress: '0x9876...fedc' // Custom recipient
5668
- * }
5669
- * ```
5703
+ * @remarks
5704
+ * Specifies the decimal precision for the amount. Typically obtained
5705
+ * from the token registry.
5670
5706
  */
5671
- interface DestinationWalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
5707
+ interface AmountConfig {
5708
+ /**
5709
+ * Number of decimal places.
5710
+ */
5711
+ decimals: number;
5712
+ }
5672
5713
  /**
5673
- * The chain definition type to use for the wallet context.
5674
- *
5675
- * @defaultValue ChainDefinition
5714
+ * Options for formatting amounts as human-readable strings.
5676
5715
  */
5677
- TChainDefinition extends ChainDefinition = ChainDefinition> extends WalletContext<TAdapterCapabilities, TChainDefinition> {
5716
+ interface FormatOptions {
5678
5717
  /**
5679
- * Optional custom recipient address for minted funds.
5680
- *
5681
- * When provided, minted tokens will be sent to this address instead of
5682
- * the address specified in the wallet context. The wallet context address
5683
- * is still used for transaction signing and authorization.
5718
+ * Locale for number formatting.
5684
5719
  *
5685
- * Must be a valid address format for the specified blockchain.
5720
+ * @defaultValue 'en-US'
5686
5721
  */
5687
- recipientAddress?: string;
5722
+ locale?: string;
5688
5723
  /**
5689
- * Whether Circle's relayer submits the destination transaction.
5724
+ * Minimum fraction digits to display.
5690
5725
  *
5691
- * How an omitted value resolves, and whether an explicit `false` is accepted,
5692
- * is provider-specific.
5726
+ * @defaultValue 0
5693
5727
  */
5694
- useForwarder?: boolean;
5728
+ minimumFractionDigits?: number;
5695
5729
  /**
5696
- * Optional destination dApp deposit action for a fast cross-chain transfer.
5730
+ * Maximum fraction digits to display.
5697
5731
  *
5698
- * When set, the burned USDC is minted to Circle's GenericExecutor on the
5699
- * destination chain, which calls the registered dApp (for example, a Gateway
5700
- * `depositFor`) in the same relayed flow. Consumed by the CCTP v2 provider's
5701
- * executor-deposit path; requires `useForwarder: true`.
5732
+ * @defaultValue decimals
5733
+ */
5734
+ maximumFractionDigits?: number;
5735
+ /**
5736
+ * Use grouping separators (e.g., 1,000,000).
5702
5737
  *
5703
- * @see {@link BridgeDepositAction}
5738
+ * @defaultValue true
5704
5739
  */
5705
- deposit?: BridgeDepositAction;
5740
+ useGrouping?: boolean;
5706
5741
  }
5707
5742
  /**
5708
- * Destination dApp deposit action for a fast cross-chain transfer.
5709
- *
5710
- * When present on a bridge destination, the CCTP v2 provider routes the
5711
- * transfer through Circle's GenericExecutor: the burned USDC is minted to the
5712
- * executor on the destination chain, which then calls the registered dApp (for
5713
- * example, a Gateway `depositFor`) in the same relayed flow. Encoded into
5714
- * executor hookData via `buildDepositForGenericExecutorPayload`.
5715
- *
5716
- * @example
5717
- * ```typescript
5718
- * import type { BridgeDepositAction } from '@core/provider'
5743
+ * Options for parsing human-readable strings to amounts.
5719
5744
  *
5720
- * const deposit: BridgeDepositAction = {
5721
- * dappId: 'gateway_deposit',
5722
- * params: ['0xTokenMessengerWithFees', '0xDepositAccount', 0n],
5723
- * }
5724
- * ```
5745
+ * @remarks
5746
+ * Currently only supports '.' as the decimal separator (en-US style).
5725
5747
  */
5726
- interface BridgeDepositAction {
5748
+ interface ParseOptions {
5727
5749
  /**
5728
- * Registered dApp identifier the GenericExecutor invokes on the destination
5729
- * chain (for example, `'gateway_deposit'`).
5750
+ * Number of decimal places.
5730
5751
  */
5731
- dappId: string;
5752
+ decimals: number;
5732
5753
  /**
5733
- * Positional arguments for the dApp function, in ABI order. Dynamic amount
5734
- * slots are filled in by the executor from the minted amount.
5754
+ * Whether to allow negative values.
5755
+ *
5756
+ * @defaultValue false
5735
5757
  */
5736
- params: readonly unknown[];
5758
+ allowNegative?: boolean;
5737
5759
  }
5738
5760
  /**
5739
- * Parameters for executing a cross-chain bridge operation.
5761
+ * Result of comparing two amounts.
5740
5762
  */
5741
- interface BridgeParams$1<TFromCapabilities extends AdapterCapabilities = AdapterCapabilities, TToCapabilities extends AdapterCapabilities = AdapterCapabilities,
5763
+ type ComparisonResult = -1 | 0 | 1;
5742
5764
  /**
5743
- * The chain definition type to use for the wallet context.
5765
+ * Types that can be converted to an Amount.
5744
5766
  *
5745
- * @defaultValue ChainDefinition
5767
+ * @remarks
5768
+ * - `bigint`: Raw value (requires config with decimals)
5769
+ * - `string`: Human-readable (e.g., "100.50")
5770
+ * - `number`: Human-readable (e.g., 100.5) - beware of precision!
5771
+ * - `Amount`: Existing amount or plain object with Amount shape
5746
5772
  */
5747
- TChainDefinition extends ChainDefinition = ChainDefinition,
5773
+ type AmountLike = bigint | string | number | Amount$1;
5748
5774
  /**
5749
- * The token type the provider accepts.
5750
- *
5751
- * @defaultValue 'USDC'
5775
+ * JSON representation of an Amount.
5752
5776
  *
5753
5777
  * @remarks
5754
- * The default preserves the original USDC-only contract for consumers that
5755
- * omit the token type. Providers that accept a different token type pass
5756
- * `TToken` explicitly.
5778
+ * Used for serialization. The `raw` value is stringified since JSON
5779
+ * does not support bigint natively.
5757
5780
  *
5758
5781
  * @example
5759
5782
  * ```typescript
5760
- * // Default — TToken resolves to 'USDC'
5761
- * type DefaultParams = BridgeParams // params.token is typed as 'USDC'
5762
- *
5763
- * // Provider that identifies tokens by a hex string template literal
5764
- * type HexTokenParams = BridgeParams<
5765
- * AdapterCapabilities,
5766
- * AdapterCapabilities,
5767
- * ChainDefinition,
5768
- * `0x${string}`
5769
- * > // params.token is typed as `0x${string}`
5783
+ * const json: AmountJSON = {
5784
+ * raw: "1500000",
5785
+ * decimals: 6,
5786
+ * formatted: "1.5"
5787
+ * }
5770
5788
  * ```
5771
5789
  */
5772
- TToken extends string = 'USDC'> {
5773
- /** The source adapter containing wallet and chain information */
5774
- source: WalletContext<TFromCapabilities, TChainDefinition>;
5775
- /** The destination adapter containing wallet and chain information */
5776
- destination: DestinationWalletContext<TToCapabilities, TChainDefinition>;
5777
- /** The amount to transfer (as a string to avoid precision issues) */
5778
- amount: string;
5779
- /** The token to transfer (provider-defined; defaults to `'USDC'`) */
5780
- token: TToken;
5781
- /** Bridge configuration (e.g., fast burn settings) */
5782
- config: BridgeConfig;
5783
- /**
5784
- * Optional server-signed quote to reuse, typically the
5785
- * {@link EstimateResult.quote} returned by an earlier `estimate` call.
5786
- *
5787
- * When present and still valid, a provider with a server-signed quote
5788
- * model may reuse it instead of fetching a fresh quote, so the fee the
5789
- * caller was quoted is the fee they pay. Providers decide when a reused
5790
- * quote is still valid (e.g. freshness, fee token, speed); an unusable or
5791
- * mismatched quote is ignored and a fresh one is fetched. Transfer
5792
- * parameters are validated by the provider's on-chain contract, so a quote
5793
- * reused for a different transfer is rejected there rather than silently.
5794
- * Providers without a quote model ignore this field entirely, and do so
5795
- * silently — nothing verifies that a quote reached the provider that issued
5796
- * it, because the route is matched to a provider only after these
5797
- * parameters are validated. A quote is meaningful only on the route that
5798
- * produced it.
5799
- *
5800
- * Typed `unknown`: a caller reaches `bridge` through a provider-agnostic
5801
- * surface, so this shared type names no provider's shape. It is public
5802
- * input in any case, and is validated before any field is read — by the
5803
- * provider that serves the route, or by the kit for routes it prices
5804
- * itself. Treat it as opaque and pass it back unmodified.
5805
- *
5806
- * This is a `bridge` input. A quote is an output of `estimate`, not an
5807
- * input to it — `estimate` always returns a freshly-priced quote, and a
5808
- * provider may reject a quote passed to `estimate` rather than ignore it.
5809
- */
5810
- quote?: unknown;
5811
- /**
5812
- * Optional invocation metadata for tracing and correlation.
5813
- *
5814
- * When provided, the `traceId` is used to correlate all events emitted during
5815
- * the bridge operation. If not provided, an OpenTelemetry-compatible traceId
5816
- * will be auto-generated.
5817
- */
5818
- invocationMeta?: InvocationMeta;
5790
+ interface AmountJSON {
5791
+ /** The raw value as a string (bigint serialized). */
5792
+ raw: string;
5793
+ /** Number of decimal places. */
5794
+ decimals: number;
5795
+ /** Human-readable formatted value. */
5796
+ formatted: string;
5819
5797
  }
5798
+
5820
5799
  /**
5821
- * Configuration options for customizing bridge behavior.
5800
+ * Minimal fields required for internal Amount operations.
5822
5801
  *
5823
5802
  * @remarks
5824
- * This interface is currently incomplete and will be expanded in future versions
5825
- * to include additional configuration options such as slippage tolerance,
5826
- * deadline settings, and other bridge parameters.
5803
+ * This internal type mirrors the public {@link Amount} interface shape but exists
5804
+ * separately to avoid circular dependencies. Internal modules (math, comparison,
5805
+ * formatting) import this lightweight type instead of the full Amount class.
5806
+ *
5807
+ * The Amount class implements this interface, so internal helpers can operate
5808
+ * on either Amount instances or plain objects with the same shape.
5827
5809
  *
5810
+ * @see {@link ../types.ts#Amount} for the public interface
5811
+ * @internal
5828
5812
  */
5829
- interface BridgeConfig {
5813
+ interface AmountFields {
5814
+ readonly raw: bigint;
5815
+ readonly decimals: number;
5816
+ }
5817
+
5818
+ /**
5819
+ * Fluent Amount class for type-safe token amount handling.
5820
+ *
5821
+ * @remarks
5822
+ * The `Amount` class provides an immutable, fluent API for working with token
5823
+ * amounts. It wraps a raw bigint value with decimal precision and provides
5824
+ * chainable methods for math, comparison, and formatting.
5825
+ *
5826
+ * Token identity (symbol, contract address) is intentionally NOT included.
5827
+ * This ensures developers explicitly source token metadata from the token
5828
+ * registry, preventing incorrect symbol display.
5829
+ *
5830
+ * @example
5831
+ * ```typescript
5832
+ * import { Amount } from '@core/amounts'
5833
+ *
5834
+ * // Create from raw value or parse from string
5835
+ * const a = Amount.of(1_000_000n, { decimals: 6 })
5836
+ * const b = Amount.parse('0.5', { decimals: 6 })
5837
+ *
5838
+ * // Fluent operations
5839
+ * const result = a.add(b).mul(2n).sub(Amount.parse('0.25', { decimals: 6 }))
5840
+ *
5841
+ * // Comparisons and formatting
5842
+ * a.gt(b) // true
5843
+ * a.toString() // "1"
5844
+ *
5845
+ * // For display with symbol, combine with token registry:
5846
+ * // `${amount.toString()} ${token.symbol}`
5847
+ * ```
5848
+ *
5849
+ * @packageDocumentation
5850
+ */
5851
+
5852
+ /**
5853
+ * An immutable token amount with fluent API methods.
5854
+ *
5855
+ * @remarks
5856
+ * The `Amount` class provides a type-safe, ergonomic way to work with token
5857
+ * amounts. It combines the raw bigint value with decimal precision and
5858
+ * provides chainable methods for:
5859
+ *
5860
+ * - **Math operations**: add, sub, mul, div, abs, neg
5861
+ * - **Comparisons**: eq, lt, lte, gt, gte, cmp, min, max
5862
+ * - **Predicates**: isZero, isPositive, isNegative
5863
+ * - **Formatting**: formatted, toString, toJSON
5864
+ * - **Conversion**: toDecimals
5865
+ *
5866
+ * All operations return new Amount instances - the class is immutable.
5867
+ *
5868
+ * Token identity (symbol) is intentionally excluded. Source token metadata
5869
+ * from the token registry for display purposes.
5870
+ */
5871
+ declare class Amount implements AmountFields {
5872
+ /** The raw value in smallest units (e.g., wei for ETH, micro-units for USDC). */
5873
+ readonly raw: bigint;
5874
+ /** Number of decimal places for this token. */
5875
+ readonly decimals: number;
5876
+ private constructor();
5830
5877
  /**
5831
- * The transfer speed mode for CCTPv2 transfers.
5878
+ * Create an Amount from a raw bigint value.
5832
5879
  *
5833
- * Controls whether to use fast burn mode (FAST) or standard mode (SLOW).
5834
- * Fast burn may reduce transfer time but could have different fee implications.
5880
+ * @param raw - The raw value in smallest units.
5881
+ * @param config - Configuration with decimals.
5882
+ * @returns A new immutable Amount instance.
5883
+ * @throws KitError If raw is not a bigint or decimals is invalid.
5835
5884
  *
5836
- * @defaultValue TransferSpeed.FAST
5885
+ * @example
5886
+ * ```typescript
5887
+ * // Get decimals from token registry
5888
+ * const amount = Amount.of(1_000_000n, { decimals: 6 })
5889
+ * ```
5837
5890
  */
5838
- transferSpeed?: TransferSpeed | `${TransferSpeed}` | undefined;
5891
+ static of(raw: bigint, config: AmountConfig): Amount;
5839
5892
  /**
5840
- * Enable or disable EIP-5792 batched transaction execution.
5841
- *
5842
- * When `true` (or `undefined` / omitted), the bridge will attempt to batch
5843
- * the approve and burn calls into a single `wallet_sendCalls` request if
5844
- * the connected wallet supports it. Set to `false` to explicitly opt out
5845
- * and always use the sequential approve -> burn flow.
5893
+ * Parse a human-readable string or number into an Amount.
5846
5894
  *
5847
- * @defaultValue `undefined` (batching attempted when the wallet supports it)
5895
+ * @param input - The input to parse (e.g., "100.50" or 100.5).
5896
+ * @param options - Parse options including decimals.
5897
+ * @returns A new immutable Amount instance.
5898
+ * @throws KitError If input is invalid or parsing fails.
5848
5899
  *
5849
5900
  * @example
5850
5901
  * ```typescript
5851
- * const config: BridgeConfig = {
5852
- * batchTransactions: false, // force sequential flow
5853
- * }
5902
+ * const amount = Amount.parse('100.50', { decimals: 6 })
5854
5903
  * ```
5855
5904
  */
5856
- batchTransactions?: boolean | undefined;
5905
+ static parse(input: string | number, options: ParseOptions): Amount;
5857
5906
  /**
5858
- * The maximum fee to pay for the burn operation.
5907
+ * Convert any AmountLike value to an Amount.
5859
5908
  *
5860
- * Provide the amount as a base-10 numeric string representing the
5861
- * token amount in human-readable format. For example: to set a maximum
5862
- * fee of 1 USDC, pass `"1"`. Decimal values are supported (e.g., `"0.5"`
5863
- * for half a USDC).
5909
+ * @param input - The input (bigint, string, number, or existing Amount).
5910
+ * @param config - Configuration (required for non-Amount inputs).
5911
+ * @returns A new immutable Amount instance.
5912
+ * @throws KitError If conversion fails or config is missing.
5864
5913
  *
5865
- * @defaultValue `"0"`
5914
+ * @remarks
5915
+ * When providing a `number` input, very large or small values may be
5916
+ * converted to exponential notation (e.g., `1e21`), which is not supported.
5917
+ * For such values, provide a `string` representation instead.
5866
5918
  *
5867
5919
  * @example
5868
5920
  * ```typescript
5869
- * import type { BridgeConfig, TransferSpeed } from '@core/provider'
5870
- *
5871
- * const config: BridgeConfig = {
5872
- * transferSpeed: TransferSpeed.FAST,
5873
- * maxFee: "1", // 1 USDC maximum fee
5874
- * customFee: {
5875
- * value: "0.5", // 0.5 USDC developer fee
5876
- * recipientAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
5877
- * }
5878
- * }
5921
+ * Amount.from(1_000_000n, { decimals: 6 }) // from bigint
5922
+ * Amount.from('1.00', { decimals: 6 }) // from string
5923
+ * Amount.from(existingAmount) // pass-through
5879
5924
  * ```
5880
5925
  */
5881
- maxFee?: string;
5926
+ static from(input: AmountLike, config?: AmountConfig): Amount;
5882
5927
  /**
5883
- * The custom fee to charge for the transfer.
5928
+ * Create a zero Amount with the given configuration.
5884
5929
  *
5885
- * Whatever value you provide here is **added on top of the transfer amount**. The user must have
5886
- * enough balance for `amount + customFee`, and the wallet signs for that total on the source
5887
- * chain. The custom fee is split automatically:
5930
+ * @param config - Configuration with decimals.
5931
+ * @returns A zero Amount instance.
5888
5932
  *
5889
- * - 10% routes to Circle.
5890
- * - 90% routes to your `recipientAddress`.
5933
+ * @example
5934
+ * ```typescript
5935
+ * const zero = Amount.zero({ decimals: 6 })
5936
+ * ```
5937
+ */
5938
+ static zero(config: AmountConfig): Amount;
5939
+ /**
5940
+ * Check if a value is an Amount-like object.
5891
5941
  *
5892
- * The original transfer amount proceeds through CCTPv2 unchanged, and the protocol fee (1–14 bps
5893
- * in FAST mode, 0% in STANDARD) is taken from that transfer amount.
5942
+ * @param value - The value to check.
5943
+ * @returns True if the value has Amount shape (raw: bigint, decimals: number).
5894
5944
  *
5895
5945
  * @example
5896
5946
  * ```typescript
5897
- * import type { BridgeConfig } from '@core/provider'
5947
+ * Amount.isAmount({ raw: 1000000n, decimals: 6 }) // true
5948
+ * Amount.isAmount({ value: 100 }) // false
5949
+ * ```
5950
+ */
5951
+ static isAmount(value: unknown): value is {
5952
+ raw: bigint;
5953
+ decimals: number;
5954
+ };
5955
+ /**
5956
+ * Sum an array of Amounts.
5898
5957
  *
5899
- * const config: BridgeConfig = {
5900
- * customFee: {
5901
- * value: '5', // 5 USDC developer fee
5902
- * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
5903
- * },
5904
- * }
5958
+ * @param amounts - The amounts to sum (must have same decimals).
5959
+ * @returns A new Amount with the total sum.
5960
+ * @throws KitError If amounts array is empty or decimals don't match.
5905
5961
  *
5906
- * // Fee flow for a 100 USDC transfer with 5 USDC custom fee:
5907
- * // Source chain (Ethereum):
5908
- * // - Wallet debits: 105 USDC total (100 transfer + 5 custom fee)
5909
- * // - Custom fee split: 0.5 USDC (10%) → Circle, 4.5 USDC (90%) → your recipientAddress
5910
- * // - Amount sent to CCTPv2: 100 USDC (unchanged)
5911
- * //
5912
- * // Destination chain (Base):
5913
- * // - CCTPv2 FAST fee (example: 1 bps): ~0.01 USDC deducted
5914
- * // - User receives: ~99.99 USDC
5915
- * //
5916
- * // Note: Actual CCTP fees vary by route (1-14 bps for FAST, 0 bps for STANDARD)
5962
+ * @example
5963
+ * ```typescript
5964
+ * const fee1 = Amount.parse('0.10', { decimals: 6 })
5965
+ * const fee2 = Amount.parse('0.25', { decimals: 6 })
5966
+ * const fee3 = Amount.parse('0.15', { decimals: 6 })
5967
+ *
5968
+ * const total = Amount.sum([fee1, fee2, fee3])
5969
+ * total.toString() // "0.5"
5917
5970
  * ```
5918
5971
  */
5919
- customFee?: CustomFee | undefined;
5972
+ static sum(amounts: readonly Amount[]): Amount;
5920
5973
  /**
5921
- * Which leg pays the protocol fee.
5974
+ * Deserialize an Amount from a JSON object.
5922
5975
  *
5923
- * `'source'` leaves the delivered amount unreduced; `'destination'` takes the
5924
- * fee from it. Omit it to let the routed provider decide — a provider rejects
5925
- * a value it cannot honour.
5976
+ * @param json - The JSON object (e.g., from `JSON.parse()`).
5977
+ * @returns A new Amount instance.
5978
+ * @throws KitError If the JSON structure is invalid.
5979
+ *
5980
+ * @example
5981
+ * ```typescript
5982
+ * const json = JSON.parse('{"raw":"1500000","decimals":6}')
5983
+ * const amount = Amount.fromJSON(json)
5984
+ * ```
5926
5985
  */
5927
- feePayment?: 'source' | 'destination' | undefined;
5928
- }
5929
- /**
5930
- * Custom fee configuration charged by the integrator.
5931
- *
5932
- * Use to charge an absolute fee on the source chain in human-readable
5933
- * token amounts.
5934
- *
5935
- * @remarks
5936
- * This is an absolute amount, not a percentage. The `recipientAddress` must be
5937
- * a valid address for the source chain of the transfer.
5938
- *
5939
- * @example
5940
- * ```typescript
5941
- * import type { CustomFee } from '@core/provider'
5942
- *
5943
- * const config: CustomFee = {
5944
- * value: '1', // 1 USDC
5945
- * recipientAddress: '0x1234567890123456789012345678901234567890',
5946
- * }
5947
- * ```
5948
- */
5949
- interface CustomFee {
5986
+ static fromJSON(json: unknown): Amount;
5950
5987
  /**
5951
- * The absolute fee to charge for the transfer.
5988
+ * Compare this Amount with another.
5952
5989
  *
5953
- * Provide the amount as a base-10 numeric string representing the token
5954
- * amount in human-readable format. For example: to charge 1 USDC, pass
5955
- * `"1"`. Decimal values are supported (e.g., `"0.5"` for half a USDC).
5956
- * This is not a percentage.
5990
+ * @param other - The Amount to compare with.
5991
+ * @returns -1 if this is less than other, 0 if equal, 1 if this is greater.
5992
+ * @throws KitError If amounts have different decimals.
5957
5993
  *
5958
- * Note: passing `"0"` results in no fee being charged.
5994
+ * @example
5995
+ * ```typescript
5996
+ * const a = Amount.parse('1.5', { decimals: 6 })
5997
+ * const b = Amount.parse('2.0', { decimals: 6 })
5998
+ * a.compare(b) // -1
5999
+ * ```
5959
6000
  */
5960
- value?: string | undefined;
6001
+ compare(other: Amount): ComparisonResult;
5961
6002
  /**
5962
- * The fee recipient for the bridge transfer.
5963
- *
5964
- * This is the address that will receive the fee on the source chain of the
5965
- * bridge transfer. The fee recipient address **must be a valid address for
5966
- * the source chain** of the bridge transfer.
6003
+ * Check if this Amount equals another.
5967
6004
  *
5968
- * @remarks
5969
- * Circle automatically receives 10% of every custom fee; the remaining 90% is
5970
- * sent to this `recipientAddress`.
6005
+ * @param other - The Amount to compare with.
6006
+ * @returns True if the raw values are equal.
6007
+ * @throws KitError If amounts have different decimals.
5971
6008
  *
5972
- * For example: if bridging from Ethereum to Solana, pass an EVM address like
5973
- * `"0x1234567890123456789012345678901234567890"` because the source chain
5974
- * is Ethereum.
6009
+ * @example
6010
+ * ```typescript
6011
+ * const a = Amount.parse('1.5', { decimals: 6 })
6012
+ * const b = Amount.parse('1.5', { decimals: 6 })
6013
+ * a.eq(b) // true
6014
+ * ```
5975
6015
  */
5976
- recipientAddress?: string | undefined;
5977
- }
5978
- /**
5979
- * Represents the context of an adapter used for cross-chain operations.
5980
- *
5981
- * An AdapterContext must always specify both the adapter and the chain explicitly.
5982
- * The address field behavior is determined by the adapter's address control model:
5983
- *
5984
- * - **Developer-controlled adapters**: The `address` field is required because
5985
- * each operation must explicitly specify which address to use.
5986
- * - **User-controlled adapters**: The `address` field is forbidden because
5987
- * the address is automatically resolved from the connected wallet or signer.
5988
- * - **Legacy adapters**: The `address` field remains optional for backward compatibility.
5989
- *
5990
- * This ensures clear, debuggable code where the intended chain is always visible at the call site,
5991
- * and address requirements are enforced at compile time based on adapter capabilities.
5992
- *
5993
- * @typeParam TAdapterCapabilities - The adapter capabilities type to derive address requirements from
5994
- * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
5995
- *
5996
- * @example
5997
- * ```typescript
5998
- * // Developer-controlled adapter (address required)
5999
- * const devContext: AdapterContext<{ addressContext: 'developer-controlled', supportedChains: [] }> = {
6000
- * adapter: myDevAdapter,
6001
- * chain: 'Ethereum',
6002
- * address: '0x123...' // Required
6003
- * }
6004
- *
6005
- * // User-controlled adapter (address forbidden)
6006
- * const userContext: AdapterContext<{ addressContext: 'user-controlled', supportedChains: [] }> = {
6007
- * adapter: myUserAdapter,
6008
- * chain: 'Ethereum'
6009
- * // address: '0x123...' // TypeScript error: not allowed
6010
- * }
6011
- * ```
6012
- */
6013
- type AdapterContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> = {
6014
- /** The adapter instance for blockchain operations */
6015
- adapter: Adapter<TAdapterCapabilities>;
6016
- /** The chain reference, which can be a ChainDefinition, Blockchain enum, or string literal */
6017
- chain: TChainIdentifier;
6018
- } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
6019
- /**
6020
- * Represents a bridge destination with an explicit custom recipient address.
6021
- *
6022
- * Extends {@link AdapterContext} with an additional `recipientAddress` field to specify
6023
- * a custom recipient that differs from the adapter's address. Use this when bridging to
6024
- * third-party wallets or smart contracts rather than the default address associated with
6025
- * the destination adapter.
6026
- *
6027
- * @typeParam TCapabilities - The adapter capabilities type for the destination adapter
6028
- * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6029
- *
6030
- * @remarks
6031
- * The `recipientAddress` must be a valid address format for the destination chain
6032
- * specified in the adapter context. The bridge provider validates address compatibility
6033
- * during the transfer preparation phase and will throw an error if the address format
6034
- * is invalid for the target chain.
6035
- *
6036
- * @example
6037
- * ```typescript
6038
- * import { BridgeDestinationWithAddress } from '@core/provider'
6039
- * import { ethereumAdapter } from './adapters'
6040
- *
6041
- * // Bridge to a custom recipient address on Ethereum
6042
- * const destination: BridgeDestinationWithAddress = {
6043
- * adapter: ethereumAdapter,
6044
- * chain: 'Ethereum',
6045
- * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
6046
- * }
6047
- * ```
6048
- */
6049
- type BridgeDestinationWithAddress<TCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> = AdapterContext<TCapabilities, TChainIdentifier> & {
6016
+ eq(other: Amount): boolean;
6050
6017
  /**
6051
- * The custom recipient address on the destination chain.
6018
+ * Check if this Amount is less than another.
6052
6019
  *
6053
- * Must be a valid address format for the chain specified in this adapter context.
6054
- * This address will receive the bridged funds instead of the adapter's default address.
6020
+ * @param other - The Amount to compare with.
6021
+ * @returns True if this.raw is less than other.raw.
6022
+ * @throws KitError If amounts have different decimals.
6023
+ *
6024
+ * @example
6025
+ * ```typescript
6026
+ * const a = Amount.parse('1.0', { decimals: 6 })
6027
+ * const b = Amount.parse('2.0', { decimals: 6 })
6028
+ * a.lt(b) // true
6029
+ * ```
6055
6030
  */
6056
- recipientAddress: string;
6057
- };
6058
- /**
6059
- * Forwarder-only destination without an adapter.
6060
- *
6061
- * Used when Circle's Forwarder handles the mint transaction and no destination
6062
- * adapter is available. Requires both `useForwarder: true` and a `recipientAddress`.
6063
- *
6064
- * When using this destination type:
6065
- * - The mint step completes when the IRIS API confirms `forwardState === 'CONFIRMED'`
6066
- * - No on-chain transaction confirmation is performed (no adapter available)
6067
- * - The mint step's `data` field will be undefined (no transaction receipt)
6068
- *
6069
- * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6070
- *
6071
- * @example
6072
- * ```typescript
6073
- * // Forwarder-only destination (no adapter needed)
6074
- * const dest: ForwarderDestination = {
6075
- * chain: 'Base',
6076
- * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
6077
- * useForwarder: true
6078
- * }
6079
- * ```
6080
- */
6081
- interface ForwarderDestination<TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> {
6082
- /** The destination chain where USDC will be minted */
6083
- chain: TChainIdentifier;
6084
- /** The recipient address that will receive the minted USDC */
6085
- recipientAddress: string;
6086
- /** Must be true for forwarder-only destinations */
6087
- useForwarder: true;
6088
- }
6089
- /**
6090
- * Union type representing a bridge destination.
6091
- *
6092
- * Supports multiple destination configurations:
6093
- * - {@link AdapterContext}: Standard destination with adapter (for default recipient)
6094
- * - {@link BridgeDestinationWithAddress}: Destination with adapter and custom recipient
6095
- * - {@link ForwarderDestination}: Forwarder-only destination without adapter (requires recipientAddress)
6096
- *
6097
- * When `useForwarder` is enabled with an adapter, Circle's Orbit relayer handles the mint
6098
- * transaction and the adapter is used to wait for transaction confirmation.
6099
- *
6100
- * When `useForwarder` is enabled without an adapter (ForwarderDestination), the mint step
6101
- * completes when the IRIS API confirms `forwardState === 'CONFIRMED'` without on-chain
6102
- * confirmation.
6103
- *
6104
- * @typeParam TAdapterCapabilities - The adapter capabilities type for the destination adapter
6105
- * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6106
- *
6107
- * @example
6108
- * ```typescript
6109
- * // Standard destination with adapter
6110
- * const dest1: BridgeDestination = { adapter, chain: 'Base' }
6111
- *
6112
- * // Destination with adapter and custom recipient
6113
- * const dest2: BridgeDestination = { adapter, chain: 'Base', recipientAddress: '0x...' }
6114
- *
6115
- * // Destination with forwarder enabled (adapter for tx confirmation)
6116
- * const dest3: BridgeDestination = { adapter, chain: 'Base', useForwarder: true }
6117
- *
6118
- * // Forwarder-only destination (no adapter, requires recipientAddress)
6119
- * const dest4: BridgeDestination = { chain: 'Base', useForwarder: true, recipientAddress: '0x...' }
6120
- * ```
6121
- */
6122
- type BridgeDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> = ((AdapterContext<TAdapterCapabilities, TChainIdentifier> | BridgeDestinationWithAddress<TAdapterCapabilities, TChainIdentifier>) & {
6031
+ lt(other: Amount): boolean;
6123
6032
  /**
6124
- * Enable Circle's relayer to submit the destination transaction.
6033
+ * Check if this Amount is less than or equal to another.
6125
6034
  *
6126
- * Where the relay fee is charged depends on the route and on
6127
- * {@link BridgeConfig.feePayment}: it may be taken from the amount that
6128
- * arrives, or priced into a quote the source transaction pays.
6035
+ * @param other - The Amount to compare with.
6036
+ * @returns True if this.raw is less than or equal to other.raw.
6037
+ * @throws KitError If amounts have different decimals.
6129
6038
  *
6130
- * Whether the option is required, optional, or refused depends on the
6131
- * routed provider and the rest of the config.
6132
- */
6133
- useForwarder?: boolean;
6134
- }) | ForwarderDestination<TChainIdentifier>;
6135
-
6136
- /**
6137
- * Type definitions for the Amount system.
6138
- *
6139
- * @remarks
6140
- * This module defines the core types for type-safe token amount handling.
6141
- * Amounts are immutable value objects that carry the raw bigint value
6142
- * and decimal precision. Token identity (symbol, address) is managed
6143
- * separately by the token registry.
6144
- *
6145
- * @packageDocumentation
6146
- */
6147
- /**
6148
- * An immutable token amount value.
6149
- *
6150
- * @remarks
6151
- * Amounts are pure numeric value objects containing the raw bigint value
6152
- * (in smallest units) and decimal precision. They are immutable - all
6153
- * math operations return new Amount instances.
6154
- *
6155
- * Token identity (symbol, contract address) is intentionally NOT included.
6156
- * This separation ensures developers explicitly source token metadata from
6157
- * the token registry, preventing incorrect symbol display.
6158
- *
6159
- * @example
6160
- * ```typescript
6161
- * const amount: Amount = {
6162
- * raw: 1_000_000n, // 1 token in smallest units (e.g., 1 USDC)
6163
- * decimals: 6,
6164
- * }
6165
- * ```
6166
- */
6167
- interface Amount$1 {
6168
- /**
6169
- * The raw value in smallest units (e.g., wei for ETH, micro-units for USDC).
6039
+ * @example
6040
+ * ```typescript
6041
+ * const a = Amount.parse('1.5', { decimals: 6 })
6042
+ * const b = Amount.parse('1.5', { decimals: 6 })
6043
+ * a.lte(b) // true
6044
+ * ```
6170
6045
  */
6171
- readonly raw: bigint;
6046
+ lte(other: Amount): boolean;
6172
6047
  /**
6173
- * Number of decimal places for this token.
6048
+ * Check if this Amount is greater than another.
6174
6049
  *
6175
- * @remarks
6176
- * Common values:
6177
- * - USDC/USDT: 6
6178
- * - ETH/ERC-20: 18
6050
+ * @param other - The Amount to compare with.
6051
+ * @returns True if this.raw is greater than other.raw.
6052
+ * @throws KitError If amounts have different decimals.
6053
+ *
6054
+ * @example
6055
+ * ```typescript
6056
+ * const a = Amount.parse('2.0', { decimals: 6 })
6057
+ * const b = Amount.parse('1.0', { decimals: 6 })
6058
+ * a.gt(b) // true
6059
+ * ```
6179
6060
  */
6180
- readonly decimals: number;
6181
- }
6182
- /**
6183
- * Configuration for creating amounts.
6184
- *
6185
- * @remarks
6186
- * Specifies the decimal precision for the amount. Typically obtained
6187
- * from the token registry.
6188
- */
6189
- interface AmountConfig {
6061
+ gt(other: Amount): boolean;
6190
6062
  /**
6191
- * Number of decimal places.
6063
+ * Check if this Amount is greater than or equal to another.
6064
+ *
6065
+ * @param other - The Amount to compare with.
6066
+ * @returns True if this.raw is greater than or equal to other.raw.
6067
+ * @throws KitError If amounts have different decimals.
6068
+ *
6069
+ * @example
6070
+ * ```typescript
6071
+ * const a = Amount.parse('2.0', { decimals: 6 })
6072
+ * const b = Amount.parse('2.0', { decimals: 6 })
6073
+ * a.gte(b) // true
6074
+ * ```
6192
6075
  */
6193
- decimals: number;
6194
- }
6195
- /**
6196
- * Options for formatting amounts as human-readable strings.
6197
- */
6198
- interface FormatOptions {
6076
+ gte(other: Amount): boolean;
6199
6077
  /**
6200
- * Locale for number formatting.
6078
+ * Return the minimum of this Amount and another.
6201
6079
  *
6202
- * @defaultValue 'en-US'
6080
+ * @param other - The Amount to compare with.
6081
+ * @returns The smaller of the two amounts.
6082
+ * @throws KitError If amounts have different decimals.
6083
+ *
6084
+ * @example
6085
+ * ```typescript
6086
+ * const a = Amount.parse('1.0', { decimals: 6 })
6087
+ * const b = Amount.parse('2.0', { decimals: 6 })
6088
+ * a.min(b).toString() // "1"
6089
+ * ```
6203
6090
  */
6204
- locale?: string;
6091
+ min(other: Amount): Amount;
6205
6092
  /**
6206
- * Minimum fraction digits to display.
6093
+ * Return the maximum of this Amount and another.
6207
6094
  *
6208
- * @defaultValue 0
6095
+ * @param other - The Amount to compare with.
6096
+ * @returns The larger of the two amounts.
6097
+ * @throws KitError If amounts have different decimals.
6098
+ *
6099
+ * @example
6100
+ * ```typescript
6101
+ * const a = Amount.parse('1.0', { decimals: 6 })
6102
+ * const b = Amount.parse('2.0', { decimals: 6 })
6103
+ * a.max(b).toString() // "2"
6104
+ * ```
6209
6105
  */
6210
- minimumFractionDigits?: number;
6106
+ max(other: Amount): Amount;
6211
6107
  /**
6212
- * Maximum fraction digits to display.
6108
+ * Add another Amount to this one.
6213
6109
  *
6214
- * @defaultValue decimals
6110
+ * @param other - The Amount to add.
6111
+ * @returns A new Amount with the sum.
6112
+ * @throws KitError If amounts have different decimals.
6113
+ *
6114
+ * @example
6115
+ * ```typescript
6116
+ * const a = Amount.parse('1.5', { decimals: 6 })
6117
+ * const b = Amount.parse('0.5', { decimals: 6 })
6118
+ * a.add(b).toString() // "2"
6119
+ * ```
6215
6120
  */
6216
- maximumFractionDigits?: number;
6121
+ add(other: Amount): Amount;
6217
6122
  /**
6218
- * Use grouping separators (e.g., 1,000,000).
6123
+ * Subtract another Amount from this one.
6219
6124
  *
6220
- * @defaultValue true
6125
+ * @param other - The Amount to subtract.
6126
+ * @returns A new Amount with the difference.
6127
+ * @throws KitError If amounts have different decimals.
6128
+ *
6129
+ * @example
6130
+ * ```typescript
6131
+ * const a = Amount.parse('2.0', { decimals: 6 })
6132
+ * const b = Amount.parse('0.5', { decimals: 6 })
6133
+ * a.sub(b).toString() // "1.5"
6134
+ * ```
6221
6135
  */
6222
- useGrouping?: boolean;
6223
- }
6224
- /**
6225
- * Options for parsing human-readable strings to amounts.
6226
- *
6227
- * @remarks
6228
- * Currently only supports '.' as the decimal separator (en-US style).
6229
- */
6230
- interface ParseOptions {
6136
+ sub(other: Amount): Amount;
6231
6137
  /**
6232
- * Number of decimal places.
6138
+ * Multiply this Amount by a scalar.
6139
+ *
6140
+ * @param multiplier - The scalar to multiply by (bigint or integer number).
6141
+ * @returns A new Amount with the product.
6142
+ *
6143
+ * @remarks
6144
+ * When using a `number` as a multiplier, precision is limited by standard
6145
+ * JavaScript floating-point capabilities (~15-17 significant digits). For
6146
+ * high-precision calculations, provide the multiplier as a `bigint`.
6147
+ *
6148
+ * @example
6149
+ * ```typescript
6150
+ * const a = Amount.parse('1.5', { decimals: 6 })
6151
+ * a.mul(2n).toString() // "3"
6152
+ * a.mul(3).toString() // "4.5"
6153
+ * ```
6233
6154
  */
6234
- decimals: number;
6155
+ mul(multiplier: bigint | number): Amount;
6235
6156
  /**
6236
- * Whether to allow negative values.
6157
+ * Divide this Amount by a scalar.
6237
6158
  *
6238
- * @defaultValue false
6159
+ * @param divisor - The scalar to divide by (bigint or integer number).
6160
+ * @returns A new Amount with the quotient (integer division).
6161
+ * @throws KitError If divisor is zero.
6162
+ *
6163
+ * @remarks
6164
+ * When using a `number` as a divisor, precision is limited by standard
6165
+ * JavaScript floating-point capabilities (~15-17 significant digits). For
6166
+ * high-precision calculations, provide the divisor as a `bigint`.
6167
+ *
6168
+ * @example
6169
+ * ```typescript
6170
+ * const a = Amount.parse('6.0', { decimals: 6 })
6171
+ * a.div(2n).toString() // "3"
6172
+ * a.div(4).toString() // "1.5"
6173
+ * ```
6239
6174
  */
6240
- allowNegative?: boolean;
6241
- }
6242
- /**
6243
- * Result of comparing two amounts.
6244
- */
6245
- type ComparisonResult = -1 | 0 | 1;
6246
- /**
6247
- * Types that can be converted to an Amount.
6248
- *
6249
- * @remarks
6250
- * - `bigint`: Raw value (requires config with decimals)
6251
- * - `string`: Human-readable (e.g., "100.50")
6252
- * - `number`: Human-readable (e.g., 100.5) - beware of precision!
6253
- * - `Amount`: Existing amount or plain object with Amount shape
6254
- */
6255
- type AmountLike = bigint | string | number | Amount$1;
6256
- /**
6257
- * JSON representation of an Amount.
6258
- *
6259
- * @remarks
6260
- * Used for serialization. The `raw` value is stringified since JSON
6261
- * does not support bigint natively.
6262
- *
6263
- * @example
6264
- * ```typescript
6265
- * const json: AmountJSON = {
6266
- * raw: "1500000",
6267
- * decimals: 6,
6268
- * formatted: "1.5"
6269
- * }
6270
- * ```
6271
- */
6272
- interface AmountJSON {
6273
- /** The raw value as a string (bigint serialized). */
6274
- raw: string;
6275
- /** Number of decimal places. */
6276
- decimals: number;
6277
- /** Human-readable formatted value. */
6278
- formatted: string;
6279
- }
6280
-
6281
- /**
6282
- * Minimal fields required for internal Amount operations.
6283
- *
6284
- * @remarks
6285
- * This internal type mirrors the public {@link Amount} interface shape but exists
6286
- * separately to avoid circular dependencies. Internal modules (math, comparison,
6287
- * formatting) import this lightweight type instead of the full Amount class.
6288
- *
6289
- * The Amount class implements this interface, so internal helpers can operate
6290
- * on either Amount instances or plain objects with the same shape.
6291
- *
6292
- * @see {@link ../types.ts#Amount} for the public interface
6293
- * @internal
6294
- */
6295
- interface AmountFields {
6296
- readonly raw: bigint;
6297
- readonly decimals: number;
6298
- }
6299
-
6300
- /**
6301
- * Fluent Amount class for type-safe token amount handling.
6302
- *
6303
- * @remarks
6304
- * The `Amount` class provides an immutable, fluent API for working with token
6305
- * amounts. It wraps a raw bigint value with decimal precision and provides
6306
- * chainable methods for math, comparison, and formatting.
6307
- *
6308
- * Token identity (symbol, contract address) is intentionally NOT included.
6309
- * This ensures developers explicitly source token metadata from the token
6310
- * registry, preventing incorrect symbol display.
6311
- *
6312
- * @example
6313
- * ```typescript
6314
- * import { Amount } from '@core/amounts'
6315
- *
6316
- * // Create from raw value or parse from string
6317
- * const a = Amount.of(1_000_000n, { decimals: 6 })
6318
- * const b = Amount.parse('0.5', { decimals: 6 })
6319
- *
6320
- * // Fluent operations
6321
- * const result = a.add(b).mul(2n).sub(Amount.parse('0.25', { decimals: 6 }))
6322
- *
6323
- * // Comparisons and formatting
6324
- * a.gt(b) // true
6325
- * a.toString() // "1"
6326
- *
6327
- * // For display with symbol, combine with token registry:
6328
- * // `${amount.toString()} ${token.symbol}`
6329
- * ```
6330
- *
6331
- * @packageDocumentation
6332
- */
6333
-
6334
- /**
6335
- * An immutable token amount with fluent API methods.
6336
- *
6337
- * @remarks
6338
- * The `Amount` class provides a type-safe, ergonomic way to work with token
6339
- * amounts. It combines the raw bigint value with decimal precision and
6340
- * provides chainable methods for:
6341
- *
6342
- * - **Math operations**: add, sub, mul, div, abs, neg
6343
- * - **Comparisons**: eq, lt, lte, gt, gte, cmp, min, max
6344
- * - **Predicates**: isZero, isPositive, isNegative
6345
- * - **Formatting**: formatted, toString, toJSON
6346
- * - **Conversion**: toDecimals
6347
- *
6348
- * All operations return new Amount instances - the class is immutable.
6349
- *
6350
- * Token identity (symbol) is intentionally excluded. Source token metadata
6351
- * from the token registry for display purposes.
6352
- */
6353
- declare class Amount implements AmountFields {
6354
- /** The raw value in smallest units (e.g., wei for ETH, micro-units for USDC). */
6355
- readonly raw: bigint;
6356
- /** Number of decimal places for this token. */
6357
- readonly decimals: number;
6358
- private constructor();
6175
+ div(divisor: bigint | number): Amount;
6359
6176
  /**
6360
- * Create an Amount from a raw bigint value.
6177
+ * Get the absolute value of this Amount.
6361
6178
  *
6362
- * @param raw - The raw value in smallest units.
6363
- * @param config - Configuration with decimals.
6364
- * @returns A new immutable Amount instance.
6365
- * @throws KitError If raw is not a bigint or decimals is invalid.
6179
+ * @returns A new Amount with the absolute value.
6366
6180
  *
6367
6181
  * @example
6368
6182
  * ```typescript
6369
- * // Get decimals from token registry
6370
- * const amount = Amount.of(1_000_000n, { decimals: 6 })
6183
+ * const a = Amount.of(-1_500_000n, { decimals: 6 })
6184
+ * a.abs().toString() // "1.5"
6371
6185
  * ```
6372
6186
  */
6373
- static of(raw: bigint, config: AmountConfig): Amount;
6187
+ abs(): Amount;
6374
6188
  /**
6375
- * Parse a human-readable string or number into an Amount.
6189
+ * Negate this Amount.
6376
6190
  *
6377
- * @param input - The input to parse (e.g., "100.50" or 100.5).
6378
- * @param options - Parse options including decimals.
6379
- * @returns A new immutable Amount instance.
6380
- * @throws KitError If input is invalid or parsing fails.
6191
+ * @returns A new Amount with the negated value.
6381
6192
  *
6382
6193
  * @example
6383
6194
  * ```typescript
6384
- * const amount = Amount.parse('100.50', { decimals: 6 })
6195
+ * const a = Amount.parse('1.5', { decimals: 6 })
6196
+ * a.neg().raw // -1_500_000n
6385
6197
  * ```
6386
6198
  */
6387
- static parse(input: string | number, options: ParseOptions): Amount;
6199
+ neg(): Amount;
6388
6200
  /**
6389
- * Convert any AmountLike value to an Amount.
6390
- *
6391
- * @param input - The input (bigint, string, number, or existing Amount).
6392
- * @param config - Configuration (required for non-Amount inputs).
6393
- * @returns A new immutable Amount instance.
6394
- * @throws KitError If conversion fails or config is missing.
6201
+ * Check if this Amount is zero.
6395
6202
  *
6396
- * @remarks
6397
- * When providing a `number` input, very large or small values may be
6398
- * converted to exponential notation (e.g., `1e21`), which is not supported.
6399
- * For such values, provide a `string` representation instead.
6203
+ * @returns True if the raw value is 0n.
6400
6204
  *
6401
6205
  * @example
6402
6206
  * ```typescript
6403
- * Amount.from(1_000_000n, { decimals: 6 }) // from bigint
6404
- * Amount.from('1.00', { decimals: 6 }) // from string
6405
- * Amount.from(existingAmount) // pass-through
6207
+ * Amount.zero({ decimals: 6 }).isZero() // true
6208
+ * Amount.parse('0.001', { decimals: 6 }).isZero() // false
6406
6209
  * ```
6407
6210
  */
6408
- static from(input: AmountLike, config?: AmountConfig): Amount;
6211
+ isZero(): boolean;
6409
6212
  /**
6410
- * Create a zero Amount with the given configuration.
6213
+ * Check if this Amount is positive.
6411
6214
  *
6412
- * @param config - Configuration with decimals.
6413
- * @returns A zero Amount instance.
6215
+ * @returns True if the raw value is greater than 0n.
6414
6216
  *
6415
6217
  * @example
6416
6218
  * ```typescript
6417
- * const zero = Amount.zero({ decimals: 6 })
6219
+ * Amount.parse('1.0', { decimals: 6 }).isPositive() // true
6220
+ * Amount.zero({ decimals: 6 }).isPositive() // false
6418
6221
  * ```
6419
6222
  */
6420
- static zero(config: AmountConfig): Amount;
6223
+ isPositive(): boolean;
6421
6224
  /**
6422
- * Check if a value is an Amount-like object.
6225
+ * Check if this Amount is negative.
6423
6226
  *
6424
- * @param value - The value to check.
6425
- * @returns True if the value has Amount shape (raw: bigint, decimals: number).
6227
+ * @returns True if the raw value is less than 0n.
6426
6228
  *
6427
6229
  * @example
6428
6230
  * ```typescript
6429
- * Amount.isAmount({ raw: 1000000n, decimals: 6 }) // true
6430
- * Amount.isAmount({ value: 100 }) // false
6231
+ * Amount.of(-1_000_000n, { decimals: 6 }).isNegative() // true
6232
+ * Amount.parse('1.0', { decimals: 6 }).isNegative() // false
6431
6233
  * ```
6432
6234
  */
6433
- static isAmount(value: unknown): value is {
6434
- raw: bigint;
6435
- decimals: number;
6436
- };
6235
+ isNegative(): boolean;
6437
6236
  /**
6438
- * Sum an array of Amounts.
6237
+ * Convert this Amount to a different decimal precision.
6439
6238
  *
6440
- * @param amounts - The amounts to sum (must have same decimals).
6441
- * @returns A new Amount with the total sum.
6442
- * @throws KitError If amounts array is empty or decimals don't match.
6239
+ * @param newDecimals - The target number of decimal places.
6240
+ * @returns A new Amount with adjusted precision (or this if same precision).
6241
+ * @throws KitError If newDecimals is invalid.
6443
6242
  *
6444
6243
  * @example
6445
6244
  * ```typescript
6446
- * const fee1 = Amount.parse('0.10', { decimals: 6 })
6447
- * const fee2 = Amount.parse('0.25', { decimals: 6 })
6448
- * const fee3 = Amount.parse('0.15', { decimals: 6 })
6245
+ * // Scale up: 6 decimals → 18 decimals
6246
+ * const usdc = Amount.parse('1.5', { decimals: 6 })
6247
+ * const scaled = usdc.toDecimals(18)
6248
+ * scaled.raw // 1_500_000_000_000_000_000n
6449
6249
  *
6450
- * const total = Amount.sum([fee1, fee2, fee3])
6451
- * total.toString() // "0.5"
6250
+ * // Scale down: 18 decimals → 6 decimals (truncates)
6251
+ * const eth = Amount.of(1_500_000_000_000_000_000n, { decimals: 18 })
6252
+ * eth.toDecimals(6).raw // 1_500_000n
6452
6253
  * ```
6453
6254
  */
6454
- static sum(amounts: readonly Amount[]): Amount;
6255
+ toDecimals(newDecimals: number): Amount;
6455
6256
  /**
6456
- * Deserialize an Amount from a JSON object.
6257
+ * Format this Amount as a human-readable string.
6457
6258
  *
6458
- * @param json - The JSON object (e.g., from `JSON.parse()`).
6459
- * @returns A new Amount instance.
6460
- * @throws KitError If the JSON structure is invalid.
6259
+ * @param options - Formatting options (locale, fraction digits, grouping).
6260
+ * @returns A formatted string (e.g., "1,000.50").
6461
6261
  *
6462
6262
  * @example
6463
6263
  * ```typescript
6464
- * const json = JSON.parse('{"raw":"1500000","decimals":6}')
6465
- * const amount = Amount.fromJSON(json)
6264
+ * const a = Amount.parse('1000.5', { decimals: 6 })
6265
+ * a.formatted() // "1,000.5"
6266
+ * a.formatted({ minimumFractionDigits: 2 }) // "1,000.50"
6267
+ * a.formatted({ useGrouping: false }) // "1000.5"
6466
6268
  * ```
6467
6269
  */
6468
- static fromJSON(json: unknown): Amount;
6270
+ formatted(options?: FormatOptions): string;
6469
6271
  /**
6470
- * Compare this Amount with another.
6272
+ * Convert to a human-readable string.
6471
6273
  *
6472
- * @param other - The Amount to compare with.
6473
- * @returns -1 if this is less than other, 0 if equal, 1 if this is greater.
6474
- * @throws KitError If amounts have different decimals.
6274
+ * @returns A formatted string like "1.5".
6275
+ *
6276
+ * @remarks
6277
+ * For display with a token symbol, combine with the token registry:
6278
+ * ```typescript
6279
+ * `${amount.toString()} ${token.symbol}`
6280
+ * ```
6475
6281
  *
6476
6282
  * @example
6477
6283
  * ```typescript
6478
6284
  * const a = Amount.parse('1.5', { decimals: 6 })
6479
- * const b = Amount.parse('2.0', { decimals: 6 })
6480
- * a.compare(b) // -1
6285
+ * a.toString() // "1.5"
6481
6286
  * ```
6482
6287
  */
6483
- compare(other: Amount): ComparisonResult;
6288
+ toString(): string;
6484
6289
  /**
6485
- * Check if this Amount equals another.
6290
+ * Convert to a JSON-serializable object.
6486
6291
  *
6487
- * @param other - The Amount to compare with.
6488
- * @returns True if the raw values are equal.
6489
- * @throws KitError If amounts have different decimals.
6292
+ * @returns An object with raw (as string), decimals, and formatted value.
6490
6293
  *
6491
6294
  * @example
6492
6295
  * ```typescript
6493
6296
  * const a = Amount.parse('1.5', { decimals: 6 })
6494
- * const b = Amount.parse('1.5', { decimals: 6 })
6495
- * a.eq(b) // true
6297
+ * a.toJSON()
6298
+ * // { raw: "1500000", decimals: 6, formatted: "1.5" }
6496
6299
  * ```
6497
6300
  */
6498
- eq(other: Amount): boolean;
6301
+ toJSON(): AmountJSON;
6302
+ }
6303
+
6304
+ /**
6305
+ * Transfer speed options for cross-chain operations.
6306
+ *
6307
+ * Defines the available speed modes for CCTPv2 transfers, affecting
6308
+ * both transfer time and potential fee implications.
6309
+ */
6310
+ declare enum TransferSpeed {
6311
+ /** Fast burn mode - reduces transfer time but may have different fee implications */
6312
+ FAST = "FAST",
6313
+ /** Standard burn mode - normal transfer time with standard fees */
6314
+ SLOW = "SLOW"
6315
+ }
6316
+ /**
6317
+ * Context object representing a wallet and signing authority on a specific blockchain network.
6318
+ *
6319
+ * Combines a wallet or contract address, the blockchain it resides on, and the adapter (signer)
6320
+ * responsible for authorizing transactions. Used to specify the source or destination in cross-chain
6321
+ * transfer operations.
6322
+ *
6323
+ * @remarks
6324
+ * The `adapter` (signer) and `address` do not always have to belong to the same entity. For example,
6325
+ * in minting or withdrawal scenarios, the signing adapter may authorize a transaction that credits
6326
+ * funds to a different recipient address. This context is essential for cross-chain operations,
6327
+ * ensuring that both the address and the associated adapter are correctly paired with the intended
6328
+ * blockchain, but not necessarily with each other.
6329
+ *
6330
+ * @example
6331
+ * ```typescript
6332
+ * import type { WalletContext } from '@core/provider'
6333
+ * import { adapter, blockchain } from './setup'
6334
+ *
6335
+ * const wallet: WalletContext = {
6336
+ * adapter,
6337
+ * address: '0x1234...abcd',
6338
+ * chain: blockchain,
6339
+ * }
6340
+ * ```
6341
+ */
6342
+ interface WalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
6343
+ /**
6344
+ * The chain definition type to use for the wallet context.
6345
+ *
6346
+ * @defaultValue ChainDefinition
6347
+ */
6348
+ TChainDefinition extends ChainDefinition = ChainDefinition> {
6499
6349
  /**
6500
- * Check if this Amount is less than another.
6501
- *
6502
- * @param other - The Amount to compare with.
6503
- * @returns True if this.raw is less than other.raw.
6504
- * @throws KitError If amounts have different decimals.
6350
+ * The adapter (signer) for the wallet on the specified chain.
6505
6351
  *
6506
- * @example
6507
- * ```typescript
6508
- * const a = Amount.parse('1.0', { decimals: 6 })
6509
- * const b = Amount.parse('2.0', { decimals: 6 })
6510
- * a.lt(b) // true
6511
- * ```
6352
+ * Responsible for authorizing transactions and signing messages on behalf of the wallet or
6353
+ * for a different recipient, depending on the use case.
6512
6354
  */
6513
- lt(other: Amount): boolean;
6355
+ adapter: Adapter<TAdapterCapabilities>;
6514
6356
  /**
6515
- * Check if this Amount is less than or equal to another.
6357
+ * The wallet or contract address.
6516
6358
  *
6517
- * @param other - The Amount to compare with.
6518
- * @returns True if this.raw is less than or equal to other.raw.
6519
- * @throws KitError If amounts have different decimals.
6359
+ * Must be a valid address format for the specified blockchain. May differ from the adapter's
6360
+ * own address in scenarios such as relayed transactions or third-party minting.
6361
+ */
6362
+ address: string;
6363
+ /**
6364
+ * The blockchain network where the wallet or contract address resides.
6520
6365
  *
6521
- * @example
6522
- * ```typescript
6523
- * const a = Amount.parse('1.5', { decimals: 6 })
6524
- * const b = Amount.parse('1.5', { decimals: 6 })
6525
- * a.lte(b) // true
6526
- * ```
6366
+ * Determines the context and format for the address and adapter.
6527
6367
  */
6528
- lte(other: Amount): boolean;
6368
+ chain: TChainDefinition;
6369
+ }
6370
+ /**
6371
+ * Wallet context for bridge destinations with optional custom recipient.
6372
+ *
6373
+ * Extends WalletContext to support scenarios where the recipient address
6374
+ * differs from the signer address (e.g., bridging to a third-party wallet).
6375
+ * The signer address is used for transaction authorization, while the
6376
+ * recipient address specifies where the minted funds should be sent.
6377
+ *
6378
+ * @typeParam TAdapterCapabilities - The adapter capabilities type to use for the wallet context.
6379
+ * @typeParam TChainDefinition - The chain definition type to use for the wallet context.
6380
+ *
6381
+ * @example
6382
+ * ```typescript
6383
+ * import type { DestinationWalletContext } from '@core/provider'
6384
+ * import { adapter, blockchain } from './setup'
6385
+ *
6386
+ * // Bridge to a custom recipient address
6387
+ * const destination: DestinationWalletContext = {
6388
+ * adapter,
6389
+ * address: '0x1234...abcd', // Signer address
6390
+ * chain: blockchain,
6391
+ * recipientAddress: '0x9876...fedc' // Custom recipient
6392
+ * }
6393
+ * ```
6394
+ */
6395
+ interface DestinationWalletContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities,
6396
+ /**
6397
+ * The chain definition type to use for the wallet context.
6398
+ *
6399
+ * @defaultValue ChainDefinition
6400
+ */
6401
+ TChainDefinition extends ChainDefinition = ChainDefinition> extends WalletContext<TAdapterCapabilities, TChainDefinition> {
6529
6402
  /**
6530
- * Check if this Amount is greater than another.
6403
+ * Optional custom recipient address for minted funds.
6531
6404
  *
6532
- * @param other - The Amount to compare with.
6533
- * @returns True if this.raw is greater than other.raw.
6534
- * @throws KitError If amounts have different decimals.
6405
+ * When provided, minted tokens will be sent to this address instead of
6406
+ * the address specified in the wallet context. The wallet context address
6407
+ * is still used for transaction signing and authorization.
6535
6408
  *
6536
- * @example
6537
- * ```typescript
6538
- * const a = Amount.parse('2.0', { decimals: 6 })
6539
- * const b = Amount.parse('1.0', { decimals: 6 })
6540
- * a.gt(b) // true
6541
- * ```
6409
+ * Must be a valid address format for the specified blockchain.
6542
6410
  */
6543
- gt(other: Amount): boolean;
6411
+ recipientAddress?: string;
6544
6412
  /**
6545
- * Check if this Amount is greater than or equal to another.
6546
- *
6547
- * @param other - The Amount to compare with.
6548
- * @returns True if this.raw is greater than or equal to other.raw.
6549
- * @throws KitError If amounts have different decimals.
6413
+ * Whether Circle's relayer submits the destination transaction.
6550
6414
  *
6551
- * @example
6552
- * ```typescript
6553
- * const a = Amount.parse('2.0', { decimals: 6 })
6554
- * const b = Amount.parse('2.0', { decimals: 6 })
6555
- * a.gte(b) // true
6556
- * ```
6415
+ * How an omitted value resolves, and whether an explicit `false` is accepted,
6416
+ * is provider-specific.
6557
6417
  */
6558
- gte(other: Amount): boolean;
6418
+ useForwarder?: boolean;
6559
6419
  /**
6560
- * Return the minimum of this Amount and another.
6420
+ * Optional destination dApp deposit action for a fast cross-chain transfer.
6561
6421
  *
6562
- * @param other - The Amount to compare with.
6563
- * @returns The smaller of the two amounts.
6564
- * @throws KitError If amounts have different decimals.
6422
+ * When set, the burned USDC is minted to Circle's GenericExecutor on the
6423
+ * destination chain, which calls the registered dApp (for example, a Gateway
6424
+ * `depositFor`) in the same relayed flow. Consumed by the CCTP v2 provider's
6425
+ * executor-deposit path; requires `useForwarder: true`.
6565
6426
  *
6566
- * @example
6567
- * ```typescript
6568
- * const a = Amount.parse('1.0', { decimals: 6 })
6569
- * const b = Amount.parse('2.0', { decimals: 6 })
6570
- * a.min(b).toString() // "1"
6571
- * ```
6427
+ * @see {@link BridgeDepositAction}
6572
6428
  */
6573
- min(other: Amount): Amount;
6429
+ deposit?: BridgeDepositAction;
6430
+ }
6431
+ /**
6432
+ * Destination dApp deposit action for a fast cross-chain transfer.
6433
+ *
6434
+ * When present on a bridge destination, the CCTP v2 provider routes the
6435
+ * transfer through Circle's GenericExecutor: the burned USDC is minted to the
6436
+ * executor on the destination chain, which then calls the registered dApp (for
6437
+ * example, a Gateway `depositFor`) in the same relayed flow. Encoded into
6438
+ * executor hookData via `buildDepositForGenericExecutorPayload`.
6439
+ *
6440
+ * @example
6441
+ * ```typescript
6442
+ * import type { BridgeDepositAction } from '@core/provider'
6443
+ *
6444
+ * const deposit: BridgeDepositAction = {
6445
+ * dappId: 'gateway_deposit',
6446
+ * params: ['0xTokenMessengerWithFees', '0xDepositAccount', 0n],
6447
+ * }
6448
+ * ```
6449
+ */
6450
+ interface BridgeDepositAction {
6451
+ /**
6452
+ * Registered dApp identifier the GenericExecutor invokes on the destination
6453
+ * chain (for example, `'gateway_deposit'`).
6454
+ */
6455
+ dappId: string;
6456
+ /**
6457
+ * Positional arguments for the dApp function, in ABI order. Dynamic amount
6458
+ * slots are filled in by the executor from the minted amount.
6459
+ */
6460
+ params: readonly unknown[];
6461
+ }
6462
+ /**
6463
+ * Parameters for executing a cross-chain bridge operation.
6464
+ */
6465
+ interface BridgeParams$1<TFromCapabilities extends AdapterCapabilities = AdapterCapabilities, TToCapabilities extends AdapterCapabilities = AdapterCapabilities,
6466
+ /**
6467
+ * The chain definition type to use for the wallet context.
6468
+ *
6469
+ * @defaultValue ChainDefinition
6470
+ */
6471
+ TChainDefinition extends ChainDefinition = ChainDefinition,
6472
+ /**
6473
+ * The token type the provider accepts.
6474
+ *
6475
+ * @defaultValue 'USDC'
6476
+ *
6477
+ * @remarks
6478
+ * The default preserves the original USDC-only contract for consumers that
6479
+ * omit the token type. Providers that accept a different token type pass
6480
+ * `TToken` explicitly.
6481
+ *
6482
+ * @example
6483
+ * ```typescript
6484
+ * // Default — TToken resolves to 'USDC'
6485
+ * type DefaultParams = BridgeParams // params.token is typed as 'USDC'
6486
+ *
6487
+ * // Provider that identifies tokens by a hex string template literal
6488
+ * type HexTokenParams = BridgeParams<
6489
+ * AdapterCapabilities,
6490
+ * AdapterCapabilities,
6491
+ * ChainDefinition,
6492
+ * `0x${string}`
6493
+ * > // params.token is typed as `0x${string}`
6494
+ * ```
6495
+ */
6496
+ TToken extends string = 'USDC'> {
6497
+ /** The source adapter containing wallet and chain information */
6498
+ source: WalletContext<TFromCapabilities, TChainDefinition>;
6499
+ /** The destination adapter containing wallet and chain information */
6500
+ destination: DestinationWalletContext<TToCapabilities, TChainDefinition>;
6501
+ /** The amount to transfer (as a string to avoid precision issues) */
6502
+ amount: string;
6503
+ /** The token to transfer (provider-defined; defaults to `'USDC'`) */
6504
+ token: TToken;
6505
+ /** Bridge configuration (e.g., fast burn settings) */
6506
+ config: BridgeConfig;
6574
6507
  /**
6575
- * Return the maximum of this Amount and another.
6576
- *
6577
- * @param other - The Amount to compare with.
6578
- * @returns The larger of the two amounts.
6579
- * @throws KitError If amounts have different decimals.
6508
+ * Optional server-signed quote to reuse, typically the
6509
+ * {@link EstimateResult.quote} returned by an earlier `estimate` call.
6580
6510
  *
6581
- * @example
6582
- * ```typescript
6583
- * const a = Amount.parse('1.0', { decimals: 6 })
6584
- * const b = Amount.parse('2.0', { decimals: 6 })
6585
- * a.max(b).toString() // "2"
6586
- * ```
6587
- */
6588
- max(other: Amount): Amount;
6589
- /**
6590
- * Add another Amount to this one.
6511
+ * When present and still valid, a provider with a server-signed quote
6512
+ * model may reuse it instead of fetching a fresh quote, so the fee the
6513
+ * caller was quoted is the fee they pay. Providers decide when a reused
6514
+ * quote is still valid (e.g. freshness, fee token, speed); an unusable or
6515
+ * mismatched quote is ignored and a fresh one is fetched. Transfer
6516
+ * parameters are validated by the provider's on-chain contract, so a quote
6517
+ * reused for a different transfer is rejected there rather than silently.
6518
+ * Providers without a quote model ignore this field entirely, and do so
6519
+ * silently — nothing verifies that a quote reached the provider that issued
6520
+ * it, because the route is matched to a provider only after these
6521
+ * parameters are validated. A quote is meaningful only on the route that
6522
+ * produced it.
6591
6523
  *
6592
- * @param other - The Amount to add.
6593
- * @returns A new Amount with the sum.
6594
- * @throws KitError If amounts have different decimals.
6524
+ * Typed `unknown`: a caller reaches `bridge` through a provider-agnostic
6525
+ * surface, so this shared type names no provider's shape. It is public
6526
+ * input in any case, and is validated before any field is read — by the
6527
+ * provider that serves the route, or by the kit for routes it prices
6528
+ * itself. Treat it as opaque and pass it back unmodified.
6595
6529
  *
6596
- * @example
6597
- * ```typescript
6598
- * const a = Amount.parse('1.5', { decimals: 6 })
6599
- * const b = Amount.parse('0.5', { decimals: 6 })
6600
- * a.add(b).toString() // "2"
6601
- * ```
6530
+ * This is a `bridge` input. A quote is an output of `estimate`, not an
6531
+ * input to it — `estimate` always returns a freshly-priced quote, and a
6532
+ * provider may reject a quote passed to `estimate` rather than ignore it.
6602
6533
  */
6603
- add(other: Amount): Amount;
6534
+ quote?: unknown;
6604
6535
  /**
6605
- * Subtract another Amount from this one.
6606
- *
6607
- * @param other - The Amount to subtract.
6608
- * @returns A new Amount with the difference.
6609
- * @throws KitError If amounts have different decimals.
6536
+ * Optional invocation metadata for tracing and correlation.
6610
6537
  *
6611
- * @example
6612
- * ```typescript
6613
- * const a = Amount.parse('2.0', { decimals: 6 })
6614
- * const b = Amount.parse('0.5', { decimals: 6 })
6615
- * a.sub(b).toString() // "1.5"
6616
- * ```
6538
+ * When provided, the `traceId` is used to correlate all events emitted during
6539
+ * the bridge operation. If not provided, an OpenTelemetry-compatible traceId
6540
+ * will be auto-generated.
6617
6541
  */
6618
- sub(other: Amount): Amount;
6542
+ invocationMeta?: InvocationMeta;
6543
+ }
6544
+ /**
6545
+ * Configuration options for customizing bridge behavior.
6546
+ *
6547
+ * @remarks
6548
+ * This interface is currently incomplete and will be expanded in future versions
6549
+ * to include additional configuration options such as slippage tolerance,
6550
+ * deadline settings, and other bridge parameters.
6551
+ *
6552
+ */
6553
+ interface BridgeConfig {
6619
6554
  /**
6620
- * Multiply this Amount by a scalar.
6621
- *
6622
- * @param multiplier - The scalar to multiply by (bigint or integer number).
6623
- * @returns A new Amount with the product.
6555
+ * The transfer speed mode for CCTPv2 transfers.
6624
6556
  *
6625
- * @remarks
6626
- * When using a `number` as a multiplier, precision is limited by standard
6627
- * JavaScript floating-point capabilities (~15-17 significant digits). For
6628
- * high-precision calculations, provide the multiplier as a `bigint`.
6557
+ * Controls whether to use fast burn mode (FAST) or standard mode (SLOW).
6558
+ * Fast burn may reduce transfer time but could have different fee implications.
6629
6559
  *
6630
- * @example
6631
- * ```typescript
6632
- * const a = Amount.parse('1.5', { decimals: 6 })
6633
- * a.mul(2n).toString() // "3"
6634
- * a.mul(3).toString() // "4.5"
6635
- * ```
6560
+ * @defaultValue TransferSpeed.FAST
6636
6561
  */
6637
- mul(multiplier: bigint | number): Amount;
6562
+ transferSpeed?: TransferSpeed | `${TransferSpeed}` | undefined;
6638
6563
  /**
6639
- * Divide this Amount by a scalar.
6564
+ * Enable or disable EIP-5792 batched transaction execution.
6640
6565
  *
6641
- * @param divisor - The scalar to divide by (bigint or integer number).
6642
- * @returns A new Amount with the quotient (integer division).
6643
- * @throws KitError If divisor is zero.
6566
+ * When `true` (or `undefined` / omitted), the bridge will attempt to batch
6567
+ * the approve and burn calls into a single `wallet_sendCalls` request if
6568
+ * the connected wallet supports it. Set to `false` to explicitly opt out
6569
+ * and always use the sequential approve -> burn flow.
6644
6570
  *
6645
- * @remarks
6646
- * When using a `number` as a divisor, precision is limited by standard
6647
- * JavaScript floating-point capabilities (~15-17 significant digits). For
6648
- * high-precision calculations, provide the divisor as a `bigint`.
6571
+ * @defaultValue `undefined` (batching attempted when the wallet supports it)
6649
6572
  *
6650
6573
  * @example
6651
6574
  * ```typescript
6652
- * const a = Amount.parse('6.0', { decimals: 6 })
6653
- * a.div(2n).toString() // "3"
6654
- * a.div(4).toString() // "1.5"
6575
+ * const config: BridgeConfig = {
6576
+ * batchTransactions: false, // force sequential flow
6577
+ * }
6655
6578
  * ```
6656
6579
  */
6657
- div(divisor: bigint | number): Amount;
6580
+ batchTransactions?: boolean | undefined;
6658
6581
  /**
6659
- * Get the absolute value of this Amount.
6660
- *
6661
- * @returns A new Amount with the absolute value.
6582
+ * The maximum fee to pay for the burn operation.
6662
6583
  *
6663
- * @example
6664
- * ```typescript
6665
- * const a = Amount.of(-1_500_000n, { decimals: 6 })
6666
- * a.abs().toString() // "1.5"
6667
- * ```
6668
- */
6669
- abs(): Amount;
6670
- /**
6671
- * Negate this Amount.
6584
+ * Provide the amount as a base-10 numeric string representing the
6585
+ * token amount in human-readable format. For example: to set a maximum
6586
+ * fee of 1 USDC, pass `"1"`. Decimal values are supported (e.g., `"0.5"`
6587
+ * for half a USDC).
6672
6588
  *
6673
- * @returns A new Amount with the negated value.
6589
+ * @defaultValue `"0"`
6674
6590
  *
6675
6591
  * @example
6676
6592
  * ```typescript
6677
- * const a = Amount.parse('1.5', { decimals: 6 })
6678
- * a.neg().raw // -1_500_000n
6593
+ * import type { BridgeConfig, TransferSpeed } from '@core/provider'
6594
+ *
6595
+ * const config: BridgeConfig = {
6596
+ * transferSpeed: TransferSpeed.FAST,
6597
+ * maxFee: "1", // 1 USDC maximum fee
6598
+ * customFee: {
6599
+ * value: "0.5", // 0.5 USDC developer fee
6600
+ * recipientAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0"
6601
+ * }
6602
+ * }
6679
6603
  * ```
6680
6604
  */
6681
- neg(): Amount;
6605
+ maxFee?: string;
6682
6606
  /**
6683
- * Check if this Amount is zero.
6607
+ * The custom fee to charge for the transfer.
6684
6608
  *
6685
- * @returns True if the raw value is 0n.
6609
+ * Whatever value you provide here is **added on top of the transfer amount**. The user must have
6610
+ * enough balance for `amount + customFee`, and the wallet signs for that total on the source
6611
+ * chain. The custom fee is split automatically:
6686
6612
  *
6687
- * @example
6688
- * ```typescript
6689
- * Amount.zero({ decimals: 6 }).isZero() // true
6690
- * Amount.parse('0.001', { decimals: 6 }).isZero() // false
6691
- * ```
6692
- */
6693
- isZero(): boolean;
6694
- /**
6695
- * Check if this Amount is positive.
6613
+ * - 10% routes to Circle.
6614
+ * - 90% routes to your `recipientAddress`.
6696
6615
  *
6697
- * @returns True if the raw value is greater than 0n.
6616
+ * The original transfer amount proceeds through CCTPv2 unchanged, and the protocol fee (1–14 bps
6617
+ * in FAST mode, 0% in STANDARD) is taken from that transfer amount.
6698
6618
  *
6699
6619
  * @example
6700
6620
  * ```typescript
6701
- * Amount.parse('1.0', { decimals: 6 }).isPositive() // true
6702
- * Amount.zero({ decimals: 6 }).isPositive() // false
6703
- * ```
6704
- */
6705
- isPositive(): boolean;
6706
- /**
6707
- * Check if this Amount is negative.
6621
+ * import type { BridgeConfig } from '@core/provider'
6708
6622
  *
6709
- * @returns True if the raw value is less than 0n.
6623
+ * const config: BridgeConfig = {
6624
+ * customFee: {
6625
+ * value: '5', // 5 USDC developer fee
6626
+ * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
6627
+ * },
6628
+ * }
6710
6629
  *
6711
- * @example
6712
- * ```typescript
6713
- * Amount.of(-1_000_000n, { decimals: 6 }).isNegative() // true
6714
- * Amount.parse('1.0', { decimals: 6 }).isNegative() // false
6630
+ * // Fee flow for a 100 USDC transfer with 5 USDC custom fee:
6631
+ * // Source chain (Ethereum):
6632
+ * // - Wallet debits: 105 USDC total (100 transfer + 5 custom fee)
6633
+ * // - Custom fee split: 0.5 USDC (10%) → Circle, 4.5 USDC (90%) → your recipientAddress
6634
+ * // - Amount sent to CCTPv2: 100 USDC (unchanged)
6635
+ * //
6636
+ * // Destination chain (Base):
6637
+ * // - CCTPv2 FAST fee (example: 1 bps): ~0.01 USDC deducted
6638
+ * // - User receives: ~99.99 USDC
6639
+ * //
6640
+ * // Note: Actual CCTP fees vary by route (1-14 bps for FAST, 0 bps for STANDARD)
6715
6641
  * ```
6716
6642
  */
6717
- isNegative(): boolean;
6643
+ customFee?: CustomFee | undefined;
6718
6644
  /**
6719
- * Convert this Amount to a different decimal precision.
6720
- *
6721
- * @param newDecimals - The target number of decimal places.
6722
- * @returns A new Amount with adjusted precision (or this if same precision).
6723
- * @throws KitError If newDecimals is invalid.
6724
- *
6725
- * @example
6726
- * ```typescript
6727
- * // Scale up: 6 decimals → 18 decimals
6728
- * const usdc = Amount.parse('1.5', { decimals: 6 })
6729
- * const scaled = usdc.toDecimals(18)
6730
- * scaled.raw // 1_500_000_000_000_000_000n
6645
+ * Which leg pays the protocol fee.
6731
6646
  *
6732
- * // Scale down: 18 decimals → 6 decimals (truncates)
6733
- * const eth = Amount.of(1_500_000_000_000_000_000n, { decimals: 18 })
6734
- * eth.toDecimals(6).raw // 1_500_000n
6735
- * ```
6647
+ * `'source'` leaves the delivered amount unreduced; `'destination'` takes the
6648
+ * fee from it. Omit it to let the routed provider decide — a provider rejects
6649
+ * a value it cannot honour.
6736
6650
  */
6737
- toDecimals(newDecimals: number): Amount;
6651
+ feePayment?: 'source' | 'destination' | undefined;
6652
+ }
6653
+ /**
6654
+ * Custom fee configuration charged by the integrator.
6655
+ *
6656
+ * Use to charge an absolute fee on the source chain in human-readable
6657
+ * token amounts.
6658
+ *
6659
+ * @remarks
6660
+ * This is an absolute amount, not a percentage. The `recipientAddress` must be
6661
+ * a valid address for the source chain of the transfer.
6662
+ *
6663
+ * @example
6664
+ * ```typescript
6665
+ * import type { CustomFee } from '@core/provider'
6666
+ *
6667
+ * const config: CustomFee = {
6668
+ * value: '1', // 1 USDC
6669
+ * recipientAddress: '0x1234567890123456789012345678901234567890',
6670
+ * }
6671
+ * ```
6672
+ */
6673
+ interface CustomFee {
6738
6674
  /**
6739
- * Format this Amount as a human-readable string.
6675
+ * The absolute fee to charge for the transfer.
6740
6676
  *
6741
- * @param options - Formatting options (locale, fraction digits, grouping).
6742
- * @returns A formatted string (e.g., "1,000.50").
6677
+ * Provide the amount as a base-10 numeric string representing the token
6678
+ * amount in human-readable format. For example: to charge 1 USDC, pass
6679
+ * `"1"`. Decimal values are supported (e.g., `"0.5"` for half a USDC).
6680
+ * This is not a percentage.
6743
6681
  *
6744
- * @example
6745
- * ```typescript
6746
- * const a = Amount.parse('1000.5', { decimals: 6 })
6747
- * a.formatted() // "1,000.5"
6748
- * a.formatted({ minimumFractionDigits: 2 }) // "1,000.50"
6749
- * a.formatted({ useGrouping: false }) // "1000.5"
6750
- * ```
6682
+ * Note: passing `"0"` results in no fee being charged.
6751
6683
  */
6752
- formatted(options?: FormatOptions): string;
6684
+ value?: string | undefined;
6753
6685
  /**
6754
- * Convert to a human-readable string.
6686
+ * The fee recipient for the bridge transfer.
6755
6687
  *
6756
- * @returns A formatted string like "1.5".
6688
+ * This is the address that will receive the fee on the source chain of the
6689
+ * bridge transfer. The fee recipient address **must be a valid address for
6690
+ * the source chain** of the bridge transfer.
6757
6691
  *
6758
6692
  * @remarks
6759
- * For display with a token symbol, combine with the token registry:
6760
- * ```typescript
6761
- * `${amount.toString()} ${token.symbol}`
6762
- * ```
6693
+ * Circle automatically receives 10% of every custom fee; the remaining 90% is
6694
+ * sent to this `recipientAddress`.
6763
6695
  *
6764
- * @example
6765
- * ```typescript
6766
- * const a = Amount.parse('1.5', { decimals: 6 })
6767
- * a.toString() // "1.5"
6768
- * ```
6696
+ * For example: if bridging from Ethereum to Solana, pass an EVM address like
6697
+ * `"0x1234567890123456789012345678901234567890"` because the source chain
6698
+ * is Ethereum.
6769
6699
  */
6770
- toString(): string;
6700
+ recipientAddress?: string | undefined;
6701
+ }
6702
+ /**
6703
+ * Represents the context of an adapter used for cross-chain operations.
6704
+ *
6705
+ * An AdapterContext must always specify both the adapter and the chain explicitly.
6706
+ * The address field behavior is determined by the adapter's address control model:
6707
+ *
6708
+ * - **Developer-controlled adapters**: The `address` field is required because
6709
+ * each operation must explicitly specify which address to use.
6710
+ * - **User-controlled adapters**: The `address` field is forbidden because
6711
+ * the address is automatically resolved from the connected wallet or signer.
6712
+ * - **Legacy adapters**: The `address` field remains optional for backward compatibility.
6713
+ *
6714
+ * This ensures clear, debuggable code where the intended chain is always visible at the call site,
6715
+ * and address requirements are enforced at compile time based on adapter capabilities.
6716
+ *
6717
+ * @typeParam TAdapterCapabilities - The adapter capabilities type to derive address requirements from
6718
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6719
+ *
6720
+ * @example
6721
+ * ```typescript
6722
+ * // Developer-controlled adapter (address required)
6723
+ * const devContext: AdapterContext<{ addressContext: 'developer-controlled', supportedChains: [] }> = {
6724
+ * adapter: myDevAdapter,
6725
+ * chain: 'Ethereum',
6726
+ * address: '0x123...' // Required
6727
+ * }
6728
+ *
6729
+ * // User-controlled adapter (address forbidden)
6730
+ * const userContext: AdapterContext<{ addressContext: 'user-controlled', supportedChains: [] }> = {
6731
+ * adapter: myUserAdapter,
6732
+ * chain: 'Ethereum'
6733
+ * // address: '0x123...' // TypeScript error: not allowed
6734
+ * }
6735
+ * ```
6736
+ */
6737
+ type AdapterContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> = {
6738
+ /** The adapter instance for blockchain operations */
6739
+ adapter: Adapter<TAdapterCapabilities>;
6740
+ /** The chain reference, which can be a ChainDefinition, Blockchain enum, or string literal */
6741
+ chain: TChainIdentifier;
6742
+ } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
6743
+ /**
6744
+ * Represents a bridge destination with an explicit custom recipient address.
6745
+ *
6746
+ * Extends {@link AdapterContext} with an additional `recipientAddress` field to specify
6747
+ * a custom recipient that differs from the adapter's address. Use this when bridging to
6748
+ * third-party wallets or smart contracts rather than the default address associated with
6749
+ * the destination adapter.
6750
+ *
6751
+ * @typeParam TCapabilities - The adapter capabilities type for the destination adapter
6752
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6753
+ *
6754
+ * @remarks
6755
+ * The `recipientAddress` must be a valid address format for the destination chain
6756
+ * specified in the adapter context. The bridge provider validates address compatibility
6757
+ * during the transfer preparation phase and will throw an error if the address format
6758
+ * is invalid for the target chain.
6759
+ *
6760
+ * @example
6761
+ * ```typescript
6762
+ * import { BridgeDestinationWithAddress } from '@core/provider'
6763
+ * import { ethereumAdapter } from './adapters'
6764
+ *
6765
+ * // Bridge to a custom recipient address on Ethereum
6766
+ * const destination: BridgeDestinationWithAddress = {
6767
+ * adapter: ethereumAdapter,
6768
+ * chain: 'Ethereum',
6769
+ * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
6770
+ * }
6771
+ * ```
6772
+ */
6773
+ type BridgeDestinationWithAddress<TCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> = AdapterContext<TCapabilities, TChainIdentifier> & {
6771
6774
  /**
6772
- * Convert to a JSON-serializable object.
6775
+ * The custom recipient address on the destination chain.
6773
6776
  *
6774
- * @returns An object with raw (as string), decimals, and formatted value.
6777
+ * Must be a valid address format for the chain specified in this adapter context.
6778
+ * This address will receive the bridged funds instead of the adapter's default address.
6779
+ */
6780
+ recipientAddress: string;
6781
+ };
6782
+ /**
6783
+ * Forwarder-only destination without an adapter.
6784
+ *
6785
+ * Used when Circle's Forwarder handles the mint transaction and no destination
6786
+ * adapter is available. Requires both `useForwarder: true` and a `recipientAddress`.
6787
+ *
6788
+ * When using this destination type:
6789
+ * - The mint step completes when the IRIS API confirms `forwardState === 'CONFIRMED'`
6790
+ * - No on-chain transaction confirmation is performed (no adapter available)
6791
+ * - The mint step's `data` field will be undefined (no transaction receipt)
6792
+ *
6793
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6794
+ *
6795
+ * @example
6796
+ * ```typescript
6797
+ * // Forwarder-only destination (no adapter needed)
6798
+ * const dest: ForwarderDestination = {
6799
+ * chain: 'Base',
6800
+ * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
6801
+ * useForwarder: true
6802
+ * }
6803
+ * ```
6804
+ */
6805
+ interface ForwarderDestination<TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> {
6806
+ /** The destination chain where USDC will be minted */
6807
+ chain: TChainIdentifier;
6808
+ /** The recipient address that will receive the minted USDC */
6809
+ recipientAddress: string;
6810
+ /** Must be true for forwarder-only destinations */
6811
+ useForwarder: true;
6812
+ }
6813
+ /**
6814
+ * Union type representing a bridge destination.
6815
+ *
6816
+ * Supports multiple destination configurations:
6817
+ * - {@link AdapterContext}: Standard destination with adapter (for default recipient)
6818
+ * - {@link BridgeDestinationWithAddress}: Destination with adapter and custom recipient
6819
+ * - {@link ForwarderDestination}: Forwarder-only destination without adapter (requires recipientAddress)
6820
+ *
6821
+ * When `useForwarder` is enabled with an adapter, Circle's Orbit relayer handles the mint
6822
+ * transaction and the adapter is used to wait for transaction confirmation.
6823
+ *
6824
+ * When `useForwarder` is enabled without an adapter (ForwarderDestination), the mint step
6825
+ * completes when the IRIS API confirms `forwardState === 'CONFIRMED'` without on-chain
6826
+ * confirmation.
6827
+ *
6828
+ * @typeParam TAdapterCapabilities - The adapter capabilities type for the destination adapter
6829
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
6830
+ *
6831
+ * @example
6832
+ * ```typescript
6833
+ * // Standard destination with adapter
6834
+ * const dest1: BridgeDestination = { adapter, chain: 'Base' }
6835
+ *
6836
+ * // Destination with adapter and custom recipient
6837
+ * const dest2: BridgeDestination = { adapter, chain: 'Base', recipientAddress: '0x...' }
6838
+ *
6839
+ * // Destination with forwarder enabled (adapter for tx confirmation)
6840
+ * const dest3: BridgeDestination = { adapter, chain: 'Base', useForwarder: true }
6841
+ *
6842
+ * // Forwarder-only destination (no adapter, requires recipientAddress)
6843
+ * const dest4: BridgeDestination = { chain: 'Base', useForwarder: true, recipientAddress: '0x...' }
6844
+ * ```
6845
+ */
6846
+ type BridgeDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier$1 = ChainIdentifier$1> = ((AdapterContext<TAdapterCapabilities, TChainIdentifier> | BridgeDestinationWithAddress<TAdapterCapabilities, TChainIdentifier>) & {
6847
+ /**
6848
+ * Enable Circle's relayer to submit the destination transaction.
6775
6849
  *
6776
- * @example
6777
- * ```typescript
6778
- * const a = Amount.parse('1.5', { decimals: 6 })
6779
- * a.toJSON()
6780
- * // { raw: "1500000", decimals: 6, formatted: "1.5" }
6781
- * ```
6850
+ * Where the relay fee is charged depends on the route and on
6851
+ * {@link BridgeConfig.feePayment}: it may be taken from the amount that
6852
+ * arrives, or priced into a quote the source transaction pays.
6853
+ *
6854
+ * Whether the option is required, optional, or refused depends on the
6855
+ * routed provider and the rest of the config.
6782
6856
  */
6783
- toJSON(): AmountJSON;
6857
+ useForwarder?: boolean;
6858
+ }) | ForwarderDestination<TChainIdentifier>;
6859
+
6860
+ /**
6861
+ * MOVED, not new. Lifted from providers/earn-service/src/validations/, where the
6862
+ * same mapper existed; borrow-service uses it instead of adding a second copy.
6863
+ */
6864
+
6865
+ /**
6866
+ * A single claimed (or claimable) reward token amount.
6867
+ *
6868
+ * @example
6869
+ * ```typescript
6870
+ * import type { ClaimedAmount } from '@core/service-client'
6871
+ *
6872
+ * const reward: ClaimedAmount = {
6873
+ * address: '0x9994E35Db50125E0DF82e4c2dde62496CE330999',
6874
+ * symbol: 'MORPHO',
6875
+ * amount: Amount.fromJSON({ raw: '12500000000000000000', decimals: 18 }),
6876
+ * }
6877
+ * ```
6878
+ */
6879
+ interface ClaimedAmount$1 {
6880
+ /** Reward token contract address. */
6881
+ readonly address: string;
6882
+ /** Reward token symbol. */
6883
+ readonly symbol: string;
6884
+ /** Claimed (or claimable) amount. */
6885
+ readonly amount: Amount;
6886
+ }
6887
+
6888
+ /**
6889
+ * MOVED, not new. The claim-rewards result types previously declared
6890
+ * identically in providers/earn-service/src/types.ts and
6891
+ * providers/borrow-service/src/types.ts. Both now re-export from here.
6892
+ */
6893
+ /**
6894
+ * Provider-level result types for the claim-rewards contract.
6895
+ *
6896
+ * The claim-rewards contract returns the same shapes to every kit that
6897
+ * consumes it, so these are declared once here rather than per service.
6898
+ *
6899
+ * @packageDocumentation
6900
+ */
6901
+
6902
+ /**
6903
+ * Result returned when no rewards were claimable.
6904
+ *
6905
+ * No transaction is submitted in this case, so there is no hash to report.
6906
+ */
6907
+ interface NoClaimableRewardsResult {
6908
+ /** Discriminant: nothing was claimable. */
6909
+ readonly status: 'no_rewards';
6910
+ /** Always empty. */
6911
+ readonly rewards: readonly [];
6912
+ }
6913
+ /**
6914
+ * Read-only claimable-rewards quote.
6915
+ *
6916
+ * Services may extend this with their own optional fields (e.g. EarnKit
6917
+ * carries an always-empty `gasFees` for symmetry with its other quotes); the
6918
+ * `rewards` list itself is contract-defined and identical everywhere.
6919
+ */
6920
+ interface ClaimRewardsQuoteInfo$1 {
6921
+ /** Reward tokens currently available for claiming. */
6922
+ readonly rewards: readonly ClaimedAmount$1[];
6784
6923
  }
6785
6924
 
6786
6925
  /** @internal */
@@ -6872,12 +7011,9 @@ interface CollateralInfo {
6872
7011
  * (e.g., 0.6 = 60%).
6873
7012
  *
6874
7013
  * Populated for Morpho V1 vaults; `null` when the underlying product
6875
- * exposes no per-market allocation (e.g. Morpho V2). Optional for now — a
6876
- * backend that predates this field omits it entirely, matching the other
6877
- * optional facets on {@link EarnOpportunityBase}; a future release makes it
6878
- * required once every backend emits it.
7014
+ * exposes no per-market allocation (e.g. Morpho V2).
6879
7015
  */
6880
- readonly allocationPct?: number | null | undefined;
7016
+ readonly allocationPct: number | null;
6881
7017
  }
6882
7018
  /**
6883
7019
  * Vault warning from the underlying earn protocol.
@@ -7047,19 +7183,19 @@ interface EarnOpportunityBase {
7047
7183
  /** Reward tokens distributed by this opportunity. */
7048
7184
  readonly rewards: readonly VaultRewardInfo[];
7049
7185
  /** Primary on-chain address (protocol-neutral; replaces vaultAddress). */
7050
- readonly address?: string | undefined;
7186
+ readonly address: string;
7051
7187
  /** RFC3339 freshness timestamp: provider state ts, else cache sync time. */
7052
- readonly asOf?: string | undefined;
7188
+ readonly asOf: string;
7053
7189
  /** Manager/curator identity; `null` when the product has no manager. */
7054
- readonly manager?: ManagerInfo | null | undefined;
7190
+ readonly manager: ManagerInfo | null;
7055
7191
  /** Yield profile including trailing averages. */
7056
- readonly apyProfile?: ApyProfile | undefined;
7192
+ readonly apyProfile: ApyProfile;
7057
7193
  /** Fee split. */
7058
- readonly fee?: FeeInfo | undefined;
7194
+ readonly fee: FeeInfo;
7059
7195
  /** Liquidity profile. */
7060
- readonly liquidityProfile?: LiquidityProfile | undefined;
7196
+ readonly liquidityProfile: LiquidityProfile;
7061
7197
  /** Risk signals. */
7062
- readonly riskSignals?: RiskSignals | undefined;
7198
+ readonly riskSignals: RiskSignals;
7063
7199
  /** @deprecated use {@link EarnOpportunityBase.address} */
7064
7200
  readonly vaultAddress: string;
7065
7201
  /** @deprecated use {@link ApyProfile.current} via apyProfile */
@@ -7126,13 +7262,9 @@ interface VaultOpportunity extends EarnOpportunityBase {
7126
7262
  /**
7127
7263
  * Universal discriminator identifying the opportunity shape.
7128
7264
  *
7129
- * Optional for now — a backend that predates the field omits it, matching
7130
- * the other optional facets — so this release stays source-compatible for
7131
- * code that constructs the type. A future release makes it required once
7132
- * every backend emits it. Always present on responses from an emitting
7133
- * backend; narrow on it before reading product-specific fields.
7265
+ * Narrow on `productType` before reading product-specific fields.
7134
7266
  */
7135
- readonly productType?: 'vault';
7267
+ readonly productType: 'vault';
7136
7268
  /** Collateral markets backing this vault. */
7137
7269
  readonly collateral: readonly CollateralInfo[];
7138
7270
  }
@@ -7604,20 +7736,19 @@ interface EarnWithdrawResult {
7604
7736
  * Extend {@link AssetAmount} with a required contract address.
7605
7737
  * The former `tokenAddress` field is now `address`, and
7606
7738
  * `amountBaseUnits` / `decimals` are collapsed into `amount`.
7739
+ *
7740
+ * @remarks
7741
+ * This is a distinct type from `@core/service-client`'s `ClaimedAmount`, which
7742
+ * carries only `address`/`symbol`/`amount`. This local, richer type is the one
7743
+ * used throughout this package (`provider/claimRewards/claimRewards.ts`,
7744
+ * `validations/schemas.ts`), by `@circle-fin/earn-kit`, and as the `rewards`
7745
+ * element type of this file's {@link ClaimRewardsResult}; take care to import
7746
+ * the one you actually mean.
7607
7747
  */
7608
7748
  interface ClaimedAmount extends AssetAmount {
7609
7749
  /** Reward token contract address (always present for claimed rewards). */
7610
7750
  readonly address: string;
7611
7751
  }
7612
- /**
7613
- * Result returned when no rewards are claimable.
7614
- */
7615
- interface NoClaimableRewardsResult {
7616
- /** Discriminates the no-op result where no transaction was submitted. */
7617
- readonly status: 'no_rewards';
7618
- /** Empty because there were no rewards to claim. */
7619
- readonly rewards: readonly [];
7620
- }
7621
7752
  /**
7622
7753
  * Fields shared by both {@link EarnGasFeeEstimate} variants.
7623
7754
  *
@@ -7796,9 +7927,7 @@ interface WithdrawalQuoteInfo {
7796
7927
  * - `amount` — claimable amount as an {@link Amount}
7797
7928
  * - `address` — reward token contract address
7798
7929
  */
7799
- interface ClaimRewardsQuoteInfo {
7800
- /** Reward tokens available for claiming. */
7801
- readonly rewards: readonly AssetAmount[];
7930
+ interface ClaimRewardsQuoteInfo extends ClaimRewardsQuoteInfo$1 {
7802
7931
  /**
7803
7932
  * Estimated native gas fees for claiming rewards.
7804
7933
  *
@@ -8158,6 +8287,12 @@ interface SameChainDepositParams<TFromAdapterCapabilities extends AdapterCapabil
8158
8287
  * @example '100.50' for 100.50 USDC
8159
8288
  */
8160
8289
  readonly amount: string;
8290
+ /**
8291
+ * Gas fee estimates from a prior {@link getDepositQuote} call. When provided,
8292
+ * the pre-broadcast gas reserve check uses the actual estimated cost instead
8293
+ * of the conservative fallback reserve.
8294
+ */
8295
+ readonly gasFees?: readonly EarnGasFeeEstimate[] | undefined;
8161
8296
  /** Optional earn configuration. */
8162
8297
  readonly config?: EarnConfig | undefined;
8163
8298
  }
@@ -8488,14 +8623,8 @@ type EarnVaultInfo = DistributiveOmit<EarnOpportunity, 'totalDeposits' | 'liquid
8488
8623
  readonly totalDeposits: string;
8489
8624
  /** Available liquidity in the vault in human-readable decimal format. */
8490
8625
  readonly liquidity: string;
8491
- /**
8492
- * Liquidity profile with amounts as human-readable decimal strings.
8493
- *
8494
- * Optional during the expand/contract migration window: a backend that
8495
- * predates the nested facets omits it, so it is absent until the response
8496
- * carries it.
8497
- */
8498
- readonly liquidityProfile?: EarnLiquidityProfile;
8626
+ /** Liquidity profile with amounts as human-readable decimal strings. */
8627
+ readonly liquidityProfile: EarnLiquidityProfile;
8499
8628
  };
8500
8629
  /** Result of a batch vault lookup. */
8501
8630
  type EarnGetVaultsResult = Omit<GetVaultsResult, 'vaults'> & {
@@ -9967,8 +10096,8 @@ interface AppKitContext {
9967
10096
  *
9968
10097
  * This property stores event handlers that are registered via the AppKit's
9969
10098
  * `on()` method. Handlers are grouped by operation type. The runtime buckets
9970
- * are `bridge` and `earn`; the context can add more operation buckets as
9971
- * AppKit wires action handlers for additional kits.
10099
+ * are `bridge`, `earn`, and `borrow`; the context can add more operation
10100
+ * buckets as AppKit wires action handlers for additional kits.
9972
10101
  *
9973
10102
  * Within each operation bucket, handlers are keyed by action name (for
9974
10103
  * example, `bridge.approve` or `earn.deposit`) or `*` for wildcard handlers.
@@ -9987,13 +10116,13 @@ interface AppKitContext {
9987
10116
  * // Earn handlers are registered with EarnKit when earn operations run
9988
10117
  * ```
9989
10118
  */
9990
- actions: Record<'bridge' | 'earn', Record<string, ((payload: unknown) => void)[]>>;
10119
+ actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
9991
10120
  /**
9992
- * Disable success analytics for the underlying EarnKit, SwapKit, and
9993
- * UnifiedBalanceKit.
10121
+ * Disable success analytics for the underlying EarnKit, SwapKit,
10122
+ * BorrowKit, and UnifiedBalanceKit.
9994
10123
  *
9995
- * When `true`, completed earn, swap, and unified balance operations will not
9996
- * POST analytics events. This does not disable error reporting; use
10124
+ * When `true`, completed earn, swap, borrow, and unified balance operations
10125
+ * will not POST analytics events. This does not disable error reporting; use
9997
10126
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
9998
10127
  *
9999
10128
  * @defaultValue false
@@ -10003,7 +10132,7 @@ interface AppKitContext {
10003
10132
  * Disable error telemetry for all sub-kits.
10004
10133
  *
10005
10134
  * When `true`, none of the underlying kits (BridgeKit, SwapKit, EarnKit,
10006
- * UnifiedBalanceKit) will POST error details to the telemetry
10135
+ * BorrowKit, UnifiedBalanceKit) will POST error details to the telemetry
10007
10136
  * endpoint when operations throw. Defaults to `false` (enabled).
10008
10137
  *
10009
10138
  * @defaultValue false