Example · wallet-flow compatibility

Wallet-flow example

One command runs a common wallet-connection flow in a real browser and shows every wallet-related value the app sent, and to whom.

Status. The example is In development: it runs end to end on a synthetic dApp with the NODAL test wallet. A second run connects the same wallet through Reown AppKit. WalletConnect QR and relay flows are Planned. MetaMask, Reown and WalletConnect are compatibility targets, not partners.

The flow

  1. Discover. The dApp asks for wallets with the EIP-6963 eip6963:requestProvider event. The NODAL Test Wallet answers.
  2. Connect. The dApp calls eth_requestAccounts and eth_chainId over the EIP-1193 provider interface, the same interface injected wallets such as MetaMask expose.
  3. Read. It reads the balance from its RPC provider.
  4. Sign in. It fetches a nonce, asks the wallet to sign a SIWE-style message with personal_sign, and verifies it with its own API.
  5. Load. It loads the portfolio, and, deliberately, sends the address to an analytics host, an ad pixel and a session-replay host.

Run it

npm install
npm run example:wallet

It uses Playwright with an installed Microsoft Edge (set PW_CHANNEL=chrome for Chrome). Output goes to examples/wallet-flow/output/: the HAR capture, a redacted nodal-findings.json and a Markdown report. The same capture is what Trace Lab shows under Wallet-flow capture.

Latest result

IDSeverityValueHostCategoryWhere

The three high findings are the deliberate disclosures. RPC and first-party flows are expected and shown at info. Host categories for the .test stand-ins are declared in the scenario, the same way a Privacy CI policy would declare them.

The Reown AppKit run In development

The same synthetic dApp, but the wallet connects through Reown AppKit with the ethers adapter and default features. Playwright opens the AppKit modal and picks the NODAL Test Wallet, which AppKit finds over EIP-6963. After connecting, the app makes the same requests as before.

npm run example:appkit:build   # bundles the dApp with AppKit (needs a Reown project ID in examples/appkit-flow/dapp/.env)
npm run example:appkit

Unlike the first example, Reown and WalletConnect hosts use the real network. The synthetic .test hosts are still local stand-ins, and anything else is blocked and listed.

IDSeverityValueHostCategoryWhere

Beyond the app’s own requests, this run recorded what AppKit requested: configuration and images from api.web3modal.org, fonts from fonts.reown.com, and requests to rpc.walletconnect.org, including a name lookup with the connected address in the URL path. NODAL’s host list classifies these hosts as wallet infrastructure, shown at info. Whether a flow like that is expected is the team’s decision; NODAL shows the evidence. This describes one run with one version and configuration, not AppKit in general.

Open the AppKit capture in Trace Lab

What NODAL captures

  • Every request the page makes, through Playwright request events on the browser context: method, URL, request headers and request body.
  • Route handlers answer every request with a local stand-in. Any request without a stand-in is blocked and listed, so nothing leaves the machine.
  • WebSocket connections are listed by URL. Their frames are not analysed.
  • The capture is written as HAR 1.2 and analysed by the same engine as Trace Lab.

Limitations

  • Not MetaMask. The NODAL Test Wallet implements EIP-6963 and EIP-1193 with a fixed address. It holds no keys and returns a fixed mock signature. Testing with the MetaMask extension needs a team’s own test profile, and the extension’s own traffic is not page traffic, so it stays a blind spot.
  • AppKit run uses the network. The AppKit example contacts Reown and WalletConnect hosts for real, because AppKit needs them. What it sends depends on the AppKit version and the project’s settings in the Reown dashboard. WalletConnect QR sessions use a relay over WebSocket, whose frames NODAL does not analyse; that flow is not covered yet.
  • Synthetic dApp. The app and its hosts are made up. The result shows how NODAL reports flows; it says nothing about any real service.
  • Service workers are blocked in this run. CORS preflight requests are handled by Playwright and are not recorded as separate entries.
  • One flow. It covers this scenario on this build only. It does not detect every leak and is not proof that an app is private.