import { MessageTransmitterClient, SvmSpokeClient } from "@across-protocol/contracts";
import { Mint } from "@solana-program/token";
import { Account, AccountMeta, Address, FetchAccountConfig, Instruction, KeyPairSigner, ReadonlyUint8Array, type TransactionSigner, type WritableAccount, type ReadonlyAccount, type Commitment } from "@solana/kit";
import winston from "winston";
import { DepositWithBlock, FillStatus, FillWithBlock, RelayData, RelayDataWithMessageHash } from "../../interfaces";
import { BigNumber, EvmAddress, Address as SdkAddress, SvmAddress } from "../../utils";
import { type AcrossPlusMessage } from "./";
import { SvmCpiEventsClient } from "./eventsClient";
import { AttestedCCTPMessage, SVMProvider, LatestBlockhash, SolanaTransaction } 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;
export declare const SOLANA_TX_SIZE_LIMIT = 1232;
type ProtoFill = Omit<RelayData, "recipient" | "outputToken"> & {
    destinationChainId: number;
    recipient: SvmAddress;
    outputToken: SvmAddress;
};
type CCTPDepositAccounts = {
    tokenMessenger: Address;
    tokenMinter: Address;
    localToken: Address;
    cctpEventAuthority: Address;
    remoteTokenMessenger: Address;
    tokenMessengerMinterSenderAuthority: Address;
    messageTransmitter: Address;
};
export declare function getSlot(provider: SVMProvider, commitment: Commitment, logger?: winston.Logger): Promise<bigint>;
/**
 * Retrieves the chain time at a particular slot.
 */
export declare function getTimestampForSlot(provider: SVMProvider, slotNumber: bigint, maxRetries?: number, logger?: winston.Logger): 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, logger: winston.Logger, slot?: bigint, secondsLookback?: number): Promise<Omit<DepositWithBlock, "originChainId" | "quoteBlockNumber" | "fromLiteChain" | "toLiteChain"> | 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: RelayDataWithMessageHash, destinationChainId: number, svmEventsClient: SvmCpiEventsClient, logger: winston.Logger, 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: RelayDataWithMessageHash[], destinationChainId: number, svmEventsClient: SvmCpiEventsClient, logger: winston.Logger, atHeight?: number): 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: RelayDataWithMessageHash, destinationChainId: number, svmEventsClient: SvmCpiEventsClient, fromSlot: number, toSlot?: number, logger?: winston.Logger): 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<Instruction>;
/**
 * @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<SolanaTransaction>;
/**
 * Creates a fill instruction with an instruction params PDA as the relayData input.
 * @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 getIPFillRelayTx(spokePoolAddr: SvmAddress, solanaClient: SVMProvider, relayData: Omit<RelayData, "recipient" | "outputToken"> & {
    destinationChainId: number;
    recipient: SvmAddress;
    outputToken: SvmAddress;
}, signer: TransactionSigner, repaymentChainId: number, repaymentAddress: SdkAddress): Promise<SolanaTransaction>;
/**
 * 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 createRecipientAta - Whether to create a recipient token account.
 * @returns The fill instruction.
 */
export declare const createFillInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, fillInput: SvmSpokeClient.FillRelayInput, relayData: Pick<SvmSpokeClient.RelayDataArgs, "outputAmount" | "recipient">, tokenDecimals: number, createRecipientAta?: boolean, remainingAccounts?: (WritableAccount | ReadonlyAccount)[]) => Promise<SolanaTransaction>;
export declare function deserializeMessage(_message: string): AcrossPlusMessage;
/**
 * 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<SolanaTransaction>;
/**
 * 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<SolanaTransaction>;
/**
 * @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<SolanaTransaction>;
/**
 * 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<SolanaTransaction>;
export declare const createReceiveMessageInstruction: (signer: TransactionSigner, solanaClient: SVMProvider, input: MessageTransmitterClient.ReceiveMessageInput, remainingAccounts: AccountMeta<string>[]) => Promise<SolanaTransaction>;
export declare function getAssociatedTokenAddress(owner: SvmAddress, mint: SvmAddress, tokenProgramId?: Address<string>): Promise<Address<string>>;
export declare function getRelayDataHash(relayData: RelayData & {
    messageHash: string;
}, destinationChainId: number): string;
export declare function getIPForFillRelayTxs(spokePool: SvmAddress, relayData: RelayData, repaymentChainId: number, repaymentAddress: SdkAddress, signer: TransactionSigner<string>, provider: SVMProvider): Promise<Array<SolanaTransaction>>;
/**
 * Returns a set of instructions to execute to fill a relay via instruction params.
 * @param spokePool The program ID of the Solana spoke pool.
 * @param relayData The relay data to write to the instruction params PDA.
 * @param repaymentChainId: The chain ID to take repayment.
 * @param repaymentAddress: The address to receive repayment on the specified repayment chain.
 * @param signer The transaction signer and authority of the instruction params PDA.
 * @param maxWriteSize The maximum fragment size to write to instruction params.
 */
export declare function getFillRelayViaInstructionParamsInstructions(spokePool: Address<string>, relayData: RelayData, repaymentChainId: number, repaymentAddress: SdkAddress, signer: TransactionSigner<string>, provider: SVMProvider, maxWriteSize?: number): Promise<Instruction[]>;
/**
 * 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.
 * @dev This function intentionally does not have error handling for `getCCTPNoncePda` nor `simulateAndDecode` since
 * the error handling would have to account for the asynchronous opening/closing of PDAs, which is better handled downstream,
 * where the caller of this function has more context.
 */
export declare const hasCCTPV1MessageBeenProcessed: (solanaClient: SVMProvider, signer: KeyPairSigner, nonce: number, sourceDomain: number, latestBlockhash?: LatestBlockhash) => Promise<boolean>;
/**
 * Returns the account metas for a tokenless message.
 * @returns The account metas for a tokenless message.
 */
export declare function getAccountMetasForTokenlessMessage(solanaClient: SVMProvider, signer: KeyPairSigner, messageBytes: string): Promise<AccountMeta<string>[]>;
/**
 * Returns the required PDAs for a deposit message.
 * @param hubChainId The chain ID of the corresponding Across hub.
 * @param cctpSourceDomain The source chain (Solana) domain ID.
 * @param tokenMessengerMinter The token messenger minter address.
 * @param messageTransmitterAddress The message transmitter address.
 */
export declare function getCCTPDepositAccounts(hubChainId: number, cctpDestinationDomainId: number, tokenMessengerMinterAddress: Address, messageTransmitterAddress: Address): Promise<CCTPDepositAccounts>;
/**
 * Returns true if the input deposit's corresponding relay data would result in a transaction size
 * that is larger than the Solana transaction size limit.
 * @param fillRelayTx The compilable fill relay transaction to check.
 * @returns Object containing a boolean if the input deposit requires a multipart fill, false otherwise and
 * the number of bytes in the serialized transaction.
 */
export declare function isSVMFillTooLarge(fillRelayTx: SolanaTransaction): {
    tooLarge: boolean;
    sizeBytes: number;
};
/**
 * Returns the byte size of a base64 transaction.
 * @param base64TxString base64 serialized Solana transaction.
 * @returns The number of bytes in the transaction.
 */
export declare function base64StrToByteSize(base64TxString: string): number;
/**
 * Returns the size of the fill relay transaction using the input relayData.
 * @param fillTx The compilable fill relay transaction.
 * @returns The number of bytes in the serialized fillRelay transaction.
 */
export declare function calculateFillSizeBytes(fillTx: SolanaTransaction): number;
/**
 * 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.
 * @param recipientAta The ATA of the recipient address (used for token finalizations only).
 * @returns The CCTP v1 receive message transaction.
 */
export declare function getCCTPV1ReceiveMessageTx(solanaClient: SVMProvider, signer: KeyPairSigner, message: AttestedCCTPMessage, hubChainId: number, recipientAta: SvmAddress): Promise<SolanaTransaction>;
/**
 * 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 recipientAta The ATA of the recipient address (used for token finalizations only).
 * @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, recipientAta: SvmAddress, simulate?: boolean, hubChainId?: number): Promise<string[]>;
export declare function getMintInfo(solanaClient: SVMProvider, mint: Address<string>, config?: FetchAccountConfig): Promise<Account<Mint, string>>;
export {};
//# sourceMappingURL=SpokeUtils.d.ts.map