@zama-fhe/sdk 3.4.0-alpha.2 → 3.4.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  import { u as FheChain } from "./index-doNE2KoX.js";
2
- import { $ as TransferOptions, Bt as EncryptedValue, C as ChainRouter, Ht as FhevmRelayerOptions, K as ZamaSDKEventInput, Mt as TransactionResult, Nt as ClearValue, Pt as DecryptPublicValuesResult, R as TransactionOperation, Rt as EncryptParams, Ut as FhevmRelayerSDK, Z as ShieldOptions, c as GenericStorage, d as WalletAccount, et as UnshieldOptions, i as ZamaConfig, l as GenericProvider, n as RelayerConfig, nt as TransferCallbacks, o as ZamaConfigGeneric, p as WalletAccountListener, rt as UnshieldCallbacks, s as GenericLogger, u as GenericSigner, x as WriteContractConfig, zt as EncryptResult } from "./types-nwhfaUCK.js";
3
- import "./cleartext-Bvx-0y6k.js";
4
- import "./types-D8g0H49N.js";
5
- import "./types-CObfaH4A.js";
6
- import "./index-CDJk5ZAg.js";
7
- import { Address, Hex } from "viem";
2
+ import { $ as TransferOptions, Bt as EncryptResult, C as ChainRouter, Ft as DecryptPublicValuesResult, K as ZamaSDKEventInput, Nt as TransactionResult, Pt as ClearValue, R as TransactionOperation, Ut as FhevmRelayerOptions, Vt as EncryptedValue, Wt as FhevmRelayerSDK, Z as ShieldOptions, c as GenericStorage, d as WalletAccount, et as UnshieldOptions, i as ZamaConfig, it as UnshieldCallbacks, l as GenericProvider, n as RelayerConfig, o as ZamaConfigGeneric, p as WalletAccountListener, rt as TransferCallbacks, s as GenericLogger, tt as UnwrapResult, u as GenericSigner, x as WriteContractConfig, zt as EncryptParams } from "./types-C5XL-FYs.js";
3
+ import "./cleartext-D2thmTZC.js";
4
+ import "./types-BHavXeSS.js";
5
+ import "./base-signer-DEZW976z.js";
6
+ import "./types-CLSVkR1j.js";
7
+ import { Address, Address as Address$1, Hex, Hex as Hex$1 } from "viem";
8
8
  import { z } from "zod/mini";
9
9
  import { MutationFunctionContext, QueryKey, QueryObserverOptions, skipToken } from "@tanstack/query-core";
10
10
  //#region src/config/create.d.ts
@@ -18459,34 +18459,6 @@ declare function isConfidentialTokenValidContract(registry: Address, confidentia
18459
18459
  readonly args: readonly [`0x${string}`];
18460
18460
  };
18461
18461
  //#endregion
18462
- //#region src/query/utils.d.ts
18463
- type StrippedQueryOptionKeys = "gcTime" | "staleTime" | "enabled" | "select" | "refetchInterval" | "refetchOnMount" | "refetchOnWindowFocus" | "refetchOnReconnect" | "retry" | "retryDelay" | "retryOnMount" | "queryFn" | "queryKey" | "queryKeyHashFn" | "initialData" | "initialDataUpdatedAt" | "placeholderData" | "structuralSharing" | "throwOnError" | "meta" | "query" | "pollingInterval";
18464
- /**
18465
- * Remove TanStack behavioral options from a query config object so only domain
18466
- * parameters remain for the lower-level factory.
18467
- *
18468
- * @example
18469
- * ```ts
18470
- * const params = filterQueryOptions({
18471
- * query: { enabled: false },
18472
- * gcTime: 60_000,
18473
- * owner: "0xabc",
18474
- * });
18475
- * // => { owner: "0xabc" }
18476
- * ```
18477
- */
18478
- declare function filterQueryOptions<TOptions extends Record<string, unknown>>(options: TOptions): Omit<TOptions, StrippedQueryOptionKeys>;
18479
- /**
18480
- * Stable hash function for query keys.
18481
- * Sorts object keys recursively and converts bigint values to strings.
18482
- *
18483
- * @remarks
18484
- * bigint values are serialized as decimal strings, so `42n` and `"42"` hash to
18485
- * the same token when they occupy the same position. This collision is accepted
18486
- * by design for the current query-key conventions in this package.
18487
- */
18488
- declare function hashFn(queryKey: readonly unknown[]): string;
18489
- //#endregion
18490
18462
  //#region src/query/factory-types.d.ts
18491
18463
  type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
18492
18464
  type QueryFactoryOptions<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = Omit<RequiredBy<QueryObserverOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, "queryKey">, "queryFn" | "queryHash" | "queryKeyHashFn" | "throwOnError"> & {
@@ -18498,11 +18470,6 @@ interface MutationFactoryOptions<TMutationKey extends readonly unknown[], TVaria
18498
18470
  onSuccess?: (data: TData, variables: TVariables, onMutateResult: TOnMutateResult, context: MutationFunctionContext) => void;
18499
18471
  }
18500
18472
  //#endregion
18501
- //#region src/query/signer-query-context.d.ts
18502
- interface SignerQueryContext {
18503
- walletAccount?: WalletAccount;
18504
- }
18505
- //#endregion
18506
18473
  //#region src/query/query-keys.d.ts
18507
18474
  /**
18508
18475
  * Canonical query-key namespace for `@zama-fhe/sdk/query`.
@@ -18706,53 +18673,19 @@ declare const zamaQueryKeys: {
18706
18673
  };
18707
18674
  };
18708
18675
  //#endregion
18709
- //#region src/query/invalidation.d.ts
18710
- interface QueryLike {
18711
- queryKey: readonly unknown[];
18712
- }
18713
- interface QueryFilterLike {
18714
- queryKey?: readonly unknown[];
18715
- predicate?: (query: QueryLike) => boolean;
18716
- }
18717
- interface QueryClientLike {
18718
- invalidateQueries(filters: QueryFilterLike): void | Promise<void>;
18719
- removeQueries(filters: QueryFilterLike): void;
18720
- }
18721
- declare function invalidateAfterUnwrap(queryClient: QueryClientLike, tokenAddress: Address): void;
18722
- declare function invalidateBalanceQueries(queryClient: QueryClientLike, tokenAddress: Address): void;
18723
- declare function invalidateAfterShield(queryClient: QueryClientLike, tokenAddress: Address): void;
18724
- declare function invalidateAfterUnshield(queryClient: QueryClientLike, tokenAddress: Address): void;
18725
- declare function invalidateAfterUnshieldSettled(queryClient: QueryClientLike, tokenAddress: Address): void;
18726
- declare function invalidateAfterTransfer(queryClient: QueryClientLike, tokenAddress: Address): void;
18727
- declare function invalidateAfterApproveUnderlying(queryClient: QueryClientLike, tokenAddress: Address): void;
18728
- declare function invalidateAfterSetOperator(queryClient: QueryClientLike, tokenAddress: Address): void;
18729
- declare function invalidateWagmiBalanceQueries(queryClient: QueryClientLike): void;
18730
- declare function invalidateWalletLifecycleQueries(queryClient: QueryClientLike): void;
18731
- //#endregion
18732
- //#region src/query/token-metadata.d.ts
18733
- /** ERC-20 token metadata returned by {@link tokenMetadataQueryOptions}. */
18734
- interface TokenMetadata {
18735
- name: string;
18736
- symbol: string;
18737
- decimals: number;
18738
- }
18739
- interface TokenMetadataQueryConfig {
18740
- query?: Record<string, unknown>;
18741
- }
18742
- declare function tokenMetadataQueryOptions(sdk: ZamaSDK, tokenAddress: Address, config?: TokenMetadataQueryConfig): QueryFactoryOptions<TokenMetadata, Error, TokenMetadata, ReturnType<typeof zamaQueryKeys.tokenMetadata.token>>;
18743
- //#endregion
18744
- //#region src/query/is-confidential.d.ts
18745
- interface IsConfidentialQueryConfig {
18746
- query?: Record<string, unknown>;
18676
+ //#region src/query/signer-query-context.d.ts
18677
+ interface SignerQueryContext {
18678
+ walletAccount?: WalletAccount;
18747
18679
  }
18748
- declare function isConfidentialQueryOptions(sdk: ZamaSDK, tokenAddress: Address, config?: IsConfidentialQueryConfig): QueryFactoryOptions<boolean, Error, boolean, ReturnType<typeof zamaQueryKeys.isConfidential.token>>;
18749
- declare function isWrapperQueryOptions(sdk: ZamaSDK, tokenAddress: Address, config?: IsConfidentialQueryConfig): QueryFactoryOptions<boolean, Error, boolean, ReturnType<typeof zamaQueryKeys.isWrapper.token>>;
18750
18680
  //#endregion
18751
- //#region src/query/total-supply.d.ts
18752
- interface TotalSupplyQueryConfig {
18753
- query?: Record<string, unknown>;
18681
+ //#region src/query/user-decrypt.d.ts
18682
+ interface EncryptedInput {
18683
+ encryptedValue: EncryptedValue;
18684
+ contractAddress: Address;
18754
18685
  }
18755
- declare function totalSupplyQueryOptions(sdk: ZamaSDK, tokenAddress: Address, config?: TotalSupplyQueryConfig): QueryFactoryOptions<bigint, Error, bigint, ReturnType<typeof zamaQueryKeys.totalSupply.token>>;
18686
+ /** Decrypted clear values keyed by encrypted handle. */
18687
+ type DecryptResult = Readonly<Record<EncryptedValue, ClearValue>>;
18688
+ declare function decryptValuesQueryOptions(sdk: ZamaSDK, encryptedInputs: EncryptedInput[], signerContext?: SignerQueryContext): QueryFactoryOptions<DecryptResult, Error, DecryptResult, ReturnType<typeof zamaQueryKeys.decryption.encryptedInputs>>;
18756
18689
  //#endregion
18757
18690
  //#region src/schemas/primitives.d.ts
18758
18691
  declare const checksummedTag: unique symbol;
@@ -18820,272 +18753,91 @@ interface SerializedTransportKeyPairWithPermissions {
18820
18753
  readonly permissions: readonly Permission[];
18821
18754
  }
18822
18755
  //#endregion
18823
- //#region src/wrappers-registry.d.ts
18824
- /**
18825
- * Default wrappers registry addresses for known chains.
18826
- * Only includes chains where a registry is deployed (excludes Hardhat).
18827
- *
18828
- * @deprecated Read `registryAddress` from the chain presets instead (e.g.
18829
- * `sepolia.registryAddress`). Will be removed in the next major version.
18830
- */
18831
- declare const DefaultRegistryAddresses: Record<number, Address>;
18832
- /** Configuration for {@link WrappersRegistry}. */
18833
- interface WrappersRegistryConfig {
18834
- /** Read-only chain provider used for every registry lookup. */
18835
- provider: GenericProvider;
18836
- /**
18837
- * Per-chain registry address overrides, merged on top of
18838
- * {@link DefaultRegistryAddresses}. Use this to supply a registry
18839
- * address for custom or local chains (e.g. Hardhat).
18840
- *
18841
- * @example
18842
- * ```ts
18843
- * new WrappersRegistry({
18844
- * provider,
18845
- * registryAddresses: { [31337]: "0xYourHardhatRegistry" },
18846
- * });
18847
- * ```
18848
- */
18849
- registryAddresses?: Record<number, Address>;
18850
- /**
18851
- * How long cached registry results remain valid, in seconds.
18852
- * Default: `86400` (24 hours).
18853
- */
18854
- registryTTL?: number;
18855
- }
18856
- /** Options for {@link WrappersRegistry.listPairs}. */
18857
- interface ListPairsOptions {
18858
- /** Page number (1-indexed). Default: `1`. */
18859
- page?: number;
18860
- /** Number of items per page. Default: `100`. */
18861
- pageSize?: number;
18862
- /**
18863
- * When `true`, fetches on-chain metadata (name, symbol, decimals) for both
18864
- * the ERC-20 and confidential token, plus totalSupply for the ERC-20.
18865
- * Default: `false`.
18866
- */
18867
- metadata?: boolean;
18756
+ //#region src/credentials/credential-service.d.ts
18757
+ /** Configuration for {@link CredentialService}. TTLs are pre-validated by the caller. */
18758
+ interface CredentialServiceConfig {
18759
+ router: ChainRouter;
18760
+ signer: GenericSigner;
18761
+ /** Transport key pair lifetime in seconds. Pre-validated. */
18762
+ transportKeyPairTTL: number;
18763
+ /** Permit lifetime in days. Pre-validated. */
18764
+ permitTTL: number;
18765
+ /** Backing storage for transport key pairs (and permits if `permitStorage` is omitted). */
18766
+ storage: GenericStorage;
18767
+ /** Optional dedicated storage for permits; defaults to `storage`. */
18768
+ permitStorage?: GenericStorage;
18769
+ /** SDK-wide logger for credential-path diagnostics. */
18770
+ logger: GenericLogger;
18868
18771
  }
18869
18772
  /**
18870
- * High-level interface for the on-chain token wrappers registry.
18871
- *
18872
- * Uses the configured {@link GenericProvider} to resolve the correct registry
18873
- * contract address for the current chain and exposes typed read helpers for
18874
- * every registry query. Results are cached in memory with a configurable TTL
18875
- * (default 24 hours).
18876
- *
18877
- * @example
18878
- * ```ts
18879
- * const registry = new WrappersRegistry({ provider });
18880
- *
18881
- * // Paginated listing
18882
- * const page1 = await registry.listPairs({ page: 1, pageSize: 20 });
18883
- *
18884
- * // Structured lookups
18885
- * const result = await registry.getConfidentialToken(erc20Address);
18886
- * if (result) console.log(result.confidentialTokenAddress);
18773
+ * Single facade coordinating the keypair vault and the permission store.
18887
18774
  *
18888
- * // Force refresh
18889
- * registry.refresh();
18890
- * ```
18775
+ * `CredentialService` is the only credentials object held by `ZamaSDK`. It accepts identity
18776
+ * transitions via `handleWalletAccountChange`.
18891
18777
  */
18892
- declare class WrappersRegistry {
18778
+ declare class CredentialService {
18893
18779
  #private;
18894
- readonly provider: GenericProvider;
18895
- constructor(config: WrappersRegistryConfig);
18896
- /**
18897
- * Synchronous lookup of the registry address for a given chain ID.
18898
- * Returns `undefined` if no address is configured for that chain.
18899
- */
18900
- getAddress(chainId: number): Address | undefined;
18901
- /**
18902
- * Force-invalidate the in-memory cache. The next call to any read method
18903
- * will fetch fresh data from the chain.
18904
- */
18905
- refresh(): void;
18906
- /**
18907
- * The cache TTL in milliseconds.
18908
- * Exposed so query option factories can set a matching `staleTime`.
18909
- */
18910
- get ttlMs(): number;
18911
- /**
18912
- * Resolve the registry contract address for the current chain.
18913
- *
18914
- * Priority: `registryAddresses[chainId]` \> built-in default.
18915
- *
18916
- * @returns The registry contract address for the connected chain.
18917
- * @throws if no address is configured for the chain. {@link ConfigurationError}
18918
- */
18919
- getRegistryAddress(): Promise<Address>;
18780
+ constructor(config: CredentialServiceConfig);
18920
18781
  /**
18921
- * List token wrapper pairs with page-based pagination.
18922
- *
18923
- * Internally maps to `getTokenConfidentialTokenPairsSlice` on-chain.
18924
- *
18925
- * @param options - Pagination and enrichment options.
18926
- * @returns A {@link PaginatedResult} of pairs.
18927
- *
18928
- * @example
18929
- * ```ts
18930
- * const result = await registry.listPairs({ page: 1, pageSize: 20 });
18931
- * console.log(`${result.total} pairs, showing page ${result.page}`);
18782
+ * Resolve a keypair and permissions covering `contracts`, minimizing wallet
18783
+ * prompts by reusing or widening existing permits where possible. Empty
18784
+ * `contracts` warms the keypair without prompting.
18932
18785
  *
18933
- * // With on-chain metadata
18934
- * const withMeta = await registry.listPairs({ metadata: true, pageSize: 10 });
18935
- * for (const pair of withMeta.items) {
18936
- * console.log(pair.underlying.symbol, "→", pair.confidential.symbol);
18937
- * }
18938
- * ```
18786
+ * @returns The resolved keypair and permits covering the requested contracts.
18787
+ * @throws if the user rejects a wallet signature prompt. {@link SigningRejectedError}
18788
+ * @throws if signing fails for any other reason. {@link SigningFailedError}
18939
18789
  */
18940
- listPairs(options: ListPairsOptions & {
18941
- metadata: true;
18942
- }): Promise<PaginatedResult<TokenWrapperPairWithMetadata>>;
18943
- listPairs(options?: ListPairsOptions): Promise<PaginatedResult<TokenWrapperPair>>;
18790
+ grantPermit(contracts: readonly Address[], delegator?: Address): Promise<SerializedTransportKeyPairWithPermissions>;
18944
18791
  /**
18945
- * Look up the confidential token for a given plain ERC-20 address.
18946
- *
18947
- * @param tokenAddress - The plain ERC-20 token address.
18948
- * @returns The lookup result, or `null` if the token has never been registered.
18949
- * **Note:** revoked tokens (registered then invalidated) return a non-null result
18950
- * with `isValid: false`. Check `result.isValid` explicitly rather than using
18951
- * `if (result)` to guard against processing revoked tokens.
18792
+ * Pure store lookup: are stored permits sufficient to cover `contracts`? No wallet prompt.
18952
18793
  *
18953
- * @example
18954
- * ```ts
18955
- * const result = await registry.getConfidentialToken(usdcAddress);
18956
- * if (result?.isValid) {
18957
- * console.log(result.confidentialTokenAddress);
18958
- * }
18959
- * ```
18794
+ * @returns `true` if cached permits cover all requested contracts (vacuously
18795
+ * true for an empty list); `false` if no keypair exists or coverage is
18796
+ * incomplete.
18960
18797
  */
18961
- getConfidentialToken(tokenAddress: Address): Promise<{
18962
- confidentialTokenAddress: Address;
18963
- isValid: boolean;
18964
- } | null>;
18798
+ hasPermit(contracts: readonly Address[], delegator?: Address): Promise<boolean>;
18965
18799
  /**
18966
- * Reverse lookup — find the plain ERC-20 for a given confidential token.
18967
- *
18968
- * @param confidentialTokenAddress - The confidential token address.
18969
- * @returns The lookup result, or `null` if no pair is registered.
18800
+ * Wipe FHE permits for the current signer.
18970
18801
  *
18971
- * @example
18972
- * ```ts
18973
- * const result = await registry.getUnderlyingToken(cUsdcAddress);
18974
- * if (result) {
18975
- * console.log(result.tokenAddress, result.isValid);
18976
- * }
18977
- * ```
18978
- */
18979
- getUnderlyingToken(confidentialTokenAddress: Address): Promise<{
18980
- tokenAddress: Address;
18981
- isValid: boolean;
18982
- } | null>;
18983
- /**
18984
- * Fetch all token wrapper pairs from the registry.
18802
+ * - With no argument: every permit referencing this signer is removed across
18803
+ * all chains and delegators. The keypair survives — use
18804
+ * {@link clearCredentials} to also wipe the keypair.
18805
+ * - With a contract list: every signed permit in the direct-decrypt scope
18806
+ * (current chain) whose immutable payload touches any listed address is
18807
+ * removed. Delegated permits are not touched in this mode.
18985
18808
  *
18986
- * @returns All registered `TokenWrapperPair` entries.
18809
+ * @throws if reading the signer address fails. {@link SigningFailedError}
18987
18810
  */
18988
- getTokenPairs(): Promise<readonly TokenWrapperPair[]>;
18811
+ revokePermits(contracts?: readonly Address[]): Promise<void>;
18989
18812
  /**
18990
- * Get the total number of token wrapper pairs.
18813
+ * Wipe the keypair for the current signer and cascade-delete every
18814
+ * permission referencing it across all chains and delegators.
18991
18815
  *
18992
- * @returns The count as a bigint.
18816
+ * @throws if reading the signer address fails. {@link SigningFailedError}
18993
18817
  */
18994
- getTokenPairsLength(): Promise<bigint>;
18818
+ clearCredentials(): Promise<void>;
18995
18819
  /**
18996
- * Fetch a range of token wrapper pairs (paginated by index).
18820
+ * Warm the signer transport key pair cache for a known address.
18997
18821
  *
18998
- * @param fromIndex - Start index (inclusive).
18999
- * @param toIndex - End index (exclusive).
19000
- * @returns The slice of `TokenWrapperPair` entries.
18822
+ * Best-effort prefetch primitive: correctness still comes from `grantPermit`,
18823
+ * which lazily creates the transport key pair when needed. Errors (storage failure,
18824
+ * relayer 4xx, missing Worker in SSR) are **not** swallowed here — the caller
18825
+ * decides whether to log, ignore, or surface them.
19001
18826
  */
19002
- getTokenPairsSlice(fromIndex: bigint, toIndex: bigint): Promise<readonly TokenWrapperPair[]>;
18827
+ warmTransportKeyPair(address: Address): Promise<void>;
19003
18828
  /**
19004
- * Fetch a single token wrapper pair by index.
18829
+ * Apply a wallet account transition.
19005
18830
  *
19006
- * @param index - Zero-based pair index.
19007
- * @returns The `TokenWrapperPair` at that index.
18831
+ * Address change clears persisted credentials for the previous account.
18832
+ * Chain-only changes keep credentials intact because permits are chain-scoped
18833
+ * already and stale decrypt plaintext is cleared by `ZamaSDK`.
19008
18834
  */
19009
- getTokenPair(index: bigint): Promise<TokenWrapperPair>;
19010
- /**
19011
- * Look up the confidential token address for a given plain ERC-20 token.
19012
- *
19013
- * @param tokenAddress - The plain ERC-20 token address.
19014
- * @returns A tuple `[isValid, confidentialTokenAddress]`. `isValid` is `true` only for a
19015
- * registered, non-revoked wrapper. The address is the zero address when no pair is registered.
19016
- * A non-zero address with `isValid=false` means the wrapper was registered but later revoked.
19017
- */
19018
- getConfidentialTokenAddress(tokenAddress: Address): Promise<readonly [boolean, Address]>;
19019
- /**
19020
- * Reverse lookup — find the plain ERC-20 for a given confidential token.
19021
- *
19022
- * @param confidentialTokenAddress - The confidential token address.
19023
- * @returns A tuple `[isValid, tokenAddress]`. `isValid` is `true` only for a registered,
19024
- * non-revoked wrapper. The address is the zero address when no pair is registered.
19025
- * A non-zero address with `isValid=false` means the wrapper was registered but later revoked.
19026
- */
19027
- getTokenAddress(confidentialTokenAddress: Address): Promise<readonly [boolean, Address]>;
19028
- /**
19029
- * Check whether a confidential token is registered and valid.
19030
- *
19031
- * @param confidentialTokenAddress - The confidential token address to check.
19032
- * @returns `true` if the token is a known valid wrapper in the registry.
19033
- */
19034
- isConfidentialTokenValid(confidentialTokenAddress: Address): Promise<boolean>;
19035
- }
19036
- //#endregion
19037
- //#region src/query/wrapper-discovery.d.ts
19038
- interface WrapperDiscoveryQueryConfig {
19039
- /**
19040
- * Address of any confidential token you control.
19041
- * Used to scope the query cache key and to gate whether the query
19042
- * is enabled — it does not affect which wrapper the registry returns.
19043
- */
19044
- tokenAddress?: Address;
19045
- /**
19046
- * The ERC-20 token address to discover the confidential wrapper for.
19047
- * The registry is resolved automatically from chain config.
19048
- */
19049
- erc20Address?: Address;
19050
- /**
19051
- * The resolved registry contract address for the current chain.
19052
- * Included in the query key so that switching chains invalidates
19053
- * stale cached results. Pass `undefined` when the chain ID is not
19054
- * yet known — the query will be disabled.
19055
- */
19056
- registryAddress?: Address;
19057
- query?: Record<string, unknown>;
19058
- }
19059
- declare function wrapperDiscoveryQueryOptions(registry: WrappersRegistry, config: WrapperDiscoveryQueryConfig): QueryFactoryOptions<Address | null, Error, Address | null, ReturnType<typeof zamaQueryKeys.wrapperDiscovery.token>>;
19060
- //#endregion
19061
- //#region src/query/underlying-allowance.d.ts
19062
- interface UnderlyingAllowanceQueryConfig {
19063
- owner?: Address;
19064
- query?: Record<string, unknown>;
19065
- }
19066
- declare function underlyingAllowanceQueryOptions(sdk: ZamaSDK, tokenAddress: Address, config: UnderlyingAllowanceQueryConfig): QueryFactoryOptions<bigint, Error, bigint, ReturnType<typeof zamaQueryKeys.underlyingAllowance.scope>>;
19067
- //#endregion
19068
- //#region src/query/pending-unshield.d.ts
19069
- interface PendingUnshieldQueryConfig {
19070
- query?: Record<string, unknown>;
19071
- }
19072
- /**
19073
- * Query options for reading the unwrap tx hash of an unshield that was
19074
- * interrupted between its two phases (returns `null` if none is pending).
19075
- *
19076
- * Backed by {@link ZamaSDK} storage via `WrappedToken.getPendingUnshield()`.
19077
- * `staleTime: 0` so the value reflects storage on mount; the unshield/unwrap
19078
- * mutations also invalidate this key on success.
19079
- */
19080
- declare function pendingUnshieldQueryOptions(sdk: ZamaSDK, tokenAddress: Address, config?: PendingUnshieldQueryConfig): QueryFactoryOptions<Hex | null, Error, Hex | null, ReturnType<typeof zamaQueryKeys.pendingUnshield.token>>;
19081
- //#endregion
19082
- //#region src/query/confidential-is-operator.d.ts
19083
- interface ConfidentialIsOperatorQueryConfig {
19084
- holder?: Address;
19085
- spender?: Address;
19086
- query?: Record<string, unknown>;
18835
+ handleWalletAccountChange(prev?: {
18836
+ address: Address;
18837
+ }, next?: {
18838
+ address: Address;
18839
+ }): Promise<void>;
19087
18840
  }
19088
- declare function confidentialIsOperatorQueryOptions(sdk: ZamaSDK, tokenAddress: Address | undefined, config: ConfidentialIsOperatorQueryConfig): QueryFactoryOptions<boolean, Error, boolean, ReturnType<typeof zamaQueryKeys.confidentialIsOperator.scope>>;
19089
18841
  //#endregion
19090
18842
  //#region src/errors/base.d.ts
19091
18843
  /**
@@ -19588,1283 +19340,1163 @@ declare function matchZamaError<R>(error: unknown, handlers: { [K in ZamaErrorCo
19588
19340
  _?: (error: unknown) => R;
19589
19341
  }): R | undefined;
19590
19342
  //#endregion
19591
- //#region src/token/token.d.ts
19592
- /** Options for {@link Token.batchDecryptBalancesAs}. */
19593
- interface BatchDecryptAsOptions {
19594
- /** The address of the account that delegated decryption rights. */
19595
- delegatorAddress: Address;
19596
- /** Pre-fetched encrypted values. When omitted, they are fetched from the chain. */
19597
- encryptedValues?: EncryptedValue[];
19343
+ //#region src/services/caching-service.d.ts
19344
+ /**
19345
+ * Storage-backed cache for decrypted FHE plaintext values.
19346
+ *
19347
+ * Each entry is keyed by `(requester, contractAddress, handle)` so different
19348
+ * signers cannot read each other's cached decryptions.
19349
+ */
19350
+ declare class CachingService {
19351
+ #private;
19352
+ constructor(storage: GenericStorage, logger: GenericLogger);
19353
+ get(requester: Address, contractAddress: Address, encryptedValue: EncryptedValue): Promise<ClearValue | null>;
19354
+ set(requester: Address, contractAddress: Address, encryptedValue: EncryptedValue, value: ClearValue): Promise<void>;
19355
+ delete(requester: Address, contractAddress: Address, encryptedValue: EncryptedValue): Promise<void>;
19356
+ clearForRequester(requester: Address): Promise<void>;
19357
+ clearAll(): Promise<void>;
19358
+ }
19359
+ //#endregion
19360
+ //#region src/services/delegation-service.d.ts
19361
+ declare class DelegationService {
19362
+ #private;
19363
+ constructor({ provider, router, emitEvent, logger }: {
19364
+ provider: GenericProvider;
19365
+ router: ChainRouter;
19366
+ logger: GenericLogger;
19367
+ emitEvent?: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;
19368
+ });
19369
+ delegateDecryption(signer: GenericSigner, { contractAddress, delegateAddress, delegatorAddress, expirationDate }: {
19370
+ contractAddress: Address;
19371
+ delegateAddress: Address;
19372
+ delegatorAddress: Address;
19373
+ expirationDate?: Date;
19374
+ }): Promise<TransactionResult>;
19375
+ revokeDelegation(signer: GenericSigner, { contractAddress, delegateAddress, delegatorAddress }: {
19376
+ contractAddress: Address;
19377
+ delegateAddress: Address;
19378
+ delegatorAddress: Address;
19379
+ }): Promise<TransactionResult>;
19380
+ isDelegated(params: {
19381
+ contractAddress: Address;
19382
+ delegatorAddress: Address;
19383
+ delegateAddress: Address;
19384
+ }): Promise<boolean>;
19385
+ getDelegationExpiry({ contractAddress, delegatorAddress, delegateAddress }: {
19386
+ contractAddress: Address;
19387
+ delegatorAddress: Address;
19388
+ delegateAddress: Address;
19389
+ }): Promise<bigint>;
19390
+ findInactiveDelegations(contractAddresses: readonly Address[], delegatorAddress: Address, delegateAddress: Address): Promise<Map<Address, DelegationNotFoundError | DelegationExpiredError>>;
19391
+ assertDelegationActive(contractAddress: Address, delegatorAddress: Address, delegateAddress: Address): Promise<void>;
19392
+ }
19393
+ //#endregion
19394
+ //#region src/services/decryption-service.d.ts
19395
+ /** Options shared by the delegated-decrypt entry points. */
19396
+ interface DelegatedDecryptOptions {
19598
19397
  /**
19599
- * The account whose on-chain balance to read. Defaults to the delegator
19600
- * address, which is the common case (the delegator grants permission to
19601
- * decrypt their own balance). Only set this when the account differs
19602
- * from the delegator.
19603
- *
19604
- * Matches the `account` parameter of `confidentialBalanceOf(account)` on-chain.
19398
+ * Ride out the gateway propagation window: when a just-granted delegation
19399
+ * has not yet synced, the delegated decrypt is retried (bounded, ~30s) until
19400
+ * it lands instead of throwing {@link DelegationNotPropagatedError}. Defaults
19401
+ * to `true`. Pass `false` to fail fast on the first not-propagated response.
19605
19402
  */
19606
- accountAddress?: Address;
19607
- /** Maximum number of concurrent decrypt calls. Default: 10. */
19608
- maxConcurrency?: number;
19609
- /** Called when decryption fails for a single token. Return a fallback bigint. */
19610
- onError?: (error: Error, address: Address) => bigint;
19403
+ waitForPropagation?: boolean;
19611
19404
  }
19612
- /** Result of {@link Token.batchBalancesOf}. */
19613
- interface BatchBalancesResult {
19614
- /** Successfully decrypted balances, keyed by token address. */
19615
- results: Map<Address, bigint>;
19616
- /** Per-token errors for tokens that failed to decrypt. */
19617
- errors: Map<Address, ZamaError>;
19405
+ interface BatchDecryptItem {
19406
+ encryptedValue: EncryptedValue;
19407
+ contractAddress: Address;
19408
+ value?: ClearValue;
19409
+ error?: ZamaError;
19410
+ }
19411
+ interface BatchDecryptResult {
19412
+ items: BatchDecryptItem[];
19413
+ }
19414
+ declare class DecryptionService {
19415
+ #private;
19416
+ constructor({ cache, credentialService, delegationService, router, emitEvent }: {
19417
+ cache: CachingService;
19418
+ credentialService: CredentialService;
19419
+ delegationService: DelegationService;
19420
+ router: ChainRouter;
19421
+ emitEvent: (input: ZamaSDKEventInput) => void;
19422
+ });
19423
+ decryptValues(handles: EncryptedInput[], signerAddress: Address, opts?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<Record<EncryptedValue, ClearValue>>;
19424
+ delegatedDecryptValues(encryptedInputs: EncryptedInput[], delegatorAddress: Address, delegateAddress: Address, accountAddress: Address, opts?: DelegatedDecryptOptions): Promise<Record<EncryptedValue, ClearValue>>;
19425
+ delegatedBatchDecryptHandlesAs({ encryptedInputs, delegatorAddress, delegateAddress, accountAddress, maxConcurrency, waitForPropagation }: {
19426
+ encryptedInputs: EncryptedInput[];
19427
+ delegatorAddress: Address;
19428
+ delegateAddress: Address;
19429
+ accountAddress: Address;
19430
+ maxConcurrency?: number;
19431
+ waitForPropagation?: boolean;
19432
+ }): Promise<BatchDecryptResult>;
19618
19433
  }
19434
+ //#endregion
19435
+ //#region src/namespaces/decryption.d.ts
19619
19436
  /**
19620
- * High-level interface for an ERC-7984 confidential token.
19621
- * Hides FHE complexity (encryption, decryption, EIP-712 signing) behind
19622
- * familiar ERC-20-like methods.
19437
+ * Public namespace for FHE decryption — the canonical way to decrypt.
19623
19438
  *
19624
- * For ERC-7984 wrappers (shield/unshield), use {@link WrappedToken} instead —
19625
- * it extends `Token` with wrapper-specific operations.
19439
+ * Exposed as `sdk.decryption`. Prefer these methods over the low-level
19440
+ * `sdk.relayer.decryptValues` / `decryptPublicValues`: they
19441
+ * assemble the credential bundle (transport key pair, EIP-712 permit) for you,
19442
+ * cache results, and wrap relayer errors. Reach for `sdk.relayer.*` only when
19443
+ * you must control credential assembly by hand.
19626
19444
  *
19627
- * Decryption, credentials, caching, and event emission are handled by the
19628
- * owning {@link ZamaSDK} — this class only exposes token-scoped helpers
19629
- * that delegate to `sdk.decryption.decryptValues` and `sdk.permits.grantPermit`.
19445
+ * Owns the SDK-level guards (signer requirement on
19446
+ * `decryptValues` and `delegatedDecryptValues`, empty-array
19447
+ * short-circuit on `decryptPublicValues`, relayer error wrapping) and delegates the
19448
+ * actual work to the internal {@link DecryptionService} or the relayer directly for
19449
+ * `decryptPublicValues`.
19450
+ *
19451
+ * **Mixed signer requirement:** `decryptValues` and
19452
+ * `delegatedDecryptValues` need a configured signer; `decryptPublicValues`
19453
+ * does not. Each method documents its requirement in its JSDoc.
19454
+ *
19455
+ * **Request chunking:** decrypt requests are split internally to stay under
19456
+ * the relayer's 2048-cleartext-bit per-request budget — callers never need to
19457
+ * size batches themselves.
19630
19458
  */
19631
- declare class Token {
19459
+ declare class Decryption {
19632
19460
  #private;
19633
- readonly sdk: ZamaSDK;
19634
- readonly address: Address;
19635
- constructor(sdk: ZamaSDK, address: Address);
19636
- /** Read the token name from the contract. */
19637
- name(): Promise<string>;
19638
- /** Read the token symbol from the contract. */
19639
- symbol(): Promise<string>;
19640
- /** Read the token decimals from the contract. */
19641
- decimals(): Promise<number>;
19642
- /**
19643
- * ERC-165 check for {@link ERC7984_INTERFACE_ID} support.
19644
- *
19645
- * @returns `true` if the contract implements the ERC-7984 confidential token interface.
19646
- */
19647
- isConfidential(): Promise<boolean>;
19461
+ /** @internal */
19462
+ constructor(opts: {
19463
+ signer: GenericSigner | undefined;
19464
+ provider: GenericProvider;
19465
+ router: ChainRouter;
19466
+ decryptionService: DecryptionService | undefined;
19467
+ });
19648
19468
  /**
19649
- * ERC-165 check for IERC7984ERC20Wrapper support.
19469
+ * Decrypt one or more FHE encrypted values. Results are cached — repeated calls
19470
+ * for the same encrypted value skip the relayer round-trip.
19650
19471
  *
19651
- * @returns `true` if the contract implements the ERC-7984 wrapper interface
19652
- * ({@link ERC7984_WRAPPER_INTERFACE_ID}, `0x1f1c62b2`).
19653
- */
19654
- isWrapper(): Promise<boolean>;
19655
- /**
19656
- * Decrypt and return the plaintext balance for the given owner.
19657
- * Acquires FHE credentials via a wallet signature if none are cached.
19472
+ * Zero encrypted values are mapped to `0n` without hitting the relayer.
19473
+ * Events (`DecryptStart/End/Error`) are emitted uniformly.
19474
+ * Relayer errors are wrapped into typed SDK errors.
19658
19475
  *
19659
- * @param owner - Balance owner address.
19660
- * @returns The decrypted plaintext balance as a bigint.
19661
- * @throws if FHE decryption fails. {@link DecryptionFailedError}
19476
+ * @param encryptedInput - Encrypted values to decrypt, each paired with its contract address.
19477
+ * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.
19478
+ * @returns A record mapping each encrypted value to its decrypted clear-text value.
19479
+ * @throws if no signer is configured. {@link SignerNotConfiguredError}
19480
+ * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19662
19481
  *
19663
19482
  * @example
19664
19483
  * ```ts
19665
- * const balance = await token.balanceOf("0xOwner");
19484
+ * const values = await sdk.decryption.decryptValues([
19485
+ * { encryptedValue: balance, contractAddress: cUSDT },
19486
+ * ]);
19487
+ * console.log(values[balance]); // 1000n
19666
19488
  * ```
19667
19489
  */
19668
- balanceOf(owner: Address): Promise<bigint>;
19490
+ decryptValues(encryptedInput: EncryptedInput[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<Record<EncryptedValue, ClearValue>>;
19669
19491
  /**
19670
- * Return the raw encrypted balance without decrypting.
19492
+ * Decrypt one or more FHE encrypted values using delegated credentials.
19671
19493
  *
19672
- * @param owner - Balance owner address.
19673
- * @returns The encrypted balance as a hex string.
19494
+ * Mirrors {@link decryptValues} with delegated credentials — same caching and
19495
+ * zero-value short-circuit. Before reading from cache or calling the relayer,
19496
+ * every non-zero encrypted value's contract must have an active delegation from the
19497
+ * delegator to the connected signer; missing or expired delegations fail fast.
19498
+ *
19499
+ * @param encryptedInputs - FHE encrypted values paired with their contract addresses.
19500
+ * @param delegatorAddress - The address that granted delegation rights.
19501
+ * @param accountAddress - Address used as the cache key's "requester"
19502
+ * dimension. Defaults to `delegatorAddress`. Pass the actual account address
19503
+ * when decrypting on behalf of someone whose balance is stored under a
19504
+ * different address (e.g. `decryptBalanceAs` with an explicit `accountAddress`).
19505
+ * @param options - Delegated-decrypt options. By default the call rides out the
19506
+ * gateway propagation window ({@link DelegatedDecryptOptions.waitForPropagation});
19507
+ * pass `{ waitForPropagation: false }` to fail fast instead.
19508
+ * @returns Map of encrypted value → clear-text value.
19674
19509
  *
19675
19510
  * @example
19676
19511
  * ```ts
19677
- * const encryptedValue = await token.confidentialBalanceOf("0xOwner");
19678
- * ```
19679
- */
19680
- confidentialBalanceOf(owner: Address): Promise<EncryptedValue>;
19681
- /**
19682
- * Decrypt the balance of a delegator using delegated decryption credentials.
19683
- * The connected signer acts as the delegatee who has been granted permission
19684
- * by the delegator to decrypt their balance.
19685
- *
19686
- * Clear values are cached in storage keyed by `(account, token, encryptedValue)`.
19687
- * Because every on-chain balance change produces a new encrypted value,
19688
- * stale cache entries are never served. Cache write failures are silently
19689
- * ignored — they do not affect the returned value.
19690
- *
19691
- * @param delegatorAddress - The address of the account that delegated decryption rights.
19692
- * @param accountAddress - The account whose on-chain balance to read. Defaults
19693
- * to the delegator address.
19694
- * @returns The decrypted plaintext balance as a bigint.
19695
- * @throws if no active delegation exists. {@link DelegationNotFoundError}
19696
- * @throws if the delegation has expired. {@link DelegationExpiredError}
19697
- * @throws if delegated decryption fails. {@link DecryptionFailedError}
19698
- *
19699
- * @example
19700
- * ```ts
19701
- * const balance = await token.decryptBalanceAs({
19702
- * delegatorAddress: "0xDelegator",
19703
- * });
19512
+ * const values = await sdk.decryption.delegatedDecryptValues([
19513
+ * { encryptedValue: balance, contractAddress: tokenAddr },
19514
+ * ], delegatorAddr);
19515
+ * console.log(values[balance]); // 1000n
19704
19516
  * ```
19705
19517
  */
19706
- decryptBalanceAs({ delegatorAddress, accountAddress }: {
19707
- delegatorAddress: Address;
19708
- accountAddress?: Address;
19709
- }): Promise<bigint>;
19518
+ delegatedDecryptValues(encryptedInputs: EncryptedInput[], delegatorAddress: Address, accountAddress?: Address, options?: DelegatedDecryptOptions): Promise<Record<EncryptedValue, ClearValue>>;
19710
19519
  /**
19711
- * Decrypt confidential balances for multiple tokens in parallel, returning
19712
- * successes and per-token errors separately. Pre-authorizes all token
19713
- * addresses in a single wallet signature, then delegates each decrypt to
19714
- * `sdk.decryption.decryptValues`.
19520
+ * Publicly decrypt one or more FHE encrypted values.
19715
19521
  *
19716
- * Tokens that fail to decrypt land in `errors` rather than aborting the
19717
- * whole batch — caller decides how to surface them.
19522
+ * Signer-independent: works without a configured signer.
19523
+ * Returns the decryption proof alongside the clear-text values so callers
19524
+ * can submit on-chain finalization transactions (e.g. `finalizeUnwrap`).
19718
19525
  *
19719
- * @param tokens - Array of {@link Token} instances bound to the same SDK.
19720
- * @param owner - Balance owner address.
19721
- * @returns `{ results, errors }` partitioning the per-token outcomes.
19526
+ * @param encryptedValues - FHE encrypted values to decrypt publicly.
19527
+ * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.
19528
+ * @returns Clear-text values, ABI-encoded values, and the decryption proof.
19722
19529
  *
19723
19530
  * @example
19724
19531
  * ```ts
19725
- * const { results, errors } = await Token.batchBalancesOf(tokens, owner);
19532
+ * const { clearValues, decryptionProof, abiEncodedClearValues } =
19533
+ * await sdk.decryption.decryptPublicValues([encryptedValue]);
19726
19534
  * ```
19727
19535
  */
19728
- static batchBalancesOf(tokens: Token[], owner: Address): Promise<BatchBalancesResult>;
19536
+ decryptPublicValues(encryptedValues: EncryptedValue[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<DecryptPublicValuesResult>;
19729
19537
  /**
19730
- * Batch decrypt confidential balances as a delegate across multiple tokens.
19731
- * Mirrors {@link batchBalancesOf} but uses delegated credentials.
19538
+ * Batch-decrypt delegated encrypted values with per-entry error isolation.
19732
19539
  *
19733
- * **Error handling:** If a per-token decryption fails and no `onError` callback
19734
- * is provided, errors are collected and thrown as an aggregated
19735
- * `DecryptionFailedError`. When the relayer returns no value for an encrypted value,
19736
- * a `DecryptionFailedError` is thrown for that token (never silently returns `0n`).
19737
- * Pass `onError: () => 0n` to opt into the silent zero behavior.
19540
+ * Attempts a single batch request first. If the batch fails with a non-fatal
19541
+ * error (e.g. one entry is invalid), falls back to per-entry decryption so
19542
+ * healthy entries still resolve. Each item in the result carries either a
19543
+ * decrypted value or an error — callers decide how to surface partial failures.
19738
19544
  *
19739
- * @param tokens - Array of Token instances to decrypt balances for.
19740
- * @param options - Delegated decryption configuration.
19741
- * @returns A Map from token address to decrypted balance.
19742
- * @throws if no active delegation exists. {@link DelegationNotFoundError}
19743
- * @throws if the delegation has expired. {@link DelegationExpiredError}
19744
- * @throws if any decryption fails and no `onError` is provided. {@link DecryptionFailedError}
19545
+ * @param encryptedInputs - FHE encrypted values paired with their contract addresses.
19546
+ * @param delegatorAddress - The address that granted delegation rights.
19547
+ * @param accountAddress - The account on whose behalf decryption is performed. Defaults to `delegatorAddress`.
19548
+ * @param maxConcurrency - Maximum parallel decrypt calls during per-entry fallback.
19549
+ * @param waitForPropagation - Ride out the gateway propagation window on the
19550
+ * initial batch attempt (default `true`). See {@link DelegatedDecryptOptions.waitForPropagation}.
19551
+ * @returns Per-entry results, each with a value or an error.
19552
+ * @throws if no signer is configured. {@link SignerNotConfiguredError}
19553
+ * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19745
19554
  *
19746
19555
  * @example
19747
19556
  * ```ts
19748
- * const balances = await Token.batchDecryptBalancesAs(tokens, {
19557
+ * const result = await sdk.decryption.delegatedBatchDecryptValues({
19558
+ * encryptedInputs: [
19559
+ * { encryptedValue: encryptedValue1, contractAddress: tokenA },
19560
+ * { encryptedValue: encryptedValue2, contractAddress: tokenB },
19561
+ * ],
19749
19562
  * delegatorAddress: "0xDelegator",
19750
- * onError: (err, addr) => { console.error(addr, err); return 0n; },
19563
+ * maxConcurrency: 5,
19751
19564
  * });
19565
+ * for (const item of result.items) {
19566
+ * if (item.error) console.error(item.encryptedValue, item.error);
19567
+ * else console.log(item.encryptedValue, item.value);
19568
+ * }
19752
19569
  * ```
19753
19570
  */
19754
- static batchDecryptBalancesAs(tokens: Token[], options: BatchDecryptAsOptions): Promise<Map<Address, bigint>>;
19755
- private static readBalanceHandlesBatch;
19571
+ delegatedBatchDecryptValues({ encryptedInputs, delegatorAddress, accountAddress, maxConcurrency, waitForPropagation }: {
19572
+ encryptedInputs: EncryptedInput[];
19573
+ delegatorAddress: Address;
19574
+ accountAddress?: Address;
19575
+ maxConcurrency?: number;
19576
+ } & DelegatedDecryptOptions): Promise<BatchDecryptResult>;
19577
+ }
19578
+ //#endregion
19579
+ //#region src/namespaces/delegations.d.ts
19580
+ /**
19581
+ * Public namespace for on-chain decryption-delegation management.
19582
+ *
19583
+ * Exposed as `sdk.delegations`. Owns the SDK-level guards (signer requirement, chain
19584
+ * alignment, delegator address resolution from the wallet account) and delegates the
19585
+ * actual work to the internal {@link DelegationService}.
19586
+ *
19587
+ * Delegation operations write to the host chain ACL; after a delegation is mined,
19588
+ * the gateway syncs the ACL state via cross-chain event propagation — usually
19589
+ * within ~10 blocks (a few seconds). Delegated decryption rides out that window
19590
+ * with a bounded internal retry, so callers can decrypt right after granting.
19591
+ */
19592
+ declare class Delegations {
19593
+ #private;
19594
+ /** @internal */
19595
+ constructor(opts: {
19596
+ signer: GenericSigner | undefined;
19597
+ provider: GenericProvider;
19598
+ delegationService: DelegationService;
19599
+ });
19756
19600
  /**
19757
- * Confidential transfer. Encrypts the amount via FHE, then calls the contract.
19601
+ * Delegate decryption rights for a confidential contract to another address.
19602
+ * Calls `ACL.delegateForUserDecryption()` on-chain.
19758
19603
  *
19759
- * By default, the SDK validates the confidential balance before submitting.
19760
- * If a cached plaintext balance exists it is used; otherwise, if credentials
19761
- * are cached, it decrypts on the fly. Set `skipBalanceCheck: true` to bypass
19762
- * this validation (e.g. for smart wallets).
19604
+ * The delegation is recorded on L1 immediately, but the gateway must sync the
19605
+ * ACL state via cross-chain event propagation — usually within ~10 blocks (a
19606
+ * few seconds). You do not need to wait: delegated decryption rides out that
19607
+ * window with a bounded internal retry, so you can decrypt right after this
19608
+ * resolves.
19763
19609
  *
19764
- * @param to - Recipient address.
19765
- * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
19766
- * @param options - Optional: `skipBalanceCheck` (default `false`).
19610
+ * @param contractAddress - The confidential contract address to delegate on.
19611
+ * @param delegateAddress - Address to delegate decryption rights to.
19612
+ * @param expirationDate - Optional expiration date (defaults to permanent delegation via `uint64.max`).
19767
19613
  * @returns The transaction hash and mined receipt.
19614
+ * @throws if no signer is configured. {@link SignerNotConfiguredError}
19768
19615
  * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19769
- * @throws if the balance is less than `amount`. {@link InsufficientConfidentialBalanceError}
19770
- * @throws if balance validation requires decryption that is not possible. {@link BalanceCheckUnavailableError}
19771
- * @throws if FHE encryption fails. {@link EncryptionFailedError}
19772
- * @throws if the on-chain transfer reverts. {@link TransactionRevertedError}
19773
- *
19774
- * @example
19775
- * ```ts
19776
- * const txHash = await token.confidentialTransfer("0xRecipient", 1000n);
19777
- * ```
19778
- */
19779
- confidentialTransfer(to: Address, amount: bigint, options?: TransferOptions): Promise<TransactionResult>;
19780
- /**
19781
- * Operator encrypted transfer on behalf of another address.
19782
- * The caller must be an approved operator for `from`.
19783
- *
19784
- * @param from - The address to transfer from (caller must be an approved operator).
19785
- * @param to - Recipient address.
19786
- * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
19787
- * @returns The transaction hash and mined receipt.
19788
- *
19789
- * @example
19790
- * ```ts
19791
- * const txHash = await token.confidentialTransferFrom("0xFrom", "0xTo", 500n);
19792
- * ```
19616
+ * @throws if `expirationDate` is less than 1 hour in the future. {@link DelegationExpirationTooSoonError}
19617
+ * @throws if the delegate equals the connected wallet. {@link DelegationSelfNotAllowedError}
19618
+ * @throws if the delegate equals the contract address. {@link DelegationDelegateEqualsContractError}
19619
+ * @throws if the new expiry equals the current one. {@link DelegationExpiryUnchangedError}
19620
+ * @throws if the delegation transaction reverts. {@link TransactionRevertedError}
19793
19621
  */
19794
- confidentialTransferFrom(from: Address, to: Address, amount: bigint, callbacks?: TransferCallbacks): Promise<TransactionResult>;
19622
+ delegateDecryption({ contractAddress, delegateAddress, expirationDate }: {
19623
+ contractAddress: Address;
19624
+ delegateAddress: Address;
19625
+ expirationDate?: Date;
19626
+ }): Promise<TransactionResult>;
19795
19627
  /**
19796
- * ERC-7984 `confidentialTransferAndCall`: encrypted transfer that also invokes
19797
- * the recipient's receiver hook (`onConfidentialTransferReceived`) in a single
19798
- * transaction. The caller crafts the opaque `data` payload — the SDK does not
19799
- * encode, validate, or interpret it.
19800
- *
19801
- * Balance validation follows the same rules as {@link Token.confidentialTransfer}.
19628
+ * Revoke decryption delegation for a confidential contract.
19629
+ * Calls `ACL.revokeDelegationForUserDecryption()` on-chain.
19802
19630
  *
19803
- * @param to - Recipient address. Must implement the ERC-7984 receiver hook.
19804
- * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
19805
- * @param data - Opaque bytes forwarded to the recipient's receiver hook.
19806
- * @param options - Optional: `skipBalanceCheck` (default `false`).
19631
+ * @param contractAddress - The confidential contract address to revoke delegation on.
19632
+ * @param delegateAddress - Address to revoke delegation from.
19807
19633
  * @returns The transaction hash and mined receipt.
19808
- *
19634
+ * @throws if no signer is configured. {@link SignerNotConfiguredError}
19809
19635
  * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19810
- * @throws if the balance is less than `amount`. {@link InsufficientConfidentialBalanceError}
19811
- * @throws if balance validation requires decryption that is not possible. {@link BalanceCheckUnavailableError}
19812
- * @throws if FHE encryption fails. {@link EncryptionFailedError}
19813
- * @throws if the on-chain transfer reverts. {@link TransactionRevertedError}
19814
- *
19815
- * @example
19816
- * ```ts
19817
- * const txHash = await token.confidentialTransferAndCall(
19818
- * "0xRecipient",
19819
- * 1000n,
19820
- * "0xabcd", // caller-encoded payload forwarded to the receiver hook
19821
- * );
19822
- * ```
19636
+ * @throws if no delegation exists for this (delegator, delegate, contract) tuple. {@link DelegationNotFoundError}
19637
+ * @throws if the revocation transaction reverts. {@link TransactionRevertedError}
19823
19638
  */
19824
- confidentialTransferAndCall(to: Address, amount: bigint, data: Hex, options?: TransferOptions): Promise<TransactionResult>;
19639
+ revokeDelegation({ contractAddress, delegateAddress }: {
19640
+ contractAddress: Address;
19641
+ delegateAddress: Address;
19642
+ }): Promise<TransactionResult>;
19825
19643
  /**
19826
- * ERC-7984 `confidentialTransferFromAndCall`: operator-initiated encrypted
19827
- * transfer that also invokes the recipient's receiver hook in a single
19828
- * transaction. The caller must be an approved operator for `from` and crafts
19829
- * the opaque `data` payload — the SDK does not encode or interpret it.
19644
+ * Check whether a delegation is active for the given contract address.
19830
19645
  *
19831
- * @param from - The address to transfer from (caller must be an approved operator).
19832
- * @param to - Recipient address. Must implement the ERC-7984 receiver hook.
19833
- * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
19834
- * @param data - Opaque bytes forwarded to the recipient's receiver hook.
19835
- * @param callbacks - Optional progress callbacks.
19836
- * @returns The transaction hash and mined receipt.
19646
+ * Signer-independent: works without a configured signer.
19837
19647
  *
19838
- * @example
19839
- * ```ts
19840
- * const txHash = await token.confidentialTransferFromAndCall(
19841
- * "0xFrom",
19842
- * "0xRecipient",
19843
- * 500n,
19844
- * "0xabcd",
19845
- * );
19846
- * ```
19648
+ * @param contractAddress - The confidential contract address.
19649
+ * @param delegatorAddress - The address that granted the delegation.
19650
+ * @param delegateAddress - The address that received delegation rights.
19651
+ * @returns `true` if the delegation exists and has not expired.
19847
19652
  */
19848
- confidentialTransferFromAndCall(from: Address, to: Address, amount: bigint, data: Hex, callbacks?: TransferCallbacks): Promise<TransactionResult>;
19653
+ isActive(params: {
19654
+ contractAddress: Address;
19655
+ delegatorAddress: Address;
19656
+ delegateAddress: Address;
19657
+ }): Promise<boolean>;
19849
19658
  /**
19850
- * Set operator approval for the confidential token.
19851
- * Defaults to 1 hour from now if `until` is not specified.
19659
+ * Get the expiration timestamp of a delegation for the given contract.
19852
19660
  *
19853
- * @param operator - The address to set as an operator.
19854
- * @param until - Optional Unix timestamp for approval expiry. Defaults to now + 1 hour.
19855
- * @returns The transaction hash and mined receipt.
19661
+ * Signer-independent: works without a configured signer.
19856
19662
  *
19857
- * @example
19858
- * ```ts
19859
- * const txHash = await token.setOperator("0xOperator");
19860
- * ```
19663
+ * @param contractAddress - The confidential contract address.
19664
+ * @param delegatorAddress - The address that granted the delegation.
19665
+ * @param delegateAddress - The address that received delegation rights.
19666
+ * @returns Unix timestamp as bigint. `0n` = no delegation. `2^64 - 1` = permanent.
19861
19667
  */
19862
- setOperator(operator: Address, until?: number): Promise<TransactionResult>;
19668
+ getExpiry(params: {
19669
+ contractAddress: Address;
19670
+ delegatorAddress: Address;
19671
+ delegateAddress: Address;
19672
+ }): Promise<bigint>;
19673
+ }
19674
+ //#endregion
19675
+ //#region src/namespaces/permits.d.ts
19676
+ /**
19677
+ * Public namespace for permit and transport-key-pair management.
19678
+ *
19679
+ * Exposed as `sdk.permits`. Owns the SDK-level guards (chain alignment, empty-array
19680
+ * short-circuit, decrypt-cache invalidation) and delegates the actual work to the
19681
+ * internal {@link CredentialService}.
19682
+ *
19683
+ * The namespace is named `permits` because the user-facing concept is the signed-permit
19684
+ * store. The transport key pair is invisible plumbing — there is no `getTransportKeyPair()`
19685
+ * surfaced; the key pair exists to sign permits and is created automatically when needed.
19686
+ * {@link clear} wipes both the permit store and the transport key pair (permits
19687
+ * cascade-delete with the key pair).
19688
+ */
19689
+ declare class Permits {
19690
+ #private;
19691
+ /** @internal */
19692
+ constructor(opts: {
19693
+ signer: GenericSigner | undefined;
19694
+ provider: GenericProvider;
19695
+ cachingService: CachingService;
19696
+ credentialService: CredentialService | undefined;
19697
+ logger: GenericLogger;
19698
+ });
19863
19699
  /**
19864
- * Check if a spender is an approved operator for a given holder.
19700
+ * Sign and store an EIP-712 permit authorising direct decryption for the
19701
+ * given contract addresses.
19865
19702
  *
19866
- * @param holder - The token holder address.
19867
- * @param spender - The address to check operator approval for.
19868
- * @returns `true` if the spender is an approved operator for the holder.
19703
+ * Idempotent: if a permit covering the requested set already exists, no
19704
+ * wallet prompt occurs. Otherwise the SDK chunks the uncovered subset into
19705
+ * groups of ≤10 contracts and prompts once per chunk; partial mid-flight
19706
+ * rejection is preserved (already-signed chunks are persisted before the
19707
+ * next prompt).
19869
19708
  *
19870
- * @example
19871
- * ```ts
19872
- * if (await token.isOperator("0xHolder", "0xSpender")) {
19873
- * // spender can call transferFrom on behalf of holder
19874
- * }
19875
- * ```
19709
+ * @param contracts - Contract addresses to authorize.
19876
19710
  */
19877
- isOperator(holder: Address, spender: Address): Promise<boolean>;
19711
+ grantPermit(contracts: Address[]): Promise<void>;
19878
19712
  /**
19879
- * Read the on-chain encrypted balance for a given owner.
19713
+ * Sign and store an EIP-712 delegation permit authorising decryption on
19714
+ * behalf of `delegator`. Same idempotence/chunking semantics as {@link grantPermit}.
19880
19715
  *
19881
- * @internal
19716
+ * @param delegator - The address that delegated decryption rights to the connected signer.
19717
+ * @param contracts - Contract addresses to authorize.
19882
19718
  */
19883
- protected readConfidentialBalanceOf(owner: Address): Promise<EncryptedValue>;
19719
+ grantDelegationPermit(delegator: Address, contracts: Address[]): Promise<void>;
19884
19720
  /**
19885
- * Pre-flight check: decrypt the confidential balance and compare against the
19886
- * requested amount. If credentials are cached the decrypt happens silently;
19887
- * if not, throws {@link BalanceCheckUnavailableError} instead of triggering
19888
- * a surprise EIP-712 popup.
19721
+ * Pure store lookup: is there a permit covering `contracts`?
19722
+ * No wallet prompt, no transport key pair generation. Returns `false` when no signer
19723
+ * is configured.
19724
+ */
19725
+ hasPermit(contracts: Address[]): Promise<boolean>;
19726
+ /**
19727
+ * Pure store lookup for a delegation permit. See {@link hasPermit}.
19889
19728
  *
19890
- * @internal
19729
+ * @param delegator - The address that delegated decryption rights to the connected signer.
19730
+ * @param contracts - Contract addresses to check.
19731
+ * @returns `true` if cached delegation permits cover all requested contracts.
19891
19732
  */
19892
- protected assertConfidentialBalance(amount: bigint): Promise<void>;
19733
+ hasDelegationPermit(delegator: Address, contracts: Address[]): Promise<boolean>;
19893
19734
  /**
19894
- * Emit a token-scoped event through the owning {@link ZamaSDK} so that
19895
- * subscribers see a unified stream.
19735
+ * Best-effort transport-key-pair prefetch for the connected signer.
19896
19736
  *
19897
- * @internal
19737
+ * Optional latency optimization: decrypt and permit flows remain correct
19738
+ * without it because they lazily create the transport key pair when needed.
19739
+ *
19740
+ * Silent no-op when no signer is configured or no wallet account is
19741
+ * available. The transport key pair is generated through the relayer dispatcher's
19742
+ * currently active chain — see {@link LifecycleService}, which calls
19743
+ * `switchChain` before fanning the wallet-account change out to listeners,
19744
+ * so any downstream caller (including React adapters) observes the
19745
+ * dispatcher on the wallet chain by the time it invokes warmup.
19898
19746
  */
19899
- protected emit(input: ZamaSDKEventInput): void;
19747
+ warmTransportKeyPair(): Promise<void>;
19900
19748
  /**
19901
- * Submit a token-scoped write transaction through the shared SDK transaction
19902
- * pipeline. Callers keep pre-flight and operation-specific work local.
19749
+ * Wipe FHE permits for the current signer.
19903
19750
  *
19904
- * @internal
19751
+ * - With no argument: every permit referencing this signer is removed across
19752
+ * all chains and delegators. The transport key pair survives — use {@link clear} to
19753
+ * also wipe the transport key pair.
19754
+ * - With a contract list: every signed permit in the direct-decrypt scope
19755
+ * (current chain) whose immutable payload touches any listed address is
19756
+ * removed. Delegation permits are not touched in this mode.
19757
+ *
19758
+ * @throws if no signer is configured. {@link SignerNotConfiguredError}
19905
19759
  */
19906
- protected submitTransaction(params: {
19907
- operation: TransactionOperation;
19908
- config: WriteContractConfig;
19909
- onSubmitted?: (txHash: Hex) => void;
19910
- }): Promise<TransactionResult>;
19911
- /** Verify all tokens share the same SDK instance and return it. */
19912
- private static assertSameSdk;
19760
+ revokePermits(contracts?: Address[]): Promise<void>;
19761
+ /**
19762
+ * Wipe the transport key pair for the current signer and cascade-delete every permit
19763
+ * (across chains and delegators) referencing it.
19764
+ *
19765
+ * @throws if no signer is configured. {@link SignerNotConfiguredError}
19766
+ */
19767
+ clear(): Promise<void>;
19913
19768
  }
19914
19769
  //#endregion
19915
- //#region src/token/wrapped-token.d.ts
19770
+ //#region src/token/token.d.ts
19771
+ /** Options for {@link Token.batchDecryptBalancesAs}. */
19772
+ interface BatchDecryptAsOptions {
19773
+ /** The address of the account that delegated decryption rights. */
19774
+ delegatorAddress: Address;
19775
+ /** Pre-fetched encrypted values. When omitted, they are fetched from the chain. */
19776
+ encryptedValues?: EncryptedValue[];
19777
+ /**
19778
+ * The account whose on-chain balance to read. Defaults to the delegator
19779
+ * address, which is the common case (the delegator grants permission to
19780
+ * decrypt their own balance). Only set this when the account differs
19781
+ * from the delegator.
19782
+ *
19783
+ * Matches the `account` parameter of `confidentialBalanceOf(account)` on-chain.
19784
+ */
19785
+ accountAddress?: Address;
19786
+ /** Maximum number of concurrent decrypt calls. Default: 10. */
19787
+ maxConcurrency?: number;
19788
+ /** Called when decryption fails for a single token. Return a fallback bigint. */
19789
+ onError?: (error: Error, address: Address) => bigint;
19790
+ }
19791
+ /** Result of {@link Token.batchBalancesOf}. */
19792
+ interface BatchBalancesResult {
19793
+ /** Successfully decrypted balances, keyed by token address. */
19794
+ results: Map<Address, bigint>;
19795
+ /** Per-token errors for tokens that failed to decrypt. */
19796
+ errors: Map<Address, ZamaError>;
19797
+ }
19916
19798
  /**
19917
- * Confidential ERC-20 wrapper (ERC-7984 ERC20Wrapper).
19799
+ * High-level interface for an ERC-7984 confidential token.
19800
+ * Hides FHE complexity (encryption, decryption, EIP-712 signing) behind
19801
+ * familiar ERC-20-like methods.
19918
19802
  *
19919
- * Extends {@link Token} with wrapper-specific operations:
19920
- * - `shield` / `unshield` — convert between the underlying ERC-20 and confidential balance
19921
- * - `unwrap` / `unwrapAll` / `finalizeUnwrap` — low-level two-phase primitives
19922
- * - `underlying` / `allowance` — wrapper reads
19803
+ * For ERC-7984 wrappers (shield/unshield), use {@link WrappedToken} instead —
19804
+ * it extends `Token` with wrapper-specific operations.
19923
19805
  *
19924
- * `WrappedToken.address` is the wrapper contract address itself — the wrapper
19925
- * IS the confidential token.
19806
+ * Decryption, credentials, caching, and event emission are handled by the
19807
+ * owning {@link ZamaSDK} — this class only exposes token-scoped helpers
19808
+ * that delegate to `sdk.decryption.decryptValues` and `sdk.permits.grantPermit`.
19926
19809
  */
19927
- declare class WrappedToken extends Token {
19810
+ declare class Token {
19928
19811
  #private;
19812
+ readonly sdk: ZamaSDK;
19813
+ readonly address: Address;
19814
+ constructor(sdk: ZamaSDK, address: Address);
19815
+ /** Read the token name from the contract. */
19816
+ name(): Promise<string>;
19817
+ /** Read the token symbol from the contract. */
19818
+ symbol(): Promise<string>;
19819
+ /** Read the token decimals from the contract. */
19820
+ decimals(): Promise<number>;
19929
19821
  /**
19930
- * Read the underlying ERC-20 token address from the wrapper contract.
19822
+ * ERC-165 check for {@link ERC7984_INTERFACE_ID} support.
19931
19823
  *
19932
- * @returns The underlying ERC-20 token address.
19933
- */
19934
- underlying(): Promise<Address>;
19935
- /**
19936
- * Check whether the underlying ERC-20 supports ERC-1363 (payable token).
19937
- * Result is cached per WrappedToken instance (negative results included):
19938
- * once we know an underlying does not support ERC-1363, subsequent shields
19939
- * go straight to the `approve` + `wrap` path without re-probing.
19824
+ * @returns `true` if the contract implements the ERC-7984 confidential token interface.
19940
19825
  */
19941
- isPayable(): Promise<boolean>;
19826
+ isConfidential(): Promise<boolean>;
19942
19827
  /**
19943
- * Read the ERC-20 allowance granted by `owner` to this wrapper for the
19944
- * underlying token.
19828
+ * ERC-165 check for IERC7984ERC20Wrapper support.
19945
19829
  *
19946
- * @param owner - The owner address whose allowance to read.
19947
- * @returns The current allowance as a bigint.
19830
+ * @returns `true` if the contract implements the ERC-7984 wrapper interface
19831
+ * ({@link ERC7984_WRAPPER_INTERFACE_ID}, `0x1f1c62b2`).
19948
19832
  */
19949
- allowance(owner: Address): Promise<bigint>;
19833
+ isWrapper(): Promise<boolean>;
19950
19834
  /**
19951
- * Shield public ERC-20 tokens into confidential tokens.
19952
- *
19953
- * The execution path is decided automatically by ERC-165 introspection on
19954
- * the underlying ERC-20:
19955
- * - **`transferAndCall`** (single tx): when the underlying supports
19956
- * ERC-1363, no approval is required — the wrapper's `onTransferReceived`
19957
- * callback mints confidential tokens directly. `approvalStrategy` is
19958
- * **ignored** on this path. See {@link ShieldPath}.
19959
- * - **`approveAndWrap`** (two-tx fallback): otherwise, an `approve` is
19960
- * followed by a `wrap`. Approval is controlled by `approvalStrategy`
19961
- * (`"exact"` by default, `"max"` for unlimited, `"skip"` to opt out).
19962
- *
19963
- * The ERC-20 balance is validated before submitting (public read, no
19964
- * signing required) so the call works for all wallet types, including
19965
- * smart wallets.
19835
+ * Decrypt and return the plaintext balance for the given owner.
19836
+ * Acquires FHE credentials via a wallet signature if none are cached.
19966
19837
  *
19967
- * @param amount - The plaintext amount to shield.
19968
- * @param options - Optional: `approvalStrategy`, `to`, callbacks.
19969
- * @returns The transaction hash and mined receipt.
19970
- * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19971
- * @throws if the ERC-20 balance is less than `amount`. {@link InsufficientERC20BalanceError}
19972
- * @throws if the ERC-20 approval or shield transaction reverts. {@link TransactionRevertedError}
19838
+ * @param owner - Balance owner address.
19839
+ * @returns The decrypted plaintext balance as a bigint.
19840
+ * @throws if FHE decryption fails. {@link DecryptionFailedError}
19973
19841
  *
19974
19842
  * @example
19975
19843
  * ```ts
19976
- * const txHash = await wrappedToken.shield(1000n);
19844
+ * const balance = await token.balanceOf("0xOwner");
19977
19845
  * ```
19978
19846
  */
19979
- shield(amount: bigint, options?: ShieldOptions): Promise<TransactionResult>;
19847
+ balanceOf(owner: Address): Promise<bigint>;
19980
19848
  /**
19981
- * Approve this wrapper contract to spend the underlying ERC-20.
19982
- * Defaults to max uint256. Resets to zero first if there's an existing
19983
- * non-zero allowance (required by tokens like USDT).
19849
+ * Return the raw encrypted balance without decrypting.
19984
19850
  *
19985
- * @param amount - Optional approval amount. Defaults to max uint256.
19986
- * @returns The transaction hash and mined receipt.
19851
+ * @param owner - Balance owner address.
19852
+ * @returns The encrypted balance as a hex string.
19987
19853
  *
19988
19854
  * @example
19989
19855
  * ```ts
19990
- * await wrappedToken.approveUnderlying(); // max approval
19991
- * await wrappedToken.approveUnderlying(1000n); // exact amount
19856
+ * const encryptedValue = await token.confidentialBalanceOf("0xOwner");
19992
19857
  * ```
19993
19858
  */
19994
- approveUnderlying(amount?: bigint): Promise<TransactionResult>;
19859
+ confidentialBalanceOf(owner: Address): Promise<EncryptedValue>;
19995
19860
  /**
19996
- * Unshield a specific amount and finalize in one call.
19997
- * Orchestrates: unshield → wait for receipt → parse event → finalize.
19861
+ * Decrypt the balance of a delegator using delegated decryption credentials.
19862
+ * The connected signer acts as the delegatee who has been granted permission
19863
+ * by the delegator to decrypt their balance.
19998
19864
  *
19999
- * By default, the SDK validates the confidential balance before submitting.
20000
- * Set `skipBalanceCheck: true` to bypass this validation (e.g. for smart wallets).
19865
+ * Clear values are cached in storage keyed by `(account, token, encryptedValue)`.
19866
+ * Because every on-chain balance change produces a new encrypted value,
19867
+ * stale cache entries are never served. Cache write failures are silently
19868
+ * ignored — they do not affect the returned value.
20001
19869
  *
20002
- * @param amount - The plaintext amount to unshield.
20003
- * @param options - Optional: `skipBalanceCheck` (default `false`), callbacks.
20004
- * @returns The finalize transaction hash and mined receipt.
19870
+ * @param delegatorAddress - The address of the account that delegated decryption rights.
19871
+ * @param accountAddress - The account whose on-chain balance to read. Defaults
19872
+ * to the delegator address.
19873
+ * @returns The decrypted plaintext balance as a bigint.
19874
+ * @throws if no active delegation exists. {@link DelegationNotFoundError}
19875
+ * @throws if the delegation has expired. {@link DelegationExpiredError}
19876
+ * @throws if delegated decryption fails. {@link DecryptionFailedError}
20005
19877
  *
20006
19878
  * @example
20007
19879
  * ```ts
20008
- * const txHash = await wrappedToken.unshield(500n);
19880
+ * const balance = await token.decryptBalanceAs({
19881
+ * delegatorAddress: "0xDelegator",
19882
+ * });
20009
19883
  * ```
20010
19884
  */
20011
- unshield(amount: bigint, options?: UnshieldOptions): Promise<TransactionResult>;
19885
+ decryptBalanceAs({ delegatorAddress, accountAddress }: {
19886
+ delegatorAddress: Address;
19887
+ accountAddress?: Address;
19888
+ }): Promise<bigint>;
20012
19889
  /**
20013
- * Unshield the entire balance and finalize in one call.
20014
- * Orchestrates: unshieldAll → wait for receipt → parse event → finalize.
19890
+ * Decrypt confidential balances for multiple tokens in parallel, returning
19891
+ * successes and per-token errors separately. Pre-authorizes all token
19892
+ * addresses in a single wallet signature, then delegates each decrypt to
19893
+ * `sdk.decryption.decryptValues`.
20015
19894
  *
20016
- * @param callbacks - Optional progress callbacks for each phase.
20017
- * @returns The finalize transaction hash and mined receipt.
20018
- * @throws if the balance is zero. {@link DecryptionFailedError}
19895
+ * Tokens that fail to decrypt land in `errors` rather than aborting the
19896
+ * whole batch — caller decides how to surface them.
19897
+ *
19898
+ * @param tokens - Array of {@link Token} instances bound to the same SDK.
19899
+ * @param owner - Balance owner address.
19900
+ * @returns `{ results, errors }` partitioning the per-token outcomes.
20019
19901
  *
20020
19902
  * @example
20021
19903
  * ```ts
20022
- * const txHash = await wrappedToken.unshieldAll();
19904
+ * const { results, errors } = await Token.batchBalancesOf(tokens, owner);
20023
19905
  * ```
20024
19906
  */
20025
- unshieldAll(callbacks?: UnshieldCallbacks): Promise<TransactionResult>;
19907
+ static batchBalancesOf(tokens: Token[], owner: Address): Promise<BatchBalancesResult>;
20026
19908
  /**
20027
- * Resume an in-progress unshield from an existing unwrap tx hash.
20028
- * Useful when the user already submitted the unwrap but the finalize step
20029
- * was interrupted (e.g. page reload, network error).
19909
+ * Batch decrypt confidential balances as a delegate across multiple tokens.
19910
+ * Mirrors {@link batchBalancesOf} but uses delegated credentials.
20030
19911
  *
20031
- * @param unwrapTxHash - The transaction hash of the previously submitted unwrap.
20032
- * @param callbacks - Optional progress callbacks.
20033
- * @returns The finalize transaction hash and mined receipt.
19912
+ * **Error handling:** If a per-token decryption fails and no `onError` callback
19913
+ * is provided, errors are collected and thrown as an aggregated
19914
+ * `DecryptionFailedError`. When the relayer returns no value for an encrypted value,
19915
+ * a `DecryptionFailedError` is thrown for that token (never silently returns `0n`).
19916
+ * Pass `onError: () => 0n` to opt into the silent zero behavior.
19917
+ *
19918
+ * @param tokens - Array of Token instances to decrypt balances for.
19919
+ * @param options - Delegated decryption configuration.
19920
+ * @returns A Map from token address to decrypted balance.
19921
+ * @throws if no active delegation exists. {@link DelegationNotFoundError}
19922
+ * @throws if the delegation has expired. {@link DelegationExpiredError}
19923
+ * @throws if any decryption fails and no `onError` is provided. {@link DecryptionFailedError}
20034
19924
  *
20035
19925
  * @example
20036
19926
  * ```ts
20037
- * const txHash = await wrappedToken.resumeUnshield(previousUnwrapTxHash);
19927
+ * const balances = await Token.batchDecryptBalancesAs(tokens, {
19928
+ * delegatorAddress: "0xDelegator",
19929
+ * onError: (err, addr) => { console.error(addr, err); return 0n; },
19930
+ * });
20038
19931
  * ```
20039
19932
  */
20040
- resumeUnshield(unwrapTxHash: Hex, callbacks?: UnshieldCallbacks): Promise<TransactionResult>;
19933
+ static batchDecryptBalancesAs(tokens: Token[], options: BatchDecryptAsOptions): Promise<Map<Address, bigint>>;
19934
+ private static readBalanceHandlesBatch;
20041
19935
  /**
20042
- * Return the unwrap tx hash of an unshield that was interrupted between its
20043
- * two phases, or `null` if none is pending for this wrapper.
19936
+ * Confidential transfer. Encrypts the amount via FHE, then calls the contract.
20044
19937
  *
20045
- * The SDK persists this automatically when {@link unshield}/{@link unshieldAll}
20046
- * submit phase 1, and clears it once phase 2 finalizes. Use the returned hash
20047
- * to surface a "resume" affordance, then pass it to {@link resumeUnshield}.
20048
- * Resuming is intentionally caller-driven — auto-resuming on load would fire a
20049
- * wallet transaction unprompted.
19938
+ * By default, the SDK validates the confidential balance before submitting.
19939
+ * If a cached plaintext balance exists it is used; otherwise, if credentials
19940
+ * are cached, it decrypts on the fly. Set `skipBalanceCheck: true` to bypass
19941
+ * this validation (e.g. for smart wallets).
20050
19942
  *
20051
- * @returns The pending unwrap tx hash, or `null`.
19943
+ * @param to - Recipient address.
19944
+ * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
19945
+ * @param options - Optional: `skipBalanceCheck` (default `false`).
19946
+ * @returns The transaction hash and mined receipt.
19947
+ * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19948
+ * @throws if the balance is less than `amount`. {@link InsufficientConfidentialBalanceError}
19949
+ * @throws if balance validation requires decryption that is not possible. {@link BalanceCheckUnavailableError}
19950
+ * @throws if FHE encryption fails. {@link EncryptionFailedError}
19951
+ * @throws if the on-chain transfer reverts. {@link TransactionRevertedError}
20052
19952
  *
20053
19953
  * @example
20054
19954
  * ```ts
20055
- * const unwrapTxHash = await wrappedToken.getPendingUnshield();
20056
- * if (unwrapTxHash) await wrappedToken.resumeUnshield(unwrapTxHash);
19955
+ * const txHash = await token.confidentialTransfer("0xRecipient", 1000n);
20057
19956
  * ```
20058
19957
  */
20059
- getPendingUnshield(): Promise<Hex | null>;
19958
+ confidentialTransfer(to: Address, amount: bigint, options?: TransferOptions): Promise<TransactionResult>;
20060
19959
  /**
20061
- * Request an unwrap for a specific amount. Encrypts the amount first.
20062
- * Call {@link finalizeUnwrap} after the request is processed on-chain.
19960
+ * Operator encrypted transfer on behalf of another address.
19961
+ * The caller must be an approved operator for `from`.
20063
19962
  *
20064
- * @param amount - The plaintext amount to unwrap (encrypted automatically).
19963
+ * @param from - The address to transfer from (caller must be an approved operator).
19964
+ * @param to - Recipient address.
19965
+ * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
20065
19966
  * @returns The transaction hash and mined receipt.
20066
19967
  *
20067
19968
  * @example
20068
19969
  * ```ts
20069
- * const txHash = await wrappedToken.unwrap(500n);
19970
+ * const txHash = await token.confidentialTransferFrom("0xFrom", "0xTo", 500n);
20070
19971
  * ```
20071
19972
  */
20072
- unwrap(amount: bigint): Promise<TransactionResult>;
19973
+ confidentialTransferFrom(from: Address, to: Address, amount: bigint, callbacks?: TransferCallbacks): Promise<TransactionResult>;
20073
19974
  /**
20074
- * Request an unwrap for the entire confidential balance.
20075
- * Uses the on-chain encrypted balance directly (no encryption needed).
20076
- * Throws if the balance is zero.
19975
+ * ERC-7984 `confidentialTransferAndCall`: encrypted transfer that also invokes
19976
+ * the recipient's receiver hook (`onConfidentialTransferReceived`) in a single
19977
+ * transaction. The caller crafts the opaque `data` payload — the SDK does not
19978
+ * encode, validate, or interpret it.
20077
19979
  *
19980
+ * Balance validation follows the same rules as {@link Token.confidentialTransfer}.
19981
+ *
19982
+ * @param to - Recipient address. Must implement the ERC-7984 receiver hook.
19983
+ * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
19984
+ * @param data - Opaque bytes forwarded to the recipient's receiver hook.
19985
+ * @param options - Optional: `skipBalanceCheck` (default `false`).
20078
19986
  * @returns The transaction hash and mined receipt.
20079
- * @throws if the balance is zero. {@link DecryptionFailedError}
19987
+ *
19988
+ * @throws if signer and provider are on different chains. {@link ChainMismatchError}
19989
+ * @throws if the balance is less than `amount`. {@link InsufficientConfidentialBalanceError}
19990
+ * @throws if balance validation requires decryption that is not possible. {@link BalanceCheckUnavailableError}
19991
+ * @throws if FHE encryption fails. {@link EncryptionFailedError}
19992
+ * @throws if the on-chain transfer reverts. {@link TransactionRevertedError}
20080
19993
  *
20081
19994
  * @example
20082
19995
  * ```ts
20083
- * const txHash = await wrappedToken.unwrapAll();
19996
+ * const txHash = await token.confidentialTransferAndCall(
19997
+ * "0xRecipient",
19998
+ * 1000n,
19999
+ * "0xabcd", // caller-encoded payload forwarded to the receiver hook
20000
+ * );
20084
20001
  * ```
20085
20002
  */
20086
- unwrapAll(): Promise<TransactionResult>;
20003
+ confidentialTransferAndCall(to: Address, amount: bigint, data: Hex, options?: TransferOptions): Promise<TransactionResult>;
20087
20004
  /**
20088
- * Complete an unwrap by providing the public decryption proof.
20089
- * Call this after an unshield request has been processed on-chain.
20005
+ * ERC-7984 `confidentialTransferFromAndCall`: operator-initiated encrypted
20006
+ * transfer that also invokes the recipient's receiver hook in a single
20007
+ * transaction. The caller must be an approved operator for `from` and crafts
20008
+ * the opaque `data` payload — the SDK does not encode or interpret it.
20090
20009
  *
20091
- * @param unwrapRequestId - `unwrapRequestId` from the `UnwrapRequested` event.
20010
+ * @param from - The address to transfer from (caller must be an approved operator).
20011
+ * @param to - Recipient address. Must implement the ERC-7984 receiver hook.
20012
+ * @param amount - Plaintext amount to transfer (encrypted automatically via FHE).
20013
+ * @param data - Opaque bytes forwarded to the recipient's receiver hook.
20014
+ * @param callbacks - Optional progress callbacks.
20092
20015
  * @returns The transaction hash and mined receipt.
20093
20016
  *
20094
20017
  * @example
20095
20018
  * ```ts
20096
- * const event = findUnwrapRequested(receipt.logs);
20097
- * const txHash = await wrappedToken.finalizeUnwrap(event.unwrapRequestId);
20019
+ * const txHash = await token.confidentialTransferFromAndCall(
20020
+ * "0xFrom",
20021
+ * "0xRecipient",
20022
+ * 500n,
20023
+ * "0xabcd",
20024
+ * );
20098
20025
  * ```
20099
20026
  */
20100
- finalizeUnwrap(unwrapRequestId: EncryptedValue): Promise<TransactionResult>;
20101
- }
20102
- //#endregion
20103
- //#region src/query/confidential-balance.d.ts
20104
- interface ConfidentialBalanceQueryConfig {
20105
- tokenAddress: Address;
20106
- account?: Address;
20107
- query?: Record<string, unknown>;
20108
- }
20109
- /** Query options for a single confidential token balance. Auto-gated on `account`. */
20110
- declare function confidentialBalanceQueryOptions(token: Token, config: ConfidentialBalanceQueryConfig, signerContext?: SignerQueryContext): QueryFactoryOptions<bigint, Error, bigint, ReturnType<typeof zamaQueryKeys.confidentialBalance.owner>>;
20111
- //#endregion
20112
- //#region src/query/confidential-balances.d.ts
20113
- interface ConfidentialBalancesQueryConfig {
20114
- account?: Address;
20115
- query?: Record<string, unknown>;
20116
- }
20117
- declare function confidentialBalancesQueryOptions(tokens: Token[], config?: ConfidentialBalancesQueryConfig, signerContext?: SignerQueryContext): QueryFactoryOptions<BatchBalancesResult, Error, BatchBalancesResult, ReturnType<typeof zamaQueryKeys.confidentialBalances.tokens>>;
20118
- //#endregion
20119
- //#region src/query/wrappers-registry.d.ts
20120
- interface WrappersRegistryQueryConfig {
20121
- registryAddress: Address | undefined;
20122
- query?: Record<string, unknown>;
20123
- }
20124
- declare function tokenPairsQueryOptions(sdk: ZamaSDK, config: WrappersRegistryQueryConfig): QueryFactoryOptions<readonly TokenWrapperPair[], Error, readonly TokenWrapperPair[], ReturnType<typeof zamaQueryKeys.wrappersRegistry.tokenPairs>>;
20125
- interface ConfidentialTokenAddressQueryConfig extends WrappersRegistryQueryConfig {
20126
- tokenAddress?: Address;
20127
- }
20128
- declare function confidentialTokenAddressQueryOptions(sdk: ZamaSDK, config: ConfidentialTokenAddressQueryConfig): QueryFactoryOptions<readonly [boolean, Address], Error, readonly [boolean, Address], ReturnType<typeof zamaQueryKeys.wrappersRegistry.confidentialTokenAddress>>;
20129
- interface TokenAddressQueryConfig extends WrappersRegistryQueryConfig {
20130
- confidentialTokenAddress?: Address;
20131
- }
20132
- declare function tokenAddressQueryOptions(sdk: ZamaSDK, config: TokenAddressQueryConfig): QueryFactoryOptions<readonly [boolean, Address], Error, readonly [boolean, Address], ReturnType<typeof zamaQueryKeys.wrappersRegistry.tokenAddress>>;
20133
- declare function tokenPairsLengthQueryOptions(sdk: ZamaSDK, config: WrappersRegistryQueryConfig): QueryFactoryOptions<bigint, Error, bigint, ReturnType<typeof zamaQueryKeys.wrappersRegistry.tokenPairsLength>>;
20134
- interface TokenPairsSliceQueryConfig extends WrappersRegistryQueryConfig {
20135
- fromIndex?: bigint;
20136
- toIndex?: bigint;
20137
- }
20138
- declare function tokenPairsSliceQueryOptions(sdk: ZamaSDK, config: TokenPairsSliceQueryConfig): QueryFactoryOptions<readonly TokenWrapperPair[], Error, readonly TokenWrapperPair[], ReturnType<typeof zamaQueryKeys.wrappersRegistry.tokenPairsSlice>>;
20139
- interface TokenPairQueryConfig extends WrappersRegistryQueryConfig {
20140
- index?: bigint;
20141
- }
20142
- declare function tokenPairQueryOptions(sdk: ZamaSDK, config: TokenPairQueryConfig): QueryFactoryOptions<TokenWrapperPair, Error, TokenWrapperPair, ReturnType<typeof zamaQueryKeys.wrappersRegistry.tokenPair>>;
20143
- interface IsConfidentialTokenValidQueryConfig extends WrappersRegistryQueryConfig {
20144
- confidentialTokenAddress?: Address;
20145
- }
20146
- declare function isConfidentialTokenValidQueryOptions(sdk: ZamaSDK, config: IsConfidentialTokenValidQueryConfig): QueryFactoryOptions<boolean, Error, boolean, ReturnType<typeof zamaQueryKeys.wrappersRegistry.isConfidentialTokenValid>>;
20147
- interface ListPairsQueryConfig {
20148
- /**
20149
- * The registry address for this chain — used as a query key discriminator.
20150
- * The registry instance already knows how to resolve the address for the
20151
- * current chain; this field just keeps the TanStack Query cache isolated
20152
- * per registry contract.
20153
- */
20154
- registryAddress: Address | undefined;
20155
- page?: number;
20156
- pageSize?: number;
20157
- metadata?: boolean;
20158
- query?: Record<string, unknown>;
20159
- }
20160
- /**
20161
- * Query options for paginated listing of token wrapper pairs.
20162
- *
20163
- * Accepts a {@link WrappersRegistry} instance rather than a raw provider so that the
20164
- * class-level TTL cache is shared across multiple `queryFn` executions. Pass
20165
- * `sdk.registry` (the ZamaSDK lazy singleton) to ensure a single shared cache.
20166
- */
20167
- declare function listPairsQueryOptions(registry: WrappersRegistry, config: ListPairsQueryConfig): QueryFactoryOptions<PaginatedResult<TokenWrapperPair | TokenWrapperPairWithMetadata>, Error, PaginatedResult<TokenWrapperPair | TokenWrapperPairWithMetadata>, ReturnType<typeof zamaQueryKeys.wrappersRegistry.listPairs>>;
20168
- //#endregion
20169
- //#region src/query/shield.d.ts
20170
- /** Variables for {@link shieldMutationOptions}. */
20171
- interface ShieldParams extends ShieldOptions {
20172
- amount: bigint;
20173
- }
20174
- declare function shieldMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.shield", Address], ShieldParams, TransactionResult>;
20175
- //#endregion
20176
- //#region src/query/transfer.d.ts
20177
- /** Variables for {@link confidentialTransferMutationOptions}. */
20178
- interface ConfidentialTransferParams extends TransferOptions {
20179
- to: Address;
20180
- amount: bigint;
20181
- }
20182
- declare function confidentialTransferMutationOptions(token: Token): MutationFactoryOptions<readonly ["zama.confidentialTransfer", Address], ConfidentialTransferParams, TransactionResult>;
20183
- //#endregion
20184
- //#region src/query/transfer-and-call.d.ts
20185
- /** Variables for {@link confidentialTransferAndCallMutationOptions}. */
20186
- interface ConfidentialTransferAndCallParams extends TransferOptions {
20187
- to: Address;
20188
- amount: bigint;
20189
- /** Opaque bytes forwarded to the recipient's ERC-7984 receiver hook. */
20190
- data: Hex;
20191
- }
20192
- declare function confidentialTransferAndCallMutationOptions(token: Token): MutationFactoryOptions<readonly ["zama.confidentialTransferAndCall", Address], ConfidentialTransferAndCallParams, TransactionResult>;
20193
- //#endregion
20194
- //#region src/query/transfer-from.d.ts
20195
- /** Variables for {@link confidentialTransferFromMutationOptions}. */
20196
- interface ConfidentialTransferFromParams {
20197
- from: Address;
20198
- to: Address;
20199
- amount: bigint;
20200
- /** Optional progress callbacks for the multi-step transfer flow. */
20201
- callbacks?: TransferCallbacks;
20202
- }
20203
- declare function confidentialTransferFromMutationOptions(token: Token): MutationFactoryOptions<readonly ["zama.confidentialTransferFrom", Address], ConfidentialTransferFromParams, TransactionResult>;
20204
- //#endregion
20205
- //#region src/query/transfer-from-and-call.d.ts
20206
- /** Variables for {@link confidentialTransferFromAndCallMutationOptions}. */
20207
- interface ConfidentialTransferFromAndCallParams {
20208
- from: Address;
20209
- to: Address;
20210
- amount: bigint;
20211
- /** Opaque bytes forwarded to the recipient's ERC-7984 receiver hook. */
20212
- data: Hex;
20213
- /** Optional progress callbacks for the multi-step transfer flow. */
20214
- callbacks?: TransferCallbacks;
20215
- }
20216
- declare function confidentialTransferFromAndCallMutationOptions(token: Token): MutationFactoryOptions<readonly ["zama.confidentialTransferFromAndCall", Address], ConfidentialTransferFromAndCallParams, TransactionResult>;
20217
- //#endregion
20218
- //#region src/query/set-operator.d.ts
20219
- /** Variables for {@link confidentialSetOperatorMutationOptions}. */
20220
- interface ConfidentialSetOperatorParams {
20221
- operator: Address;
20222
- until?: number;
20223
- }
20224
- declare function confidentialSetOperatorMutationOptions(token: Token): MutationFactoryOptions<readonly ["zama.confidentialSetOperator", Address], ConfidentialSetOperatorParams, TransactionResult>;
20225
- //#endregion
20226
- //#region src/query/approve-underlying.d.ts
20227
- /** Variables for {@link approveUnderlyingMutationOptions}. */
20228
- interface ApproveUnderlyingParams {
20229
- amount?: bigint;
20230
- }
20231
- declare function approveUnderlyingMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.approveUnderlying", Address], ApproveUnderlyingParams, TransactionResult>;
20232
- //#endregion
20233
- //#region src/query/unshield.d.ts
20234
- /** Variables for {@link unshieldMutationOptions}. */
20235
- interface UnshieldParams extends UnshieldOptions {
20236
- amount: bigint;
20237
- }
20238
- declare function unshieldMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.unshield", Address], UnshieldParams, TransactionResult>;
20239
- //#endregion
20240
- //#region src/query/unshield-all.d.ts
20241
- /** Variables for {@link unshieldAllMutationOptions}. */
20242
- interface UnshieldAllParams extends UnshieldCallbacks {}
20243
- declare function unshieldAllMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.unshieldAll", Address], UnshieldAllParams | void, TransactionResult>;
20244
- //#endregion
20245
- //#region src/query/resume-unshield.d.ts
20246
- /** Variables for {@link resumeUnshieldMutationOptions}. */
20247
- interface ResumeUnshieldParams extends UnshieldCallbacks {
20248
- unwrapTxHash: Hex;
20249
- }
20250
- declare function resumeUnshieldMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.resumeUnshield", Address], ResumeUnshieldParams, TransactionResult>;
20251
- //#endregion
20252
- //#region src/query/unwrap.d.ts
20253
- /** Variables for {@link unwrapMutationOptions}. */
20254
- interface UnwrapParams {
20255
- amount: bigint;
20256
- }
20257
- declare function unwrapMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.unwrap", Address], UnwrapParams, TransactionResult>;
20258
- //#endregion
20259
- //#region src/query/unwrap-all.d.ts
20260
- declare function unwrapAllMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.unwrapAll", Address], void, TransactionResult>;
20261
- //#endregion
20262
- //#region src/query/finalize-unwrap.d.ts
20263
- /** Variables for {@link finalizeUnwrapMutationOptions}. */
20264
- type FinalizeUnwrapParams = {
20265
- /** Identifier from an `UnwrapRequested` event. */
20266
- unwrapRequestId: EncryptedValue;
20267
- };
20268
- declare function finalizeUnwrapMutationOptions(token: WrappedToken): MutationFactoryOptions<readonly ["zama.finalizeUnwrap", Address], FinalizeUnwrapParams, TransactionResult>;
20269
- //#endregion
20270
- //#region src/query/encrypt.d.ts
20271
- declare function encryptMutationOptions(sdk: ZamaSDK): MutationFactoryOptions<readonly ["zama.encrypt"], EncryptParams, EncryptResult>;
20272
- //#endregion
20273
- //#region src/query/user-decrypt.d.ts
20274
- interface EncryptedInput {
20275
- encryptedValue: EncryptedValue;
20276
- contractAddress: Address;
20277
- }
20278
- /** Decrypted clear values keyed by encrypted handle. */
20279
- type DecryptResult = Readonly<Record<EncryptedValue, ClearValue>>;
20280
- declare function decryptValuesQueryOptions(sdk: ZamaSDK, encryptedInputs: EncryptedInput[], signerContext?: SignerQueryContext): QueryFactoryOptions<DecryptResult, Error, DecryptResult, ReturnType<typeof zamaQueryKeys.decryption.encryptedInputs>>;
20281
- //#endregion
20282
- //#region src/query/delegated-decrypt.d.ts
20283
- interface DelegatedDecryptValuesMutationParams {
20284
- encryptedInputs: EncryptedInput[];
20285
- delegatorAddress: Address;
20286
- }
20287
- declare function delegatedDecryptValuesMutationOptions(sdk: ZamaSDK): MutationFactoryOptions<readonly ["zama.delegatedDecryptValues"], DelegatedDecryptValuesMutationParams, Readonly<Record<EncryptedValue, ClearValue>>>;
20288
- //#endregion
20289
- //#region src/query/public-decrypt.d.ts
20290
- declare function decryptPublicValuesMutationOptions(sdk: ZamaSDK): MutationFactoryOptions<readonly ["zama.decryptPublicValues"], EncryptedValue[], DecryptPublicValuesResult>;
20291
- //#endregion
20292
- //#region src/query/grant-permit.d.ts
20293
- declare function grantPermitMutationOptions(sdk: ZamaSDK): MutationFactoryOptions<readonly ["zama.grantPermit"], Address[], void>;
20294
- //#endregion
20295
- //#region src/query/has-permit.d.ts
20296
- interface HasPermitQueryConfig {
20297
- /** Contract addresses to check credentials against. */
20298
- contractAddresses: Address[];
20299
- /**
20300
- * Standard TanStack query options. `hasPermit` intentionally overrides cache
20301
- * timing because permit state is wallet-local, not server state: every fetch
20302
- * should read the SDK credential service directly.
20303
- */
20304
- query?: Record<string, unknown>;
20305
- }
20306
- declare function hasPermitQueryOptions(sdk: ZamaSDK, config: HasPermitQueryConfig, signerContext?: SignerQueryContext): QueryFactoryOptions<boolean, Error, boolean, ReturnType<typeof zamaQueryKeys.hasPermit.scope>>;
20307
- //#endregion
20308
- //#region src/query/revoke-permits.d.ts
20309
- /** TanStack Query mutation factory for {@link Permits.revokePermits}. */
20310
- declare function revokePermitsMutationOptions(sdk: ZamaSDK): MutationFactoryOptions<readonly ["zama.revokePermits"], Address[] | void, void>;
20311
- //#endregion
20312
- //#region src/query/clear-credentials.d.ts
20313
- /** TanStack Query mutation factory for {@link Permits.clear}. */
20314
- declare function clearCredentialsMutationOptions(sdk: ZamaSDK): MutationFactoryOptions<readonly ["zama.clearCredentials"], void, void>;
20315
- //#endregion
20316
- //#region src/query/delegate-decryption.d.ts
20317
- /** Variables for {@link delegateDecryptionMutationOptions}. */
20318
- interface DelegateDecryptionParams {
20319
- delegateAddress: Address;
20320
- expirationDate?: Date;
20321
- }
20322
- declare function delegateDecryptionMutationOptions(sdk: ZamaSDK, contractAddress: Address): MutationFactoryOptions<readonly ["zama.delegateDecryption", Address], DelegateDecryptionParams, TransactionResult>;
20323
- //#endregion
20324
- //#region src/query/decrypt-balance-as.d.ts
20325
- /** Variables for {@link decryptBalanceAsMutationOptions}. */
20326
- interface DecryptBalanceAsParams {
20327
- delegatorAddress: Address;
20328
- accountAddress?: Address;
20329
- }
20330
- declare function decryptBalanceAsMutationOptions(token: Token): MutationFactoryOptions<readonly ["zama.decryptBalanceAs", Address], DecryptBalanceAsParams, bigint>;
20331
- //#endregion
20332
- //#region src/query/batch-decrypt-balances-as.d.ts
20333
- /** Variables for {@link batchDecryptBalancesAsMutationOptions}. */
20334
- type BatchDecryptBalancesAsParams = BatchDecryptAsOptions;
20335
- declare function batchDecryptBalancesAsMutationOptions(tokens: Token[]): MutationFactoryOptions<readonly ["zama.batchDecryptBalancesAs", ...Address[]], BatchDecryptBalancesAsParams, Map<Address, bigint>>;
20336
- //#endregion
20337
- //#region src/query/revoke-delegation.d.ts
20338
- /** Variables for {@link revokeDelegationMutationOptions}. */
20339
- interface RevokeDelegationParams {
20340
- delegateAddress: Address;
20341
- }
20342
- declare function revokeDelegationMutationOptions(sdk: ZamaSDK, contractAddress: Address): MutationFactoryOptions<readonly ["zama.revokeDelegation", Address], RevokeDelegationParams, TransactionResult>;
20343
- //#endregion
20344
- //#region src/query/delegation-status.d.ts
20345
- interface DelegationStatusData {
20346
- isActive: boolean;
20347
- expiryTimestamp: bigint;
20348
- }
20349
- interface DelegationStatusQueryConfig {
20350
- contractAddress: Address | undefined;
20351
- delegatorAddress?: Address;
20352
- delegateAddress?: Address;
20353
- query?: Record<string, unknown>;
20354
- }
20355
- declare function delegationStatusQueryOptions(sdk: ZamaSDK, config: DelegationStatusQueryConfig): QueryFactoryOptions<DelegationStatusData, Error, DelegationStatusData, ReturnType<typeof zamaQueryKeys.delegationStatus.scope>>;
20356
- //#endregion
20357
- //#region src/credentials/credential-service.d.ts
20358
- /** Configuration for {@link CredentialService}. TTLs are pre-validated by the caller. */
20359
- interface CredentialServiceConfig {
20360
- router: ChainRouter;
20361
- signer: GenericSigner;
20362
- /** Transport key pair lifetime in seconds. Pre-validated. */
20363
- transportKeyPairTTL: number;
20364
- /** Permit lifetime in days. Pre-validated. */
20365
- permitTTL: number;
20366
- /** Backing storage for transport key pairs (and permits if `permitStorage` is omitted). */
20367
- storage: GenericStorage;
20368
- /** Optional dedicated storage for permits; defaults to `storage`. */
20369
- permitStorage?: GenericStorage;
20370
- /** SDK-wide logger for credential-path diagnostics. */
20371
- logger: GenericLogger;
20372
- }
20373
- /**
20374
- * Single facade coordinating the keypair vault and the permission store.
20375
- *
20376
- * `CredentialService` is the only credentials object held by `ZamaSDK`. It accepts identity
20377
- * transitions via `handleWalletAccountChange`.
20378
- */
20379
- declare class CredentialService {
20380
- #private;
20381
- constructor(config: CredentialServiceConfig);
20027
+ confidentialTransferFromAndCall(from: Address, to: Address, amount: bigint, data: Hex, callbacks?: TransferCallbacks): Promise<TransactionResult>;
20382
20028
  /**
20383
- * Resolve a keypair and permissions covering `contracts`, minimizing wallet
20384
- * prompts by reusing or widening existing permits where possible. Empty
20385
- * `contracts` warms the keypair without prompting.
20029
+ * Set operator approval for the confidential token.
20030
+ * Defaults to 1 hour from now if `until` is not specified.
20386
20031
  *
20387
- * @returns The resolved keypair and permits covering the requested contracts.
20388
- * @throws if the user rejects a wallet signature prompt. {@link SigningRejectedError}
20389
- * @throws if signing fails for any other reason. {@link SigningFailedError}
20390
- */
20391
- grantPermit(contracts: readonly Address[], delegator?: Address): Promise<SerializedTransportKeyPairWithPermissions>;
20392
- /**
20393
- * Pure store lookup: are stored permits sufficient to cover `contracts`? No wallet prompt.
20032
+ * @param operator - The address to set as an operator.
20033
+ * @param until - Optional Unix timestamp for approval expiry. Defaults to now + 1 hour.
20034
+ * @returns The transaction hash and mined receipt.
20394
20035
  *
20395
- * @returns `true` if cached permits cover all requested contracts (vacuously
20396
- * true for an empty list); `false` if no keypair exists or coverage is
20397
- * incomplete.
20036
+ * @example
20037
+ * ```ts
20038
+ * const txHash = await token.setOperator("0xOperator");
20039
+ * ```
20398
20040
  */
20399
- hasPermit(contracts: readonly Address[], delegator?: Address): Promise<boolean>;
20041
+ setOperator(operator: Address, until?: number): Promise<TransactionResult>;
20400
20042
  /**
20401
- * Wipe FHE permits for the current signer.
20043
+ * Check if a spender is an approved operator for a given holder.
20402
20044
  *
20403
- * - With no argument: every permit referencing this signer is removed across
20404
- * all chains and delegators. The keypair survives — use
20405
- * {@link clearCredentials} to also wipe the keypair.
20406
- * - With a contract list: every signed permit in the direct-decrypt scope
20407
- * (current chain) whose immutable payload touches any listed address is
20408
- * removed. Delegated permits are not touched in this mode.
20045
+ * @param holder - The token holder address.
20046
+ * @param spender - The address to check operator approval for.
20047
+ * @returns `true` if the spender is an approved operator for the holder.
20409
20048
  *
20410
- * @throws if reading the signer address fails. {@link SigningFailedError}
20049
+ * @example
20050
+ * ```ts
20051
+ * if (await token.isOperator("0xHolder", "0xSpender")) {
20052
+ * // spender can call transferFrom on behalf of holder
20053
+ * }
20054
+ * ```
20411
20055
  */
20412
- revokePermits(contracts?: readonly Address[]): Promise<void>;
20056
+ isOperator(holder: Address, spender: Address): Promise<boolean>;
20413
20057
  /**
20414
- * Wipe the keypair for the current signer and cascade-delete every
20415
- * permission referencing it across all chains and delegators.
20058
+ * Read the on-chain encrypted balance for a given owner.
20416
20059
  *
20417
- * @throws if reading the signer address fails. {@link SigningFailedError}
20060
+ * @internal
20418
20061
  */
20419
- clearCredentials(): Promise<void>;
20062
+ protected readConfidentialBalanceOf(owner: Address): Promise<EncryptedValue>;
20420
20063
  /**
20421
- * Warm the signer transport key pair cache for a known address.
20064
+ * Pre-flight check: decrypt the confidential balance and compare against the
20065
+ * requested amount. If credentials are cached the decrypt happens silently;
20066
+ * if not, throws {@link BalanceCheckUnavailableError} instead of triggering
20067
+ * a surprise EIP-712 popup.
20422
20068
  *
20423
- * Best-effort prefetch primitive: correctness still comes from `grantPermit`,
20424
- * which lazily creates the transport key pair when needed. Errors (storage failure,
20425
- * relayer 4xx, missing Worker in SSR) are **not** swallowed here — the caller
20426
- * decides whether to log, ignore, or surface them.
20069
+ * @internal
20427
20070
  */
20428
- warmTransportKeyPair(address: Address): Promise<void>;
20071
+ protected assertConfidentialBalance(amount: bigint): Promise<void>;
20429
20072
  /**
20430
- * Apply a wallet account transition.
20073
+ * Emit a token-scoped event through the owning {@link ZamaSDK} so that
20074
+ * subscribers see a unified stream.
20431
20075
  *
20432
- * Address change clears persisted credentials for the previous account.
20433
- * Chain-only changes keep credentials intact because permits are chain-scoped
20434
- * already and stale decrypt plaintext is cleared by `ZamaSDK`.
20076
+ * @internal
20435
20077
  */
20436
- handleWalletAccountChange(prev?: {
20437
- address: Address;
20438
- }, next?: {
20439
- address: Address;
20440
- }): Promise<void>;
20441
- }
20442
- //#endregion
20443
- //#region src/services/caching-service.d.ts
20444
- /**
20445
- * Storage-backed cache for decrypted FHE plaintext values.
20446
- *
20447
- * Each entry is keyed by `(requester, contractAddress, handle)` so different
20448
- * signers cannot read each other's cached decryptions.
20449
- */
20450
- declare class CachingService {
20451
- #private;
20452
- constructor(storage: GenericStorage, logger: GenericLogger);
20453
- get(requester: Address, contractAddress: Address, encryptedValue: EncryptedValue): Promise<ClearValue | null>;
20454
- set(requester: Address, contractAddress: Address, encryptedValue: EncryptedValue, value: ClearValue): Promise<void>;
20455
- delete(requester: Address, contractAddress: Address, encryptedValue: EncryptedValue): Promise<void>;
20456
- clearForRequester(requester: Address): Promise<void>;
20457
- clearAll(): Promise<void>;
20458
- }
20459
- //#endregion
20460
- //#region src/services/delegation-service.d.ts
20461
- declare class DelegationService {
20462
- #private;
20463
- constructor({ provider, router, emitEvent, logger }: {
20464
- provider: GenericProvider;
20465
- router: ChainRouter;
20466
- logger: GenericLogger;
20467
- emitEvent?: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;
20468
- });
20469
- delegateDecryption(signer: GenericSigner, { contractAddress, delegateAddress, delegatorAddress, expirationDate }: {
20470
- contractAddress: Address;
20471
- delegateAddress: Address;
20472
- delegatorAddress: Address;
20473
- expirationDate?: Date;
20474
- }): Promise<TransactionResult>;
20475
- revokeDelegation(signer: GenericSigner, { contractAddress, delegateAddress, delegatorAddress }: {
20476
- contractAddress: Address;
20477
- delegateAddress: Address;
20478
- delegatorAddress: Address;
20479
- }): Promise<TransactionResult>;
20480
- isDelegated(params: {
20481
- contractAddress: Address;
20482
- delegatorAddress: Address;
20483
- delegateAddress: Address;
20484
- }): Promise<boolean>;
20485
- getDelegationExpiry({ contractAddress, delegatorAddress, delegateAddress }: {
20486
- contractAddress: Address;
20487
- delegatorAddress: Address;
20488
- delegateAddress: Address;
20489
- }): Promise<bigint>;
20490
- findInactiveDelegations(contractAddresses: readonly Address[], delegatorAddress: Address, delegateAddress: Address): Promise<Map<Address, DelegationNotFoundError | DelegationExpiredError>>;
20491
- assertDelegationActive(contractAddress: Address, delegatorAddress: Address, delegateAddress: Address): Promise<void>;
20492
- }
20493
- //#endregion
20494
- //#region src/services/decryption-service.d.ts
20495
- /** Options shared by the delegated-decrypt entry points. */
20496
- interface DelegatedDecryptOptions {
20078
+ protected emit(input: ZamaSDKEventInput): void;
20497
20079
  /**
20498
- * Ride out the gateway propagation window: when a just-granted delegation
20499
- * has not yet synced, the delegated decrypt is retried (bounded, ~30s) until
20500
- * it lands instead of throwing {@link DelegationNotPropagatedError}. Defaults
20501
- * to `true`. Pass `false` to fail fast on the first not-propagated response.
20080
+ * Submit a token-scoped write transaction through the shared SDK transaction
20081
+ * pipeline. Callers keep pre-flight and operation-specific work local.
20082
+ *
20083
+ * @internal
20502
20084
  */
20503
- waitForPropagation?: boolean;
20504
- }
20505
- interface BatchDecryptItem {
20506
- encryptedValue: EncryptedValue;
20507
- contractAddress: Address;
20508
- value?: ClearValue;
20509
- error?: ZamaError;
20510
- }
20511
- interface BatchDecryptResult {
20512
- items: BatchDecryptItem[];
20513
- }
20514
- declare class DecryptionService {
20515
- #private;
20516
- constructor({ cache, credentialService, delegationService, router, emitEvent }: {
20517
- cache: CachingService;
20518
- credentialService: CredentialService;
20519
- delegationService: DelegationService;
20520
- router: ChainRouter;
20521
- emitEvent: (input: ZamaSDKEventInput) => void;
20522
- });
20523
- decryptValues(handles: EncryptedInput[], signerAddress: Address, opts?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<Record<EncryptedValue, ClearValue>>;
20524
- delegatedDecryptValues(encryptedInputs: EncryptedInput[], delegatorAddress: Address, delegateAddress: Address, accountAddress: Address, opts?: DelegatedDecryptOptions): Promise<Record<EncryptedValue, ClearValue>>;
20525
- delegatedBatchDecryptHandlesAs({ encryptedInputs, delegatorAddress, delegateAddress, accountAddress, maxConcurrency, waitForPropagation }: {
20526
- encryptedInputs: EncryptedInput[];
20527
- delegatorAddress: Address;
20528
- delegateAddress: Address;
20529
- accountAddress: Address;
20530
- maxConcurrency?: number;
20531
- waitForPropagation?: boolean;
20532
- }): Promise<BatchDecryptResult>;
20085
+ protected submitTransaction(params: {
20086
+ operation: TransactionOperation;
20087
+ config: WriteContractConfig;
20088
+ onSubmitted?: (txHash: Hex) => void;
20089
+ }): Promise<TransactionResult>;
20090
+ /** Verify all tokens share the same SDK instance and return it. */
20091
+ private static assertSameSdk;
20533
20092
  }
20534
20093
  //#endregion
20535
- //#region src/namespaces/decryption.d.ts
20094
+ //#region src/token/wrapped-token.d.ts
20536
20095
  /**
20537
- * Public namespace for FHE decryption — the canonical way to decrypt.
20538
- *
20539
- * Exposed as `sdk.decryption`. Prefer these methods over the low-level
20540
- * `sdk.relayer.decryptValues` / `decryptPublicValues`: they
20541
- * assemble the credential bundle (transport key pair, EIP-712 permit) for you,
20542
- * cache results, and wrap relayer errors. Reach for `sdk.relayer.*` only when
20543
- * you must control credential assembly by hand.
20544
- *
20545
- * Owns the SDK-level guards (signer requirement on
20546
- * `decryptValues` and `delegatedDecryptValues`, empty-array
20547
- * short-circuit on `decryptPublicValues`, relayer error wrapping) and delegates the
20548
- * actual work to the internal {@link DecryptionService} or the relayer directly for
20549
- * `decryptPublicValues`.
20096
+ * Confidential ERC-20 wrapper (ERC-7984 ERC20Wrapper).
20550
20097
  *
20551
- * **Mixed signer requirement:** `decryptValues` and
20552
- * `delegatedDecryptValues` need a configured signer; `decryptPublicValues`
20553
- * does not. Each method documents its requirement in its JSDoc.
20098
+ * Extends {@link Token} with wrapper-specific operations:
20099
+ * - `shield` / `unshield` — convert between the underlying ERC-20 and confidential balance
20100
+ * - `unwrap` / `unwrapAll` / `finalizeUnwrap` — low-level two-phase primitives
20101
+ * - `underlying` / `allowance` — wrapper reads
20554
20102
  *
20555
- * **Request chunking:** decrypt requests are split internally to stay under
20556
- * the relayer's 2048-cleartext-bit per-request budget — callers never need to
20557
- * size batches themselves.
20103
+ * `WrappedToken.address` is the wrapper contract address itself — the wrapper
20104
+ * IS the confidential token.
20558
20105
  */
20559
- declare class Decryption {
20106
+ declare class WrappedToken extends Token {
20560
20107
  #private;
20561
- /** @internal */
20562
- constructor(opts: {
20563
- signer: GenericSigner | undefined;
20564
- provider: GenericProvider;
20565
- router: ChainRouter;
20566
- decryptionService: DecryptionService | undefined;
20567
- });
20568
20108
  /**
20569
- * Decrypt one or more FHE encrypted values. Results are cached — repeated calls
20570
- * for the same encrypted value skip the relayer round-trip.
20109
+ * Read the underlying ERC-20 token address from the wrapper contract.
20110
+ *
20111
+ * @returns The underlying ERC-20 token address.
20112
+ */
20113
+ underlying(): Promise<Address>;
20114
+ /**
20115
+ * Check whether the underlying ERC-20 supports ERC-1363 (payable token).
20116
+ * Result is cached per WrappedToken instance (negative results included):
20117
+ * once we know an underlying does not support ERC-1363, subsequent shields
20118
+ * go straight to the `approve` + `wrap` path without re-probing.
20119
+ */
20120
+ isPayable(): Promise<boolean>;
20121
+ /**
20122
+ * Read the ERC-20 allowance granted by `owner` to this wrapper for the
20123
+ * underlying token.
20124
+ *
20125
+ * @param owner - The owner address whose allowance to read.
20126
+ * @returns The current allowance as a bigint.
20127
+ */
20128
+ allowance(owner: Address): Promise<bigint>;
20129
+ /**
20130
+ * Shield public ERC-20 tokens into confidential tokens.
20131
+ *
20132
+ * The execution path is decided automatically by ERC-165 introspection on
20133
+ * the underlying ERC-20:
20134
+ * - **`transferAndCall`** (single tx): when the underlying supports
20135
+ * ERC-1363, no approval is required — the wrapper's `onTransferReceived`
20136
+ * callback mints confidential tokens directly. `approvalStrategy` is
20137
+ * **ignored** on this path. See {@link ShieldPath}.
20138
+ * - **`approveAndWrap`** (two-tx fallback): otherwise, an `approve` is
20139
+ * followed by a `wrap`. Approval is controlled by `approvalStrategy`
20140
+ * (`"exact"` by default, `"max"` for unlimited, `"skip"` to opt out).
20141
+ *
20142
+ * The ERC-20 balance is validated before submitting (public read, no
20143
+ * signing required) so the call works for all wallet types, including
20144
+ * smart wallets.
20145
+ *
20146
+ * @param amount - The plaintext amount to shield.
20147
+ * @param options - Optional: `approvalStrategy`, `to`, callbacks.
20148
+ * @returns The transaction hash and mined receipt.
20149
+ * @throws if signer and provider are on different chains. {@link ChainMismatchError}
20150
+ * @throws if the ERC-20 balance is less than `amount`. {@link InsufficientERC20BalanceError}
20151
+ * @throws if the ERC-20 approval or shield transaction reverts. {@link TransactionRevertedError}
20152
+ *
20153
+ * @example
20154
+ * ```ts
20155
+ * const txHash = await wrappedToken.shield(1000n);
20156
+ * ```
20157
+ */
20158
+ shield(amount: bigint, options?: ShieldOptions): Promise<TransactionResult>;
20159
+ /**
20160
+ * Approve this wrapper contract to spend the underlying ERC-20.
20161
+ * Defaults to max uint256. Resets to zero first if there's an existing
20162
+ * non-zero allowance (required by tokens like USDT).
20571
20163
  *
20572
- * Zero encrypted values are mapped to `0n` without hitting the relayer.
20573
- * Events (`DecryptStart/End/Error`) are emitted uniformly.
20574
- * Relayer errors are wrapped into typed SDK errors.
20164
+ * @param amount - Optional approval amount. Defaults to max uint256.
20165
+ * @returns The transaction hash and mined receipt.
20575
20166
  *
20576
- * @param encryptedInput - Encrypted values to decrypt, each paired with its contract address.
20577
- * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.
20578
- * @returns A record mapping each encrypted value to its decrypted clear-text value.
20579
- * @throws if no signer is configured. {@link SignerNotConfiguredError}
20580
- * @throws if signer and provider are on different chains. {@link ChainMismatchError}
20167
+ * @example
20168
+ * ```ts
20169
+ * await wrappedToken.approveUnderlying(); // max approval
20170
+ * await wrappedToken.approveUnderlying(1000n); // exact amount
20171
+ * ```
20172
+ */
20173
+ approveUnderlying(amount?: bigint): Promise<TransactionResult>;
20174
+ /**
20175
+ * Unshield a specific amount and finalize in one call.
20176
+ * Orchestrates: unshield → wait for receipt → parse event → finalize.
20177
+ *
20178
+ * By default, the SDK validates the confidential balance before submitting.
20179
+ * Set `skipBalanceCheck: true` to bypass this validation (e.g. for smart wallets).
20180
+ *
20181
+ * @param amount - The plaintext amount to unshield.
20182
+ * @param options - Optional: `skipBalanceCheck` (default `false`), callbacks.
20183
+ * @returns The finalize transaction hash and mined receipt.
20581
20184
  *
20582
20185
  * @example
20583
20186
  * ```ts
20584
- * const values = await sdk.decryption.decryptValues([
20585
- * { encryptedValue: balance, contractAddress: cUSDT },
20586
- * ]);
20587
- * console.log(values[balance]); // 1000n
20187
+ * const txHash = await wrappedToken.unshield(500n);
20588
20188
  * ```
20589
20189
  */
20590
- decryptValues(encryptedInput: EncryptedInput[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<Record<EncryptedValue, ClearValue>>;
20190
+ unshield(amount: bigint, options?: UnshieldOptions): Promise<TransactionResult>;
20591
20191
  /**
20592
- * Decrypt one or more FHE encrypted values using delegated credentials.
20192
+ * Unshield the entire balance and finalize in one call.
20193
+ * Orchestrates: unshieldAll → wait for receipt → parse event → finalize.
20593
20194
  *
20594
- * Mirrors {@link decryptValues} with delegated credentials — same caching and
20595
- * zero-value short-circuit. Before reading from cache or calling the relayer,
20596
- * every non-zero encrypted value's contract must have an active delegation from the
20597
- * delegator to the connected signer; missing or expired delegations fail fast.
20195
+ * @param callbacks - Optional progress callbacks for each phase.
20196
+ * @returns The finalize transaction hash and mined receipt.
20197
+ * @throws if the balance is zero. {@link DecryptionFailedError}
20598
20198
  *
20599
- * @param encryptedInputs - FHE encrypted values paired with their contract addresses.
20600
- * @param delegatorAddress - The address that granted delegation rights.
20601
- * @param accountAddress - Address used as the cache key's "requester"
20602
- * dimension. Defaults to `delegatorAddress`. Pass the actual account address
20603
- * when decrypting on behalf of someone whose balance is stored under a
20604
- * different address (e.g. `decryptBalanceAs` with an explicit `accountAddress`).
20605
- * @param options - Delegated-decrypt options. By default the call rides out the
20606
- * gateway propagation window ({@link DelegatedDecryptOptions.waitForPropagation});
20607
- * pass `{ waitForPropagation: false }` to fail fast instead.
20608
- * @returns Map of encrypted value → clear-text value.
20199
+ * @example
20200
+ * ```ts
20201
+ * const txHash = await wrappedToken.unshieldAll();
20202
+ * ```
20203
+ */
20204
+ unshieldAll(callbacks?: UnshieldCallbacks): Promise<TransactionResult>;
20205
+ /**
20206
+ * Resume an in-progress unshield from an existing unwrap tx hash.
20207
+ * Useful when the user already submitted the unwrap but the finalize step
20208
+ * was interrupted (e.g. page reload, network error).
20209
+ *
20210
+ * @param unwrapTxHash - The transaction hash of the previously submitted unwrap.
20211
+ * @param callbacks - Optional progress callbacks.
20212
+ * @returns The finalize transaction hash and mined receipt.
20609
20213
  *
20610
20214
  * @example
20611
20215
  * ```ts
20612
- * const values = await sdk.decryption.delegatedDecryptValues([
20613
- * { encryptedValue: balance, contractAddress: tokenAddr },
20614
- * ], delegatorAddr);
20615
- * console.log(values[balance]); // 1000n
20216
+ * const txHash = await wrappedToken.resumeUnshield(previousUnwrapTxHash);
20616
20217
  * ```
20617
20218
  */
20618
- delegatedDecryptValues(encryptedInputs: EncryptedInput[], delegatorAddress: Address, accountAddress?: Address, options?: DelegatedDecryptOptions): Promise<Record<EncryptedValue, ClearValue>>;
20219
+ resumeUnshield(unwrapTxHash: Hex, callbacks?: UnshieldCallbacks): Promise<TransactionResult>;
20619
20220
  /**
20620
- * Publicly decrypt one or more FHE encrypted values.
20221
+ * Return the unwrap tx hash of an unshield that was interrupted between its
20222
+ * two phases, or `null` if none is pending for this wrapper.
20621
20223
  *
20622
- * Signer-independent: works without a configured signer.
20623
- * Returns the decryption proof alongside the clear-text values so callers
20624
- * can submit on-chain finalization transactions (e.g. `finalizeUnwrap`).
20224
+ * The SDK persists this automatically when {@link unshield}/{@link unshieldAll}
20225
+ * submit phase 1, and clears it once phase 2 finalizes. Use the returned hash
20226
+ * to surface a "resume" affordance, then pass it to {@link resumeUnshield}.
20227
+ * Resuming is intentionally caller-driven — auto-resuming on load would fire a
20228
+ * wallet transaction unprompted.
20625
20229
  *
20626
- * @param encryptedValues - FHE encrypted values to decrypt publicly.
20627
- * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.
20628
- * @returns Clear-text values, ABI-encoded values, and the decryption proof.
20230
+ * @returns The pending unwrap tx hash, or `null`.
20629
20231
  *
20630
20232
  * @example
20631
20233
  * ```ts
20632
- * const { clearValues, decryptionProof, abiEncodedClearValues } =
20633
- * await sdk.decryption.decryptPublicValues([encryptedValue]);
20234
+ * const unwrapTxHash = await wrappedToken.getPendingUnshield();
20235
+ * if (unwrapTxHash) await wrappedToken.resumeUnshield(unwrapTxHash);
20634
20236
  * ```
20635
20237
  */
20636
- decryptPublicValues(encryptedValues: EncryptedValue[], options?: Pick<FhevmRelayerOptions, "signal" | "timeout">): Promise<DecryptPublicValuesResult>;
20238
+ getPendingUnshield(): Promise<Hex | null>;
20637
20239
  /**
20638
- * Batch-decrypt delegated encrypted values with per-entry error isolation.
20240
+ * Request an unwrap for a specific amount. Encrypts the amount first.
20241
+ * Pass the result's `unwrapRequestId` to {@link finalizeUnwrap} once the
20242
+ * request is processed on-chain.
20639
20243
  *
20640
- * Attempts a single batch request first. If the batch fails with a non-fatal
20641
- * error (e.g. one entry is invalid), falls back to per-entry decryption so
20642
- * healthy entries still resolve. Each item in the result carries either a
20643
- * decrypted value or an error — callers decide how to surface partial failures.
20244
+ * @param amount - The plaintext amount to unwrap (encrypted automatically).
20245
+ * @returns The tx hash, mined receipt, and the `unwrapRequestId` for `finalizeUnwrap`.
20644
20246
  *
20645
- * @param encryptedInputs - FHE encrypted values paired with their contract addresses.
20646
- * @param delegatorAddress - The address that granted delegation rights.
20647
- * @param accountAddress - The account on whose behalf decryption is performed. Defaults to `delegatorAddress`.
20648
- * @param maxConcurrency - Maximum parallel decrypt calls during per-entry fallback.
20649
- * @param waitForPropagation - Ride out the gateway propagation window on the
20650
- * initial batch attempt (default `true`). See {@link DelegatedDecryptOptions.waitForPropagation}.
20651
- * @returns Per-entry results, each with a value or an error.
20652
- * @throws if no signer is configured. {@link SignerNotConfiguredError}
20653
- * @throws if signer and provider are on different chains. {@link ChainMismatchError}
20247
+ * @example
20248
+ * ```ts
20249
+ * const result = await wrappedToken.unwrap(500n);
20250
+ * await wrappedToken.finalizeUnwrap(result.unwrapRequestId);
20251
+ * ```
20252
+ */
20253
+ unwrap(amount: bigint): Promise<UnwrapResult>;
20254
+ /**
20255
+ * Request an unwrap for the entire confidential balance.
20256
+ * Uses the on-chain encrypted balance directly (no encryption needed).
20257
+ * Throws if the balance is zero.
20258
+ *
20259
+ * @returns The tx hash, mined receipt, and the `unwrapRequestId` for `finalizeUnwrap`.
20260
+ * @throws if the balance is zero. {@link DecryptionFailedError}
20654
20261
  *
20655
20262
  * @example
20656
20263
  * ```ts
20657
- * const result = await sdk.decryption.delegatedBatchDecryptValues({
20658
- * encryptedInputs: [
20659
- * { encryptedValue: encryptedValue1, contractAddress: tokenA },
20660
- * { encryptedValue: encryptedValue2, contractAddress: tokenB },
20661
- * ],
20662
- * delegatorAddress: "0xDelegator",
20663
- * maxConcurrency: 5,
20664
- * });
20665
- * for (const item of result.items) {
20666
- * if (item.error) console.error(item.encryptedValue, item.error);
20667
- * else console.log(item.encryptedValue, item.value);
20668
- * }
20264
+ * const result = await wrappedToken.unwrapAll();
20265
+ * await wrappedToken.finalizeUnwrap(result.unwrapRequestId);
20669
20266
  * ```
20670
20267
  */
20671
- delegatedBatchDecryptValues({ encryptedInputs, delegatorAddress, accountAddress, maxConcurrency, waitForPropagation }: {
20672
- encryptedInputs: EncryptedInput[];
20673
- delegatorAddress: Address;
20674
- accountAddress?: Address;
20675
- maxConcurrency?: number;
20676
- } & DelegatedDecryptOptions): Promise<BatchDecryptResult>;
20268
+ unwrapAll(): Promise<UnwrapResult>;
20269
+ /**
20270
+ * Complete an unwrap by fetching the public decryption proof and finalizing.
20271
+ * Call this once the unwrap request has been processed on-chain.
20272
+ *
20273
+ * @param unwrapRequestId - The `unwrapRequestId` from an {@link UnwrapResult}
20274
+ * (`result.unwrapRequestId`) returned by {@link unwrap} / {@link unwrapAll},
20275
+ * or one decoded from an `UnwrapRequested` event (e.g. when finalizing
20276
+ * across sessions).
20277
+ * @returns The transaction hash and mined receipt.
20278
+ *
20279
+ * @example
20280
+ * ```ts
20281
+ * const { unwrapRequestId } = await wrappedToken.unwrap(500n);
20282
+ * await wrappedToken.finalizeUnwrap(unwrapRequestId);
20283
+ * ```
20284
+ */
20285
+ finalizeUnwrap(unwrapRequestId: EncryptedValue): Promise<TransactionResult>;
20677
20286
  }
20678
20287
  //#endregion
20679
- //#region src/namespaces/delegations.d.ts
20288
+ //#region src/wrappers-registry.d.ts
20680
20289
  /**
20681
- * Public namespace for on-chain decryption-delegation management.
20290
+ * Default wrappers registry addresses for known chains.
20291
+ * Only includes chains where a registry is deployed (excludes Hardhat).
20682
20292
  *
20683
- * Exposed as `sdk.delegations`. Owns the SDK-level guards (signer requirement, chain
20684
- * alignment, delegator address resolution from the wallet account) and delegates the
20685
- * actual work to the internal {@link DelegationService}.
20293
+ * @deprecated Read `registryAddress` from the chain presets instead (e.g.
20294
+ * `sepolia.registryAddress`). Will be removed in the next major version.
20295
+ */
20296
+ declare const DefaultRegistryAddresses: Record<number, Address>;
20297
+ /** Configuration for {@link WrappersRegistry}. */
20298
+ interface WrappersRegistryConfig {
20299
+ /** Read-only chain provider used for every registry lookup. */
20300
+ provider: GenericProvider;
20301
+ /**
20302
+ * Per-chain registry address overrides, merged on top of
20303
+ * {@link DefaultRegistryAddresses}. Use this to supply a registry
20304
+ * address for custom or local chains (e.g. Hardhat).
20305
+ *
20306
+ * @example
20307
+ * ```ts
20308
+ * new WrappersRegistry({
20309
+ * provider,
20310
+ * registryAddresses: { [31337]: "0xYourHardhatRegistry" },
20311
+ * });
20312
+ * ```
20313
+ */
20314
+ registryAddresses?: Record<number, Address>;
20315
+ /**
20316
+ * How long cached registry results remain valid, in seconds.
20317
+ * Default: `86400` (24 hours).
20318
+ */
20319
+ registryTTL?: number;
20320
+ }
20321
+ /** Options for {@link WrappersRegistry.listPairs}. */
20322
+ interface ListPairsOptions {
20323
+ /** Page number (1-indexed). Default: `1`. */
20324
+ page?: number;
20325
+ /** Number of items per page. Default: `100`. */
20326
+ pageSize?: number;
20327
+ /**
20328
+ * When `true`, fetches on-chain metadata (name, symbol, decimals) for both
20329
+ * the ERC-20 and confidential token, plus totalSupply for the ERC-20.
20330
+ * Default: `false`.
20331
+ */
20332
+ metadata?: boolean;
20333
+ }
20334
+ /**
20335
+ * High-level interface for the on-chain token wrappers registry.
20686
20336
  *
20687
- * Delegation operations write to the host chain ACL; after a delegation is mined,
20688
- * the gateway syncs the ACL state via cross-chain event propagation — usually
20689
- * within ~10 blocks (a few seconds). Delegated decryption rides out that window
20690
- * with a bounded internal retry, so callers can decrypt right after granting.
20337
+ * Uses the configured {@link GenericProvider} to resolve the correct registry
20338
+ * contract address for the current chain and exposes typed read helpers for
20339
+ * every registry query. Results are cached in memory with a configurable TTL
20340
+ * (default 24 hours).
20341
+ *
20342
+ * @example
20343
+ * ```ts
20344
+ * const registry = new WrappersRegistry({ provider });
20345
+ *
20346
+ * // Paginated listing
20347
+ * const page1 = await registry.listPairs({ page: 1, pageSize: 20 });
20348
+ *
20349
+ * // Structured lookups
20350
+ * const result = await registry.getConfidentialToken(erc20Address);
20351
+ * if (result) console.log(result.confidentialTokenAddress);
20352
+ *
20353
+ * // Force refresh
20354
+ * registry.refresh();
20355
+ * ```
20691
20356
  */
20692
- declare class Delegations {
20357
+ declare class WrappersRegistry {
20693
20358
  #private;
20694
- /** @internal */
20695
- constructor(opts: {
20696
- signer: GenericSigner | undefined;
20697
- provider: GenericProvider;
20698
- delegationService: DelegationService;
20699
- });
20359
+ readonly provider: GenericProvider;
20360
+ constructor(config: WrappersRegistryConfig);
20361
+ /**
20362
+ * Synchronous lookup of the registry address for a given chain ID.
20363
+ * Returns `undefined` if no address is configured for that chain.
20364
+ */
20365
+ getAddress(chainId: number): Address | undefined;
20366
+ /**
20367
+ * Force-invalidate the in-memory cache. The next call to any read method
20368
+ * will fetch fresh data from the chain.
20369
+ */
20370
+ refresh(): void;
20700
20371
  /**
20701
- * Delegate decryption rights for a confidential contract to another address.
20702
- * Calls `ACL.delegateForUserDecryption()` on-chain.
20703
- *
20704
- * The delegation is recorded on L1 immediately, but the gateway must sync the
20705
- * ACL state via cross-chain event propagation — usually within ~10 blocks (a
20706
- * few seconds). You do not need to wait: delegated decryption rides out that
20707
- * window with a bounded internal retry, so you can decrypt right after this
20708
- * resolves.
20709
- *
20710
- * @param contractAddress - The confidential contract address to delegate on.
20711
- * @param delegateAddress - Address to delegate decryption rights to.
20712
- * @param expirationDate - Optional expiration date (defaults to permanent delegation via `uint64.max`).
20713
- * @returns The transaction hash and mined receipt.
20714
- * @throws if no signer is configured. {@link SignerNotConfiguredError}
20715
- * @throws if signer and provider are on different chains. {@link ChainMismatchError}
20716
- * @throws if `expirationDate` is less than 1 hour in the future. {@link DelegationExpirationTooSoonError}
20717
- * @throws if the delegate equals the connected wallet. {@link DelegationSelfNotAllowedError}
20718
- * @throws if the delegate equals the contract address. {@link DelegationDelegateEqualsContractError}
20719
- * @throws if the new expiry equals the current one. {@link DelegationExpiryUnchangedError}
20720
- * @throws if the delegation transaction reverts. {@link TransactionRevertedError}
20372
+ * The cache TTL in milliseconds.
20373
+ * Exposed so query option factories can set a matching `staleTime`.
20721
20374
  */
20722
- delegateDecryption({ contractAddress, delegateAddress, expirationDate }: {
20723
- contractAddress: Address;
20724
- delegateAddress: Address;
20725
- expirationDate?: Date;
20726
- }): Promise<TransactionResult>;
20375
+ get ttlMs(): number;
20727
20376
  /**
20728
- * Revoke decryption delegation for a confidential contract.
20729
- * Calls `ACL.revokeDelegationForUserDecryption()` on-chain.
20377
+ * Resolve the registry contract address for the current chain.
20730
20378
  *
20731
- * @param contractAddress - The confidential contract address to revoke delegation on.
20732
- * @param delegateAddress - Address to revoke delegation from.
20733
- * @returns The transaction hash and mined receipt.
20734
- * @throws if no signer is configured. {@link SignerNotConfiguredError}
20735
- * @throws if signer and provider are on different chains. {@link ChainMismatchError}
20736
- * @throws if no delegation exists for this (delegator, delegate, contract) tuple. {@link DelegationNotFoundError}
20737
- * @throws if the revocation transaction reverts. {@link TransactionRevertedError}
20379
+ * Priority: `registryAddresses[chainId]` \> built-in default.
20380
+ *
20381
+ * @returns The registry contract address for the connected chain.
20382
+ * @throws if no address is configured for the chain. {@link ConfigurationError}
20738
20383
  */
20739
- revokeDelegation({ contractAddress, delegateAddress }: {
20740
- contractAddress: Address;
20741
- delegateAddress: Address;
20742
- }): Promise<TransactionResult>;
20384
+ getRegistryAddress(): Promise<Address>;
20743
20385
  /**
20744
- * Check whether a delegation is active for the given contract address.
20386
+ * List token wrapper pairs with page-based pagination.
20745
20387
  *
20746
- * Signer-independent: works without a configured signer.
20388
+ * Internally maps to `getTokenConfidentialTokenPairsSlice` on-chain.
20747
20389
  *
20748
- * @param contractAddress - The confidential contract address.
20749
- * @param delegatorAddress - The address that granted the delegation.
20750
- * @param delegateAddress - The address that received delegation rights.
20751
- * @returns `true` if the delegation exists and has not expired.
20390
+ * @param options - Pagination and enrichment options.
20391
+ * @returns A {@link PaginatedResult} of pairs.
20392
+ *
20393
+ * @example
20394
+ * ```ts
20395
+ * const result = await registry.listPairs({ page: 1, pageSize: 20 });
20396
+ * console.log(`${result.total} pairs, showing page ${result.page}`);
20397
+ *
20398
+ * // With on-chain metadata
20399
+ * const withMeta = await registry.listPairs({ metadata: true, pageSize: 10 });
20400
+ * for (const pair of withMeta.items) {
20401
+ * console.log(pair.underlying.symbol, "→", pair.confidential.symbol);
20402
+ * }
20403
+ * ```
20752
20404
  */
20753
- isActive(params: {
20754
- contractAddress: Address;
20755
- delegatorAddress: Address;
20756
- delegateAddress: Address;
20757
- }): Promise<boolean>;
20405
+ listPairs(options: ListPairsOptions & {
20406
+ metadata: true;
20407
+ }): Promise<PaginatedResult<TokenWrapperPairWithMetadata>>;
20408
+ listPairs(options?: ListPairsOptions): Promise<PaginatedResult<TokenWrapperPair>>;
20758
20409
  /**
20759
- * Get the expiration timestamp of a delegation for the given contract.
20410
+ * Look up the confidential token for a given plain ERC-20 address.
20760
20411
  *
20761
- * Signer-independent: works without a configured signer.
20412
+ * @param tokenAddress - The plain ERC-20 token address.
20413
+ * @returns The lookup result, or `null` if the token has never been registered.
20414
+ * **Note:** revoked tokens (registered then invalidated) return a non-null result
20415
+ * with `isValid: false`. Check `result.isValid` explicitly rather than using
20416
+ * `if (result)` to guard against processing revoked tokens.
20762
20417
  *
20763
- * @param contractAddress - The confidential contract address.
20764
- * @param delegatorAddress - The address that granted the delegation.
20765
- * @param delegateAddress - The address that received delegation rights.
20766
- * @returns Unix timestamp as bigint. `0n` = no delegation. `2^64 - 1` = permanent.
20418
+ * @example
20419
+ * ```ts
20420
+ * const result = await registry.getConfidentialToken(usdcAddress);
20421
+ * if (result?.isValid) {
20422
+ * console.log(result.confidentialTokenAddress);
20423
+ * }
20424
+ * ```
20767
20425
  */
20768
- getExpiry(params: {
20769
- contractAddress: Address;
20770
- delegatorAddress: Address;
20771
- delegateAddress: Address;
20772
- }): Promise<bigint>;
20773
- }
20774
- //#endregion
20775
- //#region src/namespaces/permits.d.ts
20776
- /**
20777
- * Public namespace for permit and transport-key-pair management.
20778
- *
20779
- * Exposed as `sdk.permits`. Owns the SDK-level guards (chain alignment, empty-array
20780
- * short-circuit, decrypt-cache invalidation) and delegates the actual work to the
20781
- * internal {@link CredentialService}.
20782
- *
20783
- * The namespace is named `permits` because the user-facing concept is the signed-permit
20784
- * store. The transport key pair is invisible plumbing — there is no `getTransportKeyPair()`
20785
- * surfaced; the key pair exists to sign permits and is created automatically when needed.
20786
- * {@link clear} wipes both the permit store and the transport key pair (permits
20787
- * cascade-delete with the key pair).
20788
- */
20789
- declare class Permits {
20790
- #private;
20791
- /** @internal */
20792
- constructor(opts: {
20793
- signer: GenericSigner | undefined;
20794
- provider: GenericProvider;
20795
- cachingService: CachingService;
20796
- credentialService: CredentialService | undefined;
20797
- logger: GenericLogger;
20798
- });
20426
+ getConfidentialToken(tokenAddress: Address): Promise<{
20427
+ confidentialTokenAddress: Address;
20428
+ isValid: boolean;
20429
+ } | null>;
20799
20430
  /**
20800
- * Sign and store an EIP-712 permit authorising direct decryption for the
20801
- * given contract addresses.
20431
+ * Reverse lookup — find the plain ERC-20 for a given confidential token.
20802
20432
  *
20803
- * Idempotent: if a permit covering the requested set already exists, no
20804
- * wallet prompt occurs. Otherwise the SDK chunks the uncovered subset into
20805
- * groups of ≤10 contracts and prompts once per chunk; partial mid-flight
20806
- * rejection is preserved (already-signed chunks are persisted before the
20807
- * next prompt).
20433
+ * @param confidentialTokenAddress - The confidential token address.
20434
+ * @returns The lookup result, or `null` if no pair is registered.
20808
20435
  *
20809
- * @param contracts - Contract addresses to authorize.
20436
+ * @example
20437
+ * ```ts
20438
+ * const result = await registry.getUnderlyingToken(cUsdcAddress);
20439
+ * if (result) {
20440
+ * console.log(result.tokenAddress, result.isValid);
20441
+ * }
20442
+ * ```
20810
20443
  */
20811
- grantPermit(contracts: Address[]): Promise<void>;
20444
+ getUnderlyingToken(confidentialTokenAddress: Address): Promise<{
20445
+ tokenAddress: Address;
20446
+ isValid: boolean;
20447
+ } | null>;
20812
20448
  /**
20813
- * Sign and store an EIP-712 delegation permit authorising decryption on
20814
- * behalf of `delegator`. Same idempotence/chunking semantics as {@link grantPermit}.
20449
+ * Fetch all token wrapper pairs from the registry.
20815
20450
  *
20816
- * @param delegator - The address that delegated decryption rights to the connected signer.
20817
- * @param contracts - Contract addresses to authorize.
20451
+ * @returns All registered `TokenWrapperPair` entries.
20818
20452
  */
20819
- grantDelegationPermit(delegator: Address, contracts: Address[]): Promise<void>;
20453
+ getTokenPairs(): Promise<readonly TokenWrapperPair[]>;
20820
20454
  /**
20821
- * Pure store lookup: is there a permit covering `contracts`?
20822
- * No wallet prompt, no transport key pair generation. Returns `false` when no signer
20823
- * is configured.
20455
+ * Get the total number of token wrapper pairs.
20456
+ *
20457
+ * @returns The count as a bigint.
20824
20458
  */
20825
- hasPermit(contracts: Address[]): Promise<boolean>;
20459
+ getTokenPairsLength(): Promise<bigint>;
20826
20460
  /**
20827
- * Pure store lookup for a delegation permit. See {@link hasPermit}.
20461
+ * Fetch a range of token wrapper pairs (paginated by index).
20828
20462
  *
20829
- * @param delegator - The address that delegated decryption rights to the connected signer.
20830
- * @param contracts - Contract addresses to check.
20831
- * @returns `true` if cached delegation permits cover all requested contracts.
20463
+ * @param fromIndex - Start index (inclusive).
20464
+ * @param toIndex - End index (exclusive).
20465
+ * @returns The slice of `TokenWrapperPair` entries.
20832
20466
  */
20833
- hasDelegationPermit(delegator: Address, contracts: Address[]): Promise<boolean>;
20467
+ getTokenPairsSlice(fromIndex: bigint, toIndex: bigint): Promise<readonly TokenWrapperPair[]>;
20834
20468
  /**
20835
- * Best-effort transport-key-pair prefetch for the connected signer.
20836
- *
20837
- * Optional latency optimization: decrypt and permit flows remain correct
20838
- * without it because they lazily create the transport key pair when needed.
20469
+ * Fetch a single token wrapper pair by index.
20839
20470
  *
20840
- * Silent no-op when no signer is configured or no wallet account is
20841
- * available. The transport key pair is generated through the relayer dispatcher's
20842
- * currently active chain — see {@link LifecycleService}, which calls
20843
- * `switchChain` before fanning the wallet-account change out to listeners,
20844
- * so any downstream caller (including React adapters) observes the
20845
- * dispatcher on the wallet chain by the time it invokes warmup.
20471
+ * @param index - Zero-based pair index.
20472
+ * @returns The `TokenWrapperPair` at that index.
20846
20473
  */
20847
- warmTransportKeyPair(): Promise<void>;
20474
+ getTokenPair(index: bigint): Promise<TokenWrapperPair>;
20848
20475
  /**
20849
- * Wipe FHE permits for the current signer.
20476
+ * Look up the confidential token address for a given plain ERC-20 token.
20850
20477
  *
20851
- * - With no argument: every permit referencing this signer is removed across
20852
- * all chains and delegators. The transport key pair survives — use {@link clear} to
20853
- * also wipe the transport key pair.
20854
- * - With a contract list: every signed permit in the direct-decrypt scope
20855
- * (current chain) whose immutable payload touches any listed address is
20856
- * removed. Delegation permits are not touched in this mode.
20478
+ * @param tokenAddress - The plain ERC-20 token address.
20479
+ * @returns A tuple `[isValid, confidentialTokenAddress]`. `isValid` is `true` only for a
20480
+ * registered, non-revoked wrapper. The address is the zero address when no pair is registered.
20481
+ * A non-zero address with `isValid=false` means the wrapper was registered but later revoked.
20482
+ */
20483
+ getConfidentialTokenAddress(tokenAddress: Address): Promise<readonly [boolean, Address]>;
20484
+ /**
20485
+ * Reverse lookup — find the plain ERC-20 for a given confidential token.
20857
20486
  *
20858
- * @throws if no signer is configured. {@link SignerNotConfiguredError}
20487
+ * @param confidentialTokenAddress - The confidential token address.
20488
+ * @returns A tuple `[isValid, tokenAddress]`. `isValid` is `true` only for a registered,
20489
+ * non-revoked wrapper. The address is the zero address when no pair is registered.
20490
+ * A non-zero address with `isValid=false` means the wrapper was registered but later revoked.
20859
20491
  */
20860
- revokePermits(contracts?: Address[]): Promise<void>;
20492
+ getTokenAddress(confidentialTokenAddress: Address): Promise<readonly [boolean, Address]>;
20861
20493
  /**
20862
- * Wipe the transport key pair for the current signer and cascade-delete every permit
20863
- * (across chains and delegators) referencing it.
20494
+ * Check whether a confidential token is registered and valid.
20864
20495
  *
20865
- * @throws if no signer is configured. {@link SignerNotConfiguredError}
20496
+ * @param confidentialTokenAddress - The confidential token address to check.
20497
+ * @returns `true` if the token is a known valid wrapper in the registry.
20866
20498
  */
20867
- clear(): Promise<void>;
20499
+ isConfidentialTokenValid(confidentialTokenAddress: Address): Promise<boolean>;
20868
20500
  }
20869
20501
  //#endregion
20870
20502
  //#region src/zama-sdk.d.ts
@@ -21025,5 +20657,74 @@ declare class ZamaSDK {
21025
20657
  [Symbol.dispose](): void;
21026
20658
  }
21027
20659
  //#endregion
21028
- export { confidentialTransferMutationOptions as $, TokenWrapperPairWithMetadata as $n, DelegationSelfNotAllowedError as $t, encryptMutationOptions as A, tokenMetadataQueryOptions as An, isOperatorContract as Ar, SignerRequiredError as At, UnshieldParams as B, invalidateAfterUnwrap as Bn, createConfig as Br, InsufficientConfidentialBalanceError as Bt, grantPermitMutationOptions as C, TotalSupplyQueryConfig as Cn, symbolContract as Cr, BatchDecryptAsOptions as Ct, DecryptResult as D, isWrapperQueryOptions as Dn, confidentialTransferFromContract as Dr, SigningFailedError as Dt, delegatedDecryptValuesMutationOptions as E, isConfidentialQueryOptions as En, confidentialTransferContract as Er, TransactionRevertedError as Et, unwrapMutationOptions as F, invalidateAfterSetOperator as Fn, unwrapFromBalanceContract as Fr, ConfigurationError as Ft, confidentialSetOperatorMutationOptions as G, SignerQueryContext as Gn, DelegationContractIsSelfError as Gt, ApproveUnderlyingParams as H, invalidateWagmiBalanceQueries as Hn, DecryptionFailedError as Ht, ResumeUnshieldParams as I, invalidateAfterShield as In, wrapContract as Ir, RelayerRequestFailedError as It, ConfidentialTransferFromParams as J, StrippedQueryOptionKeys as Jn, DelegationExpirationTooSoonError as Jt, ConfidentialTransferFromAndCallParams as K, MutationFactoryOptions as Kn, DelegationCooldownError as Kt, resumeUnshieldMutationOptions as L, invalidateAfterTransfer as Ln, ResolvedChainRelayer as Lr, BalanceCheckUnavailableError as Lt, finalizeUnwrapMutationOptions as M, QueryFilterLike as Mn, setOperatorContract as Mr, WalletNotConnectedError as Mt, unwrapAllMutationOptions as N, QueryLike as Nn, underlyingContract as Nr, RpcRateLimitError as Nt, EncryptedInput as O, TokenMetadata as On, finalizeUnwrapContract as Or, SigningRejectedError as Ot, UnwrapParams as P, invalidateAfterApproveUnderlying as Pn, unwrapContract as Pr, NotEntitledError as Pt, ConfidentialTransferParams as Q, TokenWrapperPair as Qn, DelegationNotPropagatedError as Qt, UnshieldAllParams as R, invalidateAfterUnshield as Rn, resolveChainRelayers as Rr, BalanceErrorDetails as Rt, hasPermitQueryOptions as S, StoredTransportKeyPair as Sn, nameContract as Sr, BatchBalancesResult as St, DelegatedDecryptValuesMutationParams as T, IsConfidentialQueryConfig as Tn, confidentialTotalSupplyContract as Tr, matchZamaError as Tt, approveUnderlyingMutationOptions as U, invalidateWalletLifecycleQueries as Un, EncryptionFailedError as Ut, unshieldMutationOptions as V, invalidateBalanceQueries as Vn, InsufficientERC20BalanceError as Vt, ConfidentialSetOperatorParams as W, zamaQueryKeys as Wn, AclPausedError as Wt, ConfidentialTransferAndCallParams as X, hashFn as Xn, DelegationExpiryUnchangedError as Xt, confidentialTransferFromMutationOptions as Y, filterQueryOptions as Yn, DelegationExpiredError as Yt, confidentialTransferAndCallMutationOptions as Z, PaginatedResult as Zn, DelegationNotFoundError as Zt, DelegateDecryptionParams as _, ListPairsOptions as _n, supportsInterfaceContract as _r, ConfidentialBalancesQueryConfig as _t, BatchDecryptItem as a, ZamaErrorCode as an, getTokenPairsSliceContract as ar, TokenAddressQueryConfig as at, revokePermitsMutationOptions as b, Permission as bn, balanceOfContract as br, confidentialBalanceQueryOptions as bt, DelegationStatusData as c, ConfidentialIsOperatorQueryConfig as cn, getDelegationExpiryContract as cr, WrappersRegistryQueryConfig as ct, RevokeDelegationParams as d, pendingUnshieldQueryOptions as dn, transferAndCallContract as dr, listPairsQueryOptions as dt, InvalidTransportKeyPairError as en, getConfidentialTokenAddressContract as er, ShieldParams as et, revokeDelegationMutationOptions as f, UnderlyingAllowanceQueryConfig as fn, ERC1363_INTERFACE_ID as fr, tokenAddressQueryOptions as ft, decryptBalanceAsMutationOptions as g, DefaultRegistryAddresses as gn, isConfidentialWrapperContract as gr, tokenPairsSliceQueryOptions as gt, DecryptBalanceAsParams as h, wrapperDiscoveryQueryOptions as hn, isConfidentialTokenContract as hr, tokenPairsQueryOptions as ht, Decryption as i, ZamaError as in, getTokenPairsLengthContract as ir, ListPairsQueryConfig as it, FinalizeUnwrapParams as j, QueryClientLike as jn, rateContract as jr, WalletAccountNotReadyError as jt, decryptValuesQueryOptions as k, TokenMetadataQueryConfig as kn, inferredTotalSupplyContract as kr, SignerNotConfiguredError as kt, DelegationStatusQueryConfig as l, confidentialIsOperatorQueryOptions as ln, isHandleDelegatedContract as lr, confidentialTokenAddressQueryOptions as lt, batchDecryptBalancesAsMutationOptions as m, WrapperDiscoveryQueryConfig as mn, ERC7984_WRAPPER_INTERFACE_ID as mr, tokenPairsLengthQueryOptions as mt, Permits as n, TransportKeyPairExpiredError as nn, getTokenPairContract as nr, ConfidentialTokenAddressQueryConfig as nt, BatchDecryptResult as o, isRetryable as on, isConfidentialTokenValidContract as or, TokenPairQueryConfig as ot, BatchDecryptBalancesAsParams as p, underlyingAllowanceQueryOptions as pn, ERC7984_INTERFACE_ID as pr, tokenPairQueryOptions as pt, confidentialTransferFromAndCallMutationOptions as q, QueryFactoryOptions as qn, DelegationDelegateEqualsContractError as qt, Delegations as r, ChainMismatchError as rn, getTokenPairsContract as rr, IsConfidentialTokenValidQueryConfig as rt, DelegatedDecryptOptions as s, retryAfterSeconds as sn, delegateForUserDecryptionContract as sr, TokenPairsSliceQueryConfig as st, ZamaSDK as t, NoCiphertextError as tn, getTokenAddressContract as tr, shieldMutationOptions as tt, delegationStatusQueryOptions as u, PendingUnshieldQueryConfig as un, revokeDelegationContract as ur, isConfidentialTokenValidQueryOptions as ut, delegateDecryptionMutationOptions as v, WrappersRegistry as vn, allowanceContract as vr, confidentialBalancesQueryOptions as vt, decryptPublicValuesMutationOptions as w, totalSupplyQueryOptions as wn, confidentialBalanceOfContract as wr, Token as wt, HasPermitQueryConfig as x, SerializedTransportKeyPair as xn, decimalsContract as xr, WrappedToken as xt, clearCredentialsMutationOptions as y, WrappersRegistryConfig as yn, approveContract as yr, ConfidentialBalanceQueryConfig as yt, unshieldAllMutationOptions as z, invalidateAfterUnshieldSettled as zn, resolveStorage as zr, ERC20ReadFailedError as zt };
21029
- //# sourceMappingURL=zama-sdk-aaLl2ZlA.d.ts.map
20660
+ //#region src/utils/handles.d.ts
20661
+ declare const ZERO_ENCRYPTED_VALUE: "0x0000000000000000000000000000000000000000000000000000000000000000";
20662
+ /**
20663
+ * Check whether an encrypted value represents the zero value.
20664
+ */
20665
+ declare function isEncryptedValueZero(encryptedValue: string): boolean;
20666
+ //#endregion
20667
+ //#region src/storage/memory-storage.d.ts
20668
+ /** In-memory credential store. Credentials are lost on page reload. */
20669
+ declare class MemoryStorage implements GenericStorage {
20670
+ #private;
20671
+ get<T = unknown>(key: string): Promise<T | null>;
20672
+ set<T = unknown>(key: string, value: T): Promise<void>;
20673
+ delete(key: string): Promise<void>;
20674
+ }
20675
+ /** Default singleton for application-wide use. */
20676
+ declare const memoryStorage: MemoryStorage;
20677
+ //#endregion
20678
+ //#region src/storage/indexeddb-storage.d.ts
20679
+ /**
20680
+ * IndexedDB-backed {@link GenericStorage}.
20681
+ *
20682
+ * Stores keypair and permit objects keyed by a hashed wallet address. The
20683
+ * SDK delegates security to the storage backend — values are persisted
20684
+ * verbatim with no SDK-layer encryption.
20685
+ */
20686
+ declare class IndexedDBStorage implements GenericStorage {
20687
+ #private;
20688
+ constructor(dbName?: string, dbVersion?: number, storeName?: string);
20689
+ get<T = unknown>(key: string): Promise<T | null>;
20690
+ set<T = unknown>(key: string, value: T): Promise<void>;
20691
+ delete(key: string): Promise<void>;
20692
+ clear(): Promise<void>;
20693
+ }
20694
+ /** Default singleton for application-wide use. */
20695
+ declare const indexedDBStorage: IndexedDBStorage;
20696
+ //#endregion
20697
+ //#region src/storage/chrome-session-storage.d.ts
20698
+ /**
20699
+ * {@link GenericStorage} backed by `chrome.storage.session`.
20700
+ *
20701
+ * Use this in MV3 web extensions so the wallet signature survives
20702
+ * service worker restarts and is shared across popup, background,
20703
+ * and content script contexts.
20704
+ *
20705
+ * @example
20706
+ * ```ts
20707
+ * import { ZamaSDK, indexedDBStorage, chromeSessionStorage } from "@zama-fhe/sdk";
20708
+ * import { createConfig } from "@zama-fhe/sdk/viem";
20709
+ *
20710
+ * const config = createConfig({
20711
+ * chains: [mySepolia],
20712
+ * publicClient,
20713
+ * walletClient,
20714
+ * relayers: { [mySepolia.id]: web() },
20715
+ * storage: indexedDBStorage, // encrypted transport key pair — persistent
20716
+ * permitStorage: chromeSessionStorage, // signed permits — ephemeral
20717
+ * });
20718
+ * const sdk = new ZamaSDK(config);
20719
+ * ```
20720
+ */
20721
+ declare class ChromeSessionStorage implements GenericStorage {
20722
+ get<T = unknown>(key: string): Promise<T | null>;
20723
+ set(key: string, value: unknown): Promise<void>;
20724
+ delete(key: string): Promise<void>;
20725
+ }
20726
+ /** Default singleton for application-wide use. */
20727
+ declare const chromeSessionStorage: ChromeSessionStorage;
20728
+ //#endregion
20729
+ export { DelegationNotPropagatedError as $, rateContract as $t, SignerNotConfiguredError as A, getDelegationExpiryContract as At, ERC20ReadFailedError as B, allowanceContract as Bt, BatchDecryptItem as C, getTokenAddressContract as Ct, TransactionRevertedError as D, getTokenPairsSliceContract as Dt, matchZamaError as E, getTokenPairsLengthContract as Et, NotEntitledError as F, ERC7984_INTERFACE_ID as Ft, AclPausedError as G, symbolContract as Gt, InsufficientERC20BalanceError as H, balanceOfContract as Ht, ConfigurationError as I, ERC7984_WRAPPER_INTERFACE_ID as It, DelegationDelegateEqualsContractError as J, confidentialTransferContract as Jt, DelegationContractIsSelfError as K, confidentialBalanceOfContract as Kt, RelayerRequestFailedError as L, isConfidentialTokenContract as Lt, WalletAccountNotReadyError as M, revokeDelegationContract as Mt, WalletNotConnectedError as N, transferAndCallContract as Nt, SigningFailedError as O, isConfidentialTokenValidContract as Ot, RpcRateLimitError as P, ERC1363_INTERFACE_ID as Pt, DelegationNotFoundError as Q, isOperatorContract as Qt, BalanceCheckUnavailableError as R, isConfidentialWrapperContract as Rt, Decryption as S, getConfidentialTokenAddressContract as St, DelegatedDecryptOptions as T, getTokenPairsContract as Tt, DecryptionFailedError as U, decimalsContract as Ut, InsufficientConfidentialBalanceError as V, approveContract as Vt, EncryptionFailedError as W, nameContract as Wt, DelegationExpiredError as X, finalizeUnwrapContract as Xt, DelegationExpirationTooSoonError as Y, confidentialTransferFromContract as Yt, DelegationExpiryUnchangedError as Z, inferredTotalSupplyContract as Zt, BatchBalancesResult as _, MutationFactoryOptions as _t, IndexedDBStorage as a, ResolvedChainRelayer as an, ZamaError as at, Permits as b, TokenWrapperPair as bt, memoryStorage as c, createConfig as cn, retryAfterSeconds as ct, ZamaSDK as d, StoredTransportKeyPair as dt, setOperatorContract as en, DelegationSelfNotAllowedError as et, DefaultRegistryAddresses as f, DecryptResult as ft, WrappedToken as g, zamaQueryKeys as gt, WrappersRegistryConfig as h, SignerQueryContext as ht, chromeSessionStorage as i, wrapContract as in, ChainMismatchError as it, SignerRequiredError as j, isHandleDelegatedContract as jt, SigningRejectedError as k, delegateForUserDecryptionContract as kt, ZERO_ENCRYPTED_VALUE as l, Permission as lt, WrappersRegistry as m, decryptValuesQueryOptions as mt, Hex$1 as n, unwrapContract as nn, NoCiphertextError as nt, indexedDBStorage as o, resolveChainRelayers as on, ZamaErrorCode as ot, ListPairsOptions as p, EncryptedInput as pt, DelegationCooldownError as q, confidentialTotalSupplyContract as qt, ChromeSessionStorage as r, unwrapFromBalanceContract as rn, TransportKeyPairExpiredError as rt, MemoryStorage as s, resolveStorage as sn, isRetryable as st, Address$1 as t, underlyingContract as tn, InvalidTransportKeyPairError as tt, isEncryptedValueZero as u, SerializedTransportKeyPair as ut, BatchDecryptAsOptions as v, QueryFactoryOptions as vt, BatchDecryptResult as w, getTokenPairContract as wt, Delegations as x, TokenWrapperPairWithMetadata as xt, Token as y, PaginatedResult as yt, BalanceErrorDetails as z, supportsInterfaceContract as zt };
20730
+ //# sourceMappingURL=index-09tK1t8M.d.ts.map