import { Fraction, JSBI, BigintIsh, Rounding } from '@crypto-dex-sdk/math';
import { ParachainId } from '@crypto-dex-sdk/chain';

type AddressMap = Record<number | string, string>;

/**
 * A currency is any fungible financial instrument, including Ether, all ERC20 tokens, and other chain-native currencies
 */
declare abstract class Currency {
    /**
     * Returns whether the currency is native to the chain and must be wrapped (e.g. Ether)
     */
    abstract readonly isNative: boolean;
    /**
     * Returns whether the currency is a token that is usable in Uniswap without wrapping
     */
    abstract readonly isToken: boolean;
    /**
     * The chain ID on which this currency resides
     */
    readonly chainId: ParachainId;
    /**
     * The decimals used in representing currency amounts
     */
    readonly decimals: number;
    /**
     * The symbol of the currency, i.e. a short textual non-unique identifier
     */
    readonly symbol?: string;
    /**
     * The name of the currency, i.e. a descriptive textual non-unique identifier
     */
    readonly name?: string;
    protected constructor({ chainId, decimals, symbol, name, }: {
        chainId: number | string;
        decimals: number | string;
        symbol?: string;
        name?: string;
    });
    /**
     * Returns whether this currency is functionally equivalent to the other currency
     * @param other the other currency
     */
    abstract equals(other: Native | Token): boolean;
    /**
     * Return the wrapped version of this currency
     */
    abstract get wrapped(): Token;
}

declare class Native extends Currency {
    readonly isNative: true;
    readonly isToken: false;
    readonly symbol: string;
    readonly name: string;
    protected constructor(native: {
        chainId: number;
        decimals: number;
        symbol: string;
        name: string;
    });
    get wrapped(): Token;
    private static cache;
    static onChain(chainId: number): Native;
    equals(other: Type): boolean;
}

type Type = Native | Token;

/**
 * Represents an ERC20 token with a unique address and some metadata.
 */
declare class Token extends Currency {
    readonly isNative: false;
    readonly isToken: true;
    /**
     * The contract address on the chain on which this token lives
     */
    readonly address: string;
    constructor(token: {
        chainId: number | string;
        address: string;
        decimals: number;
        symbol?: string;
        name?: string;
    });
    /**
     * Returns true if the two tokens are equivalent, i.e. have the same chainId and address.
     * @param other other token to compare
     */
    equals(other: Type): boolean;
    /**
     * Returns true if the address of this token sorts before the address of the other token
     * @param other other token to compare
     * @throws if the tokens have the same address
     * @throws if the tokens are on different chains
     */
    sortsBefore(other: Token): boolean;
    /**
     * Return this token, which does not need to be wrapped
     */
    get wrapped(): Token;
}

declare class Share<T extends Type> extends Fraction {
    readonly currency: T;
    readonly scale: JSBI;
    static fromRawShare<T extends Type>(currency: T, rawShare: BigintIsh): Share<T>;
    protected constructor(currency: T, numerator: BigintIsh, denominator?: BigintIsh);
    toAmount(rebase: {
        base: JSBI;
        elastic: JSBI;
    }, roundUp?: boolean): Amount<T>;
    /**
     * Construct a currency share with a denominator that is not equal to 1
     * @param currency the currency
     * @param numerator the numerator of the fractional token share
     * @param denominator the denominator of the fractional token share
     */
    static fromFractionalShare<T extends Type>(currency: T, numerator: BigintIsh, denominator: BigintIsh): Share<T>;
    add(other: Share<T>): Share<T>;
    subtract(other: Share<T>): Share<T>;
    multiply(other: Fraction | BigintIsh): Share<T>;
    divide(other: Fraction | BigintIsh): Share<T>;
    toSignificant(significantDigits?: number, format?: object, rounding?: Rounding): string;
    toFixed(decimalPlaces?: number, format?: object, rounding?: Rounding): string;
    toExact(format?: object): string;
}

declare class Amount<T extends Type> extends Fraction {
    readonly currency: T;
    readonly scale: JSBI;
    /**
     * Returns a new currency amount instance from the unitless amount of token, i.e. the raw amount
     * @param currency the currency in the amount
     * @param rawAmount the raw token or ether amount
     */
    static fromRawAmount<T extends Type>(currency: T, rawAmount: BigintIsh): Amount<T>;
    static fromShare<T extends Type>(currency: T, shares: BigintIsh, rebase: {
        base: JSBI;
        elastic: JSBI;
    }, roundUp?: boolean): Amount<T>;
    toShare(rebase: {
        base: JSBI;
        elastic: JSBI;
    }, roundUp?: boolean): Share<T>;
    /**
     * Construct a currency amount with a denominator that is not equal to 1
     * @param currency the currency
     * @param numerator the numerator of the fractional token amount
     * @param denominator the denominator of the fractional token amount
     */
    static fromFractionalAmount<T extends Type>(currency: T, numerator: BigintIsh, denominator: BigintIsh): Amount<T>;
    protected constructor(currency: T, numerator: BigintIsh, denominator?: BigintIsh);
    add(other: Amount<T>): Amount<T>;
    subtract(other: Amount<T>): Amount<T>;
    multiply(other: Fraction | BigintIsh): Amount<T>;
    divide(other: Fraction | BigintIsh): Amount<T>;
    toSignificant(significantDigits?: number, format?: object, rounding?: Rounding): string;
    toFixed(decimalPlaces?: number, format?: object, rounding?: Rounding): string;
    toHex(): string;
    toExact(format?: object): string;
    get wrapped(): Amount<Token>;
}

declare const WNATIVE_ADDRESS: Record<number | string, string>;
declare const WETH9_ADDRESS: Record<number | string, string>;
declare const WBTC_ADDRESS: Record<number | string, string>;
declare const UNI_ADDRESS: Record<number | string, string>;
declare const ZLK_ADDRESS: Record<number | string, string>;
declare const axlUSDC_ADDRESS: {
    readonly 8453: "0xEB466342C4d449BC9f53A865D5Cb90586f405215";
    readonly 534352: "0xEB466342C4d449BC9f53A865D5Cb90586f405215";
};
declare const axlDAI_ADDRESS: {
    readonly 8453: "0x5C7e299CF531eb66f2A1dF637d37AbB78e6200C7";
};
declare const USDC_ADDRESS: Record<number | string, string>;
declare const USDT_ADDRESS: Record<number | string, string>;
declare const DAI_ADDRESS: Record<number | string, string>;
declare const FRAX_ADDRESS: Record<number | string, string>;
declare const XCAUSD_ADDRESS: Record<number | string, string>;
declare const KSM_ADDRESS: Record<number | string, string>;
declare const DOT_ADDRESS: Record<number | string, string>;
declare const LINK_ADDRESS: Record<number | string, string>;
declare const ARB_ADDRESS: Record<number | string, string>;

declare const WNATIVE: Record<keyof typeof WNATIVE_ADDRESS, Token>;
declare const WETH9: Record<keyof typeof WETH9_ADDRESS, Token>;
declare const WBTC: Record<keyof typeof WBTC_ADDRESS, Token>;
declare const UNI: Record<keyof typeof UNI_ADDRESS, Token>;
declare const ZLK: {
    [x: string]: Token;
    [x: number]: Token;
};
declare const USDC: {
    [k: string]: Token;
};
declare const USDT: {
    [k: string]: Token;
};
declare const DAI: {
    [k: string]: Token;
};
declare const FRAX: {
    [k: string]: Token;
};
declare const XCAUSD: {
    [k: string]: Token;
};
declare const KSM: {
    [k: string]: Token;
};
declare const DOT: {
    [k: string]: Token;
};
declare const LINK: Record<keyof typeof LINK_ADDRESS, Token>;
declare const ARB: Record<keyof typeof LINK_ADDRESS, Token>;

declare const BASES_TO_CHECK_TRADES_AGAINST: {
    readonly [chainId: number]: Token[];
};
declare const ADDITIONAL_BASES: {
    [chainId: number]: {
        [tokenAddress: string]: Token[];
    };
};
declare const CUSTOM_BASES: {
    [chainId: number]: {
        [tokenAddress: string]: Token[];
    };
};
declare function getCurrencyCombinations(chainId: number, currencyA: Type, currencyB: Type): [Token, Token][];

declare class Price<TBase extends Type, TQuote extends Type> extends Fraction {
    readonly baseCurrency: TBase;
    readonly quoteCurrency: TQuote;
    readonly scalar: Fraction;
    /**
     * Construct a price, either with the base and quote currency amount, or the
     * @param args
     */
    constructor(...args: [TBase, TQuote, BigintIsh, BigintIsh] | [
        {
            baseAmount: Amount<TBase>;
            quoteAmount: Amount<TQuote>;
        }
    ]);
    /**
     * Flip the price, switching the base and quote currency
     */
    invert(): Price<TQuote, TBase>;
    /**
     * Multiply the price by another price, returning a new price. The other price must have the same base currency as this price's quote currency
     * @param other the other price
     */
    multiply<TOtherQuote extends Type>(other: Price<TQuote, TOtherQuote>): Price<TBase, TOtherQuote>;
    /**
     * Return the amount of quote currency corresponding to a given amount of the base currency
     * @param currencyAmount the amount of base currency to quote against the price
     */
    quote(currencyAmount: Amount<TBase>): Amount<TQuote>;
    /**
     * Get the value scaled by decimals for formatting
     * @private
     */
    private get adjustedForDecimals();
    toSignificant(significantDigits?: number, format?: object, rounding?: Rounding): string;
    toFixed(decimalPlaces?: number, format?: object, rounding?: Rounding): string;
}

type TokenMap = Record<number | string, Token>;

declare function tryParseAmount<T extends Type>(value?: string, currency?: T): Amount<T> | undefined;

declare function useCurrencyCombinations(chainId?: number, currencyA?: Type, currencyB?: Type): [Token, Token][];

declare function useNativeCurrency({ chainId }: {
    chainId?: number;
}): Native;

export { ADDITIONAL_BASES, ARB, ARB_ADDRESS, type AddressMap, Amount, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES, type Type as Currency, DAI, DAI_ADDRESS, DOT, DOT_ADDRESS, FRAX, FRAX_ADDRESS, KSM, KSM_ADDRESS, LINK, LINK_ADDRESS, Native, Price, Share, Token, type TokenMap, type Type, UNI, UNI_ADDRESS, USDC, USDC_ADDRESS, USDT, USDT_ADDRESS, WBTC, WBTC_ADDRESS, WETH9, WETH9_ADDRESS, WNATIVE, WNATIVE_ADDRESS, XCAUSD, XCAUSD_ADDRESS, ZLK, ZLK_ADDRESS, axlDAI_ADDRESS, axlUSDC_ADDRESS, getCurrencyCombinations, tryParseAmount, useCurrencyCombinations, useNativeCurrency };
