- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control. - Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities. - Created .gitmodules to include OpenZeppelin contracts as a submodule. - Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment. - Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks. - Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring. - Created scripts for resource import and usage validation across non-US regions. - Added tests for CCIP error handling and integration to ensure robust functionality. - Included various new files and directories for the orchestration portal and deployment scripts.
6.3 KiB
6.3 KiB
MetaMask Developer Guide for ChainID 138
Developer guide for integrating ChainID 138 with MetaMask in your dapp.
Installation
Using npm
npm install @defi-oracle/metamask-sdk
Using the source
cd metamask-sdk
npm install
npm run build
Basic Usage
Import the SDK
import {
addOrSwitchNetwork,
addToken,
isOnChain138,
getCurrentChainId,
} from '@defi-oracle/metamask-sdk';
Connect to ChainID 138
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
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
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
import React from 'react';
import { useChain138 } from './useChain138';
function Chain138Button() {
const { isConnected, isLoading, connect } = useChain138();
if (isLoading) {
return <button disabled>Loading...</button>;
}
if (isConnected) {
return <button disabled>Connected to ChainID 138</button>;
}
return (
<button onClick={connect}>
Connect to ChainID 138
</button>
);
}
Vue Integration
Composable
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
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
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
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
// 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