@cofhe/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -0
- package/dist/index.cjs +619 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +859 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +106 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.js +576 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +859 -0
- package/dist/styles.css.map +1 -0
- package/dist/styles.d.cts +2 -0
- package/dist/styles.d.ts +2 -0
- package/package.json +52 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
// src/providers/CofheProvider.tsx
|
|
2
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var CofheContext = createContext(void 0);
|
|
5
|
+
function CofheProvider({ children, client: providedClient, config }) {
|
|
6
|
+
const [client, setClient] = useState(providedClient || null);
|
|
7
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (providedClient) {
|
|
11
|
+
setClient(providedClient);
|
|
12
|
+
setIsInitialized(true);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (config) {
|
|
16
|
+
try {
|
|
17
|
+
setIsInitialized(true);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
setError(err instanceof Error ? err : new Error("Failed to initialize CoFHE client"));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}, [providedClient, config]);
|
|
23
|
+
const contextValue = {
|
|
24
|
+
client,
|
|
25
|
+
isInitialized,
|
|
26
|
+
error
|
|
27
|
+
};
|
|
28
|
+
return /* @__PURE__ */ jsx(CofheContext.Provider, { value: contextValue, children });
|
|
29
|
+
}
|
|
30
|
+
function useCofheContext() {
|
|
31
|
+
const context = useContext(CofheContext);
|
|
32
|
+
if (context === void 0) {
|
|
33
|
+
throw new Error("useCofheContext must be used within a CofheProvider");
|
|
34
|
+
}
|
|
35
|
+
return context;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/hooks/useEncryptInput.ts
|
|
39
|
+
import { useState as useState2, useCallback } from "react";
|
|
40
|
+
import { Encryptable } from "@cofhe/sdk";
|
|
41
|
+
var STEP_CONFIG = {
|
|
42
|
+
"initTfhe": {
|
|
43
|
+
label: "Initializing TFHE...",
|
|
44
|
+
progress: 5
|
|
45
|
+
},
|
|
46
|
+
"fetchKeys": {
|
|
47
|
+
label: "Fetching FHE keys...",
|
|
48
|
+
progress: 20
|
|
49
|
+
},
|
|
50
|
+
"pack": {
|
|
51
|
+
label: "Packing data...",
|
|
52
|
+
progress: 40
|
|
53
|
+
},
|
|
54
|
+
"prove": {
|
|
55
|
+
label: "Generating proof...",
|
|
56
|
+
progress: 70
|
|
57
|
+
},
|
|
58
|
+
"verify": {
|
|
59
|
+
label: "Verifying...",
|
|
60
|
+
progress: 90
|
|
61
|
+
},
|
|
62
|
+
"done": {
|
|
63
|
+
label: "Encryption complete!",
|
|
64
|
+
progress: 100
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
function useEncryptInput() {
|
|
68
|
+
const { client } = useCofheContext();
|
|
69
|
+
const [isEncrypting, setIsEncrypting] = useState2(false);
|
|
70
|
+
const [error, setError] = useState2(null);
|
|
71
|
+
const [encryptionStep, setEncryptionStep] = useState2(null);
|
|
72
|
+
const [encryptionProgress, setEncryptionProgress] = useState2(0);
|
|
73
|
+
const [encryptionProgressLabel, setEncryptionProgressLabel] = useState2("");
|
|
74
|
+
const onEncryptInput = useCallback(async (type, value) => {
|
|
75
|
+
if (!client) {
|
|
76
|
+
throw new Error("CoFHE client not initialized");
|
|
77
|
+
}
|
|
78
|
+
setIsEncrypting(true);
|
|
79
|
+
setError(null);
|
|
80
|
+
try {
|
|
81
|
+
let convertedValue;
|
|
82
|
+
if (type === "bool") {
|
|
83
|
+
convertedValue = value.toLowerCase() === "true" || value === "1";
|
|
84
|
+
} else if (type === "address") {
|
|
85
|
+
convertedValue = value;
|
|
86
|
+
} else {
|
|
87
|
+
convertedValue = value.includes(".") ? parseFloat(value) : parseInt(value, 10);
|
|
88
|
+
}
|
|
89
|
+
let encryptableItem;
|
|
90
|
+
switch (type) {
|
|
91
|
+
case "bool":
|
|
92
|
+
encryptableItem = Encryptable.bool(convertedValue);
|
|
93
|
+
break;
|
|
94
|
+
case "uint8":
|
|
95
|
+
encryptableItem = Encryptable.uint8(BigInt(convertedValue));
|
|
96
|
+
break;
|
|
97
|
+
case "uint16":
|
|
98
|
+
encryptableItem = Encryptable.uint16(BigInt(convertedValue));
|
|
99
|
+
break;
|
|
100
|
+
case "uint32":
|
|
101
|
+
encryptableItem = Encryptable.uint32(BigInt(convertedValue));
|
|
102
|
+
break;
|
|
103
|
+
case "uint64":
|
|
104
|
+
encryptableItem = Encryptable.uint64(BigInt(convertedValue));
|
|
105
|
+
break;
|
|
106
|
+
case "uint128":
|
|
107
|
+
encryptableItem = Encryptable.uint128(BigInt(convertedValue));
|
|
108
|
+
break;
|
|
109
|
+
case "address":
|
|
110
|
+
encryptableItem = Encryptable.address(convertedValue);
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
encryptableItem = Encryptable.uint32(BigInt(convertedValue));
|
|
114
|
+
}
|
|
115
|
+
const encryptionBuilder = client.encryptInputs([encryptableItem]).setStepCallback((step, context) => {
|
|
116
|
+
const stepConfig = STEP_CONFIG[step];
|
|
117
|
+
if (stepConfig) {
|
|
118
|
+
setEncryptionStep(step);
|
|
119
|
+
setEncryptionProgress(stepConfig.progress);
|
|
120
|
+
setEncryptionProgressLabel(stepConfig.label);
|
|
121
|
+
}
|
|
122
|
+
if (step === "prove" && context?.isEnd) {
|
|
123
|
+
console.log("[Encryption] Worker Status:", {
|
|
124
|
+
useWorker: context.useWorker,
|
|
125
|
+
usedWorker: context.usedWorker,
|
|
126
|
+
workerFailedError: context.workerFailedError,
|
|
127
|
+
duration: context.duration + "ms"
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
const result = await encryptionBuilder.encrypt();
|
|
132
|
+
if (!result.success) {
|
|
133
|
+
throw result.error;
|
|
134
|
+
}
|
|
135
|
+
setEncryptionStep("done");
|
|
136
|
+
setEncryptionProgress(100);
|
|
137
|
+
setEncryptionProgressLabel("Encryption complete!");
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
setEncryptionStep(null);
|
|
140
|
+
setEncryptionProgress(0);
|
|
141
|
+
setEncryptionProgressLabel("");
|
|
142
|
+
}, 1e3);
|
|
143
|
+
setIsEncrypting(false);
|
|
144
|
+
return result.data[0];
|
|
145
|
+
} catch (err) {
|
|
146
|
+
setEncryptionStep(null);
|
|
147
|
+
setEncryptionProgress(0);
|
|
148
|
+
setEncryptionProgressLabel("");
|
|
149
|
+
setIsEncrypting(false);
|
|
150
|
+
const error2 = err instanceof Error ? err : new Error("Encryption failed");
|
|
151
|
+
setError(error2);
|
|
152
|
+
throw error2;
|
|
153
|
+
}
|
|
154
|
+
}, [client]);
|
|
155
|
+
return {
|
|
156
|
+
onEncryptInput,
|
|
157
|
+
isEncryptingInput: isEncrypting,
|
|
158
|
+
encryptionStep,
|
|
159
|
+
encryptionProgress,
|
|
160
|
+
encryptionProgressLabel,
|
|
161
|
+
inputEncryptionDisabled: isEncrypting || !!error
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/components/FnxEncryptInput.tsx
|
|
166
|
+
import { useState as useState3, useRef, useEffect as useEffect2 } from "react";
|
|
167
|
+
|
|
168
|
+
// src/utils/cn.ts
|
|
169
|
+
var cn = (...classes) => {
|
|
170
|
+
return classes.filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/utils/debounce.ts
|
|
174
|
+
var debounce = (func, wait) => {
|
|
175
|
+
let timeoutId = null;
|
|
176
|
+
return (...args) => {
|
|
177
|
+
if (timeoutId !== null) {
|
|
178
|
+
clearTimeout(timeoutId);
|
|
179
|
+
}
|
|
180
|
+
timeoutId = setTimeout(() => {
|
|
181
|
+
func(...args);
|
|
182
|
+
}, wait);
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/utils/utils.ts
|
|
187
|
+
var FheTypesList = [
|
|
188
|
+
{
|
|
189
|
+
label: "Encrypted Bool",
|
|
190
|
+
value: "bool",
|
|
191
|
+
maxValue: BigInt(1),
|
|
192
|
+
// 0 or 1
|
|
193
|
+
description: "Boolean value (true/false)"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
label: "Encrypted Uint8",
|
|
197
|
+
value: "uint8",
|
|
198
|
+
maxValue: BigInt(2 ** 8 - 1),
|
|
199
|
+
// 255
|
|
200
|
+
description: "8-bit unsigned integer (0 to 255)"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
label: "Encrypted Uint16",
|
|
204
|
+
value: "uint16",
|
|
205
|
+
maxValue: BigInt(2 ** 16 - 1),
|
|
206
|
+
// 65,535
|
|
207
|
+
description: "16-bit unsigned integer (0 to 65,535)"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
label: "Encrypted Uint32",
|
|
211
|
+
value: "uint32",
|
|
212
|
+
maxValue: BigInt(2 ** 32 - 1),
|
|
213
|
+
// 4,294,967,295
|
|
214
|
+
description: "32-bit unsigned integer (0 to 4,294,967,295)"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
label: "Encrypted Uint64",
|
|
218
|
+
value: "uint64",
|
|
219
|
+
maxValue: BigInt(2 ** 64 - 1),
|
|
220
|
+
// 18,446,744,073,709,551,615
|
|
221
|
+
description: "64-bit unsigned integer (0 to 18,446,744,073,709,551,615)"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
label: "Encrypted Uint128",
|
|
225
|
+
value: "uint128",
|
|
226
|
+
maxValue: BigInt(2 ** 128 - 1),
|
|
227
|
+
// Very large number
|
|
228
|
+
description: "128-bit unsigned integer"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
label: "Encrypted Address",
|
|
232
|
+
value: "address",
|
|
233
|
+
maxValue: null,
|
|
234
|
+
// Address validation is different
|
|
235
|
+
description: "Ethereum address (0x...)"
|
|
236
|
+
}
|
|
237
|
+
];
|
|
238
|
+
|
|
239
|
+
// src/components/FnxEncryptInput.tsx
|
|
240
|
+
import SecurityIcon from "@mui/icons-material/Security";
|
|
241
|
+
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
|
242
|
+
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
243
|
+
import CheckIcon from "@mui/icons-material/Check";
|
|
244
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
245
|
+
var FnxEncryptInput = ({
|
|
246
|
+
className,
|
|
247
|
+
testId,
|
|
248
|
+
placeholder = "Enter number or address...",
|
|
249
|
+
initialValue = "",
|
|
250
|
+
options = FheTypesList,
|
|
251
|
+
size = "md",
|
|
252
|
+
hasError = false,
|
|
253
|
+
errorMessage,
|
|
254
|
+
disabled = false,
|
|
255
|
+
showProgressBar = false,
|
|
256
|
+
debounceMs = 300,
|
|
257
|
+
onTextChange,
|
|
258
|
+
onTypeChange,
|
|
259
|
+
onEncryptStart,
|
|
260
|
+
onEncryptProgress,
|
|
261
|
+
onEncryptComplete,
|
|
262
|
+
onEncryptError
|
|
263
|
+
}) => {
|
|
264
|
+
const [textValue, setTextValue] = useState3(initialValue);
|
|
265
|
+
const [selectedType, setSelectedType] = useState3(options[0]?.value || "uint32");
|
|
266
|
+
const [isDropdownOpen, setIsDropdownOpen] = useState3(false);
|
|
267
|
+
const [showProgress, setShowProgress] = useState3(false);
|
|
268
|
+
const [encryptedResult, setEncryptedResult] = useState3(null);
|
|
269
|
+
const [copySuccess, setCopySuccess] = useState3(false);
|
|
270
|
+
const dropdownRef = useRef(null);
|
|
271
|
+
const { onEncryptInput, isEncryptingInput, encryptionStep, encryptionProgress, encryptionProgressLabel } = useEncryptInput();
|
|
272
|
+
const debouncedValidation = useRef(
|
|
273
|
+
debounce((value) => {
|
|
274
|
+
console.log("Debounced validation for:", value);
|
|
275
|
+
}, debounceMs)
|
|
276
|
+
).current;
|
|
277
|
+
useEffect2(() => {
|
|
278
|
+
if (showProgressBar && isEncryptingInput) {
|
|
279
|
+
setShowProgress(true);
|
|
280
|
+
} else if (!isEncryptingInput) {
|
|
281
|
+
const timer = setTimeout(() => setShowProgress(false), 500);
|
|
282
|
+
return () => clearTimeout(timer);
|
|
283
|
+
}
|
|
284
|
+
}, [showProgressBar, isEncryptingInput]);
|
|
285
|
+
useEffect2(() => {
|
|
286
|
+
if (isEncryptingInput && encryptionStep && encryptionProgress !== null && encryptionProgressLabel) {
|
|
287
|
+
onEncryptProgress?.({
|
|
288
|
+
step: encryptionStep.toString(),
|
|
289
|
+
progress: encryptionProgress,
|
|
290
|
+
label: encryptionProgressLabel
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}, [encryptionStep, encryptionProgress, encryptionProgressLabel, isEncryptingInput, onEncryptProgress]);
|
|
294
|
+
useEffect2(() => {
|
|
295
|
+
const handleClickOutside = (event) => {
|
|
296
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
297
|
+
setIsDropdownOpen(false);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
301
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
302
|
+
}, []);
|
|
303
|
+
const sizeClasses = {
|
|
304
|
+
sm: { input: "px-3 py-2 text-sm", dropdown: "px-2 py-1 text-xs", button: "px-3 py-1 text-sm" },
|
|
305
|
+
md: { input: "px-4 py-3 text-sm", dropdown: "px-3 py-2 text-sm", button: "px-4 py-2 text-sm" },
|
|
306
|
+
lg: { input: "px-5 py-4 text-base", dropdown: "px-4 py-3 text-base", button: "px-6 py-3 text-base" }
|
|
307
|
+
};
|
|
308
|
+
const inputContainerClasses = cn(
|
|
309
|
+
"relative flex items-center bg-white dark:bg-gray-800 border rounded-lg transition-colors",
|
|
310
|
+
"focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500",
|
|
311
|
+
hasError ? "border-red-500 focus-within:ring-red-500 focus-within:border-red-500" : "border-gray-300 dark:border-gray-600",
|
|
312
|
+
(disabled || isEncryptingInput) && "bg-gray-100 dark:bg-gray-700 opacity-50",
|
|
313
|
+
className
|
|
314
|
+
);
|
|
315
|
+
const inputClasses = cn(
|
|
316
|
+
"flex-1 bg-transparent border-0 outline-none placeholder-gray-400 dark:placeholder-gray-500",
|
|
317
|
+
"text-gray-900 dark:text-white",
|
|
318
|
+
sizeClasses[size].input,
|
|
319
|
+
"pr-20",
|
|
320
|
+
// Make space for the dropdown button
|
|
321
|
+
(disabled || isEncryptingInput) && "cursor-not-allowed"
|
|
322
|
+
);
|
|
323
|
+
const dropdownButtonClasses = cn(
|
|
324
|
+
"absolute right-0 top-0 bottom-0",
|
|
325
|
+
"flex items-center gap-1 px-2 rounded-r-md border-l border-gray-300 dark:border-gray-600",
|
|
326
|
+
"bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600",
|
|
327
|
+
"transition-colors duration-200 cursor-pointer",
|
|
328
|
+
"text-xs font-medium text-gray-700 dark:text-gray-300",
|
|
329
|
+
(disabled || isEncryptingInput) && "cursor-not-allowed opacity-50",
|
|
330
|
+
isDropdownOpen && "bg-gray-200 dark:bg-gray-600"
|
|
331
|
+
);
|
|
332
|
+
const dropdownItemClasses = (isSelected, isCompatible) => cn(
|
|
333
|
+
"px-3 py-2 text-sm transition-colors",
|
|
334
|
+
isCompatible ? "cursor-pointer hover:bg-blue-50 dark:hover:bg-blue-900/30 hover:text-blue-700 dark:hover:text-blue-300" : "cursor-not-allowed opacity-50 bg-gray-50 dark:bg-gray-700",
|
|
335
|
+
isSelected && isCompatible ? "bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 font-medium" : isCompatible ? "text-gray-700 dark:text-gray-300" : "text-gray-400 dark:text-gray-500"
|
|
336
|
+
);
|
|
337
|
+
const progressVariantClasses = {
|
|
338
|
+
primary: "bg-blue-600 dark:bg-blue-500",
|
|
339
|
+
success: "bg-green-600 dark:bg-green-500",
|
|
340
|
+
warning: "bg-yellow-600 dark:bg-yellow-500",
|
|
341
|
+
error: "bg-red-600 dark:bg-red-500"
|
|
342
|
+
};
|
|
343
|
+
const progressContainerClasses = cn(
|
|
344
|
+
"w-full bg-gray-200 dark:bg-gray-700 rounded-full h-1 overflow-hidden",
|
|
345
|
+
// Debug: Add border to see container
|
|
346
|
+
"border"
|
|
347
|
+
);
|
|
348
|
+
const progressBarClasses = (variant = "primary") => cn(
|
|
349
|
+
"h-full transition-all duration-300 ease-out rounded-full",
|
|
350
|
+
progressVariantClasses[variant]
|
|
351
|
+
);
|
|
352
|
+
const isTypeCompatible = (typeValue, inputValue) => {
|
|
353
|
+
if (!inputValue.trim()) return true;
|
|
354
|
+
const typeInfo = FheTypesList.find((type) => type.value === typeValue);
|
|
355
|
+
if (!typeInfo) return false;
|
|
356
|
+
if (typeValue === "bool") {
|
|
357
|
+
const lowerValue = inputValue.toLowerCase();
|
|
358
|
+
return lowerValue === "true" || lowerValue === "false" || lowerValue === "0" || lowerValue === "1";
|
|
359
|
+
}
|
|
360
|
+
if (typeValue === "address") {
|
|
361
|
+
if (!inputValue.startsWith("0x")) return false;
|
|
362
|
+
const addressPart = inputValue.slice(2);
|
|
363
|
+
if (addressPart.length !== 40) return false;
|
|
364
|
+
const hexRegex = /^[a-fA-F0-9]+$/;
|
|
365
|
+
if (!hexRegex.test(addressPart)) return false;
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
if (typeInfo.maxValue) {
|
|
369
|
+
try {
|
|
370
|
+
const numValue = BigInt(inputValue);
|
|
371
|
+
return numValue >= 0 && numValue <= typeInfo.maxValue;
|
|
372
|
+
} catch (error) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return true;
|
|
377
|
+
};
|
|
378
|
+
const handleTextChange = (e) => {
|
|
379
|
+
const value = e.target.value;
|
|
380
|
+
setTextValue(value);
|
|
381
|
+
onTextChange?.(value);
|
|
382
|
+
setEncryptedResult(null);
|
|
383
|
+
setCopySuccess(false);
|
|
384
|
+
debouncedValidation(value);
|
|
385
|
+
};
|
|
386
|
+
const handleCopyResult = async () => {
|
|
387
|
+
if (!encryptedResult || copySuccess) return;
|
|
388
|
+
try {
|
|
389
|
+
const textToCopy = JSON.stringify(encryptedResult, (key, value) => {
|
|
390
|
+
if (typeof value === "bigint") {
|
|
391
|
+
return value.toString();
|
|
392
|
+
}
|
|
393
|
+
return value;
|
|
394
|
+
}, 2);
|
|
395
|
+
await navigator.clipboard.writeText(textToCopy);
|
|
396
|
+
console.log("Copied to clipboard:", textToCopy);
|
|
397
|
+
setCopySuccess(true);
|
|
398
|
+
setTimeout(() => {
|
|
399
|
+
setCopySuccess(false);
|
|
400
|
+
}, 2e3);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.error("Failed to copy to clipboard:", error);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
const handleTypeSelect = async (type) => {
|
|
406
|
+
setSelectedType(type);
|
|
407
|
+
setIsDropdownOpen(false);
|
|
408
|
+
onTypeChange?.(type);
|
|
409
|
+
if (textValue.trim() !== "") {
|
|
410
|
+
try {
|
|
411
|
+
console.log("Auto-encrypting value:", textValue, "as type:", type);
|
|
412
|
+
onEncryptStart?.({ value: textValue, type });
|
|
413
|
+
(async () => {
|
|
414
|
+
try {
|
|
415
|
+
const encryptionResult = await onEncryptInput(type, textValue);
|
|
416
|
+
setEncryptedResult(encryptionResult);
|
|
417
|
+
const data = { value: textValue, encrypted: encryptionResult };
|
|
418
|
+
onEncryptComplete?.(data);
|
|
419
|
+
} catch (error) {
|
|
420
|
+
const errorMessage2 = error instanceof Error ? error.message : "Encryption failed";
|
|
421
|
+
console.error("Encryption failed:", error);
|
|
422
|
+
onEncryptError?.(errorMessage2);
|
|
423
|
+
}
|
|
424
|
+
})();
|
|
425
|
+
} catch (error) {
|
|
426
|
+
const errorMessage2 = error instanceof Error ? error.message : "Encryption setup failed";
|
|
427
|
+
console.error("Encryption setup failed:", error);
|
|
428
|
+
onEncryptError?.(errorMessage2);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
const toggleDropdown = () => {
|
|
433
|
+
if (!disabled && !isEncryptingInput) {
|
|
434
|
+
setIsDropdownOpen(!isDropdownOpen);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
const ShieldIcon = () => /* @__PURE__ */ jsx2(SecurityIcon, { sx: { fontSize: 14 } });
|
|
438
|
+
const ChevronDownIcon = () => /* @__PURE__ */ jsx2(KeyboardArrowDownIcon, { sx: { fontSize: 14 } });
|
|
439
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
440
|
+
/* @__PURE__ */ jsx2("div", { className: "flex items-start gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
441
|
+
/* @__PURE__ */ jsxs("div", { className: inputContainerClasses, "data-testid": testId, children: [
|
|
442
|
+
/* @__PURE__ */ jsx2(
|
|
443
|
+
"input",
|
|
444
|
+
{
|
|
445
|
+
type: "text",
|
|
446
|
+
className: inputClasses,
|
|
447
|
+
placeholder,
|
|
448
|
+
value: textValue,
|
|
449
|
+
onChange: handleTextChange,
|
|
450
|
+
disabled: disabled || isEncryptingInput,
|
|
451
|
+
"data-testid": testId ? `${testId}-input` : "fnx-encrypt-input"
|
|
452
|
+
}
|
|
453
|
+
),
|
|
454
|
+
(isEncryptingInput || encryptedResult) && /* @__PURE__ */ jsx2("div", { className: "absolute right-16 top-1/2 transform -translate-y-1/2", children: isEncryptingInput ? /* @__PURE__ */ jsx2("div", { className: "bg-blue-500 px-2 py-1 text-xs text-white rounded animate-pulse", children: "Encrypting..." }) : encryptedResult ? /* @__PURE__ */ jsx2(
|
|
455
|
+
"button",
|
|
456
|
+
{
|
|
457
|
+
onClick: handleCopyResult,
|
|
458
|
+
disabled: copySuccess,
|
|
459
|
+
className: `px-2 py-1 text-xs text-white rounded flex items-center gap-1 transition-all duration-300 ${copySuccess ? "bg-green-600 cursor-default" : "bg-green-500 hover:bg-green-600"}`,
|
|
460
|
+
title: copySuccess ? "Copied to clipboard!" : "Copy encrypted result to clipboard",
|
|
461
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
462
|
+
copySuccess ? /* @__PURE__ */ jsx2(CheckIcon, { sx: { fontSize: 12 } }) : /* @__PURE__ */ jsx2(ContentCopyIcon, { sx: { fontSize: 12 } }),
|
|
463
|
+
"Copy"
|
|
464
|
+
] })
|
|
465
|
+
}
|
|
466
|
+
) : null }),
|
|
467
|
+
/* @__PURE__ */ jsxs("div", { className: "cofhe-dropdown-container", ref: dropdownRef, children: [
|
|
468
|
+
/* @__PURE__ */ jsxs(
|
|
469
|
+
"button",
|
|
470
|
+
{
|
|
471
|
+
type: "button",
|
|
472
|
+
className: dropdownButtonClasses,
|
|
473
|
+
onClick: toggleDropdown,
|
|
474
|
+
disabled: disabled || isEncryptingInput,
|
|
475
|
+
"data-testid": testId ? `${testId}-type-selector` : "fnx-type-selector",
|
|
476
|
+
children: [
|
|
477
|
+
/* @__PURE__ */ jsx2(ShieldIcon, {}),
|
|
478
|
+
/* @__PURE__ */ jsx2(ChevronDownIcon, {})
|
|
479
|
+
]
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
isDropdownOpen && /* @__PURE__ */ jsx2("div", { className: "cofhe-dropdown-menu", children: options.map((option) => {
|
|
483
|
+
const isCompatible = isTypeCompatible(option.value, textValue);
|
|
484
|
+
const isSelected = option.value === selectedType;
|
|
485
|
+
return /* @__PURE__ */ jsx2(
|
|
486
|
+
"div",
|
|
487
|
+
{
|
|
488
|
+
className: dropdownItemClasses(isSelected, isCompatible),
|
|
489
|
+
onClick: () => isCompatible && handleTypeSelect(option.value),
|
|
490
|
+
"data-testid": `${testId ? `${testId}-` : ""}type-option-${option.value}`,
|
|
491
|
+
title: !isCompatible ? `Value "${textValue}" is not compatible with ${option.label}` : void 0,
|
|
492
|
+
children: /* @__PURE__ */ jsx2("span", { className: "font-mono", children: option.label })
|
|
493
|
+
},
|
|
494
|
+
option.value
|
|
495
|
+
);
|
|
496
|
+
}) })
|
|
497
|
+
] })
|
|
498
|
+
] }),
|
|
499
|
+
showProgress && /* @__PURE__ */ jsxs(
|
|
500
|
+
"div",
|
|
501
|
+
{
|
|
502
|
+
className: "mt-3 overflow-hidden",
|
|
503
|
+
style: {
|
|
504
|
+
animation: isEncryptingInput ? "slideDownFadeIn 0.5s ease-out forwards" : "slideUpFadeOut 0.5s ease-out forwards"
|
|
505
|
+
},
|
|
506
|
+
"data-testid": testId ? `${testId}-progress` : "fnx-encrypt-progress",
|
|
507
|
+
children: [
|
|
508
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-1", children: [
|
|
509
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: encryptionProgressLabel || "Processing..." }),
|
|
510
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: [
|
|
511
|
+
encryptionProgress || 0,
|
|
512
|
+
"%"
|
|
513
|
+
] })
|
|
514
|
+
] }),
|
|
515
|
+
/* @__PURE__ */ jsx2("div", { className: progressContainerClasses, children: /* @__PURE__ */ jsx2(
|
|
516
|
+
"div",
|
|
517
|
+
{
|
|
518
|
+
className: progressBarClasses("primary"),
|
|
519
|
+
style: {
|
|
520
|
+
width: `${Math.min(100, Math.max(0, encryptionProgress || 0))}%`,
|
|
521
|
+
transition: "width 0.3s ease-out"
|
|
522
|
+
},
|
|
523
|
+
"data-testid": testId ? `${testId}-progress-bar` : "fnx-encrypt-progress-bar"
|
|
524
|
+
}
|
|
525
|
+
) })
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
)
|
|
529
|
+
] }) }),
|
|
530
|
+
hasError && errorMessage && /* @__PURE__ */ jsx2(
|
|
531
|
+
"p",
|
|
532
|
+
{
|
|
533
|
+
className: "mt-2 text-sm text-red-600 dark:text-red-400",
|
|
534
|
+
"data-testid": testId ? `${testId}-error` : "fnx-encrypt-error",
|
|
535
|
+
children: errorMessage
|
|
536
|
+
}
|
|
537
|
+
)
|
|
538
|
+
] });
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
// src/utils/logging.ts
|
|
542
|
+
var fheTypeToString = (fheType) => {
|
|
543
|
+
switch (fheType) {
|
|
544
|
+
case "bool":
|
|
545
|
+
return "ebool";
|
|
546
|
+
case "uint8":
|
|
547
|
+
return "euint8";
|
|
548
|
+
case "uint16":
|
|
549
|
+
return "euint16";
|
|
550
|
+
case "uint32":
|
|
551
|
+
return "euint32";
|
|
552
|
+
case "uint64":
|
|
553
|
+
return "euint64";
|
|
554
|
+
case "uint128":
|
|
555
|
+
return "euint128";
|
|
556
|
+
case "address":
|
|
557
|
+
return "eaddress";
|
|
558
|
+
default:
|
|
559
|
+
return "unknown";
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
var encryptedValueToString = (fheType, handle) => {
|
|
563
|
+
const hashStr = handle.toString();
|
|
564
|
+
const truncated = hashStr.slice(0, 6) + ".." + hashStr.slice(hashStr.length - 6);
|
|
565
|
+
return `${fheTypeToString(fheType)}(${truncated})`;
|
|
566
|
+
};
|
|
567
|
+
export {
|
|
568
|
+
CofheProvider,
|
|
569
|
+
FheTypesList,
|
|
570
|
+
FnxEncryptInput,
|
|
571
|
+
encryptedValueToString,
|
|
572
|
+
fheTypeToString,
|
|
573
|
+
useCofheContext,
|
|
574
|
+
useEncryptInput
|
|
575
|
+
};
|
|
576
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/CofheProvider.tsx","../src/hooks/useEncryptInput.ts","../src/components/FnxEncryptInput.tsx","../src/utils/cn.ts","../src/utils/debounce.ts","../src/utils/utils.ts","../src/utils/logging.ts"],"sourcesContent":["import { createContext, useContext, useEffect, useState } from 'react';\nimport type { CofhesdkClient } from '@cofhe/sdk';\nimport type { CofheContextValue, CofheProviderProps } from '../types/index.js';\n\nconst CofheContext = createContext<CofheContextValue | undefined>(undefined);\n\nexport function CofheProvider({ children, client: providedClient, config }: CofheProviderProps) {\n const [client, setClient] = useState<CofhesdkClient | null>(providedClient || null);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (providedClient) {\n setClient(providedClient);\n setIsInitialized(true);\n return;\n }\n\n if (config) {\n try {\n // Initialize client with config\n // This would need to be implemented based on the actual CofheClient constructor\n // const newClient = new CofheClient(config);\n // setClient(newClient);\n setIsInitialized(true);\n } catch (err) {\n setError(err instanceof Error ? err : new Error('Failed to initialize CoFHE client'));\n }\n }\n }, [providedClient, config]);\n\n const contextValue: CofheContextValue = {\n client,\n isInitialized,\n error,\n };\n\n return (\n <CofheContext.Provider value={contextValue}>\n {children}\n </CofheContext.Provider>\n );\n}\n\nexport function useCofheContext(): CofheContextValue {\n const context = useContext(CofheContext);\n if (context === undefined) {\n throw new Error('useCofheContext must be used within a CofheProvider');\n }\n return context;\n}\n","import { useState, useCallback } from 'react';\nimport { useCofheContext } from '../providers/CofheProvider.js';\nimport { Encryptable } from '@cofhe/sdk';\nimport type { EncryptableItem } from '@cofhe/sdk';\nimport type { FheTypeValue } from '../utils/utils.js';\nimport type { EncryptionStep } from '../types/component-types.js';\n\n// Map SDK encrypt steps to UI display info\nconst STEP_CONFIG: Record<EncryptionStep, { label: string; progress: number }> = {\n 'initTfhe': {\n label: 'Initializing TFHE...',\n progress: 5,\n },\n 'fetchKeys': {\n label: 'Fetching FHE keys...',\n progress: 20,\n },\n 'pack': {\n label: 'Packing data...',\n progress: 40,\n },\n 'prove': {\n label: 'Generating proof...',\n progress: 70,\n },\n 'verify': {\n label: 'Verifying...',\n progress: 90,\n },\n 'done': {\n label: 'Encryption complete!',\n progress: 100,\n },\n};\n\nexport interface UseEncryptInputReturn {\n onEncryptInput: (_type: FheTypeValue, _value: string) => Promise<any>;\n isEncryptingInput: boolean;\n encryptionStep: EncryptionStep | null;\n encryptionProgress: number;\n encryptionProgressLabel: string;\n inputEncryptionDisabled: boolean;\n}\n\nexport function useEncryptInput(): UseEncryptInputReturn {\n const { client } = useCofheContext();\n const [isEncrypting, setIsEncrypting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [encryptionStep, setEncryptionStep] = useState<EncryptionStep | null>(null);\n const [encryptionProgress, setEncryptionProgress] = useState<number>(0);\n const [encryptionProgressLabel, setEncryptionProgressLabel] = useState<string>('');\n\n const onEncryptInput = useCallback(async (type: FheTypeValue, value: string) => {\n if (!client) {\n throw new Error('CoFHE client not initialized');\n }\n\n setIsEncrypting(true);\n setError(null);\n\n try {\n // Convert value based on type\n let convertedValue: number | bigint | boolean | string;\n \n if (type === 'bool') {\n convertedValue = value.toLowerCase() === 'true' || value === '1';\n } else if (type === 'address') {\n convertedValue = value as string | bigint;\n } else {\n // Numeric types\n convertedValue = value.includes('.') ? parseFloat(value) : parseInt(value, 10);\n }\n\n // Create encryptable item\n let encryptableItem: EncryptableItem;\n \n switch (type) {\n case 'bool':\n encryptableItem = Encryptable.bool(convertedValue as boolean);\n break;\n case 'uint8':\n encryptableItem = Encryptable.uint8(BigInt(convertedValue));\n break;\n case 'uint16':\n encryptableItem = Encryptable.uint16(BigInt(convertedValue));\n break;\n case 'uint32':\n encryptableItem = Encryptable.uint32(BigInt(convertedValue));\n break;\n case 'uint64':\n encryptableItem = Encryptable.uint64(BigInt(convertedValue));\n break;\n case 'uint128':\n encryptableItem = Encryptable.uint128(BigInt(convertedValue));\n break;\n case 'address':\n encryptableItem = Encryptable.address(convertedValue as string | bigint);\n break;\n default:\n encryptableItem = Encryptable.uint32(BigInt(convertedValue));\n }\n\n // Perform encryption with real-time step tracking\n const encryptionBuilder = client.encryptInputs([encryptableItem]).setStepCallback((step, context) => {\n const stepConfig = STEP_CONFIG[step as EncryptionStep];\n \n if (stepConfig) {\n // Update UI with real step information\n setEncryptionStep(step as EncryptionStep);\n setEncryptionProgress(stepConfig.progress);\n setEncryptionProgressLabel(stepConfig.label);\n }\n \n // Log worker status for debugging (prove step only)\n if (step === 'prove' && context?.isEnd) {\n console.log('[Encryption] Worker Status:', {\n useWorker: context.useWorker,\n usedWorker: context.usedWorker,\n workerFailedError: context.workerFailedError,\n duration: context.duration + 'ms'\n });\n }\n });\n const result = await encryptionBuilder.encrypt();\n \n if (!result.success) {\n throw result.error;\n }\n\n // Complete\n setEncryptionStep('done');\n setEncryptionProgress(100);\n setEncryptionProgressLabel('Encryption complete!');\n\n // Reset after a short delay\n setTimeout(() => {\n setEncryptionStep(null);\n setEncryptionProgress(0);\n setEncryptionProgressLabel('');\n }, 1000);\n\n setIsEncrypting(false);\n return result.data[0]; // Return first (and only) encrypted item\n } catch (err) {\n // Reset on error\n setEncryptionStep(null);\n setEncryptionProgress(0);\n setEncryptionProgressLabel('');\n setIsEncrypting(false);\n const error = err instanceof Error ? err : new Error('Encryption failed');\n setError(error);\n throw error;\n }\n }, [client]);\n\n return {\n onEncryptInput,\n isEncryptingInput: isEncrypting,\n encryptionStep,\n encryptionProgress,\n encryptionProgressLabel,\n inputEncryptionDisabled: isEncrypting || !!error,\n };\n}\n","import { useState, useRef, useEffect } from 'react';\nimport type { BaseProps, DropdownOption, ComponentSize, EncryptionProgressData, EncryptionResultData, EncryptionStartData } from '../types/component-types.js';\nimport { cn } from '../utils/cn.js';\nimport { debounce } from '../utils/debounce.js';\nimport { FheTypesList, type FheTypeValue } from '../utils/utils.js';\nimport SecurityIcon from '@mui/icons-material/Security';\nimport KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';\nimport ContentCopyIcon from '@mui/icons-material/ContentCopy';\nimport CheckIcon from '@mui/icons-material/Check';\nimport { useEncryptInput } from '../hooks/useEncryptInput.js';\n\nexport interface FnxEncryptInputProps extends BaseProps {\n /** Placeholder text for the text field */\n placeholder?: string;\n /** Initial value for the text field */\n initialValue?: string;\n /** Dropdown options for encryption types */\n options?: DropdownOption[];\n /** Component size */\n size?: ComponentSize;\n /** Whether inputs have errors */\n hasError?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Whether the component is disabled */\n disabled?: boolean;\n /** Whether to show the progress bar during encryption */\n showProgressBar?: boolean;\n /** Debounce delay for validation in milliseconds (default: 300) */\n debounceMs?: number;\n /** Callback when text changes */\n onTextChange?: (_value: string) => void;\n /** Callback when encryption type selection changes */\n onTypeChange?: (_value: string) => void;\n /** Callback when encryption starts */\n onEncryptStart?: (_data: EncryptionStartData) => void;\n /** Callback for encryption progress updates */\n onEncryptProgress?: (_data: EncryptionProgressData) => void;\n /** Callback when encryption completes successfully */\n onEncryptComplete?: (_data: EncryptionResultData) => void;\n /** Callback when encryption fails */\n onEncryptError?: (_error: string) => void;\n}\n\nexport const FnxEncryptInput: React.FC<FnxEncryptInputProps> = ({\n className,\n testId,\n placeholder = 'Enter number or address...',\n initialValue = '',\n options = FheTypesList,\n size = 'md',\n hasError = false,\n errorMessage,\n disabled = false,\n showProgressBar = false,\n debounceMs = 300,\n onTextChange,\n onTypeChange,\n onEncryptStart,\n onEncryptProgress,\n onEncryptComplete,\n onEncryptError\n}) => {\n const [textValue, setTextValue] = useState(initialValue);\n const [selectedType, setSelectedType] = useState<FheTypeValue>(options[0]?.value || 'uint32');\n const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n const [showProgress, setShowProgress] = useState(false);\n const [encryptedResult, setEncryptedResult] = useState<any>(null);\n const [copySuccess, setCopySuccess] = useState<boolean>(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const { onEncryptInput, isEncryptingInput, encryptionStep, encryptionProgress, encryptionProgressLabel } = useEncryptInput();\n\n\n // Debounced validation function\n const debouncedValidation = useRef(\n debounce((value: string) => {\n // This will be used for validation logic if needed in the future\n console.log('Debounced validation for:', value);\n }, debounceMs)\n ).current;\n\n // Handle progress bar visibility with animation\n useEffect(() => {\n if (showProgressBar && isEncryptingInput) {\n // Show immediately when encryption starts\n setShowProgress(true);\n } else if (!isEncryptingInput) {\n // Delay hiding to allow fade-out animation\n const timer = setTimeout(() => setShowProgress(false), 500);\n return () => clearTimeout(timer);\n }\n }, [showProgressBar, isEncryptingInput]);\n\n // Handle progress updates and call onEncryptProgress callback\n useEffect(() => {\n if (isEncryptingInput && encryptionStep && encryptionProgress !== null && encryptionProgressLabel) {\n onEncryptProgress?.({\n step: encryptionStep.toString(),\n progress: encryptionProgress,\n label: encryptionProgressLabel\n });\n }\n }, [encryptionStep, encryptionProgress, encryptionProgressLabel, isEncryptingInput, onEncryptProgress]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsDropdownOpen(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n // Size variants\n const sizeClasses = {\n sm: { input: 'px-3 py-2 text-sm', dropdown: 'px-2 py-1 text-xs', button: 'px-3 py-1 text-sm' },\n md: { input: 'px-4 py-3 text-sm', dropdown: 'px-3 py-2 text-sm', button: 'px-4 py-2 text-sm' },\n lg: { input: 'px-5 py-4 text-base', dropdown: 'px-4 py-3 text-base', button: 'px-6 py-3 text-base' }\n };\n\n // Input container with integrated dropdown\n const inputContainerClasses = cn(\n 'relative flex items-center bg-white dark:bg-gray-800 border rounded-lg transition-colors',\n 'focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500',\n hasError \n ? 'border-red-500 focus-within:ring-red-500 focus-within:border-red-500' \n : 'border-gray-300 dark:border-gray-600',\n (disabled || isEncryptingInput) && 'bg-gray-100 dark:bg-gray-700 opacity-50',\n className\n );\n\n const inputClasses = cn(\n 'flex-1 bg-transparent border-0 outline-none placeholder-gray-400 dark:placeholder-gray-500',\n 'text-gray-900 dark:text-white',\n sizeClasses[size].input,\n 'pr-20', // Make space for the dropdown button\n (disabled || isEncryptingInput) && 'cursor-not-allowed'\n );\n\n // Dropdown button inside the input\n const dropdownButtonClasses = cn(\n 'absolute right-0 top-0 bottom-0',\n 'flex items-center gap-1 px-2 rounded-r-md border-l border-gray-300 dark:border-gray-600',\n 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600',\n 'transition-colors duration-200 cursor-pointer',\n 'text-xs font-medium text-gray-700 dark:text-gray-300',\n (disabled || isEncryptingInput) && 'cursor-not-allowed opacity-50',\n isDropdownOpen && 'bg-gray-200 dark:bg-gray-600'\n );\n\n const dropdownItemClasses = (isSelected: boolean, isCompatible: boolean) => cn(\n 'px-3 py-2 text-sm transition-colors',\n isCompatible \n ? 'cursor-pointer hover:bg-blue-50 dark:hover:bg-blue-900/30 hover:text-blue-700 dark:hover:text-blue-300'\n : 'cursor-not-allowed opacity-50 bg-gray-50 dark:bg-gray-700',\n isSelected && isCompatible\n ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 font-medium' \n : isCompatible\n ? 'text-gray-700 dark:text-gray-300'\n : 'text-gray-400 dark:text-gray-500'\n );\n\n // Progress bar styles\n const progressVariantClasses = {\n primary: 'bg-blue-600 dark:bg-blue-500',\n success: 'bg-green-600 dark:bg-green-500',\n warning: 'bg-yellow-600 dark:bg-yellow-500',\n error: 'bg-red-600 dark:bg-red-500'\n };\n\n const progressContainerClasses = cn(\n 'w-full bg-gray-200 dark:bg-gray-700 rounded-full h-1 overflow-hidden',\n // Debug: Add border to see container\n 'border'\n );\n\n const progressBarClasses = (variant: 'primary' | 'success' | 'warning' | 'error' = 'primary') => cn(\n 'h-full transition-all duration-300 ease-out rounded-full',\n progressVariantClasses[variant]\n );\n\n\n // Check if a type is compatible with the current input value\n const isTypeCompatible = (typeValue: FheTypeValue, inputValue: string): boolean => {\n if (!inputValue.trim()) return true; // Empty input is compatible with all types\n \n const typeInfo = FheTypesList.find(type => type.value === typeValue);\n if (!typeInfo) return false;\n \n // Boolean type validation\n if (typeValue === 'bool') {\n const lowerValue = inputValue.toLowerCase();\n return lowerValue === 'true' || lowerValue === 'false' || lowerValue === '0' || lowerValue === '1';\n }\n \n // Address type validation\n if (typeValue === 'address') {\n if (!inputValue.startsWith('0x')) return false;\n \n const addressPart = inputValue.slice(2);\n if (addressPart.length !== 40) return false;\n \n const hexRegex = /^[a-fA-F0-9]+$/;\n if (!hexRegex.test(addressPart)) return false;\n \n return true;\n }\n \n // Numeric type validation\n if (typeInfo.maxValue) {\n try {\n const numValue = BigInt(inputValue);\n return numValue >= 0 && numValue <= typeInfo.maxValue;\n } catch (error) {\n return false;\n }\n }\n \n return true;\n };\n\n const handleTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setTextValue(value);\n onTextChange?.(value);\n \n // Clear encrypted result when text changes\n setEncryptedResult(null);\n setCopySuccess(false);\n \n // Trigger debounced validation\n debouncedValidation(value);\n };\n\n const handleCopyResult = async () => {\n if (!encryptedResult || copySuccess) return;\n \n try {\n // Custom JSON serializer that handles BigInt\n const textToCopy = JSON.stringify(encryptedResult, (key, value) => {\n if (typeof value === 'bigint') {\n return value.toString();\n }\n return value;\n }, 2); // Pretty format with 2 spaces\n \n await navigator.clipboard.writeText(textToCopy);\n console.log('Copied to clipboard:', textToCopy);\n \n // Show success indication\n setCopySuccess(true);\n \n // Reset after 2 seconds\n setTimeout(() => {\n setCopySuccess(false);\n }, 2000);\n } catch (error) {\n console.error('Failed to copy to clipboard:', error);\n }\n };\n\n const handleTypeSelect = async (type: FheTypeValue) => {\n setSelectedType(type);\n setIsDropdownOpen(false);\n onTypeChange?.(type);\n\n // Auto-encrypt when type is selected (if text field has value)\n if (textValue.trim() !== '') {\n try {\n console.log('Auto-encrypting value:', textValue, 'as type:', type);\n \n // Call onEncryptStart callback\n onEncryptStart?.({ value: textValue, type: type });\n \n // TODO: Try to create non-blocking encryption call that doesn't block the UI\n // Not really work, need to improve cofhejs side to make it non-blocking\n (async () => {\n try {\n const encryptionResult = await onEncryptInput(type, textValue);\n \n // Store the result for the copy button\n setEncryptedResult(encryptionResult);\n \n const data = { value: textValue, encrypted: encryptionResult };\n \n // Call completion callback\n onEncryptComplete?.(data);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Encryption failed';\n console.error('Encryption failed:', error);\n onEncryptError?.(errorMessage);\n }\n })();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Encryption setup failed';\n console.error('Encryption setup failed:', error);\n onEncryptError?.(errorMessage);\n }\n }\n };\n\n const toggleDropdown = () => {\n if (!disabled && !isEncryptingInput) {\n setIsDropdownOpen(!isDropdownOpen);\n }\n };\n\n // Material Icons components\n const ShieldIcon = () => (\n <SecurityIcon sx={{ fontSize: 14 }} />\n );\n\n const ChevronDownIcon = () => (\n <KeyboardArrowDownIcon sx={{ fontSize: 14 }} />\n );\n\n return (\n <div className=\"w-full\">\n <div className=\"flex items-start gap-3\">\n {/* Input with integrated dropdown - this will determine progress bar width */}\n <div className=\"flex-1\">\n <div className={inputContainerClasses} data-testid={testId}>\n <input\n type=\"text\"\n className={inputClasses}\n placeholder={placeholder}\n value={textValue}\n onChange={handleTextChange}\n disabled={disabled || isEncryptingInput}\n data-testid={testId ? `${testId}-input` : 'fnx-encrypt-input'}\n />\n \n {/* Encryption status indicator */}\n {(isEncryptingInput || encryptedResult) && (\n <div className=\"absolute right-16 top-1/2 transform -translate-y-1/2\">\n {isEncryptingInput ? (\n <div className=\"bg-blue-500 px-2 py-1 text-xs text-white rounded animate-pulse\">\n Encrypting...\n </div>\n ) : encryptedResult ? (\n <button\n onClick={handleCopyResult}\n disabled={copySuccess}\n className={`px-2 py-1 text-xs text-white rounded flex items-center gap-1 transition-all duration-300 ${\n copySuccess \n ? 'bg-green-600 cursor-default' \n : 'bg-green-500 hover:bg-green-600'\n }`}\n title={copySuccess ? \"Copied to clipboard!\" : \"Copy encrypted result to clipboard\"}\n >\n <>\n {copySuccess ? (\n <CheckIcon sx={{ fontSize: 12 }} />\n ) : (\n <ContentCopyIcon sx={{ fontSize: 12 }} />\n )}\n Copy\n </>\n </button>\n ) : null}\n </div>\n )}\n \n {/* Integrated dropdown button */}\n <div className=\"cofhe-dropdown-container\" ref={dropdownRef}>\n <button\n type=\"button\"\n className={dropdownButtonClasses}\n onClick={toggleDropdown}\n disabled={disabled || isEncryptingInput}\n data-testid={testId ? `${testId}-type-selector` : 'fnx-type-selector'}\n >\n <ShieldIcon />\n <ChevronDownIcon />\n </button>\n \n {/* Dropdown menu */}\n {isDropdownOpen && (\n <div className=\"cofhe-dropdown-menu\">\n {options.map((option) => {\n const isCompatible = isTypeCompatible(option.value, textValue);\n const isSelected = option.value === selectedType;\n \n return (\n <div\n key={option.value}\n className={dropdownItemClasses(isSelected, isCompatible)}\n onClick={() => isCompatible && handleTypeSelect(option.value)}\n data-testid={`${testId ? `${testId}-` : ''}type-option-${option.value}`}\n title={!isCompatible ? `Value \"${textValue}\" is not compatible with ${option.label}` : undefined}\n >\n <span className=\"font-mono\">{option.label}</span>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n \n {/* Progress bar section - shows immediately when encryption starts */}\n {showProgress && (\n <div \n className=\"mt-3 overflow-hidden\"\n style={{\n animation: isEncryptingInput ? 'slideDownFadeIn 0.5s ease-out forwards' : 'slideUpFadeOut 0.5s ease-out forwards',\n }}\n data-testid={testId ? `${testId}-progress` : 'fnx-encrypt-progress'}\n >\n <div className=\"flex justify-between items-center mb-1\">\n <span className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n {encryptionProgressLabel || 'Processing...'}\n </span>\n <span className=\"text-sm text-gray-500 dark:text-gray-400\">\n {encryptionProgress || 0}%\n </span>\n </div>\n <div className={progressContainerClasses}>\n <div\n className={progressBarClasses('primary')}\n style={{ \n width: `${Math.min(100, Math.max(0, encryptionProgress || 0))}%`,\n transition: 'width 0.3s ease-out'\n }}\n data-testid={testId ? `${testId}-progress-bar` : 'fnx-encrypt-progress-bar'}\n />\n </div>\n </div>\n )}\n </div>\n \n </div>\n \n {/* Error message */}\n {hasError && errorMessage && (\n <p \n className=\"mt-2 text-sm text-red-600 dark:text-red-400\" \n data-testid={testId ? `${testId}-error` : 'fnx-encrypt-error'}\n >\n {errorMessage}\n </p>\n )}\n </div>\n );\n};\n","/**\n * Simple utility to merge class names\n * Filters out falsy values and joins with spaces\n */\nexport const cn = (...classes: (string | undefined | null | false)[]): string => {\n return classes.filter(Boolean).join(' ').replace(/\\s+/g, ' ').trim();\n };\n ","/**\n * Creates a debounced function that delays invoking func until after wait milliseconds\n * have elapsed since the last time the debounced function was invoked.\n */\n/* eslint-disable @typescript-eslint/no-unused-vars */\nexport const debounce = <T extends (..._args: any[]) => any>(\n func: T,\n wait: number\n ): ((..._args: Parameters<T>) => void) => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n \n return (...args: Parameters<T>) => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n \n timeoutId = setTimeout(() => {\n func(...args);\n }, wait);\n };\n };\n ","// FHE Types for the current CoFHE SDK\nexport type FheTypeValue = 'uint8' | 'uint16' | 'uint32' | 'uint64' | 'uint128' | 'bool' | 'address';\n\nexport interface FheTypeOption {\n label: string;\n value: FheTypeValue;\n maxValue: bigint | null;\n description: string;\n}\n\nexport const FheTypesList: FheTypeOption[] = [\n { \n label: \"Encrypted Bool\", \n value: 'bool',\n maxValue: BigInt(1), // 0 or 1\n description: \"Boolean value (true/false)\"\n },\n { \n label: \"Encrypted Uint8\", \n value: 'uint8',\n maxValue: BigInt(2 ** 8 - 1), // 255\n description: \"8-bit unsigned integer (0 to 255)\"\n },\n { \n label: \"Encrypted Uint16\", \n value: 'uint16',\n maxValue: BigInt(2 ** 16 - 1), // 65,535\n description: \"16-bit unsigned integer (0 to 65,535)\"\n },\n { \n label: \"Encrypted Uint32\", \n value: 'uint32',\n maxValue: BigInt(2 ** 32 - 1), // 4,294,967,295\n description: \"32-bit unsigned integer (0 to 4,294,967,295)\"\n },\n { \n label: \"Encrypted Uint64\", \n value: 'uint64',\n maxValue: BigInt(2 ** 64 - 1), // 18,446,744,073,709,551,615\n description: \"64-bit unsigned integer (0 to 18,446,744,073,709,551,615)\"\n },\n { \n label: \"Encrypted Uint128\", \n value: 'uint128',\n maxValue: BigInt(2 ** 128 - 1), // Very large number\n description: \"128-bit unsigned integer\"\n },\n { \n label: \"Encrypted Address\", \n value: 'address',\n maxValue: null, // Address validation is different\n description: \"Ethereum address (0x...)\"\n },\n];\n","import type { FheTypeValue } from './utils.js';\n\nexport const logBlockStart = (message: string) => {\n console.log(\"┌──────────────────┬──────────────────────────────────────────────────\");\n console.log(`│ [COFHE] │ ${message}`);\n console.log(\"├──────────────────┴──────────────────────────────────────────────────\");\n};\n\nexport const logBlockMessage = (message: string) => {\n console.log(`│ ${message}`);\n};\n\nexport const logBlockEnd = () => {\n console.log(\"└─────────────────────────────────────────────────────────────────────\");\n};\n\nexport const logBlockMessageAndEnd = (message: string) => {\n logBlockMessage(message);\n logBlockEnd();\n};\n\nexport const fheTypeToString = (fheType: FheTypeValue) => {\n switch (fheType) {\n case 'bool':\n return \"ebool\";\n case 'uint8':\n return \"euint8\";\n case 'uint16':\n return \"euint16\";\n case 'uint32':\n return \"euint32\";\n case 'uint64':\n return \"euint64\";\n case 'uint128':\n return \"euint128\";\n case 'address':\n return \"eaddress\";\n default:\n return \"unknown\";\n }\n};\n\nexport const plaintextToString = (fheType: FheTypeValue, plaintext: string | bigint | boolean) => {\n if (fheType === 'bool') {\n return plaintext === 1n || plaintext === true ? \"true\" : \"false\";\n }\n return plaintext;\n};\n\nexport const encryptedValueToString = (fheType: FheTypeValue, handle: bigint) => {\n const hashStr = handle.toString();\n const truncated = hashStr.slice(0, 6) + \"..\" + hashStr.slice(hashStr.length - 6);\n\n return `${fheTypeToString(fheType)}(${truncated})`;\n};\n"],"mappings":"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","names":["useState","useState","error","useState","useEffect","jsx","useState","useEffect","errorMessage"]}
|