Files
smom-dbis-138/docs/operations/integrations/METAMASK_DEVELOPER_GUIDE.md
defiQUG 1fb7266469 Add Oracle Aggregator and CCIP Integration
- 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.
2025-12-12 14:57:48 -08:00

310 lines
6.3 KiB
Markdown

# 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 <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
```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)