@circle-fin/app-kit 1.9.0 → 1.11.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.
@@ -373,6 +373,14 @@ interface CCTPSplitConfig {
373
373
  type: 'split';
374
374
  tokenMessenger: string;
375
375
  messageTransmitter: string;
376
+ /**
377
+ * Address of the `TokenMessengerWithFees` wrapper, when deployed on this chain.
378
+ *
379
+ * Optional. Present only on chains that support the prepaid FORWARD path
380
+ * (source-chain fee collection via `depositForBurnWithHookAndFees`). Resolve
381
+ * it with `resolveCCTPV2ContractAddress(chain, 'tokenMessengerWithFees')`.
382
+ */
383
+ tokenMessengerWithFees?: string;
376
384
  confirmations: number;
377
385
  }
378
386
  /**
@@ -393,6 +401,14 @@ interface CCTPSplitConfig {
393
401
  interface CCTPMergedConfig {
394
402
  type: 'merged';
395
403
  contract: string;
404
+ /**
405
+ * Address of the `TokenMessengerWithFees` wrapper, when deployed on this chain.
406
+ *
407
+ * Optional. Present only on chains that support the prepaid FORWARD path
408
+ * (source-chain fee collection via `depositForBurnWithHookAndFees`). Resolve
409
+ * it with `resolveCCTPV2ContractAddress(chain, 'tokenMessengerWithFees')`.
410
+ */
411
+ tokenMessengerWithFees?: string;
396
412
  confirmations: number;
397
413
  }
398
414
  /**
@@ -527,6 +543,21 @@ interface GatewayV1Contracts {
527
543
  * @example "0xabcdef1234567890abcdef1234567890abcdef12"
528
544
  */
529
545
  minter: string;
546
+ /**
547
+ * The address of the `DepositForHandler` contract.
548
+ *
549
+ * @description Optional. The handler the GenericExecutor calls on this chain
550
+ * to run a fast cross-chain deposit into the {@link GatewayV1Contracts.wallet}.
551
+ * Present only on chains that are fast-deposit destinations; other Gateway
552
+ * chains omit it.
553
+ *
554
+ * Address format varies by blockchain:
555
+ * - EVM chains: 40-character hexadecimal with 0x prefix (e.g., "0x1234...")
556
+ * - Solana: Base58-encoded 32-byte address (e.g., "9WzDX...")
557
+ *
558
+ * @example "0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48"
559
+ */
560
+ depositForHandler?: string;
530
561
  }
531
562
  /**
532
563
  * Versioned map of Gateway contract configurations.
@@ -1826,6 +1857,110 @@ interface CCTPv2ActionMap {
1826
1857
  */
1827
1858
  hookData: string;
1828
1859
  };
1860
+ /**
1861
+ * Initiate a prepaid cross-chain USDC transfer through the `TokenMessengerWithFees` wrapper.
1862
+ *
1863
+ * Burn USDC on the source chain while collecting all fees up front against a
1864
+ * signed quote. The wrapper collects the fee via `FeeManager`, then delegates
1865
+ * to the unmodified `TokenMessengerV2`. When `hookData` is provided (the
1866
+ * GenericExecutor FORWARD path) the wrapper's `depositForBurnWithHookAndFees`
1867
+ * contract method is used; otherwise `depositForBurnWithFees` is used.
1868
+ *
1869
+ * @remarks
1870
+ * SDK/contract naming: this SDK action is `depositForBurnWithFees` but, when a
1871
+ * `hookData` is present, it dispatches to the `depositForBurnWithHookAndFees`
1872
+ * contract method on `TokenMessengerWithFees` (NOT on `TokenMessengerV2`).
1873
+ *
1874
+ * Fee payment channel (must match the quote's `feeToken`):
1875
+ * - Native fee (`feeToken` is the zero address): exactly `feeTotalAmount` is
1876
+ * attached as `msg.value`.
1877
+ * - ERC-20 fee (e.g. USDC): no value is attached; the caller must first approve
1878
+ * the wrapper for `feeTotalAmount` (see the provider's fee approval helper).
1879
+ *
1880
+ * @remarks
1881
+ * Unlike `depositForBurn`, the `TokenMessengerWithFees` contract methods do NOT
1882
+ * take `maxFee` or `minFinalityThreshold` — fee and finality behavior are
1883
+ * derived from the signed quote — so those fields are omitted from this action.
1884
+ *
1885
+ * @example
1886
+ * ```typescript
1887
+ * await adapter.action('cctp.v2.depositForBurnWithFees', {
1888
+ * amount: BigInt('1000000'),
1889
+ * mintRecipient: executorAddress, // GenericExecutor (bytes32)
1890
+ * destinationCaller: executorAddress, // GenericExecutor (bytes32)
1891
+ * fromChain: ethereum,
1892
+ * toChain: arc,
1893
+ * hookData: geForwardHookData, // cctp-forward-wrapped GenericExecutor blob
1894
+ * claim: { signedQuote: '0x...', refundAddress: '0x...' },
1895
+ * feeToken: '0x0000000000000000000000000000000000000000', // native
1896
+ * feeTotalAmount: 3500000n,
1897
+ * })
1898
+ * ```
1899
+ */
1900
+ depositForBurnWithFees: Omit<CCTPv2ActionMap['depositForBurn'], 'maxFee' | 'minFinalityThreshold'> & {
1901
+ /**
1902
+ * Optional hex-encoded hook data for the GenericExecutor FORWARD path.
1903
+ *
1904
+ * When present, the `depositForBurnWithHookAndFees` contract method is used
1905
+ * and the blob must be wrapped in the `cctp-forward` envelope (the wrapper
1906
+ * rejects a FORWARD fee quote whose hook lacks it). When omitted, the plain
1907
+ * `depositForBurnWithFees` contract method is used.
1908
+ */
1909
+ hookData?: string;
1910
+ /**
1911
+ * Signed fee quote claim passed to the `TokenMessengerWithFees` wrapper.
1912
+ *
1913
+ * `signedQuote` is the `[uint8 0x01][abi.encode(Quote)]` blob returned by the
1914
+ * Fee Quote service; `refundAddress` receives any fee overpayment refund.
1915
+ */
1916
+ claim: QuoteClaim;
1917
+ /**
1918
+ * Fee token from the signed quote.
1919
+ *
1920
+ * The zero address (`0x000…0`) means the fee is paid in native currency and
1921
+ * is attached as `msg.value`. Any other address (e.g. USDC) means an ERC-20
1922
+ * fee that must be approved to the wrapper beforehand. This is independent of
1923
+ * `burnToken`, which is always USDC.
1924
+ */
1925
+ feeToken: string;
1926
+ /**
1927
+ * Total fee amount from the signed quote, in `feeToken` minor units.
1928
+ *
1929
+ * Firm only until the quote's `expiresAt`. For a native fee this is the exact
1930
+ * `msg.value`; for an ERC-20 fee this is the amount approved to the wrapper.
1931
+ */
1932
+ feeTotalAmount: bigint;
1933
+ };
1934
+ }
1935
+ /**
1936
+ * Signed fee quote claim consumed by the `TokenMessengerWithFees` wrapper.
1937
+ *
1938
+ * Mirrors the on-chain `IFeeManager.QuoteClaim` struct.
1939
+ *
1940
+ * @example
1941
+ * ```typescript
1942
+ * const claim: QuoteClaim = {
1943
+ * signedQuote: '0x01...', // [uint8 0x01][abi.encode(Quote)]
1944
+ * refundAddress: '0xUserWallet...',
1945
+ * }
1946
+ * ```
1947
+ */
1948
+ interface QuoteClaim {
1949
+ /**
1950
+ * Opaque signed quote bytes (`0x` hex) from the fee-quote service
1951
+ * (`SignedFeeQuote.signedQuote` returned by `fetchFeeQuote`). Pass verbatim;
1952
+ * do not decode.
1953
+ *
1954
+ * The quote binds the FORWARD fee item to the on-chain call via `argsHash`;
1955
+ * passing a quote that does not match the burn args reverts `QuoteArgsMismatch`.
1956
+ */
1957
+ signedQuote: string;
1958
+ /**
1959
+ * Address that receives any refund of overpaid fees.
1960
+ *
1961
+ * Typically the user wallet that authorized the burn.
1962
+ */
1963
+ refundAddress: string;
1829
1964
  }
1830
1965
 
1831
1966
  /**
@@ -5942,10 +6077,13 @@ interface ResolvedSpendParams<TFromAdapterCapabilities extends AdapterCapabiliti
5942
6077
  */
5943
6078
  type SpendFeeFunction = (params: ResolvedSpendParams) => Promise<string> | string;
5944
6079
  /**
5945
- * Function that resolves the fee recipient address for a given source chain.
5946
- * Called once per source chain in a multi-chain spend.
6080
+ * Function that resolves the fee recipient address for a spend.
6081
+ * Called once per spend, against the resolved **destination** chain
6082
+ * every fee burn intent in a spend mints to that single chain
6083
+ * regardless of which source chain(s) funded it, so only one
6084
+ * recipient address (valid on the destination chain) is ever needed.
5947
6085
  */
5948
- type SpendFeeRecipientFunction = (feePayoutChain: ChainDefinition, params: ResolvedSpendParams) => Promise<string> | string;
6086
+ type SpendFeeRecipientFunction = (destinationChain: ChainDefinition, params: ResolvedSpendParams) => Promise<string> | string;
5949
6087
  /**
5950
6088
  * Policy for computing and routing custom developer fees.
5951
6089
  *
@@ -5955,11 +6093,54 @@ type SpendFeeRecipientFunction = (feePayoutChain: ChainDefinition, params: Resol
5955
6093
  * Fields that only exist after resolution (e.g. per-source allocations)
5956
6094
  * may be `undefined`. Implementations should only rely on top-level
5957
6095
  * fields such as `to`, `token`, and `amount`.
6096
+ *
6097
+ * @remarks
6098
+ * `resolveFeeRecipientAddress` is optional when you configure
6099
+ * {@link UnifiedBalanceKit.setFeeRecipients} instead — the declarative
6100
+ * map takes priority over this callback when both are present. Provide
6101
+ * exactly one of the two; a policy with neither throws at spend time.
5958
6102
  */
5959
6103
  interface CustomFeePolicy {
5960
6104
  computeFee: SpendFeeFunction;
5961
- resolveFeeRecipientAddress: SpendFeeRecipientFunction;
6105
+ resolveFeeRecipientAddress?: SpendFeeRecipientFunction;
5962
6106
  }
6107
+ /**
6108
+ * Chain type group used to key {@link FeeRecipientsConfig}.
6109
+ *
6110
+ * @remarks
6111
+ * Only `'evm'` and `'solana'` are live today (the only chain types the
6112
+ * kit's provider currently supports). This is deliberately a narrow
6113
+ * subset of `@core/chains`' broader `ChainType` union rather than a
6114
+ * hardcoded two-field struct, so that support for additional non-EVM
6115
+ * chain types (e.g. Stellar, Starknet) can be added later by adding
6116
+ * new union members here — no restructuring of `FeeRecipientsConfig`
6117
+ * or its consumers required.
6118
+ */
6119
+ type FeeRecipientChainType = 'evm' | 'solana';
6120
+ /**
6121
+ * Declarative map of fee recipient addresses, keyed by chain type.
6122
+ *
6123
+ * @remarks
6124
+ * Set via {@link UnifiedBalanceKit.setFeeRecipients}. At spend time the
6125
+ * kit resolves the spend's destination chain to its
6126
+ * {@link FeeRecipientChainType} and looks up the matching entry —
6127
+ * exactly one recipient is used per spend (see
6128
+ * {@link SpendFeeRecipientFunction}). Provide entries for every chain
6129
+ * type you expect to spend to; a spend to a destination chain type
6130
+ * with no matching entry throws before any fee collection is
6131
+ * attempted.
6132
+ *
6133
+ * @example
6134
+ * ```typescript
6135
+ * import type { FeeRecipientsConfig } from '@circle-fin/unified-balance-kit'
6136
+ *
6137
+ * const feeRecipients: FeeRecipientsConfig = {
6138
+ * evm: '0x1234567890123456789012345678901234567890',
6139
+ * solana: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
6140
+ * }
6141
+ * ```
6142
+ */
6143
+ type FeeRecipientsConfig = Partial<Record<FeeRecipientChainType, string>>;
5963
6144
  /**
5964
6145
  * Fee category describing the origin of a fee line item.
5965
6146
  *
@@ -6796,10 +6977,13 @@ interface GetDelegateStatusParams<TAdapterCapabilities extends AdapterCapabiliti
6796
6977
  }
6797
6978
 
6798
6979
  /**
6799
- * Parameters for initiating a delayed fund removal from a Gateway
6980
+ * Parameters for initiating a delayed recovery fund removal from a Gateway
6800
6981
  * account.
6801
6982
  *
6802
6983
  * @remarks
6984
+ * Use fund removal only as a trustless fallback when the normal spend flow is
6985
+ * unavailable. For day-to-day movement out of a Unified Balance, use `spend`.
6986
+ *
6803
6987
  * Fund removals have a mandatory 7-day delay before they can be
6804
6988
  * completed. Only one removal may be pending per chain at a
6805
6989
  * time. Initiating a second removal on the same chain adds the
@@ -6882,7 +7066,12 @@ interface InitiateRemoveFundResult {
6882
7066
  explorerUrl?: string;
6883
7067
  }
6884
7068
  /**
6885
- * Parameters for completing a fund removal after the activation period.
7069
+ * Parameters for completing a recovery fund removal after the withdrawal
7070
+ * delay.
7071
+ *
7072
+ * @remarks
7073
+ * Use fund removal only as a trustless fallback when the normal spend flow is
7074
+ * unavailable. For day-to-day movement out of a Unified Balance, use `spend`.
6886
7075
  *
6887
7076
  * @typeParam TAdapterCapabilities - Adapter capability constraints.
6888
7077
  * @typeParam TChainIdentifier - Accepted chain identifier type.
@@ -6979,6 +7168,11 @@ interface GetSupportedChainsOptions {
6979
7168
  * Internally holds a persistent {@link UnifiedBalanceKit} instance so that
6980
7169
  * event dispatchers and custom fee policies are preserved across calls.
6981
7170
  *
7171
+ * Use {@link AppKitUnifiedBalance.spend} for normal movement out of a Unified
7172
+ * Balance. {@link AppKitUnifiedBalance.removeFund} is a trustless recovery path
7173
+ * for situations where the normal spend flow is unavailable, and it requires a
7174
+ * 7-day withdrawal delay after {@link AppKitUnifiedBalance.initiateRemoveFund}.
7175
+ *
6982
7176
  * @example
6983
7177
  * ```typescript
6984
7178
  * import { AppKit } from '@circle-fin/app-kit'
@@ -7180,7 +7374,12 @@ declare class AppKitUnifiedBalance {
7180
7374
  */
7181
7375
  removeDelegate(params: UpdateDelegateParams): Promise<UpdateDelegateResult>;
7182
7376
  /**
7183
- * Kick off a delayed fund removal from an account.
7377
+ * Initiate a trustless recovery removal from an account.
7378
+ *
7379
+ * Use `spend` for normal movement out of a Unified Balance. `removeFund` is a
7380
+ * recovery path for situations where the normal spend flow is unavailable.
7381
+ * Calling this method starts the 7-day withdrawal delay before the removal can
7382
+ * be completed.
7184
7383
  *
7185
7384
  * @param params - The account owner's adapter context, amount, and token.
7186
7385
  * @returns Promise resolving to the initiation details.
@@ -7198,11 +7397,16 @@ declare class AppKitUnifiedBalance {
7198
7397
  */
7199
7398
  initiateRemoveFund(params: InitiateRemoveFundParams): Promise<InitiateRemoveFundResult>;
7200
7399
  /**
7201
- * Complete a fund removal once the activation period has passed.
7400
+ * Complete a trustless recovery removal after the withdrawal delay.
7401
+ *
7402
+ * Use `spend` for normal movement out of a Unified Balance. `removeFund` is a
7403
+ * recovery path for situations where the normal spend flow is unavailable.
7404
+ * Both EVM and Solana removals require a 7-day withdrawal delay after
7405
+ * `initiateRemoveFund` before funds can be removed.
7202
7406
  *
7203
7407
  * @param params - The account owner context matching the original initiation.
7204
7408
  * @returns Promise resolving to the fund removal details.
7205
- * @throws {KitError} If the activation period has not elapsed or the
7409
+ * @throws {KitError} If the withdrawal delay has not elapsed or the
7206
7410
  * on-chain transaction fails.
7207
7411
  *
7208
7412
  * @example
@@ -7273,6 +7477,43 @@ declare class AppKitUnifiedBalance {
7273
7477
  * ```
7274
7478
  */
7275
7479
  removeCustomFeePolicy(): void;
7480
+ /**
7481
+ * Set a declarative fee recipient map, keyed by chain type.
7482
+ *
7483
+ * Once set, `spend()`/`estimateSpend()` resolve the fee recipient by
7484
+ * looking up the spend's destination chain type in this map — taking
7485
+ * priority over `customFeePolicy`'s `resolveFeeRecipientAddress`
7486
+ * callback.
7487
+ *
7488
+ * @remarks
7489
+ * This only controls which address a fee is sent to — it does not by
7490
+ * itself cause any fee to be charged. You still need
7491
+ * `setCustomFeePolicy`'s `computeFee` to determine the fee amount;
7492
+ * calling `setFeeRecipients` without ever calling `setCustomFeePolicy`
7493
+ * throws at spend time (there is no `computeFee` to determine an
7494
+ * amount).
7495
+ *
7496
+ * @param config - Fee recipient addresses keyed by chain type (e.g.
7497
+ * `{ evm: '0x...', solana: 'Sol...' }`).
7498
+ *
7499
+ * @example
7500
+ * ```typescript
7501
+ * kit.unifiedBalance.setFeeRecipients({
7502
+ * evm: '0x1234567890123456789012345678901234567890',
7503
+ * solana: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
7504
+ * })
7505
+ * ```
7506
+ */
7507
+ setFeeRecipients(config: FeeRecipientsConfig): void;
7508
+ /**
7509
+ * Remove the declarative fee recipient map.
7510
+ *
7511
+ * @example
7512
+ * ```typescript
7513
+ * kit.unifiedBalance.removeFeeRecipients()
7514
+ * ```
7515
+ */
7516
+ removeFeeRecipients(): void;
7276
7517
  }
7277
7518
 
7278
7519
  export { AppKitUnifiedBalance };