import type { Address } from '@solana/addresses';
import type {
    AccountInfoBase,
    AccountInfoWithBase64EncodedData,
    AccountInfoWithBase64EncodedZStdCompressedData,
    AccountInfoWithJsonData,
    Base58EncodedBytes,
    Base64EncodedDataResponse,
    Commitment,
    Lamports,
    Slot,
    SolanaRpcResponse,
    TokenBalance,
    TransactionError,
    TransactionForFullMetaInnerInstructionsParsed,
    TransactionForFullMetaInnerInstructionsUnparsed,
} from '@solana/rpc-types';
import type { Base64EncodedWireTransaction, TransactionBlockhashLifetime } from '@solana/transactions';

type SimulateTransactionConfigBase = Readonly<{
    /**
     * Simulate the transaction as of the highest slot that has reached this level of commitment.
     *
     * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For
     * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment
     * is `"confirmed"` unless configured otherwise. Unmitigated by an API layer on the client, the
     * default commitment applied by the server is `"finalized"`.
     */
    commitment?: Commitment;
    /**
     * If `true` the response will include inner instructions. These inner instructions will be
     * `jsonParsed` where possible, otherwise `json`.
     * @defaultValue false
     */
    innerInstructions?: boolean;
    /**
     * Prevents accessing stale data by enforcing that the RPC node has processed transactions up to
     * this slot
     */
    minContextSlot?: Slot;
}>;

// Both are optional booleans, but conflict - so cannot both be true
type SigVerifyAndReplaceRecentBlockhashConfig<TReplaceBlockhash extends boolean | undefined = false | undefined> =
    TReplaceBlockhash extends true
        ? Readonly<{
              /** if `true` the transaction recent blockhash will be replaced with the most recent blockhash. (conflicts with `sigVerify`) */
              replaceRecentBlockhash: true;
              /** if `true` the transaction signatures will be verified (conflicts with `replaceRecentBlockhash`) */
              sigVerify?: false;
          }>
        :
              | Readonly<{
                    /** if `true` the transaction recent blockhash will be replaced with the most recent blockhash. (conflicts with `sigVerify`) */
                    replaceRecentBlockhash?: boolean;
                    /** if `true` the transaction signatures will be verified (conflicts with `replaceRecentBlockhash`) */
                    sigVerify?: false;
                }>
              | Readonly<{
                    /** if `true` the transaction recent blockhash will be replaced with the most recent blockhash. (conflicts with `sigVerify`) */
                    replaceRecentBlockhash?: false;
                    /** if `true` the transaction signatures will be verified (conflicts with `replaceRecentBlockhash`) */
                    sigVerify: true;
                }>;

type AccountsConfigWithBase64EncodingZstdCompression = Readonly<{
    accounts: {
        /** An `array` of accounts to return */
        addresses: readonly Address[];
        /** Encoding for returned Account data */
        encoding: 'base64+zstd';
    };
}>;

type AccountsConfigWithJsonParsedEncoding = Readonly<{
    accounts: {
        /** An `array` of accounts to return */
        addresses: readonly Address[];
        /** Encoding for returned Account data */
        encoding: 'jsonParsed';
    };
}>;

type AccountsConfigWithBase64Encoding = Readonly<{
    accounts: {
        /** An `array` of accounts to return */
        addresses: readonly Address[];
        // Optional because this is the default encoding
        /** Encoding for returned Account data */
        encoding?: 'base64';
    };
}>;

type WithInnerInstructionsConfig = Readonly<{
    innerInstructions: true;
}>;

type SimulateTransactionApiResponseBase = Readonly<{
    /** If the transaction failed, this property will contain the error */
    err: TransactionError | null;
    /** The fee the transaction would have paid */
    fee: Lamports | null;
    /** The number of bytes of all accounts loaded by this transaction */
    loadedAccountsDataSize?: number;
    /** Addresses loaded from address lookup tables */
    loadedAddresses: Readonly<{
        readonly: readonly Address[];
        writable: readonly Address[];
    }> | null;
    /**
     * Array of log messages the transaction instructions output during execution, `null` if
     * simulation failed before the transaction was able to execute (for example due to an invalid
     * blockhash or signature verification failure)
     */
    logs: string[] | null;
    /** Lamport balances for each account after the transaction would have been processed */
    postBalances: readonly Lamports[] | null;
    /** Token balances for each token account after the transaction would have been processed */
    postTokenBalances: readonly TokenBalance[] | null;
    /** Lamport balances for each account before the transaction was processed */
    preBalances: readonly Lamports[] | null;
    /** Token balances for each token account before the transaction was processed */
    preTokenBalances: readonly TokenBalance[] | null;
    /**
     * The blockhash and last valid block height used to simulate the transaction. This is `null`
     * unless `replaceRecentBlockhash` was `true`, in which case it contains the blockhash that the
     * transaction's recent blockhash was replaced with.
     */
    replacementBlockhash: TransactionBlockhashLifetime | null;
    /** The most-recent return data generated by an instruction in the transaction */
    returnData: Readonly<{
        /** The return data itself, as base-64 encoded binary data */
        data: Base64EncodedDataResponse;
        /** The program that generated the return data */
        programId: Address;
    }> | null;
    /** The number of compute budget units consumed during the processing of this transaction */
    unitsConsumed?: bigint;
}>;

type SimulateTransactionApiResponseWithAccounts<T extends AccountInfoBase> = Readonly<{
    /** Array of accounts with the same length as the `accounts.addresses` array in the request */
    accounts: (T | null)[];
}>;

type SimulateTransactionApiResponseWithInnerInstructions = Readonly<
    TransactionForFullMetaInnerInstructionsParsed | TransactionForFullMetaInnerInstructionsUnparsed
>;

type SimulateTransactionApiResponseWithReplacementBlockhash = Readonly<{
    /**
     * The blockhash that the transaction's recent blockhash was replaced with, along with the last
     * block height at which it is valid. Because `replaceRecentBlockhash` was `true`, this narrows
     * the base response's `replacementBlockhash` to a non-`null` value.
     */
    replacementBlockhash: TransactionBlockhashLifetime;
}>;

export type SimulateTransactionApi = {
    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData> &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData> &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<
                AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData
            > &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<
                AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData
            > &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData> &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config?: SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        Readonly<{ readonly accounts: null }> &
            SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config?: SigVerifyAndReplaceRecentBlockhashConfig<true> & SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        Readonly<{ readonly accounts: null }> &
            SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state,
     * obtain the list of inner instructions run, if any, and replace the transaction's blockhash
     * with the most recent one.
     *
     * If the listed accounts have data, it will be returned in the response as a tuple whose first
     * element is a base64-encoded string.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64--with-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData> &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state, and
     * replace the transaction's blockhash with the most recent one.
     *
     * If the listed accounts have data, it will be returned in the response as a tuple whose first
     * element is a base64-encoded string.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64--no-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData> &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state,
     * obtain the list of inner instructions run, if any, and replace the transaction's blockhash
     * with the most recent one.
     *
     * If the listed accounts have data, it will first be compressed using
     * [ZStandard](https://facebook.github.io/zstd/) and the result will be returned in the response
     * as a tuple whose first element is a base64-encoded string.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64-zstd-compressed--with-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<
                AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData
            > &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state, and
     * replace the transaction's blockhash with the most recent one.
     *
     * If the listed accounts have data, it will first be compressed using
     * [ZStandard](https://facebook.github.io/zstd/) and the result will be returned in the response
     * as a tuple whose first element is a base64-encoded string.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64-zstd-compressed--no-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<
                AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData
            > &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state,
     * obtain the list of inner instructions run, if any, and replace the transaction's blockhash
     * with the most recent one.
     *
     * If the listed accounts have data, the server will attempt to process it using a parser
     * specific to each account's owning program. If successful, the parsed data will be returned in
     * the response as JSON. Otherwise, the raw account data will be returned in the response as a
     * tuple whose first element is a base64-encoded string.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-parsed--with-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData> &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state, and
     * replace the transaction's blockhash with the most recent one.
     *
     * If the listed accounts have data, the server will attempt to process it using a parser
     * specific to each account's owning program. If successful, the parsed data will be returned in
     * the response as JSON. Otherwise, the raw account data will be returned in the response as a
     * tuple whose first element is a base64-encoded string.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-parsed--no-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData> &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, obtain the list of inner instructions run, if any, and
     * replace the transaction's blockhash with the most recent one.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label no-accounts--with-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: SigVerifyAndReplaceRecentBlockhashConfig<true> &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        Readonly<{ readonly accounts: null }> &
            SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithInnerInstructions &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /**
     * Simulate sending a transaction, and replace the transaction's blockhash with the most recent
     * one.
     *
     * The replacement blockhash and the blockheight until which it is valid will be returned in the
     * response.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label no-accounts--no-inner-instructions--with-replacement-blockhash}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: SigVerifyAndReplaceRecentBlockhashConfig<true> & SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        Readonly<{ readonly accounts: null }> &
            SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithReplacementBlockhash
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData> &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData>
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<
                AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData
            > &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData>
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData> &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase,
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData>
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config?: SigVerifyAndReplaceRecentBlockhashConfig & SimulateTransactionConfigBase & WithInnerInstructionsConfig,
    ): SolanaRpcResponse<
        Readonly<{ readonly accounts: null }> &
            SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /** @deprecated Set `encoding` to `'base64'` when calling this method */
    simulateTransaction(
        base58EncodedWireTransaction: Base58EncodedBytes,
        config?: SigVerifyAndReplaceRecentBlockhashConfig & SimulateTransactionConfigBase,
    ): SolanaRpcResponse<Readonly<{ readonly accounts: null }> & SimulateTransactionApiResponseBase>;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state, and
     * obtain the list of inner instructions run, if any.
     *
     * If the listed accounts have data, it will be returned in the response as a tuple whose first
     * element is a base64-encoded string.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64--with-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData> &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state.
     *
     * If the listed accounts have data, it will be returned in the response as a tuple whose first
     * element is a base64-encoded string.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64--no-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64Encoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedData>
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state, and
     * obtain the list of inner instructions run, if any.
     *
     * If the listed accounts have data, it will first be compressed using
     * [ZStandard](https://facebook.github.io/zstd/) and the result will be returned in the response
     * as a tuple whose first element is a base64-encoded string.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64-zstd-compressed--with-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<
                AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData
            > &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state.
     *
     * If the listed accounts have data, it will first be compressed using
     * [ZStandard](https://facebook.github.io/zstd/) and the result will be returned in the response
     * as a tuple whose first element is a base64-encoded string.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-base64-zstd-compressed--no-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithBase64EncodingZstdCompression &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithBase64EncodedZStdCompressedData>
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state, and
     * obtain the list of inner instructions run, if any.
     *
     * If the listed accounts have data, the server will attempt to process it using a parser
     * specific to each account's owning program. If successful, the parsed data will be returned in
     * the response as JSON. Otherwise, the raw account data will be returned in the response as a
     * tuple whose first element is a base64-encoded string.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-parsed--with-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData> &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /**
     * Simulate sending a transaction, fetch a list of accounts in their post-simulation state.
     *
     * If the listed accounts have data, the server will attempt to process it using a parser
     * specific to each account's owning program. If successful, the parsed data will be returned in
     * the response as JSON. Otherwise, the raw account data will be returned in the response as a
     * tuple whose first element is a base64-encoded string.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label accounts-parsed--no-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: AccountsConfigWithJsonParsedEncoding &
            SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<
        SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithAccounts<AccountInfoBase & AccountInfoWithJsonData>
    >;

    /**
     * Simulate sending a transaction, and obtain the list of inner instructions run, if any.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label no-accounts--with-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: SigVerifyAndReplaceRecentBlockhashConfig &
            SimulateTransactionConfigBase &
            WithInnerInstructionsConfig & { encoding: 'base64' },
    ): SolanaRpcResponse<
        Readonly<{ readonly accounts: null }> &
            SimulateTransactionApiResponseBase &
            SimulateTransactionApiResponseWithInnerInstructions
    >;

    /**
     * Simulate sending a transaction.
     *
     * @param base64EncodedWireTransaction A fully signed transaction in wire format, as a base-64
     * encoded string. Use {@link getBase64EncodedWireTransaction} to obtain this.
     *
     * {@label no-accounts--no-inner-instructions}
     * @see https://solana.com/docs/rpc/http/simulatetransaction
     */
    simulateTransaction(
        base64EncodedWireTransaction: Base64EncodedWireTransaction,
        config: SigVerifyAndReplaceRecentBlockhashConfig & SimulateTransactionConfigBase & { encoding: 'base64' },
    ): SolanaRpcResponse<Readonly<{ readonly accounts: null }> & SimulateTransactionApiResponseBase>;
};
