Skip to content

feat: wallet button multichain#4688

Merged
0xmkh merged 12 commits intomainfrom
feat/wallet-button-multichain
Jul 22, 2025
Merged

feat: wallet button multichain#4688
0xmkh merged 12 commits intomainfrom
feat/wallet-button-multichain

Conversation

@0xmkh
Copy link
Copy Markdown
Collaborator

@0xmkh 0xmkh commented Jul 22, 2025

Description

Upgraded wallet button to support multichain via the namespace prop

Example usage with Components

import '@reown/appkit-wallet-button'

const wallets = [
  { wallet: 'metamask', namespace: 'eip155', label: 'MetaMask EVM' },
  { wallet: 'metamask', namespace: 'solana', label: 'MetaMask Solana' },
  { wallet: 'phantom', namespace: 'bip122', label: 'Phantom Bitcoin' },
]

export function WalletButtons() {
  return (
    <>
      {wallets.map(({ wallet, namespace, label }) => (
        <appkit-wallet-button
          key={`${wallet}-${namespace}`}
          wallet={wallet}
          namespace={namespace}
        />
      ))}
    </>
  )
}

Example usage with Hooks

import { useAppKitWallet } from '@reown/appkit-wallet-button/react'

export function YourApp() {
  const { data, error, isPending, isSuccess, isError, connect } = useAppKitWallet({
    namespace: 'eip155', // Use 'solana' or 'bip122' for other chains
    onError: err => {
      // ...
    },
    onSuccess: data => {
      // ...
    }
  })

  return (
    <>
      <button onClick={() => connect('walletConnect')}>Open QR modal</button>
      <button onClick={() => connect('metamask')}>Connect to MetaMask</button>
      <button onClick={() => connect('google')}>Connect to Google</button>
    </>
  )
}

Example usage with Vanilla JS

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <script type="module">
      import '@reown/appkit-wallet-button'
      import { createAppKitWalletButton } from '@reown/appkit-wallet-button'

      const wallet = createAppKitWalletButton({ namespace: 'eip155' })

      async function setup() {
        if (!(await wallet.isReady())) {
          wallet.subscribeIsReady(state => {
            if (state.isReady) enableButtons()
          })
        } else {
          enableButtons()
        }
      }

      function enableButtons() {
        document.querySelectorAll('button[data-wallet]').forEach(button => {
          button.disabled = false
          button.addEventListener('click', () => {
            const walletId = button.getAttribute('data-wallet')
            wallet.connect(walletId)
          })
        })
      }

      setup()
    </script>
  </head>
  <body>
    <appkit-wallet-button wallet="metamask" namespace="eip155"></appkit-wallet-button>

    <button data-wallet="walletConnect" disabled>Open QR modal</button>
    <button data-wallet="metamask" disabled>Connect to MetaMask</button>
    <button data-wallet="google" disabled>Connect to Google</button>
  </body>
</html>

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)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Associated Issues

For Linear issues: Closes APKT-3122

Checklist

  • Code in this PR is covered by automated tests (Unit tests, E2E tests)
  • My changes generate no new warnings
  • I have reviewed my own code
  • I have filled out all required sections
  • I have tested my changes on the preview link
  • Approver of this PR confirms that the changes are tested on the preview link

@vercel
Copy link
Copy Markdown

vercel bot commented Jul 22, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
appkit-basic-html ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 22, 2025 1:12pm
appkit-demo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 22, 2025 1:12pm
appkit-gallery ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 22, 2025 1:12pm
appkit-laboratory ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 22, 2025 1:12pm
10 Skipped Deployments
Name Status Preview Comments Updated (UTC)
appkit-basic-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
appkit-basic-sign-client-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
appkit-basic-up-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
appkit-ethers5-bera ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
appkit-nansen-demo ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
appkit-vue-solana ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
appkit-wagmi-cdn-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
ethereum-provider-wagmi-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
next-wagmi-solana-bitcoin-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm
vue-wagmi-example ⬜️ Ignored (Inspect) Jul 22, 2025 1:12pm

@linear
Copy link
Copy Markdown

linear bot commented Jul 22, 2025

cursor[bot]

This comment was marked as outdated.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jul 22, 2025

Warnings
⚠️

🔑 Potential High‑entropy string detected in packages/controllers/tests/controllers/ConnectorController.test.ts (line 101): ecc4036f814562b41a52...

Generated by 🚫 dangerJS against c41956a

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jul 22, 2025

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 77.65% 30911 / 39803
🔵 Statements 77.65% 30911 / 39803
🔵 Functions 68.88% 2539 / 3686
🔵 Branches 84.3% 6456 / 7658
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/controllers/src/controllers/ConnectorController.ts 86.68% 98.29% 75.4% 86.68% 62-64, 129-131, 142, 197-198, 224-232, 302-322, 339-344, 419, 423-424
packages/controllers/src/utils/ConnectorControllerUtil.ts 18.55% 88.88% 33.33% 18.55% 75-76, 96-109, 112-285, 288-318, 321-361, 364-370, 186
packages/scaffold-ui/src/partials/w3m-connect-recommended-widget/index.ts 82.85% 84% 75% 82.85% 38-42, 72-75, 94, 97, 103-104
packages/wallet-button/src/client.ts 63.09% 81.25% 36.36% 63.09% 41-42, 50-59, 66-67, 69-70, 82, 92-101, 103-104, 109-110
packages/wallet-button/src/scaffold-ui/appkit-wallet-button/index.ts 79.32% 87.5% 69.23% 79.32% 53, 61-62, 75-76, 83-84, 98-99, 137, 210-211, 213-214, 227-251
Generated in workflow #13569 for commit c41956a by the Vitest Coverage Report Action

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Jul 22, 2025

🦋 Changeset detected

Latest commit: c41956a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@reown/appkit-wallet-button Patch
@reown/appkit-controllers Patch
@reown/appkit-scaffold-ui Patch
@reown/appkit-adapter-bitcoin Patch
@reown/appkit-adapter-ethers Patch
@reown/appkit-adapter-ethers5 Patch
@reown/appkit-adapter-solana Patch
@reown/appkit-adapter-wagmi Patch
@reown/appkit Patch
@reown/appkit-utils Patch
@reown/appkit-cdn Patch
@reown/appkit-cli Patch
@reown/appkit-codemod Patch
@reown/appkit-common Patch
@reown/appkit-core Patch
@reown/appkit-experimental Patch
@reown/appkit-pay Patch
@reown/appkit-polyfills Patch
@reown/appkit-siwe Patch
@reown/appkit-siwx Patch
@reown/appkit-testing Patch
@reown/appkit-ui Patch
@reown/appkit-wallet Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@0xmkh 0xmkh changed the title Feat/wallet button multichain feat: wallet button multichain Jul 22, 2025
cursor[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Collaborator

@tomiir tomiir left a comment

Choose a reason for hiding this comment

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

Don't we need tests for the wallet buttons component?

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Optional Parameters Cause Incorrect Connector Matches

The getConnector method's id and rdns parameters were made optional, but its internal logic c.explorerId === id || c.info?.rdns === rdns does not correctly handle undefined inputs. This can lead to incorrect matches when id or rdns are undefined, as c.explorerId === undefined or c.info?.rdns === undefined will match connectors with uninitialized or missing IDs/RDNS. Crucially, if both id and rdns are undefined, the method may return an unintended connector instead of returning no connector.

packages/controllers/src/controllers/ConnectorController.ts#L284-L299

getConnector({
id,
rdns,
namespace
}: {
id?: string
rdns?: string | null
namespace?: ChainNamespace
}) {
const namespaceToUse = namespace || ChainController.state.activeChain
const connectorsByNamespace = state.allConnectors.filter(c => c.chain === namespaceToUse)
return connectorsByNamespace.find(c => c.explorerId === id || c.info?.rdns === rdns)
},

Fix in CursorFix in Web


Bug: Error State Persistence After Successful Connection

The error state reset logic was removed from AppKitWalletButton's ChainController subscriptions. Previously, this.error was set to false when activeCaipAddress became truthy. This logic is now missing from both the general and namespace-specific caipAddress subscriptions, causing the button to remain in an error state even after a successful connection.

packages/wallet-button/src/scaffold-ui/appkit-wallet-button/index.ts#L77-L93

if (this.namespace) {
this.unsubscribe.push(
ChainController.subscribeChainProp(
'accountState',
val => {
this.caipAddress = val?.caipAddress
},
this.namespace
)
)
} else {
this.unsubscribe.push(
ChainController.subscribeKey('activeCaipAddress', val => (this.caipAddress = val))
)
}
}

Fix in CursorFix in Web


Bug: Social Connector Namespace Parameter Inconsistency

The connectSocial function inconsistently passes the namespace parameter to ConnectorController.getAuthConnector(). While one call correctly uses the provided namespaceToUse, other calls within the same function omit this parameter. This can lead to different authentication connectors being retrieved within the same social connection flow, causing connection failures or incorrect behavior in multichain scenarios.

packages/controllers/src/utils/ConnectorControllerUtil.ts#L230-L245

const authConnector = ConnectorController.getAuthConnector()
if (authConnector) {
if (!AccountController.state.farcasterUrl) {
try {
const { url } = await authConnector.provider.getFarcasterUri()
AccountController.setFarcasterUrl(url, namespaceToUse)
} catch {
reject(new Error('Failed to connect to farcaster'))
}
}
}
} else {
const authConnector = ConnectorController.getAuthConnector()

Fix in CursorFix in Web


Was this report helpful? Give feedback by reacting with 👍 or 👎

@0xmkh 0xmkh added this pull request to the merge queue Jul 22, 2025
Merged via the queue into main with commit a457e61 Jul 22, 2025
50 of 60 checks passed
@0xmkh 0xmkh deleted the feat/wallet-button-multichain branch July 22, 2025 14:06
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.

3 participants