Skip to content

WalletConnect push notifications when app is closed (Echo/Push Server) #1312

Description

@0xh3rman

Problem

App closed/killed + user acts on dapp (sign request, proposal, auth) -> wallet never wakes up. Relay holds the message but nothing delivers a system notification, so the request times out and the user has to manually reopen the app.

Background

  • Fix is Reown Push Server (Echo, echo.walletconnect.com, fallback .org)
  • Same APNs/FCM token goes to two servers: Gem /v2/devices (existing) + Echo POST /{projectId}/clients (new). Existing projectId in core/gemstone/src/config/wallet_connect.rs is reused.
  • register() is never called today on either platform. Foreground flow already works; this only adds background/kill wake-up + tap-to-open routing into the existing approve screens.
  • iOS fork (gemwalletcom/reown-swift@gemwallet, pinned d343984c): Push module at parity with upstream (diff vs main is empty for Sources/WalletConnectPush; the 188-behind delta is Pay/AppKit/Yttrium removal). No fork pre-work needed, stay pinned.

iOS

  • ios/Packages/FeatureServices/WalletConnectorService/WalletConnectorService.swift: pass explicit environment to WalletKit.configure (currently defaults to .production; use .sandbox for Debug/TestFlight).
  • ios/Gem/App.swift didRegisterForRemoteNotifications: after existing Gem sync, add try await WalletKit.instance.register(deviceToken:enableEncrypted: true). Re-register every launch (APNs rotation).
  • New NotificationServiceExtension target: depend on ReownWalletKit product (local-path package), App Group group.com.gemwallet.ios + Push capability. Decrypt via WalletKitDecryptionService (tags 1100/1108/1116); model on Example/PNDecryptionService/NotificationService.swift minus Mixpanel/Notify parts. Push text = dapp name + method only, no amounts/addresses.
  • Tap routes into existing handleSessionRequests; cold start must drain getPendingRequests. If user disables push, call Push.instance.unregister().

Android

  • ReownWalletConnectClient.initialize: after init success + FCM token available, call WalletKit.registerDeviceToken(fcmToken, onSuccess, onError). Wire both directions: FCM.onNewToken -> forward to Echo if WC initialized; init success -> read stored token from DevicePushSettings and register.
  • android/flavors/fcm/.../FCM.kt onMessageReceived: branch Gem payloads (type/data + notification) vs Echo data messages; Echo path builds high-priority notification deep-linking to gem://wc/ / WalletConnectRequest route. Coordinator already drains pending via handlePendingRequests().
  • Respect POST_NOTIFICATIONS (API 33+) and existing push-enabled gate. fdroid (noop WC + stub push) needs nothing. HMS support TBD (Echo only knows FCM).

Dashboard ops (blocking, no code)

Project 3bc07... in WalletConnect dashboard: enable Push Server, upload APNs Auth Key (.p8 + Key/Team ID, Sandbox + Production), register FCM project.

Testing

  • iOS: physical device only; kill app -> dapp request (e.g. react-app.walletconnect.com) -> decrypted push -> tap -> request screen with VerifyContext. Cover sandbox/prod, rotation, unregister.
  • Android: device/emulator with Play Services; kill app -> request -> FCM -> notification -> tap -> request screen. Cover push-disabled, token refresh, cold start.
  • Extend gem-walletconnect-e2e skill to background/kill once landed.

Open decisions

  • One push toggle (Gem + WC) or two?
  • Encrypted-only on iOS (needs NSE) vs plain fallback for v1?
  • Unregister Echo on wallet deletion/logout?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions