Files
2025-12-27 21:42:23 -08:00

357 lines
11 KiB
TypeScript

import {
Abi,
AbiParameter,
AbiParameterToPrimitiveType,
AbiParametersToPrimitiveTypes,
ExtractAbiEvent,
ExtractAbiEventNames,
ExtractAbiFunction,
} from "abitype";
import type { ExtractAbiFunctionNames } from "abitype";
import type { Simplify } from "type-fest";
import type { MergeDeepRecord } from "type-fest/source/merge-deep";
import {
Address,
Block,
GetEventArgs,
GetTransactionReceiptReturnType,
GetTransactionReturnType,
Log,
TransactionReceipt,
} from "viem";
import { UseContractEventConfig, UseContractReadConfig, UseContractWriteConfig } from "wagmi";
import deployedContractsData from "~~/contracts/deployedContracts";
import externalContractsData from "~~/contracts/externalContracts";
import scaffoldConfig from "~~/scaffold.config";
import {
LuxFHEMappedInputTypes,
LuxFHEUtilsTypeModificationOption,
LuxFHEMappedOutputTypes,
} from "../luxfheUtilsTypes";
type AddExternalFlag<T> = {
[ChainId in keyof T]: {
[ContractName in keyof T[ChainId]]: T[ChainId][ContractName] & { external?: true };
};
};
const deepMergeContracts = <L extends Record<PropertyKey, any>, E extends Record<PropertyKey, any>>(
local: L,
external: E,
) => {
const result: Record<PropertyKey, any> = {};
const allKeys = Array.from(new Set([...Object.keys(external), ...Object.keys(local)]));
for (const key of allKeys) {
if (!external[key]) {
result[key] = local[key];
continue;
}
const amendedExternal = Object.fromEntries(
Object.entries(external[key] as Record<string, Record<string, unknown>>).map(([contractName, declaration]) => [
contractName,
{ ...declaration, external: true },
]),
);
result[key] = { ...local[key], ...amendedExternal };
}
return result as MergeDeepRecord<AddExternalFlag<L>, AddExternalFlag<E>, { arrayMergeMode: "replace" }>;
};
const contractsData = deepMergeContracts(deployedContractsData, externalContractsData);
export type InheritedFunctions = { readonly [key: string]: string };
export type GenericContract = {
address: Address;
abi: Abi;
inheritedFunctions?: InheritedFunctions;
external?: true;
};
export type GenericContractsDeclaration = {
[chainId: number]: {
[contractName: string]: GenericContract;
};
};
export const contracts = contractsData as GenericContractsDeclaration | null;
type ConfiguredChainId = (typeof scaffoldConfig)["targetNetworks"][0]["id"];
type IsContractDeclarationMissing<TYes, TNo> = typeof contractsData extends { [key in ConfiguredChainId]: any }
? TNo
: TYes;
type ContractsDeclaration = IsContractDeclarationMissing<GenericContractsDeclaration, typeof contractsData>;
type Contracts = ContractsDeclaration[ConfiguredChainId];
export type ContractName = keyof Contracts;
export type Contract<TContractName extends ContractName> = Contracts[TContractName];
type InferContractAbi<TContract> = TContract extends { abi: infer TAbi } ? TAbi : never;
export type ContractAbi<TContractName extends ContractName = ContractName> = InferContractAbi<Contract<TContractName>>;
export type AbiFunctionInputs<TAbi extends Abi, TFunctionName extends string> = ExtractAbiFunction<
TAbi,
TFunctionName
>["inputs"];
export type AbiFunctionArguments<TAbi extends Abi, TFunctionName extends string> = AbiParametersToPrimitiveTypes<
AbiFunctionInputs<TAbi, TFunctionName>
>;
export type AbiFunctionOutputs<TAbi extends Abi, TFunctionName extends string> = ExtractAbiFunction<
TAbi,
TFunctionName
>["outputs"];
type Normalize<T> = T extends (...args: infer A) => infer R
? (...args: Normalize<A>) => Normalize<R>
: { [K in keyof T]: Normalize<T[K]> };
export type AbiFunctionReturnType<
TAbi extends Abi,
TFunctionName extends string,
TLuxFHEMapType extends LuxFHEUtilsTypeModificationOption = "raw",
> = LuxFHEMappedOutputTypes<
IsContractDeclarationMissing<
any,
AbiParametersToPrimitiveTypes<AbiFunctionOutputs<TAbi, TFunctionName>> extends readonly [any]
? AbiParametersToPrimitiveTypes<AbiFunctionOutputs<TAbi, TFunctionName>>[0]
: AbiParametersToPrimitiveTypes<AbiFunctionOutputs<TAbi, TFunctionName>>
>,
TLuxFHEMapType
>;
export type AbiEventInputs<TAbi extends Abi, TEventName extends ExtractAbiEventNames<TAbi>> = ExtractAbiEvent<
TAbi,
TEventName
>["inputs"];
export enum ContractCodeStatus {
"LOADING",
"DEPLOYED",
"NOT_FOUND",
}
type AbiStateMutability = "pure" | "view" | "nonpayable" | "payable";
export type ReadAbiStateMutability = "view" | "pure";
export type WriteAbiStateMutability = "nonpayable" | "payable";
export type FunctionNamesWithInputs<
TContractName extends ContractName,
TAbiStateMutibility extends AbiStateMutability = AbiStateMutability,
> = Exclude<
Extract<
ContractAbi<TContractName>[number],
{
type: "function";
stateMutability: TAbiStateMutibility;
}
>,
{
inputs: readonly [];
}
>["name"];
type Expand<T> = T extends object ? (T extends infer O ? { [K in keyof O]: O[K] } : never) : T;
export type UnionToIntersection<U> = Expand<
(U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
>;
export type OptionalTupple<T> = T extends readonly [infer H, ...infer R]
? readonly [H | undefined, ...OptionalTupple<R>]
: T;
export type UseScaffoldArgsParam<
TContractName extends ContractName,
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>>,
TLuxFHEMapType extends LuxFHEUtilsTypeModificationOption = "raw",
> = TFunctionName extends FunctionNamesWithInputs<TContractName>
? {
args: OptionalTupple<
UnionToIntersection<
Normalize<
LuxFHEMappedInputTypes<
// Args
AbiFunctionArguments<ContractAbi<TContractName>, TFunctionName>,
TLuxFHEMapType
>
>
>
>;
}
: {
args?: never;
};
export type UseScaffoldReadConfig<
TContractName extends ContractName,
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>, ReadAbiStateMutability>,
> = {
contractName: TContractName;
} & IsContractDeclarationMissing<
Partial<UseContractReadConfig>,
{
functionName: TFunctionName;
} & UseScaffoldArgsParam<TContractName, TFunctionName> &
Omit<UseContractReadConfig, "chainId" | "abi" | "address" | "functionName" | "args">
>;
export type UseLuxFHEScaffoldReadConfig<
TContractName extends ContractName,
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>, ReadAbiStateMutability>,
> = {
contractName: TContractName;
} & IsContractDeclarationMissing<
Partial<UseContractReadConfig>,
{
functionName: TFunctionName;
} & UseScaffoldArgsParam<TContractName, TFunctionName, "luxfhe-utils-modified"> &
Omit<UseContractReadConfig, "chainId" | "abi" | "address" | "functionName" | "args">
>;
export type UseScaffoldWriteConfig<
TContractName extends ContractName,
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>, WriteAbiStateMutability>,
> = {
contractName: TContractName;
onBlockConfirmation?: (txnReceipt: TransactionReceipt) => void;
blockConfirmations?: number;
} & IsContractDeclarationMissing<
Partial<UseContractWriteConfig>,
{
functionName: TFunctionName;
} & UseScaffoldArgsParam<TContractName, TFunctionName> &
Omit<UseContractWriteConfig, "chainId" | "abi" | "address" | "functionName" | "args" | "mode">
>;
export type UseLuxFHEScaffoldWriteConfig<
TContractName extends ContractName,
TFunctionName extends ExtractAbiFunctionNames<ContractAbi<TContractName>, WriteAbiStateMutability>,
> = {
contractName: TContractName;
onBlockConfirmation?: (txnReceipt: TransactionReceipt) => void;
blockConfirmations?: number;
} & IsContractDeclarationMissing<
Partial<UseContractWriteConfig>,
{
functionName: TFunctionName;
} & UseScaffoldArgsParam<TContractName, TFunctionName, "luxfhe-utils-modified"> &
Omit<UseContractWriteConfig, "chainId" | "abi" | "address" | "functionName" | "args" | "mode">
>;
export type UseScaffoldEventConfig<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
TEvent extends ExtractAbiEvent<ContractAbi<TContractName>, TEventName> = ExtractAbiEvent<
ContractAbi<TContractName>,
TEventName
>,
> = {
contractName: TContractName;
} & IsContractDeclarationMissing<
Omit<UseContractEventConfig, "listener"> & {
listener: (
logs: Simplify<
Omit<Log<bigint, number, any>, "args" | "eventName"> & {
args: Record<string, unknown>;
eventName: string;
}
>[],
) => void;
},
Omit<UseContractEventConfig<ContractAbi<TContractName>, TEventName>, "listener"> & {
listener: (
logs: Simplify<
Omit<Log<bigint, number, false, TEvent, false, [TEvent], TEventName>, "args"> & {
args: AbiParametersToPrimitiveTypes<TEvent["inputs"]> &
GetEventArgs<
ContractAbi<TContractName>,
TEventName,
{
IndexedOnly: false;
}
>;
}
>[],
) => void;
}
>;
type IndexedEventInputs<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
> = Extract<AbiEventInputs<ContractAbi<TContractName>, TEventName>[number], { indexed: true }>;
export type EventFilters<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
> = IsContractDeclarationMissing<
any,
IndexedEventInputs<TContractName, TEventName> extends never
? never
: {
[Key in IsContractDeclarationMissing<
any,
IndexedEventInputs<TContractName, TEventName>["name"]
>]?: AbiParameterToPrimitiveType<Extract<IndexedEventInputs<TContractName, TEventName>, { name: Key }>>;
}
>;
export type UseScaffoldEventHistoryConfig<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
TBlockData extends boolean = false,
TTransactionData extends boolean = false,
TReceiptData extends boolean = false,
> = {
contractName: TContractName;
eventName: IsContractDeclarationMissing<string, TEventName>;
fromBlock: bigint;
filters?: EventFilters<TContractName, TEventName>;
blockData?: TBlockData;
transactionData?: TTransactionData;
receiptData?: TReceiptData;
watch?: boolean;
enabled?: boolean;
};
export type UseScaffoldEventHistoryData<
TContractName extends ContractName,
TEventName extends ExtractAbiEventNames<ContractAbi<TContractName>>,
TBlockData extends boolean = false,
TTransactionData extends boolean = false,
TReceiptData extends boolean = false,
TEvent extends ExtractAbiEvent<ContractAbi<TContractName>, TEventName> = ExtractAbiEvent<
ContractAbi<TContractName>,
TEventName
>,
> =
| IsContractDeclarationMissing<
any[],
{
log: Log<bigint, number, false, TEvent, false, [TEvent], TEventName>;
args: AbiParametersToPrimitiveTypes<TEvent["inputs"]> &
GetEventArgs<
ContractAbi<TContractName>,
TEventName,
{
IndexedOnly: false;
}
>;
block: TBlockData extends true ? Block<bigint, true> : null;
receipt: TReceiptData extends true ? GetTransactionReturnType : null;
transaction: TTransactionData extends true ? GetTransactionReceiptReturnType : null;
}[]
>
| undefined;
export type AbiParameterTuple = Extract<AbiParameter, { type: "tuple" | `tuple[${string}]` }>;
// TEST