import type { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
import { KeetaNet } from "../client/index.js";
import type { AnchorTokenLocationMetadata, AssetLocationLike, AssetTransferInstructions, KeetaAssetMovementTransaction, KeetaPersistentForwardingAddressDetails, PickChainLocation, Rail, RecipientResolved } from "../services/asset-movement/common.js";
import type { Resolver } from "./index.js";
import type { ISOCurrencyCode } from '@keetanetwork/currency-info';
import type { Account, GenericAccount, TokenAddress } from '@keetanetwork/keetanet-client/lib/account.js';
import KeetaFXAnchorClient from '../services/fx/client.js';
import KeetaAssetMovementAnchorClient from '../services/asset-movement/client.js';
import type { ExternalChainAsset } from './asset.js';
import type { Logger } from './log/index.js';
import type { BlockHash } from '@keetanetwork/keetanet-client/lib/block/index.js';
import type { AnchorMetadataLegalField } from './metadata.types.js';
type FXQuoteOrEstimate = NonNullable<Awaited<ReturnType<KeetaFXAnchorClient['getQuotesOrEstimates']>>>[number];
type AssetMovementProvider = NonNullable<Awaited<ReturnType<KeetaAssetMovementAnchorClient['getProvidersForTransfer']>>>[number];
type AssetMovementTransfer = Awaited<ReturnType<AssetMovementProvider['initiateTransfer']>>;
type FXExchange = Awaited<ReturnType<FXQuoteOrEstimate['createExchange']>>;
interface ChainStepResolutionBase<Type extends 'fx' | 'assetMovement' | 'keetaSend' | 'forwarded'> {
    type: Type;
    valueIn: bigint;
    valueOut: bigint;
    step: Type extends 'keetaSend' ? null : (Type extends 'forwarded' ? AssetMovementGraphNode : Extract<GraphNodeLike, {
        type: Type;
    }>);
}
interface ChainStepResolutionFX extends ChainStepResolutionBase<'fx'> {
    type: 'fx';
    result: FXQuoteOrEstimate;
}
type SendingToType = 'SELF' | 'NEXT_STEP' | 'FINAL_DESTINATION';
interface ChainStepResolutionAssetMovement extends ChainStepResolutionBase<'assetMovement'> {
    usingInstruction: AssetTransferInstructions;
    sendingTo: SendingToType;
    transfer: AssetMovementTransfer;
}
interface ChainStepResolutionKeetaSend extends ChainStepResolutionBase<'keetaSend'> {
    usingInstruction: Extract<AssetTransferInstructions, {
        type: 'KEETA_SEND';
    }>;
}
interface ChainStepResolutionForwarded extends ChainStepResolutionBase<'forwarded'> {
    persistentAddress: KeetaPersistentForwardingAddressDetails;
    provider: AssetMovementProvider;
}
export type Disclaimer = Exclude<AnchorMetadataLegalField['disclaimers'], undefined>[number];
type ProviderDisclaimers = {
    providerID: string;
    disclaimers: Disclaimer[];
};
type PlanDisclaimers = ProviderDisclaimers[];
export type ChainStepResolution = ChainStepResolutionFX | ChainStepResolutionAssetMovement | ChainStepResolutionKeetaSend | ChainStepResolutionForwarded;
type AnchorChainingPathComputedPlan = {
    steps: ChainStepResolution[];
    totalValueIn: bigint;
    totalValueOut: bigint;
};
type ExecutedStepFX = {
    type: 'fx';
    plan: ChainStepResolutionFX;
    exchange: FXExchange;
};
type ExecutedStepAssetMovement = {
    type: 'assetMovement';
    plan: ChainStepResolutionAssetMovement;
};
type ExecutedStepKeetaSend = {
    type: 'keetaSend';
    plan: ChainStepResolutionKeetaSend;
};
type ExecutedStepForwarded = {
    type: 'forwarded';
    plan: ChainStepResolutionForwarded;
    observedTransaction: KeetaAssetMovementTransaction;
};
export type ExecutedStep = ExecutedStepFX | ExecutedStepAssetMovement | ExecutedStepKeetaSend | ExecutedStepForwarded;
export type AnchorChainingPathExecuteResult = {
    steps: ExecutedStep[];
};
export type AnchorChainingPathExecuteOptions = {
    requireSendAuth?: boolean;
};
export type AnchorChainingPathState = {
    status: 'idle';
} | {
    status: 'executing';
    completedSteps: ExecutedStep[];
    currentStepIndex: number;
} | {
    status: 'completed';
    result: AnchorChainingPathExecuteResult;
} | {
    status: 'failed';
    error: Error;
    completedSteps: ExecutedStep[];
    failedAtStepIndex: number;
};
interface StepNeededActionEventPayloadBase<ActionType, ActionPayload, CompletedPayload extends readonly unknown[] = []> {
    type: ActionType;
    markCompleted: (...args: CompletedPayload) => void;
    markFailed: (error?: unknown) => void;
    action: ActionPayload;
}
interface StepNeededActionEventAssetMovement extends StepNeededActionEventPayloadBase<'assetMovementUserExecutionRequired', {
    assetMovementTransfer: AssetMovementTransfer;
}, []> {
}
interface StepNeededActionEventKeetaSend extends StepNeededActionEventPayloadBase<'keetaSendAuthRequired', {
    sendToAddress: GenericAccount;
    value: bigint;
    token: TokenAddress;
    external?: string;
}, [{
    sent: boolean | BlockHash;
}]> {
}
type StepNeededActionEventPayload = StepNeededActionEventKeetaSend | StepNeededActionEventAssetMovement;
type AnchorChainingPathEventMap = {
    stateChange: [state: AnchorChainingPathState];
    stepExecuted: [step: ExecutedStep, index: number];
    completed: [result: AnchorChainingPathExecuteResult];
    failed: [error: Error, completedSteps: ExecutedStep[], failedAtStepIndex: number];
    stepNeedsAction: [StepNeededActionEventPayload];
};
interface RailSupportedOperations {
    createPersistentForwarding?: boolean;
    initiateTransfer?: boolean;
}
interface AnchorChainingAssetAndLocation<AssetType extends AnchorChainingAsset = AnchorChainingAsset, Location extends AssetLocationLike = AssetLocationLike> {
    asset: AssetType;
    location: Location;
    rail: Rail;
    supportedOperations?: RailSupportedOperations;
    value?: bigint;
}
interface AnchorChainingDestination extends AnchorChainingAssetAndLocation {
    recipient: RecipientResolved;
}
interface AnchorChainingPathInput {
    source: AnchorChainingAssetAndLocation;
    destination: AnchorChainingDestination;
}
export interface AnchorChainingConfig {
    client: KeetaNet.UserClient;
    resolver?: Resolver;
    signer?: InstanceType<typeof KeetaNetLib.Account>;
    account?: InstanceType<typeof KeetaNetLib.Account>;
    logger?: Logger;
}
interface BaseGraphNodeLike<Type extends 'fx' | 'assetMovement', AssetType extends AnchorChainingAsset> {
    type: Type;
    providerID: string;
    from: AnchorChainingAssetAndLocation<AssetType>;
    to: AnchorChainingAssetAndLocation<AssetType>;
}
interface FXGraphNode extends BaseGraphNodeLike<'fx', Exclude<AnchorChainingAsset, ExternalChainAsset>> {
}
interface AssetMovementGraphNode extends BaseGraphNodeLike<'assetMovement', AnchorChainingAsset> {
}
export type GraphNodeLike = FXGraphNode | AssetMovementGraphNode;
type KeetaLocationLike = Extract<AssetLocationLike, `chain:keeta:${bigint}`> | PickChainLocation<'keeta'>;
interface KeetaSendStepLike {
    type: 'keetaSend';
    providerID?: null;
    from: AnchorChainingAssetAndLocation<AnchorChainingAsset, KeetaLocationLike>;
    to: AnchorChainingAssetAndLocation<AnchorChainingAsset, KeetaLocationLike>;
}
export type AnchorChainingStepLike = GraphNodeLike | KeetaSendStepLike;
export type AnchorChainingAsset = TokenAddress | ISOCurrencyCode | ExternalChainAsset;
export type AnchorChainingListAssetsSideFilter = {
    location?: AssetLocationLike | undefined;
    asset?: AnchorChainingAsset | undefined;
    rail?: Rail | undefined;
};
type AnchorChainingListAssetsShared = {
    maxStepCount?: number;
    onlyAllowFXLike?: boolean;
};
export type AnchorChainingListAssetsFilter = ({
    from: AnchorChainingListAssetsSideFilter;
    to?: never;
} & AnchorChainingListAssetsShared) | ({
    to: AnchorChainingListAssetsSideFilter;
    from?: never;
} & AnchorChainingListAssetsShared) | ({
    from?: never;
    to?: never;
} & AnchorChainingListAssetsShared);
export type AnchorChainingResolveAssetsFilter = {
    from?: AnchorChainingListAssetsSideFilter;
    to?: AnchorChainingListAssetsSideFilter;
    maxStepCount?: number;
    onlyAllowFXLike?: boolean;
};
export interface AnchorChainingResolveAssetsResult {
    from: AnchorChainingAssetInfo[];
    to: AnchorChainingAssetInfo[];
}
export interface AnchorChainingAssetInfo {
    asset: AnchorChainingAsset;
    location: AssetLocationLike;
    rails: {
        inbound: Rail[];
        outbound: Rail[];
    };
    distance: {
        pathLength: number;
    } | null;
}
type AnchorChainingAssetInfoWithMetadata = AnchorChainingAssetInfo & {
    metadata?: AnchorTokenLocationMetadata;
};
interface AnchorChainingResolveAssetsWithMetadataResult {
    from: AnchorChainingAssetInfoWithMetadata[];
    to: AnchorChainingAssetInfoWithMetadata[];
}
type AnchorChainingWithMetadataOptions = {
    providerID?: string;
};
type GetAccountForActionPayload = {
    type: 'assetMovement';
    providerMethod: 'initiateTransfer';
    provider?: AssetMovementProvider;
} | {
    type: 'fx';
    providerMethod: 'getAccountForAction';
};
type AccountLike = InstanceType<typeof KeetaNetLib.Account> | undefined | ((providerMethodPayload: GetAccountForActionPayload) => Promise<Account> | Account);
interface AnchorChainingAccountOverrides {
    account?: AccountLike;
    signer?: AccountLike;
}
declare class AnchorGraph {
    #private;
    client: KeetaNet.UserClient;
    resolver: Resolver;
    logger?: Logger | undefined;
    readonly assetMovementClient: KeetaAssetMovementAnchorClient;
    readonly fxClient: KeetaFXAnchorClient;
    constructor(args: {
        client: KeetaNet.UserClient;
        resolver: Resolver;
        logger?: Logger | undefined;
    });
    getAssetMovementProviderById(providerID: string): Promise<AssetMovementProvider | null>;
    getAssetMovementProvidersForAsset(asset: AnchorChainingAsset, location: AssetLocationLike): Promise<null | {
        [providerID: string]: {
            provider: AssetMovementProvider;
        };
    }>;
    computeGraphNodes(): Promise<GraphNodeLike[]>;
    findPaths(input: AnchorChainingPathInput): Promise<GraphNodeLike[][]>;
    resolveAssets(filter?: AnchorChainingResolveAssetsFilter): Promise<AnchorChainingResolveAssetsResult>;
    listAssets(filter?: AnchorChainingListAssetsFilter): Promise<AnchorChainingAssetInfo[]>;
    getExternalAssetMetadata(asset: AnchorChainingAssetInfo['asset'], location: AnchorChainingAssetInfo['location'], providerID?: string): Promise<AnchorTokenLocationMetadata | undefined>;
    resolveAssetsWithMetadata(filter?: AnchorChainingResolveAssetsFilter, options?: AnchorChainingWithMetadataOptions): Promise<AnchorChainingResolveAssetsWithMetadataResult>;
    listAssetsWithMetadata(filter?: AnchorChainingListAssetsFilter, options?: AnchorChainingWithMetadataOptions): Promise<AnchorChainingAssetInfoWithMetadata[]>;
}
export interface ComputePlanOptions {
    overrides?: AnchorChainingAccountOverrides;
    /**
     * Limit the number of plans to calculate, defaults to 3
     */
    limit?: number;
}
export declare class AnchorChainingPath {
    readonly request: AnchorChainingPathInput;
    readonly path: AnchorChainingStepLike[];
    readonly parent: AnchorChaining;
    constructor(input: {
        request: AnchorChainingPathInput;
        path: AnchorChainingStepLike[];
        parent: AnchorChaining;
    });
    get logger(): Logger | undefined;
    protected getAccountLike(action: GetAccountForActionPayload, override?: AccountLike): Promise<InstanceType<typeof KeetaNetLib.Account>>;
    protected getAccountsForAction(action: GetAccountForActionPayload, overrides?: AnchorChainingAccountOverrides): Promise<{
        account: InstanceType<typeof KeetaNetLib.Account>;
        signer: InstanceType<typeof KeetaNetLib.Account>;
    }>;
    getProviderLegalDisclaimers(): Promise<PlanDisclaimers | null>;
}
export declare class AnchorChainingPlan extends AnchorChainingPath {
    #private;
    private constructor();
    get plan(): AnchorChainingPathComputedPlan;
    static create(path: AnchorChainingPath, options?: ComputePlanOptions): Promise<AnchorChainingPlan>;
    get state(): AnchorChainingPathState;
    on<E extends keyof AnchorChainingPathEventMap>(event: E, listener: (...args: AnchorChainingPathEventMap[E]) => void): void;
    off<E extends keyof AnchorChainingPathEventMap>(event: E, listener: (...args: AnchorChainingPathEventMap[E]) => void): void;
    get logger(): Logger | undefined;
    execute(options?: {
        requireSendAuth?: boolean;
        abortSignal?: AbortSignal;
    }): Promise<AnchorChainingPathExecuteResult>;
}
type AnchorChainingFullPlanResult = (({
    success: true;
    plan: AnchorChainingPlan;
} | {
    success: false;
    error: unknown;
}) & {
    path: AnchorChainingPath;
});
export declare class AnchorChaining {
    private client;
    private resolver;
    readonly graph: AnchorGraph;
    private logger?;
    constructor(config: AnchorChainingConfig);
    getPaths(input: AnchorChainingPathInput): Promise<AnchorChainingPath[] | null>;
    getPlans(input: AnchorChainingPathInput, options?: ComputePlanOptions & {
        includeAllOutput?: false;
    }): Promise<AnchorChainingPlan[] | null>;
    getPlans(input: AnchorChainingPathInput, options: ComputePlanOptions & {
        includeAllOutput: true;
    }): Promise<AnchorChainingFullPlanResult[] | null>;
}
export {};
//# sourceMappingURL=chaining.d.ts.map