Skip to content

Conversation

@bakoushin
Copy link

@bakoushin bakoushin commented Sep 30, 2025

Description

Updates wallet_getCapabilities handling to fall back on the session’s namespace chain IDs when no explicit chainIds are provided in the request.

Per EIP-5792, the chainIds parameter is optional. If it is omitted, the wallet is expected to return capabilities for all supported chains.

With this fix, the wallet correctly enumerates capabilities across all chains defined in the session namespaces, ensuring compliance with the spec and avoiding incomplete responses when chainIds is absent.

Type of change

  • Chore (non-breaking change that addresses non-functional tasks, maintenance, or code quality improvements)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Draft PR (breaking/non-breaking change which needs more work for having a proper functionality [Mark this PR as ready to review only when completely ready])
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How has this been tested?

  • Updated unit test

Examples

  1. Wallet provided scopedProperties as a part of session approval:
...
namespaces: {
  eip155: {
    chains: ["eip155:1", "eip155:137", "eip155:84532"],
  },
},
scopedProperties: {
  "eip155:1": {
    atomic: {
      status: "unsupported",
    },
  },
  "eip155:137": {
    "eip155:137:0x0910e12C68d02B561a34569E1367c9AAb42bd811": {
      atomic: {
        status: "supported",
      },
    },
  },
  "eip155:84532": {
    "eip155:84532:0x0910e12C68d02B561a34569E1367c9AAb42bd810": {
      atomic: {
        status: "supported",
      },
    },
  },
},
...
  1. dApp is requesting wallet_getCapabilities without providing an optional array of chain ids:
wallet_getCapabilities([
  "0x0910e12C68d02B561a34569E1367c9AAb42bd811", // wallet address
                                                // no explicitly provided chain ids as they are optional
])
  1. Method execution:
Before After
Capabilities are NOT extracted from session, since no chainIds are provided Capabilities are extracted for all chain ids supported within the session

Checklist

  • I have performed a self-review of my own code
  • My changes generate no new warnings
  • (N/A) Any dependent changes have been merged and published in downstream modules

Note

extractCapabilitiesFromSession now falls back to EIP-155 session namespace chains when chainIds is not provided, with a new test covering this behavior.

  • Utils:
    • Update extractCapabilitiesFromSession in providers/universal-provider/src/utils/caip25.ts to:
      • Read namespaces.eip155.chains and convert to hex chain IDs.
      • Use these as defaults when input chainIds is empty.
  • Tests:
    • Add unit test (Case 9) in providers/universal-provider/test/utils.spec.ts validating fallback to session namespace chains.

Written by Cursor Bugbot for commit 573f2fa. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2025

All contributors have signed the CTA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@bakoushin
Copy link
Author

I have read the CTA Document and I hereby sign the CTA

github-merge-queue bot pushed a commit to divvi-xyz/divvi-mobile that referenced this pull request Oct 2, 2025
…262)

### Description

Send wallet capabilities within the session data to avoid an extra
`wallet_getCapabilities` request that would otherwise require an extra
user interaction.

By including capabilities directly in the session, WalletConnect can
respond to `wallet_getCapabilities` without prompting the user to switch
to their wallet. This makes capability extraction seamless and improves
the overall UX.

### WalletConnect capabilities support

WalletConnect currently supports two approaches for including
capabilities in session data:

1. Recommended: in `sessionProperties` or `scopedProperties`.
[Docs](https://docs.walletconnect.network/wallet-sdk/react-native/eip5792#wallet-response)
2. Legacy: in the `capabilities` prop inside `sessionProperties`.
[Source](https://github.com/WalletConnect/walletconnect-monorepo/blob/1e6d7793d0a30d2bf684cd3811ba120b4cdc0498/providers/universal-provider/src/providers/eip155.ts#L219-L223)

We do support both approaches for maximal compatibility.

### Notes

* When using the recommended approach, WalletConnect does not return
capabilities if the optional `chainIds` array is omitted in
`wallet_getCapabilities` request.
* We've proposed a PR to address this in the WalletConnect repo:
WalletConnect/walletconnect-monorepo#6955

### Test plan

* Updated unit test
* Tested manually using
https://bakoushin.github.io/wallet-connect-tester/


https://github.com/user-attachments/assets/bd3a6d15-4dd1-4dff-a295-a49828500d45

### Related issues

- Part of ENG-644

### Backwards compatibility

Y

### Network scalability

If a new NetworkId and/or Network are added in the future, the changes
in this PR will:

- [x] Continue to work without code changes, OR trigger a compilation
error (guaranteeing we find it when a new network is added)
github-merge-queue bot pushed a commit to divvi-xyz/divvi-mobile that referenced this pull request Oct 2, 2025
…262)

### Description

Send wallet capabilities within the session data to avoid an extra
`wallet_getCapabilities` request that would otherwise require an extra
user interaction.

By including capabilities directly in the session, WalletConnect can
respond to `wallet_getCapabilities` without prompting the user to switch
to their wallet. This makes capability extraction seamless and improves
the overall UX.

### WalletConnect capabilities support

WalletConnect currently supports two approaches for including
capabilities in session data:

1. Recommended: in `sessionProperties` or `scopedProperties`.
[Docs](https://docs.walletconnect.network/wallet-sdk/react-native/eip5792#wallet-response)
2. Legacy: in the `capabilities` prop inside `sessionProperties`.
[Source](https://github.com/WalletConnect/walletconnect-monorepo/blob/1e6d7793d0a30d2bf684cd3811ba120b4cdc0498/providers/universal-provider/src/providers/eip155.ts#L219-L223)

We do support both approaches for maximal compatibility.

### Notes

* When using the recommended approach, WalletConnect does not return
capabilities if the optional `chainIds` array is omitted in
`wallet_getCapabilities` request.
* We've proposed a PR to address this in the WalletConnect repo:
WalletConnect/walletconnect-monorepo#6955

### Test plan

* Updated unit test
* Tested manually using
https://bakoushin.github.io/wallet-connect-tester/


https://github.com/user-attachments/assets/bd3a6d15-4dd1-4dff-a295-a49828500d45

### Related issues

- Part of ENG-644

### Backwards compatibility

Y

### Network scalability

If a new NetworkId and/or Network are added in the future, the changes
in this PR will:

- [x] Continue to work without code changes, OR trigger a compilation
error (guaranteeing we find it when a new network is added)
Copy link
Member

@ganchoradkov ganchoradkov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the fix @bakoushin! I think the correct fix is a bit more involved though - I've added suggestions to improve it - for example to get the chains from the approved accounts rather than the chains since they are optionally present in the session. Further more I'm wondering about the case where both address specific and chain specific capabilities exist e.g.

 "eip155:137": {
          "eip155:137:0x0910e12C68d02B561a34569E1367c9AAb42bd811": {
            atomic: {
              status: "supported",
            },
          },
         paymasterService: {
              supported: true,
         },
     },

and the result should be

 "0x89": {
        atomic: {
          status: "supported",
        },
       // this capability applies to all addresses on that chain
        paymasterService: {
          supported: true,
        },
      },

this case fails because we need to loop here to get all provider capabilities
https://github.com/WalletConnect/walletconnect-monorepo/pull/6955/files#diff-c0f6b48d5568497e5d855c04009289856302dc5a75aeebb143adb37986e12c59L65-L68

Comment on lines 57 to 60
const namespaceChainIds =
namespaces[EIP155_PREFIX]?.chains
?.map((chain) => decimalToHex(chain.split(":")[1]))
.filter(Boolean) ?? [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const namespaceChainIds =
namespaces[EIP155_PREFIX]?.chains
?.map((chain) => decimalToHex(chain.split(":")[1]))
.filter(Boolean) ?? [];
const namespaceChainIds =
namespaces[EIP155_PREFIX]?.accounts
.filter((account) => account.includes(`:${address}`))
?.map((account) => decimalToHex(parseChainId(account).reference))
.filter(Boolean) ?? [];

Check the accounts because we don't want to get all chains, just the chains this address was approved with

tip: you can import parseChainId from "@walletconnect/utils"

Comment on lines +430 to +434
"0x1": {
atomic: {
status: "unsupported",
},
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"0x1": {
atomic: {
status: "unsupported",
},
},

with the change to loop through the accounts instead of chains, this 0x1 capabilty no longer applies

const session = {
namespaces: {
eip155: {
chains: ["eip155:1", "eip155:137", "eip155:84532"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
chains: ["eip155:1", "eip155:137", "eip155:84532"],
accounts: [
"eip155:137:0x0910e12C68d02B561a34569E1367c9AAb42bd811",
"eip155:84532:0x0910e12C68d02B561a34569E1367c9AAb42bd810",
],

@bakoushin
Copy link
Author

@ganchoradkov Thanks for the detailed feedback!

I guess it is now addressed:

  • namespace chainIds are extracted with respect to approved addresses
  • the resulting capabilities object is constructed by layering from the least to the most specific definitions:
  1. global capabilities
  2. chain-specific capabilities (if present)
  3. address-specific capabilities (if present)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants