Skip to main content
This is an enterprise-only feature. Please contact us to enable.
Want your app to render its own native wallet list with no web UI? Keep connection logic in the web layer and drive it from a hidden web view. The basic iOS flow is the recommended default; use headless when you need a fully native front end. After connecting, you can also sign messages and transactions over the bridge.
No SDK in your app. Your app links no wallet SDK: no CocoaPods, no native crypto. It needs a hidden web view pointed at headless.html, and your URL scheme. All WalletConnect / MetaMask / Phantom logic (and the wallet list itself) comes from that hidden view. When wallets or the SDK change, you redeploy the page; the app never changes.
Copy two files: FireblocksHeadlessConnect.swift and FireblocksConnectFlow.swift (visible fallback and shared WalletConnection).

1. Get the wallet menu (no static file)

The engine derives the list live from the Dynamic catalog and pushes it to your app over the bridge (a wallets message). No walletbook file to ship or keep in sync.
wallets message (web to app)

2. Drop in FireblocksHeadlessConnect

One file owns a hidden WKWebView pointed at headless.html, drives it over a message bridge, opens the wallet deeplink it returns, and calls you back. Pre-warm it at launch.
Connect.swift
Forward your app’s onOpenURL to FireblocksHeadlessConnect.shared.handleReturnURL($0). That is how redirect wallets (Phantom) hand their result back to the hidden view.
FireblocksHeadlessConnect.swift

3. Sign a message

The hosted engine supports window.headlessConnect.sign. After a successful headless connect, call sign() with any string. The wallet app prompts the user to approve; the callback delivers a hex signature (EVM) or base58 (Solana).
SignView.swift
Signing is only available for wallets connected through the headless engine. Wallets that completed the visible fallback flow do not hold an open session.

4. Sign a transaction

Pass a serialized transaction to signTransaction() (engine: signTx). This only signs. It does not broadcast. Format and return value differ by chain.
SignView.swift (EVM)
SignView.swift (Solana)

5. Render the list (your UI)

On tap, route to the engine (mode: "headless") or the visible flow (mode: "fallback"). The engine also returns .fallbackRequired for anything it cannot do silently, so you fall back automatically. WalletListView is a sample you would swap for your own design.
WalletListView.swift

6. The bridge (for reference)

You do not write the bridge. It is what flows between the hidden view and the harness files. Handy when debugging.
bridge messages
The component mints requestId as a fresh UUID per connect and drops any message whose id does not match the one still in flight, so a stale or forged reply cannot complete a newer request. It also drops anything posted from an origin other than the engine URL, and rejects a connected message without a non-empty address as malformed_result.

Common pitfalls

  • Keep the hidden web view in the hierarchy. A fully detached WKWebView gets suspended by iOS and its relay socket stalls. Keep it 1×1 and hidden.
  • Test on a physical device. Wallets do not run in the Simulator.
  • Serve over HTTPS. The flow mints WalletConnect URIs via WebCrypto, which needs a secure context.
  • Native deeplinks are faster. Universal links round-trip through the wallet’s link server first; the hosted page prefers native schemes when embedded.
Last modified on August 10, 2026