7Block Labs
Blockchain Development

ByAUJay

Summary: WalletConnect v1 is shut down, and migration to v2 now affects connection reliability, mobile deep linking, session security, and procurement sign-off. This pragmatic guide shows exactly what to change in code, what to measure, and how 7Block Labs de-risks rollout for Enterprise teams under SOC2 and tight roadmaps.

Wallet-Connect V2: Migration Guide for Developers

Target audience: Enterprise product and platform teams integrating wallets at scale (SOC2, SSO/MDM, vendor risk). We focus on hitting hard business outcomes: higher connect success, lower support tickets, faster procurement.


Pain — The specific technical headaches we keep seeing

  • Session negotiation keeps failing with “invalid namespaces” or “required accounts not satisfied,” blocking signatures after the QR scan. These are almost always CAIP-2/CAIP-10 or namespace mismatches in v2. (specs.walletconnect.com)
  • Mobile flows bounce users between apps or the browser due to misconfigured deep links/universal links and redirect metadata, especially on iOS. Result: stuck sessions and lost conversions. (docs.walletconnect.network)
  • Legacy Web3Modal and v1 connectors are deprecated. Teams that haven’t moved to WalletConnect v2 or Reown AppKit see breaking changes and patchwork workarounds. (docs.reown.com)
  • Long-running approvals (custody, multi-sigs) time out because dapps don’t set request expiry correctly or wallets don’t handle it. (specs.walletconnect.com)
  • Approvals fail for smart contract wallets (EIP‑1271) or counterfactual accounts unless you explicitly handle verification paths. (eips.ethereum.org)
  • ProjectId and relay configuration are inconsistent across web, RN, Android, and iOS builds, breaking connect rates in production. (1.x.wagmi.sh)
  • Reorg of the ecosystem (WalletConnect → Reown; Web3Modal → AppKit) adds new package names, dashboards, and upgrade paths that must align across CI/CD and procurement. (reown.com)

What this costs:

  • Missed quarterly feature deadlines as QA loops on flaky mobile deep links and namespace errors.
  • Vendor risk red flags in SOC2 audits (unclear PII/logging, unbounded session TTLs).
  • Support ticket spikes and conversion drops on “Connect wallet” steps.

Agitation — Why delaying the migration risks your roadmap

  • WalletConnect v1 is shut down; v2 is the supported path and the network itself has evolved toward permissioned-federated nodes with a roadmap to permissionless participation. Relying on legacy connectors or undocumented forks will keep breaking. (walletconnect.com)
  • The v2 Sign API decouples pairing and session, introduces Namespaces, explicit expiries, request history, and method-level permissions. If you don’t implement these precisely, you’ll see “connect but not sign” failures in production. (specs.walletconnect.com)
  • Mobile linking and Link Mode now define how native apps should round-trip without WebSocket dependency; without this, iOS in particular will bounce users and tank completion. (docs.walletconnect.network)
  • Ecosystem SDKs are moving: wagmi, RainbowKit, and AppKit now expect a v2 ProjectId and updated providers/adapters. “It works locally” won’t pass after library upgrades. (2.x.wagmi.sh)
  • GTM risk: WalletConnect/Reown facilitates tens of millions of monthly connections; any 1–2% regression from poor v2 handling is material at enterprise scale. (businesswire.com)

Solution — 7Block’s migration methodology (technical, measured, SOC2-ready)

We run a 3-sprint implementation that aligns code, QA, and procurement.

Sprint 0 (1 week): Architecture diff + SOC2 impact

  • Map current integration points (web, RN, native) to v2 packages:
    • Web/EVM: @walletconnect/ethereum-provider or @walletconnect/universal-provider, or wagmi’s walletConnect() connector. (npmjs.com)
    • Native wallets/dapps: WalletKit/AppKit and platform polyfills (@walletconnect/react-native-compat). (docs.walletconnect.network)
    • If you used Web3Modal: plan upgrade to Reown AppKit (web, RN, iOS/Android). (docs.reown.com)
  • Compliance quick wins:
    • Define log redaction (no PII in event payloads), retention windows, and SIEM export for relay/SDK logs.
    • Document session expiries and error handling in control narratives for SOC2 CC6.x/CC7.x.
    • Confirm ProjectId/Dashboard access controls and SSO/MDM for operational staff.

Sprint 1 (2 weeks): Namespaces, session management, and mobile linking

  • Adopt CAIP-2/10 everywhere; stop hardcoding legacy chain IDs.
  • Move to “optionalNamespaces-first” to maximize wallet compatibility (progressive authorization) and reduce rejections: (medium.com)
// Universal Provider (multichain) with optionalNamespaces
import UniversalProvider from "@walletconnect/universal-provider";

const provider = await UniversalProvider.init({
  projectId: process.env.WC_PROJECT_ID!, // from WalletConnect/Reown dashboard
  metadata: {
    name: "Acme App",
    description: "Enterprise-grade dapp",
    url: "https://example.com",
    icons: ["https://example.com/icon.png"],
  },
});

await provider.connect({
  // Keep requiredNamespaces unset; request all chains in optionalNamespaces
  optionalNamespaces: {
    eip155: {
      methods: [
        "eth_sendTransaction",
        "eth_signTransaction",
        "personal_sign",
        "eth_signTypedData",
      ],
      chains: ["eip155:1", "eip155:137", "eip155:10", "eip155:8453"],
      events: ["accountsChanged", "chainChanged"],
    },
  },
});
  • Ensure session expiry and request expiry are set and handled:
// Extending session (WalletKit API example)
const { acknowledged } = await walletKit.extendSession({ topic });
await acknowledged(); // resolves when dapp acks; if offline, resolves on reconnect
  • Implement mobile deep linking best practices:
    • Prefer deep links over universal links for wallet→app hops; scope redirect metadata only to deep-link initiated sessions. (docs.walletconnect.network)
    • For iOS/Android wallets, register wc:// or app scheme and handle “incomplete” URIs during request redirects; don’t auto-open on QR-only flows. (docs.walletconnect.network)
    • Evaluate Link Mode (low-latency requests via universal/app links) for native-to-native flows. (docs.walletconnect.network)

Sprint 2 (2 weeks): Provider adapters, EIP-1271, and production hardening

  • Web dapps using wagmi:
import { createConfig, http } from "@wagmi/core";
import { mainnet, sepolia } from "@wagmi/core/chains";
import { walletConnect } from "@wagmi/connectors";

export const config = createConfig({
  chains: [mainnet, sepolia],
  connectors: [
    walletConnect({
      projectId: process.env.WC_PROJECT_ID!,
      // optional: metadata, qrModalOptions, relayUrl
    }),
  ],
  transports: {
    [mainnet.id]: http(),
    [sepolia.id]: http(),
  },
});

This connector uses WalletConnect v2 by default; reconnection to approve new chains is required if a user switches to an unapproved chain. Plan UX for this error path. (2.x.wagmi.sh)

  • Replace Web3Modal with Reown AppKit (web/RN/iOS/Android). Align adapters (EVM/Solana/Bitcoin) and the new dashboard. (docs.reown.com)
  • Add EIP‑1271 verification for SIWE/messages and smart wallet orders; optionally support ERC‑6492 for counterfactual contracts: (eips.ethereum.org)
// EIP-1271 signature check (ethers v5-style)
import { ethers } from "ethers";
const ERC1271_ABI = ["function isValidSignature(bytes32,bytes) view returns (bytes4)"];
const MAGIC = "0x1626ba7e";

export async function isValid1271Signature(
  provider: ethers.providers.Provider,
  contractAddress: string,
  hash: string,
  sig: string
) {
  const wallet = new ethers.Contract(contractAddress, ERC1271_ABI, provider);
  try {
    const res: string = await wallet.isValidSignature(hash, sig);
    return res.toLowerCase() === MAGIC.toLowerCase();
  } catch {
    return false;
  }
}
  • Tighten signing methods for risk:
    • Prefer EIP‑712 typed data over eth_sign to reduce phishing risk and improve wallet compatibility. (eips.ethereum.org)

Practical examples you can drop into production

1) SignClient with decoupled pairing/session and namespaces

import SignClient from "@walletconnect/sign-client";

const signClient = await SignClient.init({
  projectId: process.env.WC_PROJECT_ID!, // WalletConnect/Reown dashboard
  metadata: {
    name: "Acme App",
    description: "Enterprise-grade dapp",
    url: "https://example.com",
    icons: ["https://example.com/icon.png"],
  },
});

// Subscribe to proposal and session events
signClient.on("session_proposal", async (proposal) => {
  // Validate proposal; optionally filter methods/chains
});

signClient.on("session_update", ({ topic, params }) => {
  // Handle dynamic permission changes
});

// Pair first, then propose session using pairing topic
const { uri, approval } = await signClient.connect({
  // keep requiredNamespaces unset, use optionalNamespaces for flexibility
  optionalNamespaces: {
    eip155: {
      chains: ["eip155:1", "eip155:137"],
      methods: ["eth_sendTransaction", "personal_sign", "eth_signTypedData"],
      events: ["accountsChanged", "chainChanged"],
    },
  },
});

// Render QR or deep link if needed
if (uri) {
  // Show QR or trigger deep link
}

// Wait for wallet approval
const session = await approval();
  • Tip: “invalid namespaces” and “required accounts not satisfied” are almost always CAIP-2/10 formatting errors or requesting methods chains don’t support; validate against the spec test cases. (specs.walletconnect.com)

2) Custom QR flow without the built-in modal

import EthereumProvider from "@walletconnect/ethereum-provider";

const provider = await EthereumProvider.init({
  projectId: process.env.WC_PROJECT_ID!,
  // showQrModal: false, // bring your own modal
});

provider.on("display_uri", (uri: string) => {
  // Render your enterprise-branded QR, stream analytics, apply AB tests
});

This allows you to instrument funnel events (“QR displayed → wallet opened → session settled”). (npmjs.com)

  • Register wc:// or a native scheme; configure redirect metadata and ignore “incomplete” URIs that are only meant to foreground the app for a pending request. (docs.walletconnect.network)
  • Enable Link Mode for native↔native to reduce latency and survive flaky WebSocket links: (docs.walletconnect.network)
// iOS WalletKit example (Link Mode)
let metadata = AppMetadata(
  name: "Acme Wallet",
  description: "Enterprise wallet",
  url: "https://example.com",
  icons: [...],
  redirect: try! AppMetadata.Redirect(
    native: "acmewallet://",
    universal: "https://example.com/wc",
    linkMode: true
  )
)
WalletKit.configure(metadata: metadata)

4) Long-lived approvals (custody/multisig)

  • Set per-request expiry (5 min to 7 days) and UX for “expired” responses. Ensure relay publish TTL matches expiry. (specs.walletconnect.com)
await signClient.request({
  topic: session.topic,
  chainId: "eip155:1",
  request: { method: "eth_signTypedData", params: [...] },
  expiry: Math.floor(Date.now() / 1000) + 3600, // 1 hour
});

Best emerging practices (2026) we recommend adopting now

  • Use Namespaces progressively:
    • Keep requiredNamespaces unset unless absolutely necessary; request broad optionalNamespaces and adapt to wallet capabilities. (medium.com)
  • Encode all chains/methods with CAIP-2 and events with session approval; validate accounts in CAIP-10 format. (specs.walletconnect.com)
  • Prefer deep links on mobile; scope redirect metadata only to deep-link sessions; do not auto-redirect on QR-only scans. (docs.walletconnect.network)
  • Implement Link Mode for native apps with custody or low-connectivity users. (docs.walletconnect.network)
  • Support EIP‑1271 and (optionally) ERC‑6492 to make SIWE and order signing work for smart contract wallets and counterfactual accounts. (eips.ethereum.org)
  • Raise the floor on signing safety by prioritizing EIP‑712 (eth_signTypedData) over eth_sign. (eips.ethereum.org)
  • Track session TTLs, and build explicit “extend” flows for long-lived sessions; don’t assume infinite sessions. (docs.walletconnect.network)
  • For web stacks using wagmi/RainbowKit, upgrade to versions that default to v2 and pass a ProjectId; plan UX for unapproved chain switches. (rainbowkit.com)

Prove — The GTM metrics that matter (and how we instrument them)

What we measure in pilots:

  • Connect success rate (unique QR/deep link displayed → session settled) by device/OS/wallet. Baseline against ecosystem scale (20M+ monthly connections), then close gaps. (businesswire.com)
  • Time to first signature (TTFS) P50/P95 with and without Link Mode.
  • Session stability: resume rate after app backgrounding; session extend events per active week. (docs.walletconnect.network)
  • Request completion vs. expiry (5–7 day window for custody): % expired, average response time, error code distribution. (specs.walletconnect.com)
  • EIP‑1271 success vs. fallback (ERC‑6492 path), especially for AA wallets. (eips.ethereum.org)
  • Support ticket rate per 1K sessions for “wallet failed to open,” “invalid namespaces,” “unapproved chain.”

What good looks like after this migration:

  • 97% connect success on top wallets after implementing optionalNamespaces and mobile linking best practices.

  • P95 TTFS reduced on native apps with Link Mode (less WebSocket dependency). (docs.walletconnect.network)
  • <1% request expiries for intended UX after adopting explicit expiries and wallet UI cues. (specs.walletconnect.com)
  • Clean SOC2 narrative: bounded session TTLs, least-privilege namespaces, no PII in logs, rotation and retention defined.

Procurement and security notes (Enterprise-ready)

  • SOC2 alignment: document session/approval expiries, error handling, and no-PII logging; route logs to SIEM; SSO/MDM on dashboard access; incident runbooks for wallet outages.
  • Decentralization roadmap: WalletConnect Network operates with a growing federation of node operators and is moving toward permissionless participation; this informs your vendor-risk assessment and BCP posture. (docs.walletconnect.network)
  • If you require private infra: self-hosted relay for v2 is not generally supported; rely on the network roadmap rather than forking archived code. (github.com)

Migration checklist (copy/paste for your Jira)

  • Replace deprecated Web3Modal packages with Reown AppKit on all platforms; record new ProjectId provisioning workflow in runbooks. (docs.reown.com)
  • Switch to wagmi walletConnect() or @walletconnect/* providers with projectId.
  • Refactor to CAIP-2/CAIP-10 and optionalNamespaces-first sessions; add validation tests per spec. (specs.walletconnect.com)
  • Implement deep links per platform; restrict redirect metadata to deep-link flows; evaluate Link Mode for native apps. (docs.walletconnect.network)
  • Add EIP‑1271/ERC‑6492 verification where applicable. (eips.ethereum.org)
  • Enforce request expiries and build UX for expiry/extend; alert on rising expiry rates. (specs.walletconnect.com)
  • Instrument “display_uri → session settled → first signature” with wallet and device segmentation.
  • Update security docs for SOC2: data flow (no PII), log retention, access controls, incident response.

How 7Block Labs helps you ship on time (and prove ROI)


Appendix: Reference snippets

EIP‑712 signing (prefer this over eth_sign) (eips.ethereum.org)

const typedData = {
  domain: { name: "Acme", version: "1", chainId: 1, verifyingContract: "0x..." },
  types: { Mail: [{ name: "from", type: "address" }, { name: "contents", type: "string" }] },
  primaryType: "Mail",
  message: { from: "0xabc...", contents: "hello" },
};

await provider.request({
  method: "eth_signTypedData_v4",
  params: [address, JSON.stringify(typedData)],
});

Wagmi + WalletConnect connector (v2) with projectId and metadata (2.x.wagmi.sh)

import { walletConnect } from "@wagmi/connectors";

const connector = walletConnect({
  projectId: process.env.WC_PROJECT_ID!,
  metadata: {
    name: "Acme App",
    description: "Enterprise-grade dapp",
    url: "https://example.com",
  },
});

RN polyfills and WalletKit init (ensure compat import first) (docs.walletconnect.network)

import "@walletconnect/react-native-compat";
// then import Reown/WalletConnect SDKs

If you want this executed with minimal risk and measurable ROI, we’ll run the migration and stand up metrics in 30–60 days while aligning with SOC2 and procurement.

Book a 90-Day Pilot Strategy Call. (walletconnect.com)

Like what you're reading? Let's build together.

Get a free 30‑minute consultation with our engineering team.

Related Posts

7BlockLabs

Full-stack blockchain product studio: DeFi, dApps, audits, integrations.

7Block Labs is a trading name of JAYANTH TECHNOLOGIES LIMITED.

Registered in England and Wales (Company No. 16589283).

Registered Office address: Office 13536, 182-184 High Street North, East Ham, London, E6 2JA.

© 2025 7BlockLabs. All rights reserved.