Push Server Metadata


As part of the v0.7.28 updates, one of the modifications to current tech specification was to remove the dappName from the call requests as part of the push notifications

Github Issue:

Forum Thead:

Some products might wish to retain this functionality to provide a better UX for their users. However this is currently controlled from the Dapp side using the Bridge server as an intermediary for the metadata to be accessible to the Push server.

Alternatively it would make more sense to control this from the Wallet and Push server side which is owned by the Wallet provider. This could also be user-customizable if the user wishes to reduce its fingerprint with third-parties, in this case either Android or iOS push notification services.

Additionally, a current issue reported by DDEX which Tokenary has also has encountered is the lack of localization for the push notifications. I’m confident that other Wallets would also like to see localization support by the WalletConnect SDK.

Thus the proposed solution would be to add an extra HTTP request on session creation, after approving a session request, to the Push Server that would include metadata tied to the WalletConnect session that would be used to customize these push notifications for the user’s device. This metadata would include:

  • Session ID (for indexing)
  • Device ID (to dynamically handle localization) or Language ID (to statically handle localization)
  • DappName (optional)
  • Expires (session expiration epoch time)

The React-Native SDK currently supports session approvals with optional push notification as part of the push object. This object would include an optional boolean parameter that would describe if metadata is enabled or disabled plus a deviceID / languageID required if metadata is enabled.

const walletConnector = new RNWalletConnect({
  uri: 'ethereum:wc-8a5e5bdc-a0e4-47...TJRNmhWJmoxdFo6UDk2WlhaOyQ5N0U=',  // Required
  push: {                                                                 // Optional
    type: 'fcm',
    token: 'cSgGd8BWURk:APA91bGXsLd_...YdFbutyfc8pScl0Qe8-',
    webhook: 'https://push.walletconnect.org/notification/new',
    metadata: true,                                                      // PROPOSAL - Optional
    deviceId: 23523534439148027981                                       // PROPOSAL - Optional / Required if metadata is true


Nice work!

After the meeting, we discussed about device Id. DeviceId is sensitive information, so we try to use language info as metadata to provide better user experience.

Does RNWalletConnect SDK needs work with specific versions bridge sever?


I agree 100%, I think it would be better to share a static language parameter which would be far less sensitive if comprimised.

My proposal would be to use ISO 639-1 codes to identify the language. Is this compatible with both Android and iOS? cc @Aladdin @ligi

For better semantic versioning, it might be better to publish it as 0.8.0 as there are already a few breaking changes. I’m not focused on backwards compatibility until v1.0 is out of the door, otherwise it will just move slower.

Also this architecture will allow the Bridge to not store any push notifcation data and only use the sessionID to trigger push notifications, making it easier in the future to completely remove the bridge server for v2.0


I would argue against adding a deviceId and language codes. The localisation should happen at the edge. Let’s keep the bridge dumb.


Absolutely! This metadata is for the push server which is owned by the Wallet provider. Additionally this would allow to abstract the bridge from the pushToken and pushType completely. Its an improvement from the current architecture making the bridge even dumber. The deviceId is sensitive data thats why language codes were suggested as the alternative


I really do not think the whole metadata thing is needed.


I have added a Github issue to follow the tech specification discussed on this thread and I’m planning to move forward with the proposal described.


With the optional push notifications and optional metadata, this allows for 3 levels of privacy that are user-customizable if provided by the Wallet provider

  • No Push Notifications (complete independence from the mobile platform)
  • Push Notifications (improved user experience but privacy preserving)
  • Push Notifications + Metadata (best UX with custom notifications but compromised privacy)


I agree with #1 and #2 - but do not see #3


About push notification metadata:

Currently our hack solution: compose all need metadata to URL parameters.

IMHO, wallet side definitely needs user’s language config to support localization for push notification. @ligi If bridge wanna keep clean and dumb, WalletConnect could support some best practice guides to help developer pass parameter easy and safety.

@pedrouid gave us a quick solution about this feature request: After Wallet app scan qrcode and send auth success to bridge server, Wallet app could send sessionId and metadata to Push Service endpoint, take sessionId as index to find out the followed notification tasks’ metadata.

our solution: Compose all needs metadatas to push service endpoint url as url parameters, and reduce network request times.


the wallet knows the users language config very well - no need to pass anything around. I think the whole metadata thing should be discarded - there is no need for it in my eyes.


I see clear advantages from both viewpoints, this is not so much a question about which one is technically better but how much are we willing to compromise privacy for user experience and vice-versa.

The primary mission of WalletConnect is to facilitate security and privacy best practices between Wallet-Dapp communication without compromising user experience. However different companies and products will have different thresholds.

My proposed solution for 3 options for privacy don’t invalidate both sides and allow us to share this protocol without loosing interoperability. The level of privacy or push notification customization is controlled by the Wallet provider and the user.

The Push server will be the only endpoint which will have access to the user data to trigger these notifications.

This endpoint would have to be separate from the one that triggers the push notification endpoint because they are called from different sources.

New notification is called by the Bridge server which only has access to the sessionId

New device metadata is called by the Wallet app which has access to both data (sessionId, pushType, pushToken) and metadata options (dappName, language).

Therefore my new proposal for updating the Mobile Wallet SDK looks like this:

const walletConnector = new RNWalletConnect({
  uri: 'ethereum:wc-8a5e5bdc-a0e4-47...TJRNmhWJmoxdFo6UDk2WlhaOyQ5N0U=',  // Required
  push: {                                                                 // Optional
    type: 'fcm',
    token: 'cSgGd8BWURk:APA91bGXsLd_...YdFbutyfc8pScl0Qe8-',
    webhook: 'https://push.walletconnect.org/notification/new'
  metadata: {                                                            // Optional
    endpoint: 'https://push.walletconnect.org/notification/metadata',
    dappName: true,
    language: 'en', 


I do not see any UX gain by providing either the push server or the bridge server with metadata. The notification should always display the notification and already has all information for this. There is no need for this complication or privacy trade off in my view as there is no UX gain.


I would be careful with this. The longer you make the URL - the harder the QR code gets to scan. And do not only try with your good phones in bright offices. Test with phones with bad cameras in bad light conditions. I would rather suggest options to reduce the length of the URL even more to improve here.


All of these proposal remove push data and metadata from the Bridge server. The idea is to makes the Bridge server “dumber” and expose less information such as dappName, pushToken, pushType or any other identifiable information.

They are only concerned by the Push server and additionally these are all optional and not required by any Wallet providers to have a 100% fully functional integration with the WalletConnect protocol.

A Wallet provider using the React-Native SDK could simply connect to Dapps using the URI provided by the QR Code and completely discard the Push server.

const walletConnector = new RNWalletConnect({
  uri: 'ethereum:wc-8a5e5bdc-a0e4-47...TJRNmhWJmoxdFo6UDk2WlhaOyQ5N0U='

This wouldn’t affect compatibility with any Dapp whatsoever as this Optional data wouldn’t be required by the Bridge server.


I really like making push optional! But I think I have trouble understanding the concept then a bit. Where does the metadata come into play then - who receives this on which way. Ideally let’s talk on the protocol level and not concrete implementations like React-Native.


I’ve drawn a diagram of the new data flow for the WalletConnect v0.8.x architecture for moving all the push notification data/metadata into the Push server.

This way all the payloads sent the to the Bridge server are now encrypted without requiring any extra metadata besides the sessionId and the callId which are both generated at the Bridge server. For push notifications, the Bridge server would also store the push webhook.

All other data & metadata is either only shared between the Dapp and the Wallet encrypted (accounts, chainId and call requests) using the symKey or is only shared between the Wallet and the Push server (sessionId, pushToken, pushType, dappName, language).

Here is the diagram that should help visualize a step-by-step of the flows: session requests and call requests.


  1. Request new session
  2. Get new session response (inc. sessionId & expires)
  3. Share URI using QR Code (inc. sessionId, bridgeUrl, symKey & dappName)
  4. Send session status (inc. accounts & chainId if approved)
    [optionally inc. pushWebhook]
  5. Get session status (inc. accounts & chainId if approved)
    5(a). Send push data & metadata
    (inc. sessionId, pushType, pushToken, dappName & language) [optional]
  6. Send call request
    6(a). Trigger push notification (inc. sessionId & callId) [optional]
    6(b). Send push notification message (inc. sessionId & callId) [optional]
  7. Get call request
  8. Send call request status (inc. call result if approved)
  9. Get call request status


thanks this diagram is most helpful - trying to parse it - but 5 really makes no sense to me (you query the push server but get an answer from the bridge)


5(a) shares the push data & metadata and returns 200
6(b) pushes notification to the Wallet’s device (triggered by 6 new call request)


ah yea - now I see - but that means the push-server must be stateful (store the session-id->token mapping) - this means as far as I see it would not work with cloud functions that I use currently anymore but you really need a server with db.