@tokenops/sdk 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +102 -18
  2. package/dist/{chunk-HTOMTEA3.cjs → chunk-23F7JIK5.cjs} +2 -2
  3. package/dist/{chunk-ECT3NL2L.js → chunk-3PQ2RFPC.js} +3 -3
  4. package/dist/{chunk-OLDGMKW2.cjs → chunk-3ZRHDTEX.cjs} +33 -0
  5. package/dist/chunk-5KHIQG7Y.cjs +2180 -0
  6. package/dist/{chunk-T5LVV3KY.cjs → chunk-FPQBFIUW.cjs} +3 -3
  7. package/dist/{chunk-QIHZVLIK.js → chunk-FXCW7LVB.js} +1 -1
  8. package/dist/{chunk-K6MFFDBJ.cjs → chunk-G7G75C46.cjs} +6 -6
  9. package/dist/{chunk-72YGZEQE.js → chunk-IR5AK5U5.js} +6 -8
  10. package/dist/{chunk-CMRETRZO.js → chunk-ITQBDRWX.js} +1 -1
  11. package/dist/{chunk-ZHFLRKFY.js → chunk-JJ4R5QXF.js} +1 -1
  12. package/dist/{chunk-COPFW5Z4.js → chunk-M7V2EDPB.js} +30 -1
  13. package/dist/{chunk-UOG4PJL5.js → chunk-OQZAZIAS.js} +8 -10
  14. package/dist/{chunk-SUOG3BQS.cjs → chunk-OYLZEEHF.cjs} +1 -2
  15. package/dist/chunk-QE7ZONJ2.js +2171 -0
  16. package/dist/{chunk-62DF53UQ.cjs → chunk-SAGJIEQK.cjs} +7 -9
  17. package/dist/{chunk-JFR5J4FL.cjs → chunk-SEKC7H5Y.cjs} +8 -8
  18. package/dist/{chunk-6ECAHP5O.cjs → chunk-SYHXDHWX.cjs} +9 -11
  19. package/dist/{chunk-QCA7O2Q5.cjs → chunk-W7JHOK7G.cjs} +4 -4
  20. package/dist/{chunk-52TC6BF7.js → chunk-X56UVEXS.js} +1 -2
  21. package/dist/{chunk-HGXNRR25.js → chunk-XWDVPV42.js} +2 -2
  22. package/dist/core/addresses.d.ts +22 -0
  23. package/dist/core/errors.d.ts +1 -1
  24. package/dist/core/telemetry.d.ts +0 -3
  25. package/dist/fhe/operators.d.ts +1 -1
  26. package/dist/fhe-airdrop/advanced/factory-advanced.d.ts +3 -3
  27. package/dist/fhe-airdrop/advanced/index.cjs +5 -5
  28. package/dist/fhe-airdrop/advanced/index.d.cts +2 -2
  29. package/dist/fhe-airdrop/advanced/index.d.ts +2 -2
  30. package/dist/fhe-airdrop/advanced/index.js +3 -3
  31. package/dist/fhe-airdrop/advanced/react/index.cjs +8 -8
  32. package/dist/fhe-airdrop/advanced/react/index.d.cts +1 -1
  33. package/dist/fhe-airdrop/advanced/react/index.d.ts +1 -1
  34. package/dist/fhe-airdrop/advanced/react/index.js +4 -4
  35. package/dist/fhe-airdrop/factory.d.ts +8 -10
  36. package/dist/fhe-airdrop/index.cjs +9 -9
  37. package/dist/fhe-airdrop/index.js +2 -2
  38. package/dist/fhe-airdrop/react/index.cjs +69 -69
  39. package/dist/fhe-airdrop/react/index.js +4 -4
  40. package/dist/fhe-disperse/index.cjs +19 -19
  41. package/dist/fhe-disperse/index.js +2 -2
  42. package/dist/fhe-disperse/react/index.cjs +20 -20
  43. package/dist/fhe-disperse/react/index.js +3 -3
  44. package/dist/fhe-disperse/react/useSingletonWithdrawTokenFee.d.ts +2 -2
  45. package/dist/fhe-vesting/advanced/factory-advanced.d.ts +2 -2
  46. package/dist/fhe-vesting/advanced/index.cjs +5 -5
  47. package/dist/fhe-vesting/advanced/index.d.cts +2 -2
  48. package/dist/fhe-vesting/advanced/index.d.ts +2 -2
  49. package/dist/fhe-vesting/advanced/index.js +3 -3
  50. package/dist/fhe-vesting/advanced/react/index.cjs +8 -8
  51. package/dist/fhe-vesting/advanced/react/index.d.cts +1 -1
  52. package/dist/fhe-vesting/advanced/react/index.d.ts +1 -1
  53. package/dist/fhe-vesting/advanced/react/index.js +5 -5
  54. package/dist/fhe-vesting/factory.d.ts +6 -8
  55. package/dist/fhe-vesting/index.cjs +25 -25
  56. package/dist/fhe-vesting/index.js +3 -3
  57. package/dist/fhe-vesting/manager.d.ts +1 -2
  58. package/dist/fhe-vesting/react/index.cjs +126 -126
  59. package/dist/fhe-vesting/react/index.js +4 -4
  60. package/dist/fhe-vesting/react/useManagerWithdrawTokenFee.d.ts +1 -1
  61. package/dist/fhe-vesting/types.d.ts +0 -2
  62. package/dist/index.cjs +27 -11
  63. package/dist/index.js +1 -1
  64. package/dist/testnet-faucet/abis/confidential-test-token.d.ts +1039 -0
  65. package/dist/testnet-faucet/abis/index.d.ts +2 -0
  66. package/dist/testnet-faucet/abis/test-token.d.ts +253 -0
  67. package/dist/testnet-faucet/errors.d.ts +21 -0
  68. package/dist/testnet-faucet/faucet.d.ts +173 -0
  69. package/dist/testnet-faucet/index.cjs +208 -0
  70. package/dist/testnet-faucet/index.d.cts +8 -0
  71. package/dist/testnet-faucet/index.d.ts +8 -0
  72. package/dist/testnet-faucet/index.js +7 -0
  73. package/dist/testnet-faucet/react/_shared.d.ts +61 -0
  74. package/dist/testnet-faucet/react/index.cjs +379 -0
  75. package/dist/testnet-faucet/react/index.d.cts +38 -0
  76. package/dist/testnet-faucet/react/index.d.ts +38 -0
  77. package/dist/testnet-faucet/react/index.js +219 -0
  78. package/dist/testnet-faucet/react/useConfidentialBalance.d.ts +24 -0
  79. package/dist/testnet-faucet/react/useFaucetDecimals.d.ts +9 -0
  80. package/dist/testnet-faucet/react/useFaucetMetadata.d.ts +14 -0
  81. package/dist/testnet-faucet/react/useFaucetRate.d.ts +11 -0
  82. package/dist/testnet-faucet/react/useInferredTotalSupply.d.ts +11 -0
  83. package/dist/testnet-faucet/react/useMaxTotalSupply.d.ts +10 -0
  84. package/dist/testnet-faucet/react/useMintConfidential.d.ts +35 -0
  85. package/dist/testnet-faucet/react/useMintUnderlying.d.ts +31 -0
  86. package/dist/testnet-faucet/react/useUnderlyingBalance.d.ts +19 -0
  87. package/dist/testnet-faucet/react/useUnderlyingDecimals.d.ts +9 -0
  88. package/dist/testnet-faucet/react/useUnderlyingTokenAddress.d.ts +12 -0
  89. package/dist/testnet-faucet/types.d.ts +92 -0
  90. package/dist/testnet-faucet/validate.d.ts +44 -0
  91. package/package.json +77 -29
@@ -0,0 +1,219 @@
1
+ import { createTestnetFaucetClient, isTestnetFaucetChainId } from '../../chunk-QE7ZONJ2.js';
2
+ export { FaucetSupplyExhaustedError } from '../../chunk-QE7ZONJ2.js';
3
+ import '../../chunk-JFLEEXKP.js';
4
+ import { getConfidentialTestTokenAddress } from '../../chunk-M7V2EDPB.js';
5
+ import '../../chunk-BE2AIZ3K.js';
6
+ import '../../chunk-Q2GP5UDC.js';
7
+ import '../../chunk-KWFFIJYX.js';
8
+ import { MissingClientError, UnsupportedChainError, DeploymentAddressUnavailableError } from '../../chunk-IVE3QEGD.js';
9
+ export { AccessDeniedError, AlreadyInitializedError, BatchTooLargeError, ContractRevertError, DecryptionFailedError, DeploymentAddressUnavailableError, EncryptionFailedError, FeatureDisabledError, FheHandleNotAllowedError, InsufficientBalanceError, InsufficientFeeError, InsufficientGasFundsError, InvalidArgumentError, InvalidSignatureError, MissingAccountError, MissingClientError, MissingEncryptorError, MissingPublicClientError, MissingWalletClientError, NetworkError, PausedError, ReceiptEventAmbiguousError, ReceiptEventNotFoundError, ReentrancyError, RelayerUnreachableError, SigningFailedError, TokenOpsContractError, TokenOpsSdkError, TransferFailedError, UnknownWriteFailureError, UnsupportedChainError, UserDecryptNotAllowedError, UserRejectedSignatureError, WalletChainMismatchError, WalletRejectedError, isTokenOpsSdkError } from '../../chunk-IVE3QEGD.js';
10
+ import { useQuery, useMutation } from '@tanstack/react-query';
11
+ import { useAccount, usePublicClient, useWalletClient } from 'wagmi';
12
+ import { useMemo } from 'react';
13
+
14
+ var TESTNET_FAUCET_KEY = "tokenops-sdk";
15
+ var TESTNET_FAUCET_NAMESPACE = "testnet-faucet";
16
+ function tryResolveSingletonAddress(override, chainId) {
17
+ if (chainId !== void 0 && !isTestnetFaucetChainId(chainId)) return void 0;
18
+ if (override) return override;
19
+ if (chainId === void 0) return void 0;
20
+ return getConfidentialTestTokenAddress(chainId);
21
+ }
22
+ function useMemoFaucetClient(opts = {}) {
23
+ const publicClient = usePublicClient({ chainId: opts.chainId });
24
+ const { data: walletClient } = useWalletClient({ chainId: opts.chainId });
25
+ const chainId = opts.chainId ?? publicClient?.chain?.id;
26
+ const resolvedAddress = tryResolveSingletonAddress(opts.address, chainId);
27
+ const resolutionError = computeSingletonResolutionError(opts.address, chainId);
28
+ const client = useMemo(() => {
29
+ if (!publicClient) return void 0;
30
+ if (!resolvedAddress) return void 0;
31
+ return createTestnetFaucetClient({
32
+ publicClient,
33
+ ...walletClient ? { walletClient } : {},
34
+ ...opts.address ? { address: resolvedAddress } : {},
35
+ ...chainId !== void 0 ? { chainId } : {}
36
+ });
37
+ }, [publicClient, walletClient, resolvedAddress, chainId]);
38
+ return {
39
+ client,
40
+ resolutionError,
41
+ publicClient,
42
+ walletClient: walletClient ?? void 0,
43
+ chainId,
44
+ resolvedAddress
45
+ };
46
+ }
47
+ function computeSingletonResolutionError(override, chainId) {
48
+ if (chainId !== void 0 && !isTestnetFaucetChainId(chainId)) {
49
+ return new UnsupportedChainError(chainId);
50
+ }
51
+ if (override) return void 0;
52
+ if (chainId === void 0) {
53
+ return new DeploymentAddressUnavailableError({
54
+ reason: "chain-id-missing",
55
+ product: "testnetFaucet",
56
+ contract: "confidentialTestToken",
57
+ clientLabel: "TestnetFaucetClient"
58
+ });
59
+ }
60
+ const resolved = getConfidentialTestTokenAddress(chainId);
61
+ if (!resolved) {
62
+ return new DeploymentAddressUnavailableError({
63
+ reason: "registry-not-deployed",
64
+ product: "testnetFaucet",
65
+ contract: "confidentialTestToken",
66
+ chainId,
67
+ clientLabel: "TestnetFaucetClient"
68
+ });
69
+ }
70
+ return void 0;
71
+ }
72
+ function buildQueryKey(method, chainId, address, ...args) {
73
+ return [
74
+ TESTNET_FAUCET_KEY,
75
+ TESTNET_FAUCET_NAMESPACE,
76
+ method,
77
+ chainId ?? null,
78
+ address ? address.toLowerCase() : null,
79
+ ...args.map(normalizeKeyArg)
80
+ ];
81
+ }
82
+ function normalizeKeyArg(value) {
83
+ if (typeof value === "bigint") return value.toString();
84
+ if (Array.isArray(value)) return value.map(normalizeKeyArg);
85
+ if (value && typeof value === "object") {
86
+ return Object.fromEntries(
87
+ Object.entries(value).map(([k, v]) => [k, normalizeKeyArg(v)])
88
+ );
89
+ }
90
+ if (typeof value === "string" && value.startsWith("0x")) return value.toLowerCase();
91
+ return value;
92
+ }
93
+
94
+ // src/testnet-faucet/react/useConfidentialBalance.ts
95
+ function useConfidentialBalance(args = {}) {
96
+ const { account, ...base } = args;
97
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(base);
98
+ const { address: connected } = useAccount();
99
+ const resolvedAccount = account ?? connected;
100
+ return useQuery({
101
+ queryKey: buildQueryKey("confidentialBalanceOf", chainId, resolvedAddress, resolvedAccount),
102
+ queryFn: () => client.confidentialBalanceOf(resolvedAccount),
103
+ enabled: !!client && !!resolvedAccount,
104
+ staleTime: 0
105
+ });
106
+ }
107
+ function useUnderlyingBalance(args = {}) {
108
+ const { account, ...base } = args;
109
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(base);
110
+ const { address: connected } = useAccount();
111
+ const resolvedAccount = account ?? connected;
112
+ return useQuery({
113
+ // The TTT is derived from the CTTT, which is already keyed via
114
+ // `resolvedAddress` — no separate underlying segment needed.
115
+ queryKey: buildQueryKey("underlyingBalanceOf", chainId, resolvedAddress, resolvedAccount),
116
+ queryFn: () => client.underlyingBalanceOf(resolvedAccount),
117
+ enabled: !!client && !!resolvedAccount,
118
+ staleTime: 0
119
+ });
120
+ }
121
+ function useFaucetRate(options = {}) {
122
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
123
+ return useQuery({
124
+ queryKey: buildQueryKey("rate", chainId, resolvedAddress),
125
+ queryFn: () => client.rate(),
126
+ enabled: !!client,
127
+ // The conversion rate is fixed per deployment — never goes stale.
128
+ staleTime: Infinity
129
+ });
130
+ }
131
+ function useFaucetDecimals(options = {}) {
132
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
133
+ return useQuery({
134
+ queryKey: buildQueryKey("decimals", chainId, resolvedAddress),
135
+ queryFn: () => client.decimals(),
136
+ enabled: !!client,
137
+ // CTTT decimals are fixed per deployment — never goes stale.
138
+ staleTime: Infinity
139
+ });
140
+ }
141
+ function useUnderlyingDecimals(options = {}) {
142
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
143
+ return useQuery({
144
+ // The TTT is derived from the CTTT, which is already keyed via
145
+ // `resolvedAddress` — no separate underlying segment needed.
146
+ queryKey: buildQueryKey("underlyingDecimals", chainId, resolvedAddress),
147
+ queryFn: () => client.underlyingDecimals(),
148
+ enabled: !!client,
149
+ // TTT decimals are fixed per deployment — never goes stale.
150
+ staleTime: Infinity
151
+ });
152
+ }
153
+ function useUnderlyingTokenAddress(options = {}) {
154
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
155
+ return useQuery({
156
+ // The TTT is derived from the CTTT, which is already keyed via
157
+ // `resolvedAddress` — no separate underlying segment needed.
158
+ queryKey: buildQueryKey("underlyingToken", chainId, resolvedAddress),
159
+ queryFn: () => client.underlyingToken(),
160
+ enabled: !!client,
161
+ // The backing token address is fixed per deployment — never goes stale.
162
+ staleTime: Infinity
163
+ });
164
+ }
165
+ function useInferredTotalSupply(options = {}) {
166
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
167
+ return useQuery({
168
+ queryKey: buildQueryKey("inferredTotalSupply", chainId, resolvedAddress),
169
+ queryFn: () => client.inferredTotalSupply(),
170
+ enabled: !!client,
171
+ staleTime: 0
172
+ });
173
+ }
174
+ function useMaxTotalSupply(options = {}) {
175
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
176
+ return useQuery({
177
+ queryKey: buildQueryKey("maxTotalSupply", chainId, resolvedAddress),
178
+ queryFn: () => client.maxTotalSupply(),
179
+ enabled: !!client,
180
+ // `type(uint64).max` is fixed per deployment — never goes stale.
181
+ staleTime: Infinity
182
+ });
183
+ }
184
+ function useFaucetMetadata(options = {}) {
185
+ const { client, chainId, resolvedAddress } = useMemoFaucetClient(options);
186
+ return useQuery({
187
+ // The `underlying` half of the metadata is derived from the CTTT, which is
188
+ // already keyed via `resolvedAddress` — no separate underlying segment needed.
189
+ queryKey: buildQueryKey("getMetadata", chainId, resolvedAddress),
190
+ queryFn: () => client.getMetadata(),
191
+ enabled: !!client,
192
+ // name/symbol/decimals/rate/maxTotalSupply are all fixed per deployment.
193
+ staleTime: Infinity
194
+ });
195
+ }
196
+ function useMintConfidential(options = {}) {
197
+ const { client, resolutionError } = useMemoFaucetClient(options);
198
+ return useMutation({
199
+ mutationFn: async (args) => {
200
+ if (!client) {
201
+ throw resolutionError ?? new MissingClientError("useMintConfidential", "testnet-faucet");
202
+ }
203
+ return client.mintConfidential(args);
204
+ }
205
+ });
206
+ }
207
+ function useMintUnderlying(options = {}) {
208
+ const { client, resolutionError } = useMemoFaucetClient(options);
209
+ return useMutation({
210
+ mutationFn: async (args) => {
211
+ if (!client) {
212
+ throw resolutionError ?? new MissingClientError("useMintUnderlying", "testnet-faucet");
213
+ }
214
+ return client.mintUnderlying(args);
215
+ }
216
+ });
217
+ }
218
+
219
+ export { TESTNET_FAUCET_KEY, TESTNET_FAUCET_NAMESPACE, useConfidentialBalance, useFaucetDecimals, useFaucetMetadata, useFaucetRate, useInferredTotalSupply, useMaxTotalSupply, useMintConfidential, useMintUnderlying, useUnderlyingBalance, useUnderlyingDecimals, useUnderlyingTokenAddress };
@@ -0,0 +1,24 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import type { Address, Hex } from "viem";
3
+ import { type BaseHookOptions } from "./_shared.js";
4
+ export interface UseConfidentialBalanceArgs extends BaseHookOptions {
5
+ /**
6
+ * Account whose confidential balance handle to read. Defaults to the
7
+ * connected wallet (`useAccount().address`). The hook stays disabled until an
8
+ * account is available.
9
+ */
10
+ account?: Address;
11
+ }
12
+ /**
13
+ * Read the encrypted confidential balance handle (`euint64` ciphertext) for
14
+ * `account` — defaults to the connected wallet.
15
+ *
16
+ * Returns the `bytes32` handle. The account holds persistent ACL on its own
17
+ * balance, so pass this handle — with the CTTT contract address and the
18
+ * account's signer — to the Zama relayer's `userDecrypt` to obtain the
19
+ * plaintext. The SDK is the producer side only.
20
+ *
21
+ * @example
22
+ * const { data: handle } = useConfidentialBalance(); // my own balance handle
23
+ */
24
+ export declare function useConfidentialBalance(args?: UseConfidentialBalanceArgs): UseQueryResult<Hex, Error>;
@@ -0,0 +1,9 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import { type BaseHookOptions } from "./_shared.js";
3
+ /**
4
+ * Read the decimals of the confidential token (CTTT) — `6`.
5
+ *
6
+ * @example
7
+ * const { data: decimals } = useFaucetDecimals(); // 6
8
+ */
9
+ export declare function useFaucetDecimals(options?: BaseHookOptions): UseQueryResult<number, Error>;
@@ -0,0 +1,14 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import { type FaucetMetadata } from "../types.js";
3
+ import { type BaseHookOptions } from "./_shared.js";
4
+ /**
5
+ * Read consolidated faucet metadata in a single hook — both tokens'
6
+ * name/symbol/decimals/address, the conversion `rate`, and the
7
+ * `maxTotalSupply` ceiling. Handy for rendering a faucet panel without
8
+ * composing several reads.
9
+ *
10
+ * @example
11
+ * const { data: meta } = useFaucetMetadata();
12
+ * // meta?.confidential.symbol, meta?.underlying.decimals, meta?.rate, ...
13
+ */
14
+ export declare function useFaucetMetadata(options?: BaseHookOptions): UseQueryResult<FaucetMetadata, Error>;
@@ -0,0 +1,11 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import { type BaseHookOptions } from "./_shared.js";
3
+ /**
4
+ * Read the decimal-conversion `rate` between underlying and confidential units:
5
+ * `1` CTTT 6-decimal unit is backed by `rate` TTT 18-decimal base units
6
+ * (`10^(18-6) = 10^12`).
7
+ *
8
+ * @example
9
+ * const { data: rate } = useFaucetRate(); // 1_000_000_000_000n
10
+ */
11
+ export declare function useFaucetRate(options?: BaseHookOptions): UseQueryResult<bigint, Error>;
@@ -0,0 +1,11 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import { type BaseHookOptions } from "./_shared.js";
3
+ /**
4
+ * Read the wrapper's inferred total supply: underlying held in custody divided
5
+ * by `rate`, an upper bound on the confidential total supply, in CTTT
6
+ * 6-decimal units.
7
+ *
8
+ * @example
9
+ * const { data: supply } = useInferredTotalSupply();
10
+ */
11
+ export declare function useInferredTotalSupply(options?: BaseHookOptions): UseQueryResult<bigint, Error>;
@@ -0,0 +1,10 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import { type BaseHookOptions } from "./_shared.js";
3
+ /**
4
+ * Read the max confidential total supply the wrapper supports
5
+ * (`type(uint64).max`).
6
+ *
7
+ * @example
8
+ * const { data: max } = useMaxTotalSupply();
9
+ */
10
+ export declare function useMaxTotalSupply(options?: BaseHookOptions): UseQueryResult<bigint, Error>;
@@ -0,0 +1,35 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import { type MintConfidentialArgs, type MintConfidentialResult } from "../types.js";
3
+ import { type BaseHookOptions } from "./_shared.js";
4
+ /** Args for {@link useMintConfidential} — same shape as the headless `MintConfidentialArgs`. */
5
+ export type UseMintConfidentialArgs = MintConfidentialArgs;
6
+ /**
7
+ * Mint backed confidential test tokens (CTTT) to a recipient. Open and
8
+ * permissionless on testnet — anyone can mint any `uint64` amount, fully backed
9
+ * by freshly minted underlying TTT.
10
+ *
11
+ * The amount is PUBLIC (plaintext calldata + `ConfidentialMint` event); only
12
+ * the recipient's aggregated balance and later confidential transfers are
13
+ * private. Delegates 1:1 to {@link TestnetFaucetClient.mintConfidential} and
14
+ * returns its `MintConfidentialResult` (decoded from the `ConfidentialMint`
15
+ * event).
16
+ *
17
+ * Mutations do NOT auto-invalidate read queries — that's a consumer decision.
18
+ * After a successful mint, invalidate every faucet query for fresh balances:
19
+ *
20
+ * ```ts
21
+ * const queryClient = useQueryClient();
22
+ * const mint = useMintConfidential();
23
+ * mint.mutate({ amount: 1_000_000_000n }, {
24
+ * onSuccess: () => {
25
+ * queryClient.invalidateQueries({ queryKey: ["tokenops-sdk", "testnet-faucet"] });
26
+ * },
27
+ * });
28
+ * ```
29
+ *
30
+ * @example
31
+ * const mint = useMintConfidential();
32
+ * mint.mutate({ amount: 1_000_000_000n }); // 1,000 CTTT (6-decimal units)
33
+ * // mint.data → { hash, to, amount, underlyingMinted, handle }
34
+ */
35
+ export declare function useMintConfidential(options?: BaseHookOptions): UseMutationResult<MintConfidentialResult, Error, UseMintConfidentialArgs>;
@@ -0,0 +1,31 @@
1
+ import { type UseMutationResult } from "@tanstack/react-query";
2
+ import { type MintUnderlyingArgs, type MintUnderlyingResult } from "../types.js";
3
+ import { type BaseHookOptions } from "./_shared.js";
4
+ /** Args for {@link useMintUnderlying} — same shape as the headless `MintUnderlyingArgs`. */
5
+ export type UseMintUnderlyingArgs = MintUnderlyingArgs;
6
+ /**
7
+ * Mint standard (non-confidential) ERC-20 test tokens (TTT) to a recipient.
8
+ * Open and permissionless on testnet. Use this when you want plain TTT — e.g.
9
+ * to then `approve` + `wrap` it into CTTT through the standard ERC-7984 flow.
10
+ *
11
+ * Delegates 1:1 to {@link TestnetFaucetClient.mintUnderlying}.
12
+ *
13
+ * Mutations do NOT auto-invalidate read queries. After a successful mint,
14
+ * invalidate every faucet query for fresh balances:
15
+ *
16
+ * ```ts
17
+ * const queryClient = useQueryClient();
18
+ * const mint = useMintUnderlying();
19
+ * mint.mutate({ amount: 1_000_000_000_000_000_000_000n }, {
20
+ * onSuccess: () => {
21
+ * queryClient.invalidateQueries({ queryKey: ["tokenops-sdk", "testnet-faucet"] });
22
+ * },
23
+ * });
24
+ * ```
25
+ *
26
+ * @example
27
+ * const mint = useMintUnderlying();
28
+ * mint.mutate({ amount: 1_000_000_000_000_000_000_000n }); // 1,000 TTT (18-decimal units)
29
+ * // mint.data → { hash, to, amount }
30
+ */
31
+ export declare function useMintUnderlying(options?: BaseHookOptions): UseMutationResult<MintUnderlyingResult, Error, UseMintUnderlyingArgs>;
@@ -0,0 +1,19 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import type { Address } from "viem";
3
+ import { type BaseHookOptions } from "./_shared.js";
4
+ export interface UseUnderlyingBalanceArgs extends BaseHookOptions {
5
+ /**
6
+ * Account whose underlying TTT balance to read. Defaults to the connected
7
+ * wallet (`useAccount().address`). The hook stays disabled until an account
8
+ * is available.
9
+ */
10
+ account?: Address;
11
+ }
12
+ /**
13
+ * Read the plaintext underlying `TokenopsTestToken` (TTT) balance for
14
+ * `account` (defaults to the connected wallet), in TTT 18-decimal base units.
15
+ *
16
+ * @example
17
+ * const { data: balance } = useUnderlyingBalance(); // my own TTT balance
18
+ */
19
+ export declare function useUnderlyingBalance(args?: UseUnderlyingBalanceArgs): UseQueryResult<bigint, Error>;
@@ -0,0 +1,9 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import { type BaseHookOptions } from "./_shared.js";
3
+ /**
4
+ * Read the decimals of the underlying token (TTT) — `18`.
5
+ *
6
+ * @example
7
+ * const { data: decimals } = useUnderlyingDecimals(); // 18
8
+ */
9
+ export declare function useUnderlyingDecimals(options?: BaseHookOptions): UseQueryResult<number, Error>;
@@ -0,0 +1,12 @@
1
+ import { type UseQueryResult } from "@tanstack/react-query";
2
+ import type { Address } from "viem";
3
+ import { type BaseHookOptions } from "./_shared.js";
4
+ /**
5
+ * Read the underlying `TokenopsTestToken` (TTT) address backing the CTTT
6
+ * wrapper. Resolution order inside the client: registry → the wrapper's own
7
+ * `underlying()` getter.
8
+ *
9
+ * @example
10
+ * const { data: tttAddress } = useUnderlyingTokenAddress();
11
+ */
12
+ export declare function useUnderlyingTokenAddress(options?: BaseHookOptions): UseQueryResult<Address, Error>;
@@ -0,0 +1,92 @@
1
+ import type { Account, Address } from "viem";
2
+ import type { EncryptedHandle, TxHash } from "../core/brands.js";
3
+ /**
4
+ * Arguments for {@link TestnetFaucetClient.mintConfidential} — the open,
5
+ * fully-backed faucet mint on `ConfidentialTokenopsTestToken` (CTTT).
6
+ */
7
+ export interface MintConfidentialArgs {
8
+ /**
9
+ * Recipient of the confidential balance. Defaults to the signing account
10
+ * (`account` override, else the wallet's account).
11
+ */
12
+ to?: Address;
13
+ /**
14
+ * Amount to mint, in CTTT's **6-decimal** units (a `uint64`).
15
+ *
16
+ * NOTE: this amount is PUBLIC — it is passed as plaintext calldata, emitted
17
+ * in the `ConfidentialMint` event, and wrapped via a trivial (non-secret)
18
+ * encryption. Only the recipient's *aggregated* balance and subsequent
19
+ * confidential transfers are private; the per-mint amount is not.
20
+ */
21
+ amount: bigint;
22
+ /** Signer override. Accepts a viem `Account` object or an `Address` string. */
23
+ account?: Account | Address;
24
+ }
25
+ /**
26
+ * Result of {@link TestnetFaucetClient.mintConfidential}, decoded from the
27
+ * `ConfidentialMint` event in the transaction receipt.
28
+ */
29
+ export interface MintConfidentialResult {
30
+ /** Transaction hash of the mint. */
31
+ hash: TxHash;
32
+ /** Recipient credited with the confidential balance. */
33
+ to: Address;
34
+ /** Plaintext amount minted, in CTTT 6-decimal units (echoed — the faucet mint amount is public). */
35
+ amount: bigint;
36
+ /** Underlying TTT minted into the wrapper as 1:1 backing (= `amount * rate`, in TTT 18-decimal base units). */
37
+ underlyingMinted: bigint;
38
+ /**
39
+ * The minted ciphertext handle from the `ConfidentialMint` event. Informational —
40
+ * the recipient holds persistent ACL on their *balance*, which you read via
41
+ * {@link TestnetFaucetClient.confidentialBalanceOf} and pass to the Zama
42
+ * relayer's `userDecrypt`. The caller only receives transient ACL on this
43
+ * handle (valid within the mint tx), so it is not itself user-decryptable
44
+ * afterwards.
45
+ */
46
+ handle: EncryptedHandle;
47
+ }
48
+ /**
49
+ * Arguments for {@link TestnetFaucetClient.mintUnderlying} — the open mint on
50
+ * the standard ERC-20 `TokenopsTestToken` (TTT).
51
+ */
52
+ export interface MintUnderlyingArgs {
53
+ /** Recipient of the TTT. Defaults to the signing account. */
54
+ to?: Address;
55
+ /** Amount to mint, in TTT's **18-decimal** base units (a `uint256`). */
56
+ amount: bigint;
57
+ /** Signer override. */
58
+ account?: Account | Address;
59
+ }
60
+ /** Result of {@link TestnetFaucetClient.mintUnderlying}. */
61
+ export interface MintUnderlyingResult {
62
+ /** Transaction hash of the mint. */
63
+ hash: TxHash;
64
+ /** Recipient credited with the TTT. */
65
+ to: Address;
66
+ /** Plaintext amount minted, in TTT 18-decimal base units. */
67
+ amount: bigint;
68
+ }
69
+ /** Static metadata for one side of the faucet token pair. */
70
+ export interface FaucetTokenMetadata {
71
+ address: Address;
72
+ name: string;
73
+ symbol: string;
74
+ decimals: number;
75
+ }
76
+ /**
77
+ * Consolidated faucet metadata — both tokens, the wrapper `rate`, and the
78
+ * `maxTotalSupply` ceiling. One convenience read for UI surfaces.
79
+ */
80
+ export interface FaucetMetadata {
81
+ /** The confidential ERC-7984 wrapper (CTTT). */
82
+ confidential: FaucetTokenMetadata;
83
+ /** The underlying ERC-20 (TTT). */
84
+ underlying: FaucetTokenMetadata;
85
+ /**
86
+ * Decimal-conversion rate between underlying and confidential units:
87
+ * `1` CTTT unit is backed by `rate` TTT base units (`10^(18-6) = 10^12`).
88
+ */
89
+ rate: bigint;
90
+ /** Max confidential total supply the wrapper supports (`type(uint64).max`). */
91
+ maxTotalSupply: bigint;
92
+ }
@@ -0,0 +1,44 @@
1
+ import type { Address } from "viem";
2
+ /**
3
+ * Chain ids on which the testnet faucet is allowed to operate.
4
+ *
5
+ * The faucet mints **value-less** test tokens to anyone, so it must never be
6
+ * usable on a value-bearing network. We allow Sepolia (the canonical public
7
+ * testnet deployment) and the local Anvil/Hardhat dev chain id `31337` (used
8
+ * by the SDK's own FHEVM test fixtures, which deploy the token pair at test
9
+ * time). Every other chain — mainnet above all — is rejected at construction.
10
+ */
11
+ export declare const TESTNET_FAUCET_SUPPORTED_CHAIN_IDS: readonly [11155111, 31337];
12
+ /** `true` when `chainId` is a chain the faucet is permitted to run on. */
13
+ export declare function isTestnetFaucetChainId(chainId: number): boolean;
14
+ /**
15
+ * Hard testnet-only guard. Throws {@link UnsupportedChainError} when `chainId`
16
+ * is a known non-testnet chain (mainnet, or anything outside
17
+ * {@link TESTNET_FAUCET_SUPPORTED_CHAIN_IDS}).
18
+ *
19
+ * A `undefined` chain id is intentionally NOT rejected here — the client can
20
+ * still be constructed with an explicit `address` override on an
21
+ * unknown-chain `publicClient`, and address resolution raises the precise
22
+ * `DeploymentAddressUnavailableError("chain-id-missing")` when no override is
23
+ * present. The guard's job is to slam the door on mainnet, not to second-guess
24
+ * a deliberate local override.
25
+ */
26
+ export declare function assertTestnetFaucetChain(chainId: number | undefined): void;
27
+ /**
28
+ * Assert that `value` fits the confidential faucet's `uint64` amount domain.
29
+ * CTTT balances are `euint64`, so `mint(to, amount)` takes a `uint64`. Amounts
30
+ * are denominated in CTTT's 6-decimal units.
31
+ */
32
+ export declare function assertUint64Amount(value: bigint, argument: string, method: string): void;
33
+ /**
34
+ * Assert that `value` fits the underlying ERC-20's `uint256` amount domain.
35
+ * TTT amounts are denominated in 18-decimal base units.
36
+ */
37
+ export declare function assertUint256Amount(value: bigint, argument: string, method: string): void;
38
+ /**
39
+ * Normalise an address to EIP-55 checksum form, rejecting the zero address.
40
+ * Faucet recipients (`to`) must be a real account — the contracts revert with
41
+ * `ERC7984InvalidReceiver` / `ERC20InvalidReceiver` on the zero address, but
42
+ * catching it here gives a clearer, pre-flight `InvalidArgumentError`.
43
+ */
44
+ export declare function assertNonZeroRecipient(input: Address, argument: string, method: string): Address;