import { TxStatus } from '@aztec/circuit-types';
import { retryUntil } from '@aztec/foundation/retry';
export const DefaultWaitOpts = {
    ignoreDroppedReceiptsFor: 5,
    timeout: 60,
    provenTimeout: 600,
    interval: 1,
    debug: false,
    waitForNotesAvailable: true,
};
/**
 * The SentTx class represents a sent transaction through the PXE, providing methods to fetch
 * its hash, receipt, and mining status.
 */
export class SentTx {
    constructor(pxe, txHashPromise) {
        this.pxe = pxe;
        this.txHashPromise = txHashPromise;
    }
    /**
     * Retrieves the transaction hash of the SentTx instance.
     * The function internally awaits for the 'txHashPromise' to resolve, and then returns the resolved transaction hash.
     *
     * @returns A promise that resolves to the transaction hash of the SentTx instance.
     * TODO(#7717): Don't throw here.
     */
    getTxHash() {
        return this.txHashPromise;
    }
    /**
     * Retrieve the transaction receipt associated with the current SentTx instance.
     * The function fetches the transaction hash using 'getTxHash' and then queries
     * the PXE to get the corresponding transaction receipt.
     *
     * @returns A promise that resolves to a TxReceipt object representing the fetched transaction receipt.
     */
    async getReceipt() {
        const txHash = await this.getTxHash();
        return await this.pxe.getTxReceipt(txHash);
    }
    /**
     * Awaits for a tx to be mined and returns the receipt. Throws if tx is not mined.
     * @param opts - Options for configuring the waiting for the tx to be mined.
     * @returns The transaction receipt.
     */
    async wait(opts) {
        const receipt = await this.waitForReceipt(opts);
        if (receipt.status !== TxStatus.SUCCESS && !opts?.dontThrowOnRevert) {
            throw new Error(`Transaction ${await this.getTxHash()} was ${receipt.status}. Reason: ${receipt.error ?? 'unknown'}`);
        }
        if (opts?.proven && receipt.blockNumber !== undefined) {
            await this.waitForProven(receipt.blockNumber, opts);
        }
        if (opts?.debug) {
            const txHash = await this.getTxHash();
            const { data: tx } = (await this.pxe.getTxEffect(txHash));
            receipt.debugInfo = {
                noteHashes: tx.noteHashes,
                nullifiers: tx.nullifiers,
                publicDataWrites: tx.publicDataWrites,
                l2ToL1Msgs: tx.l2ToL1Msgs,
            };
        }
        return receipt;
    }
    /**
     * Gets unencrypted logs emitted by this tx.
     * @remarks This function will wait for the tx to be mined if it hasn't been already.
     * @returns The requested logs.
     */
    async getUnencryptedLogs() {
        await this.wait();
        return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() });
    }
    async waitForReceipt(opts) {
        const txHash = await this.getTxHash();
        const startTime = Date.now();
        const ignoreDroppedReceiptsFor = opts?.ignoreDroppedReceiptsFor ?? DefaultWaitOpts.ignoreDroppedReceiptsFor;
        return await retryUntil(async () => {
            const txReceipt = await this.pxe.getTxReceipt(txHash);
            // If receipt is not yet available, try again
            if (txReceipt.status === TxStatus.PENDING) {
                return undefined;
            }
            // If the tx was "dropped", either return it or ignore based on timing.
            // We can ignore it at first because the transaction may have been sent to node 1, and now we're asking node 2 for the receipt.
            // If we don't allow a short grace period, we could incorrectly return a TxReceipt with status DROPPED.
            if (txReceipt.status === TxStatus.DROPPED) {
                const elapsedSeconds = (Date.now() - startTime) / 1000;
                if (!ignoreDroppedReceiptsFor || elapsedSeconds > ignoreDroppedReceiptsFor) {
                    return txReceipt;
                }
                return undefined;
            }
            // If we don't care about waiting for notes to be synced, return the receipt
            const waitForNotesAvailable = opts?.waitForNotesAvailable ?? DefaultWaitOpts.waitForNotesAvailable;
            if (!waitForNotesAvailable) {
                return txReceipt;
            }
            // Check if all sync blocks on the PXE Service are greater or equal than the block in which the tx was mined
            const { blocks } = await this.pxe.getSyncStatus();
            const targetBlock = txReceipt.blockNumber;
            const areNotesAvailable = blocks >= targetBlock;
            return areNotesAvailable ? txReceipt : undefined;
        }, 'isMined', opts?.timeout ?? DefaultWaitOpts.timeout, opts?.interval ?? DefaultWaitOpts.interval);
    }
    async waitForProven(minedBlock, opts) {
        return await retryUntil(async () => {
            const provenBlock = await this.pxe.getProvenBlockNumber();
            return provenBlock >= minedBlock ? provenBlock : undefined;
        }, 'isProven', opts?.provenTimeout ?? DefaultWaitOpts.provenTimeout, opts?.interval ?? DefaultWaitOpts.interval);
    }
}
//# sourceMappingURL=data:application/json;base64, 