I'm developing a DApp in the form of a Chrome extension that connects to a smart contract on Solana. When I integrate it into the browser, it cannot detect Phantom or Solflare. This is because it runs in an isolated context. I used PhantomWalletAdapter and SolflareWalletAdapter as adapters. Here are some components of the DApp Wallet.tsx
import { FC, useMemo } from 'react';
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
import {
PhantomWalletAdapter,
SolflareWalletAdapter,
TorusWalletAdapter,
LedgerWalletAdapter,
UnsafeBurnerWalletAdapter
} from '@solana/wallet-adapter-wallets';
import {
WalletModalProvider,
WalletDisconnectButton,
WalletMultiButton
} from '@solana/wallet-adapter-react-ui';
import { clusterApiUrl } from '@solana/web3.js';
import '@solana/wallet-adapter-react-ui/styles.css';
export const Wallet: FC = () => {
const network = WalletAdapterNetwork.Devnet;
const endpoint = useMemo(() => clusterApiUrl(network), [network]);
const wallets = useMemo(
() => [
new PhantomWalletAdapter(),
new SolflareWalletAdapter(),
new TorusWalletAdapter(),
new LedgerWalletAdapter(),
new UnsafeBurnerWalletAdapter(),
],
[network]
);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={wallets} autoConnect>
<WalletModalProvider>
<WalletMultiButton />
<WalletDisconnectButton />
<h1>Hello Solana</h1>
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
};
content-script.ts
console.log("Solana extension content script loaded");
window.addEventListener('message', (event) => {
if (event.data?.type?.includes('solana') && event.source === window) {
// Forward messages to your background script
chrome.runtime.sendMessage(event.data);
}
});
chrome.runtime.onMessage.addListener((message) => {
if (message?.type?.includes('solana')) {
window.postMessage(message, '*');
}
return true;
});
service-worker.ts
chrome.runtime.onInstalled.addListener((): void => {
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true })
.catch((error: Error) => {
console.error('Failed to set panel behavior:', error);
});
});
and the manifest file
{
"manifest_version": 3,
"name": "Solana Extension",
"version": "1.0.0",
"description": "Solana Chrome extension",
"background": {
"service_worker": "service-worker.js",
"type": "module"
},
"action": {
"default_title": "Click to open panel"
},
"side_panel": {
"default_path": "index.html"
},
"permissions": ["sidePanel", "activeTab", "tabs", "storage", "webNavigation"],
"host_permissions": ["<all_urls>"],
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'; connect-src 'self' https://*.solana.com https://solana-mainnet.g.alchemy.com https://*.metaplex.com"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content-script.js"],
"run_at": "document_start"
}
]
}
I managed to get it working with MetaMask on EVM using @metamask/extension-provider, but there doesn't seem to be an equivalent for Solana.