Debugging and Troubleshooting dApp Connection Issues with Nautilus Wallet: A Complete Developer Guide
The most common fixes for Nautilus Wallet connection failures involve verifying the content script injection in injected.ts, checking the IndexedDB connectedDApps store for the origin entry, and ensuring the background service worker successfully opens the approval popup via createWindow in src/common/uiHelpers.ts.
Nautilus Wallet is a popular browser extension for interacting with the Ergo blockchain, but developers often encounter friction when establishing connections between decentralized applications (dApps) and the wallet. Understanding the internal message flow and state management within the nautls/nautilus-wallet repository is essential for effectively debugging and troubleshooting dApp connection issues with Nautilus Wallet. This guide walks through the connection architecture, identifies common failure points, and provides concrete diagnostic snippets.
Understanding the Nautilus Connection Architecture
The connection flow relies on a multi-layer message passing system between the dApp, content script, background service worker, and popup UI. According to the source code in src/extension/content-scripts/injected.ts and src/extension/background/background.ts, the process follows five distinct steps:
-
dApp Initiates Request: The dApp calls
window.ergoConnector.nautilus.connect()(or the legacywindow.ergo_request_read_access). The injected content script sends anExternalRequest.Connectmessage to the background via webext-bridge usingsendMessage. -
Background Validates Origin: The background script receives the request as
InternalRequest.Connectand verifies the request originates from an internal endpoint. It checksconnectedDAppsDbService.getByOriginto see if the dApp is already authorized. -
User Approval Flow: If unauthorized, the background opens a popup window. The connector router (
src/extension/connector/router.ts) handles the/connectroute, and the popup UI writes the approval to the database viaconnectedDAppsDbService.put. -
Connection Established: The background stores the approval and replies
trueto the content script. The content script stores the API object inwindow.ergoifcreateErgoObjectwas requested. -
Subsequent API Calls: Methods like
get_utxosorsign_txroute through the same message channel, with the background checkingconnectedDAppsDbServicevia theonMessageAuthguard before fulfilling requests.
The connection state persists in the connectedDAppsDbService IndexedDB table and is validated on every internal request. Any break in this chain results in "Not connected" or "Refused" errors.
Common Failure Points and Diagnostic Strategies
When debugging and troubleshooting dApp connection issues with Nautilus Wallet, symptoms typically cluster around specific architectural failure points. Use the following diagnostic approach based on the source code in src/extension/background/background.ts and related files.
Connection Resolves to False or Popup Never Opens
If window.ergoConnector.nautilus.connect() resolves to false, the popup window likely failed to open or was blocked by the browser.
Open Extension → Service Workers in Chrome DevTools and check the console for openWindow errors. Verify that createWindow in src/common/uiHelpers.ts succeeded and that the extension manifest includes the activeTab permission required for window creation.
window.ergo Remains Undefined After Connection
When window.ergo is undefined despite a successful connection, the createErgoObject flag was likely set to false or the connection was implicitly denied.
Inspect the content script console for the resolution log in connect() (line 33 of injected.ts). Check the boolean return value to confirm whether the API object should have been injected.
"Not Connected" Errors on API Calls
If the dApp receives { code: 400, info: "Not connected." } when calling get_utxos or similar methods, the background cannot find a matching entry in the connection database.
Open the IndexedDB panel in DevTools and inspect the connectedDApps store managed by connectedDAppsDbService. Verify the record contains the correct origin and walletId matching the current dApp domain.
Signing Requests Hang or Return Invalid Params
When sign_tx or data signing requests hang or return validation errors, the payload may be malformed or the address might not belong to the connected wallet.
Check the background logs for handleDataSigningRequest validation (lines 19-24 in the relevant handler). Confirm the requested address exists in addressesDbService and is associated with the currently connected wallet ID.
Permission Denied in UI Despite User Approval
If the popup shows "Permission denied" even after the user clicks Allow, the graphQLService URL may be mismatched or the backend connection failed.
Check the InternalEvent.UpdatedBackendUrl listener (lines 51-54 in background handlers) and confirm the URL stored in browser.storage matches the active backend endpoint.
No Background Console Messages Appear
When no messages appear in the background console, the content script likely failed to inject, often due to Content Security Policy (CSP) restrictions.
Open the page’s Sources tab and verify injected.js is loaded. If blocked by CSP, test on a non-CSP page or adjust the server headers to allow the extension script.
Practical Debugging Snippets
Use these console commands and code blocks to inspect the connection state directly in the browser environment.
Testing the Connection Flow
Run this in your dApp console to verify the basic connection handshake:
window.ergoConnector.nautilus
.connect()
.then(granted => console.log('Connect granted?', granted))
.catch(err => console.error('Connect error', err));
If the promise rejects, the error object contains the APIErrorCode defined in src/types/connector.ts.
Logging Bridge Messages in the Background
Add this temporary listener to the background service worker console to trace all message traffic:
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
console.log('Bridge message →', msg.type, msg);
return true; // keep the channel open
});
Verifying the Database Entry
Check if the connection persisted correctly by querying the IndexedDB service directly:
connectedDAppsDbService.getByOrigin(window.location.origin)
.then(conn => console.log('DB entry →', conn))
.catch(e => console.error('DB error', e));
Resetting the Connection State
Force a clean reconnection when the state becomes stale:
await window.ergoConnector.nautilus.disconnect();
await window.ergoConnector.nautilus.connect();
Key Source Files for Reference
Keep these files open when debugging to trace the execution flow:
src/extension/content-scripts/injected.ts– Exposes the publicNautilusAuthApiand sends bridge messages to the background.src/extension/background/background.ts– Handles internal requests, validates connections viaonMessageAuth, and opens popup windows.src/database/connectedDAppsDbService.ts– Persisted storage of authorized dApp origins using Dexie IndexedDB.src/extension/connector/rpc/protocol.ts– Definitions forExternalRequest,InternalRequest, and result wrappers.src/extension/connector/rpc/asyncRequestQueue.ts– Queues UI-popup requests and resolves them when the popup signals readiness.src/common/uiHelpers.ts– Utility for creating popup windows viacreateWindow.src/extension/connector/router.ts– Vue router definitions for connector routes (/connect,/sign-tx).src/types/connector.ts– Central enum of error codes (APIErrorCode,TxSendErrorCode).
Summary
Effective debugging and troubleshooting of dApp connection issues with Nautilus Wallet requires tracing the message flow from the injected content script through the background service worker to the popup UI. Key takeaways include:
- Verify
injected.jsloads correctly to ensurewindow.ergoConnectoris available. - Check the IndexedDB
connectedDAppsstore to confirm the origin is authorized. - Monitor the background console for
createWindowerrors if the approval popup fails to appear. - Ensure the
activeTabpermission is present in the extension manifest. - Use
disconnect()followed byconnect()to reset stale connection states.
Frequently Asked Questions
Why does my dApp connection resolve to false even after the user clicks Allow?
This occurs when the background service worker fails to open the approval popup or the user denies the permission. Check the background console for errors in createWindow from src/common/uiHelpers.ts and verify the extension has the activeTab permission. Additionally, ensure the connectedDAppsDbService.put call in src/extension/popup/* successfully writes the origin to IndexedDB.
How can I verify that Nautilus has stored my dApp's connection persistently?
Open the browser's DevTools, navigate to the Application (or Storage) tab, and inspect the IndexedDB connectedDApps store managed by connectedDAppsDbService.ts. Run the following in the background console to verify programmatically:
connectedDAppsDbService.getByOrigin(window.location.origin)
.then(conn => console.log('Stored connection:', conn));
A valid entry must contain the correct origin and walletId.
What causes "Not connected" errors when calling sign_tx or get_utxos?
The background script's onMessageAuth guard (lines 40-50 in src/extension/background/background.ts) validates every API call against the connectedDAppsDbService. If the dApp's origin is missing from the database, or if the requested address does not exist in addressesDbService for the connected wallet, the request returns { code: 400, info: "Not connected." }. Verify the connection flow completed successfully and the address belongs to the user's wallet.
Where can I find background service worker logs to debug message routing?
In Chrome or Edge, open the extensions management page (chrome://extensions), enable Developer mode, and click the service worker link under the Nautilus extension. This opens a dedicated DevTools window for the background script. Look for logs related to InternalRequest.Connect, ExternalRequest.Connect, and createWindow calls. If no messages appear, the content script (injected.ts) may be blocked by a Content Security Policy and failed to inject into the page.
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 →