import { MessageTransmitterClient, SvmSpokeClient } from "@across-protocol/contracts";
import { Address, IAccountMeta, KeyPairSigner, ReadonlyUint8Array, type TransactionSigner } from "@solana/kit";
import { Logger } from "winston";
import { DepositWithBlock, FillStatus, FillWithBlock, RelayData } from "../../interfaces";
import { BigNumber, EvmAddress, Address as SdkAddress, SvmAddress } from "../../utils";
import { SvmCpiEventsClient } from "./eventsClient";
import { AttestedCCTPMessage, SVMProvider } from "./types";
/**
 * @note: Average Solana slot duration is about 400-500ms. We can be conservative
 *        and choose 400 to ensure that the most slots get included in our ranges
 */
export declare const SLOT_DURATION_MS = 400;
type ProtoFill = Omit<RelayData, "recipient" | "outputToken"> & {
    destinationChainId: number;
    recipient: SvmAddress;
    outputToken: SvmAddress;
};
/**
 * Retrieves the chain time at a particular slot.
 */
export declare function getTimestampForSlot(provider: SVMProvider, slotNumber: bigint): Promise<number | undefined>;
/**
 * Returns the current fill deadline buffer.
 * @param provider SVM Provider instance
 * @param statePda Spoke Pool's State PDA
 * @returns fill deadline buffer
 */
export declare function getFillDeadline(provider: SVMProvider, statePda: Address): Promise<number>;
/**
 * Finds the deposit id at a specific block number.
 * @param blockTag The block number to search for the deposit ID at.
 * @returns The deposit ID.
 */
export declare function getDepositIdAtBlock(_contract: unknown, _blockTag: number): Promise<BigNumber>;
/**
 * Finds deposit events within a 2-day window ending at the specified slot.
 *
 * @remarks
 * This implementation uses a slot-limited search approach because Solana PDA state has
 * limitations that prevent directly referencing old deposit IDs. Unlike EVM chains where
 * we might use binary search across the entire chain history, in Solana we must query within
 * a constrained slot range.
 *
 * The search window is calculated by:
 * 1. Using the provided slot (or current confirmed slot if none is provided)
 * 2. Looking back 2 days worth of slots from that point
 *
 * We use a 2-day window because:
 * 1. Most valid deposits that need to be processed will be recent
 * 2. This covers multiple bundle submission periods
 * 3. It balances performance with practical deposit age
 *
 * @important
 * This function may return `undefined` for valid deposit IDs that are older than the search
 * window (approximately 2 days before the specified slot). This is an acceptable limitation
 * as deposits this old are typically not relevant to current operations.
 *
 * @param eventClient - SvmCpiEventsClient instance
 * @param depositId - The deposit ID to search for
 * @param slot - The slot to search up to (defaults to current slot). The search will look
 *              for deposits between (slot - secondsLookback) and slot.
 * @param secondsLookback - The number of seconds to look back for deposits (defaults to 2 days).
 * @returns The deposit if found within the slot window, undefined otherwise
 */
export declare function findDeposit(eventClient: SvmCpiEventsClient, depositId: BigNumber, slot?: bigint, secondsLookback?: number): Promise<DepositWithBlock | undefined>;
/**
 * Resolves the fill status of a deposit at a specific slot or at the current confirmed one.
 *
 * If no slot is provided, attempts to solve the fill status using the PDA. Otherwise, it is reconstructed from PDA events.
 *
 * @param programId - The spoke pool program ID.
 * @param relayData - Deposit information used to locate the fill status.
 * @param destinationChainId - Destination chain ID (must be an SVM chain).
 * @param provider - SVM provider instance.
 * @param svmEventsClient - SVM events client for querying events.
 * @param atHeight - (Optional) Specific slot number to query. Defaults to the latest confirmed slot.
 * @returns The fill status for the deposit at the specified or current slot.
 */
export declare function relayFillStatus(programId: Address, relayData: RelayData, destinationChainId: number, svmEventsClient: SvmCpiEventsClient, atHeight?: number): Promise<FillStatus>;
/**
 * Resolves fill statuses for multiple deposits at a specific or latest confirmed slot,
 * using PDAs when possible and falling back to events if needed.
 *
 * @param programId The spoke pool program ID.
 * @param relayData An array of relay data to resolve fill statuses for.
 * @param destinationChainId The destination chain ID (must be an SVM chain).
 * @param provider SVM Provider instance.
 * @param svmEventsClient SVM events client instance for querying events.
 * @param atHeight (Optional) The slot number to query at. If omitted, queries the latest confirmed slot.
 * @returns An array of fill statuses for the specified deposits at the requested slot (or at the current confirmed slot).
 */
export declare function fillStatusArray(programId: Address, relayData: RelayData[], destinationChainId: number, svmEventsClient: SvmCpiEventsClient, atHeight?: number, logger?: Logger): Promise<(FillStatus | undefined)[]>;
/**
 * Finds the `FilledRelay` event for a given deposit within the provided slot range.
 *
 * @param relayData - Deposit information that is used to complete a fill.
 * @param destinationChainId - Destination chain ID (must be an SVM chain).
 * @param svmEventsClient - SVM events client instance for querying events.
 * @param fromSlot - Starting slot to search.
 * @param toSlot (Optional) Ending slot to search. If not provided, the current confirmed slot will be used.
 * @returns The fill event with block info, or `undefined` if not found.
 */
export declare function findFillEvent(relayData: RelayData, destinationChainId: number, svmEventsClient: SvmCpiEventsClient, fromSlot: number, toSlot?: number): Promise<FillWithBlock | undefined>;
/**
 * @param spokePool Address (program ID) of the SvmSpoke.
 * @param relayData RelayData instance, supplemented with destinationChainId
 * @param relayer Address of the relayer filling the deposit.
 * @param repaymentChainId Optional repaymentChainId (defaults to destinationChainId).
 * @returns An Ethers UnsignedTransaction instance.
 */
export declare function fillRelayInstruction(spokePool: SvmAddress, relayData: ProtoFill, signer: TransactionSigner<string>, recipientTokenAccount: Address<string>, repaymentAddress?: EvmAddress | SvmAddress, repaymentChainId?: number): Promise<SvmSpokeClient.FillRelayInstruction<Address<"DLv3NggMiSaef97YCkew5xKUHDh13tVGZ7tydt3ZeAru">, string, string, string, string, string, string, string, string, string, string, string, string, string, []>>;
/**
 * @param mint Address of the token corresponding to the account being made.
 * @param relayer Address of the relayer filling the deposit.
 * @returns An instruction for creating a new token account.
 */
export declare function createTokenAccountsInstruction(mint: SvmAddress, relayer: TransactionSigner<string>): SvmSpokeClient.CreateTokenAccountsInstruction;
/**
 * @notice Return the fillRelay transaction for a given deposit
 * @param spokePoolAddr Address of the spoke pool we're trying to fill through
 * @param solanaClient RPC client to interact with Solana chain
 * @param relayData RelayData instance, supplemented with destinationChainId
 * @param signer signer associated with the relayer creating a Fill. Can be VoidSigner for gas estimation
 * @param repaymentChainId Chain id where relayer repayment is desired
 * @param repaymentAddress Address to which repayment will go to on repaymentChainId
 * @returns FillRelay transaction
 */
export declare function getFillRelayTx(spokePoolAddr: SvmAddress, solanaClient: SVMProvider, relayData: Omit<RelayData, "recipient" | "outputToken"> & {
    destinationChainId: number;
    recipient: SvmAddress;
    outputToken: SvmAddress;
}, signer: TransactionSigner, repaymentChainId: number, repaymentAddress: SdkAddress): Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
/**
 * Creates a fill instruction.
 * @param signer - The signer of the transaction.
 * @param solanaClient - The Solana client.
 * @param fillInput - The fill input.
 * @param tokenDecimals - The token decimals.
 * @param createRecipientAtaIfNeeded - Whether to create a recipient token account.
 * @returns The fill instruction.
 */
export declare const createFillInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, fillInput: SvmSpokeClient.FillRelayInput, tokenDecimals: number, createRecipientAtaIfNeeded?: boolean) => Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
/**
 * Creates a deposit instruction.
 * @param signer - The signer of the transaction.
 * @param solanaClient - The Solana client.
 * @param depositInput - The deposit input.
 * @param tokenDecimals - The token decimals.
 * @param createVaultAtaIfNeeded - Whether to create a vault token account.
 * @returns The deposit instruction.
 */
export declare const createDepositInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, depositInput: SvmSpokeClient.DepositInput, tokenDecimals: number, createVaultAtaIfNeeded?: boolean) => Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
/**
 * Creates a request slow fill instruction.
 * @param signer - The signer of the transaction.
 * @param solanaClient - The Solana client.
 * @param requestSlowFillInput - The input arguments for the `requestSlowFill` instruction.
 * @returns The request slow fill instruction.
 */
export declare const createRequestSlowFillInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, requestSlowFillInput: SvmSpokeClient.RequestSlowFillInput) => Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
/**
 * @notice Return the requestSlowFill transaction for a given deposit
 * @param spokePoolAddr Address of the spoke pool we're trying to fill through
 * @param solanaClient RPC client to interact with Solana chain
 * @param relayData RelayData instance, supplemented with destinationChainId
 * @param signer signer associated with the relayer creating a Fill.
 * @returns requestSlowFill transaction
 */
export declare function getSlowFillRequestTx(spokePoolAddr: SvmAddress, solanaClient: SVMProvider, relayData: Omit<RelayData, "recipient" | "outputToken"> & {
    destinationChainId: number;
    recipient: SvmAddress;
    outputToken: SvmAddress;
}, signer: TransactionSigner): Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
/**
 * Creates a close fill PDA instruction.
 * @param signer - The signer of the transaction.
 * @param solanaClient - The Solana client.
 * @param fillStatusPda - The fill status PDA.
 * @returns The close fill PDA instruction.
 */
export declare const createCloseFillPdaInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, fillStatusPda: Address) => Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
export declare const createReceiveMessageInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, input: MessageTransmitterClient.ReceiveMessageInput, remainingAccounts: IAccountMeta<string>[]) => Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
export declare function getAssociatedTokenAddress(owner: SvmAddress, mint: SvmAddress, tokenProgramId?: Address<string>): Promise<Address<string>>;
export declare function getRelayDataHash(relayData: RelayData, destinationChainId: number): string;
/**
 * Returns the delegate PDA for deposit.
 */
export declare function getDepositDelegatePda(depositData: {
    depositor: Address<string>;
    recipient: Address<string>;
    inputToken: Address<string>;
    outputToken: Address<string>;
    inputAmount: bigint;
    outputAmount: ReadonlyUint8Array;
    destinationChainId: bigint;
    exclusiveRelayer: Address<string>;
    quoteTimestamp: bigint;
    fillDeadline: bigint;
    exclusivityParameter: bigint;
    message: Uint8Array;
}, programId: Address<string>): Promise<Address<string>>;
/**
 * Returns the delegate PDA for depositNow.
 */
export declare function getDepositNowDelegatePda(depositData: {
    depositor: Address<string>;
    recipient: Address<string>;
    inputToken: Address<string>;
    outputToken: Address<string>;
    inputAmount: bigint;
    outputAmount: ReadonlyUint8Array;
    destinationChainId: bigint;
    exclusiveRelayer: Address<string>;
    fillDeadlineOffset: bigint;
    exclusivityPeriod: bigint;
    message: Uint8Array;
}, programId: Address<string>): Promise<Address<string>>;
/**
 * Returns the fill-delegate PDA for fillRelay.
 */
export declare function getFillRelayDelegatePda(relayHash: Uint8Array, repaymentChainId: bigint, repaymentAddress: Address<string>, programId: Address<string>): Promise<Address<string>>;
/**
 * Checks if a CCTP message has been processed.
 * @param solanaClient The Solana client.
 * @param signer The signer of the transaction.
 * @param nonce The nonce to check.
 * @param sourceDomain The source domain.
 * @returns True if the message has been processed, false otherwise.
 */
export declare const hasCCTPV1MessageBeenProcessed: (solanaClient: SVMProvider, signer: KeyPairSigner, nonce: number, sourceDomain: number) => Promise<boolean>;
/**
 * Returns the account metas for a tokenless message.
 * @returns The account metas for a tokenless message.
 */
export declare function getAccountMetasForTokenlessMessage(): Promise<IAccountMeta<string>[]>;
/**
 * Returns the CCTP v1 receive message transaction.
 * @param solanaClient The Solana client.
 * @param signer The signer of the transaction.
 * @param message The CCTP message.
 * @param hubChainId The chain ID of the hub.
 * @returns The CCTP v1 receive message transaction.
 */
export declare function getCCTPV1ReceiveMessageTx(solanaClient: SVMProvider, signer: KeyPairSigner, message: AttestedCCTPMessage, hubChainId: number): Promise<import("@solana/kit").TransactionMessageWithBlockhashLifetime & import("@solana/kit").ITransactionMessageWithFeePayerSigner<string, TransactionSigner<string>> & Omit<Readonly<{
    instructions: readonly import("@solana/kit").IInstruction<string, readonly (IAccountMeta<string> | import("@solana/kit").IAccountLookupMeta<string, string>)[]>[];
    version: 0;
}>, "feePayer">>;
/**
 * Finalizes CCTP deposits and messages on Solana.
 *
 * @param solanaClient The Solana client.
 * @param attestedMessages The CCTP messages to Solana.
 * @param signer A base signer to be converted into a Solana signer.
 * @param simulate Whether to simulate the transaction.
 * @param hubChainId The chain ID of the hub.
 * @returns A list of executed transaction signatures.
 */
export declare function finalizeCCTPV1Messages(solanaClient: SVMProvider, attestedMessages: AttestedCCTPMessage[], signer: KeyPairSigner, simulate?: boolean, hubChainId?: number): Promise<string[]>;
export {};
