Skip to main content
This is an enterprise-only feature. Please contact us to enable.
On iOS the Connections contract is the same as the web, hosted inside a web view. The result comes back on a custom URL scheme instead of an https callback. You have two options:
  • Basic — present the hosted page and read the result. One Swift file to copy.
  • Headless — render your own native wallet list, driven by a hidden web view. Your app links no wallet SDK.
The basic flow is the recommended default. Use headless only when you need a fully native front end.

Basic

The whole integration is one small Swift file, FireblocksConnectFlow.swift — copy it, call it, read the result.
Present with ASWebAuthenticationSession: it’s built for “open web, return via a callback scheme,” runs ephemerally (no consent prompt, no stale-session lag), and needs no navigation glue. Use a WKWebView only if you need the flow embedded in custom UI.

1. Register your URL scheme

Add your app’s custom scheme to Info.plist. It only has to match the scheme you pass to the flow.
Info.plist

2. Present the flow

Call FireblocksConnectFlow.present. It appends redirect_uri, a random nonce, and embedded=1 to the URL, opens the session, verifies the returned nonce, and hands you a typed result.
ConnectButton.swift
Forward your app’s onOpenURL to FireblocksConnectFlow.handleCallbackURL($0). Most wallets return inside the session, but some (Phantom) finish in their own in-app browser and hand the result back via the scheme — this makes those complete.
App.swift

3. Use the result

WalletConnection carries the same fields as the web callback, with the nonce already verified for you: address, chain ("evm" | "solana"), walletName, and walletImage.
The embedded=1 flag tells the page it’s inside a native container, so it opens wallets via their native scheme and avoids redirect protocols that would escape to Safari. Render walletImage with a WebKit-backed <img> rather than UIImage — it’s usually an SVG-sprite URL.

Headless

Want your app to render its own native wallet list with no web UI at all? Keep every bit of connection logic in the web layer and drive it from a hidden web view.
No SDK in your app. Your app links no wallet SDK — no CocoaPods, no native crypto. It needs exactly two things: a hidden web view pointed at headless.html, and your URL scheme. All the 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 (the drop-in engine) and FireblocksConnectFlow.swift (the visible fallback and the shared WalletConnection result).

1. Get the wallet menu

The engine derives the list live from the Dynamic catalog and pushes it to your app over the bridge (a wallets message) — no wallet file to ship or keep in sync. Set FireblocksHeadlessConnect.shared.onWallets. Each entry carries:

2. Drop in FireblocksHeadlessConnect

It 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’s how redirect wallets (Phantom) hand their result back to the hidden view. Auto-fallback is built in: wallets with no headless path (Base Account passkey, and similar) return .fallbackRequired, and you open the visible flow for that same wallet, so the user never hits a dead end.

3. Sign a message

After a successful connect, call sign() with any string. The wallet app prompts the user to approve; the callback delivers a hex signature.
SignView.swift
Signing is only available for wallets connected through the headless engine (connectedHeadlessly == true). Wallets that completed the visible fallback flow don’t hold an open session.

4. Sign a transaction

Pass a serialized transaction to signTransaction(). This only signs — it does not broadcast. The format and return value differ by chain.
SignView.swift — EVM
SignView.swift — Solana

The bridge

You don’t write the bridge — it’s what flows between the hidden view and the two files above. The component mints a fresh requestId (UUID) per connect and drops any message whose id doesn’t match the one still in flight, so a stale or forged reply can’t 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 don’t run in the Simulator, so real wallet round-trips require a real iPhone.
  • 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 7, 2026