Web3 API Reference
This document provides detailed reference information for developers integrating with Macro Browser's Web3 capabilities.
Provider Object
Macro Browser injects a standard Web3 provider object (window.ethereum
) into all pages, following the EIP-1193 specification with some Macro-specific enhancements.
interface MacroProvider {
// Standard EIP-1193 Properties
isConnected(): boolean;
chainId: string;
selectedAddress: string | null;
// Standard EIP-1193 Methods
request(args: RequestArguments): Promise<unknown>;
on(eventName: string, listener: (arg: any) => void): Provider;
removeListener(eventName: string, listener: (arg: any) => void): Provider;
// Macro Browser Specific
isMacro: boolean; // Always true, identifies Macro Browser
isPrivate: boolean; // Indicates if browser is in private mode (always true)
securityLevel: 'standard' | 'enhanced'; // Current security settings
}
interface RequestArguments {
method: string;
params?: unknown[] | object;
}
Supported JSON-RPC Methods
Basic Methods
eth_accounts
None
string[]
Returns active accounts
eth_requestAccounts
None
string[]
Requests user permission for account access
eth_chainId
None
string
Returns current chain ID in hex
eth_blockNumber
None
string
Returns latest block number in hex
eth_getBalance
[address, blockTag]
string
Returns account balance
eth_sendTransaction
[transactionObject]
string
Sends a transaction
eth_call
[transactionObject, blockTag]
string
Executes a call without creating a transaction
eth_estimateGas
[transactionObject]
string
Estimates gas needed for transaction
eth_gasPrice
None
string
Returns current gas price
eth_getTransactionCount
[address, blockTag]
string
Returns account nonce
eth_getCode
[address, blockTag]
string
Returns contract code at address
eth_getStorageAt
[address, position, blockTag]
string
Returns value in contract storage
eth_getTransactionByHash
[txHash]
Object
Returns transaction details
eth_getTransactionReceipt
[txHash]
Object
Returns transaction receipt
Signing Methods
eth_sign
[address, message]
string
Signs a message (legacy)
personal_sign
[message, address]
string
Signs a personal message
eth_signTypedData
[address, typedData]
string
Signs typed data (legacy)
eth_signTypedData_v4
[address, typedData]
string
Signs typed data (current)
eth_signTransaction
[transactionObject]
Object
Signs without sending
Chain Management
wallet_switchEthereumChain
[{ chainId }]
None
Switches to specified chain
wallet_addEthereumChain
[chainObject]
None
Adds new chain definition
wallet_getPermissions
None
Object[]
Returns current permissions
wallet_requestPermissions
[{ eth_accounts }]
Object[]
Requests permissions
Macro-Specific Methods
macro_getVersion
None
string
Returns Macro Browser version
macro_getSecurityLevel
None
string
Gets current security level
macro_analyzeTransaction
[transactionObject]
Object
Analyzes transaction risk
macro_isVpnEnabled
None
boolean
Checks if VPN is active
Provider Events
Developers can subscribe to events from the provider:
window.ethereum.on('connect', (connectInfo) => {
console.log('Connected to chain:', connectInfo.chainId);
});
window.ethereum.on('disconnect', (error) => {
console.log('Disconnected from provider:', error);
});
window.ethereum.on('accountsChanged', (accounts) => {
console.log('Accounts changed:', accounts);
});
window.ethereum.on('chainChanged', (chainId) => {
console.log('Chain changed:', chainId);
// Best practice: reload page on chain change
window.location.reload();
});
window.ethereum.on('message', (message) => {
console.log('Provider message:', message);
});
Transaction Objects
Transaction objects have the following structure:
interface TransactionObject {
// Required
from: string; // Sender address
// Optional but usually provided
to?: string; // Recipient address (required except for contract creation)
value?: string; // Amount in hex wei (default: '0x0')
data?: string; // Transaction data in hex (default: '0x')
// Optional (can be auto-estimated)
gas?: string; // Gas limit in hex
gasPrice?: string; // Gas price in hex wei
maxFeePerGas?: string; // EIP-1559 max fee
maxPriorityFeePerGas?: string; // EIP-1559 priority fee
// Optional (advanced)
nonce?: string; // Transaction nonce in hex
chainId?: string; // Chain ID in hex
}
Chain Objects
When adding new chains, the following structure is used:
interface ChainObject {
chainId: string; // Chain ID in hex format (e.g., '0x89')
chainName: string; // Human-readable name (e.g., 'Polygon Mainnet')
nativeCurrency: {
name: string; // Currency name (e.g., 'MATIC')
symbol: string; // Currency symbol (e.g., 'MATIC')
decimals: number; // Decimal places (usually 18)
};
rpcUrls: string[]; // List of RPC endpoints
blockExplorerUrls?: string[]; // List of block explorers
iconUrls?: string[]; // List of chain icons
}
Security Considerations
Transaction Analysis
Macro Browser performs advanced transaction analysis for user safety:
// Example of using the transaction analysis feature
async function analyzeBeforeSending(transactionObject) {
try {
// Get security analysis
const analysis = await window.ethereum.request({
method: 'macro_analyzeTransaction',
params: [transactionObject]
});
// Check risk level
if (analysis.riskLevel === 'high') {
// Show warning to user
const proceed = confirm(
`Warning: This transaction has high risk factors:\n` +
analysis.warnings.join('\n') + '\n\n' +
'Do you want to proceed anyway?'
);
if (!proceed) {
throw new Error('Transaction cancelled due to security concerns');
}
}
// Proceed with transaction
return await window.ethereum.request({
method: 'eth_sendTransaction',
params: [transactionObject]
});
} catch (error) {
console.error('Transaction error:', error);
throw error;
}
}
Permissions
Always check for permissions before attempting operations:
async function checkPermissions() {
try {
const permissions = await window.ethereum.request({
method: 'wallet_getPermissions'
});
// Check if we have eth_accounts permission
const hasAccountsPermission = permissions.some(
permission => permission.parentCapability === 'eth_accounts'
);
if (!hasAccountsPermission) {
console.log('No account permissions. Request access first.');
return false;
}
return true;
} catch (error) {
console.error('Error checking permissions:', error);
return false;
}
}
Error Handling
Macro Browser provides detailed error codes. Handle common errors properly:
async function handleWeb3Operation(operation) {
try {
return await operation();
} catch (error) {
switch (error.code) {
case 4001:
console.log('User rejected the request');
break;
case 4100:
console.log('Unauthorized - request not approved');
break;
case 4200:
console.log('Unsupported method');
break;
case 4900:
console.log('Disconnected from chain');
break;
case 4901:
console.log('Chain not available');
break;
case 4902:
console.log('Chain not added - suggest adding it');
break;
default:
console.error('Unknown error:', error);
}
throw error;
}
}
Usage Examples
Connecting to a dApp
async function connectDApp() {
if (typeof window.ethereum !== 'undefined') {
try {
// Request account access
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
// Get chain ID
const chainId = await window.ethereum.request({
method: 'eth_chainId'
});
// Initialize your dApp with connected account and chain
initializeDApp(accounts[0], chainId);
// Set up event listeners
window.ethereum.on('accountsChanged', handleAccountsChanged);
window.ethereum.on('chainChanged', handleChainChanged);
return true;
} catch (error) {
console.error('Error connecting to dApp:', error);
return false;
}
} else {
console.error('No Ethereum provider found');
return false;
}
}
Contract Interaction
async function callContractMethod(contractAddress, methodABI, params) {
// Encode function call
const methodSignature = web3.eth.abi.encodeFunctionSignature(methodABI);
const encodedParams = web3.eth.abi.encodeParameters(
methodABI.inputs.map(input => input.type),
params
);
const data = methodSignature + encodedParams.slice(2);
// Call the contract
const result = await window.ethereum.request({
method: 'eth_call',
params: [{
to: contractAddress,
data: data
}, 'latest']
});
// Decode result
return web3.eth.abi.decodeParameter(
methodABI.outputs[0].type,
result
);
}
Transaction with Confirmation
async function sendTransactionWithConfirmation(tx) {
try {
// Send transaction
const txHash = await window.ethereum.request({
method: 'eth_sendTransaction',
params: [tx]
});
console.log('Transaction sent:', txHash);
// Poll for receipt
let receipt = null;
while (receipt === null) {
try {
receipt = await window.ethereum.request({
method: 'eth_getTransactionReceipt',
params: [txHash]
});
} catch (e) {
console.error('Error polling for receipt:', e);
}
if (receipt === null) {
// Wait 2 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
console.log('Transaction confirmed:', receipt);
return receipt;
} catch (error) {
console.error('Transaction failed:', error);
throw error;
}
}
Compatibility Notes
Browser Differences
Macro Browser implements the same provider API as MetaMask with some differences:
All accounts are treated as "read-only" by default for security
Contains extra security checks for potentially risky operations
Provides additional methods for transaction analysis
No support for legacy methods that have security implications
Feature Detection
Always use feature detection instead of browser detection:
// Check for specific method support
async function hasAnalysisSupport() {
if (typeof window.ethereum === 'undefined') return false;
try {
// Try getting provider metadata
const metadata = await window.ethereum.request({
method: 'web3_clientVersion'
});
// Check for explicit macro support
if (window.ethereum.isMacro === true) return true;
// Check if client version mentions macro
if (typeof metadata === 'string' &&
metadata.toLowerCase().includes('macro')) {
return true;
}
// Try calling macro-specific method
try {
await window.ethereum.request({
method: 'macro_getVersion'
});
return true;
} catch (e) {
// Method doesn't exist
return false;
}
} catch (error) {
return false;
}
}
Last updated