@circle-fin/app-kit 1.8.1 → 1.10.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 (48) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +3 -3
  3. package/bridge.cjs +1102 -260
  4. package/bridge.d.cts +161 -10
  5. package/bridge.d.mts +161 -10
  6. package/bridge.d.ts +161 -10
  7. package/bridge.mjs +1102 -260
  8. package/chains.cjs +102 -2
  9. package/chains.d.cts +3 -0
  10. package/chains.d.mts +3 -0
  11. package/chains.d.ts +3 -0
  12. package/chains.mjs +102 -2
  13. package/context.cjs +1 -0
  14. package/context.d.cts +166 -12
  15. package/context.d.mts +166 -12
  16. package/context.d.ts +166 -12
  17. package/context.mjs +1 -0
  18. package/earn.cjs +1074 -454
  19. package/earn.d.cts +546 -99
  20. package/earn.d.mts +546 -99
  21. package/earn.d.ts +546 -99
  22. package/earn.mjs +1074 -455
  23. package/estimateBridge.cjs +1102 -260
  24. package/estimateBridge.d.cts +161 -10
  25. package/estimateBridge.d.mts +161 -10
  26. package/estimateBridge.d.ts +161 -10
  27. package/estimateBridge.mjs +1102 -260
  28. package/estimateSwap.cjs +915 -96
  29. package/estimateSwap.d.cts +161 -10
  30. package/estimateSwap.d.mts +161 -10
  31. package/estimateSwap.d.ts +161 -10
  32. package/estimateSwap.mjs +915 -96
  33. package/index.cjs +3029 -862
  34. package/index.d.cts +1277 -143
  35. package/index.d.mts +1277 -143
  36. package/index.d.ts +1277 -143
  37. package/index.mjs +3029 -862
  38. package/package.json +12 -6
  39. package/swap.cjs +915 -96
  40. package/swap.d.cts +161 -10
  41. package/swap.d.mts +161 -10
  42. package/swap.d.ts +161 -10
  43. package/swap.mjs +915 -96
  44. package/unifiedBalance.cjs +822 -115
  45. package/unifiedBalance.d.cts +224 -4
  46. package/unifiedBalance.d.mts +224 -4
  47. package/unifiedBalance.d.ts +224 -4
  48. package/unifiedBalance.mjs +822 -115
package/earn.d.ts CHANGED
@@ -374,6 +374,14 @@ interface CCTPSplitConfig {
374
374
  type: 'split';
375
375
  tokenMessenger: string;
376
376
  messageTransmitter: string;
377
+ /**
378
+ * Address of the `TokenMessengerWithFees` wrapper, when deployed on this chain.
379
+ *
380
+ * Optional. Present only on chains that support the prepaid FORWARD path
381
+ * (source-chain fee collection via `depositForBurnWithHookAndFees`). Resolve
382
+ * it with `resolveCCTPV2ContractAddress(chain, 'tokenMessengerWithFees')`.
383
+ */
384
+ tokenMessengerWithFees?: string;
377
385
  confirmations: number;
378
386
  }
379
387
  /**
@@ -394,6 +402,14 @@ interface CCTPSplitConfig {
394
402
  interface CCTPMergedConfig {
395
403
  type: 'merged';
396
404
  contract: string;
405
+ /**
406
+ * Address of the `TokenMessengerWithFees` wrapper, when deployed on this chain.
407
+ *
408
+ * Optional. Present only on chains that support the prepaid FORWARD path
409
+ * (source-chain fee collection via `depositForBurnWithHookAndFees`). Resolve
410
+ * it with `resolveCCTPV2ContractAddress(chain, 'tokenMessengerWithFees')`.
411
+ */
412
+ tokenMessengerWithFees?: string;
397
413
  confirmations: number;
398
414
  }
399
415
  /**
@@ -528,6 +544,21 @@ interface GatewayV1Contracts {
528
544
  * @example "0xabcdef1234567890abcdef1234567890abcdef12"
529
545
  */
530
546
  minter: string;
547
+ /**
548
+ * The address of the `DepositForHandler` contract.
549
+ *
550
+ * @description Optional. The handler the GenericExecutor calls on this chain
551
+ * to run a fast cross-chain deposit into the {@link GatewayV1Contracts.wallet}.
552
+ * Present only on chains that are fast-deposit destinations; other Gateway
553
+ * chains omit it.
554
+ *
555
+ * Address format varies by blockchain:
556
+ * - EVM chains: 40-character hexadecimal with 0x prefix (e.g., "0x1234...")
557
+ * - Solana: Base58-encoded 32-byte address (e.g., "9WzDX...")
558
+ *
559
+ * @example "0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48"
560
+ */
561
+ depositForHandler?: string;
531
562
  }
532
563
  /**
533
564
  * Versioned map of Gateway contract configurations.
@@ -659,6 +690,8 @@ declare enum Blockchain {
659
690
  Celo_Alfajores_Testnet = "Celo_Alfajores_Testnet",
660
691
  Codex = "Codex",
661
692
  Codex_Testnet = "Codex_Testnet",
693
+ Cronos = "Cronos",
694
+ Cronos_Testnet = "Cronos_Testnet",
662
695
  Edge = "Edge",
663
696
  Edge_Testnet = "Edge_Testnet",
664
697
  Ethereum = "Ethereum",
@@ -900,6 +933,7 @@ declare enum BridgeChain {
900
933
  Avalanche = "Avalanche",
901
934
  Base = "Base",
902
935
  Codex = "Codex",
936
+ Cronos = "Cronos",
903
937
  Edge = "Edge",
904
938
  Ethereum = "Ethereum",
905
939
  HyperEVM = "HyperEVM",
@@ -923,6 +957,7 @@ declare enum BridgeChain {
923
957
  Avalanche_Fuji = "Avalanche_Fuji",
924
958
  Base_Sepolia = "Base_Sepolia",
925
959
  Codex_Testnet = "Codex_Testnet",
960
+ Cronos_Testnet = "Cronos_Testnet",
926
961
  Edge_Testnet = "Edge_Testnet",
927
962
  Ethereum_Sepolia = "Ethereum_Sepolia",
928
963
  HyperEVM_Testnet = "HyperEVM_Testnet",
@@ -2173,6 +2208,110 @@ interface CCTPv2ActionMap {
2173
2208
  */
2174
2209
  hookData: string;
2175
2210
  };
2211
+ /**
2212
+ * Initiate a prepaid cross-chain USDC transfer through the `TokenMessengerWithFees` wrapper.
2213
+ *
2214
+ * Burn USDC on the source chain while collecting all fees up front against a
2215
+ * signed quote. The wrapper collects the fee via `FeeManager`, then delegates
2216
+ * to the unmodified `TokenMessengerV2`. When `hookData` is provided (the
2217
+ * GenericExecutor FORWARD path) the wrapper's `depositForBurnWithHookAndFees`
2218
+ * contract method is used; otherwise `depositForBurnWithFees` is used.
2219
+ *
2220
+ * @remarks
2221
+ * SDK/contract naming: this SDK action is `depositForBurnWithFees` but, when a
2222
+ * `hookData` is present, it dispatches to the `depositForBurnWithHookAndFees`
2223
+ * contract method on `TokenMessengerWithFees` (NOT on `TokenMessengerV2`).
2224
+ *
2225
+ * Fee payment channel (must match the quote's `feeToken`):
2226
+ * - Native fee (`feeToken` is the zero address): exactly `feeTotalAmount` is
2227
+ * attached as `msg.value`.
2228
+ * - ERC-20 fee (e.g. USDC): no value is attached; the caller must first approve
2229
+ * the wrapper for `feeTotalAmount` (see the provider's fee approval helper).
2230
+ *
2231
+ * @remarks
2232
+ * Unlike `depositForBurn`, the `TokenMessengerWithFees` contract methods do NOT
2233
+ * take `maxFee` or `minFinalityThreshold` — fee and finality behavior are
2234
+ * derived from the signed quote — so those fields are omitted from this action.
2235
+ *
2236
+ * @example
2237
+ * ```typescript
2238
+ * await adapter.action('cctp.v2.depositForBurnWithFees', {
2239
+ * amount: BigInt('1000000'),
2240
+ * mintRecipient: executorAddress, // GenericExecutor (bytes32)
2241
+ * destinationCaller: executorAddress, // GenericExecutor (bytes32)
2242
+ * fromChain: ethereum,
2243
+ * toChain: arc,
2244
+ * hookData: geForwardHookData, // cctp-forward-wrapped GenericExecutor blob
2245
+ * claim: { signedQuote: '0x...', refundAddress: '0x...' },
2246
+ * feeToken: '0x0000000000000000000000000000000000000000', // native
2247
+ * feeTotalAmount: 3500000n,
2248
+ * })
2249
+ * ```
2250
+ */
2251
+ depositForBurnWithFees: Omit<CCTPv2ActionMap['depositForBurn'], 'maxFee' | 'minFinalityThreshold'> & {
2252
+ /**
2253
+ * Optional hex-encoded hook data for the GenericExecutor FORWARD path.
2254
+ *
2255
+ * When present, the `depositForBurnWithHookAndFees` contract method is used
2256
+ * and the blob must be wrapped in the `cctp-forward` envelope (the wrapper
2257
+ * rejects a FORWARD fee quote whose hook lacks it). When omitted, the plain
2258
+ * `depositForBurnWithFees` contract method is used.
2259
+ */
2260
+ hookData?: string;
2261
+ /**
2262
+ * Signed fee quote claim passed to the `TokenMessengerWithFees` wrapper.
2263
+ *
2264
+ * `signedQuote` is the `[uint8 0x01][abi.encode(Quote)]` blob returned by the
2265
+ * Fee Quote service; `refundAddress` receives any fee overpayment refund.
2266
+ */
2267
+ claim: QuoteClaim;
2268
+ /**
2269
+ * Fee token from the signed quote.
2270
+ *
2271
+ * The zero address (`0x000…0`) means the fee is paid in native currency and
2272
+ * is attached as `msg.value`. Any other address (e.g. USDC) means an ERC-20
2273
+ * fee that must be approved to the wrapper beforehand. This is independent of
2274
+ * `burnToken`, which is always USDC.
2275
+ */
2276
+ feeToken: string;
2277
+ /**
2278
+ * Total fee amount from the signed quote, in `feeToken` minor units.
2279
+ *
2280
+ * Firm only until the quote's `expiresAt`. For a native fee this is the exact
2281
+ * `msg.value`; for an ERC-20 fee this is the amount approved to the wrapper.
2282
+ */
2283
+ feeTotalAmount: bigint;
2284
+ };
2285
+ }
2286
+ /**
2287
+ * Signed fee quote claim consumed by the `TokenMessengerWithFees` wrapper.
2288
+ *
2289
+ * Mirrors the on-chain `IFeeManager.QuoteClaim` struct.
2290
+ *
2291
+ * @example
2292
+ * ```typescript
2293
+ * const claim: QuoteClaim = {
2294
+ * signedQuote: '0x01...', // [uint8 0x01][abi.encode(Quote)]
2295
+ * refundAddress: '0xUserWallet...',
2296
+ * }
2297
+ * ```
2298
+ */
2299
+ interface QuoteClaim {
2300
+ /**
2301
+ * Opaque signed quote bytes (`0x` hex) from the fee-quote service
2302
+ * (`SignedFeeQuote.signedQuote` returned by `fetchFeeQuote`). Pass verbatim;
2303
+ * do not decode.
2304
+ *
2305
+ * The quote binds the FORWARD fee item to the on-chain call via `argsHash`;
2306
+ * passing a quote that does not match the burn args reverts `QuoteArgsMismatch`.
2307
+ */
2308
+ signedQuote: string;
2309
+ /**
2310
+ * Address that receives any refund of overpaid fees.
2311
+ *
2312
+ * Typically the user wallet that authorized the burn.
2313
+ */
2314
+ refundAddress: string;
2176
2315
  }
2177
2316
 
2178
2317
  /**
@@ -6078,6 +6217,30 @@ declare class Amount implements AmountFields {
6078
6217
  toJSON(): AmountJSON;
6079
6218
  }
6080
6219
 
6220
+ /** @internal */
6221
+ declare const bridgeQuoteExpirySchema: z.ZodCatch<z.ZodOptional<z.ZodDiscriminatedUnion<"mode", [z.ZodObject<{
6222
+ mode: z.ZodLiteral<"TIMESTAMP">;
6223
+ expiresAt: z.ZodString;
6224
+ }, "strip", z.ZodTypeAny, {
6225
+ mode: "TIMESTAMP";
6226
+ expiresAt: string;
6227
+ }, {
6228
+ mode: "TIMESTAMP";
6229
+ expiresAt: string;
6230
+ }>, z.ZodObject<{
6231
+ mode: z.ZodLiteral<"BLOCK_NUMBER">;
6232
+ expiresAtBlock: z.ZodNumber;
6233
+ blockEstimatedAt: z.ZodOptional<z.ZodString>;
6234
+ }, "strip", z.ZodTypeAny, {
6235
+ mode: "BLOCK_NUMBER";
6236
+ expiresAtBlock: number;
6237
+ blockEstimatedAt?: string | undefined;
6238
+ }, {
6239
+ mode: "BLOCK_NUMBER";
6240
+ expiresAtBlock: number;
6241
+ blockEstimatedAt?: string | undefined;
6242
+ }>]>>>;
6243
+
6081
6244
  /**
6082
6245
  * A single vault query specifying chain and vault address.
6083
6246
  *
@@ -6125,6 +6288,7 @@ interface VaultRewardInfo {
6125
6288
  * assetAddress: '0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf',
6126
6289
  * lltv: 0.86,
6127
6290
  * supplyUsd: 50000000.25,
6291
+ * allocationPct: 0.6,
6128
6292
  * }
6129
6293
  * ```
6130
6294
  */
@@ -6137,6 +6301,17 @@ interface CollateralInfo {
6137
6301
  readonly lltv: number;
6138
6302
  /** Approximate supplied value in USD, e.g. 50000000.25 for $50,000,000.25. */
6139
6303
  readonly supplyUsd: number;
6304
+ /**
6305
+ * Share of the vault's supply allocated to this collateral market
6306
+ * (e.g., 0.6 = 60%).
6307
+ *
6308
+ * Populated for Morpho V1 vaults; `null` when the underlying product
6309
+ * exposes no per-market allocation (e.g. Morpho V2). Optional for now — a
6310
+ * backend that predates this field omits it entirely, matching the other
6311
+ * optional facets on {@link EarnOpportunityBase}; a future release makes it
6312
+ * required once every backend emits it.
6313
+ */
6314
+ readonly allocationPct?: number | null | undefined;
6140
6315
  }
6141
6316
  /**
6142
6317
  * Vault warning from the underlying earn protocol.
@@ -6156,65 +6331,253 @@ interface VaultWarning {
6156
6331
  readonly level: 'YELLOW' | 'RED';
6157
6332
  }
6158
6333
  /**
6159
- * Describe a yield-bearing vault available through the earn service.
6334
+ * Manager (e.g., curator) responsible for a yield opportunity.
6335
+ *
6336
+ * Generalizes Morpho's "curator". `null` on the opportunity when the
6337
+ * underlying product has no per-opportunity manager (e.g., a pooled
6338
+ * lending market).
6160
6339
  *
6161
6340
  * @example
6162
6341
  * ```typescript
6163
- * const vault: VaultInfo = {
6164
- * vaultAddress: '0xAabbeF1D3971c710276ed41eC791BbE14CdB8E88',
6165
- * chain: 'Arc_Testnet',
6166
- * name: 'Steakhouse USDC',
6167
- * protocol: 'MORPHO',
6168
- * asset: 'USDC',
6169
- * assetAddress: '0x3600000000000000000000000000000000000000',
6170
- * currentApy: 0.0425,
6171
- * nativeApy: 0.035,
6172
- * vaultFee: 0.05,
6173
- * rewards: [{ token: 'MORPHO', tokenAddress: '0x...', apy: 0.0075 }],
6174
- * collateral: [{ asset: 'cbBTC', assetAddress: '0x...', lltv: 0.86, supplyUsd: 50000000.25 }],
6175
- * totalDeposits: Amount.fromJSON({ raw: '15000000000000', decimals: 6 }),
6176
- * liquidity: Amount.fromJSON({ raw: '5000000000000', decimals: 6 }),
6342
+ * const manager: ManagerInfo = {
6343
+ * name: 'Steakhouse',
6344
+ * address: '0x...',
6345
+ * type: 'curator',
6346
+ * }
6347
+ * ```
6348
+ */
6349
+ interface ManagerInfo {
6350
+ /** Human-readable manager name. */
6351
+ readonly name: string;
6352
+ /** On-chain manager address, when the product exposes one. */
6353
+ readonly address?: string | undefined;
6354
+ /**
6355
+ * Manager role within the product. Only `'curator'` is emitted today
6356
+ * (Morpho V1/V2); additional roles are added as the providers that emit
6357
+ * them land.
6358
+ */
6359
+ readonly type: 'curator';
6360
+ }
6361
+ /**
6362
+ * Yield profile for an opportunity, including trailing averages.
6363
+ *
6364
+ * `current` is always present; trailing and native values are `null` when
6365
+ * unavailable for this instance (e.g., a vault younger than the lookback
6366
+ * window). `source`/`asOf` carry provenance for derived/staleness-prone
6367
+ * values.
6368
+ *
6369
+ * @example
6370
+ * ```typescript
6371
+ * const apyProfile: ApyProfile = {
6372
+ * current: 0.085,
6373
+ * native: 0.071,
6374
+ * d7: 0.082,
6375
+ * d30: 0.079,
6376
+ * d90: 0.081,
6377
+ * rewardShare: 0.16,
6378
+ * source: 'morpho:avgNetApy',
6379
+ * asOf: '2026-06-23T18:00:00Z',
6380
+ * }
6381
+ * ```
6382
+ */
6383
+ interface ApyProfile {
6384
+ /** Current total APY including rewards. */
6385
+ readonly current: number;
6386
+ /** Native APY excluding reward incentives; `null` when unavailable. */
6387
+ readonly native: number | null;
6388
+ /** Trailing 7-day average net APY; `null` when unavailable. */
6389
+ readonly d7: number | null;
6390
+ /** Trailing 30-day average net APY; `null` when unavailable. */
6391
+ readonly d30: number | null;
6392
+ /** Trailing 90-day average net APY; `null` when unavailable. */
6393
+ readonly d90: number | null;
6394
+ /** Share of current APY attributable to rewards; `null` when unavailable. */
6395
+ readonly rewardShare: number | null;
6396
+ /** Provenance of the trailing values (`native` or `circle:<source>`). */
6397
+ readonly source?: string | undefined;
6398
+ /** RFC3339 timestamp of the newest input used for the trailing values. */
6399
+ readonly asOf?: string | undefined;
6400
+ }
6401
+ /**
6402
+ * Fee split for an opportunity.
6403
+ *
6404
+ * Each component is `null` when the product does not levy it (e.g., Morpho
6405
+ * V1 vaults have no management fee).
6406
+ *
6407
+ * @example
6408
+ * ```typescript
6409
+ * const fee: FeeInfo = { performance: 0.1, management: null }
6410
+ * ```
6411
+ */
6412
+ interface FeeInfo {
6413
+ /** Performance fee as a decimal (e.g., 0.1 = 10%); `null` when unavailable. */
6414
+ readonly performance: number | null;
6415
+ /** Management fee as a decimal; `null` when unavailable. */
6416
+ readonly management: number | null;
6417
+ }
6418
+ /**
6419
+ * Liquidity profile for an opportunity.
6420
+ *
6421
+ * @example
6422
+ * ```typescript
6423
+ * const liquidityProfile: LiquidityProfile = {
6424
+ * totalDeposits: Amount.fromJSON({ raw: '45000000000000', decimals: 6 }),
6425
+ * available: Amount.fromJSON({ raw: '5200000000000', decimals: 6 }),
6426
+ * totalSupply: Amount.fromJSON({ raw: '44900000000000000000', decimals: 18 }),
6177
6427
  * status: 'active',
6178
- * circleGuarded: false,
6179
6428
  * }
6180
6429
  * ```
6181
6430
  */
6182
- interface VaultInfo {
6183
- /** On-chain vault contract address. */
6184
- readonly vaultAddress: string;
6185
- /** Blockchain where the vault is deployed. */
6431
+ interface LiquidityProfile {
6432
+ /** Total value deposited in base-unit amount form. */
6433
+ readonly totalDeposits: Amount;
6434
+ /** Available liquidity in base-unit amount form. */
6435
+ readonly available: Amount;
6436
+ /** Outstanding vault share tokens (ERC4626 totalSupply) in base-unit form. */
6437
+ readonly totalSupply: Amount;
6438
+ /** Current liquidity status. */
6439
+ readonly status: 'active' | 'low_liquidity';
6440
+ }
6441
+ /**
6442
+ * Risk signals for an opportunity.
6443
+ *
6444
+ * @example
6445
+ * ```typescript
6446
+ * const riskSignals: RiskSignals = {
6447
+ * circleSentinel: true,
6448
+ * warnings: [],
6449
+ * earnKitWarnings: [],
6450
+ * }
6451
+ * ```
6452
+ */
6453
+ interface RiskSignals {
6454
+ /** Whether the opportunity is covered by Circle Sentinel. */
6455
+ readonly circleSentinel: boolean;
6456
+ /** Protocol warnings for this opportunity. */
6457
+ readonly warnings?: readonly VaultWarning[] | undefined;
6458
+ /** Circle-specific warnings (e.g., unsupported reward protocol). */
6459
+ readonly earnKitWarnings?: readonly string[] | undefined;
6460
+ }
6461
+ /**
6462
+ * Facets common to every earn opportunity, plus the deprecated flat
6463
+ * fields retained for backward compatibility.
6464
+ *
6465
+ * The flat aliases are emitted by the backend alongside the nested facets
6466
+ * and mapped straight through, so existing consumers keep reading them until
6467
+ * they are removed in a future major release. Narrow on
6468
+ * {@link EarnOpportunity.productType} to access product-specific fields.
6469
+ */
6470
+ interface EarnOpportunityBase {
6471
+ /** Blockchain where the opportunity is deployed. */
6186
6472
  readonly chain: `${EarnChain}`;
6187
- /** Human-readable vault name. */
6473
+ /** Human-readable opportunity name. */
6188
6474
  readonly name: string;
6189
- /** Vault protocol identifier. */
6475
+ /** Protocol identifier. */
6190
6476
  readonly protocol: string;
6191
6477
  /** Underlying deposit asset symbol (e.g., 'USDC'). */
6192
6478
  readonly asset: string;
6193
6479
  /** Underlying deposit asset contract address. */
6194
6480
  readonly assetAddress: string;
6195
- /** Total annualized percentage yield including rewards. */
6481
+ /** Reward tokens distributed by this opportunity. */
6482
+ readonly rewards: readonly VaultRewardInfo[];
6483
+ /** Primary on-chain address (protocol-neutral; replaces vaultAddress). */
6484
+ readonly address?: string | undefined;
6485
+ /** RFC3339 freshness timestamp: provider state ts, else cache sync time. */
6486
+ readonly asOf?: string | undefined;
6487
+ /** Manager/curator identity; `null` when the product has no manager. */
6488
+ readonly manager?: ManagerInfo | null | undefined;
6489
+ /** Yield profile including trailing averages. */
6490
+ readonly apyProfile?: ApyProfile | undefined;
6491
+ /** Fee split. */
6492
+ readonly fee?: FeeInfo | undefined;
6493
+ /** Liquidity profile. */
6494
+ readonly liquidityProfile?: LiquidityProfile | undefined;
6495
+ /** Risk signals. */
6496
+ readonly riskSignals?: RiskSignals | undefined;
6497
+ /** @deprecated use {@link EarnOpportunityBase.address} */
6498
+ readonly vaultAddress: string;
6499
+ /** @deprecated use {@link ApyProfile.current} via apyProfile */
6196
6500
  readonly currentApy: number;
6197
- /** Native APY excluding reward incentives. */
6501
+ /** @deprecated use {@link ApyProfile.native} via apyProfile */
6198
6502
  readonly nativeApy: number;
6199
- /** Vault fee as a decimal (e.g., 0.05 = 5%). */
6503
+ /** @deprecated use {@link FeeInfo.performance} via fee */
6200
6504
  readonly vaultFee: number;
6201
- /** Reward tokens distributed by this vault. */
6202
- readonly rewards: readonly VaultRewardInfo[];
6203
- /** Collateral markets backing this vault. */
6204
- readonly collateral: readonly CollateralInfo[];
6205
- /** Total value deposited in base-unit amount form. */
6505
+ /** @deprecated use {@link LiquidityProfile.totalDeposits} via liquidityProfile */
6206
6506
  readonly totalDeposits: Amount;
6207
- /** Available liquidity in the vault. */
6507
+ /** @deprecated use {@link LiquidityProfile.available} via liquidityProfile */
6208
6508
  readonly liquidity: Amount;
6209
- /** Current vault status. */
6509
+ /** @deprecated use {@link LiquidityProfile.status} via liquidityProfile */
6210
6510
  readonly status: 'active' | 'low_liquidity';
6211
- /** Whether the vault is on Circle's curated Circle-guarded list. */
6511
+ /** @deprecated use {@link RiskSignals.circleSentinel} via riskSignals */
6212
6512
  readonly circleGuarded: boolean;
6213
- /** Morpho protocol warnings for this vault. */
6513
+ /** @deprecated use {@link RiskSignals.warnings} via riskSignals */
6214
6514
  readonly warnings?: readonly VaultWarning[] | undefined;
6215
- /** Circle-specific warnings (e.g., unsupported reward protocol). */
6515
+ /** @deprecated use {@link RiskSignals.earnKitWarnings} via riskSignals */
6216
6516
  readonly earnKitWarnings?: readonly string[] | undefined;
6217
6517
  }
6518
+ /**
6519
+ * A yield-bearing vault opportunity (`productType: 'vault'`).
6520
+ *
6521
+ * Carries the universal {@link EarnOpportunityBase} facets plus the
6522
+ * vault-specific `collateral` markets.
6523
+ *
6524
+ * @example
6525
+ * ```typescript
6526
+ * const vault: VaultOpportunity = {
6527
+ * productType: 'vault',
6528
+ * address: '0x8eB67A509616cd6A7c1B3c8C21D48FF57df3d458',
6529
+ * chain: 'Arc_Testnet',
6530
+ * name: 'Steakhouse USDC',
6531
+ * protocol: 'MORPHO',
6532
+ * asset: 'USDC',
6533
+ * assetAddress: '0x3600000000000000000000000000000000000000',
6534
+ * asOf: '2026-06-23T18:00:00Z',
6535
+ * manager: { name: 'Steakhouse', address: '0x...', type: 'curator' },
6536
+ * apyProfile: { current: 0.085, native: 0.071, d7: 0.082, d30: 0.079, d90: 0.081, rewardShare: 0.16 },
6537
+ * fee: { performance: 0.1, management: null },
6538
+ * liquidityProfile: {
6539
+ * totalDeposits: Amount.fromJSON({ raw: '15000000000000', decimals: 6 }),
6540
+ * available: Amount.fromJSON({ raw: '5000000000000', decimals: 6 }),
6541
+ * totalSupply: Amount.fromJSON({ raw: '14950000000000000000', decimals: 18 }),
6542
+ * status: 'active',
6543
+ * },
6544
+ * riskSignals: { circleSentinel: true, warnings: [], earnKitWarnings: [] },
6545
+ * rewards: [{ token: 'MORPHO', tokenAddress: '0x...', apy: 0.0075 }],
6546
+ * collateral: [{ asset: 'cbBTC', assetAddress: '0x...', lltv: 0.86, supplyUsd: 50000000.25, allocationPct: 0.6 }],
6547
+ * // deprecated flat aliases (dual-emitted during migration)
6548
+ * vaultAddress: '0x8eB67A509616cd6A7c1B3c8C21D48FF57df3d458',
6549
+ * currentApy: 0.085,
6550
+ * nativeApy: 0.071,
6551
+ * vaultFee: 0.1,
6552
+ * totalDeposits: Amount.fromJSON({ raw: '15000000000000', decimals: 6 }),
6553
+ * liquidity: Amount.fromJSON({ raw: '5000000000000', decimals: 6 }),
6554
+ * status: 'active',
6555
+ * circleGuarded: true,
6556
+ * }
6557
+ * ```
6558
+ */
6559
+ interface VaultOpportunity extends EarnOpportunityBase {
6560
+ /**
6561
+ * Universal discriminator identifying the opportunity shape.
6562
+ *
6563
+ * Optional for now — a backend that predates the field omits it, matching
6564
+ * the other optional facets — so this release stays source-compatible for
6565
+ * code that constructs the type. A future release makes it required once
6566
+ * every backend emits it. Always present on responses from an emitting
6567
+ * backend; narrow on it before reading product-specific fields.
6568
+ */
6569
+ readonly productType?: 'vault';
6570
+ /** Collateral markets backing this vault. */
6571
+ readonly collateral: readonly CollateralInfo[];
6572
+ }
6573
+ /**
6574
+ * A yield opportunity available through the earn service.
6575
+ *
6576
+ * Modeled as a discriminated union on `productType` over a shared base.
6577
+ * Only the `vault` variant ships today; additional product types (e.g.
6578
+ * `lending_market`, `rwa_token`) are added as additive union members.
6579
+ */
6580
+ type EarnOpportunity = VaultOpportunity;
6218
6581
  /**
6219
6582
  * Per-vault error from a batch vault lookup.
6220
6583
  *
@@ -6380,10 +6743,11 @@ interface AssetAmount {
6380
6743
  /**
6381
6744
  * Optional category tag for the amount.
6382
6745
  *
6383
- * Present on fee entries to identify the kind of fee for cross-chain
6384
- * deposit quotes this is the source-fee item type (e.g. `'FORWARD'`,
6385
- * `'PRE_FINALITY'`). Omitted when the amount has no meaningful category
6386
- * (plain deposit/withdrawal/share/reward amounts).
6746
+ * Present on fee entries to identify the kind of fee. For cross-chain deposit
6747
+ * quotes this is the source-fee item type (e.g. `'FORWARD'`,
6748
+ * `'PRE_FINALITY'`), and for withdrawal quotes this can identify Circle fees
6749
+ * (e.g. `'circle'`). Omitted when the amount has no meaningful
6750
+ * category (plain deposit/withdrawal/share/reward amounts).
6387
6751
  */
6388
6752
  readonly type?: string | undefined;
6389
6753
  /**
@@ -6393,6 +6757,14 @@ interface AssetAmount {
6393
6757
  */
6394
6758
  readonly status?: string | undefined;
6395
6759
  }
6760
+ /**
6761
+ * Source-fee quote expiry metadata returned by bridge prepare.
6762
+ *
6763
+ * `TIMESTAMP` expiries use an ISO-8601 UTC `expiresAt`; `BLOCK_NUMBER`
6764
+ * expiries use a source-chain `expiresAtBlock`, with an optional ISO-8601 UTC
6765
+ * `blockEstimatedAt` for when that block estimate was produced.
6766
+ */
6767
+ type EarnBridgeQuoteExpiry = Readonly<Exclude<z.infer<typeof bridgeQuoteExpirySchema>, undefined>>;
6396
6768
  /**
6397
6769
  * Result of a deposit operation returned by
6398
6770
  * {@link EarningProvider.deposit}.
@@ -6493,6 +6865,13 @@ interface EarnCrossChainDepositResult {
6493
6865
  * @example '2026-05-19T00:00:00Z'
6494
6866
  */
6495
6867
  readonly expiresAt: string;
6868
+ /** ISO-8601 UTC timestamp at which the source-fee quote was issued. */
6869
+ readonly quoteIssuedAt?: string | undefined;
6870
+ /**
6871
+ * Optional source-fee quote expiry metadata for display and refresh UX.
6872
+ * This deadline is independent of the prepared-bundle `expiresAt` above.
6873
+ */
6874
+ readonly quoteExpiry?: EarnBridgeQuoteExpiry | undefined;
6496
6875
  }
6497
6876
  /**
6498
6877
  * Status of one hop (source relay or destination mint) of a cross-chain
@@ -6753,27 +7132,21 @@ interface DepositQuoteInfo {
6753
7132
  */
6754
7133
  readonly fees: readonly AssetAmount[];
6755
7134
  /**
6756
- * Estimated native gas fees for the transactions needed to deposit
6757
- * (e.g. token approval and the deposit itself).
7135
+ * Estimated native gas fees for the transactions needed to deposit (e.g.
7136
+ * token approval and the deposit itself).
6758
7137
  *
6759
7138
  * Optional so that custom {@link EarningProvider} implementations are not
6760
7139
  * required to produce gas estimates. The bundled Earn Service provider
6761
- * always populates this with one entry per transaction in the flow. When an
6762
- * individual estimate cannot be produced, that entry is still present with
6763
- * `fees` set to `null` and `error` describing why — so a non-empty array
6764
- * does not imply every estimate succeeded; inspect each entry's `fees`.
6765
- *
6766
- * The number of entries depends on where estimation stopped: when the flow
6767
- * fails before the approval step is examined, a single entry named after
6768
- * the main action is returned. Look entries up by `name`, not by index.
6769
- *
6770
- * Each estimate simulates the transaction against current chain state.
6771
- * When a token approval is still pending (typically a first-time deposit),
6772
- * the deposit simulation reverts because the allowance is not yet in
6773
- * place, so the deposit entry resolves with `fees: null` while the
6774
- * approval entry still carries a real estimate. Render a fallback (e.g.
6775
- * "available after approval") for that case rather than treating it as an
6776
- * error.
7140
+ * populates this from the server-side estimate returned on the quote, with
7141
+ * one entry per action. Empty for cross-chain quotes, which resolve no
7142
+ * single source chain.
7143
+ *
7144
+ * Each entry is the Earn Service's estimate for that action, so a pending
7145
+ * token approval no longer causes the deposit entry to fail. An entry may
7146
+ * still carry `fees: null` with an `error` when the service could not
7147
+ * estimate it, so a non-empty array does not imply every estimate
7148
+ * succeeded — inspect each entry's `fees` and look entries up by `name`,
7149
+ * not by index.
6777
7150
  */
6778
7151
  readonly gasFees?: readonly EarnGasFeeEstimate$1[] | undefined;
6779
7152
  }
@@ -6806,29 +7179,29 @@ interface WithdrawalQuoteInfo {
6806
7179
  * available balance and quoted withdrawal in a single round-trip.
6807
7180
  */
6808
7181
  readonly maxWithdrawable: AssetAmount;
6809
- /** Fees applied to the withdrawal. */
7182
+ /**
7183
+ * Fees applied to the withdrawal.
7184
+ *
7185
+ * Circle fees are returned with `type: 'circle'` so callers can distinguish
7186
+ * them from untyped plain fees and native gas estimates.
7187
+ */
6810
7188
  readonly fees: readonly AssetAmount[];
6811
7189
  /**
6812
- * Estimated native gas fees for the transactions needed to withdraw.
7190
+ * Estimated native gas fees for the transactions needed to withdraw (e.g.
7191
+ * vault-share approval and the withdrawal itself).
6813
7192
  *
6814
7193
  * Optional so that custom {@link EarningProvider} implementations are not
6815
7194
  * required to produce gas estimates. The bundled Earn Service provider
6816
- * always populates this with one entry per transaction in the flow. When an
6817
- * individual estimate cannot be produced, that entry is still present with
6818
- * `fees` set to `null` and `error` describing why — so a non-empty array
6819
- * does not imply every estimate succeeded; inspect each entry's `fees`.
6820
- *
6821
- * The number of entries depends on where estimation stopped: when the flow
6822
- * fails before the approval step is examined, a single entry named after
6823
- * the main action is returned. Look entries up by `name`, not by index.
6824
- *
6825
- * Each estimate simulates the transaction against current chain state.
6826
- * When a vault-share approval is still pending (typically the first
6827
- * withdrawal from a vault), the withdrawal simulation reverts because the
6828
- * allowance is not yet in place, so the withdrawal entry resolves with
6829
- * `fees: null` while the approval entry still carries a real estimate.
6830
- * Render a fallback (e.g. "available after approval") for that case
6831
- * rather than treating it as an error.
7195
+ * populates this from the server-side estimate returned on the quote, with
7196
+ * one entry per action. Empty for cross-chain quotes, which resolve no
7197
+ * single source chain.
7198
+ *
7199
+ * Each entry is the Earn Service's estimate for that action, so a pending
7200
+ * vault-share approval no longer causes the withdrawal entry to fail. An
7201
+ * entry may still carry `fees: null` with an `error` when the service could
7202
+ * not estimate it, so a non-empty array does not imply every estimate
7203
+ * succeeded — inspect each entry's `fees` and look entries up by `name`,
7204
+ * not by index.
6832
7205
  */
6833
7206
  readonly gasFees?: readonly EarnGasFeeEstimate$1[] | undefined;
6834
7207
  /**
@@ -6861,16 +7234,13 @@ interface ClaimRewardsQuoteInfo {
6861
7234
  /** Reward tokens available for claiming. */
6862
7235
  readonly rewards: readonly AssetAmount[];
6863
7236
  /**
6864
- * Estimated native gas fees for claiming rewards. Empty when there are no
6865
- * rewards to claim.
7237
+ * Estimated native gas fees for claiming rewards.
6866
7238
  *
6867
7239
  * Optional so that custom {@link EarningProvider} implementations are not
6868
- * required to produce gas estimates. Otherwise the bundled Earn Service
6869
- * provider populates this with one entry per claim transaction; when an
6870
- * estimate cannot be produced, that entry is still present with `fees` set
6871
- * to `null` and `error` describing why — so a non-empty array does not imply
6872
- * every estimate succeeded; inspect each entry's `fees`. Look entries up by
6873
- * `name`, not by index.
7240
+ * required to produce gas estimates. The bundled Earn Service provider does
7241
+ * not return a gas estimate for claim-rewards quotes, so this is always
7242
+ * empty (`[]`); it is retained for API symmetry with the deposit and
7243
+ * withdrawal quotes.
6874
7244
  */
6875
7245
  readonly gasFees?: readonly EarnGasFeeEstimate$1[] | undefined;
6876
7246
  }
@@ -6881,8 +7251,8 @@ interface ClaimRewardsQuoteInfo {
6881
7251
  * `vaults` while per-vault failures are in `errors`.
6882
7252
  */
6883
7253
  interface GetVaultsResult {
6884
- /** Successfully resolved vault information. */
6885
- readonly vaults: readonly VaultInfo[];
7254
+ /** Successfully resolved opportunities. */
7255
+ readonly vaults: readonly EarnOpportunity[];
6886
7256
  /** Per-vault errors for failed lookups. */
6887
7257
  readonly errors: readonly VaultError[];
6888
7258
  }
@@ -6935,7 +7305,7 @@ interface ExploreVaultsPagination {
6935
7305
  */
6936
7306
  interface ExploreVaultsResult {
6937
7307
  /** Vaults matching the query, in the requested sort order. */
6938
- readonly vaults: readonly VaultInfo[];
7308
+ readonly vaults: readonly EarnOpportunity[];
6939
7309
  /** Pagination metadata for the query. */
6940
7310
  readonly pagination: ExploreVaultsPagination;
6941
7311
  }
@@ -7498,12 +7868,42 @@ type EarnAssetAmount = Omit<AssetAmount, 'amount'> & {
7498
7868
  /** Token amount in human-readable decimal format. */
7499
7869
  readonly amount: string;
7500
7870
  };
7501
- /** Vault information returned by the SDK. */
7502
- type EarnVaultInfo = Omit<VaultInfo, 'totalDeposits' | 'liquidity'> & {
7871
+ /**
7872
+ * Distributive `Omit` over a union.
7873
+ *
7874
+ * A plain `Omit<Union, K>` is not distributive: `keyof (A | B)` collapses to
7875
+ * the shared keys, dropping every variant-specific field and the discriminant
7876
+ * narrowing. Distributing over each member preserves the union.
7877
+ */
7878
+ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
7879
+ /** Liquidity profile returned by the SDK with amounts as decimal strings. */
7880
+ type EarnLiquidityProfile = Omit<LiquidityProfile, 'totalDeposits' | 'available' | 'totalSupply'> & {
7881
+ /** Total value deposited in human-readable decimal format. */
7882
+ readonly totalDeposits: string;
7883
+ /** Available liquidity in human-readable decimal format. */
7884
+ readonly available: string;
7885
+ /** Outstanding vault share tokens (ERC4626 totalSupply) in decimal format. */
7886
+ readonly totalSupply: string;
7887
+ };
7888
+ /**
7889
+ * Vault information returned by the SDK.
7890
+ *
7891
+ * Derived with a distributive `Omit` so each opportunity variant keeps its
7892
+ * product-specific fields and the `productType` discriminant.
7893
+ */
7894
+ type EarnVaultInfo = DistributiveOmit<EarnOpportunity, 'totalDeposits' | 'liquidity' | 'liquidityProfile'> & {
7503
7895
  /** Total value deposited in human-readable decimal format. */
7504
7896
  readonly totalDeposits: string;
7505
7897
  /** Available liquidity in the vault in human-readable decimal format. */
7506
7898
  readonly liquidity: string;
7899
+ /**
7900
+ * Liquidity profile with amounts as human-readable decimal strings.
7901
+ *
7902
+ * Optional during the expand/contract migration window: a backend that
7903
+ * predates the nested facets omits it, so it is absent until the response
7904
+ * carries it.
7905
+ */
7906
+ readonly liquidityProfile?: EarnLiquidityProfile;
7507
7907
  };
7508
7908
  /** Result of a batch vault lookup. */
7509
7909
  type EarnGetVaultsResult = Omit<GetVaultsResult, 'vaults'> & {
@@ -8034,26 +8434,28 @@ interface AppKitContext {
8034
8434
  * Event handlers registered for AppKit operations.
8035
8435
  *
8036
8436
  * This property stores event handlers that are registered via the AppKit's
8037
- * `on()` method. Handlers are grouped by operation type. The current runtime
8038
- * bucket is `bridge`, and the context can add more operation buckets as AppKit
8039
- * wires action handlers for additional kits.
8437
+ * `on()` method. Handlers are grouped by operation type. The runtime buckets
8438
+ * are `bridge` and `earn`; the context can add more operation buckets as
8439
+ * AppKit wires action handlers for additional kits.
8040
8440
  *
8041
- * Within each operation bucket, handlers are keyed by action name (for example,
8042
- * `bridge.approve`) or `*` for wildcard handlers. Each action can have multiple
8043
- * handlers registered, allowing multiple subscribers to listen to the same event.
8441
+ * Within each operation bucket, handlers are keyed by action name (for
8442
+ * example, `bridge.approve` or `earn.deposit`) or `*` for wildcard handlers.
8443
+ * Each action can have multiple handlers registered, allowing multiple
8444
+ * subscribers to listen to the same event.
8044
8445
  *
8045
8446
  * The handlers are stored in the context to allow deferred registration with
8046
- * underlying operation kits, enabling a clean separation between event registration
8047
- * and operation execution.
8447
+ * underlying operation kits, enabling a clean separation between event
8448
+ * registration and operation execution.
8048
8449
  *
8049
8450
  * @example
8050
8451
  * ```typescript
8051
8452
  * const context = createContext()
8052
8453
  * // Handlers registered via kit.on() are stored by operation type
8053
- * // Bridge handlers are registered with BridgeKit when bridge() is executed
8454
+ * // Bridge handlers are registered with BridgeKit when bridge() runs
8455
+ * // Earn handlers are registered with EarnKit when earn operations run
8054
8456
  * ```
8055
8457
  */
8056
- actions: Record<'bridge', Record<string, ((payload: unknown) => void)[]>>;
8458
+ actions: Record<'bridge' | 'earn', Record<string, ((payload: unknown) => void)[]>>;
8057
8459
  /**
8058
8460
  * Disable error telemetry for all sub-kits.
8059
8461
  *
@@ -8064,6 +8466,16 @@ interface AppKitContext {
8064
8466
  * @defaultValue false
8065
8467
  */
8066
8468
  disableErrorReporting?: boolean;
8469
+ /**
8470
+ * Custom HTTP headers forwarded with the underlying CCTP provider's
8471
+ * attestation (Iris) API requests made by bridge operations.
8472
+ *
8473
+ * @remarks
8474
+ * Headers are merged on top of the SDK defaults (such as `Content-Type`)
8475
+ * rather than replacing them. The header is forwarded as-is to Circle's API;
8476
+ * the SDK does not interpret it.
8477
+ */
8478
+ headers?: Record<string, string>;
8067
8479
  }
8068
8480
 
8069
8481
  /**
@@ -8336,5 +8748,40 @@ declare function getWithdrawalQuote<TFromAdapterCapabilities extends AdapterCapa
8336
8748
  * ```
8337
8749
  */
8338
8750
  declare function getClaimRewardsQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(context: AppKitContext, params: GetClaimRewardsQuoteParams<TFromAdapterCapabilities>): Promise<EarnClaimRewardsQuoteInfo>;
8751
+ /**
8752
+ * Resume a multi-phase earn operation that previously failed.
8753
+ *
8754
+ * Pass the {@link KitError} caught from `deposit`, `withdraw`, or
8755
+ * `claimRewards`. Completed phases can be skipped when the error carries
8756
+ * earn retry context. Call `isRetryableError(error)` first.
8757
+ *
8758
+ * @remarks
8759
+ * Retry re-fetches execution params and may re-submit the execute
8760
+ * transaction. Treat this as best-effort recovery if a prior execute
8761
+ * broadcast may still be in flight.
8762
+ *
8763
+ * @param context - AppKit context
8764
+ * @param error - The error caught from a previous multi-phase earn operation
8765
+ * @returns Promise resolving to the result of the resumed operation
8766
+ * @throws If the error is not retryable or lacks earn retry context
8767
+ *
8768
+ * @example
8769
+ * ```typescript
8770
+ * import { isRetryableError } from '@circle-fin/app-kit'
8771
+ * import { createContext } from '@circle-fin/app-kit/context'
8772
+ * import { retry } from '@circle-fin/app-kit/earn'
8773
+ *
8774
+ * const context = createContext()
8775
+ *
8776
+ * try {
8777
+ * await deposit(context, params)
8778
+ * } catch (error) {
8779
+ * if (isRetryableError(error)) {
8780
+ * const result = await retry(context, error)
8781
+ * }
8782
+ * }
8783
+ * ```
8784
+ */
8785
+ declare function retry(context: AppKitContext, error: unknown): Promise<EarnDepositOutcome | EarnWithdrawResult | EarnClaimRewardsResult>;
8339
8786
 
8340
- export { claimRewards, deposit, exploreVaults, exploreVaultsIterator, getClaimRewardsQuote, getCrossChainDepositStatus, getDepositQuote, getPosition, getVaults, getWithdrawalQuote, waitForCrossChainDeposit, withdraw };
8787
+ export { claimRewards, deposit, exploreVaults, exploreVaultsIterator, getClaimRewardsQuote, getCrossChainDepositStatus, getDepositQuote, getPosition, getVaults, getWithdrawalQuote, retry, waitForCrossChainDeposit, withdraw };