@circle-fin/app-kit 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -740,6 +740,8 @@ declare enum Blockchain {
740
740
  World_Chain_Sepolia = "World_Chain_Sepolia",
741
741
  XDC = "XDC",
742
742
  XDC_Apothem = "XDC_Apothem",
743
+ X_Layer = "X_Layer",
744
+ X_Layer_Testnet = "X_Layer_Testnet",
743
745
  ZKSync_Era = "ZKSync_Era",
744
746
  ZKSync_Sepolia = "ZKSync_Sepolia"
745
747
  }
@@ -952,6 +954,7 @@ declare enum BridgeChain {
952
954
  Unichain = "Unichain",
953
955
  World_Chain = "World_Chain",
954
956
  XDC = "XDC",
957
+ X_Layer = "X_Layer",
955
958
  Arc_Testnet = "Arc_Testnet",
956
959
  Arbitrum_Sepolia = "Arbitrum_Sepolia",
957
960
  Avalanche_Fuji = "Avalanche_Fuji",
@@ -975,7 +978,8 @@ declare enum BridgeChain {
975
978
  Sonic_Testnet = "Sonic_Testnet",
976
979
  Unichain_Sepolia = "Unichain_Sepolia",
977
980
  World_Chain_Sepolia = "World_Chain_Sepolia",
978
- XDC_Apothem = "XDC_Apothem"
981
+ XDC_Apothem = "XDC_Apothem",
982
+ X_Layer_Testnet = "X_Layer_Testnet"
979
983
  }
980
984
  /**
981
985
  * Type representing valid bridge chain identifiers.
@@ -3386,7 +3390,7 @@ declare const PolygonAmoy: {
3386
3390
  readonly chainId: 80002;
3387
3391
  readonly isTestnet: true;
3388
3392
  readonly explorerUrl: "https://amoy.polygonscan.com/tx/{hash}";
3389
- readonly rpcEndpoints: readonly ["https://rpc-amoy.polygon.technology"];
3393
+ readonly rpcEndpoints: readonly ["https://polygon-amoy-bor-rpc.publicnode.com", "https://polygon-amoy.drpc.org"];
3390
3394
  readonly eurcAddress: null;
3391
3395
  readonly usdcAddress: "0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582";
3392
3396
  readonly usdtAddress: null;
@@ -4232,6 +4236,98 @@ declare const XDCApothem: {
4232
4236
  };
4233
4237
  };
4234
4238
 
4239
+ /**
4240
+ * X Layer Mainnet chain definition
4241
+ * @remarks
4242
+ * This represents the official production network for the X Layer blockchain.
4243
+ * X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
4244
+ * using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
4245
+ * OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
4246
+ */
4247
+ declare const XLayer: {
4248
+ readonly type: "evm";
4249
+ readonly chain: Blockchain.X_Layer;
4250
+ readonly name: "X Layer";
4251
+ readonly title: "X Layer Mainnet";
4252
+ readonly nativeCurrency: {
4253
+ readonly name: "OKB";
4254
+ readonly symbol: "OKB";
4255
+ readonly decimals: 18;
4256
+ };
4257
+ readonly chainId: 196;
4258
+ readonly isTestnet: false;
4259
+ readonly explorerUrl: "https://www.oklink.com/xlayer/tx/{hash}";
4260
+ readonly rpcEndpoints: readonly ["https://xlayerrpc.okx.com"];
4261
+ readonly eurcAddress: null;
4262
+ readonly usdcAddress: "0xB6CEceAB302E2E4948951eE7843FC24E92933061";
4263
+ readonly usdtAddress: null;
4264
+ readonly cctp: {
4265
+ readonly domain: 37;
4266
+ readonly contracts: {
4267
+ readonly v2: {
4268
+ readonly type: "split";
4269
+ readonly tokenMessenger: "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d";
4270
+ readonly messageTransmitter: "0x81D40F21F12A8F0E3252Bccb954D722d4c464B64";
4271
+ readonly confirmations: 65;
4272
+ readonly fastConfirmations: 1;
4273
+ };
4274
+ };
4275
+ readonly forwarderSupported: {
4276
+ readonly source: false;
4277
+ readonly destination: false;
4278
+ };
4279
+ };
4280
+ readonly kitContracts: {
4281
+ readonly bridge: "0xB3FA262d0fB521cc93bE83d87b322b8A23DAf3F0";
4282
+ };
4283
+ };
4284
+
4285
+ /**
4286
+ * X Layer Testnet chain definition
4287
+ * @remarks
4288
+ * This represents the official test network for the X Layer blockchain.
4289
+ * X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
4290
+ * using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
4291
+ * OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
4292
+ */
4293
+ declare const XLayerTestnet: {
4294
+ readonly type: "evm";
4295
+ readonly chain: Blockchain.X_Layer_Testnet;
4296
+ readonly name: "X Layer Testnet";
4297
+ readonly title: "X Layer Testnet";
4298
+ readonly nativeCurrency: {
4299
+ readonly name: "OKB";
4300
+ readonly symbol: "OKB";
4301
+ readonly decimals: 18;
4302
+ };
4303
+ readonly chainId: 1952;
4304
+ readonly isTestnet: true;
4305
+ readonly explorerUrl: "https://web3.okx.com/explorer/x-layer-testnet/tx/{hash}";
4306
+ readonly rpcEndpoints: readonly ["https://testrpc.xlayer.tech"];
4307
+ readonly eurcAddress: null;
4308
+ readonly usdcAddress: "0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3";
4309
+ readonly usdtAddress: null;
4310
+ readonly cctp: {
4311
+ readonly domain: 37;
4312
+ readonly contracts: {
4313
+ readonly v2: {
4314
+ readonly type: "split";
4315
+ readonly tokenMessenger: "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA";
4316
+ readonly messageTransmitter: "0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275";
4317
+ readonly confirmations: 65;
4318
+ readonly fastConfirmations: 1;
4319
+ };
4320
+ };
4321
+ readonly forwarderSupported: {
4322
+ readonly source: false;
4323
+ readonly destination: false;
4324
+ };
4325
+ };
4326
+ readonly kitContracts: {
4327
+ readonly bridge: "0xC5567a5E3370d4DBfB0540025078e283e36A363d";
4328
+ };
4329
+ };
4330
+
4235
4331
  /**
4236
4332
  * ZKSync Era Mainnet chain definition
4237
4333
  * @remarks
@@ -4347,6 +4443,8 @@ declare const Chains_WorldChain: typeof WorldChain;
4347
4443
  declare const Chains_WorldChainSepolia: typeof WorldChainSepolia;
4348
4444
  declare const Chains_XDC: typeof XDC;
4349
4445
  declare const Chains_XDCApothem: typeof XDCApothem;
4446
+ declare const Chains_XLayer: typeof XLayer;
4447
+ declare const Chains_XLayerTestnet: typeof XLayerTestnet;
4350
4448
  declare const Chains_ZKSyncEra: typeof ZKSyncEra;
4351
4449
  declare const Chains_ZKSyncEraSepolia: typeof ZKSyncEraSepolia;
4352
4450
  declare namespace Chains {
@@ -4416,6 +4514,8 @@ declare namespace Chains {
4416
4514
  Chains_WorldChainSepolia as WorldChainSepolia,
4417
4515
  Chains_XDC as XDC,
4418
4516
  Chains_XDCApothem as XDCApothem,
4517
+ Chains_XLayer as XLayer,
4518
+ Chains_XLayerTestnet as XLayerTestnet,
4419
4519
  Chains_ZKSyncEra as ZKSyncEra,
4420
4520
  Chains_ZKSyncEraSepolia as ZKSyncEraSepolia,
4421
4521
  };
@@ -15871,6 +15971,17 @@ interface EarnServiceConfig {
15871
15971
  * Override for testing against staging or local environments.
15872
15972
  */
15873
15973
  readonly baseUrl?: string | undefined;
15974
+ /**
15975
+ * Enable or disable batched transaction execution.
15976
+ *
15977
+ * When `true` (or `undefined` / omitted), same-chain deposit and withdraw
15978
+ * bundle the approve and execute calls into one adapter-native atomic batch
15979
+ * when the connected wallet supports it. Set to `false` to force the
15980
+ * sequential approve → execute flow.
15981
+ *
15982
+ * @defaultValue `undefined` (batching attempted when the wallet supports it)
15983
+ */
15984
+ readonly batchTransactions?: boolean | undefined;
15874
15985
  }
15875
15986
  /**
15876
15987
  * A single vault query specifying chain and vault address.
@@ -16388,6 +16499,278 @@ interface AssetAmount {
16388
16499
  */
16389
16500
  readonly status?: string | undefined;
16390
16501
  }
16502
+ /**
16503
+ * The earn write operation a decoded transaction represents.
16504
+ *
16505
+ * Same-chain deposit, withdraw, and claim-rewards all bundle their work inside a
16506
+ * single Adapter `execute()` call, so the action cannot be inferred from the
16507
+ * calldata alone and is carried explicitly.
16508
+ *
16509
+ * @example
16510
+ * ```typescript
16511
+ * const action: EarnActionKind = 'deposit'
16512
+ * ```
16513
+ */
16514
+ type EarnActionKind = 'deposit' | 'withdraw' | 'claimRewards';
16515
+ /**
16516
+ * A token address paired with a base-unit amount.
16517
+ *
16518
+ * Amounts are kept as base-unit decimal strings (never a `number`) so they are
16519
+ * lossless and JSON-safe; format them for display with the token's decimals.
16520
+ *
16521
+ * @example
16522
+ * ```typescript
16523
+ * const usdc: DecodedTokenAmount = {
16524
+ * address: '0x3600000000000000000000000000000000000000',
16525
+ * amount: '1000000',
16526
+ * }
16527
+ * ```
16528
+ */
16529
+ interface DecodedTokenAmount {
16530
+ /** Token contract address. */
16531
+ readonly address: `0x${string}`;
16532
+ /** Amount in the token's smallest unit, as a decimal string. */
16533
+ readonly amount: string;
16534
+ }
16535
+ /**
16536
+ * A single claimed reward: the token and cumulative amount, plus the account
16537
+ * credited.
16538
+ *
16539
+ * Extends {@link DecodedTokenAmount} with the Merkl `claim` recipient so a
16540
+ * signer can see who receives each reward, not just the token and amount.
16541
+ *
16542
+ * The inherited `amount` is the *cumulative lifetime* total claimable for this
16543
+ * `(recipient, token)` pair, exactly as encoded in the signed Merkl `claim`
16544
+ * calldata — not the net amount transferred by this transaction. The Merkl
16545
+ * Distributor sends only `amount - alreadyClaimed`, so treat this as the
16546
+ * running claim total, not "the reward about to be received."
16547
+ *
16548
+ * @example
16549
+ * ```typescript
16550
+ * const reward: DecodedRewardClaim = {
16551
+ * recipient: '0xdbfF385d31bee3bA4DbdD7563c512e1C491bdD19',
16552
+ * address: '0x0000000000000000000000000000000000000a22',
16553
+ * amount: '1000000',
16554
+ * }
16555
+ * ```
16556
+ */
16557
+ interface DecodedRewardClaim extends DecodedTokenAmount {
16558
+ /** Account credited with this reward (the Merkl `claim` user). */
16559
+ readonly recipient: `0x${string}`;
16560
+ }
16561
+ /**
16562
+ * A single decoded inner instruction from an Adapter `execute()` bundle.
16563
+ *
16564
+ * Each variant mirrors the on-chain call the earn service signed, so a signer
16565
+ * sees exactly what the bundle does rather than opaque calldata. Values decoded
16566
+ * from `uint256` fields are represented as base-unit decimal strings.
16567
+ *
16568
+ * @example
16569
+ * ```typescript
16570
+ * const instruction: DecodedEarnInstruction = {
16571
+ * method: 'deposit',
16572
+ * vault: '0xAabbeF1D3971c710276ed41eC791BbE14CdB8E88',
16573
+ * assets: '1000000',
16574
+ * receiver: '0xdbfF385d31bee3bA4DbdD7563c512e1C491bdD19',
16575
+ * }
16576
+ * ```
16577
+ */
16578
+ type DecodedEarnInstruction = {
16579
+ readonly method: 'deposit';
16580
+ /** ERC-4626 vault the assets are deposited into. */
16581
+ readonly vault: `0x${string}`;
16582
+ /** Assets deposited, in the underlying token's smallest unit. */
16583
+ readonly assets: string;
16584
+ /** Account credited with the minted vault shares. */
16585
+ readonly receiver: `0x${string}`;
16586
+ } | {
16587
+ readonly method: 'withdraw';
16588
+ /** ERC-4626 vault the assets are withdrawn from. */
16589
+ readonly vault: `0x${string}`;
16590
+ /** Assets withdrawn, in the underlying token's smallest unit. */
16591
+ readonly assets: string;
16592
+ /** Account credited with the withdrawn assets. */
16593
+ readonly receiver: `0x${string}`;
16594
+ /** Account whose shares are burned (the Adapter for EarnKit). */
16595
+ readonly owner: `0x${string}`;
16596
+ } | {
16597
+ readonly method: 'redeem';
16598
+ /** ERC-4626 vault the shares are redeemed from. */
16599
+ readonly vault: `0x${string}`;
16600
+ /** Shares redeemed, in the vault-share token's smallest unit. */
16601
+ readonly shares: string;
16602
+ /** Account credited with the redeemed assets. */
16603
+ readonly receiver: `0x${string}`;
16604
+ /** Account whose shares are burned (the Adapter for EarnKit). */
16605
+ readonly owner: `0x${string}`;
16606
+ } | {
16607
+ readonly method: 'takeFeeERC20';
16608
+ /** FeeTaker contract the fee is paid to. */
16609
+ readonly feeTaker: `0x${string}`;
16610
+ /** Token the fee is denominated in. */
16611
+ readonly token: `0x${string}`;
16612
+ /** Account credited with the fee. */
16613
+ readonly beneficiary: `0x${string}`;
16614
+ /** Fee amount in the token's smallest unit. */
16615
+ readonly fee: string;
16616
+ /** 8-byte kit identifier passed to the FeeTaker. */
16617
+ readonly kitType: `0x${string}`;
16618
+ } | {
16619
+ readonly method: 'claim';
16620
+ /** Merkl Distributor the rewards are claimed from. */
16621
+ readonly distributor: `0x${string}`;
16622
+ /** One entry per claimed reward token. */
16623
+ readonly rewards: readonly DecodedRewardClaim[];
16624
+ };
16625
+ /**
16626
+ * A human-readable decode of the Adapter `execute()` transaction a signer is
16627
+ * asked to sign for a same-chain earn operation.
16628
+ *
16629
+ * `instructions` is the full-fidelity decode of every inner call; `summary`
16630
+ * lifts the values a wallet prompt cares about (token + amount, vault, receiver,
16631
+ * fee, rewards) to the top level. Every value is derived from the same signed
16632
+ * `executeParams` the SDK encodes into the transaction, so the decode cannot
16633
+ * drift from what is actually signed.
16634
+ *
16635
+ * @example
16636
+ * ```typescript
16637
+ * const decoded: DecodedEarnTx = {
16638
+ * action: 'deposit',
16639
+ * chain: 'Arc_Testnet',
16640
+ * adapter: '0xBBD70b01a1CAbc96d5b7b129Ae1AAabdf50dd40b',
16641
+ * instructions: [
16642
+ * {
16643
+ * method: 'deposit',
16644
+ * vault: '0xAabbeF1D3971c710276ed41eC791BbE14CdB8E88',
16645
+ * assets: '1000000',
16646
+ * receiver: '0xdbfF385d31bee3bA4DbdD7563c512e1C491bdD19',
16647
+ * },
16648
+ * ],
16649
+ * summary: {
16650
+ * token: {
16651
+ * address: '0x3600000000000000000000000000000000000000',
16652
+ * amount: '1000000',
16653
+ * },
16654
+ * vault: '0xAabbeF1D3971c710276ed41eC791BbE14CdB8E88',
16655
+ * receiver: '0xdbfF385d31bee3bA4DbdD7563c512e1C491bdD19',
16656
+ * },
16657
+ * }
16658
+ * ```
16659
+ */
16660
+ interface DecodedEarnTx {
16661
+ /** The earn operation this transaction performs. */
16662
+ readonly action: EarnActionKind;
16663
+ /** Chain identifier the transaction executes on. */
16664
+ readonly chain: EarnChainIdentifier;
16665
+ /** Adapter contract the `execute()` call targets. */
16666
+ readonly adapter: `0x${string}`;
16667
+ /** Full decode of every inner instruction in the `execute()` bundle. */
16668
+ readonly instructions: readonly DecodedEarnInstruction[];
16669
+ /** Wallet-prompt-ready summary of the primary values being signed. */
16670
+ readonly summary: {
16671
+ /**
16672
+ * The token and amount this operation is denominated in, with the address
16673
+ * and amount always in the same unit: the underlying asset deposited
16674
+ * (deposit) or withdrawn (withdraw), or the vault-share token redeemed
16675
+ * (redeem).
16676
+ */
16677
+ readonly token?: DecodedTokenAmount;
16678
+ /** Target vault, when the action operates on one. */
16679
+ readonly vault?: `0x${string}`;
16680
+ /** Account credited by the operation. */
16681
+ readonly receiver?: `0x${string}`;
16682
+ /** Circle fee taken by the operation, when charged. */
16683
+ readonly fee?: DecodedTokenAmount;
16684
+ /** Rewards claimed, for claim-rewards, each with its credited recipient. */
16685
+ readonly rewards?: readonly DecodedRewardClaim[];
16686
+ };
16687
+ }
16688
+ /**
16689
+ * The exact single EVM call an EarnKit same-chain operation authorizes.
16690
+ *
16691
+ * This is the canonical Adapter `execute()` call as it will be handed to the
16692
+ * wallet or signing strategy — target, calldata, and native value — not a
16693
+ * serialized transaction (fees and nonce are still selected by the wallet
16694
+ * afterwards).
16695
+ *
16696
+ * @example
16697
+ * ```typescript
16698
+ * const encoded: EarnEncodedTransaction = {
16699
+ * to: '0xBBD70b01a1CAbc96d5b7b129Ae1AAabdf50dd40b',
16700
+ * data: '0x…',
16701
+ * value: 0n,
16702
+ * }
16703
+ * ```
16704
+ */
16705
+ interface EarnEncodedTransaction {
16706
+ /** Adapter contract the `execute()` call targets. */
16707
+ readonly to: `0x${string}`;
16708
+ /** ABI-encoded `execute()` calldata about to be authorized. */
16709
+ readonly data: `0x${string}`;
16710
+ /** Native token value the authorized call specifies, when the call sets one. */
16711
+ readonly value?: bigint | undefined;
16712
+ }
16713
+ /**
16714
+ * Namespaced discriminator for the EarnKit authorization review.
16715
+ *
16716
+ * Applications match on this in an adapter `onBeforeAuthorize` hook to decide
16717
+ * whether the request carries EarnKit semantic data. Prefer the
16718
+ * {@link isEarnExecuteReview} type guard over comparing this string directly.
16719
+ *
16720
+ * @example
16721
+ * ```typescript
16722
+ * if (review?.kind === EARN_EXECUTE_REVIEW_KIND) { … }
16723
+ * ```
16724
+ */
16725
+ declare const EARN_EXECUTE_REVIEW_KIND: "earn.execute";
16726
+ /**
16727
+ * Verified semantic review data EarnKit attaches to a same-chain
16728
+ * deposit / withdraw / claim-rewards authorization.
16729
+ *
16730
+ * Surfaced as the `data` of the adapter `AuthorizationReview` whose `kind` is
16731
+ * {@link EARN_EXECUTE_REVIEW_KIND}. It pairs the exact calldata being
16732
+ * authorized ({@link encoded}) with a drift-free decode of it
16733
+ * ({@link decoded}). The factory that produces it re-decodes the final
16734
+ * calldata and asserts every instruction matches the service-signed
16735
+ * parameters, so a populated review is proof the preview matches what is
16736
+ * signed — never a best-effort guess.
16737
+ *
16738
+ * @example
16739
+ * ```typescript
16740
+ * import { createViemAdapter } from '@circle-fin/adapter-viem-v2/next'
16741
+ *
16742
+ * const adapter = createViemAdapter({
16743
+ * capabilities,
16744
+ * getPublicClient,
16745
+ * getWalletClient,
16746
+ * onBeforeAuthorize: async ({ review }) => {
16747
+ * if (isEarnExecuteReview(review)) {
16748
+ * const { decoded } = review.data
16749
+ * await showEarnConfirmation(decoded.summary)
16750
+ * }
16751
+ * return 'approve'
16752
+ * },
16753
+ * })
16754
+ * ```
16755
+ */
16756
+ interface EarnExecuteReview {
16757
+ /** The exact Adapter `execute()` call being authorized. */
16758
+ readonly encoded: EarnEncodedTransaction;
16759
+ /** Drift-free decode of {@link encoded}, verified against signed params. */
16760
+ readonly decoded: DecodedEarnTx;
16761
+ }
16762
+ /**
16763
+ * An adapter authorization review carrying {@link EarnExecuteReview} data.
16764
+ *
16765
+ * The shape an `onBeforeAuthorize` hook sees on `request.review` once
16766
+ * {@link isEarnExecuteReview} narrows it.
16767
+ */
16768
+ interface EarnExecuteAuthorizationReview {
16769
+ /** Always {@link EARN_EXECUTE_REVIEW_KIND}. */
16770
+ readonly kind: typeof EARN_EXECUTE_REVIEW_KIND;
16771
+ /** Verified EarnKit semantic review data. */
16772
+ readonly data: EarnExecuteReview;
16773
+ }
16391
16774
  /**
16392
16775
  * Source-fee quote expiry metadata returned by bridge prepare.
16393
16776
  *
@@ -17816,6 +18199,49 @@ declare class EarnServiceProvider implements EarningProvider {
17816
18199
  getClaimRewardsQuote<T extends AdapterCapabilities>(params: GetClaimRewardsQuoteServiceParams<T>): Promise<ClaimRewardsQuoteInfo>;
17817
18200
  }
17818
18201
 
18202
+ /**
18203
+ * Lazy `earn.execute` authorization-review factory for same-chain EarnKit
18204
+ * operations.
18205
+ *
18206
+ * @remarks
18207
+ * The provider attaches the {@link buildEarnExecuteDescriptor} descriptor to
18208
+ * the final earn adapter action. The adapter's shared authorization gate runs
18209
+ * the descriptor's `createReview` factory only when the application configured
18210
+ * an `onBeforeAuthorize` hook, so the decode + consistency check are skipped
18211
+ * entirely otherwise. The factory fails closed: it decodes the exact calldata
18212
+ * about to be authorized and asserts every instruction matches the
18213
+ * service-signed parameters, so a populated `earn.execute` review is proof the
18214
+ * preview matches what is signed rather than a best-effort guess.
18215
+ *
18216
+ * @packageDocumentation
18217
+ */
18218
+
18219
+ /**
18220
+ * Type guard: narrow an adapter authorization review to an EarnKit
18221
+ * `earn.execute` review.
18222
+ *
18223
+ * Use this inside an adapter `onBeforeAuthorize` hook to detect whether the
18224
+ * request carries EarnKit semantic data before reading it, instead of
18225
+ * comparing `review.kind` by hand. Robust against plain-JavaScript callers:
18226
+ * accepts `unknown` and checks the shape at runtime.
18227
+ *
18228
+ * @param review - The `review` field from an `AuthorizationRequest`, or any
18229
+ * value.
18230
+ * @returns `true` when `review` is an `earn.execute` review with the expected
18231
+ * `{ encoded, decoded }` data shape.
18232
+ *
18233
+ * @example
18234
+ * ```typescript
18235
+ * onBeforeAuthorize: async ({ review }) => {
18236
+ * if (isEarnExecuteReview(review)) {
18237
+ * await showEarnConfirmation(review.data.decoded.summary)
18238
+ * }
18239
+ * return 'approve'
18240
+ * }
18241
+ * ```
18242
+ */
18243
+ declare function isEarnExecuteReview(review: unknown): review is EarnExecuteAuthorizationReview;
18244
+
17819
18245
  /**
17820
18246
  * Estimated gas details for one transaction in a kit-level Earn quote, with
17821
18247
  * every amount as a decimal string so quote results stay JSON-serializable.
@@ -17904,6 +18330,24 @@ interface EarnConfig {
17904
18330
  * Format: `KIT_KEY:<keyId>:<keySecret>`
17905
18331
  */
17906
18332
  readonly kitKey?: string | undefined;
18333
+ /**
18334
+ * Optional base URL override for the Earn Service API.
18335
+ *
18336
+ * Defaults to `https://api.circle.com` when omitted. Override for testing
18337
+ * against staging or local environments.
18338
+ */
18339
+ readonly baseUrl?: string | undefined;
18340
+ /**
18341
+ * Enable or disable atomic batched transaction execution.
18342
+ *
18343
+ * When `true` (or `undefined` / omitted), same-chain deposit and withdraw
18344
+ * bundle the approve and execute calls into one adapter-native atomic batch
18345
+ * when the connected wallet supports it. Set to `false` to force the
18346
+ * sequential approve → execute flow.
18347
+ *
18348
+ * @defaultValue `undefined` (batching attempted when the wallet supports it)
18349
+ */
18350
+ readonly batchTransactions?: boolean | undefined;
17907
18351
  }
17908
18352
  /**
17909
18353
  * Parameters for fetching vault information.
@@ -20263,10 +20707,16 @@ declare const getVaultsParamsSchema: z.ZodObject<{
20263
20707
  }>, "many">;
20264
20708
  config: z.ZodOptional<z.ZodObject<{
20265
20709
  kitKey: z.ZodOptional<z.ZodString>;
20710
+ baseUrl: z.ZodOptional<z.ZodString>;
20711
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
20266
20712
  }, "strict", z.ZodTypeAny, {
20267
20713
  kitKey?: string | undefined;
20714
+ baseUrl?: string | undefined;
20715
+ batchTransactions?: boolean | undefined;
20268
20716
  }, {
20269
20717
  kitKey?: string | undefined;
20718
+ baseUrl?: string | undefined;
20719
+ batchTransactions?: boolean | undefined;
20270
20720
  }>>;
20271
20721
  }, "strip", z.ZodTypeAny, {
20272
20722
  vaults: {
@@ -20346,6 +20796,8 @@ declare const getVaultsParamsSchema: z.ZodObject<{
20346
20796
  }[];
20347
20797
  config?: {
20348
20798
  kitKey?: string | undefined;
20799
+ baseUrl?: string | undefined;
20800
+ batchTransactions?: boolean | undefined;
20349
20801
  } | undefined;
20350
20802
  }, {
20351
20803
  vaults: {
@@ -20425,6 +20877,8 @@ declare const getVaultsParamsSchema: z.ZodObject<{
20425
20877
  }[];
20426
20878
  config?: {
20427
20879
  kitKey?: string | undefined;
20880
+ baseUrl?: string | undefined;
20881
+ batchTransactions?: boolean | undefined;
20428
20882
  } | undefined;
20429
20883
  }>;
20430
20884
  /**
@@ -20941,10 +21395,16 @@ declare const exploreVaultsParamsSchema: z.ZodObject<{
20941
21395
  pageSize: z.ZodOptional<z.ZodNumber>;
20942
21396
  config: z.ZodOptional<z.ZodObject<{
20943
21397
  kitKey: z.ZodOptional<z.ZodString>;
21398
+ baseUrl: z.ZodOptional<z.ZodString>;
21399
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
20944
21400
  }, "strict", z.ZodTypeAny, {
20945
21401
  kitKey?: string | undefined;
21402
+ baseUrl?: string | undefined;
21403
+ batchTransactions?: boolean | undefined;
20946
21404
  }, {
20947
21405
  kitKey?: string | undefined;
21406
+ baseUrl?: string | undefined;
21407
+ batchTransactions?: boolean | undefined;
20948
21408
  }>>;
20949
21409
  }, "strip", z.ZodTypeAny, {
20950
21410
  chain: string | {
@@ -21021,6 +21481,8 @@ declare const exploreVaultsParamsSchema: z.ZodObject<{
21021
21481
  };
21022
21482
  config?: {
21023
21483
  kitKey?: string | undefined;
21484
+ baseUrl?: string | undefined;
21485
+ batchTransactions?: boolean | undefined;
21024
21486
  } | undefined;
21025
21487
  protocol?: string | undefined;
21026
21488
  asset?: string | undefined;
@@ -21104,6 +21566,8 @@ declare const exploreVaultsParamsSchema: z.ZodObject<{
21104
21566
  };
21105
21567
  config?: {
21106
21568
  kitKey?: string | undefined;
21569
+ baseUrl?: string | undefined;
21570
+ batchTransactions?: boolean | undefined;
21107
21571
  } | undefined;
21108
21572
  protocol?: string | undefined;
21109
21573
  asset?: string | undefined;
@@ -21629,10 +22093,16 @@ declare const exploreVaultsIteratorParamsSchema: z.ZodObject<Omit<{
21629
22093
  pageSize: z.ZodOptional<z.ZodNumber>;
21630
22094
  config: z.ZodOptional<z.ZodObject<{
21631
22095
  kitKey: z.ZodOptional<z.ZodString>;
22096
+ baseUrl: z.ZodOptional<z.ZodString>;
22097
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
21632
22098
  }, "strict", z.ZodTypeAny, {
21633
22099
  kitKey?: string | undefined;
22100
+ baseUrl?: string | undefined;
22101
+ batchTransactions?: boolean | undefined;
21634
22102
  }, {
21635
22103
  kitKey?: string | undefined;
22104
+ baseUrl?: string | undefined;
22105
+ batchTransactions?: boolean | undefined;
21636
22106
  }>>;
21637
22107
  }, "page">, "strip", z.ZodTypeAny, {
21638
22108
  chain: string | {
@@ -21709,6 +22179,8 @@ declare const exploreVaultsIteratorParamsSchema: z.ZodObject<Omit<{
21709
22179
  };
21710
22180
  config?: {
21711
22181
  kitKey?: string | undefined;
22182
+ baseUrl?: string | undefined;
22183
+ batchTransactions?: boolean | undefined;
21712
22184
  } | undefined;
21713
22185
  protocol?: string | undefined;
21714
22186
  asset?: string | undefined;
@@ -21791,6 +22263,8 @@ declare const exploreVaultsIteratorParamsSchema: z.ZodObject<Omit<{
21791
22263
  };
21792
22264
  config?: {
21793
22265
  kitKey?: string | undefined;
22266
+ baseUrl?: string | undefined;
22267
+ batchTransactions?: boolean | undefined;
21794
22268
  } | undefined;
21795
22269
  protocol?: string | undefined;
21796
22270
  asset?: string | undefined;
@@ -21817,21 +22291,31 @@ declare const getPositionParamsSchema: z.ZodObject<{
21817
22291
  vaultAddress: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, `0x${string}`, string>, `0x${string}`, string>;
21818
22292
  config: z.ZodOptional<z.ZodObject<{
21819
22293
  kitKey: z.ZodOptional<z.ZodString>;
22294
+ baseUrl: z.ZodOptional<z.ZodString>;
22295
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
21820
22296
  }, "strict", z.ZodTypeAny, {
21821
22297
  kitKey?: string | undefined;
22298
+ baseUrl?: string | undefined;
22299
+ batchTransactions?: boolean | undefined;
21822
22300
  }, {
21823
22301
  kitKey?: string | undefined;
22302
+ baseUrl?: string | undefined;
22303
+ batchTransactions?: boolean | undefined;
21824
22304
  }>>;
21825
22305
  }, "strip", z.ZodTypeAny, {
21826
22306
  vaultAddress: `0x${string}`;
21827
22307
  config?: {
21828
22308
  kitKey?: string | undefined;
22309
+ baseUrl?: string | undefined;
22310
+ batchTransactions?: boolean | undefined;
21829
22311
  } | undefined;
21830
22312
  from?: any;
21831
22313
  }, {
21832
22314
  vaultAddress: string;
21833
22315
  config?: {
21834
22316
  kitKey?: string | undefined;
22317
+ baseUrl?: string | undefined;
22318
+ batchTransactions?: boolean | undefined;
21835
22319
  } | undefined;
21836
22320
  from?: any;
21837
22321
  }>;
@@ -22508,10 +22992,16 @@ declare const anyDepositParamsSchema: z.ZodUnion<[z.ZodObject<{
22508
22992
  transferSpeed: z.ZodOptional<z.ZodEnum<["FAST", "SLOW"]>>;
22509
22993
  config: z.ZodOptional<z.ZodObject<{
22510
22994
  kitKey: z.ZodOptional<z.ZodString>;
22995
+ baseUrl: z.ZodOptional<z.ZodString>;
22996
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22511
22997
  }, "strict", z.ZodTypeAny, {
22512
22998
  kitKey?: string | undefined;
22999
+ baseUrl?: string | undefined;
23000
+ batchTransactions?: boolean | undefined;
22513
23001
  }, {
22514
23002
  kitKey?: string | undefined;
23003
+ baseUrl?: string | undefined;
23004
+ batchTransactions?: boolean | undefined;
22515
23005
  }>>;
22516
23006
  }, "strict", z.ZodTypeAny, {
22517
23007
  vaultAddress: `0x${string}`;
@@ -22594,6 +23084,8 @@ declare const anyDepositParamsSchema: z.ZodUnion<[z.ZodObject<{
22594
23084
  maxFee: string;
22595
23085
  config?: {
22596
23086
  kitKey?: string | undefined;
23087
+ baseUrl?: string | undefined;
23088
+ batchTransactions?: boolean | undefined;
22597
23089
  } | undefined;
22598
23090
  from?: any;
22599
23091
  transferSpeed?: "FAST" | "SLOW" | undefined;
@@ -22678,6 +23170,8 @@ declare const anyDepositParamsSchema: z.ZodUnion<[z.ZodObject<{
22678
23170
  maxFee: string;
22679
23171
  config?: {
22680
23172
  kitKey?: string | undefined;
23173
+ baseUrl?: string | undefined;
23174
+ batchTransactions?: boolean | undefined;
22681
23175
  } | undefined;
22682
23176
  from?: any;
22683
23177
  transferSpeed?: "FAST" | "SLOW" | undefined;
@@ -22688,16 +23182,24 @@ declare const anyDepositParamsSchema: z.ZodUnion<[z.ZodObject<{
22688
23182
  amount: z.ZodEffects<z.ZodPipeline<z.ZodString, z.ZodType<string, z.ZodTypeDef, string>>, string, string>;
22689
23183
  config: z.ZodOptional<z.ZodObject<{
22690
23184
  kitKey: z.ZodOptional<z.ZodString>;
23185
+ baseUrl: z.ZodOptional<z.ZodString>;
23186
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22691
23187
  }, "strict", z.ZodTypeAny, {
22692
23188
  kitKey?: string | undefined;
23189
+ baseUrl?: string | undefined;
23190
+ batchTransactions?: boolean | undefined;
22693
23191
  }, {
22694
23192
  kitKey?: string | undefined;
23193
+ baseUrl?: string | undefined;
23194
+ batchTransactions?: boolean | undefined;
22695
23195
  }>>;
22696
23196
  }, "strict", z.ZodTypeAny, {
22697
23197
  vaultAddress: `0x${string}`;
22698
23198
  amount: string;
22699
23199
  config?: {
22700
23200
  kitKey?: string | undefined;
23201
+ baseUrl?: string | undefined;
23202
+ batchTransactions?: boolean | undefined;
22701
23203
  } | undefined;
22702
23204
  from?: any;
22703
23205
  to?: undefined;
@@ -22706,6 +23208,8 @@ declare const anyDepositParamsSchema: z.ZodUnion<[z.ZodObject<{
22706
23208
  amount: string;
22707
23209
  config?: {
22708
23210
  kitKey?: string | undefined;
23211
+ baseUrl?: string | undefined;
23212
+ batchTransactions?: boolean | undefined;
22709
23213
  } | undefined;
22710
23214
  from?: any;
22711
23215
  to?: undefined;
@@ -22733,16 +23237,24 @@ declare const depositParamsSchema: z.ZodObject<{
22733
23237
  amount: z.ZodEffects<z.ZodPipeline<z.ZodString, z.ZodType<string, z.ZodTypeDef, string>>, string, string>;
22734
23238
  config: z.ZodOptional<z.ZodObject<{
22735
23239
  kitKey: z.ZodOptional<z.ZodString>;
23240
+ baseUrl: z.ZodOptional<z.ZodString>;
23241
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22736
23242
  }, "strict", z.ZodTypeAny, {
22737
23243
  kitKey?: string | undefined;
23244
+ baseUrl?: string | undefined;
23245
+ batchTransactions?: boolean | undefined;
22738
23246
  }, {
22739
23247
  kitKey?: string | undefined;
23248
+ baseUrl?: string | undefined;
23249
+ batchTransactions?: boolean | undefined;
22740
23250
  }>>;
22741
23251
  }, "strip", z.ZodTypeAny, {
22742
23252
  vaultAddress: `0x${string}`;
22743
23253
  amount: string;
22744
23254
  config?: {
22745
23255
  kitKey?: string | undefined;
23256
+ baseUrl?: string | undefined;
23257
+ batchTransactions?: boolean | undefined;
22746
23258
  } | undefined;
22747
23259
  from?: any;
22748
23260
  }, {
@@ -22750,6 +23262,8 @@ declare const depositParamsSchema: z.ZodObject<{
22750
23262
  amount: string;
22751
23263
  config?: {
22752
23264
  kitKey?: string | undefined;
23265
+ baseUrl?: string | undefined;
23266
+ batchTransactions?: boolean | undefined;
22753
23267
  } | undefined;
22754
23268
  from?: any;
22755
23269
  }>;
@@ -22769,20 +23283,30 @@ declare const getCrossChainDepositStatusParamsSchema: z.ZodObject<{
22769
23283
  execId: z.ZodString;
22770
23284
  config: z.ZodOptional<z.ZodObject<{
22771
23285
  kitKey: z.ZodOptional<z.ZodString>;
23286
+ baseUrl: z.ZodOptional<z.ZodString>;
23287
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22772
23288
  }, "strict", z.ZodTypeAny, {
22773
23289
  kitKey?: string | undefined;
23290
+ baseUrl?: string | undefined;
23291
+ batchTransactions?: boolean | undefined;
22774
23292
  }, {
22775
23293
  kitKey?: string | undefined;
23294
+ baseUrl?: string | undefined;
23295
+ batchTransactions?: boolean | undefined;
22776
23296
  }>>;
22777
23297
  }, "strip", z.ZodTypeAny, {
22778
23298
  execId: string;
22779
23299
  config?: {
22780
23300
  kitKey?: string | undefined;
23301
+ baseUrl?: string | undefined;
23302
+ batchTransactions?: boolean | undefined;
22781
23303
  } | undefined;
22782
23304
  }, {
22783
23305
  execId: string;
22784
23306
  config?: {
22785
23307
  kitKey?: string | undefined;
23308
+ baseUrl?: string | undefined;
23309
+ batchTransactions?: boolean | undefined;
22786
23310
  } | undefined;
22787
23311
  }>;
22788
23312
  /**
@@ -22803,10 +23327,16 @@ declare const waitForCrossChainDepositParamsSchema: z.ZodObject<{
22803
23327
  execId: z.ZodString;
22804
23328
  config: z.ZodOptional<z.ZodObject<{
22805
23329
  kitKey: z.ZodOptional<z.ZodString>;
23330
+ baseUrl: z.ZodOptional<z.ZodString>;
23331
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22806
23332
  }, "strict", z.ZodTypeAny, {
22807
23333
  kitKey?: string | undefined;
23334
+ baseUrl?: string | undefined;
23335
+ batchTransactions?: boolean | undefined;
22808
23336
  }, {
22809
23337
  kitKey?: string | undefined;
23338
+ baseUrl?: string | undefined;
23339
+ batchTransactions?: boolean | undefined;
22810
23340
  }>>;
22811
23341
  pollIntervalMs: z.ZodOptional<z.ZodNumber>;
22812
23342
  maxWaitMs: z.ZodOptional<z.ZodNumber>;
@@ -22815,6 +23345,8 @@ declare const waitForCrossChainDepositParamsSchema: z.ZodObject<{
22815
23345
  execId: string;
22816
23346
  config?: {
22817
23347
  kitKey?: string | undefined;
23348
+ baseUrl?: string | undefined;
23349
+ batchTransactions?: boolean | undefined;
22818
23350
  } | undefined;
22819
23351
  pollIntervalMs?: number | undefined;
22820
23352
  maxWaitMs?: number | undefined;
@@ -22823,6 +23355,8 @@ declare const waitForCrossChainDepositParamsSchema: z.ZodObject<{
22823
23355
  execId: string;
22824
23356
  config?: {
22825
23357
  kitKey?: string | undefined;
23358
+ baseUrl?: string | undefined;
23359
+ batchTransactions?: boolean | undefined;
22826
23360
  } | undefined;
22827
23361
  pollIntervalMs?: number | undefined;
22828
23362
  maxWaitMs?: number | undefined;
@@ -22848,16 +23382,24 @@ declare const withdrawParamsSchema: z.ZodObject<{
22848
23382
  amount: z.ZodEffects<z.ZodPipeline<z.ZodString, z.ZodType<string, z.ZodTypeDef, string>>, string, string>;
22849
23383
  config: z.ZodOptional<z.ZodObject<{
22850
23384
  kitKey: z.ZodOptional<z.ZodString>;
23385
+ baseUrl: z.ZodOptional<z.ZodString>;
23386
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22851
23387
  }, "strict", z.ZodTypeAny, {
22852
23388
  kitKey?: string | undefined;
23389
+ baseUrl?: string | undefined;
23390
+ batchTransactions?: boolean | undefined;
22853
23391
  }, {
22854
23392
  kitKey?: string | undefined;
23393
+ baseUrl?: string | undefined;
23394
+ batchTransactions?: boolean | undefined;
22855
23395
  }>>;
22856
23396
  }, "strip", z.ZodTypeAny, {
22857
23397
  vaultAddress: `0x${string}`;
22858
23398
  amount: string;
22859
23399
  config?: {
22860
23400
  kitKey?: string | undefined;
23401
+ baseUrl?: string | undefined;
23402
+ batchTransactions?: boolean | undefined;
22861
23403
  } | undefined;
22862
23404
  from?: any;
22863
23405
  }, {
@@ -22865,6 +23407,8 @@ declare const withdrawParamsSchema: z.ZodObject<{
22865
23407
  amount: string;
22866
23408
  config?: {
22867
23409
  kitKey?: string | undefined;
23410
+ baseUrl?: string | undefined;
23411
+ batchTransactions?: boolean | undefined;
22868
23412
  } | undefined;
22869
23413
  from?: any;
22870
23414
  }>;
@@ -22888,21 +23432,31 @@ declare const claimRewardsParamsSchema: z.ZodObject<{
22888
23432
  vaultAddress: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, `0x${string}`, string>, `0x${string}`, string>;
22889
23433
  config: z.ZodOptional<z.ZodObject<{
22890
23434
  kitKey: z.ZodOptional<z.ZodString>;
23435
+ baseUrl: z.ZodOptional<z.ZodString>;
23436
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22891
23437
  }, "strict", z.ZodTypeAny, {
22892
23438
  kitKey?: string | undefined;
23439
+ baseUrl?: string | undefined;
23440
+ batchTransactions?: boolean | undefined;
22893
23441
  }, {
22894
23442
  kitKey?: string | undefined;
23443
+ baseUrl?: string | undefined;
23444
+ batchTransactions?: boolean | undefined;
22895
23445
  }>>;
22896
23446
  }, "strip", z.ZodTypeAny, {
22897
23447
  vaultAddress: `0x${string}`;
22898
23448
  config?: {
22899
23449
  kitKey?: string | undefined;
23450
+ baseUrl?: string | undefined;
23451
+ batchTransactions?: boolean | undefined;
22900
23452
  } | undefined;
22901
23453
  from?: any;
22902
23454
  }, {
22903
23455
  vaultAddress: string;
22904
23456
  config?: {
22905
23457
  kitKey?: string | undefined;
23458
+ baseUrl?: string | undefined;
23459
+ batchTransactions?: boolean | undefined;
22906
23460
  } | undefined;
22907
23461
  from?: any;
22908
23462
  }>;
@@ -22952,16 +23506,24 @@ declare const getWithdrawalQuoteParamsSchema: z.ZodObject<{
22952
23506
  amount: z.ZodEffects<z.ZodPipeline<z.ZodString, z.ZodType<string, z.ZodTypeDef, string>>, string, string>;
22953
23507
  config: z.ZodOptional<z.ZodObject<{
22954
23508
  kitKey: z.ZodOptional<z.ZodString>;
23509
+ baseUrl: z.ZodOptional<z.ZodString>;
23510
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22955
23511
  }, "strict", z.ZodTypeAny, {
22956
23512
  kitKey?: string | undefined;
23513
+ baseUrl?: string | undefined;
23514
+ batchTransactions?: boolean | undefined;
22957
23515
  }, {
22958
23516
  kitKey?: string | undefined;
23517
+ baseUrl?: string | undefined;
23518
+ batchTransactions?: boolean | undefined;
22959
23519
  }>>;
22960
23520
  }, "strip", z.ZodTypeAny, {
22961
23521
  vaultAddress: `0x${string}`;
22962
23522
  amount: string;
22963
23523
  config?: {
22964
23524
  kitKey?: string | undefined;
23525
+ baseUrl?: string | undefined;
23526
+ batchTransactions?: boolean | undefined;
22965
23527
  } | undefined;
22966
23528
  from?: any;
22967
23529
  }, {
@@ -22969,6 +23531,8 @@ declare const getWithdrawalQuoteParamsSchema: z.ZodObject<{
22969
23531
  amount: string;
22970
23532
  config?: {
22971
23533
  kitKey?: string | undefined;
23534
+ baseUrl?: string | undefined;
23535
+ batchTransactions?: boolean | undefined;
22972
23536
  } | undefined;
22973
23537
  from?: any;
22974
23538
  }>;
@@ -22992,21 +23556,31 @@ declare const getClaimRewardsQuoteParamsSchema: z.ZodObject<{
22992
23556
  vaultAddress: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, string, string>, string, string>, `0x${string}`, string>, `0x${string}`, string>;
22993
23557
  config: z.ZodOptional<z.ZodObject<{
22994
23558
  kitKey: z.ZodOptional<z.ZodString>;
23559
+ baseUrl: z.ZodOptional<z.ZodString>;
23560
+ batchTransactions: z.ZodOptional<z.ZodBoolean>;
22995
23561
  }, "strict", z.ZodTypeAny, {
22996
23562
  kitKey?: string | undefined;
23563
+ baseUrl?: string | undefined;
23564
+ batchTransactions?: boolean | undefined;
22997
23565
  }, {
22998
23566
  kitKey?: string | undefined;
23567
+ baseUrl?: string | undefined;
23568
+ batchTransactions?: boolean | undefined;
22999
23569
  }>>;
23000
23570
  }, "strip", z.ZodTypeAny, {
23001
23571
  vaultAddress: `0x${string}`;
23002
23572
  config?: {
23003
23573
  kitKey?: string | undefined;
23574
+ baseUrl?: string | undefined;
23575
+ batchTransactions?: boolean | undefined;
23004
23576
  } | undefined;
23005
23577
  from?: any;
23006
23578
  }, {
23007
23579
  vaultAddress: string;
23008
23580
  config?: {
23009
23581
  kitKey?: string | undefined;
23582
+ baseUrl?: string | undefined;
23583
+ batchTransactions?: boolean | undefined;
23010
23584
  } | undefined;
23011
23585
  from?: any;
23012
23586
  }>;
@@ -24615,956 +25189,828 @@ interface IGatewayProvider<TProviderActions = GatewayV1Actions> {
24615
25189
  }
24616
25190
 
24617
25191
  /**
24618
- * A custom token contract address string.
24619
- *
24620
- * This type represents token addresses that are not known aliases.
24621
- * It uses a branded type pattern to preserve IDE autocomplete for TokenAlias
24622
- * while still accepting arbitrary address strings.
24623
- */
24624
- type TokenAddress = string & {
24625
- readonly __tokenAddress?: never;
24626
- };
24627
- /**
24628
- * Known token aliases supported by AppKit.
24629
- *
24630
- * These aliases map to chain-specific token addresses. `USDC`, `USDT`, and
24631
- * `NATIVE` have dedicated transfer actions in the adapter layer. `EURC` has no
24632
- * dedicated action — it resolves to the chain's `eurcAddress` and is sent via
24633
- * the generic token transfer action, so it is only supported on chains where
24634
- * `eurcAddress` is set.
25192
+ * Destination for a Gateway spend (mint) operation.
24635
25193
  *
24636
25194
  * @remarks
24637
- * For swap operations, see {@link SupportedToken} in SwapKit which supports
24638
- * additional tokens (DAI, USDE, PYUSD).
24639
- */
24640
- type TokenAlias = 'USDC' | 'USDT' | 'NATIVE' | 'EURC';
24641
- /**
24642
- * Operation types that support the `getFee`/`getFeeRecipient` hooks.
24643
- */
24644
- type FeeOperationType = 'bridge' | 'swap';
24645
- /**
24646
- * Union type of all supported operation types in the AppKit.
24647
- *
24648
- * This type ensures type safety when specifying operation types and enables
24649
- * proper parameter validation based on the selected operation.
24650
- */
24651
- type OperationType = FeeOperationType | 'earn' | 'unifiedBalance';
24652
- /**
24653
- * Maps operation types to their corresponding parameter interfaces.
24654
- *
24655
- * This interface maps operation types to their parameter structures for
24656
- * compile-time validation in shared AppKit helpers.
25195
+ * Omitting `recipientAddress` causes funds to be minted to the
25196
+ * address resolved from the adapter. Providing it overrides the
25197
+ * default destination.
24657
25198
  *
24658
- * @remarks `earn` is included so consumers can refer to the full EarnKit
24659
- * operation-parameter union through AppKit types. Developer fee hooks
24660
- * intentionally use {@link FeeOperationType}, so they do not accept earn
24661
- * parameters until EarnKit supports fee-bearing requests.
25199
+ * @typeParam TAdapterCapabilities - Adapter capability constraints.
25200
+ * @typeParam TChainIdentifier - Accepted chain identifier type.
24662
25201
  *
24663
25202
  * @example
24664
25203
  * ```typescript
24665
- * // TypeScript will enforce that bridge operations use BridgeParams
24666
- * type BridgeParamsType = OperationParamsMap['bridge'] // BridgeParams
24667
- * // TypeScript will enforce that swap operations use SwapParams
24668
- * type SwapParamsType = OperationParamsMap['swap'] // SwapParams
24669
- * // TypeScript will enforce that earn operations use EarnOperationParams
24670
- * type EarnParamsType = OperationParamsMap['earn'] // EarnOperationParams
25204
+ * import type { SpendDestination } from '@circle-fin/unified-balance-kit'
25205
+ *
25206
+ * const destination: SpendDestination = {
25207
+ * adapter: avalancheAdapter,
25208
+ * chain: 'Avalanche',
25209
+ * recipientAddress: '0xDEST…abcd',
25210
+ * }
24671
25211
  * ```
24672
25212
  */
24673
- interface OperationParamsMap {
24674
- bridge: BridgeParams;
24675
- swap: SwapParams;
24676
- earn: EarnOperationParams;
24677
- }
25213
+ type SpendDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> = {
25214
+ /** The adapter for executing on-chain calls. */
25215
+ adapter: Adapter<TAdapterCapabilities>;
25216
+ /** The destination chain. */
25217
+ chain: TChainIdentifier;
25218
+ /**
25219
+ * Optional custom recipient address. When omitted the adapter's
25220
+ * resolved address is used.
25221
+ */
25222
+ recipientAddress?: string;
25223
+ /**
25224
+ * Enable Circle's Forwarding Service for automatic mint submission.
25225
+ * When `true`, the Gateway API handles the destination mint via its
25226
+ * relayer and the SDK polls for completion instead of executing a
25227
+ * user-signed mint transaction.
25228
+ */
25229
+ useForwarder?: boolean;
25230
+ } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
24678
25231
  /**
24679
- * Context interface for the AppKit with strongly typed getFee method.
25232
+ * Forwarder-only destination for spend operations.
24680
25233
  *
24681
- * This interface uses TypeScript function overloads to provide type-safe
24682
- * parameter validation based on the operation type. Each operation type
24683
- * maps to specific parameter types, ensuring compile-time safety and
24684
- * excellent developer experience with full IntelliSense support.
25234
+ * Used when Circle's Forwarding Service handles the mint transaction
25235
+ * and no destination adapter is available. Set `useForwarder` to `true`
25236
+ * and provide a `recipientAddress`.
24685
25237
  *
24686
- * The interface supports both direct operation-specific overloads and a
24687
- * generic overload for advanced use cases while maintaining type safety.
25238
+ * @typeParam TChainIdentifier - Accepted chain identifier type.
24688
25239
  *
24689
25240
  * @example
24690
25241
  * ```typescript
24691
- * // Bridge operation - uses BridgeParams
24692
- * const bridgeFee = await context.getFee('bridge', {
24693
- * from: { adapter: sourceAdapter, chain: 'Ethereum' },
24694
- * to: { adapter: destAdapter, chain: 'Polygon' },
24695
- * amount: '100.50'
24696
- * })
25242
+ * import type { ForwarderSpendDestination } from '@circle-fin/unified-balance-kit'
25243
+ *
25244
+ * const destination: ForwarderSpendDestination = {
25245
+ * chain: 'Base',
25246
+ * recipientAddress: '0xDEST…abcd',
25247
+ * useForwarder: true,
25248
+ * }
24697
25249
  * ```
24698
25250
  */
24699
- interface AppKitContext {
24700
- /**
24701
- * Get fee estimation for bridge or swap operations.
24702
- *
24703
- * Calculate the estimated fees for cross-chain bridge transfers, same-chain
24704
- * token swaps. Returns the fee amount in smallest token units.
24705
- *
24706
- * The function signature uses TypeScript's generic constraint pattern to ensure
24707
- * type safety: when type is 'bridge', params must be BridgeParams; when type
24708
- * is 'swap', params must be SwapParams.
24709
- *
24710
- * @typeParam T - The fee operation type ('bridge' | 'swap')
24711
- * @param type - Operation type: 'bridge' for cross-chain transfers, 'swap' for same-chain swaps
24712
- * @param params - Operation-specific parameters matching the type
24713
- * @returns Promise resolving to fee amount as string in smallest token units
24714
- * @throws {@link ValidationError} If operation parameters are invalid
24715
- * @throws {@link UnsupportedRouteError} If the operation route is not supported
24716
- *
24717
- * @example
24718
- * ```typescript
24719
- * // Bridge fee
24720
- * const bridgeFee = await context.getFee?.('bridge', bridgeParams)
24721
- *
24722
- * // Swap fee
24723
- * const swapFee = await context.getFee?.('swap', swapParams)
24724
- *
24725
- * // Generic usage
24726
- * function estimateFee<T extends FeeOperationType>(
24727
- * operation: T,
24728
- * params: OperationParamsMap[T]
24729
- * ) {
24730
- * return context.getFee(operation, params) // Fully type-safe
24731
- * }
24732
- * ```
24733
- */
24734
- getFee?<T extends FeeOperationType>(type: T, params: OperationParamsMap[T]): Promise<string>;
24735
- /**
24736
- * Get the fee recipient address for a specific operation and chain.
24737
- *
24738
- * This method returns the address that will receive protocol fees for
24739
- * the specified operation type on the given chain. Useful for transparency
24740
- * and fee tracking purposes.
24741
- *
24742
- * @remarks When this hook is used for bridging operations, the `params` object within `info` will be empty.
24743
- * This is due to a limitation in the underlying `BridgeKit`, which does not provide bridge parameters
24744
- * to its fee recipient hook.
24745
- *
24746
- * @typeParam T - The fee operation type ('bridge' | 'swap')
24747
- * @param type - The specific operation type
24748
- * @param info - Object containing chain and parameter information
24749
- * @returns Promise resolving to the fee recipient address
24750
- * @throws {@link ValidationError} If parameters are invalid
24751
- * @throws {@link UnsupportedChainError} If the chain is not supported
24752
- *
24753
- * @example
24754
- * ```typescript
24755
- * const recipient = await context.getFeeRecipient('bridge', {
24756
- * chain: ethereumChain,
24757
- * params: bridgeParams
24758
- * })
24759
- * ```
24760
- */
24761
- getFeeRecipient?<T extends FeeOperationType>(type: T, info: {
24762
- chain: ChainDefinition;
24763
- params: OperationParamsMap[T];
24764
- }): Promise<string>;
24765
- /**
24766
- * Event handlers registered for AppKit operations.
24767
- *
24768
- * This property stores event handlers that are registered via the AppKit's
24769
- * `on()` method. Handlers are grouped by operation type. The runtime buckets
24770
- * are `bridge` and `earn`; the context can add more operation buckets as
24771
- * AppKit wires action handlers for additional kits.
24772
- *
24773
- * Within each operation bucket, handlers are keyed by action name (for
24774
- * example, `bridge.approve` or `earn.deposit`) or `*` for wildcard handlers.
24775
- * Each action can have multiple handlers registered, allowing multiple
24776
- * subscribers to listen to the same event.
24777
- *
24778
- * The handlers are stored in the context to allow deferred registration with
24779
- * underlying operation kits, enabling a clean separation between event
24780
- * registration and operation execution.
24781
- *
24782
- * @example
24783
- * ```typescript
24784
- * const context = createContext()
24785
- * // Handlers registered via kit.on() are stored by operation type
24786
- * // Bridge handlers are registered with BridgeKit when bridge() runs
24787
- * // Earn handlers are registered with EarnKit when earn operations run
24788
- * ```
24789
- */
24790
- actions: Record<'bridge' | 'earn', Record<string, ((payload: unknown) => void)[]>>;
24791
- /**
24792
- * Disable success analytics for the underlying EarnKit, SwapKit, and
24793
- * UnifiedBalanceKit.
24794
- *
24795
- * When `true`, completed earn, swap, and unified balance operations will not
24796
- * POST analytics events. This does not disable error reporting; use
24797
- * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
24798
- *
24799
- * @defaultValue false
24800
- */
24801
- disableAnalytics?: boolean;
25251
+ interface ForwarderSpendDestination<TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
25252
+ /** The destination chain where USDC will be minted. */
25253
+ chain: TChainIdentifier;
25254
+ /** The recipient address that will receive the minted USDC. */
25255
+ recipientAddress: string;
25256
+ /** Enable Circle's Forwarding Service for the destination mint. */
25257
+ useForwarder: boolean;
25258
+ }
25259
+ /**
25260
+ * Union of spend destination variants.
25261
+ *
25262
+ * @see {@link SpendDestination}
25263
+ * @see {@link ForwarderSpendDestination}
25264
+ */
25265
+ type SpendDestinationUnion<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> = SpendDestination<TAdapterCapabilities, TChainIdentifier> | ForwarderSpendDestination<TChainIdentifier>;
25266
+ /**
25267
+ * An amount of USDC to pull from a specific chain.
25268
+ *
25269
+ * @example
25270
+ * ```typescript
25271
+ * import type { Allocation } from '@circle-fin/unified-balance-kit'
25272
+ *
25273
+ * const allocation: Allocation = {
25274
+ * amount: '50',
25275
+ * chain: 'Ethereum',
25276
+ * }
25277
+ * ```
25278
+ */
25279
+ interface Allocation {
24802
25280
  /**
24803
- * Disable error telemetry for all sub-kits.
24804
- *
24805
- * When `true`, none of the underlying kits (BridgeKit, SwapKit, EarnKit,
24806
- * UnifiedBalanceKit) will POST error details to the telemetry
24807
- * endpoint when operations throw. Defaults to `false` (enabled).
24808
- *
24809
- * @defaultValue false
25281
+ * The amount to pull from this chain (human-readable decimal
25282
+ * string).
24810
25283
  */
24811
- disableErrorReporting?: boolean;
25284
+ amount: string;
24812
25285
  /**
24813
- * Custom HTTP headers forwarded with the underlying CCTP provider's
24814
- * attestation (Iris) API requests made by bridge operations.
25286
+ * The chain from which to pull the funds.
24815
25287
  *
24816
25288
  * @remarks
24817
- * Headers are merged on top of the SDK defaults (such as `Content-Type`)
24818
- * rather than replacing them. The header is forwarded as-is to Circle's API;
24819
- * the SDK does not interpret it.
25289
+ * All allocations in a single spend must be either all mainnet
25290
+ * or all testnet. Mixing is not allowed.
24820
25291
  */
24821
- headers?: Record<string, string>;
25292
+ chain: UnifiedBalanceChainIdentifier;
24822
25293
  }
24823
25294
  /**
24824
- * Earn operation namespace exposed as `kit.earn`.
25295
+ * Extends {@link Allocation} with the resolved source Gateway
25296
+ * account address.
24825
25297
  *
24826
- * Mirrors the operations currently available from `@circle-fin/earn-kit`.
24827
- * Step events use the AppKit event API (`kit.on('earn.*')` / `kit.on('*')`).
25298
+ * @example
25299
+ * ```typescript
25300
+ * import type { AllocationResult } from '@circle-fin/unified-balance-kit'
25301
+ *
25302
+ * const result: AllocationResult = {
25303
+ * amount: '50',
25304
+ * chain: 'Ethereum',
25305
+ * sourceAccount: '0x1234…5678',
25306
+ * }
25307
+ * ```
25308
+ */
25309
+ interface AllocationResult extends Allocation {
25310
+ /** The Gateway account address from which this amount was pulled. */
25311
+ sourceAccount: string;
25312
+ }
25313
+ /**
25314
+ * A spend source providing an adapter and optional per-chain allocations.
25315
+ *
25316
+ * @remarks
25317
+ * When `allocations` is omitted the provider's automatic allocation
25318
+ * logic decides which chains to draw from. A top-level `amount`
25319
+ * field on {@link SpendParams} is **required** in that case.
25320
+ *
25321
+ * When `allocations` is present, every source in the `from` array
25322
+ * must also include `allocations` (all-or-nothing rule).
25323
+ *
25324
+ * @typeParam TAdapterCapabilities - Adapter capability constraints.
24828
25325
  *
24829
25326
  * @example
24830
25327
  * ```typescript
24831
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
25328
+ * import type { SpendSource } from '@circle-fin/unified-balance-kit'
24832
25329
  *
24833
- * const kit = new AppKit()
25330
+ * // With explicit allocations
25331
+ * const withAlloc: SpendSource = {
25332
+ * adapter: evmAdapter,
25333
+ * allocations: [
25334
+ * { amount: '40', chain: 'Ethereum' },
25335
+ * { amount: '60', chain: 'Base' },
25336
+ * ],
25337
+ * }
24834
25338
  *
24835
- * const result = await kit.earn.deposit({
24836
- * from: { adapter, chain: EarnChain.Arc_Testnet },
24837
- * vaultAddress: '0x...',
24838
- * amount: '100.50',
24839
- * })
25339
+ * // Adapter-only (auto-allocation)
25340
+ * const adapterOnly: SpendSource = {
25341
+ * adapter: evmAdapter,
25342
+ * }
24840
25343
  * ```
24841
25344
  */
24842
- interface AppKitEarnOperations {
25345
+ type SpendSource<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = {
25346
+ /** The adapter for executing on-chain calls. */
25347
+ adapter: Adapter<TAdapterCapabilities>;
24843
25348
  /**
24844
- * Deposit into an earn vault.
24845
- *
24846
- * @param params - Deposit parameters
24847
- * @returns Promise resolving to the deposit result
24848
- * @throws If validation, provider lookup, or transaction execution fails
24849
- *
24850
- * @example
24851
- * ```typescript
24852
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
24853
- *
24854
- * const kit = new AppKit()
24855
- * const result = await kit.earn.deposit({
24856
- * from: { adapter, chain: EarnChain.Arc_Testnet },
24857
- * vaultAddress: '0x...',
24858
- * amount: '100.50',
24859
- * })
24860
- * ```
25349
+ * Optional per-chain allocations describing how much to pull from
25350
+ * each chain. When omitted the provider computes allocations
25351
+ * automatically.
24861
25352
  */
24862
- deposit<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: SameChainDepositParams<TFromAdapterCapabilities>): Promise<EarnSameChainDepositResult>;
25353
+ allocations?: Allocation | Allocation[];
24863
25354
  /**
24864
- * Deposit into an earn vault from another chain through the bridge flow.
25355
+ * Optional Gateway account to pull from (delegate scenarios).
24865
25356
  *
24866
- * @param params - Cross-chain deposit parameters
24867
- * @returns Promise resolving to the bridge submission details
24868
- * @throws If validation, provider lookup, or the bridge flow fails
25357
+ * @remarks
25358
+ * When omitted the adapter's resolved address is used. When
25359
+ * provided you must be a delegate for this account.
24869
25360
  */
24870
- deposit<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: CrossChainDepositParams<TFromAdapterCapabilities>): Promise<EarnCrossChainDepositResult>;
25361
+ sourceAccount?: string;
25362
+ } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
25363
+ /**
25364
+ * Base fields shared by all spend parameter variants.
25365
+ */
25366
+ interface SpendParamsBase<TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
25367
+ /** Where to mint the USDC on the destination chain. */
25368
+ to: SpendDestinationUnion<TToAdapterCapabilities, TChainIdentifier>;
24871
25369
  /**
24872
- * Deposit into an earn vault, on the same chain or cross-chain.
24873
- *
24874
- * @param params - Deposit parameters
24875
- * @returns Promise resolving to same-chain transaction details or
24876
- * cross-chain submission details
24877
- * @throws If validation, provider lookup, or execution fails
25370
+ * The token to spend. Currently only USDC is supported.
25371
+ * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
24878
25372
  */
24879
- deposit<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: AnyDepositParams<TFromAdapterCapabilities>): Promise<EarnDepositOutcome>;
25373
+ token?: SupportedTokenInput;
24880
25374
  /**
24881
- * Withdraw from an earn vault.
24882
- *
24883
- * @param params - Withdrawal parameters
24884
- * @returns Promise resolving to the withdrawal result
24885
- * @throws If validation, provider lookup, or transaction execution fails
24886
- *
24887
- * @example
24888
- * ```typescript
24889
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
25375
+ * Total USDC amount to spend (human-readable decimal string).
24890
25376
  *
24891
- * const kit = new AppKit()
24892
- * const result = await kit.earn.withdraw({
24893
- * from: { adapter, chain: EarnChain.Arc_Testnet },
24894
- * vaultAddress: '0x...',
24895
- * amount: '50.00',
24896
- * })
24897
- * ```
25377
+ * @remarks
25378
+ * Always required. When sources include explicit `allocations`,
25379
+ * `sum(allocations)` must equal `amount`.
24898
25380
  */
24899
- withdraw<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: WithdrawParams<TFromAdapterCapabilities>): Promise<EarnWithdrawResult>;
25381
+ amount: string;
25382
+ /** Optional configuration for the spend operation. */
25383
+ config?: SpendConfig;
25384
+ }
25385
+ /**
25386
+ * Standard spend: `from` is required (no retry).
25387
+ */
25388
+ interface SpendParamsWithFrom<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> extends SpendParamsBase<TToAdapterCapabilities, TChainIdentifier> {
24900
25389
  /**
24901
- * Claim available earn rewards.
24902
- *
24903
- * @param params - Claim rewards parameters
24904
- * @returns Promise resolving to the claim rewards result
24905
- * @throws If validation, provider lookup, or transaction execution fails
24906
- *
24907
- * @example
24908
- * ```typescript
24909
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
24910
- *
24911
- * const kit = new AppKit()
24912
- * const result = await kit.earn.claimRewards({
24913
- * from: { adapter, chain: EarnChain.Arc_Testnet },
24914
- * vaultAddress: '0x...',
24915
- * })
24916
- * ```
25390
+ * One or more sources to pull funds from.
24917
25391
  *
24918
- * @internal
25392
+ * Use an array when spending from multiple adapters (e.g.
25393
+ * combining EVM and non-EVM accounts).
24919
25394
  */
24920
- claimRewards<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: ClaimRewardsParams<TFromAdapterCapabilities>): Promise<EarnClaimRewardsResult>;
25395
+ from: SpendSource<TFromAdapterCapabilities> | SpendSource<TFromAdapterCapabilities>[];
25396
+ }
25397
+ /**
25398
+ * Retry spend: `from` is optional because we skip the
25399
+ * estimate/sign/transfer steps and go straight to mint.
25400
+ */
25401
+ interface SpendParamsRetry<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> extends SpendParamsBase<TToAdapterCapabilities, TChainIdentifier> {
25402
+ from?: SpendSource<TFromAdapterCapabilities> | SpendSource<TFromAdapterCapabilities>[];
25403
+ config: SpendConfig & {
25404
+ retry: RetryMintConfig;
25405
+ };
25406
+ }
25407
+ /**
25408
+ * Parameters for spending (minting) USDC on a destination chain from
25409
+ * one or more Gateway account sources.
25410
+ *
25411
+ * @remarks
25412
+ * `from` can be a single source or an array when pulling from
25413
+ * multiple adapters (e.g. an EVM account and a Solana account).
25414
+ *
25415
+ * @typeParam TFromAdapterCapabilities - Source adapter capabilities.
25416
+ * @typeParam TToAdapterCapabilities - Destination adapter capabilities.
25417
+ * @typeParam TChainIdentifier - Accepted chain identifier type.
25418
+ *
25419
+ * @example
25420
+ * ```typescript
25421
+ * import type { SpendParams } from '@circle-fin/unified-balance-kit'
25422
+ *
25423
+ * const params: SpendParams = {
25424
+ * from: {
25425
+ * adapter: evmAdapter,
25426
+ * allocations: { amount: '100', chain: 'Ethereum' },
25427
+ * },
25428
+ * to: { adapter: avalancheAdapter, chain: 'Avalanche' },
25429
+ * amount: '100',
25430
+ * token: 'USDC',
25431
+ * }
25432
+ * ```
25433
+ */
25434
+ type SpendParams<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> = SpendParamsWithFrom<TFromAdapterCapabilities, TToAdapterCapabilities, TChainIdentifier> | SpendParamsRetry<TFromAdapterCapabilities, TToAdapterCapabilities, TChainIdentifier>;
25435
+ /**
25436
+ * Result returned after a successful spend (mint) operation.
25437
+ *
25438
+ * @example
25439
+ * ```typescript
25440
+ * import type { SpendResult } from '@circle-fin/unified-balance-kit'
25441
+ *
25442
+ * const result: SpendResult = {
25443
+ * allocations: [
25444
+ * { amount: '100', chain: 'Ethereum', sourceAccount: '0x…' },
25445
+ * ],
25446
+ * recipientAddress: '0xDEST…abcd',
25447
+ * destinationChain: 'Avalanche',
25448
+ * txHash: '0xabcdef…',
25449
+ * explorerUrl: 'https://snowtrace.io/tx/0xabcdef…',
25450
+ * }
25451
+ * ```
25452
+ */
25453
+ interface SpendResult {
24921
25454
  /**
24922
- * Fetch earn vault information.
24923
- *
24924
- * @param params - Vault query parameters
24925
- * @returns Promise resolving to vault data and per-vault errors
24926
- * @throws If validation or provider lookup fails
24927
- *
24928
- * @example
24929
- * ```typescript
24930
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
24931
- *
24932
- * const kit = new AppKit()
24933
- * const result = await kit.earn.getVaults({
24934
- * vaults: [{ chain: EarnChain.Arc_Testnet, vaultAddress: '0x...' }],
24935
- * })
24936
- * ```
25455
+ * Flattened list of allocations that were executed, each with its
25456
+ * source Gateway account. Only present for non-retry spends.
24937
25457
  */
24938
- getVaults(params: GetVaultsParams): Promise<EarnGetVaultsResult>;
25458
+ allocations?: AllocationResult[];
25459
+ /** The address that received the minted USDC. */
25460
+ recipientAddress: string;
25461
+ /** The destination chain on which the recipient received the USDC. */
25462
+ destinationChain: Blockchain;
24939
25463
  /**
24940
- * Discover earn vaults available on a chain.
24941
- *
24942
- * @param params - Discovery parameters with chain and optional filters
24943
- * @returns Promise resolving to matching vaults with pagination metadata
24944
- * @throws If validation or provider lookup fails
24945
- *
24946
- * @example
24947
- * ```typescript
24948
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
24949
- *
24950
- * const kit = new AppKit()
24951
- * const result = await kit.earn.exploreVaults({
24952
- * chain: EarnChain.Arc_Testnet,
24953
- * minApy: '0.03',
24954
- * sortBy: 'apy',
24955
- * })
24956
- * ```
25464
+ * Unique identifier returned by the blockchain once the
25465
+ * transaction is mined.
24957
25466
  */
24958
- exploreVaults(params: ExploreVaultsParams): Promise<EarnExploreVaultsResult>;
25467
+ txHash: string;
24959
25468
  /**
24960
- * Lazily iterate every earn vault available on a chain.
24961
- *
24962
- * @param params - Discovery parameters (no `page`; the iterator manages it)
24963
- * @returns An async generator yielding each matching vault
24964
- * @throws If validation or provider lookup fails
24965
- *
24966
- * @example
24967
- * ```typescript
24968
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
25469
+ * Link to view the transaction details on the appropriate
25470
+ * blockchain explorer.
24969
25471
  *
24970
- * const kit = new AppKit()
24971
- * for await (const vault of kit.earn.exploreVaultsIterator({
24972
- * chain: EarnChain.Arc_Testnet,
24973
- * })) {
24974
- * console.log(vault.name)
24975
- * }
24976
- * ```
25472
+ * @remarks
25473
+ * May be `undefined` when the explorer URL cannot be resolved
25474
+ * for the chain.
24977
25475
  */
24978
- exploreVaultsIterator(params: ExploreVaultsIteratorParams): AsyncGenerator<EarnVaultInfo, void, undefined>;
25476
+ explorerUrl?: string;
24979
25477
  /**
24980
- * Fetch wallet position information for an earn vault.
24981
- *
24982
- * @param params - Position query parameters
24983
- * @returns Promise resolving to position information
24984
- * @throws If validation or provider lookup fails
24985
- *
24986
- * @example
24987
- * ```typescript
24988
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
24989
- *
24990
- * const kit = new AppKit()
24991
- * const position = await kit.earn.getPosition({
24992
- * from: { adapter, chain: EarnChain.Arc_Testnet },
24993
- * vaultAddress: '0x...',
24994
- * })
24995
- * ```
25478
+ * Fee breakdown (provider, gasFee, optional kit, forwarder) for the
25479
+ * executed spend. Same shape as estimateSpend fees. Omitted when
25480
+ * using config.retry.
24996
25481
  */
24997
- getPosition<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetPositionParams<TFromAdapterCapabilities>): Promise<EarnPositionInfo>;
25482
+ fees?: FeeEntry[];
24998
25483
  /**
24999
- * Fetch the current status of a cross-chain Earn deposit.
25000
- *
25001
- * @param params - Status query parameters identifying the deposit by execId
25002
- * @returns Promise resolving to the structured cross-chain deposit status
25003
- * @throws If validation, provider lookup, or the status request fails
25484
+ * Gateway transfer identifier. Present when `useForwarder` is enabled
25485
+ * and can be used to query transfer status via `GET /v1/transfer/{id}`.
25004
25486
  */
25005
- getCrossChainDepositStatus(params: GetCrossChainDepositStatusParams): Promise<EarnCrossChainDepositStatus>;
25487
+ transferId?: string;
25006
25488
  /**
25007
- * Poll a cross-chain Earn deposit until it reaches a terminal bridge state.
25008
- *
25009
- * @param params - Wait parameters including execId and optional polling knobs
25010
- * @returns Promise resolving to the wait result and last observed bridge status
25011
- * @throws If validation, provider lookup, or a status request fails
25012
- */
25013
- waitForCrossChainDeposit(params: WaitForCrossChainDepositParams): Promise<EarnCrossChainDepositWaitResult>;
25014
- /**
25015
- * Fetch a deposit quote.
25016
- *
25017
- * @param params - Deposit quote parameters
25018
- * @returns Promise resolving to deposit quote information
25019
- * @throws If validation or provider lookup fails
25020
- *
25021
- * @example
25022
- * ```typescript
25023
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
25024
- *
25025
- * const kit = new AppKit()
25026
- * const quote = await kit.earn.getDepositQuote({
25027
- * from: { adapter, chain: EarnChain.Arc_Testnet },
25028
- * vaultAddress: '0x...',
25029
- * amount: '100.50',
25030
- * })
25031
- * ```
25032
- */
25033
- getDepositQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetDepositQuoteParams<TFromAdapterCapabilities>): Promise<EarnDepositQuoteInfo>;
25034
- /**
25035
- * Fetch a withdrawal quote.
25036
- *
25037
- * @param params - Withdrawal quote parameters
25038
- * @returns Promise resolving to withdrawal quote information
25039
- * @throws If validation or provider lookup fails
25040
- *
25041
- * @example
25042
- * ```typescript
25043
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
25044
- *
25045
- * const kit = new AppKit()
25046
- * const quote = await kit.earn.getWithdrawalQuote({
25047
- * from: { adapter, chain: EarnChain.Arc_Testnet },
25048
- * vaultAddress: '0x...',
25049
- * amount: '50.00',
25050
- * })
25051
- * ```
25489
+ * Block height after which the transfer attestation expires.
25490
+ * Returned by the Gateway transfer API.
25052
25491
  */
25053
- getWithdrawalQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetWithdrawalQuoteParams<TFromAdapterCapabilities>): Promise<EarnWithdrawalQuoteInfo>;
25492
+ expirationBlock?: string;
25054
25493
  /**
25055
- * Fetch a claim rewards quote.
25056
- *
25057
- * @param params - Claim rewards quote parameters
25058
- * @returns Promise resolving to claim rewards quote information
25059
- * @throws If validation or provider lookup fails
25060
- *
25061
- * @example
25062
- * ```typescript
25063
- * import { AppKit, EarnChain } from '@circle-fin/app-kit'
25064
- *
25065
- * const kit = new AppKit()
25066
- * const quote = await kit.earn.getClaimRewardsQuote({
25067
- * from: { adapter, chain: EarnChain.Arc_Testnet },
25068
- * vaultAddress: '0x...',
25069
- * })
25070
- * ```
25494
+ * Ordered list of steps executed during the spend operation.
25071
25495
  *
25072
- * @internal
25496
+ * @remarks
25497
+ * Each entry records the outcome of one phase of the spend flow.
25498
+ * For a normal spend the order is:
25499
+ * `buildBurnIntents` → `signBurnIntents` → `transfer` → `mint`.
25500
+ * For a retry spend only `mint` is present.
25073
25501
  */
25074
- getClaimRewardsQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetClaimRewardsQuoteParams<TFromAdapterCapabilities>): Promise<EarnClaimRewardsQuoteInfo>;
25502
+ steps?: SpendStep[];
25503
+ }
25504
+ interface CustomFeeConfig {
25505
+ recipientAddress: string;
25506
+ value: string;
25507
+ }
25508
+ /**
25509
+ * Data needed to retry a mint that failed after the transfer was
25510
+ * already committed (funds locked).
25511
+ *
25512
+ * Obtain these values from the KitError (TRANSACTION_REVERTED) thrown when
25513
+ * the on-chain mint step fails. The attestation and signature are available
25514
+ * in `error.cause.trace`.
25515
+ */
25516
+ interface RetryMintConfig {
25517
+ /** The attestation hex string returned by the Gateway `/v1/transfer` API. */
25518
+ attestation: string;
25519
+ /** The attestation signature hex string returned by `/v1/transfer`. */
25520
+ signature: string;
25521
+ }
25522
+ interface SpendConfig {
25523
+ customFee?: CustomFeeConfig;
25075
25524
  /**
25076
- * Resume a multi-phase earn operation that previously failed.
25525
+ * When provided, skips the estimate/sign/transfer steps and proceeds
25526
+ * directly to the on-chain mint using a previously obtained attestation.
25077
25527
  *
25078
- * Pass the {@link KitError} caught from `deposit`, `withdraw`, or
25079
- * `claimRewards`. The error carries the original inputs and step
25080
- * progress, so completed phases (for example a successful token
25081
- * approval) can be skipped. Call `isRetryableError(error)` first.
25528
+ * Use this to retry a mint that failed due to an RPC or network issue
25529
+ * after the transfer was already committed.
25082
25530
  *
25083
25531
  * @remarks
25084
- * Retry re-fetches execution params and may re-submit the execute
25085
- * transaction. Treat this as best-effort recovery: if a prior attempt
25086
- * broadcast execute but failed before observing the receipt, that
25087
- * transaction may still be in flight.
25088
- *
25089
- * @param error - The error caught from a previous multi-phase earn operation
25090
- * @returns Promise resolving to the result of the resumed operation
25091
- * @throws If the error is not retryable or lacks earn retry context
25092
- *
25093
- * @example
25094
- * ```typescript
25095
- * import { AppKit, isRetryableError } from '@circle-fin/app-kit'
25096
- *
25097
- * const kit = new AppKit()
25098
- *
25099
- * try {
25100
- * await kit.earn.deposit(params)
25101
- * } catch (error) {
25102
- * if (isRetryableError(error)) {
25103
- * const result = await kit.earn.retry(error)
25104
- * }
25105
- * }
25106
- * ```
25532
+ * The `useForwarder` flag on the destination is ignored during retry
25533
+ * because the attestation was already issued the Forwarding Service
25534
+ * is only involved in the initial transfer, not re-mints.
25107
25535
  */
25108
- retry(error: unknown): Promise<EarnDepositOutcome | EarnWithdrawResult | EarnClaimRewardsResult>;
25536
+ retry?: RetryMintConfig;
25537
+ }
25538
+ interface ResolvedAllocation {
25539
+ amount: string;
25540
+ chain: ChainDefinition;
25541
+ }
25542
+ interface ResolvedSpendSource<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
25543
+ adapter: Adapter<TAdapterCapabilities>;
25544
+ allocations: ResolvedAllocation[];
25545
+ address?: string;
25546
+ sourceAccount?: string;
25547
+ }
25548
+ interface ResolvedSpendDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
25549
+ adapter?: Adapter<TAdapterCapabilities>;
25550
+ chain: ChainDefinition;
25551
+ recipientAddress?: string;
25552
+ address?: string;
25553
+ useForwarder?: boolean;
25554
+ }
25555
+ interface ResolvedSpendParams<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
25556
+ from: ResolvedSpendSource<TFromAdapterCapabilities>[];
25557
+ to: ResolvedSpendDestination<TToAdapterCapabilities>;
25558
+ token: SupportedToken;
25559
+ config?: SpendConfig;
25109
25560
  }
25110
25561
  /**
25111
- * Type for event handler functions that can be registered with the AppKit.
25562
+ * Function that computes the fee amount (in human-readable units, e.g. "10.5")
25563
+ * given the resolved spend parameters.
25564
+ */
25565
+ type SpendFeeFunction = (params: ResolvedSpendParams) => Promise<string> | string;
25566
+ /**
25567
+ * Function that resolves the fee recipient address for a spend.
25568
+ * Called once per spend, against the resolved **destination** chain —
25569
+ * every fee burn intent in a spend mints to that single chain
25570
+ * regardless of which source chain(s) funded it, so only one
25571
+ * recipient address (valid on the destination chain) is ever needed.
25572
+ */
25573
+ type SpendFeeRecipientFunction = (destinationChain: ChainDefinition, params: ResolvedSpendParams) => Promise<string> | string;
25574
+ /**
25575
+ * Policy for computing and routing custom developer fees.
25112
25576
  *
25113
- * This type extracts the handler function type from the `on` method parameters,
25114
- * ensuring that event handlers have the correct signature and payload types.
25115
- * It enables type-safe event handling by preserving the specific payload types
25116
- * for each action.
25577
+ * **Important:** When the kit invokes `computeFee` and
25578
+ * `resolveFeeRecipientAddress`, the `params` argument may be the
25579
+ * **raw, unresolved** `SpendParams` (cast to `ResolvedSpendParams`).
25580
+ * Fields that only exist after resolution (e.g. per-source allocations)
25581
+ * may be `undefined`. Implementations should only rely on top-level
25582
+ * fields such as `to`, `token`, and `amount`.
25117
25583
  *
25118
- * Uses a structural type constraint to avoid circular dependencies while still
25119
- * providing full type safety when used with an AppKit instance.
25584
+ * @remarks
25585
+ * `resolveFeeRecipientAddress` is optional when you configure
25586
+ * {@link UnifiedBalanceKit.setFeeRecipients} instead — the declarative
25587
+ * map takes priority over this callback when both are present. Provide
25588
+ * exactly one of the two; a policy with neither throws at spend time.
25589
+ */
25590
+ interface CustomFeePolicy {
25591
+ computeFee: SpendFeeFunction;
25592
+ resolveFeeRecipientAddress?: SpendFeeRecipientFunction;
25593
+ }
25594
+ /**
25595
+ * Chain type group used to key {@link FeeRecipientsConfig}.
25120
25596
  *
25121
- * @typeParam T - A type that has an `on` method matching AppKit's signature
25122
- * @returns The function type for event handlers with proper payload typing
25597
+ * @remarks
25598
+ * Only `'evm'` and `'solana'` are live today (the only chain types the
25599
+ * kit's provider currently supports). This is deliberately a narrow
25600
+ * subset of `@core/chains`' broader `ChainType` union rather than a
25601
+ * hardcoded two-field struct, so that support for additional non-EVM
25602
+ * chain types (e.g. Stellar, Starknet) can be added later by adding
25603
+ * new union members here — no restructuring of `FeeRecipientsConfig`
25604
+ * or its consumers required.
25605
+ */
25606
+ type FeeRecipientChainType = 'evm' | 'solana';
25607
+ /**
25608
+ * Declarative map of fee recipient addresses, keyed by chain type.
25609
+ *
25610
+ * @remarks
25611
+ * Set via {@link UnifiedBalanceKit.setFeeRecipients}. At spend time the
25612
+ * kit resolves the spend's destination chain to its
25613
+ * {@link FeeRecipientChainType} and looks up the matching entry —
25614
+ * exactly one recipient is used per spend (see
25615
+ * {@link SpendFeeRecipientFunction}). Provide entries for every chain
25616
+ * type you expect to spend to; a spend to a destination chain type
25617
+ * with no matching entry throws before any fee collection is
25618
+ * attempted.
25123
25619
  *
25124
25620
  * @example
25125
25621
  * ```typescript
25126
- * import { AppKit, ActionHandler } from '@circle-fin/app-kit'
25127
- *
25128
- * const kit = new AppKit()
25622
+ * import type { FeeRecipientsConfig } from '@circle-fin/unified-balance-kit'
25129
25623
  *
25130
- * // ActionHandler will be the correct function type for handlers
25131
- * const handler: ActionHandler<typeof kit> = (payload) => {
25132
- * // payload is properly typed based on the action
25624
+ * const feeRecipients: FeeRecipientsConfig = {
25625
+ * evm: '0x1234567890123456789012345678901234567890',
25626
+ * solana: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
25133
25627
  * }
25134
25628
  * ```
25135
25629
  */
25136
- type ActionHandler<T extends {
25137
- on: (action: string, handler: (payload: unknown) => void) => void;
25138
- }> = Parameters<T['on']>[1];
25630
+ type FeeRecipientsConfig = Partial<Record<FeeRecipientChainType, string>>;
25139
25631
  /**
25140
- * Parameters for sending USDC, USDT, native tokens, or custom ERC-20/SPL tokens.
25141
- *
25142
- * This interface is the canonical input for send operations in App Kit. It supports
25143
- * sending to either a destination {@link Adapter} (recipient derives from the adapter's
25144
- * default account) or an explicit recipient `string` address.
25145
- *
25146
- * - The `from` field provides the source signing context and chain.
25147
- * - The `to` field identifies the destination as an adapter or an explicit address.
25148
- * - The `amount` field is a human-readable decimal string (for example, `'10.5'`).
25149
- * - The `token` field selects the asset to move and defaults to `'USDC'`.
25150
- *
25151
- * @remarks
25152
- * When `to` is a `string`, the address must be a valid address. When `to` is an
25153
- * {@link Adapter}, the recipient is derived from the adapter's active account.
25632
+ * Fee category describing the origin of a fee line item.
25154
25633
  *
25155
- * The `token` field accepts both supported token aliases ('USDC', 'USDT', 'NATIVE', 'EURC') and custom token
25156
- * contract addresses.
25634
+ * - `'provider'` Fee charged by the cross-chain provider (e.g. protocol fee).
25635
+ * - `'gasFee'` — On-chain gas cost denominated in the transfer token (e.g. USDC).
25636
+ * - `'kit'` — Fee charged by the kit / developer integration.
25637
+ * - `'forwarder'` — Fee charged by Circle's Forwarding Service for automatic mint.
25638
+ */
25639
+ type FeeType = 'provider' | 'gasFee' | 'kit' | 'forwarder';
25640
+ /**
25641
+ * Per-chain breakdown of a fee amount.
25157
25642
  *
25158
25643
  * @example
25159
25644
  * ```typescript
25160
- * // Send USDC to a recipient adapter (address derived on-chain)
25161
- * const params: SendParams = {
25162
- * from: { adapter: sourceAdapter, chain: 'Ethereum' },
25163
- * to: recipientAdapter,
25164
- * amount: '10.5',
25165
- * token: 'USDC'
25166
- * }
25645
+ * import type { FeeAllocation } from '@circle-fin/unified-balance-kit'
25167
25646
  *
25168
- * // Send using a custom token address (DAI on Ethereum)
25169
- * const paramsCustomToken: SendParams = {
25170
- * from: { adapter: sourceAdapter, chain: 'Ethereum' },
25171
- * to: '0x1234...abcd',
25172
- * amount: '100.0',
25173
- * token: '0x6B175474E89094C44Da98b954EedeAC495271d0F'
25647
+ * const allocation: FeeAllocation = {
25648
+ * chain: 'Ethereum',
25649
+ * amount: '0.00005',
25174
25650
  * }
25175
25651
  * ```
25176
25652
  */
25177
- interface SendParams {
25178
- /**
25179
- * The source adapter context (wallet and chain) for the transfer.
25180
- */
25181
- from: AdapterContext;
25182
- /**
25183
- * The destination for the transfer, supporting explicit or derived recipient addresses.
25184
- */
25185
- to: Adapter | string;
25186
- /**
25187
- * The amount to transfer.
25188
- */
25653
+ interface FeeAllocation {
25654
+ /** The chain to which this portion of the fee applies. */
25655
+ chain: Blockchain;
25656
+ /** The fee amount on this chain (human-readable decimal string). */
25189
25657
  amount: string;
25190
- /**
25191
- * The token to transfer. Defaults to 'USDC'.
25192
- * If omitted, the provider will use 'USDC' by default.
25193
- *
25194
- * Supports both known aliases and custom token contract addresses:
25195
- * - Known aliases: 'USDC', 'USDT', 'NATIVE', 'EURC' ('EURC' requires the
25196
- * chain to have an `eurcAddress` configured)
25197
- * - Custom token addresses: EVM addresses or Solana SPL token mint addresses
25198
- *
25199
- * @example
25200
- * ```typescript
25201
- * // Using an alias
25202
- * token: 'USDC'
25203
- *
25204
- * // Using a custom ERC-20 address (DAI on Ethereum)
25205
- * token: '0x6B175474E89094C44Da98b954EedeAC495271d0F'
25206
- *
25207
- * // Using a custom SPL token mint (Solana)
25208
- * token: 'So11111111111111111111111111111111111111112'
25209
- * ```
25210
- */
25211
- token?: TokenAlias | TokenAddress;
25212
25658
  }
25213
25659
  /**
25214
- * Extract action types from BridgeKit's actionDispatcher.
25215
- *
25216
- * This utility type extracts the action map type from a BridgeKit instance
25217
- * by inspecting its actionDispatcher property.
25218
- *
25219
- * @typeParam T - The BridgeKit instance type
25220
- */
25221
- type ExtractBridgeKitActions<T extends BridgeKit> = T extends BridgeKit ? T['actionDispatcher'] extends Actionable<infer Actions> ? Actions : never : never;
25222
- /**
25223
- * Prefix action names with a namespace.
25224
- *
25225
- * Transforms an action map by prefixing all keys with the specified namespace.
25226
- * For example, `{ approve: Payload }` becomes `{ 'bridge.approve': Payload }`.
25660
+ * A single fee line item within an estimate.
25227
25661
  *
25228
- * @typeParam Actions - The original action map
25229
- * @typeParam Prefix - The prefix to apply (e.g., 'bridge')
25230
- */
25231
- type PrefixActions<Prefix extends string, Actions> = {
25232
- [K in keyof Actions as K extends string ? `${Prefix}.${K}` : never]: Actions[K];
25233
- };
25234
- /**
25235
- * Default BridgeKit instance type (no extra providers).
25236
- */
25237
- type DefaultBridgeKit = BridgeKit;
25238
- /**
25239
- * Extract actions from default BridgeKit.
25240
- */
25241
- type DefaultBridgeKitActions = ExtractBridgeKitActions<DefaultBridgeKit>;
25242
- /**
25243
- * Prefixed bridge actions for AppKit.
25662
+ * @remarks
25663
+ * Each entry describes a fee category (`type`), the token it is
25664
+ * denominated in, the aggregate `amount`, and an optional per-chain
25665
+ * `allocations` breakdown.
25244
25666
  *
25245
- * All BridgeKit events are prefixed with 'bridge.' to namespace them
25246
- * within the AppKit event system.
25247
- */
25248
- type AppKitBridgeActions = PrefixActions<'bridge', DefaultBridgeKitActions>;
25249
- /**
25250
- * Prefixed unified balance actions for AppKit.
25667
+ * @example
25668
+ * ```typescript
25669
+ * import type { FeeEntry } from '@circle-fin/unified-balance-kit'
25251
25670
  *
25252
- * All UnifiedBalanceKit (Gateway) events are prefixed with 'unifiedBalance.'
25253
- * to namespace them within the AppKit event system.
25254
- */
25255
- type AppKitUnifiedBalanceActions = PrefixActions<'unifiedBalance', GatewayV1Actions>;
25256
- /**
25257
- * Prefixed earn actions for AppKit.
25671
+ * // Fee with per-chain allocation breakdown
25672
+ * const providerFee: FeeEntry = {
25673
+ * type: 'provider',
25674
+ * token: 'USDC',
25675
+ * amount: '0.00011',
25676
+ * allocations: [
25677
+ * { chain: 'Ethereum', amount: '0.00005' },
25678
+ * { chain: 'Polygon', amount: '0.00006' },
25679
+ * ],
25680
+ * }
25258
25681
  *
25259
- * Earn step events are exposed under the `earn.` namespace (for example
25260
- * `earn.deposit`, `earn.approve`, `earn.withdraw`) so they can be
25261
- * subscribed to via `kit.on()` alongside bridge and unified balance
25262
- * events.
25263
- */
25264
- type AppKitEarnActions = PrefixActions<'earn', EarnActions>;
25265
- /**
25266
- * Union of all AppKit action names.
25267
- */
25268
- type AppKitActionName = keyof AppKitBridgeActions | keyof AppKitUnifiedBalanceActions | keyof AppKitEarnActions;
25269
- /**
25270
- * All actions available in AppKit.
25682
+ * // Flat fee without allocations (e.g. forwarder)
25683
+ * const forwarderFee: FeeEntry = {
25684
+ * type: 'forwarder',
25685
+ * token: 'USDC',
25686
+ * amount: '0.005',
25687
+ * }
25688
+ * ```
25271
25689
  */
25272
- type AppKitActions = AppKitBridgeActions & AppKitUnifiedBalanceActions & AppKitEarnActions;
25273
-
25690
+ interface FeeEntry {
25691
+ /** The category of this fee. */
25692
+ type: FeeType;
25693
+ /** The token in which this fee is denominated (e.g. `'USDC'`, `'ETH'`). */
25694
+ token: string;
25695
+ /** Aggregate fee amount (human-readable decimal string). */
25696
+ amount: string;
25697
+ /** Per-chain breakdown of the fee. Omitted for flat fees (e.g. forwarder). */
25698
+ allocations?: FeeAllocation[];
25699
+ /**
25700
+ * When `type === 'kit'`, the address that receives the kit fee.
25701
+ * Omitted for other fee types.
25702
+ */
25703
+ recipientAddress?: string;
25704
+ }
25274
25705
  /**
25275
- * Parameters for creating a AppKit context.
25706
+ * Cost estimation for a spend (mint) operation.
25276
25707
  *
25277
- * This type allows partial customization of the context while ensuring
25278
- * that all required properties have sensible defaults. Users can override
25279
- * specific methods while keeping the rest intact. Action handler buckets
25280
- * may also be supplied partially; missing buckets default to empty maps.
25708
+ * @remarks
25709
+ * Returned by the provider's `estimateSpend` method to give callers
25710
+ * visibility into the expected fees *before* executing a spend.
25711
+ * Each entry in `fees` represents a distinct fee category with its
25712
+ * per-chain allocation breakdown.
25281
25713
  *
25282
25714
  * @example
25283
25715
  * ```typescript
25284
- * const customContext = createContext({
25285
- * getFee: async (type, params) => {
25286
- * // Custom fee calculation logic
25287
- * return { totalFee: '0.05', networkFee: '0.05' }
25288
- * }
25289
- * })
25716
+ * import type { EstimateSpendResult } from '@circle-fin/unified-balance-kit'
25717
+ *
25718
+ * const estimate: EstimateSpendResult = {
25719
+ * fees: [
25720
+ * {
25721
+ * type: 'provider',
25722
+ * token: 'USDC',
25723
+ * amount: '0.00011',
25724
+ * allocations: [
25725
+ * { chain: 'Ethereum', amount: '0.00005' },
25726
+ * { chain: 'Polygon', amount: '0.00006' },
25727
+ * ],
25728
+ * },
25729
+ * {
25730
+ * type: 'gasFee',
25731
+ * token: 'USDC',
25732
+ * amount: '0.0025',
25733
+ * allocations: [
25734
+ * { chain: 'Ethereum', amount: '0.0015' },
25735
+ * { chain: 'Polygon', amount: '0.0010' },
25736
+ * ],
25737
+ * },
25738
+ * {
25739
+ * type: 'kit',
25740
+ * token: 'USDC',
25741
+ * amount: '0.05',
25742
+ * allocations: [
25743
+ * { chain: 'Ethereum', amount: '0.05' },
25744
+ * ],
25745
+ * },
25746
+ * ],
25747
+ * }
25290
25748
  * ```
25291
25749
  */
25292
- type CreateContextParams = Omit<Partial<AppKitContext>, 'actions'> & {
25293
- actions?: Partial<AppKitContext['actions']>;
25294
- };
25750
+ interface EstimateSpendResult {
25751
+ /** Itemised fee breakdown for the spend operation. */
25752
+ fees: FeeEntry[];
25753
+ }
25295
25754
 
25296
25755
  /**
25297
- * Destination for a Gateway spend (mint) operation.
25298
- *
25299
- * @remarks
25300
- * Omitting `recipientAddress` causes funds to be minted to the
25301
- * address resolved from the adapter. Providing it overrides the
25302
- * default destination.
25303
- *
25304
- * @typeParam TAdapterCapabilities - Adapter capability constraints.
25305
- * @typeParam TChainIdentifier - Accepted chain identifier type.
25756
+ * Runtime array of token identifiers supported by the unified-balance-kit.
25306
25757
  *
25307
25758
  * @example
25308
25759
  * ```typescript
25309
- * import type { SpendDestination } from '@circle-fin/unified-balance-kit'
25760
+ * import { SUPPORTED_TOKENS } from '@circle-fin/unified-balance-kit'
25310
25761
  *
25311
- * const destination: SpendDestination = {
25312
- * adapter: avalancheAdapter,
25313
- * chain: 'Avalanche',
25314
- * recipientAddress: '0xDEST…abcd',
25762
+ * if (SUPPORTED_TOKENS.includes('USDC')) {
25763
+ * console.log('USDC is supported')
25315
25764
  * }
25316
25765
  * ```
25317
25766
  */
25318
- type SpendDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> = {
25319
- /** The adapter for executing on-chain calls. */
25320
- adapter: Adapter<TAdapterCapabilities>;
25321
- /** The destination chain. */
25322
- chain: TChainIdentifier;
25323
- /**
25324
- * Optional custom recipient address. When omitted the adapter's
25325
- * resolved address is used.
25326
- */
25327
- recipientAddress?: string;
25328
- /**
25329
- * Enable Circle's Forwarding Service for automatic mint submission.
25330
- * When `true`, the Gateway API handles the destination mint via its
25331
- * relayer and the SDK polls for completion instead of executing a
25332
- * user-signed mint transaction.
25333
- */
25334
- useForwarder?: boolean;
25335
- } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
25767
+ declare const SUPPORTED_TOKENS: readonly ["USDC"];
25336
25768
  /**
25337
- * Forwarder-only destination for spend operations.
25338
- *
25339
- * Used when Circle's Forwarding Service handles the mint transaction
25340
- * and no destination adapter is available. Set `useForwarder` to `true`
25341
- * and provide a `recipientAddress`.
25342
- *
25343
- * @typeParam TChainIdentifier - Accepted chain identifier type.
25769
+ * Token identifiers supported by the unified-balance-kit.
25344
25770
  *
25345
25771
  * @example
25346
25772
  * ```typescript
25347
- * import type { ForwarderSpendDestination } from '@circle-fin/unified-balance-kit'
25773
+ * import type { SupportedToken } from '@circle-fin/unified-balance-kit'
25348
25774
  *
25349
- * const destination: ForwarderSpendDestination = {
25350
- * chain: 'Base',
25351
- * recipientAddress: '0xDEST…abcd',
25352
- * useForwarder: true,
25353
- * }
25775
+ * const token: SupportedToken = 'USDC'
25354
25776
  * ```
25355
25777
  */
25356
- interface ForwarderSpendDestination<TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
25357
- /** The destination chain where USDC will be minted. */
25358
- chain: TChainIdentifier;
25359
- /** The recipient address that will receive the minted USDC. */
25360
- recipientAddress: string;
25361
- /** Enable Circle's Forwarding Service for the destination mint. */
25362
- useForwarder: boolean;
25363
- }
25778
+ type SupportedToken = (typeof SUPPORTED_TOKENS)[number];
25364
25779
  /**
25365
- * Union of spend destination variants.
25780
+ * Case-insensitive variant of {@link SupportedToken} for user-facing input.
25366
25781
  *
25367
- * @see {@link SpendDestination}
25368
- * @see {@link ForwarderSpendDestination}
25782
+ * Accepts the canonical uppercase form, fully lowercase, and title-case
25783
+ * (e.g. `'USDC'`, `'usdc'`, `'Usdc'`). Arbitrary mixed-case input like
25784
+ * `'uSdC'` is handled at runtime by the Zod schema and
25785
+ * {@link normalizeToken}, so exhaustive compile-time permutations are
25786
+ * unnecessary. Avoiding a recursive `CasePermutations` type prevents
25787
+ * 2^N type-literal explosion as the token list grows.
25788
+ *
25789
+ * @example
25790
+ * ```typescript
25791
+ * import type { SupportedTokenInput } from '@circle-fin/unified-balance-kit'
25792
+ *
25793
+ * const token: SupportedTokenInput = 'usdc' // OK
25794
+ * ```
25369
25795
  */
25370
- type SpendDestinationUnion<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> = SpendDestination<TAdapterCapabilities, TChainIdentifier> | ForwarderSpendDestination<TChainIdentifier>;
25796
+ type SupportedTokenInput = SupportedToken | Lowercase<SupportedToken> | Capitalize<Lowercase<SupportedToken>>;
25371
25797
  /**
25372
- * An amount of USDC to pull from a specific chain.
25798
+ * Intentional `any` escape hatch so heterogeneous providers can be stored
25799
+ * in a single array while `MergeActions` rebuilds concrete action types.
25800
+ *
25801
+ * Type safety is re-established by the `on()`/`off()` overloads in
25802
+ * {@link UnifiedBalanceKit} — do not remove those overloads.
25803
+ *
25804
+ * Caveat: custom providers whose `TProviderActions` differs from the
25805
+ * default map will have action types erased to `any` unless the consumer
25806
+ * passes the provider tuple as a generic, e.g. `UnifiedBalanceKit<[MyProvider]>`.
25807
+ */
25808
+ type FlexibleGatewayProvider = IGatewayProvider<any>;
25809
+ /**
25810
+ * Configuration options for initializing a {@link UnifiedBalanceKit} instance.
25811
+ *
25812
+ * When no providers are specified, the kit uses the default Gateway v1
25813
+ * provider. Any additional providers supplied via config are appended
25814
+ * to the defaults.
25815
+ *
25816
+ * @typeParam TExtraProviders - Array type of additional providers
25373
25817
  *
25374
25818
  * @example
25375
25819
  * ```typescript
25376
- * import type { Allocation } from '@circle-fin/unified-balance-kit'
25820
+ * import { UnifiedBalanceKit } from '@circle-fin/unified-balance-kit'
25377
25821
  *
25378
- * const allocation: Allocation = {
25379
- * amount: '50',
25380
- * chain: 'Ethereum',
25381
- * }
25822
+ * // Create kit with default providers
25823
+ * const kit = new UnifiedBalanceKit()
25824
+ * ```
25825
+ *
25826
+ * @example
25827
+ * ```typescript
25828
+ * import { UnifiedBalanceKit } from '@circle-fin/unified-balance-kit'
25829
+ *
25830
+ * // Create kit with additional providers
25831
+ * const kit = new UnifiedBalanceKit({
25832
+ * providers: [myCustomProvider],
25833
+ * })
25382
25834
  * ```
25383
25835
  */
25384
- interface Allocation {
25836
+ interface UnifiedBalanceKitConfig<TExtraProviders extends FlexibleGatewayProvider[] = []> {
25385
25837
  /**
25386
- * The amount to pull from this chain (human-readable decimal
25387
- * string).
25838
+ * Optional array of additional Gateway providers.
25839
+ *
25840
+ * If not provided, default providers will be initialized.
25388
25841
  */
25389
- amount: string;
25842
+ providers?: TExtraProviders;
25390
25843
  /**
25391
- * The chain from which to pull the funds.
25844
+ * Disable analytics telemetry (success events with `txHash`).
25845
+ *
25846
+ * When `true`, the SDK will not POST to the telemetry endpoint
25847
+ * after successful verb operations. Defaults to `false` (enabled).
25392
25848
  *
25393
25849
  * @remarks
25394
- * All allocations in a single spend must be either all mainnet
25395
- * or all testnet. Mixing is not allowed.
25850
+ * Only applies to the class-based API (`new UnifiedBalanceKit()`).
25851
+ * The functional API via `createUnifiedBalanceKitContext()` does not
25852
+ * register telemetry handlers.
25853
+ *
25854
+ * @defaultValue false
25396
25855
  */
25397
- chain: UnifiedBalanceChainIdentifier;
25856
+ disableAnalytics?: boolean;
25857
+ /**
25858
+ * Disable error telemetry.
25859
+ *
25860
+ * When `true`, the SDK will not POST error details to the telemetry
25861
+ * endpoint when public methods throw. Defaults to `false` (enabled).
25862
+ *
25863
+ * @remarks
25864
+ * Only applies to the class-based API (`new UnifiedBalanceKit()`).
25865
+ *
25866
+ * @defaultValue false
25867
+ */
25868
+ disableErrorReporting?: boolean;
25869
+ /**
25870
+ * Skip the built-in default providers when assembling the context.
25871
+ *
25872
+ * By default the kit prepends the standard Gateway v1 provider so
25873
+ * `providers` is treated as additive. Pass `true` to use only the
25874
+ * providers supplied in {@link UnifiedBalanceKitConfig.providers}.
25875
+ *
25876
+ * Useful when stubbing the gateway in integration tests, when running
25877
+ * against a self-hosted gateway replacement, or any time you want full
25878
+ * control over which provider serves a given chain.
25879
+ *
25880
+ * @defaultValue false
25881
+ */
25882
+ excludeDefaultProviders?: boolean;
25398
25883
  }
25884
+
25399
25885
  /**
25400
- * Extends {@link Allocation} with the resolved source Gateway
25401
- * account address.
25886
+ * Token allowance strategy used to authorize a Gateway deposit.
25887
+ *
25888
+ * - `'approve'` — traditional ERC-20 `approve` transaction.
25889
+ * - `'permit'` — gasless EIP-2612 off-chain signature.
25890
+ * - `'authorize'` — EIP-3009 `transferWithAuthorization`.
25402
25891
  *
25403
25892
  * @example
25404
25893
  * ```typescript
25405
- * import type { AllocationResult } from '@circle-fin/unified-balance-kit'
25894
+ * import type { AllowanceStrategy } from '@circle-fin/unified-balance-kit'
25406
25895
  *
25407
- * const result: AllocationResult = {
25408
- * amount: '50',
25409
- * chain: 'Ethereum',
25410
- * sourceAccount: '0x1234…5678',
25411
- * }
25896
+ * const strategy: AllowanceStrategy = 'permit'
25412
25897
  * ```
25413
25898
  */
25414
- interface AllocationResult extends Allocation {
25415
- /** The Gateway account address from which this amount was pulled. */
25416
- sourceAccount: string;
25417
- }
25899
+ type AllowanceStrategy = 'approve' | 'permit' | 'authorize';
25418
25900
  /**
25419
- * A spend source providing an adapter and optional per-chain allocations.
25901
+ * Parameters for depositing tokens into the caller's own Gateway
25902
+ * account on a specific chain.
25420
25903
  *
25421
25904
  * @remarks
25422
- * When `allocations` is omitted the provider's automatic allocation
25423
- * logic decides which chains to draw from. A top-level `amount`
25424
- * field on {@link SpendParams} is **required** in that case.
25425
- *
25426
- * When `allocations` is present, every source in the `from` array
25427
- * must also include `allocations` (all-or-nothing rule).
25905
+ * Although a Gateway account can span multiple chains (e.g. all EVM
25906
+ * chains share the same account), every deposit targets exactly one
25907
+ * chain. The depositor is identified by the adapter context.
25428
25908
  *
25429
25909
  * @typeParam TAdapterCapabilities - Adapter capability constraints.
25910
+ * @typeParam TChainIdentifier - Accepted chain identifier type.
25430
25911
  *
25431
25912
  * @example
25432
25913
  * ```typescript
25433
- * import type { SpendSource } from '@circle-fin/unified-balance-kit'
25434
- *
25435
- * // With explicit allocations
25436
- * const withAlloc: SpendSource = {
25437
- * adapter: evmAdapter,
25438
- * allocations: [
25439
- * { amount: '40', chain: 'Ethereum' },
25440
- * { amount: '60', chain: 'Base' },
25441
- * ],
25442
- * }
25914
+ * import type { DepositParams } from '@circle-fin/unified-balance-kit'
25443
25915
  *
25444
- * // Adapter-only (auto-allocation)
25445
- * const adapterOnly: SpendSource = {
25446
- * adapter: evmAdapter,
25916
+ * const params: DepositParams = {
25917
+ * from: { adapter: evmAdapter, chain: 'Ethereum' },
25918
+ * amount: '100',
25919
+ * token: 'USDC',
25920
+ * allowanceStrategy: 'permit',
25447
25921
  * }
25448
25922
  * ```
25449
25923
  */
25450
- type SpendSource<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = {
25451
- /** The adapter for executing on-chain calls. */
25452
- adapter: Adapter<TAdapterCapabilities>;
25924
+ interface DepositParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
25453
25925
  /**
25454
- * Optional per-chain allocations describing how much to pull from
25455
- * each chain. When omitted the provider computes allocations
25456
- * automatically.
25926
+ * The adapter context identifying the depositor and chain.
25457
25927
  */
25458
- allocations?: Allocation | Allocation[];
25928
+ from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
25459
25929
  /**
25460
- * Optional Gateway account to pull from (delegate scenarios).
25930
+ * The amount of tokens to deposit (human-readable decimal string).
25461
25931
  *
25462
- * @remarks
25463
- * When omitted the adapter's resolved address is used. When
25464
- * provided you must be a delegate for this account.
25932
+ * @example "100", "0.5"
25465
25933
  */
25466
- sourceAccount?: string;
25467
- } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
25468
- /**
25469
- * Base fields shared by all spend parameter variants.
25470
- */
25471
- interface SpendParamsBase<TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
25472
- /** Where to mint the USDC on the destination chain. */
25473
- to: SpendDestinationUnion<TToAdapterCapabilities, TChainIdentifier>;
25934
+ amount: string;
25474
25935
  /**
25475
- * The token to spend. Currently only USDC is supported.
25936
+ * The token to deposit.
25476
25937
  * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
25477
- */
25478
- token?: SupportedTokenInput;
25479
- /**
25480
- * Total USDC amount to spend (human-readable decimal string).
25481
25938
  *
25482
- * @remarks
25483
- * Always required. When sources include explicit `allocations`,
25484
- * `sum(allocations)` must equal `amount`.
25939
+ * @defaultValue 'USDC'
25485
25940
  */
25486
- amount: string;
25487
- /** Optional configuration for the spend operation. */
25488
- config?: SpendConfig;
25489
- }
25490
- /**
25491
- * Standard spend: `from` is required (no retry).
25492
- */
25493
- interface SpendParamsWithFrom<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> extends SpendParamsBase<TToAdapterCapabilities, TChainIdentifier> {
25941
+ token?: SupportedTokenInput;
25494
25942
  /**
25495
- * One or more sources to pull funds from.
25943
+ * The token allowance strategy to authorize the deposit.
25496
25944
  *
25497
- * Use an array when spending from multiple adapters (e.g.
25498
- * combining EVM and non-EVM accounts).
25945
+ * @defaultValue 'authorize'
25499
25946
  */
25500
- from: SpendSource<TFromAdapterCapabilities> | SpendSource<TFromAdapterCapabilities>[];
25501
- }
25502
- /**
25503
- * Retry spend: `from` is optional because we skip the
25504
- * estimate/sign/transfer steps and go straight to mint.
25505
- */
25506
- interface SpendParamsRetry<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> extends SpendParamsBase<TToAdapterCapabilities, TChainIdentifier> {
25507
- from?: SpendSource<TFromAdapterCapabilities> | SpendSource<TFromAdapterCapabilities>[];
25508
- config: SpendConfig & {
25509
- retry: RetryMintConfig;
25510
- };
25947
+ allowanceStrategy?: AllowanceStrategy;
25511
25948
  }
25512
25949
  /**
25513
- * Parameters for spending (minting) USDC on a destination chain from
25514
- * one or more Gateway account sources.
25950
+ * Parameters for depositing tokens into *another* Gateway account.
25515
25951
  *
25516
25952
  * @remarks
25517
- * `from` can be a single source or an array when pulling from
25518
- * multiple adapters (e.g. an EVM account and a Solana account).
25953
+ * Extends `DepositParams` with a `depositAccount` field that
25954
+ * specifies the Gateway account to credit instead of the caller's
25955
+ * own account. The Gateway contract only supports approval-based
25956
+ * deposit-for (no permit/authorize); allowance strategy is not
25957
+ * configurable and is not part of this type.
25519
25958
  *
25520
- * @typeParam TFromAdapterCapabilities - Source adapter capabilities.
25521
- * @typeParam TToAdapterCapabilities - Destination adapter capabilities.
25959
+ * @typeParam TAdapterCapabilities - Adapter capability constraints.
25522
25960
  * @typeParam TChainIdentifier - Accepted chain identifier type.
25523
25961
  *
25524
25962
  * @example
25525
25963
  * ```typescript
25526
- * import type { SpendParams } from '@circle-fin/unified-balance-kit'
25964
+ * import type { DepositForParams } from '@circle-fin/unified-balance-kit'
25527
25965
  *
25528
- * const params: SpendParams = {
25529
- * from: {
25530
- * adapter: evmAdapter,
25531
- * allocations: { amount: '100', chain: 'Ethereum' },
25532
- * },
25533
- * to: { adapter: avalancheAdapter, chain: 'Avalanche' },
25966
+ * const params: DepositForParams = {
25967
+ * from: { adapter: evmAdapter, chain: 'Ethereum' },
25534
25968
  * amount: '100',
25535
25969
  * token: 'USDC',
25970
+ * depositAccount: '0x1234…abcd',
25536
25971
  * }
25537
25972
  * ```
25538
25973
  */
25539
- type SpendParams<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> = SpendParamsWithFrom<TFromAdapterCapabilities, TToAdapterCapabilities, TChainIdentifier> | SpendParamsRetry<TFromAdapterCapabilities, TToAdapterCapabilities, TChainIdentifier>;
25540
- /**
25541
- * Result returned after a successful spend (mint) operation.
25542
- *
25974
+ interface DepositForParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> extends Omit<DepositParams<TAdapterCapabilities, TChainIdentifier>, 'allowanceStrategy'> {
25975
+ /**
25976
+ * The Gateway account address to credit with the deposit.
25977
+ *
25978
+ * When provided the deposit is credited to this account rather
25979
+ * than the caller's own.
25980
+ */
25981
+ depositAccount: string;
25982
+ }
25983
+ /**
25984
+ * Result returned after a successful deposit operation.
25985
+ *
25543
25986
  * @example
25544
25987
  * ```typescript
25545
- * import type { SpendResult } from '@circle-fin/unified-balance-kit'
25988
+ * import type { DepositResult } from '@circle-fin/unified-balance-kit'
25546
25989
  *
25547
- * const result: SpendResult = {
25548
- * allocations: [
25549
- * { amount: '100', chain: 'Ethereum', sourceAccount: '0x…' },
25550
- * ],
25551
- * recipientAddress: '0xDEST…abcd',
25552
- * destinationChain: 'Avalanche',
25553
- * txHash: '0xabcdef…',
25554
- * explorerUrl: 'https://snowtrace.io/tx/0xabcdef…',
25990
+ * const result: DepositResult = {
25991
+ * amount: '100',
25992
+ * token: 'USDC',
25993
+ * depositedTo: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD38',
25994
+ * depositedBy: '0x8ba1f109551bD432803012645632213Ab0521A3c',
25995
+ * chain: 'Ethereum',
25996
+ * txHash:
25997
+ * '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3',
25998
+ * explorerUrl:
25999
+ * 'https://etherscan.io/tx/0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3',
25555
26000
  * }
25556
26001
  * ```
25557
26002
  */
25558
- interface SpendResult {
25559
- /**
25560
- * Flattened list of allocations that were executed, each with its
25561
- * source Gateway account. Only present for non-retry spends.
25562
- */
25563
- allocations?: AllocationResult[];
25564
- /** The address that received the minted USDC. */
25565
- recipientAddress: string;
25566
- /** The destination chain on which the recipient received the USDC. */
25567
- destinationChain: Blockchain;
26003
+ interface DepositResult {
26004
+ /** The deposited amount (human-readable decimal string). */
26005
+ amount: string;
26006
+ /** The token that was deposited. */
26007
+ token: SupportedToken;
26008
+ /** The Gateway account address credited by the deposit. */
26009
+ depositedTo: string;
26010
+ /** The address that signed and funded the deposit. */
26011
+ depositedBy: string;
26012
+ /** The chain on which the deposit occurred. */
26013
+ chain: Blockchain;
25568
26014
  /**
25569
26015
  * Unique identifier returned by the blockchain once the
25570
26016
  * transaction is mined.
@@ -25579,543 +26025,518 @@ interface SpendResult {
25579
26025
  * for the chain.
25580
26026
  */
25581
26027
  explorerUrl?: string;
25582
- /**
25583
- * Fee breakdown (provider, gasFee, optional kit, forwarder) for the
25584
- * executed spend. Same shape as estimateSpend fees. Omitted when
25585
- * using config.retry.
25586
- */
25587
- fees?: FeeEntry[];
25588
- /**
25589
- * Gateway transfer identifier. Present when `useForwarder` is enabled
25590
- * and can be used to query transfer status via `GET /v1/transfer/{id}`.
25591
- */
25592
- transferId?: string;
25593
- /**
25594
- * Block height after which the transfer attestation expires.
25595
- * Returned by the Gateway transfer API.
25596
- */
25597
- expirationBlock?: string;
25598
- /**
25599
- * Ordered list of steps executed during the spend operation.
25600
- *
25601
- * @remarks
25602
- * Each entry records the outcome of one phase of the spend flow.
25603
- * For a normal spend the order is:
25604
- * `buildBurnIntents` → `signBurnIntents` → `transfer` → `mint`.
25605
- * For a retry spend only `mint` is present.
25606
- */
25607
- steps?: SpendStep[];
25608
- }
25609
- interface CustomFeeConfig {
25610
- recipientAddress: string;
25611
- value: string;
25612
26028
  }
26029
+
25613
26030
  /**
25614
- * Data needed to retry a mint that failed after the transfer was
25615
- * already committed (funds locked).
26031
+ * Network type for balance queries when the target chain(s) are not
26032
+ * explicitly specified. Default is mainnet.
26033
+ */
26034
+ type NetworkType = 'mainnet' | 'testnet';
26035
+ /**
26036
+ * A single balance source identifying an account to query.
25616
26037
  *
25617
- * Obtain these values from the KitError (TRANSACTION_REVERTED) thrown when
25618
- * the on-chain mint step fails. The attestation and signature are available
25619
- * in `error.cause.trace`.
26038
+ * Provide **at least one** of `adapter` or `address`:
26039
+ *
26040
+ * - **Address only** — pass `address` without `adapter` to query by
26041
+ * raw Gateway account address.
26042
+ * - **Adapter (user-controlled)** — pass `adapter` without `address`;
26043
+ * the wallet address is resolved automatically.
26044
+ * - **Adapter (developer-controlled)** — pass both `adapter` and
26045
+ * `address`; the explicit address is required because there is no
26046
+ * single connected wallet.
26047
+ *
26048
+ * @typeParam TAdapterCapabilities - Adapter capability constraints.
26049
+ *
26050
+ * @example
26051
+ * ```typescript
26052
+ * import type { BalanceSource } from '@circle-fin/unified-balance-kit'
26053
+ *
26054
+ * // Address-only (no adapter needed)
26055
+ * const addrSource: BalanceSource = {
26056
+ * address: '0x1234…abcd',
26057
+ * chains: ['Ethereum', 'Base'],
26058
+ * }
26059
+ *
26060
+ * // Adapter (user-controlled wallet)
26061
+ * const adapterSource: BalanceSource = {
26062
+ * adapter: evmAdapter,
26063
+ * chains: 'Ethereum',
26064
+ * }
26065
+ *
26066
+ * // Adapter (developer-controlled) — address required
26067
+ * const devSource: BalanceSource = {
26068
+ * adapter: circleWalletsAdapter,
26069
+ * address: '0x1234…abcd',
26070
+ * chains: ['Ethereum'],
26071
+ * }
26072
+ * ```
25620
26073
  */
25621
- interface RetryMintConfig {
25622
- /** The attestation hex string returned by the Gateway `/v1/transfer` API. */
25623
- attestation: string;
25624
- /** The attestation signature hex string returned by `/v1/transfer`. */
25625
- signature: string;
25626
- }
25627
- interface SpendConfig {
25628
- customFee?: CustomFeeConfig;
26074
+ interface BalanceSource<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
26075
+ /** The adapter whose resolved address is used to fetch balances. */
26076
+ adapter?: Adapter<TAdapterCapabilities>;
25629
26077
  /**
25630
- * When provided, skips the estimate/sign/transfer steps and proceeds
25631
- * directly to the on-chain mint using a previously obtained attestation.
25632
- *
25633
- * Use this to retry a mint that failed due to an RPC or network issue
25634
- * after the transfer was already committed.
26078
+ * The account address to query balances for.
25635
26079
  *
25636
- * @remarks
25637
- * The `useForwarder` flag on the destination is ignored during retry
25638
- * because the attestation was already issued the Forwarding Service
25639
- * is only involved in the initial transfer, not re-mints.
26080
+ * - Required when no `adapter` is provided (address-only query).
26081
+ * - Required for developer-controlled adapters.
26082
+ * - Must be omitted for user-controlled adapters (auto-resolved).
25640
26083
  */
25641
- retry?: RetryMintConfig;
25642
- }
25643
- interface ResolvedAllocation {
25644
- amount: string;
25645
- chain: ChainDefinition;
25646
- }
25647
- interface ResolvedSpendSource<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
25648
- adapter: Adapter<TAdapterCapabilities>;
25649
- allocations: ResolvedAllocation[];
25650
- address?: string;
25651
- sourceAccount?: string;
25652
- }
25653
- interface ResolvedSpendDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
25654
- adapter?: Adapter<TAdapterCapabilities>;
25655
- chain: ChainDefinition;
25656
- recipientAddress?: string;
25657
26084
  address?: string;
25658
- useForwarder?: boolean;
25659
- }
25660
- interface ResolvedSpendParams<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
25661
- from: ResolvedSpendSource<TFromAdapterCapabilities>[];
25662
- to: ResolvedSpendDestination<TToAdapterCapabilities>;
25663
- token: SupportedToken;
25664
- config?: SpendConfig;
26085
+ /**
26086
+ * Chains to fetch balances from.
26087
+ *
26088
+ * - If omitted, get balances from all supported chains.
26089
+ * - If provided, only get balances for the specified chain(s).
26090
+ */
26091
+ chains?: UnifiedBalanceChainIdentifier | UnifiedBalanceChainIdentifier[];
25665
26092
  }
25666
26093
  /**
25667
- * Function that computes the fee amount (in human-readable units, e.g. "10.5")
25668
- * given the resolved spend parameters.
25669
- */
25670
- type SpendFeeFunction = (params: ResolvedSpendParams) => Promise<string> | string;
25671
- /**
25672
- * Function that resolves the fee recipient address for a spend.
25673
- * Called once per spend, against the resolved **destination** chain —
25674
- * every fee burn intent in a spend mints to that single chain
25675
- * regardless of which source chain(s) funded it, so only one
25676
- * recipient address (valid on the destination chain) is ever needed.
25677
- */
25678
- type SpendFeeRecipientFunction = (destinationChain: ChainDefinition, params: ResolvedSpendParams) => Promise<string> | string;
25679
- /**
25680
- * Policy for computing and routing custom developer fees.
25681
- *
25682
- * **Important:** When the kit invokes `computeFee` and
25683
- * `resolveFeeRecipientAddress`, the `params` argument may be the
25684
- * **raw, unresolved** `SpendParams` (cast to `ResolvedSpendParams`).
25685
- * Fields that only exist after resolution (e.g. per-source allocations)
25686
- * may be `undefined`. Implementations should only rely on top-level
25687
- * fields such as `to`, `token`, and `amount`.
26094
+ * Accept a single item or an array of items of the same type.
25688
26095
  *
25689
- * @remarks
25690
- * `resolveFeeRecipientAddress` is optional when you configure
25691
- * {@link UnifiedBalanceKit.setFeeRecipients} instead — the declarative
25692
- * map takes priority over this callback when both are present. Provide
25693
- * exactly one of the two; a policy with neither throws at spend time.
26096
+ * @typeParam T - The element type.
25694
26097
  */
25695
- interface CustomFeePolicy {
25696
- computeFee: SpendFeeFunction;
25697
- resolveFeeRecipientAddress?: SpendFeeRecipientFunction;
25698
- }
26098
+ type OneOrMany<T> = T | T[];
25699
26099
  /**
25700
- * Chain type group used to key {@link FeeRecipientsConfig}.
25701
- *
25702
- * @remarks
25703
- * Only `'evm'` and `'solana'` are live today (the only chain types the
25704
- * kit's provider currently supports). This is deliberately a narrow
25705
- * subset of `@core/chains`' broader `ChainType` union rather than a
25706
- * hardcoded two-field struct, so that support for additional non-EVM
25707
- * chain types (e.g. Stellar, Starknet) can be added later by adding
25708
- * new union members here — no restructuring of `FeeRecipientsConfig`
25709
- * or its consumers required.
26100
+ * One or more balance sources, each of which may be a single object
26101
+ * or an array.
25710
26102
  */
25711
- type FeeRecipientChainType = 'evm' | 'solana';
26103
+ type Sources<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = OneOrMany<BalanceSource<TAdapterCapabilities>>;
25712
26104
  /**
25713
- * Declarative map of fee recipient addresses, keyed by chain type.
26105
+ * Parameters for the balances and pending-deposits API requests.
25714
26106
  *
25715
- * @remarks
25716
- * Set via {@link UnifiedBalanceKit.setFeeRecipients}. At spend time the
25717
- * kit resolves the spend's destination chain to its
25718
- * {@link FeeRecipientChainType} and looks up the matching entry —
25719
- * exactly one recipient is used per spend (see
25720
- * {@link SpendFeeRecipientFunction}). Provide entries for every chain
25721
- * type you expect to spend to; a spend to a destination chain type
25722
- * with no matching entry throws before any fee collection is
25723
- * attempted.
26107
+ * Specify the `token` to query and one or more `sources` identifying
26108
+ * the accounts or adapters whose balances should be retrieved.
26109
+ * When `includePending` is true, the result includes pending balances
26110
+ * and pending transaction details per chain.
25724
26111
  *
25725
26112
  * @example
25726
26113
  * ```typescript
25727
- * import type { FeeRecipientsConfig } from '@circle-fin/unified-balance-kit'
26114
+ * import type { GetBalancesParams } from '@circle-fin/unified-balance-kit'
25728
26115
  *
25729
- * const feeRecipients: FeeRecipientsConfig = {
25730
- * evm: '0x1234567890123456789012345678901234567890',
25731
- * solana: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
26116
+ * // Single adapter source
26117
+ * const params1: GetBalancesParams = {
26118
+ * token: 'USDC',
26119
+ * sources: { adapter: evmAdapter },
25732
26120
  * }
25733
- * ```
26121
+ *
26122
+ * // Single address source with pending
26123
+ * const params2: GetBalancesParams = {
26124
+ * token: 'USDC',
26125
+ * sources: { address: '0x1234…abcd', chains: 'Ethereum' },
26126
+ * includePending: true,
26127
+ * }
26128
+ *
26129
+ * // Multiple address sources
26130
+ * const params3: GetBalancesParams = {
26131
+ * token: 'USDC',
26132
+ * sources: [
26133
+ * { address: '0x8f3Cf7…', chains: ['ChainA', 'ChainB'] },
26134
+ * { address: '0x4B0897…', chains: ['ChainB', 'ChainC'] },
26135
+ * ],
26136
+ * }
26137
+ *
26138
+ * // Adapter only (confirmed balances only; includePending defaults to false)
26139
+ * const params4: GetBalancesParams = {
26140
+ * token: 'USDC',
26141
+ * sources: { adapter: evmAdapter },
26142
+ * }
26143
+ * ```
25734
26144
  */
25735
- type FeeRecipientsConfig = Partial<Record<FeeRecipientChainType, string>>;
26145
+ interface GetBalancesParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
26146
+ /**
26147
+ * The token to query balances for.
26148
+ * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26149
+ *
26150
+ * @defaultValue 'USDC'
26151
+ */
26152
+ token?: SupportedTokenInput;
26153
+ /**
26154
+ * One or more sources identifying the accounts or adapters to
26155
+ * query. Accepts a single object or an array.
26156
+ */
26157
+ sources: Sources<TAdapterCapabilities>;
26158
+ /**
26159
+ * When true, the result includes pending balances.
26160
+ * When false or omitted, only confirmed balances
26161
+ * are returned.
26162
+ *
26163
+ * @defaultValue false
26164
+ */
26165
+ includePending?: boolean;
26166
+ /**
26167
+ * Network to use when no chains are specified on a source.
26168
+ * When omitted, mainnet is used when chains cannot be derived.
26169
+ *
26170
+ * @defaultValue 'mainnet'
26171
+ */
26172
+ networkType?: NetworkType;
26173
+ }
25736
26174
  /**
25737
- * Fee category describing the origin of a fee line item.
26175
+ * A pending transaction included in {@link GetBalancesResult}
26176
+ * when `includePending` is true.
25738
26177
  *
25739
- * - `'provider'` — Fee charged by the cross-chain provider (e.g. protocol fee).
25740
- * - `'gasFee'` — On-chain gas cost denominated in the transfer token (e.g. USDC).
25741
- * - `'kit'` — Fee charged by the kit / developer integration.
25742
- * - `'forwarder'` — Fee charged by Circle's Forwarding Service for automatic mint.
26178
+ * @example
26179
+ * ```typescript
26180
+ * import type { PendingBalanceTransaction } from '@circle-fin/unified-balance-kit'
26181
+ *
26182
+ * const tx: PendingBalanceTransaction = {
26183
+ * transactionHash: '0x2c5f3e4a…',
26184
+ * amount: '50.00',
26185
+ * blockTimestamp: '2023-11-07T05:31:56Z',
26186
+ * }
26187
+ * ```
25743
26188
  */
25744
- type FeeType = 'provider' | 'gasFee' | 'kit' | 'forwarder';
26189
+ interface PendingBalanceTransaction {
26190
+ /** Transaction hash of the pending deposit. */
26191
+ transactionHash: string;
26192
+ /** Pending amount (human-readable decimal string). */
26193
+ amount: string;
26194
+ /** ISO 8601 timestamp of the block. */
26195
+ blockTimestamp: string;
26196
+ }
25745
26197
  /**
25746
- * Per-chain breakdown of a fee amount.
26198
+ * Per-chain balance within a breakdown in {@link GetBalancesResult}.
26199
+ *
26200
+ * When `includePending` is true, `pendingBalance` and `pendingTransactions`
26201
+ * are present.
25747
26202
  *
25748
26203
  * @example
25749
26204
  * ```typescript
25750
- * import type { FeeAllocation } from '@circle-fin/unified-balance-kit'
26205
+ * import type { ChainBalanceBreakdown } from '@circle-fin/unified-balance-kit'
25751
26206
  *
25752
- * const allocation: FeeAllocation = {
26207
+ * // Confirmed only (includePending: false)
26208
+ * const chain: ChainBalanceBreakdown = {
26209
+ * chain: 'Arbitrum',
26210
+ * confirmedBalance: '1500.00',
26211
+ * }
26212
+ *
26213
+ * // With pending (includePending: true)
26214
+ * const chainWithPending: ChainBalanceBreakdown = {
25753
26215
  * chain: 'Ethereum',
25754
- * amount: '0.00005',
26216
+ * confirmedBalance: '1000.00',
26217
+ * pendingBalance: '50.00',
26218
+ * pendingTransactions: [
26219
+ * { transactionHash: '0x2c5f3e…', amount: '50.00', blockTimestamp: '2023-11-07T05:31:56Z' },
26220
+ * ],
25755
26221
  * }
25756
26222
  * ```
25757
26223
  */
25758
- interface FeeAllocation {
25759
- /** The chain to which this portion of the fee applies. */
26224
+ interface ChainBalanceBreakdown {
26225
+ /** The chain. */
25760
26226
  chain: Blockchain;
25761
- /** The fee amount on this chain (human-readable decimal string). */
25762
- amount: string;
26227
+ /** Confirmed balance (human-readable decimal string). */
26228
+ confirmedBalance: string;
26229
+ /**
26230
+ * Pending balance on this chain.
26231
+ * Present only when {@link GetBalancesParams.includePending} is true.
26232
+ */
26233
+ pendingBalance?: string;
26234
+ /**
26235
+ * Pending deposit transactions on this chain.
26236
+ * Present only when {@link GetBalancesParams.includePending} is true.
26237
+ */
26238
+ pendingTransactions?: PendingBalanceTransaction[];
25763
26239
  }
25764
26240
  /**
25765
- * A single fee line item within an estimate.
26241
+ * Per-account balance breakdown used in {@link GetBalancesResult}.
25766
26242
  *
25767
- * @remarks
25768
- * Each entry describes a fee category (`type`), the token it is
25769
- * denominated in, the aggregate `amount`, and an optional per-chain
25770
- * `allocations` breakdown.
26243
+ * When `includePending` is true, `totalPending` is present and each chain
26244
+ * entry may include `pendingBalance` and `pendingTransactions`.
25771
26245
  *
25772
26246
  * @example
25773
26247
  * ```typescript
25774
- * import type { FeeEntry } from '@circle-fin/unified-balance-kit'
26248
+ * import type { BalanceWithPendingBreakdown } from '@circle-fin/unified-balance-kit'
25775
26249
  *
25776
- * // Fee with per-chain allocation breakdown
25777
- * const providerFee: FeeEntry = {
25778
- * type: 'provider',
25779
- * token: 'USDC',
25780
- * amount: '0.00011',
25781
- * allocations: [
25782
- * { chain: 'Ethereum', amount: '0.00005' },
25783
- * { chain: 'Polygon', amount: '0.00006' },
26250
+ * const entry: BalanceWithPendingBreakdown = {
26251
+ * depositor: '0x71C765…',
26252
+ * totalConfirmed: '1000.00',
26253
+ * totalPending: '50.00',
26254
+ * breakdown: [
26255
+ * { chain: 'Ethereum', confirmedBalance: '1000.00', pendingBalance: '50.00', pendingTransactions: [...] },
25784
26256
  * ],
25785
26257
  * }
25786
- *
25787
- * // Flat fee without allocations (e.g. forwarder)
25788
- * const forwarderFee: FeeEntry = {
25789
- * type: 'forwarder',
25790
- * token: 'USDC',
25791
- * amount: '0.005',
25792
- * }
25793
26258
  * ```
25794
26259
  */
25795
- interface FeeEntry {
25796
- /** The category of this fee. */
25797
- type: FeeType;
25798
- /** The token in which this fee is denominated (e.g. `'USDC'`, `'ETH'`). */
25799
- token: string;
25800
- /** Aggregate fee amount (human-readable decimal string). */
25801
- amount: string;
25802
- /** Per-chain breakdown of the fee. Omitted for flat fees (e.g. forwarder). */
25803
- allocations?: FeeAllocation[];
26260
+ interface BalanceWithPendingBreakdown {
26261
+ /** Gateway account (depositor) address. */
26262
+ depositor: string;
26263
+ /** Total confirmed balance across chains (human-readable decimal string). */
26264
+ totalConfirmed: string;
25804
26265
  /**
25805
- * When `type === 'kit'`, the address that receives the kit fee.
25806
- * Omitted for other fee types.
26266
+ * Total pending balance across chains.
26267
+ * Present only when `includePending` is true.
25807
26268
  */
25808
- recipientAddress?: string;
26269
+ totalPending?: string;
26270
+ /** Per-chain breakdown for this depositor. */
26271
+ breakdown: ChainBalanceBreakdown[];
25809
26272
  }
25810
26273
  /**
25811
- * Cost estimation for a spend (mint) operation.
26274
+ * Result returned from the provider's `getBalances` method (combined confirmed and pending).
25812
26275
  *
25813
- * @remarks
25814
- * Returned by the provider's `estimateSpend` method to give callers
25815
- * visibility into the expected fees *before* executing a spend.
25816
- * Each entry in `fees` represents a distinct fee category with its
25817
- * per-chain allocation breakdown.
26276
+ * When `includePending` is false (default), only `totalConfirmedBalance` and
26277
+ * `breakdown` with confirmed fields are returned. When `includePending` is true,
26278
+ * `totalPendingBalance` is present and breakdown entries include pending amounts
26279
+ * and `pendingTransactions` per chain.
25818
26280
  *
25819
26281
  * @example
25820
26282
  * ```typescript
25821
- * import type { EstimateSpendResult } from '@circle-fin/unified-balance-kit'
26283
+ * import type { GetBalancesResult } from '@circle-fin/unified-balance-kit'
25822
26284
  *
25823
- * const estimate: EstimateSpendResult = {
25824
- * fees: [
25825
- * {
25826
- * type: 'provider',
25827
- * token: 'USDC',
25828
- * amount: '0.00011',
25829
- * allocations: [
25830
- * { chain: 'Ethereum', amount: '0.00005' },
25831
- * { chain: 'Polygon', amount: '0.00006' },
25832
- * ],
25833
- * },
26285
+ * // includePending: false
26286
+ * const result: GetBalancesResult = {
26287
+ * token: 'USDC',
26288
+ * totalConfirmedBalance: '3500.00',
26289
+ * breakdown: [
25834
26290
  * {
25835
- * type: 'gasFee',
25836
- * token: 'USDC',
25837
- * amount: '0.0025',
25838
- * allocations: [
25839
- * { chain: 'Ethereum', amount: '0.0015' },
25840
- * { chain: 'Polygon', amount: '0.0010' },
26291
+ * depositor: '0xAAAd67…',
26292
+ * totalConfirmed: '2500.00',
26293
+ * breakdown: [
26294
+ * { chain: 'Arbitrum', confirmedBalance: '1500.00' },
26295
+ * { chain: 'Optimism', confirmedBalance: '1000.00' },
25841
26296
  * ],
25842
26297
  * },
26298
+ * ],
26299
+ * }
26300
+ *
26301
+ * // includePending: true
26302
+ * const resultWithPending: GetBalancesResult = {
26303
+ * token: 'USDC',
26304
+ * totalConfirmedBalance: '3500.00',
26305
+ * totalPendingBalance: '650.00',
26306
+ * breakdown: [
25843
26307
  * {
25844
- * type: 'kit',
25845
- * token: 'USDC',
25846
- * amount: '0.05',
25847
- * allocations: [
25848
- * { chain: 'Ethereum', amount: '0.05' },
26308
+ * depositor: '0x71C765…',
26309
+ * totalConfirmed: '1000.00',
26310
+ * totalPending: '50.00',
26311
+ * breakdown: [
26312
+ * {
26313
+ * chain: 'Ethereum',
26314
+ * confirmedBalance: '1000.00',
26315
+ * pendingBalance: '50.00',
26316
+ * pendingTransactions: [
26317
+ * { transactionHash: '0x2c5f3e…', amount: '50.00', blockTimestamp: '2023-11-07T05:31:56Z' },
26318
+ * ],
26319
+ * },
25849
26320
  * ],
25850
26321
  * },
25851
26322
  * ],
25852
26323
  * }
25853
26324
  * ```
25854
26325
  */
25855
- interface EstimateSpendResult {
25856
- /** Itemised fee breakdown for the spend operation. */
25857
- fees: FeeEntry[];
26326
+ interface GetBalancesResult {
26327
+ /** Token that was queried. */
26328
+ token: SupportedToken;
26329
+ /** Total confirmed balance across all accounts and chains (human-readable decimal string). */
26330
+ totalConfirmedBalance: string;
26331
+ /**
26332
+ * Total pending balance across all accounts and chains.
26333
+ * Present only when `includePending` is true.
26334
+ */
26335
+ totalPendingBalance?: string;
26336
+ /** Per-account, per-chain breakdown. */
26337
+ breakdown: BalanceWithPendingBreakdown[];
25858
26338
  }
25859
26339
 
25860
26340
  /**
25861
- * Runtime array of token identifiers supported by the unified-balance-kit.
26341
+ * Parameters for adding or removing a delegate on a Gateway account.
25862
26342
  *
25863
- * @example
25864
- * ```typescript
25865
- * import { SUPPORTED_TOKENS } from '@circle-fin/unified-balance-kit'
25866
- *
25867
- * if (SUPPORTED_TOKENS.includes('USDC')) {
25868
- * console.log('USDC is supported')
25869
- * }
25870
- * ```
25871
- */
25872
- declare const SUPPORTED_TOKENS: readonly ["USDC"];
25873
- /**
25874
- * Token identifiers supported by the unified-balance-kit.
25875
- *
25876
- * @example
25877
- * ```typescript
25878
- * import type { SupportedToken } from '@circle-fin/unified-balance-kit'
25879
- *
25880
- * const token: SupportedToken = 'USDC'
25881
- * ```
25882
- */
25883
- type SupportedToken = (typeof SUPPORTED_TOKENS)[number];
25884
- /**
25885
- * Case-insensitive variant of {@link SupportedToken} for user-facing input.
26343
+ * @remarks
26344
+ * Delegation allows a different signer to move funds out of the
26345
+ * owner's account. The delegate must be added explicitly per chain.
25886
26346
  *
25887
- * Accepts the canonical uppercase form, fully lowercase, and title-case
25888
- * (e.g. `'USDC'`, `'usdc'`, `'Usdc'`). Arbitrary mixed-case input like
25889
- * `'uSdC'` is handled at runtime by the Zod schema and
25890
- * {@link normalizeToken}, so exhaustive compile-time permutations are
25891
- * unnecessary. Avoiding a recursive `CasePermutations` type prevents
25892
- * 2^N type-literal explosion as the token list grows.
26347
+ * @typeParam TAdapterCapabilities - Adapter capability constraints.
26348
+ * @typeParam TChainIdentifier - Accepted chain identifier type.
25893
26349
  *
25894
26350
  * @example
25895
26351
  * ```typescript
25896
- * import type { SupportedTokenInput } from '@circle-fin/unified-balance-kit'
26352
+ * import type { UpdateDelegateParams } from '@circle-fin/unified-balance-kit'
25897
26353
  *
25898
- * const token: SupportedTokenInput = 'usdc' // OK
26354
+ * const params: UpdateDelegateParams = {
26355
+ * from: { adapter: evmAdapter, chain: 'Ethereum' },
26356
+ * delegateAddress: '0xDELEGATE…1111',
26357
+ * }
25899
26358
  * ```
25900
26359
  */
25901
- type SupportedTokenInput = SupportedToken | Lowercase<SupportedToken> | Capitalize<Lowercase<SupportedToken>>;
25902
- /**
25903
- * Intentional `any` escape hatch so heterogeneous providers can be stored
25904
- * in a single array while `MergeActions` rebuilds concrete action types.
25905
- *
25906
- * Type safety is re-established by the `on()`/`off()` overloads in
25907
- * {@link UnifiedBalanceKit} — do not remove those overloads.
25908
- *
25909
- * Caveat: custom providers whose `TProviderActions` differs from the
25910
- * default map will have action types erased to `any` unless the consumer
25911
- * passes the provider tuple as a generic, e.g. `UnifiedBalanceKit<[MyProvider]>`.
25912
- */
25913
- type FlexibleGatewayProvider = IGatewayProvider<any>;
26360
+ interface UpdateDelegateParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26361
+ /**
26362
+ * The owner's adapter context identifying the account and chain
26363
+ * to which the delegate will be authorized.
26364
+ */
26365
+ from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26366
+ /**
26367
+ * The address being added or removed as an authorized delegate.
26368
+ */
26369
+ delegateAddress: string;
26370
+ /**
26371
+ * The token for which delegation applies.
26372
+ * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26373
+ *
26374
+ * @defaultValue 'USDC'
26375
+ */
26376
+ token?: SupportedTokenInput;
26377
+ }
25914
26378
  /**
25915
- * Configuration options for initializing a {@link UnifiedBalanceKit} instance.
25916
- *
25917
- * When no providers are specified, the kit uses the default Gateway v1
25918
- * provider. Any additional providers supplied via config are appended
25919
- * to the defaults.
25920
- *
25921
- * @typeParam TExtraProviders - Array type of additional providers
25922
- *
25923
- * @example
25924
- * ```typescript
25925
- * import { UnifiedBalanceKit } from '@circle-fin/unified-balance-kit'
25926
- *
25927
- * // Create kit with default providers
25928
- * const kit = new UnifiedBalanceKit()
25929
- * ```
26379
+ * Result returned after a successful add or remove delegate
26380
+ * operation.
25930
26381
  *
25931
26382
  * @example
25932
26383
  * ```typescript
25933
- * import { UnifiedBalanceKit } from '@circle-fin/unified-balance-kit'
26384
+ * import type { UpdateDelegateResult } from '@circle-fin/unified-balance-kit'
25934
26385
  *
25935
- * // Create kit with additional providers
25936
- * const kit = new UnifiedBalanceKit({
25937
- * providers: [myCustomProvider],
25938
- * })
26386
+ * const result: UpdateDelegateResult = {
26387
+ * account: '0xOWNER…1234',
26388
+ * delegateAddress: '0xDELEGATE…1111',
26389
+ * chain: 'Ethereum',
26390
+ * state: 'added',
26391
+ * txHash: '0xabc…',
26392
+ * explorerUrl: 'https://etherscan.io/tx/0xabc…',
26393
+ * }
25939
26394
  * ```
25940
26395
  */
25941
- interface UnifiedBalanceKitConfig<TExtraProviders extends FlexibleGatewayProvider[] = []> {
25942
- /**
25943
- * Optional array of additional Gateway providers.
25944
- *
25945
- * If not provided, default providers will be initialized.
25946
- */
25947
- providers?: TExtraProviders;
26396
+ interface UpdateDelegateResult {
26397
+ /** The Gateway account that was modified. */
26398
+ account: string;
26399
+ /** The delegate address that was added or removed. */
26400
+ delegateAddress: string;
25948
26401
  /**
25949
- * Disable analytics telemetry (success events with `txHash`).
25950
- *
25951
- * When `true`, the SDK will not POST to the telemetry endpoint
25952
- * after successful verb operations. Defaults to `false` (enabled).
26402
+ * The chain on which the delegate was updated.
25953
26403
  *
25954
26404
  * @remarks
25955
- * Only applies to the class-based API (`new UnifiedBalanceKit()`).
25956
- * The functional API via `createUnifiedBalanceKitContext()` does not
25957
- * register telemetry handlers.
25958
- *
25959
- * @defaultValue false
26405
+ * Delegates must be added explicitly per chain. You cannot
26406
+ * authorize a delegate for all chains at once.
25960
26407
  */
25961
- disableAnalytics?: boolean;
26408
+ chain: Blockchain;
26409
+ /** Whether the delegate was added or removed. */
26410
+ state: 'added' | 'removed';
25962
26411
  /**
25963
- * Disable error telemetry.
25964
- *
25965
- * When `true`, the SDK will not POST error details to the telemetry
25966
- * endpoint when public methods throw. Defaults to `false` (enabled).
25967
- *
25968
- * @remarks
25969
- * Only applies to the class-based API (`new UnifiedBalanceKit()`).
25970
- *
25971
- * @defaultValue false
26412
+ * Unique identifier returned by the blockchain once the
26413
+ * transaction is mined.
25972
26414
  */
25973
- disableErrorReporting?: boolean;
26415
+ txHash: string;
25974
26416
  /**
25975
- * Skip the built-in default providers when assembling the context.
25976
- *
25977
- * By default the kit prepends the standard Gateway v1 provider so
25978
- * `providers` is treated as additive. Pass `true` to use only the
25979
- * providers supplied in {@link UnifiedBalanceKitConfig.providers}.
25980
- *
25981
- * Useful when stubbing the gateway in integration tests, when running
25982
- * against a self-hosted gateway replacement, or any time you want full
25983
- * control over which provider serves a given chain.
26417
+ * Link to view the transaction details on the appropriate
26418
+ * blockchain explorer.
25984
26419
  *
25985
- * @defaultValue false
26420
+ * @remarks
26421
+ * May be `undefined` when the explorer URL cannot be resolved
26422
+ * for the chain.
25986
26423
  */
25987
- excludeDefaultProviders?: boolean;
26424
+ explorerUrl?: string;
25988
26425
  }
25989
-
25990
26426
  /**
25991
- * Token allowance strategy used to authorize a Gateway deposit.
25992
- *
25993
- * - `'approve'` — traditional ERC-20 `approve` transaction.
25994
- * - `'permit'` — gasless EIP-2612 off-chain signature.
25995
- * - `'authorize'` — EIP-3009 `transferWithAuthorization`.
25996
- *
25997
- * @example
25998
- * ```typescript
25999
- * import type { AllowanceStrategy } from '@circle-fin/unified-balance-kit'
26427
+ * The finality-aware status of a delegate on a Gateway account.
26000
26428
  *
26001
- * const strategy: AllowanceStrategy = 'permit'
26002
- * ```
26429
+ * - `'none'` — not a delegate on-chain.
26430
+ * - `'pending'` — delegate set on-chain but Gateway hasn't finalized it yet;
26431
+ * spend will fail until the status advances to `'ready'`.
26432
+ * - `'ready'` — finalized at Gateway; spend will succeed.
26003
26433
  */
26004
- type AllowanceStrategy = 'approve' | 'permit' | 'authorize';
26434
+ type DelegateStatus = 'none' | 'pending' | 'ready';
26005
26435
  /**
26006
- * Parameters for depositing tokens into the caller's own Gateway
26007
- * account on a specific chain.
26008
- *
26009
- * @remarks
26010
- * Although a Gateway account can span multiple chains (e.g. all EVM
26011
- * chains share the same account), every deposit targets exactly one
26012
- * chain. The depositor is identified by the adapter context.
26436
+ * Parameters for checking the delegate status of an address on a
26437
+ * Gateway account.
26013
26438
  *
26014
26439
  * @typeParam TAdapterCapabilities - Adapter capability constraints.
26015
26440
  * @typeParam TChainIdentifier - Accepted chain identifier type.
26016
26441
  *
26017
26442
  * @example
26018
26443
  * ```typescript
26019
- * import type { DepositParams } from '@circle-fin/unified-balance-kit'
26444
+ * import type { GetDelegateStatusParams } from '@circle-fin/unified-balance-kit'
26020
26445
  *
26021
- * const params: DepositParams = {
26446
+ * const params: GetDelegateStatusParams = {
26022
26447
  * from: { adapter: evmAdapter, chain: 'Ethereum' },
26023
- * amount: '100',
26024
- * token: 'USDC',
26025
- * allowanceStrategy: 'permit',
26448
+ * delegateAddress: '0xDELEGATE…1111',
26026
26449
  * }
26027
26450
  * ```
26028
26451
  */
26029
- interface DepositParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26030
- /**
26031
- * The adapter context identifying the depositor and chain.
26032
- */
26452
+ interface GetDelegateStatusParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26453
+ /** The adapter context identifying the account owner and chain. */
26033
26454
  from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26455
+ /** The address to check for delegate status. */
26456
+ delegateAddress: string;
26034
26457
  /**
26035
- * The amount of tokens to deposit (human-readable decimal string).
26036
- *
26037
- * @example "100", "0.5"
26038
- */
26039
- amount: string;
26040
- /**
26041
- * The token to deposit.
26458
+ * The token for which delegation is checked.
26042
26459
  * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26043
26460
  *
26044
26461
  * @defaultValue 'USDC'
26045
26462
  */
26046
26463
  token?: SupportedTokenInput;
26047
- /**
26048
- * The token allowance strategy to authorize the deposit.
26049
- *
26050
- * @defaultValue 'authorize'
26051
- */
26052
- allowanceStrategy?: AllowanceStrategy;
26053
26464
  }
26465
+
26054
26466
  /**
26055
- * Parameters for depositing tokens into *another* Gateway account.
26467
+ * Parameters for initiating a delayed recovery fund removal from a Gateway
26468
+ * account.
26056
26469
  *
26057
26470
  * @remarks
26058
- * Extends `DepositParams` with a `depositAccount` field that
26059
- * specifies the Gateway account to credit instead of the caller's
26060
- * own account. The Gateway contract only supports approval-based
26061
- * deposit-for (no permit/authorize); allowance strategy is not
26062
- * configurable and is not part of this type.
26471
+ * Use fund removal only as a trustless fallback when the normal spend flow is
26472
+ * unavailable. For day-to-day movement out of a Unified Balance, use `spend`.
26473
+ *
26474
+ * Fund removals have a mandatory 7-day delay before they can be
26475
+ * completed. Only one removal may be pending per chain at a
26476
+ * time. Initiating a second removal on the same chain adds the
26477
+ * requested amount to the existing pending removal and restarts
26478
+ * the 7-day timer.
26063
26479
  *
26064
26480
  * @typeParam TAdapterCapabilities - Adapter capability constraints.
26065
26481
  * @typeParam TChainIdentifier - Accepted chain identifier type.
26066
26482
  *
26067
26483
  * @example
26068
26484
  * ```typescript
26069
- * import type { DepositForParams } from '@circle-fin/unified-balance-kit'
26485
+ * import type { InitiateRemoveFundParams } from '@circle-fin/unified-balance-kit'
26070
26486
  *
26071
- * const params: DepositForParams = {
26487
+ * const params: InitiateRemoveFundParams = {
26072
26488
  * from: { adapter: evmAdapter, chain: 'Ethereum' },
26073
26489
  * amount: '100',
26074
- * token: 'USDC',
26075
- * depositAccount: '0x1234…abcd',
26076
26490
  * }
26077
26491
  * ```
26078
26492
  */
26079
- interface DepositForParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> extends Omit<DepositParams<TAdapterCapabilities, TChainIdentifier>, 'allowanceStrategy'> {
26493
+ interface InitiateRemoveFundParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26080
26494
  /**
26081
- * The Gateway account address to credit with the deposit.
26082
- *
26083
- * When provided the deposit is credited to this account rather
26084
- * than the caller's own.
26495
+ * The account owner's adapter context identifying the account,
26496
+ * chain, and address.
26085
26497
  */
26086
- depositAccount: string;
26087
- }
26088
- /**
26089
- * Result returned after a successful deposit operation.
26090
- *
26091
- * @example
26092
- * ```typescript
26093
- * import type { DepositResult } from '@circle-fin/unified-balance-kit'
26498
+ from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26499
+ /** The amount to remove (human-readable decimal string). */
26500
+ amount: string;
26501
+ /**
26502
+ * The token to remove.
26503
+ * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26504
+ * @defaultValue 'USDC'
26505
+ */
26506
+ token?: SupportedTokenInput;
26507
+ }
26508
+ /**
26509
+ * Result returned after successfully initiating a fund removal.
26094
26510
  *
26095
- * const result: DepositResult = {
26511
+ * @example
26512
+ * ```typescript
26513
+ * import type { InitiateRemoveFundResult } from '@circle-fin/unified-balance-kit'
26514
+ *
26515
+ * const result: InitiateRemoveFundResult = {
26096
26516
  * amount: '100',
26097
26517
  * token: 'USDC',
26098
- * depositedTo: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD38',
26099
- * depositedBy: '0x8ba1f109551bD432803012645632213Ab0521A3c',
26518
+ * account: '0xOWNER…1234',
26100
26519
  * chain: 'Ethereum',
26101
- * txHash:
26102
- * '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3',
26103
- * explorerUrl:
26104
- * 'https://etherscan.io/tx/0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3',
26520
+ * withdrawingBalance: '100',
26521
+ * withdrawalBlock: 19_500_000,
26522
+ * txHash: '0xabc…',
26523
+ * explorerUrl: 'https://etherscan.io/tx/0xabc…',
26105
26524
  * }
26106
26525
  * ```
26107
26526
  */
26108
- interface DepositResult {
26109
- /** The deposited amount (human-readable decimal string). */
26527
+ interface InitiateRemoveFundResult {
26528
+ /** The amount requested for removal. */
26110
26529
  amount: string;
26111
- /** The token that was deposited. */
26530
+ /** The token type (always USDC). */
26112
26531
  token: SupportedToken;
26113
- /** The Gateway account address credited by the deposit. */
26114
- depositedTo: string;
26115
- /** The address that signed and funded the deposit. */
26116
- depositedBy: string;
26117
- /** The chain on which the deposit occurred. */
26532
+ /** The Gateway account from which this removal will occur. */
26533
+ account: string;
26534
+ /** The chain on which this removal was initiated. */
26118
26535
  chain: Blockchain;
26536
+ /** The balance currently in the withdrawing state for this account. */
26537
+ withdrawingBalance: string;
26538
+ /** The block number at which the removal can be completed. */
26539
+ withdrawalBlock: number;
26119
26540
  /**
26120
26541
  * Unique identifier returned by the blockchain once the
26121
26542
  * transaction is mined.
@@ -26131,623 +26552,818 @@ interface DepositResult {
26131
26552
  */
26132
26553
  explorerUrl?: string;
26133
26554
  }
26134
-
26135
- /**
26136
- * Network type for balance queries when the target chain(s) are not
26137
- * explicitly specified. Default is mainnet.
26138
- */
26139
- type NetworkType = 'mainnet' | 'testnet';
26140
26555
  /**
26141
- * A single balance source identifying an account to query.
26142
- *
26143
- * Provide **at least one** of `adapter` or `address`:
26556
+ * Parameters for completing a recovery fund removal after the withdrawal
26557
+ * delay.
26144
26558
  *
26145
- * - **Address only** — pass `address` without `adapter` to query by
26146
- * raw Gateway account address.
26147
- * - **Adapter (user-controlled)** pass `adapter` without `address`;
26148
- * the wallet address is resolved automatically.
26149
- * - **Adapter (developer-controlled)** — pass both `adapter` and
26150
- * `address`; the explicit address is required because there is no
26151
- * single connected wallet.
26559
+ * @remarks
26560
+ * Use fund removal only as a trustless fallback when the normal spend flow is
26561
+ * unavailable. For day-to-day movement out of a Unified Balance, use `spend`.
26152
26562
  *
26153
26563
  * @typeParam TAdapterCapabilities - Adapter capability constraints.
26564
+ * @typeParam TChainIdentifier - Accepted chain identifier type.
26154
26565
  *
26155
26566
  * @example
26156
26567
  * ```typescript
26157
- * import type { BalanceSource } from '@circle-fin/unified-balance-kit'
26158
- *
26159
- * // Address-only (no adapter needed)
26160
- * const addrSource: BalanceSource = {
26161
- * address: '0x1234…abcd',
26162
- * chains: ['Ethereum', 'Base'],
26163
- * }
26164
- *
26165
- * // Adapter (user-controlled wallet)
26166
- * const adapterSource: BalanceSource = {
26167
- * adapter: evmAdapter,
26168
- * chains: 'Ethereum',
26169
- * }
26568
+ * import type { RemoveFundParams } from '@circle-fin/unified-balance-kit'
26170
26569
  *
26171
- * // Adapter (developer-controlled) address required
26172
- * const devSource: BalanceSource = {
26173
- * adapter: circleWalletsAdapter,
26174
- * address: '0x1234…abcd',
26175
- * chains: ['Ethereum'],
26570
+ * const params: RemoveFundParams = {
26571
+ * from: { adapter: evmAdapter, chain: 'Ethereum' },
26176
26572
  * }
26177
26573
  * ```
26178
26574
  */
26179
- interface BalanceSource<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
26180
- /** The adapter whose resolved address is used to fetch balances. */
26181
- adapter?: Adapter<TAdapterCapabilities>;
26575
+ interface RemoveFundParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26182
26576
  /**
26183
- * The account address to query balances for.
26184
- *
26185
- * - Required when no `adapter` is provided (address-only query).
26186
- * - Required for developer-controlled adapters.
26187
- * - Must be omitted for user-controlled adapters (auto-resolved).
26577
+ * The account owner's adapter context. Must match the one
26578
+ * used when initiating the fund removal.
26188
26579
  */
26189
- address?: string;
26580
+ from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26190
26581
  /**
26191
- * Chains to fetch balances from.
26582
+ * The token to remove.
26583
+ * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26192
26584
  *
26193
- * - If omitted, get balances from all supported chains.
26194
- * - If provided, only get balances for the specified chain(s).
26585
+ * @defaultValue 'USDC'
26195
26586
  */
26196
- chains?: UnifiedBalanceChainIdentifier | UnifiedBalanceChainIdentifier[];
26587
+ token?: SupportedTokenInput;
26197
26588
  }
26198
26589
  /**
26199
- * Accept a single item or an array of items of the same type.
26200
- *
26201
- * @typeParam T - The element type.
26202
- */
26203
- type OneOrMany<T> = T | T[];
26204
- /**
26205
- * One or more balance sources, each of which may be a single object
26206
- * or an array.
26207
- */
26208
- type Sources<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = OneOrMany<BalanceSource<TAdapterCapabilities>>;
26209
- /**
26210
- * Parameters for the balances and pending-deposits API requests.
26211
- *
26212
- * Specify the `token` to query and one or more `sources` identifying
26213
- * the accounts or adapters whose balances should be retrieved.
26214
- * When `includePending` is true, the result includes pending balances
26215
- * and pending transaction details per chain.
26590
+ * Result returned after successfully completing a fund removal.
26216
26591
  *
26217
26592
  * @example
26218
26593
  * ```typescript
26219
- * import type { GetBalancesParams } from '@circle-fin/unified-balance-kit'
26220
- *
26221
- * // Single adapter source
26222
- * const params1: GetBalancesParams = {
26223
- * token: 'USDC',
26224
- * sources: { adapter: evmAdapter },
26225
- * }
26226
- *
26227
- * // Single address source with pending
26228
- * const params2: GetBalancesParams = {
26229
- * token: 'USDC',
26230
- * sources: { address: '0x1234…abcd', chains: 'Ethereum' },
26231
- * includePending: true,
26232
- * }
26233
- *
26234
- * // Multiple address sources
26235
- * const params3: GetBalancesParams = {
26236
- * token: 'USDC',
26237
- * sources: [
26238
- * { address: '0x8f3Cf7…', chains: ['ChainA', 'ChainB'] },
26239
- * { address: '0x4B0897…', chains: ['ChainB', 'ChainC'] },
26240
- * ],
26241
- * }
26594
+ * import type { RemoveFundResult } from '@circle-fin/unified-balance-kit'
26242
26595
  *
26243
- * // Adapter only (confirmed balances only; includePending defaults to false)
26244
- * const params4: GetBalancesParams = {
26596
+ * const result: RemoveFundResult = {
26597
+ * amount: '100',
26245
26598
  * token: 'USDC',
26246
- * sources: { adapter: evmAdapter },
26599
+ * account: '0xOWNER…1234',
26600
+ * chain: 'Ethereum',
26601
+ * txHash: '0xdef…',
26602
+ * explorerUrl: 'https://etherscan.io/tx/0xdef…',
26247
26603
  * }
26248
26604
  * ```
26249
26605
  */
26250
- interface GetBalancesParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
26251
- /**
26252
- * The token to query balances for.
26253
- * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26254
- *
26255
- * @defaultValue 'USDC'
26256
- */
26257
- token?: SupportedTokenInput;
26606
+ interface RemoveFundResult {
26607
+ /** The final removed amount. */
26608
+ amount: string;
26609
+ /** The token type (always USDC). */
26610
+ token: SupportedToken;
26611
+ /** The Gateway account from which the tokens were removed. */
26612
+ account: string;
26613
+ /** The chain on which the removal occurred. */
26614
+ chain: Blockchain;
26258
26615
  /**
26259
- * One or more sources identifying the accounts or adapters to
26260
- * query. Accepts a single object or an array.
26616
+ * Unique identifier returned by the blockchain once the
26617
+ * transaction is mined.
26261
26618
  */
26262
- sources: Sources<TAdapterCapabilities>;
26619
+ txHash: string;
26263
26620
  /**
26264
- * When true, the result includes pending balances.
26265
- * When false or omitted, only confirmed balances
26266
- * are returned.
26621
+ * Link to view the transaction details on the appropriate
26622
+ * blockchain explorer.
26267
26623
  *
26268
- * @defaultValue false
26624
+ * @remarks
26625
+ * May be `undefined` when the explorer URL cannot be resolved
26626
+ * for the chain.
26269
26627
  */
26270
- includePending?: boolean;
26628
+ explorerUrl?: string;
26629
+ }
26630
+
26631
+ /**
26632
+ * Options for filtering supported chains.
26633
+ */
26634
+ interface GetSupportedChainsOptions {
26271
26635
  /**
26272
- * Network to use when no chains are specified on a source.
26273
- * When omitted, mainnet is used when chains cannot be derived.
26636
+ * Filter chains by forwarder support. When set, only chains whose
26637
+ * `gateway.forwarderSupported.source` or `gateway.forwarderSupported.destination`
26638
+ * matches the specified value are returned.
26274
26639
  *
26275
- * @defaultValue 'mainnet'
26640
+ * - `undefined` (default) — no forwarder filtering; all supported chains are returned.
26641
+ * - `'source'` — only chains that support forwarding as a source.
26642
+ * - `'destination'` — only chains that support forwarding as a destination.
26276
26643
  */
26277
- networkType?: NetworkType;
26644
+ forwarderSupported?: 'source' | 'destination';
26278
26645
  }
26646
+
26279
26647
  /**
26280
- * A pending transaction included in {@link GetBalancesResult}
26281
- * when `includePending` is true.
26282
- *
26283
- * @example
26284
- * ```typescript
26285
- * import type { PendingBalanceTransaction } from '@circle-fin/unified-balance-kit'
26648
+ * A custom token contract address string.
26286
26649
  *
26287
- * const tx: PendingBalanceTransaction = {
26288
- * transactionHash: '0x2c5f3e4a…',
26289
- * amount: '50.00',
26290
- * blockTimestamp: '2023-11-07T05:31:56Z',
26291
- * }
26292
- * ```
26650
+ * This type represents token addresses that are not known aliases.
26651
+ * It uses a branded type pattern to preserve IDE autocomplete for TokenAlias
26652
+ * while still accepting arbitrary address strings.
26293
26653
  */
26294
- interface PendingBalanceTransaction {
26295
- /** Transaction hash of the pending deposit. */
26296
- transactionHash: string;
26297
- /** Pending amount (human-readable decimal string). */
26298
- amount: string;
26299
- /** ISO 8601 timestamp of the block. */
26300
- blockTimestamp: string;
26301
- }
26654
+ type TokenAddress = string & {
26655
+ readonly __tokenAddress?: never;
26656
+ };
26302
26657
  /**
26303
- * Per-chain balance within a breakdown in {@link GetBalancesResult}.
26304
- *
26305
- * When `includePending` is true, `pendingBalance` and `pendingTransactions`
26306
- * are present.
26658
+ * Known token aliases supported by AppKit.
26307
26659
  *
26308
- * @example
26309
- * ```typescript
26310
- * import type { ChainBalanceBreakdown } from '@circle-fin/unified-balance-kit'
26660
+ * These aliases map to chain-specific token addresses. `USDC`, `USDT`, and
26661
+ * `NATIVE` have dedicated transfer actions in the adapter layer. `EURC` has no
26662
+ * dedicated action it resolves to the chain's `eurcAddress` and is sent via
26663
+ * the generic token transfer action, so it is only supported on chains where
26664
+ * `eurcAddress` is set.
26311
26665
  *
26312
- * // Confirmed only (includePending: false)
26313
- * const chain: ChainBalanceBreakdown = {
26314
- * chain: 'Arbitrum',
26315
- * confirmedBalance: '1500.00',
26316
- * }
26317
- *
26318
- * // With pending (includePending: true)
26319
- * const chainWithPending: ChainBalanceBreakdown = {
26320
- * chain: 'Ethereum',
26321
- * confirmedBalance: '1000.00',
26322
- * pendingBalance: '50.00',
26323
- * pendingTransactions: [
26324
- * { transactionHash: '0x2c5f3e…', amount: '50.00', blockTimestamp: '2023-11-07T05:31:56Z' },
26325
- * ],
26326
- * }
26327
- * ```
26666
+ * @remarks
26667
+ * For swap operations, see {@link SupportedToken} in SwapKit which supports
26668
+ * additional tokens (DAI, USDE, PYUSD).
26328
26669
  */
26329
- interface ChainBalanceBreakdown {
26330
- /** The chain. */
26331
- chain: Blockchain;
26332
- /** Confirmed balance (human-readable decimal string). */
26333
- confirmedBalance: string;
26334
- /**
26335
- * Pending balance on this chain.
26336
- * Present only when {@link GetBalancesParams.includePending} is true.
26337
- */
26338
- pendingBalance?: string;
26339
- /**
26340
- * Pending deposit transactions on this chain.
26341
- * Present only when {@link GetBalancesParams.includePending} is true.
26342
- */
26343
- pendingTransactions?: PendingBalanceTransaction[];
26344
- }
26670
+ type TokenAlias = 'USDC' | 'USDT' | 'NATIVE' | 'EURC';
26345
26671
  /**
26346
- * Per-account balance breakdown used in {@link GetBalancesResult}.
26347
- *
26348
- * When `includePending` is true, `totalPending` is present and each chain
26349
- * entry may include `pendingBalance` and `pendingTransactions`.
26350
- *
26351
- * @example
26352
- * ```typescript
26353
- * import type { BalanceWithPendingBreakdown } from '@circle-fin/unified-balance-kit'
26672
+ * Operation types that support the `getFee`/`getFeeRecipient` hooks.
26673
+ */
26674
+ type FeeOperationType = 'bridge' | 'swap';
26675
+ /**
26676
+ * Union type of all supported operation types in the AppKit.
26354
26677
  *
26355
- * const entry: BalanceWithPendingBreakdown = {
26356
- * depositor: '0x71C765…',
26357
- * totalConfirmed: '1000.00',
26358
- * totalPending: '50.00',
26359
- * breakdown: [
26360
- * { chain: 'Ethereum', confirmedBalance: '1000.00', pendingBalance: '50.00', pendingTransactions: [...] },
26361
- * ],
26362
- * }
26363
- * ```
26678
+ * This type ensures type safety when specifying operation types and enables
26679
+ * proper parameter validation based on the selected operation.
26364
26680
  */
26365
- interface BalanceWithPendingBreakdown {
26366
- /** Gateway account (depositor) address. */
26367
- depositor: string;
26368
- /** Total confirmed balance across chains (human-readable decimal string). */
26369
- totalConfirmed: string;
26370
- /**
26371
- * Total pending balance across chains.
26372
- * Present only when `includePending` is true.
26373
- */
26374
- totalPending?: string;
26375
- /** Per-chain breakdown for this depositor. */
26376
- breakdown: ChainBalanceBreakdown[];
26377
- }
26681
+ type OperationType = FeeOperationType | 'earn' | 'unifiedBalance';
26378
26682
  /**
26379
- * Result returned from the provider's `getBalances` method (combined confirmed and pending).
26683
+ * Maps operation types to their corresponding parameter interfaces.
26380
26684
  *
26381
- * When `includePending` is false (default), only `totalConfirmedBalance` and
26382
- * `breakdown` with confirmed fields are returned. When `includePending` is true,
26383
- * `totalPendingBalance` is present and breakdown entries include pending amounts
26384
- * and `pendingTransactions` per chain.
26685
+ * This interface maps operation types to their parameter structures for
26686
+ * compile-time validation in shared AppKit helpers.
26687
+ *
26688
+ * @remarks `earn` is included so consumers can refer to the full EarnKit
26689
+ * operation-parameter union through AppKit types. Developer fee hooks
26690
+ * intentionally use {@link FeeOperationType}, so they do not accept earn
26691
+ * parameters until EarnKit supports fee-bearing requests.
26385
26692
  *
26386
26693
  * @example
26387
26694
  * ```typescript
26388
- * import type { GetBalancesResult } from '@circle-fin/unified-balance-kit'
26389
- *
26390
- * // includePending: false
26391
- * const result: GetBalancesResult = {
26392
- * token: 'USDC',
26393
- * totalConfirmedBalance: '3500.00',
26394
- * breakdown: [
26395
- * {
26396
- * depositor: '0xAAAd67…',
26397
- * totalConfirmed: '2500.00',
26398
- * breakdown: [
26399
- * { chain: 'Arbitrum', confirmedBalance: '1500.00' },
26400
- * { chain: 'Optimism', confirmedBalance: '1000.00' },
26401
- * ],
26402
- * },
26403
- * ],
26404
- * }
26405
- *
26406
- * // includePending: true
26407
- * const resultWithPending: GetBalancesResult = {
26408
- * token: 'USDC',
26409
- * totalConfirmedBalance: '3500.00',
26410
- * totalPendingBalance: '650.00',
26411
- * breakdown: [
26412
- * {
26413
- * depositor: '0x71C765…',
26414
- * totalConfirmed: '1000.00',
26415
- * totalPending: '50.00',
26416
- * breakdown: [
26417
- * {
26418
- * chain: 'Ethereum',
26419
- * confirmedBalance: '1000.00',
26420
- * pendingBalance: '50.00',
26421
- * pendingTransactions: [
26422
- * { transactionHash: '0x2c5f3e…', amount: '50.00', blockTimestamp: '2023-11-07T05:31:56Z' },
26423
- * ],
26424
- * },
26425
- * ],
26426
- * },
26427
- * ],
26428
- * }
26695
+ * // TypeScript will enforce that bridge operations use BridgeParams
26696
+ * type BridgeParamsType = OperationParamsMap['bridge'] // BridgeParams
26697
+ * // TypeScript will enforce that swap operations use SwapParams
26698
+ * type SwapParamsType = OperationParamsMap['swap'] // SwapParams
26699
+ * // TypeScript will enforce that earn operations use EarnOperationParams
26700
+ * type EarnParamsType = OperationParamsMap['earn'] // EarnOperationParams
26429
26701
  * ```
26430
26702
  */
26431
- interface GetBalancesResult {
26432
- /** Token that was queried. */
26433
- token: SupportedToken;
26434
- /** Total confirmed balance across all accounts and chains (human-readable decimal string). */
26435
- totalConfirmedBalance: string;
26436
- /**
26437
- * Total pending balance across all accounts and chains.
26438
- * Present only when `includePending` is true.
26439
- */
26440
- totalPendingBalance?: string;
26441
- /** Per-account, per-chain breakdown. */
26442
- breakdown: BalanceWithPendingBreakdown[];
26703
+ interface OperationParamsMap {
26704
+ bridge: BridgeParams;
26705
+ swap: SwapParams;
26706
+ earn: EarnOperationParams;
26443
26707
  }
26444
-
26445
26708
  /**
26446
- * Parameters for adding or removing a delegate on a Gateway account.
26447
- *
26448
- * @remarks
26449
- * Delegation allows a different signer to move funds out of the
26450
- * owner's account. The delegate must be added explicitly per chain.
26709
+ * Operation-scoped custom fee policies configured at the AppKit level.
26451
26710
  *
26452
- * @typeParam TAdapterCapabilities - Adapter capability constraints.
26453
- * @typeParam TChainIdentifier - Accepted chain identifier type.
26711
+ * Each property is optional so consumers can enable custom fees only for the
26712
+ * operation they use. AppKit forwards the supplied policy to the matching
26713
+ * underlying kit when that operation runs.
26454
26714
  *
26455
26715
  * @example
26456
26716
  * ```typescript
26457
- * import type { UpdateDelegateParams } from '@circle-fin/unified-balance-kit'
26458
- *
26459
- * const params: UpdateDelegateParams = {
26460
- * from: { adapter: evmAdapter, chain: 'Ethereum' },
26461
- * delegateAddress: '0xDELEGATE…1111',
26717
+ * const policy: AppKitCustomFeePolicy = {
26718
+ * bridge: {
26719
+ * computeFee: () => '1.00',
26720
+ * resolveFeeRecipientAddress: () => '0x1234567890123456789012345678901234567890',
26721
+ * },
26462
26722
  * }
26463
26723
  * ```
26464
26724
  */
26465
- interface UpdateDelegateParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26466
- /**
26467
- * The owner's adapter context identifying the account and chain
26468
- * to which the delegate will be authorized.
26469
- */
26470
- from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26471
- /**
26472
- * The address being added or removed as an authorized delegate.
26473
- */
26474
- delegateAddress: string;
26475
- /**
26476
- * The token for which delegation applies.
26477
- * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26478
- *
26479
- * @defaultValue 'USDC'
26480
- */
26481
- token?: SupportedTokenInput;
26725
+ interface AppKitCustomFeePolicy {
26726
+ /** Custom fee policy forwarded to BridgeKit bridge operations. */
26727
+ bridge?: CustomFeePolicy$2;
26728
+ /** Custom fee policy forwarded to SwapKit swap operations. */
26729
+ swap?: CustomFeePolicy$1;
26730
+ /** Custom fee policy forwarded to UnifiedBalanceKit spend operations. */
26731
+ unifiedBalance?: CustomFeePolicy;
26482
26732
  }
26483
26733
  /**
26484
- * Result returned after a successful add or remove delegate
26485
- * operation.
26734
+ * Operation name whose AppKit-level custom fee policy can be removed.
26486
26735
  *
26487
26736
  * @example
26488
26737
  * ```typescript
26489
- * import type { UpdateDelegateResult } from '@circle-fin/unified-balance-kit'
26490
- *
26491
- * const result: UpdateDelegateResult = {
26492
- * account: '0xOWNER…1234',
26493
- * delegateAddress: '0xDELEGATE…1111',
26494
- * chain: 'Ethereum',
26495
- * state: 'added',
26496
- * txHash: '0xabc…',
26497
- * explorerUrl: 'https://etherscan.io/tx/0xabc…',
26498
- * }
26738
+ * const operation: AppKitCustomFeePolicyScope = 'bridge'
26499
26739
  * ```
26500
26740
  */
26501
- interface UpdateDelegateResult {
26502
- /** The Gateway account that was modified. */
26503
- account: string;
26504
- /** The delegate address that was added or removed. */
26505
- delegateAddress: string;
26506
- /**
26507
- * The chain on which the delegate was updated.
26508
- *
26509
- * @remarks
26510
- * Delegates must be added explicitly per chain. You cannot
26511
- * authorize a delegate for all chains at once.
26512
- */
26513
- chain: Blockchain;
26514
- /** Whether the delegate was added or removed. */
26515
- state: 'added' | 'removed';
26516
- /**
26517
- * Unique identifier returned by the blockchain once the
26518
- * transaction is mined.
26519
- */
26520
- txHash: string;
26521
- /**
26522
- * Link to view the transaction details on the appropriate
26523
- * blockchain explorer.
26524
- *
26525
- * @remarks
26526
- * May be `undefined` when the explorer URL cannot be resolved
26527
- * for the chain.
26528
- */
26529
- explorerUrl?: string;
26530
- }
26741
+ type AppKitCustomFeePolicyScope = keyof AppKitCustomFeePolicy;
26531
26742
  /**
26532
- * The finality-aware status of a delegate on a Gateway account.
26743
+ * Context interface for the AppKit with strongly typed getFee method.
26533
26744
  *
26534
- * - `'none'` — not a delegate on-chain.
26535
- * - `'pending'` delegate set on-chain but Gateway hasn't finalized it yet;
26536
- * spend will fail until the status advances to `'ready'`.
26537
- * - `'ready'` — finalized at Gateway; spend will succeed.
26538
- */
26539
- type DelegateStatus = 'none' | 'pending' | 'ready';
26540
- /**
26541
- * Parameters for checking the delegate status of an address on a
26542
- * Gateway account.
26745
+ * This interface uses TypeScript function overloads to provide type-safe
26746
+ * parameter validation based on the operation type. Each operation type
26747
+ * maps to specific parameter types, ensuring compile-time safety and
26748
+ * excellent developer experience with full IntelliSense support.
26543
26749
  *
26544
- * @typeParam TAdapterCapabilities - Adapter capability constraints.
26545
- * @typeParam TChainIdentifier - Accepted chain identifier type.
26750
+ * The interface supports both direct operation-specific overloads and a
26751
+ * generic overload for advanced use cases while maintaining type safety.
26546
26752
  *
26547
26753
  * @example
26548
26754
  * ```typescript
26549
- * import type { GetDelegateStatusParams } from '@circle-fin/unified-balance-kit'
26550
- *
26551
- * const params: GetDelegateStatusParams = {
26552
- * from: { adapter: evmAdapter, chain: 'Ethereum' },
26553
- * delegateAddress: '0xDELEGATE…1111',
26554
- * }
26755
+ * // Bridge operation - uses BridgeParams
26756
+ * const bridgeFee = await context.getFee('bridge', {
26757
+ * from: { adapter: sourceAdapter, chain: 'Ethereum' },
26758
+ * to: { adapter: destAdapter, chain: 'Polygon' },
26759
+ * amount: '100.50'
26760
+ * })
26555
26761
  * ```
26556
26762
  */
26557
- interface GetDelegateStatusParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26558
- /** The adapter context identifying the account owner and chain. */
26559
- from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26560
- /** The address to check for delegate status. */
26561
- delegateAddress: string;
26763
+ interface AppKitContext {
26562
26764
  /**
26563
- * The token for which delegation is checked.
26564
- * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26765
+ * Get fee estimation for bridge or swap operations.
26565
26766
  *
26566
- * @defaultValue 'USDC'
26767
+ * Calculate the estimated fees for cross-chain bridge transfers, same-chain
26768
+ * token swaps. Returns the fee amount in smallest token units.
26769
+ *
26770
+ * The function signature uses TypeScript's generic constraint pattern to ensure
26771
+ * type safety: when type is 'bridge', params must be BridgeParams; when type
26772
+ * is 'swap', params must be SwapParams.
26773
+ *
26774
+ * @typeParam T - The fee operation type ('bridge' | 'swap')
26775
+ * @param type - Operation type: 'bridge' for cross-chain transfers, 'swap' for same-chain swaps
26776
+ * @param params - Operation-specific parameters matching the type
26777
+ * @returns Promise resolving to fee amount as string in smallest token units
26778
+ * @throws {@link ValidationError} If operation parameters are invalid
26779
+ * @throws {@link UnsupportedRouteError} If the operation route is not supported
26780
+ *
26781
+ * @example
26782
+ * ```typescript
26783
+ * // Bridge fee
26784
+ * const bridgeFee = await context.getFee?.('bridge', bridgeParams)
26785
+ *
26786
+ * // Swap fee
26787
+ * const swapFee = await context.getFee?.('swap', swapParams)
26788
+ *
26789
+ * // Generic usage
26790
+ * function estimateFee<T extends FeeOperationType>(
26791
+ * operation: T,
26792
+ * params: OperationParamsMap[T]
26793
+ * ) {
26794
+ * return context.getFee(operation, params) // Fully type-safe
26795
+ * }
26796
+ * ```
26567
26797
  */
26568
- token?: SupportedTokenInput;
26798
+ getFee?<T extends FeeOperationType>(type: T, params: OperationParamsMap[T]): Promise<string>;
26799
+ /**
26800
+ * Get the fee recipient address for a specific operation and chain.
26801
+ *
26802
+ * This method returns the address that will receive protocol fees for
26803
+ * the specified operation type on the given chain. Useful for transparency
26804
+ * and fee tracking purposes.
26805
+ *
26806
+ * @remarks When this hook is used for bridging operations, the `params` object within `info` will be empty.
26807
+ * This is due to a limitation in the underlying `BridgeKit`, which does not provide bridge parameters
26808
+ * to its fee recipient hook.
26809
+ *
26810
+ * @typeParam T - The fee operation type ('bridge' | 'swap')
26811
+ * @param type - The specific operation type
26812
+ * @param info - Object containing chain and parameter information
26813
+ * @returns Promise resolving to the fee recipient address
26814
+ * @throws {@link ValidationError} If parameters are invalid
26815
+ * @throws {@link UnsupportedChainError} If the chain is not supported
26816
+ *
26817
+ * @example
26818
+ * ```typescript
26819
+ * const recipient = await context.getFeeRecipient('bridge', {
26820
+ * chain: ethereumChain,
26821
+ * params: bridgeParams
26822
+ * })
26823
+ * ```
26824
+ */
26825
+ getFeeRecipient?<T extends FeeOperationType>(type: T, info: {
26826
+ chain: ChainDefinition;
26827
+ params: OperationParamsMap[T];
26828
+ }): Promise<string>;
26829
+ /**
26830
+ * Operation-scoped custom fee policies.
26831
+ *
26832
+ * Prefer {@link AppKit.setCustomFeePolicy} for runtime configuration. This
26833
+ * context property is read by the internal kit factories when AppKit creates
26834
+ * BridgeKit and SwapKit instances for each operation.
26835
+ */
26836
+ customFeePolicy?: AppKitCustomFeePolicy;
26837
+ /**
26838
+ * Event handlers registered for AppKit operations.
26839
+ *
26840
+ * This property stores event handlers that are registered via the AppKit's
26841
+ * `on()` method. Handlers are grouped by operation type. The runtime buckets
26842
+ * are `bridge` and `earn`; the context can add more operation buckets as
26843
+ * AppKit wires action handlers for additional kits.
26844
+ *
26845
+ * Within each operation bucket, handlers are keyed by action name (for
26846
+ * example, `bridge.approve` or `earn.deposit`) or `*` for wildcard handlers.
26847
+ * Each action can have multiple handlers registered, allowing multiple
26848
+ * subscribers to listen to the same event.
26849
+ *
26850
+ * The handlers are stored in the context to allow deferred registration with
26851
+ * underlying operation kits, enabling a clean separation between event
26852
+ * registration and operation execution.
26853
+ *
26854
+ * @example
26855
+ * ```typescript
26856
+ * const context = createContext()
26857
+ * // Handlers registered via kit.on() are stored by operation type
26858
+ * // Bridge handlers are registered with BridgeKit when bridge() runs
26859
+ * // Earn handlers are registered with EarnKit when earn operations run
26860
+ * ```
26861
+ */
26862
+ actions: Record<'bridge' | 'earn', Record<string, ((payload: unknown) => void)[]>>;
26863
+ /**
26864
+ * Disable success analytics for the underlying EarnKit, SwapKit, and
26865
+ * UnifiedBalanceKit.
26866
+ *
26867
+ * When `true`, completed earn, swap, and unified balance operations will not
26868
+ * POST analytics events. This does not disable error reporting; use
26869
+ * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
26870
+ *
26871
+ * @defaultValue false
26872
+ */
26873
+ disableAnalytics?: boolean;
26874
+ /**
26875
+ * Disable error telemetry for all sub-kits.
26876
+ *
26877
+ * When `true`, none of the underlying kits (BridgeKit, SwapKit, EarnKit,
26878
+ * UnifiedBalanceKit) will POST error details to the telemetry
26879
+ * endpoint when operations throw. Defaults to `false` (enabled).
26880
+ *
26881
+ * @defaultValue false
26882
+ */
26883
+ disableErrorReporting?: boolean;
26884
+ /**
26885
+ * Custom HTTP headers forwarded with the underlying CCTP provider's
26886
+ * attestation (Iris) API requests made by bridge operations.
26887
+ *
26888
+ * @remarks
26889
+ * Headers are merged on top of the SDK defaults (such as `Content-Type`)
26890
+ * rather than replacing them. The header is forwarded as-is to Circle's API;
26891
+ * the SDK does not interpret it.
26892
+ */
26893
+ headers?: Record<string, string>;
26569
26894
  }
26570
-
26571
26895
  /**
26572
- * Parameters for initiating a delayed recovery fund removal from a Gateway
26573
- * account.
26574
- *
26575
- * @remarks
26576
- * Use fund removal only as a trustless fallback when the normal spend flow is
26577
- * unavailable. For day-to-day movement out of a Unified Balance, use `spend`.
26578
- *
26579
- * Fund removals have a mandatory 7-day delay before they can be
26580
- * completed. Only one removal may be pending per chain at a
26581
- * time. Initiating a second removal on the same chain adds the
26582
- * requested amount to the existing pending removal and restarts
26583
- * the 7-day timer.
26896
+ * Earn operation namespace exposed as `kit.earn`.
26584
26897
  *
26585
- * @typeParam TAdapterCapabilities - Adapter capability constraints.
26586
- * @typeParam TChainIdentifier - Accepted chain identifier type.
26898
+ * Mirrors the operations currently available from `@circle-fin/earn-kit`.
26899
+ * Step events use the AppKit event API (`kit.on('earn.*')` / `kit.on('*')`).
26587
26900
  *
26588
26901
  * @example
26589
26902
  * ```typescript
26590
- * import type { InitiateRemoveFundParams } from '@circle-fin/unified-balance-kit'
26903
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
26591
26904
  *
26592
- * const params: InitiateRemoveFundParams = {
26593
- * from: { adapter: evmAdapter, chain: 'Ethereum' },
26594
- * amount: '100',
26595
- * }
26905
+ * const kit = new AppKit()
26906
+ *
26907
+ * const result = await kit.earn.deposit({
26908
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
26909
+ * vaultAddress: '0x...',
26910
+ * amount: '100.50',
26911
+ * })
26596
26912
  * ```
26597
26913
  */
26598
- interface InitiateRemoveFundParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26914
+ interface AppKitEarnOperations {
26599
26915
  /**
26600
- * The account owner's adapter context identifying the account,
26601
- * chain, and address.
26916
+ * Deposit into an earn vault.
26917
+ *
26918
+ * @param params - Deposit parameters
26919
+ * @returns Promise resolving to the deposit result
26920
+ * @throws If validation, provider lookup, or transaction execution fails
26921
+ *
26922
+ * @example
26923
+ * ```typescript
26924
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
26925
+ *
26926
+ * const kit = new AppKit()
26927
+ * const result = await kit.earn.deposit({
26928
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
26929
+ * vaultAddress: '0x...',
26930
+ * amount: '100.50',
26931
+ * })
26932
+ * ```
26602
26933
  */
26603
- from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26604
- /** The amount to remove (human-readable decimal string). */
26605
- amount: string;
26934
+ deposit<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: SameChainDepositParams<TFromAdapterCapabilities>): Promise<EarnSameChainDepositResult>;
26606
26935
  /**
26607
- * The token to remove.
26608
- * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26609
- * @defaultValue 'USDC'
26936
+ * Deposit into an earn vault from another chain through the bridge flow.
26937
+ *
26938
+ * @param params - Cross-chain deposit parameters
26939
+ * @returns Promise resolving to the bridge submission details
26940
+ * @throws If validation, provider lookup, or the bridge flow fails
26610
26941
  */
26611
- token?: SupportedTokenInput;
26612
- }
26613
- /**
26614
- * Result returned after successfully initiating a fund removal.
26615
- *
26616
- * @example
26617
- * ```typescript
26618
- * import type { InitiateRemoveFundResult } from '@circle-fin/unified-balance-kit'
26619
- *
26620
- * const result: InitiateRemoveFundResult = {
26621
- * amount: '100',
26622
- * token: 'USDC',
26623
- * account: '0xOWNER…1234',
26624
- * chain: 'Ethereum',
26625
- * withdrawingBalance: '100',
26626
- * withdrawalBlock: 19_500_000,
26627
- * txHash: '0xabc…',
26628
- * explorerUrl: 'https://etherscan.io/tx/0xabc…',
26629
- * }
26630
- * ```
26631
- */
26632
- interface InitiateRemoveFundResult {
26633
- /** The amount requested for removal. */
26634
- amount: string;
26635
- /** The token type (always USDC). */
26636
- token: SupportedToken;
26637
- /** The Gateway account from which this removal will occur. */
26638
- account: string;
26639
- /** The chain on which this removal was initiated. */
26640
- chain: Blockchain;
26641
- /** The balance currently in the withdrawing state for this account. */
26642
- withdrawingBalance: string;
26643
- /** The block number at which the removal can be completed. */
26644
- withdrawalBlock: number;
26942
+ deposit<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: CrossChainDepositParams<TFromAdapterCapabilities>): Promise<EarnCrossChainDepositResult>;
26645
26943
  /**
26646
- * Unique identifier returned by the blockchain once the
26647
- * transaction is mined.
26944
+ * Deposit into an earn vault, on the same chain or cross-chain.
26945
+ *
26946
+ * @param params - Deposit parameters
26947
+ * @returns Promise resolving to same-chain transaction details or
26948
+ * cross-chain submission details
26949
+ * @throws If validation, provider lookup, or execution fails
26648
26950
  */
26649
- txHash: string;
26951
+ deposit<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: AnyDepositParams<TFromAdapterCapabilities>): Promise<EarnDepositOutcome>;
26650
26952
  /**
26651
- * Link to view the transaction details on the appropriate
26652
- * blockchain explorer.
26953
+ * Withdraw from an earn vault.
26954
+ *
26955
+ * @param params - Withdrawal parameters
26956
+ * @returns Promise resolving to the withdrawal result
26957
+ * @throws If validation, provider lookup, or transaction execution fails
26958
+ *
26959
+ * @example
26960
+ * ```typescript
26961
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
26962
+ *
26963
+ * const kit = new AppKit()
26964
+ * const result = await kit.earn.withdraw({
26965
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
26966
+ * vaultAddress: '0x...',
26967
+ * amount: '50.00',
26968
+ * })
26969
+ * ```
26970
+ */
26971
+ withdraw<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: WithdrawParams<TFromAdapterCapabilities>): Promise<EarnWithdrawResult>;
26972
+ /**
26973
+ * Claim available earn rewards.
26974
+ *
26975
+ * @param params - Claim rewards parameters
26976
+ * @returns Promise resolving to the claim rewards result
26977
+ * @throws If validation, provider lookup, or transaction execution fails
26978
+ *
26979
+ * @example
26980
+ * ```typescript
26981
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
26982
+ *
26983
+ * const kit = new AppKit()
26984
+ * const result = await kit.earn.claimRewards({
26985
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
26986
+ * vaultAddress: '0x...',
26987
+ * })
26988
+ * ```
26989
+ *
26990
+ * @internal
26991
+ */
26992
+ claimRewards<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: ClaimRewardsParams<TFromAdapterCapabilities>): Promise<EarnClaimRewardsResult>;
26993
+ /**
26994
+ * Fetch earn vault information.
26995
+ *
26996
+ * @param params - Vault query parameters
26997
+ * @returns Promise resolving to vault data and per-vault errors
26998
+ * @throws If validation or provider lookup fails
26999
+ *
27000
+ * @example
27001
+ * ```typescript
27002
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27003
+ *
27004
+ * const kit = new AppKit()
27005
+ * const result = await kit.earn.getVaults({
27006
+ * vaults: [{ chain: EarnChain.Arc_Testnet, vaultAddress: '0x...' }],
27007
+ * })
27008
+ * ```
27009
+ */
27010
+ getVaults(params: GetVaultsParams): Promise<EarnGetVaultsResult>;
27011
+ /**
27012
+ * Discover earn vaults available on a chain.
27013
+ *
27014
+ * @param params - Discovery parameters with chain and optional filters
27015
+ * @returns Promise resolving to matching vaults with pagination metadata
27016
+ * @throws If validation or provider lookup fails
27017
+ *
27018
+ * @example
27019
+ * ```typescript
27020
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27021
+ *
27022
+ * const kit = new AppKit()
27023
+ * const result = await kit.earn.exploreVaults({
27024
+ * chain: EarnChain.Arc_Testnet,
27025
+ * minApy: '0.03',
27026
+ * sortBy: 'apy',
27027
+ * })
27028
+ * ```
27029
+ */
27030
+ exploreVaults(params: ExploreVaultsParams): Promise<EarnExploreVaultsResult>;
27031
+ /**
27032
+ * Lazily iterate every earn vault available on a chain.
27033
+ *
27034
+ * @param params - Discovery parameters (no `page`; the iterator manages it)
27035
+ * @returns An async generator yielding each matching vault
27036
+ * @throws If validation or provider lookup fails
27037
+ *
27038
+ * @example
27039
+ * ```typescript
27040
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27041
+ *
27042
+ * const kit = new AppKit()
27043
+ * for await (const vault of kit.earn.exploreVaultsIterator({
27044
+ * chain: EarnChain.Arc_Testnet,
27045
+ * })) {
27046
+ * console.log(vault.name)
27047
+ * }
27048
+ * ```
27049
+ */
27050
+ exploreVaultsIterator(params: ExploreVaultsIteratorParams): AsyncGenerator<EarnVaultInfo, void, undefined>;
27051
+ /**
27052
+ * Fetch wallet position information for an earn vault.
27053
+ *
27054
+ * @param params - Position query parameters
27055
+ * @returns Promise resolving to position information
27056
+ * @throws If validation or provider lookup fails
27057
+ *
27058
+ * @example
27059
+ * ```typescript
27060
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27061
+ *
27062
+ * const kit = new AppKit()
27063
+ * const position = await kit.earn.getPosition({
27064
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
27065
+ * vaultAddress: '0x...',
27066
+ * })
27067
+ * ```
27068
+ */
27069
+ getPosition<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetPositionParams<TFromAdapterCapabilities>): Promise<EarnPositionInfo>;
27070
+ /**
27071
+ * Fetch the current status of a cross-chain Earn deposit.
27072
+ *
27073
+ * @param params - Status query parameters identifying the deposit by execId
27074
+ * @returns Promise resolving to the structured cross-chain deposit status
27075
+ * @throws If validation, provider lookup, or the status request fails
27076
+ */
27077
+ getCrossChainDepositStatus(params: GetCrossChainDepositStatusParams): Promise<EarnCrossChainDepositStatus>;
27078
+ /**
27079
+ * Poll a cross-chain Earn deposit until it reaches a terminal bridge state.
27080
+ *
27081
+ * @param params - Wait parameters including execId and optional polling knobs
27082
+ * @returns Promise resolving to the wait result and last observed bridge status
27083
+ * @throws If validation, provider lookup, or a status request fails
27084
+ */
27085
+ waitForCrossChainDeposit(params: WaitForCrossChainDepositParams): Promise<EarnCrossChainDepositWaitResult>;
27086
+ /**
27087
+ * Fetch a deposit quote.
27088
+ *
27089
+ * @param params - Deposit quote parameters
27090
+ * @returns Promise resolving to deposit quote information
27091
+ * @throws If validation or provider lookup fails
27092
+ *
27093
+ * @example
27094
+ * ```typescript
27095
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27096
+ *
27097
+ * const kit = new AppKit()
27098
+ * const quote = await kit.earn.getDepositQuote({
27099
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
27100
+ * vaultAddress: '0x...',
27101
+ * amount: '100.50',
27102
+ * })
27103
+ * ```
27104
+ */
27105
+ getDepositQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetDepositQuoteParams<TFromAdapterCapabilities>): Promise<EarnDepositQuoteInfo>;
27106
+ /**
27107
+ * Fetch a withdrawal quote.
27108
+ *
27109
+ * @param params - Withdrawal quote parameters
27110
+ * @returns Promise resolving to withdrawal quote information
27111
+ * @throws If validation or provider lookup fails
27112
+ *
27113
+ * @example
27114
+ * ```typescript
27115
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27116
+ *
27117
+ * const kit = new AppKit()
27118
+ * const quote = await kit.earn.getWithdrawalQuote({
27119
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
27120
+ * vaultAddress: '0x...',
27121
+ * amount: '50.00',
27122
+ * })
27123
+ * ```
27124
+ */
27125
+ getWithdrawalQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetWithdrawalQuoteParams<TFromAdapterCapabilities>): Promise<EarnWithdrawalQuoteInfo>;
27126
+ /**
27127
+ * Fetch a claim rewards quote.
27128
+ *
27129
+ * @param params - Claim rewards quote parameters
27130
+ * @returns Promise resolving to claim rewards quote information
27131
+ * @throws If validation or provider lookup fails
27132
+ *
27133
+ * @example
27134
+ * ```typescript
27135
+ * import { AppKit, EarnChain } from '@circle-fin/app-kit'
27136
+ *
27137
+ * const kit = new AppKit()
27138
+ * const quote = await kit.earn.getClaimRewardsQuote({
27139
+ * from: { adapter, chain: EarnChain.Arc_Testnet },
27140
+ * vaultAddress: '0x...',
27141
+ * })
27142
+ * ```
27143
+ *
27144
+ * @internal
27145
+ */
27146
+ getClaimRewardsQuote<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: GetClaimRewardsQuoteParams<TFromAdapterCapabilities>): Promise<EarnClaimRewardsQuoteInfo>;
27147
+ /**
27148
+ * Resume a multi-phase earn operation that previously failed.
27149
+ *
27150
+ * Pass the {@link KitError} caught from `deposit`, `withdraw`, or
27151
+ * `claimRewards`. The error carries the original inputs and step
27152
+ * progress, so completed phases (for example a successful token
27153
+ * approval) can be skipped. Call `isRetryableError(error)` first.
27154
+ *
27155
+ * @remarks
27156
+ * Retry re-fetches execution params and may re-submit the execute
27157
+ * transaction. Treat this as best-effort recovery: if a prior attempt
27158
+ * broadcast execute but failed before observing the receipt, that
27159
+ * transaction may still be in flight.
27160
+ *
27161
+ * @param error - The error caught from a previous multi-phase earn operation
27162
+ * @returns Promise resolving to the result of the resumed operation
27163
+ * @throws If the error is not retryable or lacks earn retry context
27164
+ *
27165
+ * @example
27166
+ * ```typescript
27167
+ * import { AppKit, isRetryableError } from '@circle-fin/app-kit'
26653
27168
  *
26654
- * @remarks
26655
- * May be `undefined` when the explorer URL cannot be resolved
26656
- * for the chain.
27169
+ * const kit = new AppKit()
27170
+ *
27171
+ * try {
27172
+ * await kit.earn.deposit(params)
27173
+ * } catch (error) {
27174
+ * if (isRetryableError(error)) {
27175
+ * const result = await kit.earn.retry(error)
27176
+ * }
27177
+ * }
27178
+ * ```
26657
27179
  */
26658
- explorerUrl?: string;
27180
+ retry(error: unknown): Promise<EarnDepositOutcome | EarnWithdrawResult | EarnClaimRewardsResult>;
26659
27181
  }
26660
27182
  /**
26661
- * Parameters for completing a recovery fund removal after the withdrawal
26662
- * delay.
27183
+ * Type for event handler functions that can be registered with the AppKit.
26663
27184
  *
26664
- * @remarks
26665
- * Use fund removal only as a trustless fallback when the normal spend flow is
26666
- * unavailable. For day-to-day movement out of a Unified Balance, use `spend`.
27185
+ * This type extracts the handler function type from the `on` method parameters,
27186
+ * ensuring that event handlers have the correct signature and payload types.
27187
+ * It enables type-safe event handling by preserving the specific payload types
27188
+ * for each action.
26667
27189
  *
26668
- * @typeParam TAdapterCapabilities - Adapter capability constraints.
26669
- * @typeParam TChainIdentifier - Accepted chain identifier type.
27190
+ * Uses a structural type constraint to avoid circular dependencies while still
27191
+ * providing full type safety when used with an AppKit instance.
27192
+ *
27193
+ * @typeParam T - A type that has an `on` method matching AppKit's signature
27194
+ * @returns The function type for event handlers with proper payload typing
26670
27195
  *
26671
27196
  * @example
26672
27197
  * ```typescript
26673
- * import type { RemoveFundParams } from '@circle-fin/unified-balance-kit'
27198
+ * import { AppKit, ActionHandler } from '@circle-fin/app-kit'
26674
27199
  *
26675
- * const params: RemoveFundParams = {
26676
- * from: { adapter: evmAdapter, chain: 'Ethereum' },
27200
+ * const kit = new AppKit()
27201
+ *
27202
+ * // ActionHandler will be the correct function type for handlers
27203
+ * const handler: ActionHandler<typeof kit> = (payload) => {
27204
+ * // payload is properly typed based on the action
26677
27205
  * }
26678
27206
  * ```
26679
27207
  */
26680
- interface RemoveFundParams<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends UnifiedBalanceChainIdentifier = UnifiedBalanceChainIdentifier> {
26681
- /**
26682
- * The account owner's adapter context. Must match the one
26683
- * used when initiating the fund removal.
26684
- */
26685
- from: AdapterContext<TAdapterCapabilities, TChainIdentifier>;
26686
- /**
26687
- * The token to remove.
26688
- * Accepts any case (e.g. `'usdc'`, `'Usdc'`); normalised to uppercase internally.
26689
- *
26690
- * @defaultValue 'USDC'
26691
- */
26692
- token?: SupportedTokenInput;
26693
- }
27208
+ type ActionHandler<T extends {
27209
+ on: (action: string, handler: (payload: unknown) => void) => void;
27210
+ }> = Parameters<T['on']>[1];
26694
27211
  /**
26695
- * Result returned after successfully completing a fund removal.
27212
+ * Parameters for sending USDC, USDT, native tokens, or custom ERC-20/SPL tokens.
27213
+ *
27214
+ * This interface is the canonical input for send operations in App Kit. It supports
27215
+ * sending to either a destination {@link Adapter} (recipient derives from the adapter's
27216
+ * default account) or an explicit recipient `string` address.
27217
+ *
27218
+ * - The `from` field provides the source signing context and chain.
27219
+ * - The `to` field identifies the destination as an adapter or an explicit address.
27220
+ * - The `amount` field is a human-readable decimal string (for example, `'10.5'`).
27221
+ * - The `token` field selects the asset to move and defaults to `'USDC'`.
27222
+ *
27223
+ * @remarks
27224
+ * When `to` is a `string`, the address must be a valid address. When `to` is an
27225
+ * {@link Adapter}, the recipient is derived from the adapter's active account.
27226
+ *
27227
+ * The `token` field accepts both supported token aliases ('USDC', 'USDT', 'NATIVE', 'EURC') and custom token
27228
+ * contract addresses.
26696
27229
  *
26697
27230
  * @example
26698
27231
  * ```typescript
26699
- * import type { RemoveFundResult } from '@circle-fin/unified-balance-kit'
27232
+ * // Send USDC to a recipient adapter (address derived on-chain)
27233
+ * const params: SendParams = {
27234
+ * from: { adapter: sourceAdapter, chain: 'Ethereum' },
27235
+ * to: recipientAdapter,
27236
+ * amount: '10.5',
27237
+ * token: 'USDC'
27238
+ * }
26700
27239
  *
26701
- * const result: RemoveFundResult = {
26702
- * amount: '100',
26703
- * token: 'USDC',
26704
- * account: '0xOWNER…1234',
26705
- * chain: 'Ethereum',
26706
- * txHash: '0xdef…',
26707
- * explorerUrl: 'https://etherscan.io/tx/0xdef…',
27240
+ * // Send using a custom token address (DAI on Ethereum)
27241
+ * const paramsCustomToken: SendParams = {
27242
+ * from: { adapter: sourceAdapter, chain: 'Ethereum' },
27243
+ * to: '0x1234...abcd',
27244
+ * amount: '100.0',
27245
+ * token: '0x6B175474E89094C44Da98b954EedeAC495271d0F'
26708
27246
  * }
26709
27247
  * ```
26710
27248
  */
26711
- interface RemoveFundResult {
26712
- /** The final removed amount. */
26713
- amount: string;
26714
- /** The token type (always USDC). */
26715
- token: SupportedToken;
26716
- /** The Gateway account from which the tokens were removed. */
26717
- account: string;
26718
- /** The chain on which the removal occurred. */
26719
- chain: Blockchain;
27249
+ interface SendParams {
26720
27250
  /**
26721
- * Unique identifier returned by the blockchain once the
26722
- * transaction is mined.
27251
+ * The source adapter context (wallet and chain) for the transfer.
26723
27252
  */
26724
- txHash: string;
27253
+ from: AdapterContext;
26725
27254
  /**
26726
- * Link to view the transaction details on the appropriate
26727
- * blockchain explorer.
27255
+ * The destination for the transfer, supporting explicit or derived recipient addresses.
27256
+ */
27257
+ to: Adapter | string;
27258
+ /**
27259
+ * The amount to transfer.
27260
+ */
27261
+ amount: string;
27262
+ /**
27263
+ * The token to transfer. Defaults to 'USDC'.
27264
+ * If omitted, the provider will use 'USDC' by default.
26728
27265
  *
26729
- * @remarks
26730
- * May be `undefined` when the explorer URL cannot be resolved
26731
- * for the chain.
27266
+ * Supports both known aliases and custom token contract addresses:
27267
+ * - Known aliases: 'USDC', 'USDT', 'NATIVE', 'EURC' ('EURC' requires the
27268
+ * chain to have an `eurcAddress` configured)
27269
+ * - Custom token addresses: EVM addresses or Solana SPL token mint addresses
27270
+ *
27271
+ * @example
27272
+ * ```typescript
27273
+ * // Using an alias
27274
+ * token: 'USDC'
27275
+ *
27276
+ * // Using a custom ERC-20 address (DAI on Ethereum)
27277
+ * token: '0x6B175474E89094C44Da98b954EedeAC495271d0F'
27278
+ *
27279
+ * // Using a custom SPL token mint (Solana)
27280
+ * token: 'So11111111111111111111111111111111111111112'
27281
+ * ```
26732
27282
  */
26733
- explorerUrl?: string;
27283
+ token?: TokenAlias | TokenAddress;
26734
27284
  }
27285
+ /**
27286
+ * Extract action types from BridgeKit's actionDispatcher.
27287
+ *
27288
+ * This utility type extracts the action map type from a BridgeKit instance
27289
+ * by inspecting its actionDispatcher property.
27290
+ *
27291
+ * @typeParam T - The BridgeKit instance type
27292
+ */
27293
+ type ExtractBridgeKitActions<T extends BridgeKit> = T extends BridgeKit ? T['actionDispatcher'] extends Actionable<infer Actions> ? Actions : never : never;
27294
+ /**
27295
+ * Prefix action names with a namespace.
27296
+ *
27297
+ * Transforms an action map by prefixing all keys with the specified namespace.
27298
+ * For example, `{ approve: Payload }` becomes `{ 'bridge.approve': Payload }`.
27299
+ *
27300
+ * @typeParam Actions - The original action map
27301
+ * @typeParam Prefix - The prefix to apply (e.g., 'bridge')
27302
+ */
27303
+ type PrefixActions<Prefix extends string, Actions> = {
27304
+ [K in keyof Actions as K extends string ? `${Prefix}.${K}` : never]: Actions[K];
27305
+ };
27306
+ /**
27307
+ * Default BridgeKit instance type (no extra providers).
27308
+ */
27309
+ type DefaultBridgeKit = BridgeKit;
27310
+ /**
27311
+ * Extract actions from default BridgeKit.
27312
+ */
27313
+ type DefaultBridgeKitActions = ExtractBridgeKitActions<DefaultBridgeKit>;
27314
+ /**
27315
+ * Prefixed bridge actions for AppKit.
27316
+ *
27317
+ * All BridgeKit events are prefixed with 'bridge.' to namespace them
27318
+ * within the AppKit event system.
27319
+ */
27320
+ type AppKitBridgeActions = PrefixActions<'bridge', DefaultBridgeKitActions>;
27321
+ /**
27322
+ * Prefixed unified balance actions for AppKit.
27323
+ *
27324
+ * All UnifiedBalanceKit (Gateway) events are prefixed with 'unifiedBalance.'
27325
+ * to namespace them within the AppKit event system.
27326
+ */
27327
+ type AppKitUnifiedBalanceActions = PrefixActions<'unifiedBalance', GatewayV1Actions>;
27328
+ /**
27329
+ * Prefixed earn actions for AppKit.
27330
+ *
27331
+ * Earn step events are exposed under the `earn.` namespace (for example
27332
+ * `earn.deposit`, `earn.approve`, `earn.withdraw`) so they can be
27333
+ * subscribed to via `kit.on()` alongside bridge and unified balance
27334
+ * events.
27335
+ */
27336
+ type AppKitEarnActions = PrefixActions<'earn', EarnActions>;
27337
+ /**
27338
+ * Union of all AppKit action names.
27339
+ */
27340
+ type AppKitActionName = keyof AppKitBridgeActions | keyof AppKitUnifiedBalanceActions | keyof AppKitEarnActions;
27341
+ /**
27342
+ * All actions available in AppKit.
27343
+ */
27344
+ type AppKitActions = AppKitBridgeActions & AppKitUnifiedBalanceActions & AppKitEarnActions;
26735
27345
 
26736
27346
  /**
26737
- * Options for filtering supported chains.
27347
+ * Parameters for creating a AppKit context.
27348
+ *
27349
+ * This type allows partial customization of the context while ensuring
27350
+ * that all required properties have sensible defaults. Users can override
27351
+ * specific methods while keeping the rest intact. Action handler buckets
27352
+ * may also be supplied partially; missing buckets default to empty maps.
27353
+ *
27354
+ * @example
27355
+ * ```typescript
27356
+ * const customContext = createContext({
27357
+ * getFee: async (type, params) => {
27358
+ * // Custom fee calculation logic
27359
+ * return { totalFee: '0.05', networkFee: '0.05' }
27360
+ * }
27361
+ * })
27362
+ * ```
26738
27363
  */
26739
- interface GetSupportedChainsOptions {
26740
- /**
26741
- * Filter chains by forwarder support. When set, only chains whose
26742
- * `gateway.forwarderSupported.source` or `gateway.forwarderSupported.destination`
26743
- * matches the specified value are returned.
26744
- *
26745
- * - `undefined` (default) — no forwarder filtering; all supported chains are returned.
26746
- * - `'source'` — only chains that support forwarding as a source.
26747
- * - `'destination'` — only chains that support forwarding as a destination.
26748
- */
26749
- forwarderSupported?: 'source' | 'destination';
26750
- }
27364
+ type CreateContextParams = Omit<Partial<AppKitContext>, 'actions'> & {
27365
+ actions?: Partial<AppKitContext['actions']>;
27366
+ };
26751
27367
 
26752
27368
  /**
26753
27369
  * Namespace object that exposes UnifiedBalanceKit operations through AppKit.
@@ -27679,6 +28295,46 @@ declare class AppKit {
27679
28295
  * ```
27680
28296
  */
27681
28297
  getSupportedChains(operationType?: OperationType): ChainDefinition[];
28298
+ /**
28299
+ * Set operation-scoped custom fee policies.
28300
+ *
28301
+ * Configure custom fees for only the operations that need them. Bridge and
28302
+ * swap policies are forwarded to the underlying kits when those operations
28303
+ * run. Unified balance policies are applied immediately to the namespaced
28304
+ * Unified Balance Kit.
28305
+ *
28306
+ * @param policy - Partial custom fee policy grouped by operation.
28307
+ * @returns Nothing.
28308
+ * @throws \{KitError\} If `policy` or a provided operation policy is invalid.
28309
+ *
28310
+ * @example
28311
+ * ```typescript
28312
+ * kit.setCustomFeePolicy({
28313
+ * bridge: {
28314
+ * computeFee: () => '1.00',
28315
+ * resolveFeeRecipientAddress: () => '0x1234567890123456789012345678901234567890',
28316
+ * },
28317
+ * })
28318
+ * ```
28319
+ */
28320
+ setCustomFeePolicy(policy: AppKitCustomFeePolicy): void;
28321
+ /**
28322
+ * Remove an AppKit-level custom fee policy for one operation.
28323
+ *
28324
+ * Bridge and swap policies are removed from AppKit's persistent context so
28325
+ * future operations fall back to legacy fee hooks. Unified balance policies
28326
+ * are also removed from the namespaced Unified Balance Kit.
28327
+ *
28328
+ * @param operation - Operation whose custom fee policy should be removed.
28329
+ * @returns Nothing.
28330
+ * @throws \{KitError\} If `operation` is invalid.
28331
+ *
28332
+ * @example
28333
+ * ```typescript
28334
+ * kit.removeCustomFeePolicy('bridge')
28335
+ * ```
28336
+ */
28337
+ removeCustomFeePolicy(operation: AppKitCustomFeePolicyScope): void;
27682
28338
  /**
27683
28339
  * Register an event handler for a specific AppKit action.
27684
28340
  *
@@ -27881,5 +28537,5 @@ declare function isTokenAddress(token: string, chain: ChainDefinition): token is
27881
28537
  */
27882
28538
  declare function validateToken(token: string, chain: ChainDefinition): TokenValidationResult;
27883
28539
 
27884
- export { AppKit, AppKitUnifiedBalance, BalanceError, Blockchain, BridgeChain, EarnChain, EarnError, EarnKit, InputError, KitError, NetworkError, OnchainError, RateLimitError, RpcError, ServiceError, SwapChain, TOKEN_ALIASES, TransferSpeed, UnifiedBalanceChain, anyDepositParamsSchema, claimRewardsParamsSchema, createEarnKitContext, depositParamsSchema, claimRewards as earnClaimRewards, deposit as earnDeposit, exploreVaults as earnExploreVaults, exploreVaultsIterator as earnExploreVaultsIterator, getClaimRewardsQuote as earnGetClaimRewardsQuote, getCrossChainDepositStatus as earnGetCrossChainDepositStatus, getCrossChainDepositStatusOutcome as earnGetCrossChainDepositStatusOutcome, getDepositQuote as earnGetDepositQuote, getPosition as earnGetPosition, getSupportedChains as earnGetSupportedChains, getVaults as earnGetVaults, getWithdrawalQuote as earnGetWithdrawalQuote, waitForCrossChainDeposit as earnWaitForCrossChainDeposit, withdraw as earnWithdraw, exploreVaultsIteratorParamsSchema, exploreVaultsParamsSchema, getClaimRewardsQuoteParamsSchema, getCrossChainDepositStatusParamsSchema, getDepositQuoteParamsSchema, getErrorCode, getErrorMessage, getPositionParamsSchema, getTokenDecimals, getVaultsParamsSchema, getWithdrawalQuoteParamsSchema, isBalanceError, isFatalError, isInputError, isKitError, isNetworkError, isOnchainError, isRateLimitError, isRetryableError, isRpcError, isServiceError, isTerminalCrossChainDepositStatus as isTerminalEarnCrossChainDepositStatus, isTokenAddress, isTokenAlias, isUserCancellationError, setExternalPrefix, validateToken, waitForCrossChainDepositParamsSchema, withdrawParamsSchema };
27885
- export type { ActionHandler, AdapterContext, AllowanceStrategy$2 as AllowanceStrategy, AppKitActionName, AppKitActions, AppKitBridgeActions, AppKitConfig, AppKitContext, AppKitEarnActions, AppKitEarnOperations, AppKitUnifiedBalanceActions, BaseChainDefinition, BridgeConfig, CustomFeePolicy$2 as BridgeCustomFeePolicy, BridgeParams, BridgeResult, BridgeStep, CCTPConfig, CCTPMergedConfig, CCTPSplitConfig, ChainDefinition, Currency, DelegateStatus, DepositForParams, DepositParams, DepositResult, DeveloperFeeHooks, EVMChainDefinition, EarnAccruedRewardInfo, EarnAdapterContext, AnyDepositParams as EarnAnyDepositParams, EarnAssetAmount, EarnBridgeCctpStatus, EarnBridgeHopStatus, EarnBridgeQuoteExpiry, ClaimRewardsParams as EarnClaimRewardsParams, EarnClaimRewardsQuoteInfo, EarnClaimRewardsResult, EarnClaimedAmount, EarnClaimedRewardsResult, EarnConfig, EarnCrossChainDepositDestination, CrossChainDepositParams as EarnCrossChainDepositParams, EarnCrossChainDepositResult, EarnCrossChainDepositStatus, EarnCrossChainDepositWaitOutcome, EarnCrossChainDepositWaitResult, CrossChainGetDepositQuoteParams as EarnCrossChainGetDepositQuoteParams, EarnDepositOutcome, DepositParams$2 as EarnDepositParams, EarnDepositQuoteInfo, EarnDepositResult, ExploreVaultsIteratorParams as EarnExploreVaultsIteratorParams, ExploreVaultsPagination as EarnExploreVaultsPagination, ExploreVaultsParams as EarnExploreVaultsParams, EarnExploreVaultsResult, ExploreVaultsSortBy as EarnExploreVaultsSortBy, EarnGasFeeEstimate, EarnGasFeeEstimateBase, GetClaimRewardsQuoteParams as EarnGetClaimRewardsQuoteParams, GetCrossChainDepositStatusParams as EarnGetCrossChainDepositStatusParams, GetDepositQuoteParams as EarnGetDepositQuoteParams, GetPositionParams as EarnGetPositionParams, GetVaultsParams as EarnGetVaultsParams, EarnGetVaultsResult, GetWithdrawalQuoteParams as EarnGetWithdrawalQuoteParams, EarnKitConfig, EarnKitContext, EarnOperationParams, EarnPositionInfo, EarnPositionPnLInfo, EarningProvider as EarnProvider, SameChainDepositParams as EarnSameChainDepositParams, EarnSameChainDepositResult, SameChainGetDepositQuoteParams as EarnSameChainGetDepositQuoteParams, EarnServiceConfig, EarnVaultInfo, VaultQuery as EarnVaultQuery, WaitForCrossChainDepositParams as EarnWaitForCrossChainDepositParams, WithdrawParams as EarnWithdrawParams, EarnWithdrawResult, EarnWithdrawalQuoteInfo, ErrorDetails, EstimateResult$1 as EstimateResult, EstimateSpendResult, EstimatedGas, FeeOperationType, GetBalancesParams, GetBalancesResult, GetDelegateStatusParams, GetSupportedChainsOptions, GetSwapStatusParams, GetTokenRatesParams, GetTokenRatesResult, InitiateRemoveFundParams, InitiateRemoveFundResult, KitContractType, NonEVMChainDefinition, OperationParamsMap, OperationType, Recoverability, RemoveFundParams, RemoveFundResult, RetryContext, SendParams, SpendDestination, SpendParams, SpendResult, SwapConfig, CustomFeePolicy$1 as SwapCustomFeePolicy, SwapDestinationLeg, SwapEstimate, SwapFeeContext, SwapKitConfig, SwapKitContext, SwapParams, SwapProgress, SwapResult, SwapSourceLeg, SwapStatus, SwapStatusResult, SwapTerminalStatus, TokenInfo, TokenRate, UnifiedBalanceChainIdentifier, CustomFeePolicy as UnifiedBalanceCustomFeePolicy, FeeRecipientsConfig as UnifiedBalanceFeeRecipientsConfig, UnifiedBalanceKitConfig, SupportedToken as UnifiedBalanceSupportedToken, UpdateDelegateParams, UpdateDelegateResult, VersionConfig, WaitForSwapDiscreteParams, WaitForSwapParams, WaitForSwapResultParams };
28540
+ export { AppKit, AppKitUnifiedBalance, BalanceError, Blockchain, BridgeChain, EARN_EXECUTE_REVIEW_KIND, EarnChain, EarnError, EarnKit, InputError, KitError, NetworkError, OnchainError, RateLimitError, RpcError, ServiceError, SwapChain, TOKEN_ALIASES, TransferSpeed, UnifiedBalanceChain, anyDepositParamsSchema, claimRewardsParamsSchema, createEarnKitContext, depositParamsSchema, claimRewards as earnClaimRewards, deposit as earnDeposit, exploreVaults as earnExploreVaults, exploreVaultsIterator as earnExploreVaultsIterator, getClaimRewardsQuote as earnGetClaimRewardsQuote, getCrossChainDepositStatus as earnGetCrossChainDepositStatus, getCrossChainDepositStatusOutcome as earnGetCrossChainDepositStatusOutcome, getDepositQuote as earnGetDepositQuote, getPosition as earnGetPosition, getSupportedChains as earnGetSupportedChains, getVaults as earnGetVaults, getWithdrawalQuote as earnGetWithdrawalQuote, waitForCrossChainDeposit as earnWaitForCrossChainDeposit, withdraw as earnWithdraw, exploreVaultsIteratorParamsSchema, exploreVaultsParamsSchema, getClaimRewardsQuoteParamsSchema, getCrossChainDepositStatusParamsSchema, getDepositQuoteParamsSchema, getErrorCode, getErrorMessage, getPositionParamsSchema, getTokenDecimals, getVaultsParamsSchema, getWithdrawalQuoteParamsSchema, isBalanceError, isEarnExecuteReview, isFatalError, isInputError, isKitError, isNetworkError, isOnchainError, isRateLimitError, isRetryableError, isRpcError, isServiceError, isTerminalCrossChainDepositStatus as isTerminalEarnCrossChainDepositStatus, isTokenAddress, isTokenAlias, isUserCancellationError, setExternalPrefix, validateToken, waitForCrossChainDepositParamsSchema, withdrawParamsSchema };
28541
+ export type { ActionHandler, AdapterContext, AllowanceStrategy$2 as AllowanceStrategy, AppKitActionName, AppKitActions, AppKitBridgeActions, AppKitConfig, AppKitContext, AppKitCustomFeePolicy, AppKitCustomFeePolicyScope, AppKitEarnActions, AppKitEarnOperations, AppKitUnifiedBalanceActions, BaseChainDefinition, BridgeConfig, CustomFeePolicy$2 as BridgeCustomFeePolicy, BridgeParams, BridgeResult, BridgeStep, CCTPConfig, CCTPMergedConfig, CCTPSplitConfig, ChainDefinition, Currency, DecodedEarnTx, DelegateStatus, DepositForParams, DepositParams, DepositResult, DeveloperFeeHooks, EVMChainDefinition, EarnAccruedRewardInfo, EarnAdapterContext, AnyDepositParams as EarnAnyDepositParams, EarnAssetAmount, EarnBridgeCctpStatus, EarnBridgeHopStatus, EarnBridgeQuoteExpiry, ClaimRewardsParams as EarnClaimRewardsParams, EarnClaimRewardsQuoteInfo, EarnClaimRewardsResult, EarnClaimedAmount, EarnClaimedRewardsResult, EarnConfig, EarnCrossChainDepositDestination, CrossChainDepositParams as EarnCrossChainDepositParams, EarnCrossChainDepositResult, EarnCrossChainDepositStatus, EarnCrossChainDepositWaitOutcome, EarnCrossChainDepositWaitResult, CrossChainGetDepositQuoteParams as EarnCrossChainGetDepositQuoteParams, EarnDepositOutcome, DepositParams$2 as EarnDepositParams, EarnDepositQuoteInfo, EarnDepositResult, EarnEncodedTransaction, EarnExecuteAuthorizationReview, EarnExecuteReview, ExploreVaultsIteratorParams as EarnExploreVaultsIteratorParams, ExploreVaultsPagination as EarnExploreVaultsPagination, ExploreVaultsParams as EarnExploreVaultsParams, EarnExploreVaultsResult, ExploreVaultsSortBy as EarnExploreVaultsSortBy, EarnGasFeeEstimate, EarnGasFeeEstimateBase, GetClaimRewardsQuoteParams as EarnGetClaimRewardsQuoteParams, GetCrossChainDepositStatusParams as EarnGetCrossChainDepositStatusParams, GetDepositQuoteParams as EarnGetDepositQuoteParams, GetPositionParams as EarnGetPositionParams, GetVaultsParams as EarnGetVaultsParams, EarnGetVaultsResult, GetWithdrawalQuoteParams as EarnGetWithdrawalQuoteParams, EarnKitConfig, EarnKitContext, EarnOperationParams, EarnPositionInfo, EarnPositionPnLInfo, EarningProvider as EarnProvider, SameChainDepositParams as EarnSameChainDepositParams, EarnSameChainDepositResult, SameChainGetDepositQuoteParams as EarnSameChainGetDepositQuoteParams, EarnServiceConfig, EarnVaultInfo, VaultQuery as EarnVaultQuery, WaitForCrossChainDepositParams as EarnWaitForCrossChainDepositParams, WithdrawParams as EarnWithdrawParams, EarnWithdrawResult, EarnWithdrawalQuoteInfo, ErrorDetails, EstimateResult$1 as EstimateResult, EstimateSpendResult, EstimatedGas, FeeOperationType, GetBalancesParams, GetBalancesResult, GetDelegateStatusParams, GetSupportedChainsOptions, GetSwapStatusParams, GetTokenRatesParams, GetTokenRatesResult, InitiateRemoveFundParams, InitiateRemoveFundResult, KitContractType, NonEVMChainDefinition, OperationParamsMap, OperationType, Recoverability, RemoveFundParams, RemoveFundResult, RetryContext, SendParams, SpendDestination, SpendParams, SpendResult, SwapConfig, CustomFeePolicy$1 as SwapCustomFeePolicy, SwapDestinationLeg, SwapEstimate, SwapFeeContext, SwapKitConfig, SwapKitContext, SwapParams, SwapProgress, SwapResult, SwapSourceLeg, SwapStatus, SwapStatusResult, SwapTerminalStatus, TokenInfo, TokenRate, UnifiedBalanceChainIdentifier, CustomFeePolicy as UnifiedBalanceCustomFeePolicy, FeeRecipientsConfig as UnifiedBalanceFeeRecipientsConfig, UnifiedBalanceKitConfig, SupportedToken as UnifiedBalanceSupportedToken, UpdateDelegateParams, UpdateDelegateResult, VersionConfig, WaitForSwapDiscreteParams, WaitForSwapParams, WaitForSwapResultParams };