@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,12 +1,12 @@
1
- import { mapZamaError } from './chunk-ZXCOJY2Z.js';
2
- import { scaleRatio } from './chunk-XSNLAS5M.js';
3
- import { getFhevmAclAddress, requireFhevmAclAddress, ACL_ALLOWED_EVENT } from './chunk-FYQ2UW4T.js';
4
- import { SDK_VERSION, mapContractRevert, isContractRevert } from './chunk-JFLEEXKP.js';
5
- import { normaliseAddress } from './chunk-BE2AIZ3K.js';
1
+ import { mapZamaError } from './chunk-NFW7AUEX.js';
2
+ import { resolveEncryptor, encryptUint64Batch, scaleRatio, encryptUint64 } from './chunk-PD7ME2BT.js';
3
+ import { getFhevmAclAddress, requireFhevmAclAddress, ACL_ALLOWED_EVENT } from './chunk-YPYCWLYP.js';
4
+ import { erc7984OperatorAbi } from './chunk-7VELUOMI.js';
5
+ import { SDK_VERSION, mapContractRevert, isContractRevert } from './chunk-6WSNS3UV.js';
6
+ import { normaliseAddress } from './chunk-46T67CE2.js';
7
+ import { TokenOpsSdkError, PausedError, InsufficientFeeError, AccessDeniedError, InvalidArgumentError, OperatorNotApprovedError, MissingEncryptorError, ReceiptEventNotFoundError, ReceiptEventAmbiguousError, MissingWalletClientError, MissingAccountError, asEncryptedHandle, asTxHash } from './chunk-DRSPMIZ7.js';
6
8
  import { withTelemetry } from './chunk-Q2GP5UDC.js';
7
- import { asExternalInputProof, asEncryptedHandle, asTxHash } from './chunk-KWFFIJYX.js';
8
- import { InvalidArgumentError, TokenOpsSdkError, PausedError, InsufficientFeeError, MissingEncryptorError, ReceiptEventNotFoundError, ReceiptEventAmbiguousError, MissingWalletClientError, MissingAccountError } from './chunk-IVE3QEGD.js';
9
- import { bytesToHex, parseEventLogs, isAddress } from 'viem';
9
+ import { parseEventLogs, isAddress, BaseError, ContractFunctionZeroDataError } from 'viem';
10
10
 
11
11
  // src/fhe-vesting/abis/manager.ts
12
12
  var confidentialVestingManagerAbi = [
@@ -986,78 +986,6 @@ var confidentialVestingManagerAbi = [
986
986
  type: "function"
987
987
  }
988
988
  ];
989
- function resolveEncryptor(source) {
990
- if (source === void 0) return void 0;
991
- return typeof source === "function" ? source() : source;
992
- }
993
- var MAX_UINT64 = (1n << 64n) - 1n;
994
- function assertUint64(value, label) {
995
- if (value < 0n || value > MAX_UINT64) {
996
- throw new InvalidArgumentError({
997
- method: "encryptUint64",
998
- argument: label,
999
- reason: `does not fit in uint64 (0..2^64-1)`,
1000
- value
1001
- });
1002
- }
1003
- }
1004
- async function encryptUint64({
1005
- encryptor,
1006
- contractAddress,
1007
- userAddress,
1008
- value
1009
- }) {
1010
- assertUint64(value, "value");
1011
- const { handles, inputProof } = await encryptor.encrypt({
1012
- values: [{ value, type: "euint64" }],
1013
- contractAddress,
1014
- userAddress
1015
- });
1016
- if (handles.length !== 1) {
1017
- throw new InvalidArgumentError({
1018
- method: "encryptUint64",
1019
- argument: "handles",
1020
- reason: `expected 1 handle, got ${handles.length}`,
1021
- value: handles.length
1022
- });
1023
- }
1024
- return {
1025
- handle: asEncryptedHandle(bytesToHex(handles[0])),
1026
- inputProof: asExternalInputProof(bytesToHex(inputProof))
1027
- };
1028
- }
1029
- async function encryptUint64Batch({
1030
- encryptor,
1031
- contractAddress,
1032
- userAddress,
1033
- values
1034
- }) {
1035
- if (values.length === 0) {
1036
- throw new InvalidArgumentError({
1037
- method: "encryptUint64Batch",
1038
- argument: "values",
1039
- reason: "must be non-empty"
1040
- });
1041
- }
1042
- values.forEach((v, i) => assertUint64(v, `values[${i}]`));
1043
- const { handles, inputProof } = await encryptor.encrypt({
1044
- values: values.map((value) => ({ value, type: "euint64" })),
1045
- contractAddress,
1046
- userAddress
1047
- });
1048
- if (handles.length !== values.length) {
1049
- throw new InvalidArgumentError({
1050
- method: "encryptUint64Batch",
1051
- argument: "handles",
1052
- reason: `expected ${values.length} handles, got ${handles.length}`,
1053
- value: handles.length
1054
- });
1055
- }
1056
- return {
1057
- handles: handles.map((h) => asEncryptedHandle(bytesToHex(h))),
1058
- inputProof: asExternalInputProof(bytesToHex(inputProof))
1059
- };
1060
- }
1061
989
 
1062
990
  // src/fhe-vesting/errors.ts
1063
991
  var VestingNotFoundError = class extends TokenOpsSdkError {
@@ -1529,6 +1457,118 @@ var ConfidentialVestingManagerClient = class {
1529
1457
  }
1530
1458
  return { ready: blockers.length === 0, blockers };
1531
1459
  }
1460
+ /**
1461
+ * Read-only preflight for {@link createVesting} / {@link batchCreateVesting}.
1462
+ * Runs the deterministic-from-off-chain checks and reports blockers both as
1463
+ * human-readable strings (`blockers`) and as typed {@link TokenOpsSdkError}s
1464
+ * (`blockerErrors`), index-aligned.
1465
+ *
1466
+ * Preflight is **opt-in**. Consumers who have already validated state can
1467
+ * skip this call and invoke the write directly — they'll receive the same
1468
+ * typed errors at write time via the revert mapper.
1469
+ *
1470
+ * Report fields: `token`, `hasCreatorRole`, `isOperatorSet`, `ready`,
1471
+ * `blockers`, `blockerErrors` — see {@link CreateVestingPreflightReport} for
1472
+ * the meaning of each.
1473
+ *
1474
+ * Checks performed (all read-only, no gas):
1475
+ * - Structural `params` validation mirroring the contract's
1476
+ * `_validateVestingParams` (`InvalidArgumentError` blockers): recipient is
1477
+ * a checksummed non-zero address, `startTimestamp < endTimestamp`, cliff
1478
+ * within the window, `initialUnlockBps + cliffAmountBps ≤ 10000`.
1479
+ * - Role: creator holds `VESTING_CREATOR_ROLE`
1480
+ * ({@link AccessDeniedError} blocker).
1481
+ * - Operator: creator has approved this manager as an ERC-7984 operator on
1482
+ * the distribution token, required for the manager's
1483
+ * `confidentialTransferFrom` pull ({@link OperatorNotApprovedError} blocker).
1484
+ * If the bound `token` does not implement the ERC-7984 `isOperator`
1485
+ * view — a revert, or a zero-data response for an EOA / undeployed
1486
+ * address — operator status is undetermined rather than the call
1487
+ * throwing: `isOperatorSet` reports `false` and the read failure becomes
1488
+ * an {@link InvalidArgumentError} blocker on `token` instead (TOK-436).
1489
+ *
1490
+ * **Not preflight-detectable — read before trusting `ready: true`:**
1491
+ * - The creator's confidential token balance is an encrypted `euint64` the
1492
+ * SDK cannot read in plaintext. An underfunded create does **not** revert:
1493
+ * the contract's all-or-nothing `FHE.select` pattern silently zeroes the
1494
+ * vesting amounts instead. Confirm the creator's balance covers the total
1495
+ * before submitting.
1496
+ * - `batchCreateVesting` additionally enforces `items.length ≤ maxBatchSize()`
1497
+ * on-chain; check {@link maxBatchSize} for batches.
1498
+ *
1499
+ * Pausing the manager does NOT block vesting creation (only claims), so
1500
+ * paused state is intentionally not a blocker here.
1501
+ *
1502
+ * @param args.params The vesting schedule parameters to validate.
1503
+ * @param args.creator The address that will send the create transaction.
1504
+ * @returns A {@link CreateVestingPreflightReport}.
1505
+ */
1506
+ async preflightCreateVesting(args) {
1507
+ const blockers = [];
1508
+ const blockerErrors = [];
1509
+ const pushBlocker = (err) => {
1510
+ blockerErrors.push(err);
1511
+ blockers.push(err.message);
1512
+ };
1513
+ for (const err of collectVestingParamsErrors(args.params, "createVesting")) {
1514
+ pushBlocker(err);
1515
+ }
1516
+ const [token, creatorRole] = await Promise.all([
1517
+ this.token(),
1518
+ this.#read("VESTING_CREATOR_ROLE")
1519
+ ]);
1520
+ const [hasCreatorRole, operatorRead] = await Promise.all([
1521
+ this.hasRole(creatorRole, args.creator),
1522
+ this.publicClient.readContract({
1523
+ address: token,
1524
+ abi: erc7984OperatorAbi,
1525
+ functionName: "isOperator",
1526
+ args: [args.creator, this.address]
1527
+ }).then((v) => ({ ok: true, value: v })).catch((err) => {
1528
+ if (isNotErc7984Failure(err)) return { ok: false, err };
1529
+ throw err;
1530
+ })
1531
+ ]);
1532
+ const isOperatorSet = operatorRead.ok ? operatorRead.value : false;
1533
+ if (!hasCreatorRole) {
1534
+ pushBlocker(
1535
+ new AccessDeniedError({
1536
+ method: "createVesting",
1537
+ contractAddress: this.address,
1538
+ account: args.creator,
1539
+ role: creatorRole
1540
+ })
1541
+ );
1542
+ }
1543
+ if (!operatorRead.ok) {
1544
+ pushBlocker(
1545
+ new InvalidArgumentError({
1546
+ method: "createVesting",
1547
+ argument: "token",
1548
+ 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)",
1549
+ value: token
1550
+ })
1551
+ );
1552
+ } else if (!isOperatorSet) {
1553
+ pushBlocker(
1554
+ new OperatorNotApprovedError({
1555
+ method: "createVesting",
1556
+ contractAddress: this.address,
1557
+ tokenAddress: token,
1558
+ holder: args.creator,
1559
+ spender: this.address
1560
+ })
1561
+ );
1562
+ }
1563
+ return {
1564
+ token,
1565
+ hasCreatorRole,
1566
+ isOperatorSet,
1567
+ ready: blockers.length === 0,
1568
+ blockers,
1569
+ blockerErrors
1570
+ };
1571
+ }
1532
1572
  // ============================================================
1533
1573
  // ENCRYPTED VIEWS (TX)
1534
1574
  // ============================================================
@@ -1594,6 +1634,21 @@ var ConfidentialVestingManagerClient = class {
1594
1634
  *
1595
1635
  * Pass `encryptedInput` to bypass the encryptor when you manage encryption yourself.
1596
1636
  *
1637
+ * **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.
1638
+ *
1639
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1640
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1641
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1642
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1643
+ * transparent TTT test token uses 18 decimals.
1644
+ *
1645
+ * Prerequisites: caller must have set this manager as an operator on the
1646
+ * token: `token.setOperator(managerAddress, deadline)` — or use
1647
+ * `ensureOperator()` from `@tokenops/sdk/fhe`. Skipping it fails with
1648
+ * {@link OperatorNotApprovedError} (the SDK's mapping of the on-chain
1649
+ * `ERC7984UnauthorizedSpender` revert, whose message is the canonical
1650
+ * `OPERATOR_NOT_APPROVED_REMEDIATION` copy).
1651
+ *
1597
1652
  * @returns Transaction hash. Parse the `VestingCreated` event to extract the `vestingId`.
1598
1653
  * @example
1599
1654
  * const hash = await manager.createVesting({
@@ -1635,6 +1690,21 @@ var ConfidentialVestingManagerClient = class {
1635
1690
  *
1636
1691
  * Respects `maxBatchSize` — check before calling on large lists.
1637
1692
  *
1693
+ * **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.
1694
+ *
1695
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1696
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1697
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1698
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1699
+ * transparent TTT test token uses 18 decimals.
1700
+ *
1701
+ * Prerequisites: caller must have set this manager as an operator on the
1702
+ * token: `token.setOperator(managerAddress, deadline)` — or use
1703
+ * `ensureOperator()` from `@tokenops/sdk/fhe`. Skipping it fails with
1704
+ * {@link OperatorNotApprovedError} (the SDK's mapping of the on-chain
1705
+ * `ERC7984UnauthorizedSpender` revert, whose message is the canonical
1706
+ * `OPERATOR_NOT_APPROVED_REMEDIATION` copy).
1707
+ *
1638
1708
  * @returns Transaction hash.
1639
1709
  */
1640
1710
  async batchCreateVesting(args) {
@@ -1685,6 +1755,9 @@ var ConfidentialVestingManagerClient = class {
1685
1755
  /**
1686
1756
  * Claim all currently vested tokens for `vestingId`.
1687
1757
  * For `FeeType.Gas` managers, pass `value` (gas fee in wei from `getFeeInfo()`).
1758
+ *
1759
+ * **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.
1760
+ *
1688
1761
  * @param args Discriminated by `feeType`: pass `{ feeType, vestingId, value }` for Gas, `{ feeType, vestingId }` for DistributionToken.
1689
1762
  * @returns Transaction hash.
1690
1763
  * @example
@@ -1713,6 +1786,9 @@ var ConfidentialVestingManagerClient = class {
1713
1786
  /**
1714
1787
  * Admin variant of `claim` — callable by the manager admin on behalf of any recipient.
1715
1788
  * Useful for gas-sponsored claim flows. Same fee rules as `claim`.
1789
+ *
1790
+ * **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.
1791
+ *
1716
1792
  * @param args Same discriminated union as `claim`.
1717
1793
  * @returns Transaction hash.
1718
1794
  */
@@ -1741,6 +1817,15 @@ var ConfidentialVestingManagerClient = class {
1741
1817
  /**
1742
1818
  * Claim a specific encrypted amount from a vesting schedule rather than the full claimable balance.
1743
1819
  * The SDK encrypts `amount` — pass plaintext. Alternatively pass `encryptedInput` to bypass encryption.
1820
+ *
1821
+ * **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.
1822
+ *
1823
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1824
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1825
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1826
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1827
+ * transparent TTT test token uses 18 decimals.
1828
+ *
1744
1829
  * @param args Includes `vestingId`, `amount` or `encryptedInput`, and optional `value` for Gas-fee managers.
1745
1830
  * @returns Transaction hash.
1746
1831
  */
@@ -1775,6 +1860,15 @@ var ConfidentialVestingManagerClient = class {
1775
1860
  }
1776
1861
  /**
1777
1862
  * Admin variant of `partialClaim` — callable by the manager admin on behalf of any recipient.
1863
+ *
1864
+ * **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.
1865
+ *
1866
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
1867
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
1868
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
1869
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
1870
+ * transparent TTT test token uses 18 decimals.
1871
+ *
1778
1872
  * @param args Same as `partialClaim`.
1779
1873
  * @returns Transaction hash.
1780
1874
  */
@@ -2164,6 +2258,13 @@ var ConfidentialVestingManagerClient = class {
2164
2258
  /**
2165
2259
  * Withdraw a confidential token amount from the manager's balance back to the admin.
2166
2260
  * The SDK encrypts `amount` — pass plaintext. Alternatively pass `encryptedInput`.
2261
+ *
2262
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
2263
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
2264
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
2265
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
2266
+ * transparent TTT test token uses 18 decimals.
2267
+ *
2167
2268
  * @param args `{ amount }` (plaintext, SDK encrypts) or `{ encryptedInput }` (pre-encrypted).
2168
2269
  * @returns Transaction hash.
2169
2270
  */
@@ -2220,6 +2321,13 @@ var ConfidentialVestingManagerClient = class {
2220
2321
  /**
2221
2322
  * Withdraw accumulated token fees from a `FeeType.DistributionToken` manager. Admin only.
2222
2323
  * The SDK encrypts `amount` — pass plaintext. Alternatively pass `encryptedInput`.
2324
+ *
2325
+ * **Amount units:** TokenOps confidential (ERC-7984) tokens use a 6-decimals
2326
+ * convention (1 token = 1_000_000 base units), not the 18 decimals typical of
2327
+ * ERC-20. Amount parameters are base units of the token's actual decimals:
2328
+ * for the CTTT test token (6 decimals) `1_000_000n` = 1 CTTT, while the
2329
+ * transparent TTT test token uses 18 decimals.
2330
+ *
2223
2331
  * @param args `{ to, amount }` (plaintext, SDK encrypts) or `{ to, encryptedInput }` (pre-encrypted).
2224
2332
  * @returns Transaction hash.
2225
2333
  */
@@ -2633,45 +2741,8 @@ var ConfidentialVestingManagerClient = class {
2633
2741
  * than wait for the on-chain revert.
2634
2742
  */
2635
2743
  #validateVestingParams(params, where) {
2636
- if (!isAddress(params.recipient, { strict: true })) {
2637
- throw new InvalidArgumentError({
2638
- method: where,
2639
- argument: "recipient",
2640
- reason: "must be a valid EIP-55 checksummed address",
2641
- value: params.recipient
2642
- });
2643
- }
2644
- if (params.recipient === ZERO_ADDRESS) {
2645
- throw new InvalidArgumentError({
2646
- method: where,
2647
- argument: "recipient",
2648
- reason: "must not be the zero address"
2649
- });
2650
- }
2651
- if (params.startTimestamp >= params.endTimestamp) {
2652
- throw new InvalidArgumentError({
2653
- method: where,
2654
- argument: "startTimestamp/endTimestamp",
2655
- reason: "startTimestamp must be strictly less than endTimestamp",
2656
- value: { startTimestamp: params.startTimestamp, endTimestamp: params.endTimestamp }
2657
- });
2658
- }
2659
- if (params.startTimestamp + params.cliffSeconds > params.endTimestamp) {
2660
- throw new InvalidArgumentError({
2661
- method: where,
2662
- argument: "cliffSeconds",
2663
- reason: "cliff cannot extend past endTimestamp",
2664
- value: params.cliffSeconds
2665
- });
2666
- }
2667
- if (params.initialUnlockBps + params.cliffAmountBps > 1e4) {
2668
- throw new InvalidArgumentError({
2669
- method: where,
2670
- argument: "initialUnlockBps + cliffAmountBps",
2671
- reason: "must be \u2264 10000 (100%)",
2672
- value: { initialUnlockBps: params.initialUnlockBps, cliffAmountBps: params.cliffAmountBps }
2673
- });
2674
- }
2744
+ const [first] = collectVestingParamsErrors(params, where);
2745
+ if (first) throw first;
2675
2746
  }
2676
2747
  async #read(functionName, args = []) {
2677
2748
  const result = await this.publicClient.readContract({
@@ -2746,9 +2817,66 @@ var ConfidentialVestingManagerClient = class {
2746
2817
  function createConfidentialVestingManagerClient(config) {
2747
2818
  return new ConfidentialVestingManagerClient(config);
2748
2819
  }
2820
+ function isNotErc7984Failure(err) {
2821
+ if (isContractRevert(err)) return true;
2822
+ if (!(err instanceof BaseError)) return false;
2823
+ return err.walk((e) => e instanceof ContractFunctionZeroDataError) instanceof ContractFunctionZeroDataError;
2824
+ }
2749
2825
  function accountAddress(account) {
2750
2826
  return typeof account === "string" ? account : account.address;
2751
2827
  }
2752
2828
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2829
+ function collectVestingParamsErrors(params, where) {
2830
+ const errors = [];
2831
+ if (!isAddress(params.recipient, { strict: true })) {
2832
+ errors.push(
2833
+ new InvalidArgumentError({
2834
+ method: where,
2835
+ argument: "recipient",
2836
+ reason: "must be a valid EIP-55 checksummed address",
2837
+ value: params.recipient
2838
+ })
2839
+ );
2840
+ } else if (params.recipient === ZERO_ADDRESS) {
2841
+ errors.push(
2842
+ new InvalidArgumentError({
2843
+ method: where,
2844
+ argument: "recipient",
2845
+ reason: "must not be the zero address"
2846
+ })
2847
+ );
2848
+ }
2849
+ if (params.startTimestamp >= params.endTimestamp) {
2850
+ errors.push(
2851
+ new InvalidArgumentError({
2852
+ method: where,
2853
+ argument: "startTimestamp/endTimestamp",
2854
+ reason: "startTimestamp must be strictly less than endTimestamp",
2855
+ value: { startTimestamp: params.startTimestamp, endTimestamp: params.endTimestamp }
2856
+ })
2857
+ );
2858
+ }
2859
+ if (params.startTimestamp < params.endTimestamp && params.startTimestamp + params.cliffSeconds > params.endTimestamp) {
2860
+ errors.push(
2861
+ new InvalidArgumentError({
2862
+ method: where,
2863
+ argument: "cliffSeconds",
2864
+ reason: "cliff cannot extend past endTimestamp",
2865
+ value: params.cliffSeconds
2866
+ })
2867
+ );
2868
+ }
2869
+ if (params.initialUnlockBps + params.cliffAmountBps > 1e4) {
2870
+ errors.push(
2871
+ new InvalidArgumentError({
2872
+ method: where,
2873
+ argument: "initialUnlockBps + cliffAmountBps",
2874
+ reason: "must be \u2264 10000 (100%)",
2875
+ value: { initialUnlockBps: params.initialUnlockBps, cliffAmountBps: params.cliffAmountBps }
2876
+ })
2877
+ );
2878
+ }
2879
+ return errors;
2880
+ }
2753
2881
 
2754
- export { ClaimLockedError, ConfidentialVestingManagerClient, NoPendingTransferError, NotPendingRecipientError, NotVestingRecipientError, TransferAlreadyPendingError, TransferExpiredError, VestingExpiredError, VestingNotFoundError, VestingNotRevocableError, VestingRevokedError, confidentialVestingManagerAbi, createConfidentialVestingManagerClient, encryptUint64, encryptUint64Batch, resolveEncryptor };
2882
+ export { ClaimLockedError, ConfidentialVestingManagerClient, NoPendingTransferError, NotPendingRecipientError, NotVestingRecipientError, TransferAlreadyPendingError, TransferExpiredError, VestingExpiredError, VestingNotFoundError, VestingNotRevocableError, VestingRevokedError, confidentialVestingManagerAbi, createConfidentialVestingManagerClient };
@@ -0,0 +1,56 @@
1
+ import { useWagmiAccount } from './chunk-FT4LNBOS.js';
2
+ import { isOperator, ensureOperator } from './chunk-4KJ66YRH.js';
3
+ import { MissingPublicClientError, MissingWalletClientError } from './chunk-DRSPMIZ7.js';
4
+ import { useQuery, useMutation } from '@tanstack/react-query';
5
+ import { usePublicClient, useWalletClient } from 'wagmi';
6
+
7
+ function useIsOperator(options = {}) {
8
+ const publicClient = usePublicClient({ chainId: options.chainId });
9
+ const { address: connected } = useWagmiAccount();
10
+ const chainId = options.chainId ?? publicClient?.chain?.id;
11
+ const holder = options.holder ?? connected;
12
+ const { token, spender, telemetry } = options;
13
+ return useQuery({
14
+ queryKey: [
15
+ "tokenops-sdk",
16
+ "fhe",
17
+ "isOperator",
18
+ chainId ?? null,
19
+ token ? token.toLowerCase() : null,
20
+ holder ? holder.toLowerCase() : null,
21
+ spender ? spender.toLowerCase() : null
22
+ ],
23
+ queryFn: () => isOperator({
24
+ publicClient,
25
+ token,
26
+ holder,
27
+ spender,
28
+ ...telemetry ? { telemetry } : {}
29
+ }),
30
+ enabled: !!publicClient && !!token && !!holder && !!spender && options.enabled !== false,
31
+ staleTime: 0
32
+ });
33
+ }
34
+ function useEnsureOperator(options = {}) {
35
+ const publicClient = usePublicClient({ chainId: options.chainId });
36
+ const { data: walletClient } = useWalletClient({ chainId: options.chainId });
37
+ const telemetry = options.telemetry;
38
+ return useMutation({
39
+ mutationFn: async (vars) => {
40
+ if (!publicClient) throw new MissingPublicClientError("useEnsureOperator");
41
+ if (!walletClient) throw new MissingWalletClientError("useEnsureOperator");
42
+ return ensureOperator({
43
+ publicClient,
44
+ walletClient,
45
+ token: vars.token,
46
+ spender: vars.spender,
47
+ deadline: vars.deadline,
48
+ ...vars.account !== void 0 ? { account: vars.account } : {},
49
+ ...vars.waitForReceipt !== void 0 ? { waitForReceipt: vars.waitForReceipt } : {},
50
+ ...telemetry ? { telemetry } : {}
51
+ });
52
+ }
53
+ });
54
+ }
55
+
56
+ export { useEnsureOperator, useIsOperator };