Skip to content

Commit

Permalink
Merge pull request #834 from vsakos/solflare-metamask-inpage-provider
Browse files Browse the repository at this point in the history
Initialize the MetaMask extension provider internally
  • Loading branch information
jordaaash authored Oct 10, 2023
2 parents 0574e65 + 3d2e0cd commit 4341474
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 54 deletions.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-cows-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solana/wallet-adapter-solflare': patch
---

Optimize Solflare MetaMask snap detection
12 changes: 6 additions & 6 deletions packages/wallets/solflare/src/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import type { WalletAdapterNetwork, WalletName } from '@solana/wallet-adapter-base';
import {
BaseMessageSignerWalletAdapter,
isIosAndRedirectable,
isVersionedTransaction,
scopePollingDetectionStrategy,
type SendTransactionOptions,
WalletConfigError,
WalletConnectionError,
WalletDisconnectedError,
Expand All @@ -18,9 +14,13 @@ import {
WalletSendTransactionError,
WalletSignMessageError,
WalletSignTransactionError,
isIosAndRedirectable,
isVersionedTransaction,
scopePollingDetectionStrategy,
type SendTransactionOptions,
} from '@solana/wallet-adapter-base';
import type { Transaction, TransactionVersion, VersionedTransaction } from '@solana/web3.js';
import { type Connection, PublicKey, type TransactionSignature } from '@solana/web3.js';
import { PublicKey, type Connection, type TransactionSignature } from '@solana/web3.js';
import type { default as Solflare } from '@solflare-wallet/sdk';
import { detectAndRegisterSolflareMetaMaskWallet } from './metamask/detect.js';

Expand Down Expand Up @@ -71,7 +71,7 @@ export class SolflareWalletAdapter extends BaseMessageSignerWalletAdapter {
}
return false;
});
scopePollingDetectionStrategy(detectAndRegisterSolflareMetaMaskWallet);
detectAndRegisterSolflareMetaMaskWallet();
}
}

Expand Down
87 changes: 39 additions & 48 deletions packages/wallets/solflare/src/metamask/detect.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,52 @@
import type { EthereumProvider, WindowWithEthereum } from '@solflare-wallet/metamask-sdk';
import { registerWallet } from '@wallet-standard/wallet';
import { SolflareMetaMaskWallet } from './wallet.js';

let stopPolling = false;
let registered = false;

/** @internal */
export function detectAndRegisterSolflareMetaMaskWallet(): boolean {
// If detected, stop polling.
if (stopPolling) return true;
(async function () {
try {
// Try to detect, stop polling if detected, and register the wallet.
if (await isSnapProviderDetected()) {
if (!stopPolling) {
stopPolling = true;
registerWallet(new SolflareMetaMaskWallet());
}
}
} catch (error) {
// Stop polling on unhandled errors (this should never happen).
stopPolling = true;
}
})();
// Keep polling.
return false;
function register() {
if (registered) return;
registerWallet(new SolflareMetaMaskWallet());
registered = true;
}

async function isSnapProviderDetected(): Promise<boolean> {
try {
const provider = (window as WindowWithEthereum).ethereum;
if (!provider) return false;
/** @internal */
export async function detectAndRegisterSolflareMetaMaskWallet(): Promise<void> {
const id = 'solflare-detect-metamask';

const providerProviders = provider.providers;
if (providerProviders && Array.isArray(providerProviders)) {
for (const provider of providerProviders) {
if (await isSnapSupported(provider)) return true;
}
}
function postMessage() {
window.postMessage(
{
target: 'metamask-contentscript',
data: {
name: 'metamask-provider',
data: {
id,
jsonrpc: '2.0',
method: 'wallet_getSnaps',
},
},
},
window.location.origin
);
}

function onMessage(event: MessageEvent) {
const message = event.data;
if (message?.target === 'metamask-inpage' && message.data?.name === 'metamask-provider') {
if (message.data.data?.id === id) {
window.removeEventListener('message', onMessage);

const providerDetected = provider.detected;
if (providerDetected && Array.isArray(providerDetected)) {
for (const provider of providerDetected) {
if (await isSnapSupported(provider)) return true;
if (!message.data.data.error) {
register();
}
} else {
postMessage();
}
}

return await isSnapSupported(provider);
} catch (error) {
return false;
}
}

async function isSnapSupported(provider: EthereumProvider): Promise<boolean> {
try {
await provider.request({ method: 'wallet_getSnaps' });
return true;
} catch (error) {
return false;
}
window.addEventListener('message', onMessage);
window.setTimeout(() => window.removeEventListener('message', onMessage), 5000);

postMessage();
}

0 comments on commit 4341474

Please sign in to comment.