import BN from "bn.js";
import { ethers } from "ethers";
import { ABISerializableObject } from "../serializer/Serializable.js";
import { ABIDecoder } from "../serializer/Decoder.js";
import { ABIEncoder } from "../serializer/Encoder.js";
type IntType = Int | number | string | BN;
/**
 * How to handle integer overflow.
 * - `throw`: Throws an error if value overflows (or underflows).
 * - `truncate`: Truncates or extends bit-pattern with sign extension (C++11 behavior).
 * - `clamp`: Clamps the value within the supported range.
 */
export type OverflowBehavior = "throw" | "truncate" | "clamp";
/**
 * How to handle remainder when dividing integers.
 * - `floor`: Round down to nearest integer.
 * - `round`: Round to nearest integer.
 * - `ceil`: Round up to nearest integer.
 */
export type DivisionBehavior = "floor" | "round" | "ceil";
/**
 * Binary integer with the underlying value represented by a BN.js instance.
 * Follows C++11 standard for arithmetic operators and conversions.
 * @note This type is optimized for correctness not speed, if you plan to manipulate
 *       integers in a tight loop you're advised to use the underlying BN.js value or
 *       convert to a JavaScript number first.
 */
export declare class Int implements ABISerializableObject {
    static abiName: string;
    static isSigned: boolean;
    static byteWidth: number;
    /** Largest value that can be represented by this integer type. */
    static get max(): BN;
    /** Smallest value that can be represented by this integer type. */
    static get min(): BN;
    /** Add `lhs` to `rhs` and return the resulting value. */
    static add(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int;
    /** Add `lhs` to `rhs` and return the resulting value. */
    static sub(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int;
    /** Multiply `lhs` by `rhs` and return the resulting value. */
    static mul(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int;
    /**
     * Divide `lhs` by `rhs` and return the quotient, dropping the remainder.
     * @throws When dividing by zero.
     */
    static div(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int;
    /**
     * Divide `lhs` by `rhs` and return the quotient + remainder rounded to the closest integer.
     * @throws When dividing by zero.
     */
    static divRound(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int;
    /**
     * Divide `lhs` by `rhs` and return the quotient + remainder rounded up to the closest integer.
     * @throws When dividing by zero.
     */
    static divCeil(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int;
    /** Compare `lhs` to `rhs` and return true if `lhs` is greater than `rhs`. */
    static gt(lhs: Int, rhs: Int): boolean;
    /** Compare `lhs` to `rhs` and return true if `lhs` is less than `rhs`. */
    static lt(lhs: Int, rhs: Int): boolean;
    /** Compare `lhs` to `rhs` and return true if `lhs` is greater than or equal to `rhs`. */
    static gte(lhs: Int, rhs: Int): boolean;
    /** Compare `lhs` to `rhs` and return true if `lhs` is less than or equal to `rhs`. */
    static lte(lhs: Int, rhs: Int): boolean;
    /**
     * Can be used to implement custom operator.
     * @internal
     */
    static operator(lhs: Int, rhs: Int, overflow: OverflowBehavior, fn: (lhs: BN, rhs: BN) => BN): Int;
    /**
     * Create a new instance from value.
     * @param value Value to create new Int instance from, can be a string, number,
     *              little-endian byte array or another Int instance.
     * @param overflow How to handle integer overflow, default behavior is to throw.
     */
    static from<T extends typeof Int>(this: T, value: IntType | Uint8Array, overflow?: OverflowBehavior): InstanceType<T>;
    static from(value: any, overflow?: OverflowBehavior): unknown;
    static fromABI<T extends typeof Int>(this: T, decoder: ABIDecoder): InstanceType<T>;
    static fromABI(decoder: ABIDecoder): unknown;
    static abiDefault(): Int;
    static random<T extends typeof Int>(this: T): InstanceType<T>;
    static random(): unknown;
    /**
     * The underlying BN.js instance – don't modify this
     * directly – take a copy first using `.clone()`.
     */
    value: BN;
    /**
     * Create a new instance, don't use this directly. Use the `.from` factory method instead.
     * @throws If the value over- or under-flows the integer type.
     */
    constructor(value: BN);
    /**
     * Cast this integer to other type.
     * @param overflow How to handle overflow, default is to preserve bit-pattern (C++11 behavior).
     */
    cast<T extends typeof Int>(type: T, overflow?: OverflowBehavior): InstanceType<T>;
    /** Number as bytes in little endian (matches memory layout in C++ contract). */
    get byteArray(): Uint8Array;
    /**
     * Compare two integers, if strict is set to true the test will only consider integers
     * of the exact same type. I.e. Int64.from(1).equals(UInt64.from(1)) will return false.
     */
    equals(other: IntType | Uint8Array, strict?: boolean): boolean;
    /** Mutating add. */
    add(num: IntType): void;
    /** Non-mutating add. */
    adding(num: IntType): this;
    /** Mutating subtract. */
    subtract(num: IntType): void;
    /** Non-mutating subtract. */
    subtracting(num: IntType): this;
    /** Mutating multiply. */
    multiply(by: IntType): void;
    /** Non-mutating multiply. */
    multiplying(by: IntType): this;
    /**
     * Mutating divide.
     * @param behavior How to handle the remainder, default is to floor (round down).
     * @throws When dividing by zero.
     */
    divide(by: IntType, behavior?: DivisionBehavior): void;
    /**
     * Non-mutating divide.
     * @param behavior How to handle the remainder, default is to floor (round down).
     * @throws When dividing by zero.
     */
    dividing(by: IntType, behavior?: DivisionBehavior): this;
    /** Greater than comparision operator */
    gt(other: Int): boolean;
    /** Less than comparision operator */
    lt(other: Int): boolean;
    /** Greater than or equal comparision operator */
    gte(other: Int): boolean;
    /** Less than or equal comparision operator */
    lte(other: Int): boolean;
    /**
     * Run operator with C++11 implicit conversion.
     * @internal
     */
    private operator;
    /**
     * Convert to a JavaScript number.
     * @throws If the number cannot be represented by 53-bits.
     **/
    toNumber(): number;
    toString(): string;
    [Symbol.toPrimitive](type: string): string | number;
    toABI(encoder: ABIEncoder): void;
    toJSON(): string | number;
}
export type Int8Type = Int8 | IntType;
export declare class Int8 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type Int16Type = Int16 | IntType;
export declare class Int16 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type Int32Type = Int32 | IntType;
export declare class Int32 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type Int64Type = Int64 | IntType;
export declare class Int64 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type Int128Type = Int128 | IntType;
export declare class Int128 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type UInt8Type = UInt8 | IntType;
export declare class UInt8 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type UInt16Type = UInt16 | IntType;
export declare class UInt16 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type UInt32Type = UInt32 | IntType;
export declare class UInt32 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type UInt64Type = UInt64 | IntType;
export declare class UInt64 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type UInt128Type = UInt128 | IntType;
export declare class UInt128 extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
}
export type UInt256Type = UInt256 | UInt256Parts;
export interface UInt256Parts {
    low: number;
    high: number;
}
export declare class UInt256 {
    static readonly abiName = "uint256";
    static readonly byteWidth = 32;
    static readonly isSigned = false;
    static readonly DECIMALS = 18;
    static readonly SCALE: BN;
    static readonly MAX_UINT256: BN;
    low: UInt128;
    high: UInt128;
    constructor(low: UInt128, high: UInt128);
    /**
     * Create a UInt256 from:
     *  • number|string    → interpreted as an 18‐decimal fixed‐point (scaled by 10^18).
     *  • ethers.BigNumber → interpreted as a “whole integer,” multiply by 10^18.
     *  • BN               → interpreted as a “whole integer,” multiply by 10^18.
     *  • UInt128           → interpreted as a “whole integer,” multiply by 10^18.
     *  • UInt256           → just return it (clone).
     *  • { low, high }     → raw halves (H<<128 + L) as a “whole integer,” multiply by 10^18.
     */
    static from(value: number | string | UInt128 | UInt256 | ethers.BigNumber | BN | {
        low: UInt128Type;
        high: UInt128Type;
    }): UInt256;
    /**
     * Construct a UInt256 from a raw 256-bit BN (no scaling).
     * Internal helper for add/sub/mul/div.
     */
    static fromRaw(raw: BN): UInt256;
    /**
     * Helper to combine `low` + `high` into a single BN that includes the
     * _already-scaled_ 10^18 factor.
     */
    raw(): BN;
    /**
     * Convert the UInt256 to a human-readable string,
     * e.g. "123.456" for internal BN "123456000000000000000".
     */
    toString(): string;
    /**
     * Convert the UInt256 to a JS number if safe; otherwise returns a BN.
     * This "descale" by 10^18 first, so "123.456" comes back as ~123.456 in JS.
     */
    toNumber(): number | BN;
    /**
     * Add another UInt256 (both 18-decimal scaled).
     */
    add(other: UInt256): UInt256;
    /**
     * Subtract another UInt256. Throws if result < 0 (underflow).
     */
    subtract(other: UInt256): UInt256;
    /**
     * Multiply this UInt256 by another, then scale back down by 10^18
     * so final is still 18-decimals.
     *
     * So effectively: (a * b) / 10^18
     */
    multiply(other: UInt256): UInt256;
    /**
     * Divide this UInt256 by another, scaling up the dividend by 10^18
     * first so final is still 18 decimals.
     *
     * So effectively: (a * 10^18) / b
     */
    divide(divisor: UInt256): UInt256;
    /**
     * Modulo. Because both sides are scaled, we just do raw mod.
     * The result is still scaled with 18 decimals.
     */
    modulo(divisor: UInt256): UInt256;
    /**
     * Compare: -1 if this < other, 0 if equal, +1 if this > other.
     */
    compare(other: UInt256): -1 | 0 | 1;
    equals(other: UInt256): boolean;
    greaterThan(other: UInt256): boolean;
    lessThan(other: UInt256): boolean;
    private static u128ToBN;
}
export type VarIntType = VarInt | IntType;
export declare class VarInt extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
    static fromABI(decoder: ABIDecoder): VarInt;
    toABI(encoder: ABIEncoder): void;
}
export type VarUIntType = VarUInt | IntType;
export declare class VarUInt extends Int {
    static abiName: string;
    static byteWidth: number;
    static isSigned: boolean;
    static fromABI(decoder: ABIDecoder): VarUInt;
    toABI(encoder: ABIEncoder): void;
}
export type AnyInt = Int8Type | Int16Type | Int32Type | Int64Type | Int128Type | UInt8Type | UInt16Type | UInt32Type | UInt64Type | UInt128Type | UInt256Type | VarIntType | VarUIntType;
export {};
//# sourceMappingURL=Integer.d.ts.map