Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integrations/wagmi/metamask-connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
return createConnector<Provider, Properties>((config) => ({
id: 'metaMaskSDK',
name: 'MetaMask',
rdns: ['io.metamask', 'io.metamask.mobile'],
rdns: ['io.metamask', 'io.metamask.mobile', 'io.metamask.flask'],
type: metaMask.type,
async connect({ chainId = 1, isReconnecting, withCapabilities } = {}) {
const instance = await this.getInstance();
Expand Down
4 changes: 4 additions & 0 deletions packages/connect-evm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- Recognize MetaMask Flask (`io.metamask.flask`) as a native MetaMask EIP-6963 provider. The MMConnect-managed provider announcement is now suppressed when Flask has announced, avoiding a duplicate MetaMask entry in wallet pickers. ([#336](https://github.com/MetaMask/connect-monorepo/pull/336))

## [2.1.0]

### Changed
Expand Down
2 changes: 1 addition & 1 deletion packages/connect-evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ await client.disconnect();

##### `announceProvider()`

Announces the MMConnect-managed EIP-1193 provider through EIP-6963 unless a native MetaMask provider has already announced with `rdns` `io.metamask` or `io.metamask.mobile`. This is called automatically by `createEVMClient()` unless `skipAutoAnnounce: true` is set. The first call may take up to 300 ms while native providers are requested.
Announces the MMConnect-managed EIP-1193 provider through EIP-6963 unless a native MetaMask provider has already announced with `rdns` `io.metamask`, `io.metamask.mobile`, or `io.metamask.flask`. This is called automatically by `createEVMClient()` unless `skipAutoAnnounce: true` is set. The first call may take up to 300 ms while native providers are requested.

**Parameters**

Expand Down
5 changes: 2 additions & 3 deletions packages/connect-evm/src/eip6963.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ describe('EIP-6963 announcement', () => {
expect(details).toHaveLength(0);
});

it('does not suppress the SDK provider when MetaMask Flask has announced', async () => {
it('suppresses the SDK provider when MetaMask Flask has announced', async () => {
const client = await MetamaskConnectEVM.create({ core: createMockCore() });
const nativeHandler = (): void =>
announceNativeMetaMaskProvider('io.metamask.flask');
Expand All @@ -278,8 +278,7 @@ describe('EIP-6963 announcement', () => {
EIP6963_REQUEST_PROVIDER_EVENT,
nativeHandler,
);
expect(details).toHaveLength(1);
expect(details[0].info.rdns).toBe(CONNECT_EVM_EIP6963_RDNS);
expect(details).toHaveLength(0);
});

it('re-announces the same SDK provider detail on later EIP-6963 provider requests', async () => {
Expand Down
5 changes: 3 additions & 2 deletions packages/connect-evm/src/eip6963.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const CONNECT_EVM_EIP6963_RDNS = 'io.metamask.mmc';
export const METAMASK_EIP6963_RDNS = [
'io.metamask',
'io.metamask.mobile',
'io.metamask.flask',
] as const;

/**
Expand Down Expand Up @@ -232,8 +233,8 @@ const hasNativeMetaMaskProvider = async (): Promise<boolean> => {
* Announces an MMConnect-managed EIP-1193 provider through EIP-6963.
*
* Announcement is best-effort and browser-only. Native MetaMask providers with
* `io.metamask` or `io.metamask.mobile` suppress this SDK provider to avoid
* duplicate MetaMask entries in wallet pickers.
* `io.metamask`, `io.metamask.mobile`, or `io.metamask.flask` suppress this SDK
* provider to avoid duplicate MetaMask entries in wallet pickers.
*/
export class EIP6963ProviderAnnouncer {
/** EIP-1193 provider exposed in EIP-6963 announcements. */
Expand Down
1 change: 1 addition & 0 deletions packages/connect-multichain/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- Recognize MetaMask Flask (`io.metamask.flask`) as a native MetaMask extension in EIP-6963 detection. `hasExtension()` now returns `true` when only Flask is installed, so `connect()` uses the browser extension transport instead of falling back to the MWP/QR flow. ([#336](https://github.com/MetaMask/connect-monorepo/pull/336))
- Closing the QR code / install modal mid-connection now emits `mmconnect_connection_rejected` instead of `mmconnect_connection_failed`. Modal close is a user-driven cancellation; it previously rejected with a plain `Error('User closed modal')` that `isRejectionError` did not recognise, so user cancellations polluted the `_failed` bucket. The close handler now rejects with the canonical EIP-1193 `4001` error (`providerErrors.userRejectedRequest()`). Genuine errors (transport timeouts/disconnects, wallet RPC errors) still emit `mmconnect_connection_failed`. ([#333](https://github.com/MetaMask/connect-monorepo/pull/333))

## [1.1.0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe('hasExtension', () => {
await expect(detection).resolves.toBe(true);
});

it.each(['io.metamask', 'io.metamask.mobile'])(
it.each(['io.metamask', 'io.metamask.mobile', 'io.metamask.flask'])(
'treats native MetaMask rdns %s as the extension',
async (rdns) => {
setupEip6963Window(rdns);
Expand Down
1 change: 1 addition & 0 deletions packages/connect-multichain/src/domain/platform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum PlatformType {
const NATIVE_METAMASK_EIP6963_RDNS = new Set([
'io.metamask',
'io.metamask.mobile',
'io.metamask.flask',
]);

function isNotBrowser(): boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
return createConnector<Provider, Properties>((config) => ({
id: 'metaMaskSDK',
name: 'MetaMask',
rdns: ['io.metamask', 'io.metamask.mobile'],
rdns: ['io.metamask', 'io.metamask.mobile', 'io.metamask.flask'],
type: metaMask.type,
async connect({ chainId = 1, isReconnecting, withCapabilities } = {}) {
const instance = await this.getInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
return createConnector<Provider, Properties>((config) => ({
id: 'metaMaskSDK',
name: 'MetaMask',
rdns: ['io.metamask', 'io.metamask.mobile'],
rdns: ['io.metamask', 'io.metamask.mobile', 'io.metamask.flask'],
type: metaMask.type,
async connect({ chainId = 1, isReconnecting, withCapabilities } = {}) {
const instance = await this.getInstance();
Expand Down
10 changes: 10 additions & 0 deletions skills/metamask-connect/references/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,16 @@ Add `connect-src` entries for any custom RPC endpoints you pass to `supportedNet

---

### 23. MetaMask Flask not detected as the extension (falls back to QR / mobile)

**Cause:** Before this fix, MetaMask Connect only recognized the native MetaMask RDNS values `io.metamask` (production extension) and `io.metamask.mobile`. MetaMask **Flask** announces itself over EIP-6963 with `rdns: 'io.metamask.flask'`, which was not in the allowlist — so `hasExtension()` returned `false` when only Flask was installed, and `connect()` fell through to the MWP transport (QR code / mobile deeplink) instead of using the local Flask extension. (The legacy `@metamask/sdk` did recognize Flask, which is why this looked like a regression.)

**Fix:** `io.metamask.flask` is now included in the recognized native MetaMask RDNS values (extension detection, the connect-evm EIP-6963 announcement suppression, and the wagmi `metaMask()` connector's `rdns`). With a current version, Flask connects through the browser extension transport just like the production extension — no extra configuration needed.

If you are pinned to an older version and cannot upgrade, the workaround is to connect through wagmi's built-in EIP-6963 auto-discovery: Flask shows up as a separate connector whose `id` is its rdns, `io.metamask.flask`. Selecting that connector talks directly to the Flask injected provider, but note it bypasses the MetaMask Connect SDK (no MWP fallback, no Connect session handling).

---

## Diagnostic Checklist

Run through this checklist when any MetaMask Connect integration is misbehaving:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ metaMask({

- `@metamask/connect-evm` is an **optional peer dependency** of `@wagmi/connectors` — you only need it if you use the `metaMask()` connector
- The connector ID remains `'metaMaskSDK'` and the name remains `'MetaMask'` — no changes to connector identity
- The connector's `rdns` is `['io.metamask', 'io.metamask.mobile']` — unchanged
- The connector's `rdns` is `['io.metamask', 'io.metamask.mobile', 'io.metamask.flask']` — MetaMask Flask is recognized as a native install, so it connects through the extension transport like the production extension (the legacy `@metamask/sdk` also recognized Flask)
- The `supportedNetworks` map is now auto-built from wagmi's configured chains and their default RPC URLs — you no longer need to pass `readonlyRPCMap`
- The `dappMetadata` parameter still works (it's mapped to `dapp` internally) but is deprecated — migrate to `dapp` for forward compatibility
- The `logging` parameter still works (mapped to `debug: true`) but is deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ Ensure React Native polyfills are set up per [../references/react-native.md](../
## Important Notes

- The connector ID is `'metaMaskSDK'` and the display name is `'MetaMask'`
- The connector RDNS is `['io.metamask', 'io.metamask.mobile']`
- The connector RDNS is `['io.metamask', 'io.metamask.mobile', 'io.metamask.flask']` — MetaMask Flask (`io.metamask.flask`) is recognized as a native MetaMask install, so the connector uses the extension transport for Flask just like the production extension
- `@metamask/connect-evm` is an optional peer dependency of `@wagmi/connectors` — only needed when you use the `metaMask()` connector, and the installed version must satisfy wagmi's declared peer range (currently `^2.1.0`), not "latest"
- The `supportedNetworks` map is auto-built from wagmi chain config — no manual RPC URL configuration needed
- If no `dapp` config is provided, defaults to `{ name: window.location.hostname, url: window.location.href }` in browsers
Expand Down
Loading