MetaMask Browser Extension Integration
MetaMask is the most popular Ethereum browser extension wallet, providing secure access to Ethereum and EVM-compatible networks. SwapKit SDK v4 offers comprehensive support for MetaMask and other EVM browser extensions through a unified interface.
Supported Extensions
Section titled “Supported Extensions”SwapKit’s EVM extension integration supports:
- MetaMask: The most popular Ethereum wallet extension
- Brave Wallet: Built into Brave browser
- Coinbase Wallet: Browser extension version
- Trust Wallet: Browser extension version
- OKX Wallet: Browser extension version
- Any EIP-6963 compatible wallet: Standard for wallet discovery
Supported Chains
Section titled “Supported Chains”All EVM-compatible chains are supported:
- Layer 1: Ethereum, BinanceSmartChain, Avalanche, Polygon
- Layer 2: Arbitrum, Optimism, Base
- Side Chains: Gnosis, Aurora
- Custom Networks: Any EVM-compatible chain
Installation and Setup
Section titled “Installation and Setup”1. Install Browser Extension
Section titled “1. Install Browser Extension”Install your preferred EVM wallet extension:
- MetaMask: [Chrome Web Store](https:
- Brave Wallet: Built into Brave browser
- Coinbase Wallet: [Chrome Web Store](https:
- Trust Wallet: [Chrome Web Store](https:
2. Set Up Wallet
Section titled “2. Set Up Wallet”- Create or import a wallet using your seed phrase
- Set up a secure password
- Add the networks you want to use (if not already present)
3. Browser Requirements
Section titled “3. Browser Requirements”EVM extensions work in:
- Chrome/Chromium: Full support
- Firefox: Full support
- Safari: Limited support (depends on extension)
- Edge: Full support
- Brave: Built-in wallet support
SwapKit Integration
Section titled “SwapKit Integration”Basic Setup
Section titled “Basic Setup”Granular Approach (Recommended for Frontend)
Section titled “Granular Approach (Recommended for Frontend)”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ config: { apiKeys: { swapKit: "your-api-key", }, }, wallets: { ...evmWallet },});All-in-One Approach (Backend/Node.js)
Section titled “All-in-One Approach (Backend/Node.js)”import { createSwapKit, Chain } from "@swapkit/sdk";
const swapKit = createSwapKit({ config: { apiKeys: { swapKit: "your-api-key", }, },});Connecting MetaMask
Section titled “Connecting MetaMask”Basic Connection
Section titled “Basic Connection”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function connectMetaMask() { try { await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.METAMASK);
const address = swapKit.getAddress(Chain.Ethereum); const balance = await swapKit.getBalance(Chain.Ethereum, true);
console.log("Connected address:", address); console.log("ETH balance:", balance);
return { success: true, address, balance }; } catch (error) { console.error("Failed to connect MetaMask:", error); return { success: false, error }; }}Multi-Chain Connection
Section titled “Multi-Chain Connection”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function connectMultipleEVMChains() { const evmChains = [ Chain.Ethereum, Chain.Polygon, Chain.Arbitrum, Chain.BinanceSmartChain, Chain.Avalanche, ];
try { await swapKit.connectEVMWallet(evmChains, WalletOption.METAMASK);
const address = swapKit.getAddress(Chain.Ethereum); console.log("EVM address (same on all chains):", address);
const balances = await Promise.all( evmChains.map(async (chain) => { const balance = await swapKit.getBalance(chain, true); return { chain, balance }; }) );
return { success: true, address, balances }; } catch (error) { console.error("Multi-chain connection failed:", error); return { success: false, error }; }}Connecting Other EVM Extensions
Section titled “Connecting Other EVM Extensions”Brave Wallet
Section titled “Brave Wallet”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function connectBraveWallet() { try { await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.BRAVE);
const address = swapKit.getAddress(Chain.Ethereum); console.log("Brave Wallet address:", address);
return { success: true, address }; } catch (error) { console.error("Failed to connect Brave Wallet:", error); return { success: false, error }; }}Coinbase Wallet Extension
Section titled “Coinbase Wallet Extension”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function connectCoinbaseWallet() { try { await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.COINBASE_WEB);
const address = swapKit.getAddress(Chain.Ethereum); console.log("Coinbase Wallet address:", address);
return { success: true, address }; } catch (error) { console.error("Failed to connect Coinbase Wallet:", error); return { success: false, error }; }}Trust Wallet Extension
Section titled “Trust Wallet Extension”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function connectTrustWallet() { try { await swapKit.connectEVMWallet( [Chain.Ethereum], WalletOption.TRUSTWALLET_WEB );
const address = swapKit.getAddress(Chain.Ethereum); console.log("Trust Wallet address:", address);
return { success: true, address }; } catch (error) { console.error("Failed to connect Trust Wallet:", error); return { success: false, error }; }}EIP-6963 Compatible Wallets
Section titled “EIP-6963 Compatible Wallets”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
function getEIP6963Wallets() { return new Promise((resolve) => { const wallets = [];
window.addEventListener("eip6963:announceProvider", (event) => { wallets.push(event.detail); });
window.dispatchEvent(new Event("eip6963:requestProvider"));
setTimeout(() => resolve(wallets), 100); });}
async function connectEIP6963Wallet(providerDetail) { try { const { provider } = providerDetail;
await swapKit.connectEVMWallet( [Chain.Ethereum], WalletOption.EIP6963, provider );
const address = swapKit.getAddress(Chain.Ethereum); console.log(`${providerDetail.info.name} address:`, address);
return { success: true, address }; } catch (error) { console.error(`Failed to connect ${providerDetail.info.name}:`, error); return { success: false, error }; }}
async function showAvailableWallets() { const wallets = await getEIP6963Wallets();
console.log("Available wallets:"); wallets.forEach((wallet) => { console.log(`- ${wallet.info.name}: ${wallet.info.rdns}`); });
if (wallets.length > 0) { await connectEIP6963Wallet(wallets[0]); }}Transaction Examples
Section titled “Transaction Examples”Basic ETH Transfer
Section titled “Basic ETH Transfer”import { SwapKit, evmWallet, Chain, AssetValue, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.METAMASK);
async function sendEther() { const recipient = "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC"; const amount = AssetValue.fromChainOrSignature("ETH.ETH", 0.01);
try { console.log("Sending ETH transaction..."); console.log("Amount:", amount.toSignificant(6), "ETH"); console.log("To:", recipient);
const txHash = await swapKit.transfer({ assetValue: amount, recipient, });
console.log("✅ Transaction sent:", txHash); console.log("🔍 View on Etherscan:", `https:
return txHash; } catch (error) { console.error("❌ Transaction failed:", error); throw error; }}ERC-20 Token Transfer
Section titled “ERC-20 Token Transfer”import { SwapKit, evmWallet, Chain, AssetValue, WalletOption,} from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.METAMASK);
async function sendERC20Token() { const recipient = "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC";
const amount = AssetValue.fromChainOrSignature( "ETH.USDC-0xA0B86A33E6441E89D5E4C4EDF4C8DF4C0E6C62F6", 100 );
try { const txHash = await swapKit.transfer({ assetValue: amount, recipient, });
console.log("✅ USDC transfer sent:", txHash); return txHash; } catch (error) { console.error("❌ USDC transfer failed:", error); throw error; }}
async function sendAnyERC20Token( tokenAddress: string, amount: number, recipient: string, decimals: number = 18) { const tokenAsset = AssetValue.fromChainOrSignature( `ETH.TOKEN-${tokenAddress}`, amount );
try { const txHash = await swapKit.transfer({ assetValue: tokenAsset, recipient, });
console.log(`✅ Token transfer sent:`, txHash); return txHash; } catch (error) { console.error(`❌ Token transfer failed:`, error); throw error; }}Multi-Chain Transactions
Section titled “Multi-Chain Transactions”import { SwapKit, evmWallet, Chain, AssetValue, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
await swapKit.connectEVMWallet([Chain.Ethereum, Chain.Polygon, Chain.Arbitrum], WalletOption.METAMASK);
async function sendOnPolygon() { const recipient = "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC"; const amount = AssetValue.fromChainOrSignature("MATIC.MATIC", 1);
try { const txHash = await swapKit.transfer({ assetValue: amount, recipient, });
console.log("✅ MATIC transfer sent:", txHash); console.log("🔍 View on PolygonScan:", `https:
return txHash; } catch (error) { console.error("❌ MATIC transfer failed:", error); throw error; }}
async function sendOnArbitrum() { const recipient = "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC"; const amount = AssetValue.fromChainOrSignature("ARB.ETH", 0.001);
try { const txHash = await swapKit.transfer({ assetValue: amount, recipient, });
console.log("✅ Arbitrum ETH transfer sent:", txHash); console.log("🔍 View on Arbiscan:", `https:
return txHash; } catch (error) { console.error("❌ Arbitrum transfer failed:", error); throw error; }}Network Management
Section titled “Network Management”Automatic Network Switching
Section titled “Automatic Network Switching”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function switchAndTransact() { try { await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.METAMASK);
await swapKit.connectEVMWallet([Chain.Polygon], WalletOption.METAMASK);
const amount = AssetValue.fromChainOrSignature("MATIC.MATIC", 1); const recipient = "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC";
const txHash = await swapKit.transfer({ assetValue: amount, recipient, });
console.log("Transaction on Polygon:", txHash); return txHash; } catch (error) { if (error.message.includes("network")) { console.error("❌ Network switch failed"); console.log("Please manually switch to Polygon network in MetaMask"); } throw error; }}Adding Custom Networks
Section titled “Adding Custom Networks”async function addCustomNetwork() { if (typeof window.ethereum !== 'undefined') { try {
await window.ethereum.request({ method: 'wallet_addEthereumChain', params: [ { chainId: '0x89', chainName: 'Polygon Mainnet', nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18, }, rpcUrls: [''] }, ], });
console.log('✅ Network added successfully'); } catch (error) { console.error('❌ Failed to add network:', error); } }}Common Troubleshooting
Section titled “Common Troubleshooting”Connection Issues
Section titled “Connection Issues”import { SwapKit, evmWallet, Chain, WalletOption } from "@swapkit/sdk";
const swapKit = SwapKit({ wallets: { ...evmWallet },});
async function diagnosticConnection() { try { if (typeof window.ethereum === "undefined") { console.error("❌ No Ethereum provider found"); console.log("🔧 Install MetaMask or another Ethereum wallet"); return { success: false, error: "No provider" }; }
if (!window.ethereum.isMetaMask) { console.warn("⚠️ MetaMask not detected as active provider"); console.log("🔧 Ensure MetaMask is enabled and active"); }
console.log("🔍 Attempting to connect...");
await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.METAMASK);
const address = swapKit.getAddress(Chain.Ethereum); console.log("✅ Successfully connected:", address);
return { success: true, address }; } catch (error) { console.error("❌ Connection failed:", error);
if (error.message.includes("User rejected")) { console.log("🔧 User rejected connection request"); console.log("Please approve the connection in MetaMask"); }
if (error.message.includes("Already processing")) { console.log("🔧 MetaMask is busy processing another request"); console.log("Please wait and try again"); }
return { success: false, error }; }}
async function checkWalletStatus() { try { const accounts = await window.ethereum.request({ method: "eth_accounts", });
if (accounts.length === 0) { console.log("❌ No accounts connected"); return { connected: false }; }
const chainId = await window.ethereum.request({ method: "eth_chainId", });
console.log("✅ Wallet connected"); console.log("Account:", accounts[0]); console.log("Chain ID:", chainId);
return { connected: true, account: accounts[0], chainId, }; } catch (error) { console.error("Failed to check wallet status:", error); return { connected: false, error }; }}Transaction Failures
Section titled “Transaction Failures”async function handleTransactionErrors() { try { const amount = AssetValue.fromChainOrSignature("ETH.ETH", 0.01); const txHash = await swapKit.transfer({ assetValue: amount, recipient: "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC", }); return txHash; } catch (error) { if (error.message.includes("insufficient funds")) { console.error("❌ Insufficient ETH for transaction + gas fees");
const balance = await swapKit.getBalance(Chain.Ethereum, true); console.log("Current balance:", balance); console.log( "🔧 Add more ETH to your wallet or reduce transaction amount" ); }
if (error.message.includes("User denied")) { console.error("❌ Transaction rejected in MetaMask"); console.log("🔧 Please approve the transaction in MetaMask"); }
if (error.message.includes("gas")) { console.error("❌ Gas estimation failed or gas limit too low"); console.log("🔧 Try increasing gas limit or check network congestion"); }
if (error.message.includes("nonce")) { console.error("❌ Nonce issues"); console.log( "🔧 Reset account in MetaMask (Settings > Advanced > Reset Account)" ); }
if (error.message.includes("network")) { console.error("❌ Wrong network selected"); console.log("🔧 Switch to the correct network in MetaMask"); }
throw error; }}Network Issues
Section titled “Network Issues”async function handleNetworkIssues() { try { await swapKit.connectEVMWallet([Chain.Polygon], WalletOption.METAMASK); } catch (error) { if (error.message.includes("failed_to_switch_network")) { console.error("❌ Failed to switch to Polygon network");
try { await window.ethereum.request({ method: 'wallet_addEthereumChain', params: [ { chainId: '0x89', chainName: 'Polygon Mainnet', nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18, }, rpcUrls: ['https:'], }, ], });
console.log("✅ Network added, please try connecting again"); } catch (addError) { console.error("❌ Failed to add network:", addError); console.log("🔧 Please add Polygon network manually in MetaMask"); } }
throw error; }}Security Considerations
Section titled “Security Considerations”Best Practices
Section titled “Best Practices”async function verifyConnection() { const swapKit = SwapKit({ wallets: { ...evmWallet } }); await swapKit.connectEVMWallet([Chain.Ethereum], WalletOption.METAMASK);
const address = swapKit.getAddress(Chain.Ethereum);
console.log("Connected address:", address); console.log("⚠️ Please verify this is your intended address");
return address;}
async function secureTransaction() { try { const amount = AssetValue.fromChainOrSignature("ETH.ETH", 0.01); const recipient = "0x742d35Cc6632C0532c718C5E6F99d7E89b12c9bC";
console.log("📋 Transaction Details:"); console.log("Amount:", amount.toSignificant(6), "ETH"); console.log("Recipient:", recipient); console.log("⚠️ Please verify these details in MetaMask before confirming");
const txHash = await swapKit.transfer({ assetValue: amount, recipient, });
return txHash; } catch (error) { console.error("Transaction failed"); throw new Error("Transaction failed. Please try again."); }}
function isValidEthereumAddress(address: string): boolean { return /^0x[a-fA-F0-9]{40}$/.test(address);}
async function safeTransfer(recipient: string, amount: number) { if (!isValidEthereumAddress(recipient)) { throw new Error("Invalid recipient address"); }
const assetValue = AssetValue.fromChainOrSignature("ETH.ETH", amount);
if (amount <= 0) { throw new Error("Amount must be positive"); }
return await swapKit.transfer({ assetValue, recipient, });}Secure Configuration
Section titled “Secure Configuration”const secureSwapKit = SwapKit({ config: {
rpcUrls: { [Chain.Ethereum]: "https: [Chain.Polygon]: "https: [Chain.Arbitrum]: "https: },
apiKeys: { swapKit: process.env.SWAPKIT_API_KEY, }, }, wallets: { ...evmWallet },});React Integration
Section titled “React Integration”import React, { useState, useEffect } from 'react';import { SwapKit, evmWallet, Chain, WalletOption, AssetValue } from "@swapkit/sdk";
interface MetaMaskWalletProps { onConnect: (address: string) => void; onError: (error: Error) => void;}
export function MetaMaskWallet({ onConnect, onError }: MetaMaskWalletProps) { const [isConnecting, setIsConnecting] = useState(false); const [isConnected, setIsConnected] = useState(false); const [address, setAddress] = useState<string>(""); const [selectedChain, setSelectedChain] = useState<Chain>(Chain.Ethereum);
const swapKit = SwapKit({ wallets: { ...evmWallet } });
const isMetaMaskInstalled = typeof window !== 'undefined' && typeof window.ethereum !== 'undefined';
useEffect(() => { if (!isMetaMaskInstalled) return;
const handleAccountsChanged = (accounts: string[]) => { if (accounts.length === 0) {
setIsConnected(false); setAddress(""); } else if (accounts[0] !== address) {
setAddress(accounts[0]); onConnect(accounts[0]); } };
const handleChainChanged = (chainId: string) => {
console.log("Chain changed to:", chainId); };
window.ethereum.on('accountsChanged', handleAccountsChanged); window.ethereum.on('chainChanged', handleChainChanged);
return () => { if (window.ethereum.removeListener) { window.ethereum.removeListener('accountsChanged', handleAccountsChanged); window.ethereum.removeListener('chainChanged', handleChainChanged); } }; }, [address, isMetaMaskInstalled]);
const connectMetaMask = async () => { if (!isMetaMaskInstalled) { onError(new Error("MetaMask not installed")); return; }
setIsConnecting(true);
try { await swapKit.connectEVMWallet([selectedChain], WalletOption.METAMASK); const walletAddress = swapKit.getAddress(selectedChain);
setAddress(walletAddress); setIsConnected(true); onConnect(walletAddress); } catch (error) { onError(error as Error); } finally { setIsConnecting(false); } };
const disconnect = async () => { try { swapKit.disconnectAll(); setIsConnected(false); setAddress(""); } catch (error) { console.error("Disconnect failed:", error); } };
if (!isMetaMaskInstalled) { return ( <div> <p>MetaMask not installed</p> <a href="https: target="_blank" rel="noopener noreferrer" > Install MetaMask </a> </div> ); }
return ( <div> <h3>MetaMask Wallet</h3>
{!isConnected ? ( <div> <select value={selectedChain} onChange={(e) => setSelectedChain(e.target.value as Chain)} disabled={isConnecting} > <option value={Chain.Ethereum}>Ethereum</option> <option value={Chain.Polygon}>Polygon</option> <option value={Chain.Arbitrum}>Arbitrum</option> <option value={Chain.BinanceSmartChain}>BSC</option> </select>
<button onClick={connectMetaMask} disabled={isConnecting} > {isConnecting ? "Connecting..." : "Connect MetaMask"} </button> </div> ) : ( <div> <p><strong>Chain:</strong> {selectedChain}</p> <p><strong>Address:</strong> {address}</p> <button onClick={disconnect}>Disconnect</button> </div> )} </div> );}This comprehensive guide covers all aspects of MetaMask and EVM browser extension integration with SwapKit SDK v4, including setup, usage, troubleshooting, and security best practices.