@cofhe/abi 0.2.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.
@@ -0,0 +1,279 @@
1
+ import { type Primitive, type LiteralToPrimitive, FheTypes } from '@cofhe/sdk';
2
+ import type { Abi, AbiFunction, ExtractAbiFunction, AbiParameter } from 'abitype';
3
+ import type {
4
+ EncryptedReturnType,
5
+ CofheAbiParametersToPrimitiveTypes,
6
+ EBool,
7
+ EAddress,
8
+ EUint128,
9
+ EUint16,
10
+ EUint32,
11
+ EUint64,
12
+ EUint8,
13
+ } from './fhenixMap';
14
+ import {
15
+ getAbiFunction,
16
+ type IsUnion,
17
+ type UnionToTuple,
18
+ type ContractReturnType,
19
+ extractArrayParameterType,
20
+ } from './utils';
21
+
22
+ type FirstCofheReturnValue<T> = [T] extends [void]
23
+ ? never
24
+ : T extends readonly [infer Head, ...(readonly unknown[])]
25
+ ? Head
26
+ : T;
27
+
28
+ type FheTypeFromCofheReturnValue<T> = T extends { utype: infer U }
29
+ ? U
30
+ : T extends readonly (infer Element)[]
31
+ ? FheTypeFromCofheReturnValue<Element>
32
+ : never;
33
+
34
+ /**
35
+ * Extracts the `FheTypes` of the first returned value of a CoFHE call.
36
+ *
37
+ * Examples:
38
+ * - `returns (ebool)` -> `FheTypes.Bool`
39
+ * - `returns (euint8, euint64)` -> `FheTypes.Uint8`
40
+ * - `returns (euint16[])` -> `FheTypes.Uint16`
41
+ */
42
+ export type CofheFirstReturnFheType<
43
+ abi extends Abi | readonly unknown[] = Abi,
44
+ functionName extends string = string,
45
+ args extends readonly unknown[] | undefined = readonly unknown[] | undefined,
46
+ > = FheTypeFromCofheReturnValue<FirstCofheReturnValue<CofheReturnType<abi, functionName, args>>>;
47
+
48
+ export type CofheReturnType<
49
+ abi extends Abi | readonly unknown[] = Abi,
50
+ functionName extends string = string,
51
+ args extends readonly unknown[] | undefined = readonly unknown[] | undefined,
52
+ ///
53
+ abiFunction extends AbiFunction = (
54
+ abi extends Abi ? ExtractAbiFunction<abi, functionName> : AbiFunction
55
+ ) extends infer abiFunction_ extends AbiFunction
56
+ ? IsUnion<abiFunction_> extends true // narrow overloads by `args` by converting to tuple and filtering out overloads that don't match
57
+ ? UnionToTuple<abiFunction_> extends infer abiFunctions extends readonly AbiFunction[]
58
+ ? {
59
+ [K in keyof abiFunctions]: (
60
+ readonly unknown[] | undefined extends args // for functions that don't have inputs, `args` can be `undefined` so fallback to `readonly []`
61
+ ? readonly []
62
+ : args
63
+ ) extends CofheAbiParametersToPrimitiveTypes<abiFunctions[K]['inputs'], 'inputs'>
64
+ ? abiFunctions[K]
65
+ : never;
66
+ }[number] // convert back to union (removes `never` tuple entries: `['foo', never, 'bar'][number]` => `'foo' | 'bar'`)
67
+ : never
68
+ : abiFunction_
69
+ : never,
70
+ outputs extends readonly AbiParameter[] = abiFunction['outputs'],
71
+ primitiveTypes extends readonly unknown[] = CofheAbiParametersToPrimitiveTypes<outputs, 'outputs'>,
72
+ > = [abiFunction] extends [never]
73
+ ? unknown // `abiFunction` was not inferrable (e.g. `abi` declared as `Abi`)
74
+ : readonly unknown[] extends primitiveTypes
75
+ ? unknown // `abiFunction` was not inferrable (e.g. `abi` not const-asserted)
76
+ : primitiveTypes extends readonly [] // unwrap `primitiveTypes`
77
+ ? // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>
78
+ void // no outputs
79
+ : primitiveTypes extends readonly [infer primitiveType]
80
+ ? primitiveType // single output
81
+ : primitiveTypes;
82
+
83
+ type EncryptedReturnTypeToReturnTypeMap<E extends EncryptedReturnType> = E extends EBool
84
+ ? boolean
85
+ : E extends EUint8
86
+ ? bigint
87
+ : E extends EUint16
88
+ ? bigint
89
+ : E extends EUint32
90
+ ? bigint
91
+ : E extends EUint64
92
+ ? bigint
93
+ : E extends EUint128
94
+ ? bigint
95
+ : E extends EAddress
96
+ ? string
97
+ : never;
98
+
99
+ type EncryptedReturnTypesToReturnTypes<T> = T extends Primitive
100
+ ? LiteralToPrimitive<T>
101
+ : T extends EncryptedReturnType
102
+ ? EncryptedReturnTypeToReturnTypeMap<T>
103
+ : {
104
+ [K in keyof T]: EncryptedReturnTypesToReturnTypes<T[K]>;
105
+ };
106
+
107
+ export type CofheReturnTypePostTransform<
108
+ abi extends Abi | readonly unknown[] = Abi,
109
+ functionName extends string = string,
110
+ args extends readonly unknown[] | undefined = readonly unknown[] | undefined,
111
+ > = EncryptedReturnTypesToReturnTypes<CofheReturnType<abi, functionName, args>>;
112
+
113
+ const ENCRYPTED_RETURN_TYPE_INTERNAL_TYPES = [
114
+ 'ebool',
115
+ 'euint8',
116
+ 'euint16',
117
+ 'euint32',
118
+ 'euint64',
119
+ 'euint128',
120
+ 'eaddress',
121
+ ] as const;
122
+ type EncryptedReturnTypeInternalType = (typeof ENCRYPTED_RETURN_TYPE_INTERNAL_TYPES)[number];
123
+
124
+ type EncryptedReturnTypeInternalTypeToReturnTypeMap<T extends EncryptedReturnTypeInternalType> = T extends 'ebool'
125
+ ? EBool
126
+ : T extends 'euint8'
127
+ ? EUint8
128
+ : T extends 'euint16'
129
+ ? EUint16
130
+ : T extends 'euint32'
131
+ ? EUint32
132
+ : T extends 'euint64'
133
+ ? EUint64
134
+ : T extends 'euint128'
135
+ ? EUint128
136
+ : T extends 'eaddress'
137
+ ? EAddress
138
+ : never;
139
+
140
+ function transformSingleEncryptedReturnTypeToReturnType<T extends EncryptedReturnTypeInternalType>(
141
+ internalType: T,
142
+ data: bigint
143
+ ): EncryptedReturnTypeInternalTypeToReturnTypeMap<T> {
144
+ switch (internalType) {
145
+ case 'ebool':
146
+ return {
147
+ ctHash: data,
148
+ utype: FheTypes.Bool,
149
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
150
+ case 'euint8':
151
+ return {
152
+ ctHash: data,
153
+ utype: FheTypes.Uint8,
154
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
155
+ case 'euint16':
156
+ return {
157
+ ctHash: data,
158
+ utype: FheTypes.Uint16,
159
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
160
+ case 'euint32':
161
+ return {
162
+ ctHash: data,
163
+ utype: FheTypes.Uint32,
164
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
165
+ case 'euint64':
166
+ return {
167
+ ctHash: data,
168
+ utype: FheTypes.Uint64,
169
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
170
+ case 'euint128':
171
+ return {
172
+ ctHash: data,
173
+ utype: FheTypes.Uint128,
174
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
175
+ case 'eaddress':
176
+ return {
177
+ ctHash: data,
178
+ utype: FheTypes.Uint160,
179
+ } as EncryptedReturnTypeInternalTypeToReturnTypeMap<T>;
180
+ default:
181
+ throw new Error(`Unknown encrypted return type: ${internalType}`);
182
+ }
183
+ }
184
+
185
+ function transformArrayOfEncryptedReturnTypesToReturnTypes<T extends EncryptedReturnTypeInternalType>(
186
+ internalType: T,
187
+ size: string | undefined,
188
+ data: bigint[]
189
+ ): EncryptedReturnTypeInternalTypeToReturnTypeMap<T>[] {
190
+ // Ensure data is an array
191
+ if (!Array.isArray(data)) {
192
+ throw new Error('Data must be an array');
193
+ }
194
+
195
+ // Ensure length of fixed length tuple matches the length of the data array
196
+ if (size != null && size !== '' && parseInt(size) !== data.length) {
197
+ throw new Error(`Array size mismatch: ${size} !== ${data.length}`);
198
+ }
199
+
200
+ // Transform each item in the data array into an return type
201
+ return data.map((item) => transformSingleEncryptedReturnTypeToReturnType(internalType, item));
202
+ }
203
+
204
+ function internalTypeIsEncryptedReturnType(internalType: string): internalType is EncryptedReturnTypeInternalType {
205
+ return ENCRYPTED_RETURN_TYPE_INTERNAL_TYPES.includes(internalType as any);
206
+ }
207
+
208
+ export function transformEncryptedReturnTypes<TAbi extends Abi, TFunctionName extends string>(
209
+ abi: TAbi,
210
+ functionName: TFunctionName,
211
+ data: ContractReturnType<TAbi, TFunctionName>
212
+ ): CofheReturnType<TAbi, TFunctionName> {
213
+ const abiFunction = getAbiFunction(abi, functionName);
214
+ const outputs = abiFunction?.outputs;
215
+ if (abiFunction == null || outputs == null) {
216
+ throw new Error(`Function ${functionName} not found in ABI`);
217
+ }
218
+ const outputsLength = outputs.length;
219
+
220
+ function processParameter(param: AbiParameter, value: unknown): unknown {
221
+ const [typeHead, typeSize] = extractArrayParameterType(param.type);
222
+ const [internalTypeHead, internalTypeSize] = extractArrayParameterType(param.internalType);
223
+
224
+ // Is encrypted return type
225
+ if (internalTypeHead != null && internalTypeIsEncryptedReturnType(internalTypeHead)) {
226
+ // Is single encrypted return type
227
+ if (internalTypeSize == null) {
228
+ return transformSingleEncryptedReturnTypeToReturnType(internalTypeHead, value as bigint);
229
+ }
230
+
231
+ // Is array of encrypted return types
232
+ if (internalTypeSize != null) {
233
+ console.log('array of encrypted return types', internalTypeHead, internalTypeSize, value);
234
+ return transformArrayOfEncryptedReturnTypesToReturnTypes(internalTypeHead, internalTypeSize, value as bigint[]);
235
+ }
236
+ }
237
+
238
+ // Tuple but not an encrypted return type (recursive case)
239
+ if (typeHead === 'tuple') {
240
+ if ('components' in param && Array.isArray(param.components)) {
241
+ const valueObj = value as Record<string, unknown>;
242
+ const result: Record<string, unknown> = {};
243
+
244
+ param.components.forEach((component) => {
245
+ const componentName = component.name;
246
+ if (componentName) {
247
+ const componentValue = valueObj[componentName];
248
+ if (componentValue !== undefined) {
249
+ result[componentName] = processParameter(component, componentValue);
250
+ }
251
+ }
252
+ });
253
+
254
+ return result;
255
+ }
256
+
257
+ return value;
258
+ }
259
+
260
+ // Not an encrypted return type, return original value
261
+ return value;
262
+ }
263
+
264
+ // Process results (array case)
265
+ if (outputsLength > 1) {
266
+ if (!Array.isArray(data)) {
267
+ throw new Error('Data must be an array');
268
+ }
269
+ if (outputsLength !== data.length) {
270
+ throw new Error(`Mismatch in outputs length: ${outputsLength} !== ${data.length}`);
271
+ }
272
+ return data.map((item, index) => {
273
+ return processParameter(outputs[index], item);
274
+ }) as CofheReturnType<TAbi, TFunctionName>;
275
+ }
276
+
277
+ // Process retuls (single item case)
278
+ return processParameter(outputs[0], data) as CofheReturnType<TAbi, TFunctionName>;
279
+ }
@@ -0,0 +1,162 @@
1
+ import type {
2
+ EncryptedAddressInput,
3
+ EncryptedBoolInput,
4
+ EncryptedUint128Input,
5
+ EncryptedUint16Input,
6
+ EncryptedUint32Input,
7
+ EncryptedUint64Input,
8
+ EncryptedUint8Input,
9
+ FheTypes,
10
+ } from '@cofhe/sdk';
11
+ import type {
12
+ AbiParameter,
13
+ AbiParameterKind,
14
+ AbiTypeToPrimitiveType,
15
+ SolidityTuple,
16
+ ResolvedRegister,
17
+ SolidityFixedArraySizeLookup,
18
+ } from 'abitype';
19
+ import type { AbiBasicType, Error, Merge, Tuple, MaybeExtractArrayParameterType } from './utils';
20
+
21
+ export type EBool = {
22
+ ctHash: bigint;
23
+ utype: FheTypes.Bool;
24
+ };
25
+ export type EUint8 = {
26
+ ctHash: bigint;
27
+ utype: FheTypes.Uint8;
28
+ };
29
+ export type EUint16 = {
30
+ ctHash: bigint;
31
+ utype: FheTypes.Uint16;
32
+ };
33
+ export type EUint32 = {
34
+ ctHash: bigint;
35
+ utype: FheTypes.Uint32;
36
+ };
37
+ export type EUint64 = {
38
+ ctHash: bigint;
39
+ utype: FheTypes.Uint64;
40
+ };
41
+ export type EUint128 = {
42
+ ctHash: bigint;
43
+ utype: FheTypes.Uint128;
44
+ };
45
+ export type EAddress = {
46
+ ctHash: bigint;
47
+ utype: FheTypes.Uint160;
48
+ };
49
+ export type EncryptedReturnType = EBool | EUint8 | EUint16 | EUint32 | EUint64 | EUint128 | EAddress;
50
+
51
+ /**
52
+ * Narrows {@link EncryptedReturnType} to the specific member matching a given `utype`.
53
+ *
54
+ * @example
55
+ * type T = EncryptedReturnTypeByUtype<FheTypes.Uint32> // EUint32
56
+ */
57
+ export type EncryptedReturnTypeByUtype<U extends FheTypes> = Extract<EncryptedReturnType, { utype: U }>;
58
+
59
+ export type FhenixInternalTypeMap = {
60
+ // Input Structs
61
+ 'struct InEbool': EncryptedBoolInput;
62
+ 'struct InEuint8': EncryptedUint8Input;
63
+ 'struct InEuint16': EncryptedUint16Input;
64
+ 'struct InEuint32': EncryptedUint32Input;
65
+ 'struct InEuint64': EncryptedUint64Input;
66
+ 'struct InEuint128': EncryptedUint128Input;
67
+ 'struct InEaddress': EncryptedAddressInput;
68
+
69
+ // Exposed encrypted primitives
70
+ ebool: EBool;
71
+ euint8: EUint8;
72
+ euint16: EUint16;
73
+ euint32: EUint32;
74
+ euint64: EUint64;
75
+ euint128: EUint128;
76
+ eaddress: EAddress;
77
+ };
78
+
79
+ export type FhenixInternalTypeMapUnion = keyof FhenixInternalTypeMap;
80
+
81
+ export type CofheAbiParameterToPrimitiveType<
82
+ abiParameter extends AbiParameter | { name: string; type: unknown; internalType?: unknown },
83
+ abiParameterKind extends AbiParameterKind = AbiParameterKind,
84
+ // 1. Check to see if type is basic (not tuple or array) and can be looked up immediately.
85
+ > = abiParameter['internalType'] extends FhenixInternalTypeMapUnion
86
+ ? FhenixInternalTypeMap[abiParameter['internalType']]
87
+ : abiParameter['type'] extends AbiBasicType
88
+ ? AbiTypeToPrimitiveType<abiParameter['type'], abiParameterKind>
89
+ : // 2. Check if type is tuple and covert each component
90
+ abiParameter extends {
91
+ type: SolidityTuple;
92
+ components: infer components extends readonly AbiParameter[];
93
+ }
94
+ ? CofheAbiComponentsToPrimitiveType<components, abiParameterKind>
95
+ : // 2.5 Check if type is array of fhenix types (struct InEuint32[2])
96
+ MaybeExtractArrayParameterType<abiParameter['internalType']> extends [
97
+ infer head extends FhenixInternalTypeMapUnion,
98
+ infer size,
99
+ ]
100
+ ? CofheArrayToPrimitiveType<head, size>
101
+ : // 3. Check if type is array.
102
+ MaybeExtractArrayParameterType<abiParameter['type']> extends [infer head extends string, infer size]
103
+ ? CofheAbiArrayToPrimitiveType<abiParameter, abiParameterKind, head, size>
104
+ : // 4. If type is not basic, tuple, or array, we don't know what the type is.
105
+ // This can happen when a fixed-length array is out of range (`Size` doesn't exist in `SolidityFixedArraySizeLookup`),
106
+ // the array has depth greater than `ResolvedRegister['arrayMaxDepth']`, etc.
107
+ ResolvedRegister['strictAbiType'] extends true
108
+ ? Error<`Unknown type '${abiParameter['type'] & string}'.`>
109
+ : // 5. If we've gotten this far, let's check for errors in tuple components.
110
+ // (Happens for recursive tuple typed data types.)
111
+ abiParameter extends { components: Error<string> }
112
+ ? abiParameter['components']
113
+ : unknown;
114
+
115
+ export type CofheAbiParametersToPrimitiveTypes<
116
+ abiParameters extends readonly AbiParameter[],
117
+ abiParameterKind extends AbiParameterKind = AbiParameterKind,
118
+ > = {
119
+ [key in keyof abiParameters]: CofheAbiParameterToPrimitiveType<abiParameters[key], abiParameterKind>;
120
+ };
121
+
122
+ type CofheAbiComponentsToPrimitiveType<
123
+ components extends readonly AbiParameter[],
124
+ abiParameterKind extends AbiParameterKind,
125
+ > = components extends readonly []
126
+ ? []
127
+ : // Compare the original set of names to a "validated"
128
+ // set where each name is coerced to a string and undefined|"" are excluded
129
+ components[number]['name'] extends Exclude<components[number]['name'] & string, undefined | ''>
130
+ ? // If all the original names are present, all tuple parameters are named so return as object
131
+ {
132
+ [component in components[number] as component['name'] & {}]: CofheAbiParameterToPrimitiveType<
133
+ component,
134
+ abiParameterKind
135
+ >;
136
+ }
137
+ : // Otherwise, has unnamed tuple parameters so return as array
138
+ {
139
+ [key in keyof components]: CofheAbiParameterToPrimitiveType<components[key], abiParameterKind>;
140
+ };
141
+
142
+ type CofheArrayToPrimitiveType<
143
+ head extends FhenixInternalTypeMapUnion,
144
+ size,
145
+ > = size extends keyof SolidityFixedArraySizeLookup
146
+ ? Tuple<FhenixInternalTypeMap[head], SolidityFixedArraySizeLookup[size]>
147
+ : readonly FhenixInternalTypeMap[head][];
148
+
149
+ type CofheAbiArrayToPrimitiveType<
150
+ abiParameter extends AbiParameter | { name: string; type: unknown },
151
+ abiParameterKind extends AbiParameterKind,
152
+ head extends string,
153
+ size,
154
+ > = size extends keyof SolidityFixedArraySizeLookup
155
+ ? // Check if size is within range for fixed-length arrays, if so create a tuple.
156
+ Tuple<
157
+ CofheAbiParameterToPrimitiveType<Merge<abiParameter, { type: head }>, abiParameterKind>,
158
+ SolidityFixedArraySizeLookup[size]
159
+ >
160
+ : // Otherwise, create an array. Tuples and arrays are created with `[${Size}]` popped off the end
161
+ // and passed back into the function to continue reducing down to the basic types found in Step 1.
162
+ readonly CofheAbiParameterToPrimitiveType<Merge<abiParameter, { type: head }>, abiParameterKind>[];
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './encryptedInputs';
2
+ export * from './encryptedReturnTypes';
3
+ export * from './fhenixMap';
4
+ export type { Abi } from 'abitype';
5
+ export type { ContractReturnType } from './utils';
6
+ export { transformEncryptedReturnTypes } from './encryptedReturnTypes';
@@ -0,0 +1,86 @@
1
+ import {
2
+ FheTypes,
3
+ type EncryptableItem,
4
+ type EncryptableToEncryptedItemInputMap,
5
+ type EncryptedAddressInput,
6
+ type EncryptedBoolInput,
7
+ type EncryptedItemInput,
8
+ type EncryptedItemInputs,
9
+ type EncryptedUint128Input,
10
+ type EncryptedUint16Input,
11
+ type EncryptedUint32Input,
12
+ type EncryptedUint64Input,
13
+ type EncryptedUint8Input,
14
+ } from '@cofhe/sdk';
15
+
16
+ /**
17
+ * Generates a mock ctHash from the encryptable data.
18
+ * This is a simple deterministic hash function for testing purposes.
19
+ */
20
+ export function generateMockCtHash(data: unknown): bigint {
21
+ if (typeof data === 'boolean') {
22
+ return BigInt(data ? 1 : 0);
23
+ }
24
+ if (typeof data === 'bigint') {
25
+ return data;
26
+ }
27
+ if (typeof data === 'string') {
28
+ // Simple hash: convert string to number and create a bigint
29
+ let hash = 0n;
30
+ for (let i = 0; i < data.length; i++) {
31
+ const char = data.charCodeAt(i);
32
+ hash = (hash << 5n) - hash + BigInt(char);
33
+ hash = hash & hash; // Convert to 32-bit integer
34
+ }
35
+ return hash < 0n ? -hash : hash;
36
+ }
37
+ // Fallback: use a simple hash based on string representation
38
+ return BigInt(
39
+ Math.abs(
40
+ JSON.stringify(data)
41
+ .split('')
42
+ .reduce((a, b) => {
43
+ a = (a << 5) - a + b.charCodeAt(0);
44
+ return a & a;
45
+ }, 0)
46
+ )
47
+ );
48
+ }
49
+
50
+ /**
51
+ * Generates a mock signature for testing purposes.
52
+ * Returns a hex string that looks like a valid signature.
53
+ */
54
+ function generateMockSignature(): `0x${string}` {
55
+ return '0xMockSignature';
56
+ }
57
+
58
+ export function mockEncryptEncryptable<T extends EncryptableItem>(encryptable: T): EncryptedItemInputs<T> {
59
+ const ctHash = generateMockCtHash(encryptable.data);
60
+ const signature = generateMockSignature();
61
+
62
+ return {
63
+ ctHash,
64
+ securityZone: 0,
65
+ utype: encryptable.utype,
66
+ signature,
67
+ } as EncryptedItemInputs<T>;
68
+ }
69
+
70
+ /**
71
+ * Converts an EncryptableItem to a mock EncryptedItemInput.
72
+ * This is useful for testing and development when you don't need actual encryption.
73
+ *
74
+ * @param encryptable - The EncryptableItem to convert
75
+ * @returns A mock EncryptedItemInput with the same utype and securityZone, but with mock ctHash and signature
76
+ *
77
+ * @example
78
+ * const encryptable = Encryptable.uint32(100n);
79
+ * const mockEncrypted = mockEncryptedInput(encryptable);
80
+ * // Returns: { ctHash: 100n, securityZone: 0, utype: FheTypes.Uint32, signature: "0x..." }
81
+ */
82
+ export function mockEncrypt<T extends EncryptableItem[]>(
83
+ encryptables: [...T] | readonly [...T]
84
+ ): [...EncryptedItemInputs<T>] {
85
+ return encryptables.map(mockEncryptEncryptable) as [...EncryptedItemInputs<[...T]>];
86
+ }
@@ -0,0 +1,139 @@
1
+ import {
2
+ FheTypes,
3
+ type EncryptableItem,
4
+ type EncryptedAddressInput,
5
+ type EncryptedBoolInput,
6
+ type EncryptedItemInput,
7
+ type EncryptedUint128Input,
8
+ type EncryptedUint16Input,
9
+ type EncryptedUint32Input,
10
+ type EncryptedUint64Input,
11
+ type EncryptedUint8Input,
12
+ } from '@cofhe/sdk';
13
+
14
+ /**
15
+ * Generates a mock ctHash from the encryptable data.
16
+ * This is a simple deterministic hash function for testing purposes.
17
+ */
18
+ function generateMockCtHash(data: unknown): bigint {
19
+ if (typeof data === 'boolean') {
20
+ return BigInt(data ? 1 : 0);
21
+ }
22
+ if (typeof data === 'bigint') {
23
+ return data;
24
+ }
25
+ if (typeof data === 'string') {
26
+ // Simple hash: convert string to number and create a bigint
27
+ let hash = 0n;
28
+ for (let i = 0; i < data.length; i++) {
29
+ const char = data.charCodeAt(i);
30
+ hash = (hash << 5n) - hash + BigInt(char);
31
+ hash = hash & hash; // Convert to 32-bit integer
32
+ }
33
+ return hash < 0n ? -hash : hash;
34
+ }
35
+ // Fallback: use a simple hash based on string representation
36
+ return BigInt(
37
+ Math.abs(
38
+ JSON.stringify(data)
39
+ .split('')
40
+ .reduce((a, b) => {
41
+ a = (a << 5) - a + b.charCodeAt(0);
42
+ return a & a;
43
+ }, 0)
44
+ )
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Generates a mock signature for testing purposes.
50
+ * Returns a hex string that looks like a valid signature.
51
+ */
52
+ function generateMockSignature(): `0x${string}` {
53
+ // Generate a 64-character hex string (32 bytes)
54
+ const hexChars = '0123456789abcdef';
55
+ let signature = '0x';
56
+ for (let i = 0; i < 64; i++) {
57
+ signature += hexChars[Math.floor(Math.random() * hexChars.length)];
58
+ }
59
+ return signature as `0x${string}`;
60
+ }
61
+
62
+ /**
63
+ * Converts an EncryptableItem to a mock EncryptedItemInput.
64
+ * This is useful for testing and development when you don't need actual encryption.
65
+ *
66
+ * @param encryptable - The EncryptableItem to convert
67
+ * @returns A mock EncryptedItemInput with the same utype and securityZone, but with mock ctHash and signature
68
+ *
69
+ * @example
70
+ * const encryptable = Encryptable.uint32(100n);
71
+ * const mockEncrypted = mockEncryptedInput(encryptable);
72
+ * // Returns: { ctHash: 100n, securityZone: 0, utype: FheTypes.Uint32, signature: "0x..." }
73
+ */
74
+ export function mockEncryptedInput<T extends EncryptableItem>(encryptable: T): EncryptedItemInput {
75
+ const ctHash = generateMockCtHash(encryptable.data);
76
+ const signature = generateMockSignature();
77
+
78
+ // Map based on utype to return the correct specific type
79
+ switch (encryptable.utype) {
80
+ case FheTypes.Bool:
81
+ return {
82
+ ctHash,
83
+ securityZone: 0,
84
+ utype: FheTypes.Bool,
85
+ signature,
86
+ } as EncryptedBoolInput;
87
+
88
+ case FheTypes.Uint8:
89
+ return {
90
+ ctHash,
91
+ securityZone: 0,
92
+ utype: FheTypes.Uint8,
93
+ signature,
94
+ } as EncryptedUint8Input;
95
+
96
+ case FheTypes.Uint16:
97
+ return {
98
+ ctHash,
99
+ securityZone: 0,
100
+ utype: FheTypes.Uint16,
101
+ signature,
102
+ } as EncryptedUint16Input;
103
+
104
+ case FheTypes.Uint32:
105
+ return {
106
+ ctHash,
107
+ securityZone: 0,
108
+ utype: FheTypes.Uint32,
109
+ signature,
110
+ } as EncryptedUint32Input;
111
+
112
+ case FheTypes.Uint64:
113
+ return {
114
+ ctHash,
115
+ securityZone: 0,
116
+ utype: FheTypes.Uint64,
117
+ signature,
118
+ } as EncryptedUint64Input;
119
+
120
+ case FheTypes.Uint128:
121
+ return {
122
+ ctHash,
123
+ securityZone: 0,
124
+ utype: FheTypes.Uint128,
125
+ signature,
126
+ } as EncryptedUint128Input;
127
+
128
+ case FheTypes.Uint160:
129
+ return {
130
+ ctHash,
131
+ securityZone: 0,
132
+ utype: FheTypes.Uint160,
133
+ signature,
134
+ } as EncryptedAddressInput;
135
+
136
+ default:
137
+ throw new Error(`Unsupported encryptable: ${encryptable}`);
138
+ }
139
+ }