@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.
- package/CHANGELOG.md +13 -0
- package/README.md +184 -0
- package/package.json +54 -0
- package/src/encryptedInputs.ts +451 -0
- package/src/encryptedReturnTypes.ts +279 -0
- package/src/fhenixMap.ts +162 -0
- package/src/index.ts +6 -0
- package/src/mockEncrypt.ts +86 -0
- package/src/mockEncryptedInput.ts +139 -0
- package/src/utils.ts +205 -0
|
@@ -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
|
+
}
|
package/src/fhenixMap.ts
ADDED
|
@@ -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
|
+
}
|