import * as abitype from 'abitype';
import type * as Abi from './Abi.js';
import * as AbiItem from './AbiItem.js';
import * as AbiParameters from './AbiParameters.js';
import * as Errors from './Errors.js';
import * as Hex from './Hex.js';
import type * as internal from './internal/abiConstructor.js';
import * as formatAbiItem from './internal/human-readable/formatAbiItem.js';
import type { IsNarrowable } from './internal/types.js';
/** Root type for an {@link ox#AbiItem.AbiItem} with a `constructor` type. */
export type AbiConstructor = abitype.AbiConstructor;
type ExtractConstructor<abi extends Abi.Abi | readonly unknown[]> = [
    fromAbi.ReturnType<abi>
] extends [never] ? undefined : fromAbi.ReturnType<abi> extends AbiConstructor ? fromAbi.ReturnType<abi> : undefined;
type ExtractArgs<abiConstructor extends AbiConstructor | undefined> = [
    abiConstructor
] extends [never] ? readonly [] : abiConstructor extends AbiConstructor ? abitype.AbiParametersToPrimitiveTypes<abiConstructor['inputs']> : readonly [];
/**
 * ABI-decodes the provided constructor input (`inputs`).
 *
 * @example
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * const constructor = AbiConstructor.from(
 *   'constructor(address, uint256)'
 * )
 *
 * const bytecode = '0x...'
 *
 * const data = AbiConstructor.encode(constructor, {
 *   bytecode,
 *   args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n]
 * })
 *
 * const decoded = AbiConstructor.decode(constructor, {
 *   // [!code focus]
 *   bytecode, // [!code focus]
 *   data // [!code focus]
 * }) // [!code focus]
 * ```
 *
 * @example
 * ### ABI-shorthand
 *
 * You can also specify an entire ABI object as a parameter to `AbiConstructor.decode`.
 *
 * ```ts twoslash
 * // @noErrors
 * import { Abi, AbiConstructor } from 'ox'
 *
 * const abi = Abi.from([...])
 *
 * const data = AbiConstructor.encode(abi, {
 *   bytecode: '0x...',
 *   args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n],
 * })
 *
 * const decoded = AbiConstructor.decode(abi, { // [!code focus]
 *   bytecode: '0x...', // [!code focus]
 *   data, // [!code focus]
 * }) // [!code focus]
 * ```
 *
 * @param abiConstructor - The ABI Constructor to decode.
 * @param options - Decoding options.
 * @returns The decoded constructor inputs.
 */
export declare function decode<const abi extends Abi.Abi | readonly unknown[], abiConstructor extends AbiConstructor | undefined = ExtractConstructor<abi>>(abi: abi | Abi.Abi | readonly unknown[], options: decode.Options): decode.ReturnType<abiConstructor>;
export declare function decode<const abiConstructor extends AbiConstructor>(abiConstructor: abiConstructor | AbiConstructor, options: decode.Options): decode.ReturnType<abiConstructor>;
export declare namespace decode {
    interface Options {
        /** The bytecode of the contract. */
        bytecode: Hex.Hex;
        /** The encoded constructor. */
        data: Hex.Hex;
        /**
         * Whether decoded addresses should be checksummed.
         *
         * @default true
         */
        checksumAddress?: boolean | undefined;
    }
    type ReturnType<abiConstructor extends AbiConstructor | undefined = AbiConstructor> = (abiConstructor extends undefined ? undefined : abiConstructor extends AbiConstructor ? abiConstructor['inputs']['length'] extends 0 ? undefined : abitype.AbiParametersToPrimitiveTypes<abiConstructor['inputs']> : never) | (IsNarrowable<abiConstructor, AbiConstructor> extends true ? never : undefined);
    type ErrorType = Errors.GlobalErrorType;
}
/**
 * ABI-encodes the provided constructor input (`inputs`).
 *
 * @example
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * const constructor = AbiConstructor.from(
 *   'constructor(address, uint256)'
 * )
 *
 * const data = AbiConstructor.encode(constructor, {
 *   bytecode: '0x...',
 *   args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n]
 * })
 * ```
 *
 * @example
 * ### ABI-shorthand
 *
 * You can also specify an entire ABI object as a parameter to `AbiConstructor.encode`.
 *
 * ```ts twoslash
 * // @noErrors
 * import { Abi, AbiConstructor } from 'ox'
 *
 * const abi = Abi.from([...])
 *
 * const data = AbiConstructor.encode(abi, { // [!code focus]
 *   bytecode: '0x...', // [!code focus]
 *   args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n], // [!code focus]
 * }) // [!code focus]
 * ```
 *
 * @example
 * ### End-to-end
 *
 * Below is an end-to-end example of using `AbiConstructor.encode` to encode the constructor of a contract and deploy it.
 *
 * ```ts twoslash
 * import 'ox/window'
 * import { AbiConstructor, Hex } from 'ox'
 *
 * // 1. Instantiate the ABI Constructor.
 * const constructor = AbiConstructor.from(
 *   'constructor(address owner, uint256 amount)'
 * )
 *
 * // 2. Encode the ABI Constructor.
 * const data = AbiConstructor.encode(constructor, {
 *   bytecode: '0x...',
 *   args: ['0xd8da6bf26964af9d7eed9e03e53415d37aa96045', 123n]
 * })
 *
 * // 3. Deploy the contract.
 * const hash = await window.ethereum!.request({
 *   method: 'eth_sendTransaction',
 *   params: [{ data }]
 * })
 * ```
 *
 * :::note
 *
 * For simplicity, the above example uses `window.ethereum.request`, but you can use any
 * type of JSON-RPC interface.
 *
 * :::
 *
 * @param abiConstructor - The ABI Constructor to encode.
 * @param options - Encoding options.
 * @returns The encoded constructor.
 */
export declare function encode<const abi extends Abi.Abi | readonly unknown[], abiConstructor extends AbiConstructor | undefined = ExtractConstructor<abi>>(abi: abi | Abi.Abi | readonly unknown[], options: encode.Options<abiConstructor>): encode.ReturnType;
export declare function encode<const abiConstructor extends AbiConstructor>(abiConstructor: abiConstructor | AbiConstructor, options: encode.Options<abiConstructor>): encode.ReturnType;
export declare namespace encode {
    type Options<abiConstructor extends AbiConstructor | undefined = AbiConstructor, args extends ExtractArgs<abiConstructor> = ExtractArgs<abiConstructor>> = {
        /** The bytecode of the contract. */
        bytecode: Hex.Hex;
        /** The constructor arguments to encode. */
        args?: args | undefined;
    } & (readonly [] extends args ? {} : {
        /** The constructor arguments to encode. */
        args: args;
    });
    type ReturnType = Hex.Hex;
    type ErrorType = Hex.concat.ErrorType | AbiParameters.encode.ErrorType | Errors.GlobalErrorType;
}
/** @internal */
export declare function format<const abiConstructor extends AbiConstructor>(abiConstructor: abiConstructor): format.ReturnType<abiConstructor>;
/**
 * Formats an {@link ox#AbiConstructor.AbiConstructor} into a **Human Readable ABI Function**.
 *
 * @example
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * const formatted = AbiConstructor.format({
 *   inputs: [{ name: 'owner', type: 'address' }],
 *   payable: false,
 *   stateMutability: 'nonpayable',
 *   type: 'constructor'
 * })
 *
 * formatted
 * //    ^?
 * ```
 *
 * @param abiConstructor - The ABI Constructor to format.
 * @returns The formatted ABI Constructor.
 */
export declare function format(abiConstructor: AbiConstructor): string;
export declare namespace format {
    type ReturnType<abiConstructor extends AbiConstructor = AbiConstructor> = formatAbiItem.FormatAbiItem<abiConstructor>;
    type ErrorType = Errors.GlobalErrorType;
}
/** @internal */
export declare function from<const abiConstructor extends AbiConstructor | string | readonly string[]>(abiConstructor: (abiConstructor | string | readonly string[]) & ((abiConstructor extends string ? internal.Signature<abiConstructor> : never) | (abiConstructor extends readonly string[] ? internal.Signatures<abiConstructor> : never) | AbiConstructor)): from.ReturnType<abiConstructor>;
/**
 * Parses an arbitrary **JSON ABI Constructor** or **Human Readable ABI Constructor** into a typed {@link ox#AbiConstructor.AbiConstructor}.
 *
 * @example
 * ### JSON ABIs
 *
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * const constructor = AbiConstructor.from({
 *   inputs: [{ name: 'owner', type: 'address' }],
 *   payable: false,
 *   stateMutability: 'nonpayable',
 *   type: 'constructor'
 * })
 *
 * constructor
 * //^?
 * ```
 *
 * @example
 * ### Human Readable ABIs
 *
 * A Human Readable ABI can be parsed into a typed ABI object:
 *
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * const constructor = AbiConstructor.from(
 *   'constructor(address owner)' // [!code hl]
 * )
 *
 * constructor
 * //^?
 * ```
 *
 * @example
 * It is possible to specify `struct`s along with your definitions:
 *
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * const constructor = AbiConstructor.from([
 *   'struct Foo { address owner; uint256 amount; }', // [!code hl]
 *   'constructor(Foo foo)'
 * ])
 *
 * constructor
 * //^?
 * ```
 *
 *
 *
 * @param abiConstructor - The ABI Constructor to parse.
 * @returns Typed ABI Constructor.
 */
export declare function from(abiConstructor: AbiConstructor | string | readonly string[]): AbiConstructor;
export declare namespace from {
    type ReturnType<abiConstructor extends AbiConstructor | string | readonly string[] = AbiConstructor> = AbiItem.from.ReturnType<abiConstructor>;
    type ErrorType = AbiItem.from.ErrorType | Errors.GlobalErrorType;
}
/** @internal */
export declare function fromAbi<const abi extends Abi.Abi | readonly unknown[]>(abi: abi | Abi.Abi | readonly unknown[]): fromAbi.ReturnType<abi>;
/**
 * Extracts an {@link ox#AbiConstructor.AbiConstructor} from an {@link ox#Abi.Abi} given a name and optional arguments.
 *
 * @example
 * ### Extracting by Name
 *
 * ABI Events can be extracted by their name using the `name` option:
 *
 * ```ts twoslash
 * import { Abi, AbiConstructor } from 'ox'
 *
 * const abi = Abi.from([
 *   'constructor(address owner)',
 *   'function foo()',
 *   'event Transfer(address owner, address to, uint256 tokenId)',
 *   'function bar(string a) returns (uint256 x)'
 * ])
 *
 * const item = AbiConstructor.fromAbi(abi) // [!code focus]
 * //    ^?
 * ```
 *
 * @returns The ABI constructor.
 */
export declare function fromAbi(abi: Abi.Abi | readonly unknown[]): AbiConstructor;
export declare namespace fromAbi {
    type ReturnType<abi extends Abi.Abi | readonly unknown[] = Abi.Abi> = Extract<abi[number], {
        type: 'constructor';
    }>;
    type ErrorType = AbiItem.NotFoundError | Errors.GlobalErrorType;
}
/**
 * Throws when the provided `data` does not begin with the provided `bytecode`.
 *
 * @example
 * ```ts twoslash
 * import { AbiConstructor } from 'ox'
 *
 * AbiConstructor.decode(
 *   AbiConstructor.from('constructor(address)'),
 *   { bytecode: '0x6080...', data: '0xdeadbeef' }
 * )
 * // @error: AbiConstructor.BytecodeMismatchError: Provided `data` does not start with the provided `bytecode`.
 * ```
 */
export declare class BytecodeMismatchError extends Errors.BaseError {
    readonly name = "AbiConstructor.BytecodeMismatchError";
    constructor({ bytecode, data }: {
        bytecode: Hex.Hex;
        data: Hex.Hex;
    });
}
export {};
//# sourceMappingURL=AbiConstructor.d.ts.map