How to Handle Zero-Confirmation Transactions in Nautilus Wallet: A Complete Developer's Guide
Nautilus Wallet supports zero-confirmation transactions by conditionally including unconfirmed UTXOs from the mempool when the zeroConf setting is enabled, allowing immediate spending of incoming funds while accepting the risks of blockchain reorganizations and potential double-spends.
Zero-confirmation transactions allow cryptocurrency users to spend funds immediately after receiving them, before they are mined into a block. In Nautilus Wallet, this feature is implemented through a configurable zeroConf flag that propagates through the entire application stack—from user settings to transaction construction and balance calculation. This guide explains the technical implementation and recommended workflow for handling zero-confirmation transactions in Nautilus Wallet.
Understanding Zero-Confirmation Support in Nautilus Wallet
The Core Setting: zeroConf Flag
The foundation of zero-confirmation support resides in the application's settings layer. In src/constants/settings.ts, the zeroConf property defaults to false to ensure conservative security by default:
// src/constants/settings.ts
export const DEFAULT_SETTINGS = { …, zeroConf: false, … };
This setting is strongly typed in the Pinia store defined in src/stores/appStore.ts:
// src/stores/appStore.ts
export type Settings = { …, zeroConf: boolean; … };
How the Flag Propagates Through the Application
When a user enables zero-confirmation transactions through the UI, the appStore.settings.zeroConf value updates to true. This boolean then flows through three critical pathways:
- Transaction Building: The transaction builder passes the flag to
fetchBoxes()to include mempool UTXOs - Balance Calculation: The wallet store merges pool balances only when the flag is active
- DApp Connector: Extension background handlers respect the setting for external API calls
Technical Implementation: From Settings to Transaction Building
Step 1: Settings Definition and Storage
The settings persist across sessions through the Pinia store. The zeroConf boolean maintains type safety throughout the application, ensuring that any component accessing settings knows exactly what data to expect.
Step 2: Fetching Boxes with Mempool Awareness
The core logic for including unconfirmed transactions lives in src/chains/ergo/boxFetcher.ts. The fetchBoxes() function accepts an includeUnconf parameter that determines whether to query only the blockchain or include the mempool:
// src/chains/ergo/boxFetcher.ts
export async function fetchBoxes(walletId: number, includeUnconf = true): Promise<ChainProviderBox<string>[]> {
const from: BoxSource = includeUnconf ? "blockchain+mempool" : "blockchain";
…
}
When includeUnconf is true, the GraphQL query requests data from both "blockchain+mempool" sources, returning UTXOs that have not yet been mined.
Step 3: Transaction Builder Integration
Transaction construction in src/chains/ergo/transaction/builder.ts integrates the zero-confirmation setting by passing app.settings.zeroConf directly to fetchBoxes():
// src/chains/ergo/transaction/builder.ts
const [inputs, currentHeight] = await Promise.all([
fetchBoxes(wallet.id, app.settings.zeroConf),
graphQLService.getHeight()
]);
This ensures that both RBF cancellation transactions and standard P2P transactions can spend unconfirmed UTXOs when the user has explicitly enabled the feature.
Step 4: Balance Calculation and UI Updates
The wallet store in src/stores/walletStore.ts handles how unconfirmed balances appear in the UI. It conditionally merges pool balances based on the zeroConf setting:
// src/stores/walletStore.ts
const poolBalance = appStore.settings.zeroConf ? new Map(pool.balance) : new Map();
When zero-confirmation is disabled, the pool balance map remains empty, showing only confirmed UTXOs. When enabled, the map contains unconfirmed amounts, allowing the UI to display updated balances immediately after transaction submission.
Step 5: DApp Connector API Compliance
The extension background handlers in src/extension/background/ergoHandlers.ts ensure that connected decentralized applications respect the user's zero-confirmation preference. The getUTxOs and getBalance functions check the setting before returning data:
// src/extension/background/ergoHandlers.ts
const settings = await getSettings();
const boxes = await fetchBoxes(walletId, settings.zeroConf);
…
return settings.zeroConf ? getRemoteBalance(walletId, tokenId) : getLocalBalance(walletId, tokenId);
This prevents DApps from accidentally spending unconfirmed UTXOs when the user has disabled the feature, maintaining security boundaries across the API boundary.
Enabling and Using Zero-Confirmation Transactions
To handle zero-confirmation transactions in Nautilus Wallet, follow this workflow:
-
Enable the setting – Navigate to Settings and toggle "Zero-Confirmation" to
true. This updatesappStore.settings.zeroConf. -
Construct transactions normally – Call the standard transaction builders. The
fetchBoxes()function automatically includes mempool UTXOs when the flag is active:const unsigned = await createP2PTransaction({ … }); -
Sign and submit – After signing, broadcast the transaction. The wallet reflects the new balance immediately because
poolBalancemerges unconfirmed amounts. -
Query via DApp connector – Connected applications receive mempool-aware balances when calling
window.nautilus.getBalance('all').
Risks and Considerations
While zero-confirmation transactions improve UX, they introduce specific risks:
- Blockchain reorganizations – Unconfirmed UTXOs can drop from the mempool during a reorg, causing transactions that spent them to fail.
- Double-spend potential – Without block confirmation, conflicting transactions might replace the unconfirmed UTXO you received.
- Balance volatility – The UI may display balances that decrease if the unconfirmed transaction is evicted or replaced.
Enable zeroConf only when you understand these trade-offs, typically for low-value or high-frequency operations where speed outweighs the security of confirmation.
Summary
- Nautilus Wallet implements zero-confirmation support through a boolean
zeroConfflag insrc/constants/settings.tsandsrc/stores/appStore.ts. - The
fetchBoxes()function insrc/chains/ergo/boxFetcher.tsqueries"blockchain+mempool"when the flag is true, returning unconfirmed UTXOs. - Transaction builders in
src/chains/ergo/transaction/builder.tsautomatically spend unconfirmed inputs whenapp.settings.zeroConfis enabled. - Balance calculations in
src/stores/walletStore.tsmerge pool balances only when the setting is active, providing immediate UI feedback. - DApp connector APIs in
src/extension/background/ergoHandlers.tsrespect the flag, ensuring external applications handle unconfirmed UTXOs according to user preference.
Frequently Asked Questions
What are the risks of enabling zero-confirmation transactions in Nautilus Wallet?
Enabling zero-confirmation transactions exposes users to blockchain reorganizations and potential double-spends. If the network drops an unconfirmed UTXO from the mempool, any transaction spending it will fail. Additionally, conflicting transactions might replace unconfirmed UTXOs before they are mined, causing the wallet's displayed balance to revert unexpectedly.
How does Nautilus Wallet fetch unconfirmed UTXOs when zeroConf is enabled?
When zeroConf is set to true, the fetchBoxes() function in src/chains/ergo/boxFetcher.ts sets the BoxSource to "blockchain+mempool". This parameter instructs the GraphQL query to return boxes from both the confirmed blockchain state and the unconfirmed mempool, making those UTXOs available for transaction construction and balance calculation.
Do DApps connected to Nautilus Wallet respect the zero-confirmation setting?
Yes, the extension background handlers in src/extension/background/ergoHandlers.ts enforce the user's zeroConf preference for all DApp API calls. When a connected application calls getUTxOs or getBalance, the handlers check settings.zeroConf and either include mempool data or restrict queries to confirmed UTXOs accordingly, maintaining security boundaries across the API.
Can I disable zero-confirmation support after enabling it?
Yes, you can disable zero-confirmation support at any time by toggling the setting to false in the Nautilus Wallet UI. When disabled, fetchBoxes() defaults to querying only "blockchain" sources, the balance view excludes pool amounts, and DApp connectors return only confirmed UTXOs. This immediately reverts the wallet to a conservative security model that waits for block confirmations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →