@circle-fin/app-kit 1.15.1 → 1.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/server.d.mts CHANGED
@@ -1785,17 +1785,17 @@ interface KitEventSubscription<M extends EventMap = KitEventMap> {
1785
1785
  * embeds. Never sent back by the client; it is redeemed inside the
1786
1786
  * widget origin only.
1787
1787
  * - `widgetUrl` — fully composed launch URL (origin + path + token +
1788
- * `destinationWallet`). The server kit prefers to compose this itself
1788
+ * asset-scoping params). The server kit prefers to compose this itself
1789
1789
  * so the client kit has no exposure to the widget origin. The client
1790
1790
  * still accepts a bare `sessionToken` and composes a URL locally as a
1791
1791
  * fallback. `getOnrampUrl` is the single place that enforces the
1792
1792
  * https-scheme / origin-pin safety checks before the URL reaches the
1793
1793
  * DOM — that is a security boundary, not response validation.
1794
1794
  * - `destinationWallet` — the wallet that receives funds. The widget
1795
- * requires it as a launch query param, so the server kit echoes the
1796
- * `destinationAddress` it was minted with here (and bakes it into
1797
- * `widgetUrl`). Used by the client fallback path when it has to
1798
- * compose the URL from a bare `sessionToken`.
1795
+ * reads it from the signed session token, not the launch URL, so the
1796
+ * kit never adds it there. The server kit still echoes the
1797
+ * `destinationAddress` it was minted with here for the host's
1798
+ * convenience.
1799
1799
  * - `expiresAt` — RFC 3339 timestamp. The client refuses to launch an
1800
1800
  * expired session and throws an `INPUT` `KitError` so the host can
1801
1801
  * re-mint.
@@ -1819,8 +1819,8 @@ interface OnrampSession {
1819
1819
  */
1820
1820
  readonly sessionToken: string;
1821
1821
  /**
1822
- * Fully composed launch URL (origin + path + token +
1823
- * `destinationWallet`).
1822
+ * Fully composed launch URL (origin + path + token + optional
1823
+ * asset-scoping params).
1824
1824
  *
1825
1825
  * @remarks
1826
1826
  * The server kit prefers to compose this itself; the client falls
@@ -1833,8 +1833,9 @@ interface OnrampSession {
1833
1833
  *
1834
1834
  * @remarks
1835
1835
  * Echoed verbatim from the `destinationAddress` the server kit
1836
- * minted with. Used by the client kit's URL-composition fallback
1837
- * when `widgetUrl` is absent.
1836
+ * minted with, for the host's convenience (e.g. to display it). Never
1837
+ * added to the launch URL: the widget reads the destination wallet
1838
+ * from the signed session token.
1838
1839
  */
1839
1840
  readonly destinationWallet?: string;
1840
1841
  /**
package/server.d.ts CHANGED
@@ -1785,17 +1785,17 @@ interface KitEventSubscription<M extends EventMap = KitEventMap> {
1785
1785
  * embeds. Never sent back by the client; it is redeemed inside the
1786
1786
  * widget origin only.
1787
1787
  * - `widgetUrl` — fully composed launch URL (origin + path + token +
1788
- * `destinationWallet`). The server kit prefers to compose this itself
1788
+ * asset-scoping params). The server kit prefers to compose this itself
1789
1789
  * so the client kit has no exposure to the widget origin. The client
1790
1790
  * still accepts a bare `sessionToken` and composes a URL locally as a
1791
1791
  * fallback. `getOnrampUrl` is the single place that enforces the
1792
1792
  * https-scheme / origin-pin safety checks before the URL reaches the
1793
1793
  * DOM — that is a security boundary, not response validation.
1794
1794
  * - `destinationWallet` — the wallet that receives funds. The widget
1795
- * requires it as a launch query param, so the server kit echoes the
1796
- * `destinationAddress` it was minted with here (and bakes it into
1797
- * `widgetUrl`). Used by the client fallback path when it has to
1798
- * compose the URL from a bare `sessionToken`.
1795
+ * reads it from the signed session token, not the launch URL, so the
1796
+ * kit never adds it there. The server kit still echoes the
1797
+ * `destinationAddress` it was minted with here for the host's
1798
+ * convenience.
1799
1799
  * - `expiresAt` — RFC 3339 timestamp. The client refuses to launch an
1800
1800
  * expired session and throws an `INPUT` `KitError` so the host can
1801
1801
  * re-mint.
@@ -1819,8 +1819,8 @@ interface OnrampSession {
1819
1819
  */
1820
1820
  readonly sessionToken: string;
1821
1821
  /**
1822
- * Fully composed launch URL (origin + path + token +
1823
- * `destinationWallet`).
1822
+ * Fully composed launch URL (origin + path + token + optional
1823
+ * asset-scoping params).
1824
1824
  *
1825
1825
  * @remarks
1826
1826
  * The server kit prefers to compose this itself; the client falls
@@ -1833,8 +1833,9 @@ interface OnrampSession {
1833
1833
  *
1834
1834
  * @remarks
1835
1835
  * Echoed verbatim from the `destinationAddress` the server kit
1836
- * minted with. Used by the client kit's URL-composition fallback
1837
- * when `widgetUrl` is absent.
1836
+ * minted with, for the host's convenience (e.g. to display it). Never
1837
+ * added to the launch URL: the widget reads the destination wallet
1838
+ * from the signed session token.
1838
1839
  */
1839
1840
  readonly destinationWallet?: string;
1840
1841
  /**
package/server.mjs CHANGED
@@ -8644,7 +8644,7 @@ const swapTokenEnumSchema = z.enum([
8644
8644
  return kit;
8645
8645
  }
8646
8646
 
8647
- var version = "1.0.1";
8647
+ var version = "1.0.2";
8648
8648
  var pkg = {
8649
8649
  version: version};
8650
8650
 
@@ -9160,10 +9160,10 @@ function isAbortLikeError(err) {
9160
9160
  * @param widgetPath - Path appended to `widgetBaseUrl`. Leading `/`
9161
9161
  * is required by the URL semantics below — see remarks.
9162
9162
  * @param params - Additional query parameters to set on the launch URL
9163
- * (e.g. `destinationWallet`, `hostApp`). Entries whose value is
9164
- * `undefined` or empty are skipped. The widget reads these from the
9165
- * query string — `destinationWallet` in particular is **required** by
9166
- * the widget, so callers that have it must pass it here.
9163
+ * (e.g. the asset-scoping `chains` / `tokens` / `pairs`). Entries whose
9164
+ * value is `undefined` or empty are skipped. Launch URLs end up in
9165
+ * browser history and access logs, so never pass user identifiers
9166
+ * such as wallet addresses here.
9167
9167
  * @returns A fully-qualified launch URL.
9168
9168
  *
9169
9169
  * @remarks
@@ -9187,9 +9187,9 @@ function isAbortLikeError(err) {
9187
9187
  * @example
9188
9188
  * ```ts
9189
9189
  * composeWidgetUrl('https://onramp.arc.io', 'tok-1', '', {
9190
- * destinationWallet: '0xabc',
9190
+ * tokens: 'USDC',
9191
9191
  * })
9192
- * // → 'https://onramp.arc.io/?sessionToken=tok-1&destinationWallet=0xabc'
9192
+ * // → 'https://onramp.arc.io/?sessionToken=tok-1&tokens=USDC'
9193
9193
  * ```
9194
9194
  *
9195
9195
  * @internal Implementation detail shared by the server kit
@@ -9428,17 +9428,13 @@ function isAbortLikeError(err) {
9428
9428
  const session = unwrapped !== null && typeof unwrapped === 'object' ? unwrapped : {};
9429
9429
  const sessionToken = typeof session['sessionToken'] === 'string' ? session['sessionToken'] : undefined;
9430
9430
  const existingWidgetUrl = typeof session['widgetUrl'] === 'string' && session['widgetUrl'].length > 0 ? session['widgetUrl'] : undefined;
9431
- // The widget reads the destination wallet from the launch URL
9432
- // (`destinationWallet` query param), NOT from the session token —
9433
- // the `/v1/stablecoinKits/sessions` body is anonymous. We must
9434
- // therefore bake it into the composed URL or the widget reports
9435
- // "Destination wallet is required." mid-flow. Host-app asset scoping
9436
- // (`assets`) rides the same launch URL as `chains`/`tokens`/`pairs`.
9431
+ // The launch URL carries only the session token and host-app asset
9432
+ // scoping (`chains`/`tokens`/`pairs`). The destination wallet must
9433
+ // stay out of it: the widget reads the wallet from the signed session
9434
+ // token's `walletAddress` claim, and a query param would only leak
9435
+ // the address into browser history and access logs.
9437
9436
  const assetParams = serializeAssetSelection(params.assets);
9438
- const composedWidgetUrl = sessionToken === undefined ? undefined : composeWidgetUrl(widgetBaseUrl, sessionToken, ONRAMP_WIDGET_PATH, {
9439
- destinationWallet: params.destinationAddress,
9440
- ...assetParams
9441
- });
9437
+ const composedWidgetUrl = sessionToken === undefined ? undefined : composeWidgetUrl(widgetBaseUrl, sessionToken, ONRAMP_WIDGET_PATH, assetParams);
9442
9438
  // When wallets-api returns a `widgetUrl`, asset scoping must still be
9443
9439
  // applied — `assets` is a display-only widget concern and is never
9444
9440
  // forwarded upstream, so we merge the params directly into the returned
package/swap.cjs CHANGED
@@ -10564,7 +10564,7 @@ const swapTokenEnumSchema = zod.z.enum([
10564
10564
  }
10565
10565
 
10566
10566
  var name$2 = "@circle-fin/bridge-kit";
10567
- var version$2 = "1.15.0";
10567
+ var version$2 = "1.15.1";
10568
10568
  var pkg$2 = {
10569
10569
  name: name$2,
10570
10570
  version: version$2};
@@ -22576,7 +22576,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
22576
22576
  };
22577
22577
 
22578
22578
  var name = "@circle-fin/earn-kit";
22579
- var version = "1.7.0";
22579
+ var version = "1.8.0";
22580
22580
  var pkg = {
22581
22581
  name: name,
22582
22582
  version: version};
@@ -22718,10 +22718,8 @@ const bridgeFeeTokenSchema = hexAddressSchema;
22718
22718
  assetAddress: zod.z.string(),
22719
22719
  lltv: zod.z.number(),
22720
22720
  supplyUsd: zod.z.number(),
22721
- // Optional during the expand/contract window (a backend that predates the
22722
- // field omits the key), mirroring the `.optional()` facets on the base
22723
- // schema; `null` when the product exposes no per-market allocation (V2).
22724
- allocationPct: zod.z.number().nullable().optional()
22721
+ // `null` when the product exposes no per-market allocation (V2).
22722
+ allocationPct: zod.z.number().nullable()
22725
22723
  });
22726
22724
  /**
22727
22725
  * Zod schema for a Morpho vault warning in the API response.
@@ -22828,19 +22826,20 @@ const bridgeFeeTokenSchema = hexAddressSchema;
22828
22826
  earnKitWarnings: zod.z.array(zod.z.string()).optional()
22829
22827
  });
22830
22828
  /**
22831
- * Shared base schema: existing flat fields (kept) plus the new nested
22832
- * facets and neutral identity. Facets are `.optional()` during the
22833
- * transition; flip to required once the backend is confirmed emitting.
22829
+ * Shared base schema: existing flat fields (kept as deprecated aliases) plus
22830
+ * the nested facets. Zenith emits all facets on every response; required here
22831
+ * so a partial emission is caught at parse time rather than surfacing as a
22832
+ * runtime `undefined` access.
22834
22833
  *
22835
22834
  * @internal
22836
22835
  */ const earnBaseSchema = vaultInfoResponseSchema.extend({
22837
- address: zod.z.string().optional(),
22838
- asOf: zod.z.string().optional(),
22839
- manager: managerSchema.nullable().optional(),
22840
- apyProfile: apyProfileSchema.optional(),
22841
- fee: feeInfoSchema.optional(),
22842
- liquidityProfile: liquidityProfileSchema.optional(),
22843
- riskSignals: riskSignalsSchema.optional()
22836
+ address: zod.z.string(),
22837
+ asOf: zod.z.string(),
22838
+ manager: managerSchema.nullable(),
22839
+ apyProfile: apyProfileSchema,
22840
+ fee: feeInfoSchema,
22841
+ liquidityProfile: liquidityProfileSchema,
22842
+ riskSignals: riskSignalsSchema
22844
22843
  });
22845
22844
  /**
22846
22845
  * Zod schema for the `vault` opportunity variant.
@@ -23810,6 +23809,49 @@ const sourceAdapterContextSchema = zod.z.object({
23810
23809
  vaultAddress: vaultAddressSchema,
23811
23810
  config: earnConfigSchema.optional()
23812
23811
  });
23812
+ /**
23813
+ * Schema for a successful gas fee entry (fees is non-null).
23814
+ *
23815
+ * Validates the kit shape — {@link EarnEstimatedGas} uses decimal strings for
23816
+ * `gas`, `gasPrice`, and `fee`. Only digits are accepted so that the deposit
23817
+ * operation can safely convert them to `bigint` before passing them to the
23818
+ * provider's `computeGasReserve`.
23819
+ *
23820
+ * @internal
23821
+ */ const earnGasFeeEstimateSuccessSchema = zod.z.object({
23822
+ name: zod.z.string(),
23823
+ token: zod.z.string(),
23824
+ blockchain: zod.z.string(),
23825
+ fees: zod.z.object({
23826
+ gas: zod.z.string().regex(/^\d+$/, 'gas must be a non-negative integer string'),
23827
+ gasPrice: zod.z.string().regex(/^\d+$/, 'gasPrice must be a non-negative integer string'),
23828
+ fee: zod.z.string().regex(/^\d+$/, 'fee must be a non-negative integer string')
23829
+ }),
23830
+ error: zod.z.undefined().optional()
23831
+ }).strict();
23832
+ /**
23833
+ * Schema for a failed gas fee entry (fees is null, error is a string).
23834
+ *
23835
+ * @internal
23836
+ */ const earnGasFeeEstimateFailureSchema = zod.z.object({
23837
+ name: zod.z.string(),
23838
+ token: zod.z.string(),
23839
+ blockchain: zod.z.string(),
23840
+ fees: zod.z.null(),
23841
+ error: zod.z.string()
23842
+ }).strict();
23843
+ /**
23844
+ * Schema for a single kit-level gas fee estimate entry.
23845
+ *
23846
+ * Rejects arbitrary inputs (null, numbers, empty objects, non-numeric fee
23847
+ * strings) so callers receive a descriptive validation error instead of a
23848
+ * raw `BigInt` conversion error inside `computeGasReserve`.
23849
+ *
23850
+ * @internal
23851
+ */ const earnGasFeeEstimateSchema = zod.z.union([
23852
+ earnGasFeeEstimateSuccessSchema,
23853
+ earnGasFeeEstimateFailureSchema
23854
+ ]);
23813
23855
  /**
23814
23856
  * Validation schema for the same-chain variant of DepositParams.
23815
23857
  *
@@ -23822,6 +23864,7 @@ const sourceAdapterContextSchema = zod.z.object({
23822
23864
  to: zod.z.undefined().optional(),
23823
23865
  vaultAddress: vaultAddressSchema,
23824
23866
  amount: amountSchema,
23867
+ gasFees: zod.z.array(earnGasFeeEstimateSchema).optional(),
23825
23868
  config: earnConfigSchema.optional()
23826
23869
  }).strict();
23827
23870
  const crossChainDepositDestinationSchema = zod.z.object({
package/swap.d.cts CHANGED
@@ -7533,6 +7533,26 @@ interface VaultQuery {
7533
7533
  /** On-chain vault contract address. */
7534
7534
  readonly vaultAddress: string;
7535
7535
  }
7536
+ /**
7537
+ * Fields shared by both {@link EarnGasFeeEstimate} variants.
7538
+ *
7539
+ * @example
7540
+ * ```typescript
7541
+ * const base: EarnGasFeeEstimateBase = {
7542
+ * name: 'Deposit',
7543
+ * token: 'ETH',
7544
+ * blockchain: 'Arc_Testnet',
7545
+ * }
7546
+ * ```
7547
+ */
7548
+ interface EarnGasFeeEstimateBase {
7549
+ /** The earn step being estimated, e.g. "Approve", "Deposit", "Withdraw". */
7550
+ readonly name: string;
7551
+ /** Native token used to pay gas fees, e.g. "ETH". */
7552
+ readonly token: string;
7553
+ /** Blockchain where this gas fee applies. */
7554
+ readonly blockchain: ChainDefinition['chain'];
7555
+ }
7536
7556
  /**
7537
7557
  * Sort order for a vault discovery query.
7538
7558
  *
@@ -7547,6 +7567,51 @@ interface VaultQuery {
7547
7567
  */
7548
7568
  type ExploreVaultsSortBy = 'apy' | 'tvl' | 'name';
7549
7569
 
7570
+ /**
7571
+ * Estimated gas details for one transaction in a kit-level Earn quote, with
7572
+ * every amount as a decimal string so quote results stay JSON-serializable.
7573
+ *
7574
+ * @example
7575
+ * ```typescript
7576
+ * const gas: EarnEstimatedGas = { gas: '73567', gasPrice: '20003763738', fee: '1471616886913446' }
7577
+ * ```
7578
+ */
7579
+ interface EarnEstimatedGas {
7580
+ /** Estimated gas units as a decimal string, e.g. '73567'. */
7581
+ readonly gas: string;
7582
+ /** Estimated price per gas unit as a decimal string in wei. */
7583
+ readonly gasPrice: string;
7584
+ /** Total estimated fee as a decimal string in wei. */
7585
+ readonly fee: string;
7586
+ }
7587
+ /**
7588
+ * Estimated native gas fee for one transaction in an Earn quote.
7589
+ *
7590
+ * A discriminated union on `fees`: a successful estimate carries
7591
+ * {@link EarnEstimatedGas} details and no `error`; a failed estimate carries
7592
+ * `fees: null` and a sanitized `error` message.
7593
+ *
7594
+ * @example
7595
+ * ```typescript
7596
+ * function describe(entry: EarnGasFeeEstimate): string {
7597
+ * if (entry.fees === null) {
7598
+ * return `${entry.name}: estimation failed (${entry.error})`
7599
+ * }
7600
+ * return `${entry.name}: ${entry.fees.fee} wei`
7601
+ * }
7602
+ * ```
7603
+ */
7604
+ type EarnGasFeeEstimate = (EarnGasFeeEstimateBase & {
7605
+ /** Estimated gas details with amounts formatted as decimal strings. */
7606
+ readonly fees: EarnEstimatedGas;
7607
+ /** Never present on a successful estimate. */
7608
+ readonly error?: never;
7609
+ }) | (EarnGasFeeEstimateBase & {
7610
+ /** Null because estimation failed. */
7611
+ readonly fees: null;
7612
+ /** Sanitized estimation error message. */
7613
+ readonly error: string;
7614
+ });
7550
7615
  /**
7551
7616
  * Adapter context for earn operations, constrained to earn-supported chains.
7552
7617
  *
@@ -7730,6 +7795,12 @@ interface SameChainDepositParams<TFromAdapterCapabilities extends AdapterCapabil
7730
7795
  * @example '100.50' for 100.50 USDC
7731
7796
  */
7732
7797
  readonly amount: string;
7798
+ /**
7799
+ * Gas fee estimates from a prior {@link getDepositQuote} call. When provided,
7800
+ * the pre-broadcast gas reserve check uses the actual estimated cost instead
7801
+ * of the conservative fallback reserve.
7802
+ */
7803
+ readonly gasFees?: readonly EarnGasFeeEstimate[] | undefined;
7733
7804
  /** Optional earn configuration. */
7734
7805
  readonly config?: EarnConfig | undefined;
7735
7806
  }
package/swap.d.mts CHANGED
@@ -7533,6 +7533,26 @@ interface VaultQuery {
7533
7533
  /** On-chain vault contract address. */
7534
7534
  readonly vaultAddress: string;
7535
7535
  }
7536
+ /**
7537
+ * Fields shared by both {@link EarnGasFeeEstimate} variants.
7538
+ *
7539
+ * @example
7540
+ * ```typescript
7541
+ * const base: EarnGasFeeEstimateBase = {
7542
+ * name: 'Deposit',
7543
+ * token: 'ETH',
7544
+ * blockchain: 'Arc_Testnet',
7545
+ * }
7546
+ * ```
7547
+ */
7548
+ interface EarnGasFeeEstimateBase {
7549
+ /** The earn step being estimated, e.g. "Approve", "Deposit", "Withdraw". */
7550
+ readonly name: string;
7551
+ /** Native token used to pay gas fees, e.g. "ETH". */
7552
+ readonly token: string;
7553
+ /** Blockchain where this gas fee applies. */
7554
+ readonly blockchain: ChainDefinition['chain'];
7555
+ }
7536
7556
  /**
7537
7557
  * Sort order for a vault discovery query.
7538
7558
  *
@@ -7547,6 +7567,51 @@ interface VaultQuery {
7547
7567
  */
7548
7568
  type ExploreVaultsSortBy = 'apy' | 'tvl' | 'name';
7549
7569
 
7570
+ /**
7571
+ * Estimated gas details for one transaction in a kit-level Earn quote, with
7572
+ * every amount as a decimal string so quote results stay JSON-serializable.
7573
+ *
7574
+ * @example
7575
+ * ```typescript
7576
+ * const gas: EarnEstimatedGas = { gas: '73567', gasPrice: '20003763738', fee: '1471616886913446' }
7577
+ * ```
7578
+ */
7579
+ interface EarnEstimatedGas {
7580
+ /** Estimated gas units as a decimal string, e.g. '73567'. */
7581
+ readonly gas: string;
7582
+ /** Estimated price per gas unit as a decimal string in wei. */
7583
+ readonly gasPrice: string;
7584
+ /** Total estimated fee as a decimal string in wei. */
7585
+ readonly fee: string;
7586
+ }
7587
+ /**
7588
+ * Estimated native gas fee for one transaction in an Earn quote.
7589
+ *
7590
+ * A discriminated union on `fees`: a successful estimate carries
7591
+ * {@link EarnEstimatedGas} details and no `error`; a failed estimate carries
7592
+ * `fees: null` and a sanitized `error` message.
7593
+ *
7594
+ * @example
7595
+ * ```typescript
7596
+ * function describe(entry: EarnGasFeeEstimate): string {
7597
+ * if (entry.fees === null) {
7598
+ * return `${entry.name}: estimation failed (${entry.error})`
7599
+ * }
7600
+ * return `${entry.name}: ${entry.fees.fee} wei`
7601
+ * }
7602
+ * ```
7603
+ */
7604
+ type EarnGasFeeEstimate = (EarnGasFeeEstimateBase & {
7605
+ /** Estimated gas details with amounts formatted as decimal strings. */
7606
+ readonly fees: EarnEstimatedGas;
7607
+ /** Never present on a successful estimate. */
7608
+ readonly error?: never;
7609
+ }) | (EarnGasFeeEstimateBase & {
7610
+ /** Null because estimation failed. */
7611
+ readonly fees: null;
7612
+ /** Sanitized estimation error message. */
7613
+ readonly error: string;
7614
+ });
7550
7615
  /**
7551
7616
  * Adapter context for earn operations, constrained to earn-supported chains.
7552
7617
  *
@@ -7730,6 +7795,12 @@ interface SameChainDepositParams<TFromAdapterCapabilities extends AdapterCapabil
7730
7795
  * @example '100.50' for 100.50 USDC
7731
7796
  */
7732
7797
  readonly amount: string;
7798
+ /**
7799
+ * Gas fee estimates from a prior {@link getDepositQuote} call. When provided,
7800
+ * the pre-broadcast gas reserve check uses the actual estimated cost instead
7801
+ * of the conservative fallback reserve.
7802
+ */
7803
+ readonly gasFees?: readonly EarnGasFeeEstimate[] | undefined;
7733
7804
  /** Optional earn configuration. */
7734
7805
  readonly config?: EarnConfig | undefined;
7735
7806
  }
package/swap.d.ts CHANGED
@@ -7533,6 +7533,26 @@ interface VaultQuery {
7533
7533
  /** On-chain vault contract address. */
7534
7534
  readonly vaultAddress: string;
7535
7535
  }
7536
+ /**
7537
+ * Fields shared by both {@link EarnGasFeeEstimate} variants.
7538
+ *
7539
+ * @example
7540
+ * ```typescript
7541
+ * const base: EarnGasFeeEstimateBase = {
7542
+ * name: 'Deposit',
7543
+ * token: 'ETH',
7544
+ * blockchain: 'Arc_Testnet',
7545
+ * }
7546
+ * ```
7547
+ */
7548
+ interface EarnGasFeeEstimateBase {
7549
+ /** The earn step being estimated, e.g. "Approve", "Deposit", "Withdraw". */
7550
+ readonly name: string;
7551
+ /** Native token used to pay gas fees, e.g. "ETH". */
7552
+ readonly token: string;
7553
+ /** Blockchain where this gas fee applies. */
7554
+ readonly blockchain: ChainDefinition['chain'];
7555
+ }
7536
7556
  /**
7537
7557
  * Sort order for a vault discovery query.
7538
7558
  *
@@ -7547,6 +7567,51 @@ interface VaultQuery {
7547
7567
  */
7548
7568
  type ExploreVaultsSortBy = 'apy' | 'tvl' | 'name';
7549
7569
 
7570
+ /**
7571
+ * Estimated gas details for one transaction in a kit-level Earn quote, with
7572
+ * every amount as a decimal string so quote results stay JSON-serializable.
7573
+ *
7574
+ * @example
7575
+ * ```typescript
7576
+ * const gas: EarnEstimatedGas = { gas: '73567', gasPrice: '20003763738', fee: '1471616886913446' }
7577
+ * ```
7578
+ */
7579
+ interface EarnEstimatedGas {
7580
+ /** Estimated gas units as a decimal string, e.g. '73567'. */
7581
+ readonly gas: string;
7582
+ /** Estimated price per gas unit as a decimal string in wei. */
7583
+ readonly gasPrice: string;
7584
+ /** Total estimated fee as a decimal string in wei. */
7585
+ readonly fee: string;
7586
+ }
7587
+ /**
7588
+ * Estimated native gas fee for one transaction in an Earn quote.
7589
+ *
7590
+ * A discriminated union on `fees`: a successful estimate carries
7591
+ * {@link EarnEstimatedGas} details and no `error`; a failed estimate carries
7592
+ * `fees: null` and a sanitized `error` message.
7593
+ *
7594
+ * @example
7595
+ * ```typescript
7596
+ * function describe(entry: EarnGasFeeEstimate): string {
7597
+ * if (entry.fees === null) {
7598
+ * return `${entry.name}: estimation failed (${entry.error})`
7599
+ * }
7600
+ * return `${entry.name}: ${entry.fees.fee} wei`
7601
+ * }
7602
+ * ```
7603
+ */
7604
+ type EarnGasFeeEstimate = (EarnGasFeeEstimateBase & {
7605
+ /** Estimated gas details with amounts formatted as decimal strings. */
7606
+ readonly fees: EarnEstimatedGas;
7607
+ /** Never present on a successful estimate. */
7608
+ readonly error?: never;
7609
+ }) | (EarnGasFeeEstimateBase & {
7610
+ /** Null because estimation failed. */
7611
+ readonly fees: null;
7612
+ /** Sanitized estimation error message. */
7613
+ readonly error: string;
7614
+ });
7550
7615
  /**
7551
7616
  * Adapter context for earn operations, constrained to earn-supported chains.
7552
7617
  *
@@ -7730,6 +7795,12 @@ interface SameChainDepositParams<TFromAdapterCapabilities extends AdapterCapabil
7730
7795
  * @example '100.50' for 100.50 USDC
7731
7796
  */
7732
7797
  readonly amount: string;
7798
+ /**
7799
+ * Gas fee estimates from a prior {@link getDepositQuote} call. When provided,
7800
+ * the pre-broadcast gas reserve check uses the actual estimated cost instead
7801
+ * of the conservative fallback reserve.
7802
+ */
7803
+ readonly gasFees?: readonly EarnGasFeeEstimate[] | undefined;
7733
7804
  /** Optional earn configuration. */
7734
7805
  readonly config?: EarnConfig | undefined;
7735
7806
  }
package/swap.mjs CHANGED
@@ -10557,7 +10557,7 @@ const swapTokenEnumSchema = z.enum([
10557
10557
  }
10558
10558
 
10559
10559
  var name$2 = "@circle-fin/bridge-kit";
10560
- var version$2 = "1.15.0";
10560
+ var version$2 = "1.15.1";
10561
10561
  var pkg$2 = {
10562
10562
  name: name$2,
10563
10563
  version: version$2};
@@ -22569,7 +22569,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
22569
22569
  };
22570
22570
 
22571
22571
  var name = "@circle-fin/earn-kit";
22572
- var version = "1.7.0";
22572
+ var version = "1.8.0";
22573
22573
  var pkg = {
22574
22574
  name: name,
22575
22575
  version: version};
@@ -22711,10 +22711,8 @@ const bridgeFeeTokenSchema = hexAddressSchema;
22711
22711
  assetAddress: z.string(),
22712
22712
  lltv: z.number(),
22713
22713
  supplyUsd: z.number(),
22714
- // Optional during the expand/contract window (a backend that predates the
22715
- // field omits the key), mirroring the `.optional()` facets on the base
22716
- // schema; `null` when the product exposes no per-market allocation (V2).
22717
- allocationPct: z.number().nullable().optional()
22714
+ // `null` when the product exposes no per-market allocation (V2).
22715
+ allocationPct: z.number().nullable()
22718
22716
  });
22719
22717
  /**
22720
22718
  * Zod schema for a Morpho vault warning in the API response.
@@ -22821,19 +22819,20 @@ const bridgeFeeTokenSchema = hexAddressSchema;
22821
22819
  earnKitWarnings: z.array(z.string()).optional()
22822
22820
  });
22823
22821
  /**
22824
- * Shared base schema: existing flat fields (kept) plus the new nested
22825
- * facets and neutral identity. Facets are `.optional()` during the
22826
- * transition; flip to required once the backend is confirmed emitting.
22822
+ * Shared base schema: existing flat fields (kept as deprecated aliases) plus
22823
+ * the nested facets. Zenith emits all facets on every response; required here
22824
+ * so a partial emission is caught at parse time rather than surfacing as a
22825
+ * runtime `undefined` access.
22827
22826
  *
22828
22827
  * @internal
22829
22828
  */ const earnBaseSchema = vaultInfoResponseSchema.extend({
22830
- address: z.string().optional(),
22831
- asOf: z.string().optional(),
22832
- manager: managerSchema.nullable().optional(),
22833
- apyProfile: apyProfileSchema.optional(),
22834
- fee: feeInfoSchema.optional(),
22835
- liquidityProfile: liquidityProfileSchema.optional(),
22836
- riskSignals: riskSignalsSchema.optional()
22829
+ address: z.string(),
22830
+ asOf: z.string(),
22831
+ manager: managerSchema.nullable(),
22832
+ apyProfile: apyProfileSchema,
22833
+ fee: feeInfoSchema,
22834
+ liquidityProfile: liquidityProfileSchema,
22835
+ riskSignals: riskSignalsSchema
22837
22836
  });
22838
22837
  /**
22839
22838
  * Zod schema for the `vault` opportunity variant.
@@ -23803,6 +23802,49 @@ const sourceAdapterContextSchema = z.object({
23803
23802
  vaultAddress: vaultAddressSchema,
23804
23803
  config: earnConfigSchema.optional()
23805
23804
  });
23805
+ /**
23806
+ * Schema for a successful gas fee entry (fees is non-null).
23807
+ *
23808
+ * Validates the kit shape — {@link EarnEstimatedGas} uses decimal strings for
23809
+ * `gas`, `gasPrice`, and `fee`. Only digits are accepted so that the deposit
23810
+ * operation can safely convert them to `bigint` before passing them to the
23811
+ * provider's `computeGasReserve`.
23812
+ *
23813
+ * @internal
23814
+ */ const earnGasFeeEstimateSuccessSchema = z.object({
23815
+ name: z.string(),
23816
+ token: z.string(),
23817
+ blockchain: z.string(),
23818
+ fees: z.object({
23819
+ gas: z.string().regex(/^\d+$/, 'gas must be a non-negative integer string'),
23820
+ gasPrice: z.string().regex(/^\d+$/, 'gasPrice must be a non-negative integer string'),
23821
+ fee: z.string().regex(/^\d+$/, 'fee must be a non-negative integer string')
23822
+ }),
23823
+ error: z.undefined().optional()
23824
+ }).strict();
23825
+ /**
23826
+ * Schema for a failed gas fee entry (fees is null, error is a string).
23827
+ *
23828
+ * @internal
23829
+ */ const earnGasFeeEstimateFailureSchema = z.object({
23830
+ name: z.string(),
23831
+ token: z.string(),
23832
+ blockchain: z.string(),
23833
+ fees: z.null(),
23834
+ error: z.string()
23835
+ }).strict();
23836
+ /**
23837
+ * Schema for a single kit-level gas fee estimate entry.
23838
+ *
23839
+ * Rejects arbitrary inputs (null, numbers, empty objects, non-numeric fee
23840
+ * strings) so callers receive a descriptive validation error instead of a
23841
+ * raw `BigInt` conversion error inside `computeGasReserve`.
23842
+ *
23843
+ * @internal
23844
+ */ const earnGasFeeEstimateSchema = z.union([
23845
+ earnGasFeeEstimateSuccessSchema,
23846
+ earnGasFeeEstimateFailureSchema
23847
+ ]);
23806
23848
  /**
23807
23849
  * Validation schema for the same-chain variant of DepositParams.
23808
23850
  *
@@ -23815,6 +23857,7 @@ const sourceAdapterContextSchema = z.object({
23815
23857
  to: z.undefined().optional(),
23816
23858
  vaultAddress: vaultAddressSchema,
23817
23859
  amount: amountSchema,
23860
+ gasFees: z.array(earnGasFeeEstimateSchema).optional(),
23818
23861
  config: earnConfigSchema.optional()
23819
23862
  }).strict();
23820
23863
  const crossChainDepositDestinationSchema = z.object({