# How Nautilus Wallet Handles Transaction Mempool and Unconfirmed Transactions

> Discover how Nautilus Wallet manages unconfirmed transactions by querying the blockchain and mempool, ensuring stale UTXOs are cleared.

- Repository: [Nautilus Team/nautilus-wallet](https://github.com/nautls/nautilus-wallet)
- Tags: how-to-guide
- Published: 2026-03-07

---

**Nautilus Wallet tracks unconfirmed transactions through a zero-confirmation setting that queries both the blockchain and mempool, automatically cleaning up stale pending UTXOs when transactions leave the mempool.**

Nautilus Wallet is an open-source browser extension wallet for the Ergo blockchain. To provide accurate balance displays while transactions await confirmation, the wallet implements a sophisticated mempool handling system that optionally includes unconfirmed transactions in balance calculations and actively monitors pending transaction status.

## Zero-Confirmation Settings and Mempool Integration

### Enabling Zero-Confirmation Mode

The wallet exposes a user-configurable `zeroConf` flag in the application settings. When enabled, the wallet treats mempool transactions as valid for balance calculations and UTXO selection.

In [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts), the settings type definition includes:

```typescript
export type Settings = {
  …
  zeroConf: boolean;               // toggle for mempool inclusion
  …
};

```

The default value is defined in [`src/constants/settings.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/settings.ts) as `false`, ensuring conservative behavior for new users.

### Fetching Boxes from Blockchain and Mempool

When the wallet needs to retrieve UTXOs (boxes), the `fetchBoxes()` function in [`src/chains/ergo/boxFetcher.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/boxFetcher.ts) dynamically selects the data source based on the zero-confirmation setting:

```typescript
const from: BoxSource = includeUnconf ? "blockchain+mempool" : "blockchain";

let boxes = await graphQLService.getBoxes({ where: { addresses }, from });

```

The `includeUnconf` parameter is passed from [`ergoHandlers.ts`](https://github.com/nautls/nautilus-wallet/blob/main/ergoHandlers.ts) based on `settings.zeroConf`. This ensures that when zero-confirmation mode is active, the wallet sees unconfirmed incoming transactions and excludes spent outputs that are waiting for confirmation.

## Tracking Pending Transactions in the Mempool

### Mempool Transaction Lookup

To determine whether a pending transaction is still waiting for confirmation or has been included in a block (or dropped), Nautilus uses `graphQLService.mempoolTransactionsLookup()`. This method, located in [`src/chains/ergo/services/graphQlService.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/services/graphQlService.ts), queries the GraphQL backend for the presence of specific transaction IDs in the mempool:

```typescript
async mempoolTransactionsLookup(txIds: string[]): Promise<Set<string>> {
  const set = new Set<string>();
  const chunks = chunk(txIds, MAX_PARAMS_PER_REQUEST);

  for (const txIds of chunks) {
    const { data } = await this.#checkMempoolTxs({ transactionIds: txIds });
    if (data?.mempool?.transactions?.length === 0) continue;
    for (const tx of data.mempool.transactions) set.add(tx.transactionId);
  }
  return set;
}

```

The function returns a `Set<string>` containing only the transaction IDs still present in the mempool. This powers the wallet's ability to distinguish between transactions that are still pending versus those that have been confirmed or evicted.

### Merging Local Unconfirmed Boxes

When a user creates a transaction, the resulting output boxes are stored locally in `utxosDbService` before the transaction is confirmed. The [`boxFetcher.ts`](https://github.com/nautls/nautilus-wallet/blob/main/boxFetcher.ts) file merges these local unconfirmed boxes with the remote fetched boxes:

```typescript
if (localUnconfirmedBoxes.length > 0) {
  const lockedIds = localUnconfirmedBoxes.filter((x) => x.locked).map((x) => x.id);
  const unconfirmed = localUnconfirmedBoxes
    .filter((b) => !b.locked && b.content)
    .map((b) => b.content!);
  …
  if (unconfirmed.length > 0) boxes = unionBy(boxes, unconfirmed, (b) => b.boxId);
}

```

These local entries remain valid only while the parent transaction exists in the mempool. Once the transaction is confirmed or dropped, `checkPendingBoxes()` removes them from the local database.

## Cleaning Up Stale Pending UTXOs

### Automatic Cleanup on New Blocks

Nautilus implements an automatic cleanup mechanism to prevent stale pending UTXOs from accumulating. In [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts), the application watches for blockchain height changes and triggers `checkPendingBoxes()`:

```typescript
watch(() => chain.height, checkPendingBoxes);

```

This function retrieves all pending UTXOs from the local database, filters for those older than `UTXO_CHECK_INTERVAL`, queries the mempool to see which transactions are still pending, and removes entries for transactions that no longer exist in the mempool:

```typescript
async function checkPendingBoxes() {
  const dbBoxes = await utxosDbService.getAllPending();
  const boxesToCheck = dbBoxes.filter(
    (b) => b.spentTimestamp && Date.now() - b.spentTimestamp >= UTXO_CHECK_INTERVAL
  );
  if (boxesToCheck.length === 0) return;

  const txIds = uniq(boxesToCheck.map((b) => b.spentTxId));
  const mempool = await graphQLService.mempoolTransactionsLookup(txIds);
  await utxosDbService.removeByTxIds(
    txIds.filter((id) => !mempool.has(id))
  );
}

```

### The Pending UTXO Check Interval

The cleanup interval is defined in [`src/constants/intervals.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/intervals.ts) as `UTXO_CHECK_INTERVAL` (default 30 seconds). This prevents excessive GraphQL queries while ensuring that dropped or confirmed transactions are cleaned up promptly.

## Balance Queries and Zero-Confirmation Display

The background handlers in [`src/extension/background/ergoHandlers.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/extension/background/ergoHandlers.ts) respect the zero-confirmation setting when responding to balance and UTXO queries from the extension UI:

```typescript
// In background handler
const boxes = await fetchBoxes(walletId, settings.zeroConf);
…
return settings.zeroConf ? getRemoteBalance(walletId, tokenId) : getLocalBalance(walletId, tokenId);

```

When `settings.zeroConf` is `true`, `getRemoteBalance` queries the GraphQL backend with `from: "blockchain+mempool"`, ensuring that unconfirmed incoming and outgoing transactions are reflected in the displayed balance.

## Key Implementation Files

| File | Primary Responsibility |
|------|------------------------|
| [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts) | Holds `settings.zeroConf`; watches chain height → `checkPendingBoxes()` |
| [`src/chains/ergo/services/graphQlService.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/services/graphQlService.ts) | GraphQL wrapper; implements `mempoolTransactionsLookup` |
| [`src/chains/ergo/boxFetcher.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/boxFetcher.ts) | Retrieves boxes from `"blockchain+mempool"` and merges local unconfirmed boxes |
| [`src/extension/background/ergoHandlers.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/extension/background/ergoHandlers.ts) | Public API for UTXO & balance queries; respects zero‑conf |
| [`src/constants/settings.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/settings.ts) | Default `zeroConf: false` |
| [`src/constants/intervals.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/intervals.ts) | `UTXO_CHECK_INTERVAL` (time before a pending box is re‑checked) |

## Summary

- **Zero-confirmation mode** is controlled by the `zeroConf` setting in [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts), defaulting to `false` in [`src/constants/settings.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/settings.ts).
- **Mempool data** is retrieved via GraphQL using the `"blockchain+mempool"` source parameter in [`src/chains/ergo/boxFetcher.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/boxFetcher.ts).
- **Pending transaction monitoring** uses `mempoolTransactionsLookup()` in [`src/chains/ergo/services/graphQlService.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/services/graphQlService.ts) to check if specific transaction IDs remain in the mempool.
- **Automatic cleanup** occurs via `checkPendingBoxes()` in [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts), triggered on every new block height, removing local pending UTXOs whose transactions have left the mempool.
- **Balance accuracy** depends on whether `zeroConf` is enabled, with [`src/extension/background/ergoHandlers.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/extension/background/ergoHandlers.ts) switching between local and remote balance queries accordingly.

## Frequently Asked Questions

### How does Nautilus Wallet determine if a pending transaction is still valid?

Nautilus Wallet uses the `mempoolTransactionsLookup()` method in [`src/chains/ergo/services/graphQlService.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/services/graphQlService.ts) to query the GraphQL backend for specific transaction IDs. This returns a `Set` of transactions still present in the mempool. If a transaction ID is not in this set, the wallet assumes it has been confirmed or dropped and removes the associated pending UTXO from the local database via `checkPendingBoxes()`.

### What is the zero-confirmation setting and how does it affect my balance?

The `zeroConf` setting, defined in [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts) and defaulting to `false` in [`src/constants/settings.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/settings.ts), controls whether the wallet includes mempool transactions in balance calculations and UTXO selection. When enabled, [`src/chains/ergo/boxFetcher.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/boxFetcher.ts) queries the GraphQL backend with `from: "blockchain+mempool"`, allowing you to see incoming funds immediately and spend change outputs before confirmation.

### How often does Nautilus Wallet clean up stale pending transactions?

The wallet checks for stale pending UTXOs every time the blockchain height changes, as implemented in [`src/stores/appStore.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/stores/appStore.ts) via `watch(() => chain.height, checkPendingBoxes)`. Additionally, individual UTXOs are only checked against the mempool if they have been pending for longer than `UTXO_CHECK_INTERVAL` (30 seconds by default), defined in [`src/constants/intervals.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/constants/intervals.ts). This prevents excessive API calls while ensuring timely cleanup.

### Can I manually verify if my transaction is still in the mempool?

Yes, you can use the internal `graphQLService.mempoolTransactionsLookup()` method to check specific transaction IDs. While the wallet automatically handles this in `checkPendingBoxes()`, developers can call this method directly with an array of transaction IDs to receive a `Set` of those still present in the mempool, as shown in the implementation in [`src/chains/ergo/services/graphQlService.ts`](https://github.com/nautls/nautilus-wallet/blob/main/src/chains/ergo/services/graphQlService.ts).