import { EncryptedBoolInput, EncryptedUint8Input, EncryptedUint16Input, EncryptedUint32Input, EncryptedUint64Input, EncryptedUint128Input, EncryptedAddressInput, FheTypes, Primitive, LiteralToPrimitive, EncryptedItemInput, EncryptableBool, EncryptableUint8, EncryptableUint16, EncryptableUint32, EncryptableUint64, EncryptableUint128, EncryptableAddress, EncryptableItem } from '@cofhe/sdk';
import { Abi, AbiFunction, ExtractAbiFunction, AbiParametersToPrimitiveTypes, AbiParameter, AbiType, SolidityTuple, SolidityArray, SolidityFixedArrayRange, ResolvedRegister, Address, AbiParameterKind, AbiTypeToPrimitiveType, SolidityFixedArraySizeLookup } from 'abitype';
export { Abi } from 'abitype';

type ContractReturnType<abi extends Abi | readonly unknown[] = Abi, functionName extends string = string, args extends readonly unknown[] | undefined = readonly unknown[] | undefined, abiFunction extends AbiFunction = (abi extends Abi ? ExtractAbiFunction<abi, functionName> : AbiFunction) extends infer abiFunction_ extends AbiFunction ? IsUnion<abiFunction_> extends true ? UnionToTuple<abiFunction_> extends infer abiFunctions extends readonly AbiFunction[] ? {
    [K in keyof abiFunctions]: (readonly unknown[] | undefined extends args ? readonly [] : args) extends AbiParametersToPrimitiveTypes<abiFunctions[K]['inputs'], 'inputs'> ? abiFunctions[K] : never;
}[number] : never : abiFunction_ : never, outputs extends readonly AbiParameter[] = abiFunction['outputs'], primitiveTypes extends readonly unknown[] = AbiParametersToPrimitiveTypes<outputs, 'outputs', true>> = [abiFunction] extends [never] ? unknown : readonly unknown[] extends primitiveTypes ? unknown : primitiveTypes extends readonly [] ? void : primitiveTypes extends readonly [infer primitiveType] ? primitiveType : primitiveTypes;
type Error<messages extends string | string[]> = messages extends string ? [
    `Error: ${messages}`
] : {
    [key in keyof messages]: messages[key] extends infer message extends string ? `Error: ${message}` : never;
};
type PartialBy<TType, TKeys extends keyof TType> = ExactPartial<Pick<TType, TKeys>> & Omit<TType, TKeys>;
type ExactPartial<T> = {
    [K in keyof T]?: T[K] | undefined;
};
type MaybePartialBy<TType, TKeys extends string> = TKeys extends keyof TType ? PartialBy<TType, TKeys> : TType;
type ReadonlyWiden<TType> = (TType extends Function ? TType : never) | (TType extends ResolvedRegister['bigIntType'] ? bigint : never) | (TType extends boolean ? boolean : never) | (TType extends ResolvedRegister['intType'] ? number : never) | (TType extends string ? TType extends Address ? Address : TType extends ResolvedRegister['bytesType']['inputs'] ? ResolvedRegister['bytesType'] : string : never) | (TType extends readonly [] ? readonly [] : never) | (TType extends Record<string, unknown> ? {
    [K in keyof TType]: ReadonlyWiden<TType[K]>;
} : never) | (TType extends {
    length: number;
} ? {
    [K in keyof TType]: ReadonlyWiden<TType[K]>;
} extends infer Val extends unknown[] ? readonly [...Val] : never : never);
type AbiBasicType = Exclude<AbiType, SolidityTuple | SolidityArray>;
/**
 * First, infer `Head` against a known size type (either fixed-length array value or `""`).
 *
 * | Input           | Head         |
 * | --------------- | ------------ |
 * | `string[]`      | `string`     |
 * | `string[][][3]` | `string[][]` |
 */
type MaybeExtractArrayParameterType<type> = type extends `${infer head}[${'' | `${SolidityFixedArrayRange}`}]` ? type extends `${head}[${infer size}]` ? [head, size] : undefined : undefined;
type IsUnion<T, C = T> = T extends C ? ([C] extends [T] ? false : true) : never;
type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, Last>>, Last];
type LastInUnion<U> = UnionToIntersection<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never;
type UnionToIntersection<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never;
/**
 * Create tuple of {@link type} type with {@link size} size
 *
 * @param Type - Type of tuple
 * @param Size - Size of tuple
 * @returns Tuple of {@link type} type with {@link size} size
 *
 * @example
 * type Result = Tuple<string, 2>
 * //   ^? type Result = [string, string]
 */
type Tuple<type, size extends number> = size extends size ? number extends size ? type[] : _TupleOf<type, size, []> : never;
type _TupleOf<length, size extends number, acc extends readonly unknown[]> = acc['length'] extends size ? acc : _TupleOf<length, size, readonly [length, ...acc]>;
/**
 * Merges two object types into new type
 *
 * @param object1 - Object to merge into
 * @param object2 - Object to merge and override keys from {@link object1}
 * @returns New object type with keys from {@link object1} and {@link object2}. If a key exists in both {@link object1} and {@link object2}, the key from {@link object2} will be used.
 *
 * @example
 * type Result = Merge<{ foo: string }, { foo: number; bar: string }>
 * //   ^? type Result = { foo: number; bar: string }
 */
type Merge<object1, object2> = Omit<object1, keyof object2> & object2;

type EBool = {
    ctHash: string;
    utype: FheTypes.Bool;
};
type EUint8 = {
    ctHash: string;
    utype: FheTypes.Uint8;
};
type EUint16 = {
    ctHash: string;
    utype: FheTypes.Uint16;
};
type EUint32 = {
    ctHash: string;
    utype: FheTypes.Uint32;
};
type EUint64 = {
    ctHash: string;
    utype: FheTypes.Uint64;
};
type EUint128 = {
    ctHash: string;
    utype: FheTypes.Uint128;
};
type EAddress = {
    ctHash: string;
    utype: FheTypes.Uint160;
};
type EncryptedReturnType = EBool | EUint8 | EUint16 | EUint32 | EUint64 | EUint128 | EAddress;
/**
 * Narrows {@link EncryptedReturnType} to the specific member matching a given `utype`.
 *
 * @example
 * type T = EncryptedReturnTypeByUtype<FheTypes.Uint32> // EUint32
 */
type EncryptedReturnTypeByUtype<U extends FheTypes> = Extract<EncryptedReturnType, {
    utype: U;
}>;
type FhenixInternalTypeMap = {
    'struct InEbool': EncryptedBoolInput;
    'struct InEuint8': EncryptedUint8Input;
    'struct InEuint16': EncryptedUint16Input;
    'struct InEuint32': EncryptedUint32Input;
    'struct InEuint64': EncryptedUint64Input;
    'struct InEuint128': EncryptedUint128Input;
    'struct InEaddress': EncryptedAddressInput;
    ebool: EBool;
    euint8: EUint8;
    euint16: EUint16;
    euint32: EUint32;
    euint64: EUint64;
    euint128: EUint128;
    eaddress: EAddress;
};
type FhenixInternalTypeMapUnion = keyof FhenixInternalTypeMap;
type CofheAbiParameterToPrimitiveType<abiParameter extends AbiParameter | {
    name: string;
    type: unknown;
    internalType?: unknown;
}, abiParameterKind extends AbiParameterKind = AbiParameterKind> = abiParameter['internalType'] extends FhenixInternalTypeMapUnion ? FhenixInternalTypeMap[abiParameter['internalType']] : abiParameter['type'] extends AbiBasicType ? AbiTypeToPrimitiveType<abiParameter['type'], abiParameterKind> : abiParameter extends {
    type: SolidityTuple;
    components: infer components extends readonly AbiParameter[];
} ? CofheAbiComponentsToPrimitiveType<components, abiParameterKind> : MaybeExtractArrayParameterType<abiParameter['internalType']> extends [
    infer head extends FhenixInternalTypeMapUnion,
    infer size
] ? CofheArrayToPrimitiveType<head, size> : MaybeExtractArrayParameterType<abiParameter['type']> extends [infer head extends string, infer size] ? CofheAbiArrayToPrimitiveType<abiParameter, abiParameterKind, head, size> : ResolvedRegister['strictAbiType'] extends true ? Error<`Unknown type '${abiParameter['type'] & string}'.`> : abiParameter extends {
    components: Error<string>;
} ? abiParameter['components'] : unknown;
type CofheAbiParametersToPrimitiveTypes<abiParameters extends readonly AbiParameter[], abiParameterKind extends AbiParameterKind = AbiParameterKind> = {
    [key in keyof abiParameters]: CofheAbiParameterToPrimitiveType<abiParameters[key], abiParameterKind>;
};
type CofheAbiComponentsToPrimitiveType<components extends readonly AbiParameter[], abiParameterKind extends AbiParameterKind> = components extends readonly [] ? [] : components[number]['name'] extends Exclude<components[number]['name'] & string, undefined | ''> ? {
    [component in components[number] as component['name'] & {}]: CofheAbiParameterToPrimitiveType<component, abiParameterKind>;
} : {
    [key in keyof components]: CofheAbiParameterToPrimitiveType<components[key], abiParameterKind>;
};
type CofheArrayToPrimitiveType<head extends FhenixInternalTypeMapUnion, size> = size extends keyof SolidityFixedArraySizeLookup ? Tuple<FhenixInternalTypeMap[head], SolidityFixedArraySizeLookup[size]> : readonly FhenixInternalTypeMap[head][];
type CofheAbiArrayToPrimitiveType<abiParameter extends AbiParameter | {
    name: string;
    type: unknown;
}, abiParameterKind extends AbiParameterKind, head extends string, size> = size extends keyof SolidityFixedArraySizeLookup ? Tuple<CofheAbiParameterToPrimitiveType<Merge<abiParameter, {
    type: head;
}>, abiParameterKind>, SolidityFixedArraySizeLookup[size]> : readonly CofheAbiParameterToPrimitiveType<Merge<abiParameter, {
    type: head;
}>, abiParameterKind>[];

type CofheInputArgs<abi extends Abi | readonly unknown[] = Abi, functionName extends string = string> = GetArgs<abi, functionName>['args'];
type EncryptedInputToInputMap<E extends EncryptedItemInput> = E extends EncryptedBoolInput ? EncryptableBool['data'] : E extends EncryptedUint8Input ? EncryptableUint8['data'] : E extends EncryptedUint16Input ? EncryptableUint16['data'] : E extends EncryptedUint32Input ? EncryptableUint32['data'] : E extends EncryptedUint64Input ? EncryptableUint64['data'] : E extends EncryptedUint128Input ? EncryptableUint128['data'] : E extends EncryptedAddressInput ? EncryptableAddress['data'] : never;
type EncryptedInputsToInputs<T> = T extends Primitive ? LiteralToPrimitive<T> : T extends EncryptedItemInput ? EncryptedInputToInputMap<T> : {
    [K in keyof T]: EncryptedInputsToInputs<T[K]>;
};
type CofheInputArgsPreTransform<abi extends Abi | readonly unknown[] = Abi, functionName extends string = string> = EncryptedInputsToInputs<CofheInputArgs<abi, functionName>>;
type GetArgs<abi extends Abi | readonly unknown[] = Abi, // `readonly unknown[]` allows for non-const asserted types
functionName extends string = string, args extends readonly unknown[] | undefined = readonly [], abiFunction extends AbiFunction = abi extends Abi ? ExtractAbiFunction<abi, functionName> : AbiFunction, primitiveTypes = CofheAbiParametersToPrimitiveTypes<abiFunction['inputs']>, args_ = primitiveTypes | (abi extends Abi ? args extends primitiveTypes ? primitiveTypes extends args ? ReadonlyWiden<args> : never : never : never) | (Abi extends abi ? readonly unknown[] : never)> = MaybePartialBy<{
    args: args_;
}, readonly [] extends primitiveTypes ? 'args' : Abi extends abi ? 'args' : string>;
/**
 * Extracts encryptable values from function arguments based on the ABI.
 * Transforms raw data values into EncryptableItem objects that can be passed to the encrypt function.
 *
 * @param abi - The ABI containing the function definition
 * @param functionName - Name of the function
 * @param args - Function arguments in the format of CofheInputArgsPreTransform (raw data values)
 * @returns Array of EncryptableItem objects ready for encryption
 */
declare function extractEncryptableValues<TAbi extends Abi, TFunctionName extends string>(abi: TAbi, functionName: TFunctionName, args: CofheInputArgsPreTransform<TAbi, TFunctionName>): EncryptableItem[];
/**
 * Re-inserts encrypted values back into function arguments based on the ABI.
 * Takes the extracted values (now encrypted) and the original args structure, and replaces
 * the encryptable values with their encrypted counterparts.
 *
 * This function mirrors the extraction logic in extractEncryptableValues, ensuring values
 * are inserted in the exact same order and locations where they were extracted.
 *
 * @param abi - The ABI containing the function definition
 * @param functionName - Name of the function
 * @param args - Original function arguments in the format of CofheInputArgsPreTransform
 * @param encryptedValues - Encrypted values in the same order as returned by extractEncryptableValues
 * @returns Function arguments with encrypted values inserted (format of CofheInputArgs)
 */
declare function insertEncryptedValues<TAbi extends Abi, TFunctionName extends string>(abi: TAbi, functionName: TFunctionName, args: CofheInputArgsPreTransform<TAbi, TFunctionName>, encryptedValues: readonly EncryptedItemInput[]): CofheInputArgs<TAbi, TFunctionName>;

type FirstCofheReturnValue<T> = [T] extends [void] ? never : T extends readonly [infer Head, ...(readonly unknown[])] ? Head : T;
type FheTypeFromCofheReturnValue<T> = T extends {
    utype: infer U;
} ? U : T extends readonly (infer Element)[] ? FheTypeFromCofheReturnValue<Element> : never;
/**
 * Extracts the `FheTypes` of the first returned value of a CoFHE call.
 *
 * Examples:
 * - `returns (ebool)` -> `FheTypes.Bool`
 * - `returns (euint8, euint64)` -> `FheTypes.Uint8`
 * - `returns (euint16[])` -> `FheTypes.Uint16`
 */
type CofheFirstReturnFheType<abi extends Abi | readonly unknown[] = Abi, functionName extends string = string, args extends readonly unknown[] | undefined = readonly unknown[] | undefined> = FheTypeFromCofheReturnValue<FirstCofheReturnValue<CofheReturnType<abi, functionName, args>>>;
type CofheReturnType<abi extends Abi | readonly unknown[] = Abi, functionName extends string = string, args extends readonly unknown[] | undefined = readonly unknown[] | undefined, abiFunction extends AbiFunction = (abi extends Abi ? ExtractAbiFunction<abi, functionName> : AbiFunction) extends infer abiFunction_ extends AbiFunction ? IsUnion<abiFunction_> extends true ? UnionToTuple<abiFunction_> extends infer abiFunctions extends readonly AbiFunction[] ? {
    [K in keyof abiFunctions]: (readonly unknown[] | undefined extends args ? readonly [] : args) extends CofheAbiParametersToPrimitiveTypes<abiFunctions[K]['inputs'], 'inputs'> ? abiFunctions[K] : never;
}[number] : never : abiFunction_ : never, outputs extends readonly AbiParameter[] = abiFunction['outputs'], primitiveTypes extends readonly unknown[] = CofheAbiParametersToPrimitiveTypes<outputs, 'outputs'>> = [abiFunction] extends [never] ? unknown : readonly unknown[] extends primitiveTypes ? unknown : primitiveTypes extends readonly [] ? void : primitiveTypes extends readonly [infer primitiveType] ? primitiveType : primitiveTypes;
type EncryptedReturnTypeToReturnTypeMap<E extends EncryptedReturnType> = E extends EBool ? boolean : E extends EUint8 ? bigint : E extends EUint16 ? bigint : E extends EUint32 ? bigint : E extends EUint64 ? bigint : E extends EUint128 ? bigint : E extends EAddress ? string : never;
type EncryptedReturnTypesToReturnTypes<T> = T extends Primitive ? LiteralToPrimitive<T> : T extends EncryptedReturnType ? EncryptedReturnTypeToReturnTypeMap<T> : {
    [K in keyof T]: EncryptedReturnTypesToReturnTypes<T[K]>;
};
type CofheReturnTypePostTransform<abi extends Abi | readonly unknown[] = Abi, functionName extends string = string, args extends readonly unknown[] | undefined = readonly unknown[] | undefined> = EncryptedReturnTypesToReturnTypes<CofheReturnType<abi, functionName, args>>;
declare function transformEncryptedReturnTypes<TAbi extends Abi, TFunctionName extends string>(abi: TAbi, functionName: TFunctionName, data: ContractReturnType<TAbi, TFunctionName>): CofheReturnType<TAbi, TFunctionName>;

export { type CofheAbiParameterToPrimitiveType, type CofheAbiParametersToPrimitiveTypes, type CofheFirstReturnFheType, type CofheInputArgs, type CofheInputArgsPreTransform, type CofheReturnType, type CofheReturnTypePostTransform, type ContractReturnType, type EAddress, type EBool, type EUint128, type EUint16, type EUint32, type EUint64, type EUint8, type EncryptedReturnType, type EncryptedReturnTypeByUtype, type FhenixInternalTypeMap, type FhenixInternalTypeMapUnion, extractEncryptableValues, insertEncryptedValues, transformEncryptedReturnTypes };
