@tokenops/sdk 1.1.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/CHANGELOG.md +158 -2
  2. package/README.md +18 -8
  3. package/SECURITY.md +7 -1
  4. package/dist/{chunk-56UI7LUR.cjs → chunk-2RNW4MIJ.cjs} +37 -0
  5. package/dist/{chunk-VDXVNZCO.cjs → chunk-43RFBQ73.cjs} +85 -29
  6. package/dist/{chunk-BE2AIZ3K.js → chunk-46T67CE2.js} +1 -1
  7. package/dist/{chunk-WRCUDSUJ.js → chunk-4KJ66YRH.js} +61 -3
  8. package/dist/{chunk-ITQ7WKVC.cjs → chunk-4ZCXK4VI.cjs} +68 -8
  9. package/dist/{chunk-JFLEEXKP.js → chunk-6WSNS3UV.js} +58 -2
  10. package/dist/{chunk-W7JHOK7G.cjs → chunk-7G7UOQV4.cjs} +4 -4
  11. package/dist/{chunk-5KHIQG7Y.cjs → chunk-AYGRYDBX.cjs} +35 -36
  12. package/dist/{chunk-5SGMJADP.cjs → chunk-BD4LZBVF.cjs} +85 -9
  13. package/dist/{chunk-OYLZEEHF.cjs → chunk-BK7YIVLK.cjs} +304 -179
  14. package/dist/{chunk-SEKC7H5Y.cjs → chunk-CBRL2PJA.cjs} +12 -11
  15. package/dist/{chunk-XWDVPV42.js → chunk-CNP4L3GF.js} +4 -4
  16. package/dist/{chunk-IVE3QEGD.js → chunk-DRSPMIZ7.js} +28 -1
  17. package/dist/{chunk-SAGJIEQK.cjs → chunk-EUKPOXWR.cjs} +15 -16
  18. package/dist/chunk-FT4LNBOS.js +11 -0
  19. package/dist/{chunk-ITQBDRWX.js → chunk-HETNKZEE.js} +1 -1
  20. package/dist/{chunk-JJ4R5QXF.js → chunk-KSDSXJ34.js} +1 -1
  21. package/dist/{chunk-SYHXDHWX.cjs → chunk-LBWRFZR3.cjs} +218 -31
  22. package/dist/{chunk-ZXCOJY2Z.js → chunk-NFW7AUEX.js} +1 -1
  23. package/dist/{chunk-FPQBFIUW.cjs → chunk-OL6SHN3D.cjs} +3 -3
  24. package/dist/{chunk-XSNLAS5M.js → chunk-PD7ME2BT.js} +75 -2
  25. package/dist/{chunk-FXCW7LVB.js → chunk-QET3Q4JP.js} +94 -9
  26. package/dist/{chunk-M7V2EDPB.js → chunk-QKKBBH7I.js} +2 -2
  27. package/dist/{chunk-XXXDQSHE.js → chunk-S2XD75JM.js} +12 -3
  28. package/dist/{chunk-5SA2HF2W.cjs → chunk-SPGSO5SO.cjs} +31 -22
  29. package/dist/{chunk-Q7ARQSUH.cjs → chunk-SYHNZSZZ.cjs} +3 -3
  30. package/dist/{chunk-X56UVEXS.js → chunk-TN65XNTI.js} +248 -120
  31. package/dist/chunk-U57COLUE.js +56 -0
  32. package/dist/{chunk-OQZAZIAS.js → chunk-UE5XK2SY.js} +193 -6
  33. package/dist/{chunk-NS44KBV5.cjs → chunk-UJS4N2XM.cjs} +12 -12
  34. package/dist/{chunk-IR5AK5U5.js → chunk-V5D7BHW3.js} +4 -5
  35. package/dist/{chunk-3PQ2RFPC.js → chunk-VHSNYUYV.js} +5 -4
  36. package/dist/{chunk-CQIPRNS7.cjs → chunk-VR3FREBX.cjs} +3 -3
  37. package/dist/{chunk-G7G75C46.cjs → chunk-WO72UBQD.cjs} +11 -11
  38. package/dist/chunk-WOEETTH7.cjs +59 -0
  39. package/dist/{chunk-QE7ZONJ2.js → chunk-WTK6JDSI.js} +4 -5
  40. package/dist/{chunk-3ZRHDTEX.cjs → chunk-WUXUWTFW.cjs} +3 -3
  41. package/dist/{chunk-23F7JIK5.cjs → chunk-YFIWCYHC.cjs} +141 -54
  42. package/dist/{chunk-FYQ2UW4T.js → chunk-YPYCWLYP.js} +1 -1
  43. package/dist/chunk-ZQUE2B3Q.cjs +33 -0
  44. package/dist/core/addresses.d.ts +1 -1
  45. package/dist/core/errors.d.ts +41 -1
  46. package/dist/core/revert-mapper.d.ts +77 -0
  47. package/dist/core/wagmi-compat.d.ts +40 -0
  48. package/dist/fhe/index.cjs +134 -68
  49. package/dist/fhe/index.d.cts +2 -1
  50. package/dist/fhe/index.d.ts +2 -1
  51. package/dist/fhe/index.js +64 -10
  52. package/dist/fhe/mock-erc7984.d.ts +4 -4
  53. package/dist/fhe/operators.d.ts +142 -2
  54. package/dist/fhe/react/index.cjs +21 -8
  55. package/dist/fhe/react/index.d.cts +2 -0
  56. package/dist/fhe/react/index.d.ts +2 -0
  57. package/dist/fhe/react/index.js +8 -3
  58. package/dist/fhe/react/useEnsureOperator.d.ts +56 -0
  59. package/dist/fhe/react/useIsOperator.d.ts +54 -0
  60. package/dist/fhe/sepolia-encryptor-web.d.ts +45 -4
  61. package/dist/fhe/sepolia-encryptor.d.ts +38 -0
  62. package/dist/fhe-airdrop/advanced/index.cjs +9 -9
  63. package/dist/fhe-airdrop/advanced/index.js +7 -7
  64. package/dist/fhe-airdrop/advanced/react/index.cjs +14 -14
  65. package/dist/fhe-airdrop/advanced/react/index.js +10 -10
  66. package/dist/fhe-airdrop/airdrop.d.ts +9 -0
  67. package/dist/fhe-airdrop/encryption.d.ts +8 -0
  68. package/dist/fhe-airdrop/factory.d.ts +86 -1
  69. package/dist/fhe-airdrop/index.cjs +69 -66
  70. package/dist/fhe-airdrop/index.d.cts +3 -3
  71. package/dist/fhe-airdrop/index.d.ts +3 -3
  72. package/dist/fhe-airdrop/index.js +7 -8
  73. package/dist/fhe-airdrop/react/index.cjs +176 -135
  74. package/dist/fhe-airdrop/react/index.d.cts +7 -4
  75. package/dist/fhe-airdrop/react/index.d.ts +7 -4
  76. package/dist/fhe-airdrop/react/index.js +43 -16
  77. package/dist/fhe-airdrop/react/useAccessClaimAmount.d.ts +17 -11
  78. package/dist/fhe-airdrop/react/useAirdropIsSignatureValid.d.ts +3 -2
  79. package/dist/fhe-airdrop/react/useClaim.d.ts +10 -0
  80. package/dist/fhe-airdrop/react/useCreateAndFundConfidentialAirdrop.d.ts +8 -0
  81. package/dist/fhe-airdrop/react/useCreateAndFundConfidentialAirdropAndGetAddress.d.ts +8 -0
  82. package/dist/fhe-airdrop/react/useFundConfidentialAirdrop.d.ts +8 -0
  83. package/dist/fhe-airdrop/react/usePreflightCreateAirdrop.d.ts +51 -0
  84. package/dist/fhe-airdrop/react/useSignClaimAuthorization.d.ts +1 -1
  85. package/dist/fhe-airdrop/types.d.ts +56 -0
  86. package/dist/fhe-disperse/encryption.d.ts +8 -0
  87. package/dist/fhe-disperse/errors.d.ts +55 -0
  88. package/dist/fhe-disperse/index.cjs +77 -66
  89. package/dist/fhe-disperse/index.d.cts +2 -2
  90. package/dist/fhe-disperse/index.d.ts +2 -2
  91. package/dist/fhe-disperse/index.js +8 -9
  92. package/dist/fhe-disperse/react/index.cjs +108 -87
  93. package/dist/fhe-disperse/react/index.d.cts +4 -2
  94. package/dist/fhe-disperse/react/index.d.ts +4 -2
  95. package/dist/fhe-disperse/react/index.js +12 -11
  96. package/dist/fhe-disperse/react/useCalculateFee.d.ts +7 -0
  97. package/dist/fhe-disperse/react/useDisperse.d.ts +9 -0
  98. package/dist/fhe-disperse/react/usePreflightDisperse.d.ts +7 -0
  99. package/dist/fhe-disperse/react/useSingletonCalculateFee.d.ts +7 -0
  100. package/dist/fhe-disperse/react/useSingletonWithdrawTokenFee.d.ts +6 -0
  101. package/dist/fhe-disperse/react/useWithdrawTokenFee.d.ts +6 -0
  102. package/dist/fhe-disperse/singleton.d.ts +29 -0
  103. package/dist/fhe-disperse/subtotals.d.ts +6 -0
  104. package/dist/fhe-vesting/advanced/index.cjs +8 -9
  105. package/dist/fhe-vesting/advanced/index.js +6 -7
  106. package/dist/fhe-vesting/advanced/react/index.cjs +15 -15
  107. package/dist/fhe-vesting/advanced/react/index.js +12 -12
  108. package/dist/fhe-vesting/encryption.d.ts +8 -0
  109. package/dist/fhe-vesting/index.cjs +82 -79
  110. package/dist/fhe-vesting/index.d.cts +2 -2
  111. package/dist/fhe-vesting/index.d.ts +2 -2
  112. package/dist/fhe-vesting/index.js +9 -10
  113. package/dist/fhe-vesting/manager.d.ts +119 -1
  114. package/dist/fhe-vesting/react/index.cjs +264 -224
  115. package/dist/fhe-vesting/react/index.d.cts +9 -6
  116. package/dist/fhe-vesting/react/index.d.ts +9 -6
  117. package/dist/fhe-vesting/react/index.js +44 -21
  118. package/dist/fhe-vesting/react/useAccessClaimableAmount.d.ts +11 -3
  119. package/dist/fhe-vesting/react/useAccessSettledAmount.d.ts +11 -3
  120. package/dist/fhe-vesting/react/useAccessTotalAllocation.d.ts +11 -3
  121. package/dist/fhe-vesting/react/useAccessVestedAmount.d.ts +11 -3
  122. package/dist/fhe-vesting/react/useAdminClaim.d.ts +2 -0
  123. package/dist/fhe-vesting/react/useAdminGetClaimableAmount.d.ts +1 -1
  124. package/dist/fhe-vesting/react/useAdminGetSettledAmount.d.ts +1 -1
  125. package/dist/fhe-vesting/react/useAdminGetTotalAllocation.d.ts +1 -1
  126. package/dist/fhe-vesting/react/useAdminGetVestedAmount.d.ts +1 -1
  127. package/dist/fhe-vesting/react/useAdminPartialClaim.d.ts +10 -0
  128. package/dist/fhe-vesting/react/useBatchCreateVesting.d.ts +8 -0
  129. package/dist/fhe-vesting/react/useClaim.d.ts +3 -1
  130. package/dist/fhe-vesting/react/useCreateVesting.d.ts +8 -0
  131. package/dist/fhe-vesting/react/useDiscloseHandleToParty.d.ts +1 -1
  132. package/dist/fhe-vesting/react/useManagerDiscloseHandleToParty.d.ts +1 -1
  133. package/dist/fhe-vesting/react/useManagerWithdrawTokenFee.d.ts +6 -0
  134. package/dist/fhe-vesting/react/usePartialClaim.d.ts +9 -1
  135. package/dist/fhe-vesting/react/usePreflightCreateVesting.d.ts +37 -0
  136. package/dist/fhe-vesting/react/useVestingClaim.d.ts +2 -0
  137. package/dist/fhe-vesting/react/useVestingInfo.d.ts +1 -1
  138. package/dist/fhe-vesting/react/useWithdrawAdmin.d.ts +6 -0
  139. package/dist/fhe-vesting/react/useWithdrawTokenFee.d.ts +6 -0
  140. package/dist/fhe-vesting/types.d.ts +45 -0
  141. package/dist/index.cjs +93 -86
  142. package/dist/index.d.cts +1 -1
  143. package/dist/index.d.ts +1 -1
  144. package/dist/index.js +2 -3
  145. package/dist/testnet-faucet/index.cjs +58 -55
  146. package/dist/testnet-faucet/index.d.cts +1 -1
  147. package/dist/testnet-faucet/index.d.ts +1 -1
  148. package/dist/testnet-faucet/index.js +5 -6
  149. package/dist/testnet-faucet/react/index.cjs +60 -56
  150. package/dist/testnet-faucet/react/index.d.cts +3 -2
  151. package/dist/testnet-faucet/react/index.d.ts +3 -2
  152. package/dist/testnet-faucet/react/index.js +11 -11
  153. package/dist/testnet-faucet/react/useConfidentialBalance.d.ts +3 -2
  154. package/dist/testnet-faucet/react/useUnderlyingBalance.d.ts +2 -2
  155. package/package.json +14 -8
  156. package/dist/chunk-66IHPTOK.cjs +0 -20
  157. package/dist/chunk-KWFFIJYX.js +0 -11
  158. package/dist/fhe-airdrop/react/useAirdropClaim.d.ts +0 -25
  159. package/dist/fhe-airdrop/react/useGetClaimAmount.d.ts +0 -30
  160. package/dist/fhe-vesting/react/useGetClaimableAmount.d.ts +0 -13
  161. package/dist/fhe-vesting/react/useGetSettledAmount.d.ts +0 -14
  162. package/dist/fhe-vesting/react/useGetTotalAllocation.d.ts +0 -13
  163. package/dist/fhe-vesting/react/useGetVestedAmount.d.ts +0 -25
@@ -1,10 +1,10 @@
1
- import { SDK_VERSION, mapContractRevert, isContractRevert } from './chunk-JFLEEXKP.js';
2
- import { getFheAirdropFactoryAddress } from './chunk-M7V2EDPB.js';
3
- import { normaliseAddress } from './chunk-BE2AIZ3K.js';
1
+ import { erc7984OperatorAbi } from './chunk-7VELUOMI.js';
2
+ import { SDK_VERSION, mapContractRevert, isContractRevert } from './chunk-6WSNS3UV.js';
3
+ import { getFheAirdropFactoryAddress } from './chunk-QKKBBH7I.js';
4
+ import { normaliseAddress } from './chunk-46T67CE2.js';
5
+ import { InvalidArgumentError, asExternalInputProof, asEncryptedHandle, TokenOpsSdkError, MissingAccountError, asSignature, DeploymentAddressUnavailableError, OperatorNotApprovedError, AlreadyInitializedError, asTxHash, MissingWalletClientError, MissingEncryptorError } from './chunk-DRSPMIZ7.js';
4
6
  import { withTelemetry } from './chunk-Q2GP5UDC.js';
5
- import { asExternalInputProof, asEncryptedHandle, asSignature, asTxHash } from './chunk-KWFFIJYX.js';
6
- import { InvalidArgumentError, TokenOpsSdkError, MissingAccountError, DeploymentAddressUnavailableError, MissingWalletClientError, MissingEncryptorError } from './chunk-IVE3QEGD.js';
7
- import { bytesToHex, parseEventLogs } from 'viem';
7
+ import { bytesToHex, isAddress, parseEventLogs, BaseError, ContractFunctionZeroDataError } from 'viem';
8
8
 
9
9
  // src/fhe-airdrop/abis/factory.ts
10
10
  var confidentialAirdropFactoryAbi = [
@@ -1116,6 +1116,14 @@ var ConfidentialAirdropFactoryClient = class {
1116
1116
  * Prerequisites: caller must have set this factory as an operator on the
1117
1117
  * token: `token.setOperator(factoryAddress, deadline)`.
1118
1118
  *
1119
+ * **Silent-zero transfers.** ERC-7984 transfers do not revert when the sender's encrypted balance is insufficient — the transfer succeeds and moves an encrypted zero instead. This is by design: reverting would leak balance information. The transaction receipt alone cannot tell you whether value actually moved.
1120
+ *
1121
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1122
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1123
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1124
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1125
+ * transparent TTT test token uses 18 decimals.
1126
+ *
1119
1127
  * Symmetric with {@link ConfidentialAirdropFactoryClient.createConfidentialAirdrop}
1120
1128
  * — both return `{ hash, airdrop }` parsed from the
1121
1129
  * `ConfidentialAirdropCreated` event.
@@ -1178,6 +1186,14 @@ var ConfidentialAirdropFactoryClient = class {
1178
1186
  * Prerequisites: caller must have set this factory as an operator on the token:
1179
1187
  * `token.setOperator(factoryAddress, deadline)`
1180
1188
  *
1189
+ * **Silent-zero transfers.** ERC-7984 transfers do not revert when the sender's encrypted balance is insufficient — the transfer succeeds and moves an encrypted zero instead. This is by design: reverting would leak balance information. The transaction receipt alone cannot tell you whether value actually moved.
1190
+ *
1191
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1192
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1193
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1194
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1195
+ * transparent TTT test token uses 18 decimals.
1196
+ *
1181
1197
  * @returns Transaction hash.
1182
1198
  */
1183
1199
  async fundConfidentialAirdrop(args) {
@@ -1247,6 +1263,14 @@ var ConfidentialAirdropFactoryClient = class {
1247
1263
  * Symmetry with {@link ConfidentialAirdropFactoryClient.createConfidentialAirdropAndGetAddress}
1248
1264
  * — use this when you also need to seed the pool in the same transaction.
1249
1265
  *
1266
+ * **Silent-zero transfers.** ERC-7984 transfers do not revert when the sender's encrypted balance is insufficient — the transfer succeeds and moves an encrypted zero instead. This is by design: reverting would leak balance information. The transaction receipt alone cannot tell you whether value actually moved.
1267
+ *
1268
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1269
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1270
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1271
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1272
+ * transparent TTT test token uses 18 decimals.
1273
+ *
1250
1274
  * Internally: {@link ConfidentialAirdropFactoryClient.createAndFundConfidentialAirdrop} →
1251
1275
  * {@link PublicClient.waitForTransactionReceipt} →
1252
1276
  * `parseEventLogs({ eventName: "ConfidentialAirdropCreated" })`.
@@ -1329,6 +1353,163 @@ var ConfidentialAirdropFactoryClient = class {
1329
1353
  async getInitCodeHash(args) {
1330
1354
  return this.#read("getInitCodeHash", [toAbiParams(args.params), args.gasFee]);
1331
1355
  }
1356
+ // ----------------------- preflight -----------------------
1357
+ /**
1358
+ * Read-only preflight for {@link createConfidentialAirdrop} /
1359
+ * {@link createAndFundConfidentialAirdrop}. Runs the
1360
+ * deterministic-from-off-chain checks and reports blockers both as
1361
+ * human-readable strings (`blockers`) and as typed {@link TokenOpsSdkError}s
1362
+ * (`blockerErrors`), index-aligned.
1363
+ *
1364
+ * Preflight is **opt-in**. Consumers who have already validated state can
1365
+ * skip this call and invoke the write directly — they'll receive the same
1366
+ * typed errors at write time via the revert mapper.
1367
+ *
1368
+ * Report fields: `isFactoryOperator`, `gasFee`, `predictedAirdrop`,
1369
+ * `alreadyDeployed`, `ready`, `blockers`, `blockerErrors` — see
1370
+ * {@link CreateAirdropPreflightReport} for the meaning of each.
1371
+ *
1372
+ * Checks performed (all read-only, no gas):
1373
+ * - Structural `params` validation mirroring the factory + clone
1374
+ * `initialize` requirements (`InvalidArgumentError` blockers): `token` and
1375
+ * `admin` are checksummed non-zero addresses,
1376
+ * `startTimestamp < endTimestamp`, and `endTimestamp` is in the future
1377
+ * (the clone's `initialize` reverts with `EndTimeInPast`).
1378
+ * - Operator: creator has approved this factory as an ERC-7984 operator on
1379
+ * `params.token` — a blocker only when `funding: true`
1380
+ * ({@link OperatorNotApprovedError}); otherwise informational via
1381
+ * `isFactoryOperator`.
1382
+ * - Collision (only when `userSalt` is supplied): bytecode already at the
1383
+ * predicted CREATE2 address means a repeat create with the same
1384
+ * `(params, userSalt, gasFee)` would revert
1385
+ * ({@link AlreadyInitializedError} blocker).
1386
+ *
1387
+ * **Not preflight-detectable — read before trusting `ready: true`:** the
1388
+ * creator's confidential token balance is an encrypted `euint64` the SDK
1389
+ * cannot read in plaintext, and an underfunded `createAndFund` does **not**
1390
+ * revert — the ERC-7984 transfer silently moves an encrypted zero. Confirm
1391
+ * the creator's balance covers the pool before submitting.
1392
+ *
1393
+ * @param args See {@link PreflightCreateAirdropArgs}.
1394
+ * @returns A {@link CreateAirdropPreflightReport}.
1395
+ */
1396
+ async preflightCreateAirdrop(args) {
1397
+ const { params, creator, userSalt, funding } = args;
1398
+ const blockers = [];
1399
+ const blockerErrors = [];
1400
+ const pushBlocker = (err) => {
1401
+ blockerErrors.push(err);
1402
+ blockers.push(err.message);
1403
+ };
1404
+ const tokenOk = isAddress(params.token, { strict: true }) && params.token !== ZERO_ADDRESS;
1405
+ if (!tokenOk) {
1406
+ pushBlocker(
1407
+ new InvalidArgumentError({
1408
+ method: "createConfidentialAirdrop",
1409
+ argument: "params.token",
1410
+ reason: "must be a valid, non-zero EIP-55 checksummed address",
1411
+ value: params.token
1412
+ })
1413
+ );
1414
+ }
1415
+ const adminOk = isAddress(params.admin, { strict: true }) && params.admin !== ZERO_ADDRESS;
1416
+ if (!adminOk) {
1417
+ pushBlocker(
1418
+ new InvalidArgumentError({
1419
+ method: "createConfidentialAirdrop",
1420
+ argument: "params.admin",
1421
+ reason: "must be a valid, non-zero EIP-55 checksummed address",
1422
+ value: params.admin
1423
+ })
1424
+ );
1425
+ }
1426
+ if (params.startTimestamp >= params.endTimestamp) {
1427
+ pushBlocker(
1428
+ new InvalidArgumentError({
1429
+ method: "createConfidentialAirdrop",
1430
+ argument: "params.startTimestamp/params.endTimestamp",
1431
+ reason: "startTimestamp must be strictly less than endTimestamp",
1432
+ value: { startTimestamp: params.startTimestamp, endTimestamp: params.endTimestamp }
1433
+ })
1434
+ );
1435
+ }
1436
+ const [block, customFee, defaultFee, operatorRead] = await Promise.all([
1437
+ this.publicClient.getBlock(),
1438
+ this.getCustomFee(creator),
1439
+ this.defaultGasFee(),
1440
+ tokenOk ? this.publicClient.readContract({
1441
+ address: params.token,
1442
+ abi: erc7984OperatorAbi,
1443
+ functionName: "isOperator",
1444
+ args: [creator, this.address]
1445
+ }).then((v) => ({ ok: true, value: v })).catch((err) => {
1446
+ if (isNotErc7984Failure(err)) return { ok: false, err };
1447
+ throw err;
1448
+ }) : Promise.resolve({ ok: true, value: false })
1449
+ ]);
1450
+ const isFactoryOperator = operatorRead.ok ? operatorRead.value : false;
1451
+ if (!operatorRead.ok) {
1452
+ pushBlocker(
1453
+ new InvalidArgumentError({
1454
+ method: "createConfidentialAirdrop",
1455
+ argument: "params.token",
1456
+ reason: "does not implement the ERC-7984 `isOperator(address,address)` view \u2014 it is not a confidential token (or the address holds no contract on this chain)",
1457
+ value: params.token
1458
+ })
1459
+ );
1460
+ }
1461
+ const gasFee = customFee.enabled ? customFee.gasFee : defaultFee;
1462
+ if (params.endTimestamp <= Number(block.timestamp)) {
1463
+ pushBlocker(
1464
+ new InvalidArgumentError({
1465
+ method: "createConfidentialAirdrop",
1466
+ argument: "params.endTimestamp",
1467
+ reason: "must be in the future (the clone's initialize reverts with EndTimeInPast)",
1468
+ value: params.endTimestamp
1469
+ })
1470
+ );
1471
+ }
1472
+ if (funding === true && tokenOk && operatorRead.ok && !isFactoryOperator) {
1473
+ pushBlocker(
1474
+ new OperatorNotApprovedError({
1475
+ method: "createAndFundConfidentialAirdrop",
1476
+ contractAddress: this.address,
1477
+ tokenAddress: params.token,
1478
+ holder: creator,
1479
+ spender: this.address
1480
+ })
1481
+ );
1482
+ }
1483
+ let predictedAirdrop;
1484
+ let alreadyDeployed;
1485
+ if (userSalt !== void 0 && tokenOk && adminOk) {
1486
+ predictedAirdrop = await this.#read("predictAirdropAddress", [
1487
+ toAbiParams(params),
1488
+ userSalt,
1489
+ creator,
1490
+ gasFee
1491
+ ]);
1492
+ const bytecode = await this.publicClient.getCode({ address: predictedAirdrop });
1493
+ alreadyDeployed = bytecode !== void 0 && bytecode !== "0x";
1494
+ if (alreadyDeployed) {
1495
+ pushBlocker(
1496
+ new AlreadyInitializedError({
1497
+ method: "createConfidentialAirdrop",
1498
+ contractAddress: predictedAirdrop
1499
+ })
1500
+ );
1501
+ }
1502
+ }
1503
+ return {
1504
+ isFactoryOperator,
1505
+ gasFee,
1506
+ predictedAirdrop,
1507
+ alreadyDeployed,
1508
+ ready: blockers.length === 0,
1509
+ blockers,
1510
+ blockerErrors
1511
+ };
1512
+ }
1332
1513
  // ----------------------- internals -----------------------
1333
1514
  /**
1334
1515
  * Wait for the receipt of a clone-deploy tx and parse the
@@ -1470,6 +1651,12 @@ var ConfidentialAirdropFactoryClient = class {
1470
1651
  function createConfidentialAirdropFactoryClient(config) {
1471
1652
  return new ConfidentialAirdropFactoryClient(config);
1472
1653
  }
1654
+ function isNotErc7984Failure(err) {
1655
+ if (isContractRevert(err)) return true;
1656
+ if (!(err instanceof BaseError)) return false;
1657
+ return err.walk((e) => e instanceof ContractFunctionZeroDataError) instanceof ContractFunctionZeroDataError;
1658
+ }
1659
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
1473
1660
  function accountAddress(account) {
1474
1661
  return typeof account === "string" ? account : account.address;
1475
1662
  }
@@ -1,29 +1,29 @@
1
1
  'use strict';
2
2
 
3
- var chunk56UI7LUR_cjs = require('./chunk-56UI7LUR.cjs');
3
+ var chunk2RNW4MIJ_cjs = require('./chunk-2RNW4MIJ.cjs');
4
4
 
5
5
  // src/core/zama-error-mapper.ts
6
6
  function mapZamaError(error, args) {
7
- if (error instanceof chunk56UI7LUR_cjs.TokenOpsSdkError) return error;
7
+ if (error instanceof chunk2RNW4MIJ_cjs.TokenOpsSdkError) return error;
8
8
  const zama = readZamaError(error);
9
9
  if (zama?.code) {
10
10
  switch (zama.code) {
11
11
  case "SIGNING_REJECTED":
12
- return new chunk56UI7LUR_cjs.UserRejectedSignatureError({ ...args, cause: error });
12
+ return new chunk2RNW4MIJ_cjs.UserRejectedSignatureError({ ...args, cause: error });
13
13
  case "SIGNING_FAILED":
14
- return new chunk56UI7LUR_cjs.SigningFailedError({ ...args, cause: error });
14
+ return new chunk2RNW4MIJ_cjs.SigningFailedError({ ...args, cause: error });
15
15
  case "RELAYER_REQUEST_FAILED":
16
- return new chunk56UI7LUR_cjs.RelayerUnreachableError({
16
+ return new chunk2RNW4MIJ_cjs.RelayerUnreachableError({
17
17
  ...args,
18
18
  statusCode: zama.statusCode,
19
19
  cause: error
20
20
  });
21
21
  case "ENCRYPTION_FAILED":
22
- return new chunk56UI7LUR_cjs.EncryptionFailedError({ ...args, cause: error });
22
+ return new chunk2RNW4MIJ_cjs.EncryptionFailedError({ ...args, cause: error });
23
23
  case "DECRYPTION_FAILED":
24
- return new chunk56UI7LUR_cjs.DecryptionFailedError({ ...args, cause: error });
24
+ return new chunk2RNW4MIJ_cjs.DecryptionFailedError({ ...args, cause: error });
25
25
  case "CONFIGURATION":
26
- return new chunk56UI7LUR_cjs.InvalidArgumentError({
26
+ return new chunk2RNW4MIJ_cjs.InvalidArgumentError({
27
27
  method: args.method,
28
28
  argument: "config",
29
29
  reason: "Zama SDK configuration is invalid (chain id, type, or signer state).",
@@ -34,13 +34,13 @@ function mapZamaError(error, args) {
34
34
  const message = readMessage(error);
35
35
  if (message) {
36
36
  if (USER_REJECTION_PATTERNS.some((pat) => pat.test(message))) {
37
- return new chunk56UI7LUR_cjs.UserRejectedSignatureError({ ...args, cause: error });
37
+ return new chunk2RNW4MIJ_cjs.UserRejectedSignatureError({ ...args, cause: error });
38
38
  }
39
39
  if (USER_DECRYPT_NOT_ALLOWED_PATTERNS.some((pat) => pat.test(message))) {
40
- return new chunk56UI7LUR_cjs.UserDecryptNotAllowedError({ method: args.method, cause: error });
40
+ return new chunk2RNW4MIJ_cjs.UserDecryptNotAllowedError({ method: args.method, cause: error });
41
41
  }
42
42
  if (INVALID_INPUT_PATTERNS.some((pat) => pat.test(message))) {
43
- return new chunk56UI7LUR_cjs.InvalidArgumentError({
43
+ return new chunk2RNW4MIJ_cjs.InvalidArgumentError({
44
44
  method: args.method,
45
45
  argument: "input",
46
46
  reason: "encrypted input value rejected by FHE SDK \u2014 see `error.cause` for details",
@@ -48,7 +48,7 @@ function mapZamaError(error, args) {
48
48
  });
49
49
  }
50
50
  }
51
- return args.operation === "encrypt" ? new chunk56UI7LUR_cjs.EncryptionFailedError({ ...args, cause: error }) : new chunk56UI7LUR_cjs.DecryptionFailedError({ ...args, cause: error });
51
+ return args.operation === "encrypt" ? new chunk2RNW4MIJ_cjs.EncryptionFailedError({ ...args, cause: error }) : new chunk2RNW4MIJ_cjs.DecryptionFailedError({ ...args, cause: error });
52
52
  }
53
53
  function readZamaError(err) {
54
54
  if (typeof err !== "object" || err === null) return void 0;
@@ -1,9 +1,8 @@
1
- import { SDK_VERSION, mapContractRevert, isContractRevert } from './chunk-JFLEEXKP.js';
2
- import { getFheVestingFactoryAddress } from './chunk-M7V2EDPB.js';
3
- import { normaliseAddress } from './chunk-BE2AIZ3K.js';
1
+ import { SDK_VERSION, mapContractRevert, isContractRevert } from './chunk-6WSNS3UV.js';
2
+ import { getFheVestingFactoryAddress } from './chunk-QKKBBH7I.js';
3
+ import { normaliseAddress } from './chunk-46T67CE2.js';
4
+ import { DeploymentAddressUnavailableError, TokenOpsSdkError, asTxHash, MissingWalletClientError, MissingAccountError } from './chunk-DRSPMIZ7.js';
4
5
  import { withTelemetry } from './chunk-Q2GP5UDC.js';
5
- import { asTxHash } from './chunk-KWFFIJYX.js';
6
- import { DeploymentAddressUnavailableError, TokenOpsSdkError, MissingWalletClientError, MissingAccountError } from './chunk-IVE3QEGD.js';
7
6
  import { parseEventLogs } from 'viem';
8
7
 
9
8
  // src/fhe-vesting/abis/factory.ts
@@ -1,7 +1,8 @@
1
- import { createConfidentialVestingManagerClient, resolveEncryptor } from './chunk-X56UVEXS.js';
2
- import { createConfidentialVestingFactoryClient } from './chunk-IR5AK5U5.js';
3
- import { getFheVestingFactoryAddress } from './chunk-M7V2EDPB.js';
4
- import { DeploymentAddressUnavailableError } from './chunk-IVE3QEGD.js';
1
+ import { createConfidentialVestingManagerClient } from './chunk-TN65XNTI.js';
2
+ import { resolveEncryptor } from './chunk-PD7ME2BT.js';
3
+ import { createConfidentialVestingFactoryClient } from './chunk-V5D7BHW3.js';
4
+ import { getFheVestingFactoryAddress } from './chunk-QKKBBH7I.js';
5
+ import { DeploymentAddressUnavailableError } from './chunk-DRSPMIZ7.js';
5
6
  import { useMemo, useRef, useEffect } from 'react';
6
7
  import { usePublicClient, useWalletClient } from 'wagmi';
7
8
 
@@ -1,17 +1,17 @@
1
1
  'use strict';
2
2
 
3
- var chunk56UI7LUR_cjs = require('./chunk-56UI7LUR.cjs');
3
+ var chunk2RNW4MIJ_cjs = require('./chunk-2RNW4MIJ.cjs');
4
4
  var viem = require('viem');
5
5
 
6
6
  function normaliseAddress(input) {
7
7
  if (typeof input !== "string") {
8
- throw new chunk56UI7LUR_cjs.TokenOpsValidationError("normaliseAddress: input is not a string", {
8
+ throw new chunk2RNW4MIJ_cjs.TokenOpsValidationError("normaliseAddress: input is not a string", {
9
9
  method: "normaliseAddress",
10
10
  args: { input: typeof input }
11
11
  });
12
12
  }
13
13
  if (!viem.isAddress(input, { strict: false })) {
14
- throw new chunk56UI7LUR_cjs.TokenOpsValidationError(
14
+ throw new chunk2RNW4MIJ_cjs.TokenOpsValidationError(
15
15
  `normaliseAddress: '${input}' is not a valid 0x-prefixed 20-byte hex address`,
16
16
  {
17
17
  method: "normaliseAddress",
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunk5SA2HF2W_cjs = require('./chunk-5SA2HF2W.cjs');
4
- var chunkSYHXDHWX_cjs = require('./chunk-SYHXDHWX.cjs');
5
- var chunk3ZRHDTEX_cjs = require('./chunk-3ZRHDTEX.cjs');
6
- var chunk56UI7LUR_cjs = require('./chunk-56UI7LUR.cjs');
3
+ var chunkSPGSO5SO_cjs = require('./chunk-SPGSO5SO.cjs');
4
+ var chunkLBWRFZR3_cjs = require('./chunk-LBWRFZR3.cjs');
5
+ var chunkWUXUWTFW_cjs = require('./chunk-WUXUWTFW.cjs');
6
+ var chunk2RNW4MIJ_cjs = require('./chunk-2RNW4MIJ.cjs');
7
7
  var react = require('react');
8
8
  var wagmi = require('wagmi');
9
9
 
@@ -12,7 +12,7 @@ var FHE_AIRDROP_NAMESPACE = "fhe-airdrop";
12
12
  function tryResolveFactoryAddress(override, chainId) {
13
13
  if (override) return override;
14
14
  if (chainId === void 0) return void 0;
15
- return chunk3ZRHDTEX_cjs.getFheAirdropFactoryAddress(chainId);
15
+ return chunkWUXUWTFW_cjs.getFheAirdropFactoryAddress(chainId);
16
16
  }
17
17
  function useMemoFactoryClient(opts = {}) {
18
18
  const publicClient = wagmi.usePublicClient({ chainId: opts.chainId });
@@ -25,14 +25,14 @@ function useMemoFactoryClient(opts = {}) {
25
25
  const client = react.useMemo(() => {
26
26
  if (!publicClient) return void 0;
27
27
  if (!resolvedAddress) return void 0;
28
- return chunkSYHXDHWX_cjs.createConfidentialAirdropFactoryClient({
28
+ return chunkLBWRFZR3_cjs.createConfidentialAirdropFactoryClient({
29
29
  publicClient,
30
30
  ...walletClient ? { walletClient } : {},
31
31
  address: resolvedAddress,
32
32
  ...chainId !== void 0 ? { chainId } : {},
33
33
  // Lazy — invoked per-encryption inside the headless client. Picks up
34
34
  // whichever EncryptorSource the consumer last passed in.
35
- encryptor: () => chunkSYHXDHWX_cjs.resolveEncryptor(encryptorSourceRef.current)
35
+ encryptor: () => chunkLBWRFZR3_cjs.resolveEncryptor(encryptorSourceRef.current)
36
36
  });
37
37
  }, [publicClient, walletClient, resolvedAddress, chainId]);
38
38
  return {
@@ -47,16 +47,16 @@ function useMemoFactoryClient(opts = {}) {
47
47
  function computeFactoryResolutionError(override, chainId) {
48
48
  if (override) return void 0;
49
49
  if (chainId === void 0) {
50
- return new chunk56UI7LUR_cjs.DeploymentAddressUnavailableError({
50
+ return new chunk2RNW4MIJ_cjs.DeploymentAddressUnavailableError({
51
51
  reason: "chain-id-missing",
52
52
  product: "fheAirdrop",
53
53
  contract: "confidentialAirdropFactory",
54
54
  clientLabel: "ConfidentialAirdropFactoryClient"
55
55
  });
56
56
  }
57
- const resolved = chunk3ZRHDTEX_cjs.getFheAirdropFactoryAddress(chainId);
57
+ const resolved = chunkWUXUWTFW_cjs.getFheAirdropFactoryAddress(chainId);
58
58
  if (!resolved) {
59
- return new chunk56UI7LUR_cjs.DeploymentAddressUnavailableError({
59
+ return new chunk2RNW4MIJ_cjs.DeploymentAddressUnavailableError({
60
60
  reason: "registry-not-deployed",
61
61
  product: "fheAirdrop",
62
62
  contract: "confidentialAirdropFactory",
@@ -73,7 +73,7 @@ function useMemoAirdropClient(opts) {
73
73
  const client = react.useMemo(() => {
74
74
  if (!publicClient) return void 0;
75
75
  if (!opts.address) return void 0;
76
- return chunk5SA2HF2W_cjs.createConfidentialAirdropClient({
76
+ return chunkSPGSO5SO_cjs.createConfidentialAirdropClient({
77
77
  publicClient,
78
78
  ...walletClient ? { walletClient } : {},
79
79
  address: opts.address,
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var chunkZQUE2B3Q_cjs = require('./chunk-ZQUE2B3Q.cjs');
4
+ var chunk4ZCXK4VI_cjs = require('./chunk-4ZCXK4VI.cjs');
5
+ var chunk2RNW4MIJ_cjs = require('./chunk-2RNW4MIJ.cjs');
6
+ var reactQuery = require('@tanstack/react-query');
7
+ var wagmi = require('wagmi');
8
+
9
+ function useIsOperator(options = {}) {
10
+ const publicClient = wagmi.usePublicClient({ chainId: options.chainId });
11
+ const { address: connected } = chunkZQUE2B3Q_cjs.useWagmiAccount();
12
+ const chainId = options.chainId ?? publicClient?.chain?.id;
13
+ const holder = options.holder ?? connected;
14
+ const { token, spender, telemetry } = options;
15
+ return reactQuery.useQuery({
16
+ queryKey: [
17
+ "tokenops-sdk",
18
+ "fhe",
19
+ "isOperator",
20
+ chainId ?? null,
21
+ token ? token.toLowerCase() : null,
22
+ holder ? holder.toLowerCase() : null,
23
+ spender ? spender.toLowerCase() : null
24
+ ],
25
+ queryFn: () => chunk4ZCXK4VI_cjs.isOperator({
26
+ publicClient,
27
+ token,
28
+ holder,
29
+ spender,
30
+ ...telemetry ? { telemetry } : {}
31
+ }),
32
+ enabled: !!publicClient && !!token && !!holder && !!spender && options.enabled !== false,
33
+ staleTime: 0
34
+ });
35
+ }
36
+ function useEnsureOperator(options = {}) {
37
+ const publicClient = wagmi.usePublicClient({ chainId: options.chainId });
38
+ const { data: walletClient } = wagmi.useWalletClient({ chainId: options.chainId });
39
+ const telemetry = options.telemetry;
40
+ return reactQuery.useMutation({
41
+ mutationFn: async (vars) => {
42
+ if (!publicClient) throw new chunk2RNW4MIJ_cjs.MissingPublicClientError("useEnsureOperator");
43
+ if (!walletClient) throw new chunk2RNW4MIJ_cjs.MissingWalletClientError("useEnsureOperator");
44
+ return chunk4ZCXK4VI_cjs.ensureOperator({
45
+ publicClient,
46
+ walletClient,
47
+ token: vars.token,
48
+ spender: vars.spender,
49
+ deadline: vars.deadline,
50
+ ...vars.account !== void 0 ? { account: vars.account } : {},
51
+ ...vars.waitForReceipt !== void 0 ? { waitForReceipt: vars.waitForReceipt } : {},
52
+ ...telemetry ? { telemetry } : {}
53
+ });
54
+ }
55
+ });
56
+ }
57
+
58
+ exports.useEnsureOperator = useEnsureOperator;
59
+ exports.useIsOperator = useIsOperator;
@@ -1,9 +1,8 @@
1
- import { SDK_VERSION, isContractRevert, mapContractRevert } from './chunk-JFLEEXKP.js';
2
- import { getConfidentialTestTokenAddress, getTestTokenAddress } from './chunk-M7V2EDPB.js';
3
- import { normaliseAddress } from './chunk-BE2AIZ3K.js';
1
+ import { SDK_VERSION, isContractRevert, mapContractRevert } from './chunk-6WSNS3UV.js';
2
+ import { getConfidentialTestTokenAddress, getTestTokenAddress } from './chunk-QKKBBH7I.js';
3
+ import { normaliseAddress } from './chunk-46T67CE2.js';
4
+ import { TokenOpsSdkError, UnsupportedChainError, DeploymentAddressUnavailableError, asEncryptedHandle, TokenOpsContractError, ReceiptEventNotFoundError, ReceiptEventAmbiguousError, asTxHash, MissingWalletClientError, MissingAccountError, InvalidArgumentError } from './chunk-DRSPMIZ7.js';
4
5
  import { withTelemetry } from './chunk-Q2GP5UDC.js';
5
- import { asEncryptedHandle, asTxHash } from './chunk-KWFFIJYX.js';
6
- import { TokenOpsSdkError, UnsupportedChainError, DeploymentAddressUnavailableError, TokenOpsContractError, ReceiptEventNotFoundError, ReceiptEventAmbiguousError, MissingWalletClientError, MissingAccountError, InvalidArgumentError } from './chunk-IVE3QEGD.js';
7
6
  import { sepolia } from 'viem/chains';
8
7
  import { parseEventLogs } from 'viem';
9
8
 
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunk56UI7LUR_cjs = require('./chunk-56UI7LUR.cjs');
3
+ var chunk2RNW4MIJ_cjs = require('./chunk-2RNW4MIJ.cjs');
4
4
  var chains = require('viem/chains');
5
5
 
6
6
  var DEPLOYED_ADDRESSES = {
7
7
  fheVesting: {
8
8
  confidentialVestingFactory: {
9
- [chains.sepolia.id]: "0xA87701CE9A52D43681600583a99c85b50DbE3150"
9
+ [chains.sepolia.id]: "0x059d6Bb8ff9a13E794fe416d4757d7310CdC69ab"
10
10
  // mainnet omitted — not deployed.
11
11
  }
12
12
  },
@@ -50,7 +50,7 @@ function requireDeployedAddress(product, contract, chainId) {
50
50
  const contractEntry = productEntry[contract];
51
51
  const entry = contractEntry?.[chainId];
52
52
  if (entry) return entry;
53
- throw new chunk56UI7LUR_cjs.DeploymentAddressUnavailableError({
53
+ throw new chunk2RNW4MIJ_cjs.DeploymentAddressUnavailableError({
54
54
  reason: entry === null ? "registry-not-deployed" : "registry-unknown-chain",
55
55
  product: String(product),
56
56
  contract: String(contract),