Wallet doesn't connect: where WalletConnect integration breaks
Connecting a mobile wallet is the most fragile part of the flow. On desktop, the session lives as long as the tab is open, but on mobile the user leaves for the wallet and comes back — and that transition breaks what seemed to be working.
The first failure point is session breakage when switching between apps. The operating system unloads the background, the connection to the relay loses activity, and on return the app considers the channel alive and keeps waiting for a response that will never come.
The second is scanning the connection code. If the code is opened in an external scanner, the return goes not to the app but to the wallet's main screen; a retry creates a second key pair, and the user sees a wallet connection error while the session is formally active.
The third is a lost response to a signature request: the transaction is already signed and sent, but the response didn't reach the app, and it shows a failure where the operation succeeded.
The fourth is a network mismatch: the wallet operates on a different network, the signature is assembled for a foreign identifier, and the confirmation silently hangs.
All four failures lie not in the product logic but at the boundary between the app and the wallet. We'll break down how each of them is closed at the WalletConnect integration level.
What seamless wallet connection in an app delivers
Every extra step between the intention to sign and the signature costs connection conversion. A typical failure: the user leaves for the wallet app, returns — the session is not restored, and they see the "Connect" button again. Part of the audience stops there, and it never reaches the signature request.
We build wallet connection on WalletConnect with a persistent session: keys and the identifier are stored on the device, so returning from the wallet happens without a repeated handshake, and a network switch doesn't break the connection but pulls the current chain identifier.
The "left and didn't return" branch is closed by a time-limited wait for confirmation and an explicit status on the screen.
Re-entry time is reduced to a single confirmation — a session with extended lifetime survives tab closure and app restart.
Instead of four to five steps on every visit, a single screen remains, and the share of users reaching the signature grows several times compared to the scenario with code scanning at login.
The share of successful signatures relies on preliminary checks: before the request, the app verifies the address, network, and availability of funds for the fee, so the error doesn't surface after confirmation.
The class of failures "signed but the transaction didn't go through" almost disappears, and retries don't eat up the user's time.
For support, these are direct metrics: requests like "wallet doesn't connect" and "transaction stuck" stop being mass-scale, leaving only a narrow stream of questions about individual wallets.
Retention grows next — a user who once went through the path without friction returns to the app instead of looking for an alternative.
Wallet connection methods: comparison of options
Wallet connection options differ in where the key is stored and who signs the transaction — this determines device coverage and the number of failure points.
Mobile browser limitations break any scenario designed only for an injected provider: there are no extensions there, the background tab goes to sleep, and returning from the app via a link resets the context.
Integration of WalletConnect covers the mobile scenario through a connection intermediary but doesn't cancel the other methods. Below is a comparison of connection methods that we usually assemble in a single app.
| Option | When it fits | Limitations |
|---|---|---|
| Direct exchange with the wallet | Desktop browser with an extension, one-click signing | Unavailable in mobile browsers; the key remains inside the wallet |
| Relay intermediary (relay) | Mobile wallet and desktop browser via QR code, unified scenario | Requires a stable channel, a separate session layer, and correct revocation of access |
| Built-in gateway | Quick login without installing an extension, simple scenarios | The provider holds the key — some users refuse this type of login |
| Desktop browser only | Internal panels and administrative scenarios | Cuts off mobile traffic, which accounts for the main share of new connections |
In practice, the connection intermediary becomes the main path for mobile, direct exchange is the fast path for desktop browsers, and the built-in gateway remains a fallback. Such a set covers almost all connection traffic: failure of one method doesn't block login via another.
WalletConnect integration into an app: work stages
Mobile wallet connection almost never fails in the direct scenario: the user scans the code, confirms access — and everything works.
It breaks on returns: the app went to the background, the device switched networks, the session expired, the wallet updated and stopped responding to the previous request format.
That's why the work proceeds in stages — from analyzing the current connection scheme to a maintenance procedure that records who responds to such changes and how.
- Analysis of the current scheme. We look at which wallets and networks are already supported, where the session state is stored, what failures come from users and support, and what prevents adding new wallets without rewriting the logic.
- Session design. We fix the session lifetime, rules for its restoration after app restart, the order of access revocation, and behavior with multiple active sessions on one account.
- Connection assembly. Desktop gets a code for scanning, mobile gets a transition to the wallet app and a correct return back, preserving the context of the operation the user started.
- Failure handling. We separately work through timeouts, retries, user refusal to sign, and connection loss at the moment of confirmation — so the transaction isn't silently lost.
- Testing on real devices. We run scenarios across a matrix: different OS versions, built-in wallet browsers, tablets, slow network. An emulator doesn't count here.
- Handover. We provide the connection scheme, environment configurations, description of failure points, and instructions for first-line support.
- Maintenance procedure. We define how we track changes on the wallet side, who updates the configuration, and in what timeframe we restore operation.
Configuration, schemes, and procedures: what we hand over as a result of the work
The result of the work is not only a connected wallet inside the app but also a kit that your team can use to change settings, add networks, and handle support requests without us.
We put everything into a single set and go through it at acceptance together with your engineers — from configuration to the on-call actions.
What remains in your hands:
- Environment configuration — sets of settings for test and production environments: project ID, allowed networks and sources, list of variables, and the procedure for adding a new environment.
- Connection flow scheme — the path from session initiation to transaction signature, including the user's return from the wallet app, session restoration after restart, and failure handling.
- Access policies — where keys are stored, to whom they are issued, how rotation is performed, and how rights are separated between development, support, and infrastructure.
- Handover documentation — module description, list of supported wallets and networks, known limitations, and a changelog by release.
- Support instructions — typical requests (session not restored, transaction rejected, wallet doesn't open) and what to do at each step.
- Diagnostics scheme — which events we log and how to distinguish a failure on our side from a failure on the wallet side.
- Update procedure — how we track protocol changes, what we do on version incompatibility, and in what order we roll back.
Case study: wallet connection in a service with growing active users
A service with a growing audience connected mobile wallets through a custom bridge: QR code, manual state polling, and its own session restoration logic.
While there were few users, the scheme held up, but as the load grew it began to fall apart — the session was lost when the app was minimized, and on some devices the signature didn't reach the wallet at all.
The measurements before the migration looked like this: share of failed connections — 34%, time to first signature — from 90 seconds and above, on average 2.4 retries per user. Support was drowning in identical requests: "wallet doesn't see the app".
What we changed
We moved the transport and session lifecycle to the current WalletConnect branch. The connection is established through intermediate nodes, session keys live on the client side, and the break after minimizing the app restores itself — without repeated QR scanning.
Following a link from the browser and a QR code lead to the same scenario, so the logic doesn't fork between platforms.
What the metrics showed
The share of failed connections dropped from 34% to 6% — the remainder is user refusals and incompatible wallet builds. Time to first signature decreased to 20-25 seconds, retries — to 1.05 per user, meaning the scenario goes through on the first try.
Support requests on the topic of connection became almost seven times fewer, and the share of mobile connections grew: the step of scanning a QR on the same device where the service is open was eliminated.
How a built-in gateway differs from an external wallet and what to choose
The difference between a built-in gateway and an external wallet comes down to one thing: where the private key is stored and who is responsible for its safety.
A built-in gateway holds keys on the app side — the user logs in in a familiar way, and the transaction signature is formed inside the service. An external wallet leaves the key with the user: the app receives the address and a ready signature but doesn't touch the secret itself.
From this grows a difference in audience coverage. The built-in option lowers the entry barrier and works for anyone who opened the service from a phone, including those who don't yet have a wallet.
The external one connects only wallet owners but brings an audience that is already used to signing operations and carefully checks requested permissions.
A protocol like WalletConnect solves exactly the second task — it connects a mobile wallet to the interface without transferring the key.
Both options lose in their respective scenarios. A built-in gateway is not suitable where large amounts and long-term asset storage are involved: the user won't give the key to the service, and you take on all responsibility for its leak.
The external one loses in mass short operations — some of those who come simply won't reach the signature, losing interest at the wallet installation stage.
The choice of connection option is made based on the primary task. If assets are stored for a long time and the stakes are high, the external wallet is left as the only path. If mass scale and a quick first login are important, the built-in gateway becomes the main one.
In practice, both are more often assembled: the external one as the main path, the built-in one as a fallback for those who came without a wallet, with an explicit limit on the volume of operations.
Technical concerns: sessions, keys, restoration
The pairing session relies on a symmetric key that is created on the user's device, and the wallet's private keys never leave the wallet app itself.
We get from the session only the address, signatures, and the agreed set of methods and networks — permissions are fixed at the moment of confirmation and cannot be expanded from the app side.
A connection loss or wallet restart doesn't kill the session: the identifier and key are stored locally, the client reconnects to the same pair and sends missed requests.
The session lives for a limited time, so we build re-pairing and state checks before sending a transaction into the scenario.
Do wallet keys pass through your backend?
No. The signature is formed inside the wallet, and only its result and the address go out. We store the session state and request history but not secrets — compromising the backend doesn't give access to funds.
What happens to a request during a connection loss?
It is queued and retried with increasing delay, so a short network loss doesn't turn into a lost transaction. If the wallet is closed, the request waits for the user to return; after the session expires, we suggest scanning the code again.
Does this work with old wallet builds?
The current protocol branch is supported by most modern wallets, but not all. At the start, we check the list from your audience and leave a fallback for unsupported ones — connection by code or via a browser extension, with the same set of signable operations.
Let's discuss the task: we'll select a connection scheme for your product
To come back with an estimate and work plan rather than general wording, we need to understand your landscape: where the app lives, which wallets are already in use by your audience, and what exactly breaks in the current connection.
Below is what is useful to prepare for the conversation; some points usually become clear directly in the correspondence.
- Platforms and their limitations: web, mobile app, built-in browser — this determines whether we go via QR code, deep link, or native pairing.
- Scenarios: only connection and transaction signing, or also address reading, network switching, session revocation, and reconnection without a new scan.
- Target networks: one chain or several, whether switches between them within a single session are needed.
- Current scheme: set of supported wallets, where the session state is stored, and what happens when the app is minimized.
- Limitations: requirements for key storage, policy on external services, implementation timelines, and upcoming releases.
- Failure points: what is most often written to support — session drop, stuck request, network mismatch.
Describe the task in free form: that will be enough for us to come back with an estimate and plan — work stages, selection of a connection scheme for your platforms, and what will be required on your side.
We take WalletConnect as a basis, but we choose the specific scheme for the product, not the other way around.







