# MetaMask Developer Guide for ChainID 138 Developer guide for integrating ChainID 138 with MetaMask in your dapp. ## Installation ### Using npm ```bash npm install @defi-oracle/metamask-sdk ``` ### Using the source ```bash cd metamask-sdk npm install npm run build ``` ## Basic Usage ### Import the SDK ```typescript import { addOrSwitchNetwork, addToken, isOnChain138, getCurrentChainId, } from '@defi-oracle/metamask-sdk'; ``` ### Connect to ChainID 138 ```typescript async function connect() { try { await addOrSwitchNetwork(); const isOn138 = await isOnChain138(); if (isOn138) { console.log('Connected to ChainID 138'); } } catch (error) { console.error('Connection error:', error); } } ``` ### Add Token ```typescript async function addWETHToken() { try { await addToken( '0xYourWETHAddress', 'WETH', 18, 'https://explorer.d-bis.org/images/tokens/weth.png' ); } catch (error) { console.error('Token add error:', error); } } ``` ## React Integration ### Custom Hook ```typescript import { useState, useEffect } from 'react'; import { isOnChain138, addOrSwitchNetwork } from '@defi-oracle/metamask-sdk'; function useChain138() { const [isConnected, setIsConnected] = useState(false); const [isLoading, setIsLoading] = useState(true); useEffect(() => { checkConnection(); // Listen for chain changes if (window.ethereum) { window.ethereum.on('chainChanged', checkConnection); return () => { window.ethereum.removeListener('chainChanged', checkConnection); }; } }, []); async function checkConnection() { try { const on138 = await isOnChain138(); setIsConnected(on138); } catch (error) { setIsConnected(false); } finally { setIsLoading(false); } } async function connect() { try { await addOrSwitchNetwork(); await checkConnection(); } catch (error) { console.error('Connection error:', error); } } return { isConnected, isLoading, connect }; } ``` ### React Component ```typescript import React from 'react'; import { useChain138 } from './useChain138'; function Chain138Button() { const { isConnected, isLoading, connect } = useChain138(); if (isLoading) { return ; } if (isConnected) { return ; } return ( ); } ``` ## Vue Integration ### Composable ```typescript import { ref, onMounted, onUnmounted } from 'vue'; import { isOnChain138, addOrSwitchNetwork } from '@defi-oracle/metamask-sdk'; export function useChain138() { const isConnected = ref(false); const isLoading = ref(true); async function checkConnection() { try { const on138 = await isOnChain138(); isConnected.value = on138; } catch (error) { isConnected.value = false; } finally { isLoading.value = false; } } async function connect() { try { await addOrSwitchNetwork(); await checkConnection(); } catch (error) { console.error('Connection error:', error); } } function handleChainChanged() { checkConnection(); } onMounted(() => { checkConnection(); if (window.ethereum) { window.ethereum.on('chainChanged', handleChainChanged); } }); onUnmounted(() => { if (window.ethereum) { window.ethereum.removeListener('chainChanged', handleChainChanged); } }); return { isConnected, isLoading, connect }; } ``` ## Error Handling ### Common Errors ```typescript import { addNetwork } from '@defi-oracle/metamask-sdk'; try { await addNetwork(); } catch (error) { if (error.message.includes('MetaMask is not installed')) { // Handle MetaMask not installed alert('Please install MetaMask'); } else if (error.message.includes('User rejected')) { // Handle user rejection console.log('User rejected the request'); } else if (error.code === 4902) { // Network already added, try switching await switchNetwork(); } else { // Handle other errors console.error('Unexpected error:', error); } } ``` ## RPC Best Practices ### Rate Limiting - Default: 1200 requests/minute per IP - Use request batching when possible - Implement client-side rate limiting - Use WebSocket connections for real-time data ### Request Batching ```typescript const batch = [ { method: 'eth_blockNumber', params: [] }, { method: 'eth_gasPrice', params: [] }, { method: 'eth_getBalance', params: [address, 'latest'] }, ]; const results = await Promise.all( batch.map(req => window.ethereum.request(req)) ); ``` ### WebSocket Connections ```typescript const ws = new WebSocket('wss://rpc.d-bis.org'); ws.onmessage = (event) => { const data = JSON.parse(event.data); console.log('Received:', data); }; ws.send(JSON.stringify({ jsonrpc: '2.0', method: 'eth_subscribe', params: ['newHeads'], id: 1 })); ``` ## Testing ### Mock MetaMask for Testing ```typescript // mock-metamask.ts export function createMockMetaMask() { return { isMetaMask: true, request: async (args: { method: string; params?: unknown[] }) => { if (args.method === 'eth_chainId') { return '0x8a'; } if (args.method === 'wallet_addEthereumChain') { return null; } if (args.method === 'wallet_switchEthereumChain') { return null; } throw new Error('Method not implemented'); }, on: () => {}, removeListener: () => {}, }; } // In your tests global.window.ethereum = createMockMetaMask(); ``` ## Production Checklist - [ ] Verify RPC URLs are correct and accessible - [ ] Test network addition on all target browsers - [ ] Test token addition for all tokens - [ ] Verify error handling for all error cases - [ ] Test network switching functionality - [ ] Verify chain change event listeners - [ ] Test on mobile MetaMask - [ ] Verify token logos are accessible - [ ] Test with different MetaMask versions - [ ] Verify CORS headers on RPC endpoints ## References - [MetaMask SDK Documentation](../metamask-sdk/README.md) - [MetaMask Integration Guide](./METAMASK_INTEGRATION.md) - [Quick Start Guide](../metamask/QUICK_START.md) - [MetaMask Documentation](https://docs.metamask.io)