一键导入
metamask-openclaw-wallet-integration
Connect MetaMask wallets, read balances, sign messages, and send transactions on EVM chains with a safety-first TypeScript SDK
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Connect MetaMask wallets, read balances, sign messages, and send transactions on EVM chains with a safety-first TypeScript SDK
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | metamask-openclaw-wallet-integration |
| description | Connect MetaMask wallets, read balances, sign messages, and send transactions on EVM chains with a safety-first TypeScript SDK |
| triggers | ["integrate MetaMask wallet into my dapp","connect to MetaMask and read user balance","sign a message with MetaMask","send a transaction using OpenClaw","switch MetaMask to a different network","set up wallet connection in my web3 app","handle MetaMask account changes","prepare an Ethereum transfer with user approval"] |
Skill by ara.so — Hermes Skills collection.
OpenClaw is a safety-first TypeScript toolkit and SDK for integrating MetaMask wallets into dapps. Built on the official MetaMask SDK, it provides a clean API for:
Safety guarantee: OpenClaw never requests or handles seed phrases or private keys. All sensitive operations require user approval in the MetaMask UI.
npm install metamask-openclaw-skill
# or
yarn add metamask-openclaw-skill
# or
pnpm add metamask-openclaw-skill
git clone https://github.com/veryyoldman/metamask-openclaw-skill.git
cd metamask-openclaw-skill
npm install
npm run build
git clone https://github.com/veryyoldman/metamask-openclaw-skill.git && cd metamask-openclaw-skill && npm install && npm run build
import { OpenClaw } from "metamask-openclaw-skill";
// Initialize
const claw = new OpenClaw({
dappMetadata: {
name: "My Dapp",
url: "https://mydapp.example"
},
// Optional: provide Infura key for reliable RPC
infuraApiKey: process.env.INFURA_API_KEY
});
// Connect wallet (triggers MetaMask popup or QR code)
await claw.connect();
// Get current state
const { account, chainId } = claw.getState();
console.log(`Connected: ${account} on chain ${chainId}`);
# Connect and display address + network
node dist/cli/openclaw.js connect
# Check balance
node dist/cli/openclaw.js balance
# Prepare a transfer (user approves in MetaMask)
node dist/cli/openclaw.js send 0xRecipientAddress 0.001
<!DOCTYPE html>
<html>
<head>
<title>OpenClaw Demo</title>
</head>
<body>
<button id="connect">Connect MetaMask</button>
<div id="info"></div>
<script type="module">
import { OpenClaw } from './dist/index.js';
const claw = new OpenClaw({
dappMetadata: { name: "Demo", url: window.location.href }
});
document.getElementById('connect').onclick = async () => {
await claw.connect();
const { account, chainId } = claw.getState();
const balance = await claw.getBalance();
document.getElementById('info').innerText =
`${account}\nChain: ${chainId}\nBalance: ${balance.formatted} ${balance.symbol}`;
};
</script>
</body>
</html>
interface OpenClawOptions {
dappMetadata: {
name: string; // Your dapp name
url: string; // Your dapp URL
iconUrl?: string; // Optional icon
};
infuraApiKey?: string; // Optional Infura key for RPC
defaultChainId?: string; // e.g. "0x1" for Ethereum mainnet
}
const claw = new OpenClaw(options);
// Connect to MetaMask (shows popup or QR)
await claw.connect();
// Disconnect
claw.disconnect();
// Check connection status
const isConnected = claw.isConnected();
// Get current state
const state = claw.getState();
// Returns: { account: string | null, chainId: string | null }
// Get native token balance
const balance = await claw.getBalance();
// Returns: { formatted: string, symbol: string, raw: string }
// Example: { formatted: "1.234", symbol: "ETH", raw: "1234000000000000000" }
// Get balance for specific address
const balance = await claw.getBalance("0xOtherAddress");
// Sign a message (user approves in MetaMask)
const signature = await claw.signMessage("Hello, Web3!");
// Returns: string (hex signature)
// Switch to a different network
await claw.switchChain("0x89"); // Polygon
await claw.switchChain("0x2105"); // Base
await claw.switchChain("0xa4b1"); // Arbitrum
// If the network isn't in MetaMask, it will be added (user approves)
// Send native token (user approves amount + gas in MetaMask)
const txHash = await claw.sendNative({
to: "0xRecipientAddress",
amount: "0.001" // in native token (e.g. ETH, POL)
});
console.log(`Transaction sent: ${txHash}`);
// Listen for account or network changes
claw.onChange((state) => {
console.log("Wallet changed:", state);
// state: { account: string | null, chainId: string | null }
});
// Remove listener
const unsubscribe = claw.onChange(handler);
unsubscribe();
# .env file
INFURA_API_KEY=your_infura_key_here
import { OpenClaw } from "metamask-openclaw-skill";
const claw = new OpenClaw({
dappMetadata: {
name: process.env.DAPP_NAME || "My Dapp",
url: process.env.DAPP_URL || "http://localhost:3000"
},
infuraApiKey: process.env.INFURA_API_KEY
});
| Network | Chain ID | Symbol |
|---|---|---|
| Ethereum Mainnet | 0x1 | ETH |
| Polygon | 0x89 | POL |
| Arbitrum One | 0xa4b1 | ETH |
| OP Mainnet | 0xa | ETH |
| Base | 0x2105 | ETH |
| Linea | 0xe708 | ETH |
| Sepolia (testnet) | 0xaa36a7 | ETH |
Add custom networks in src/chains.ts.
import { OpenClaw } from "metamask-openclaw-skill";
import { useEffect, useState } from "react";
function WalletButton() {
const [claw] = useState(() => new OpenClaw({
dappMetadata: { name: "My App", url: window.location.href }
}));
const [account, setAccount] = useState<string | null>(null);
const [balance, setBalance] = useState<string>("");
useEffect(() => {
claw.onChange((state) => {
setAccount(state.account);
if (state.account) {
claw.getBalance().then(b => setBalance(`${b.formatted} ${b.symbol}`));
}
});
}, [claw]);
const handleConnect = async () => {
await claw.connect();
const state = claw.getState();
setAccount(state.account);
if (state.account) {
const b = await claw.getBalance();
setBalance(`${b.formatted} ${b.symbol}`);
}
};
return (
<div>
{!account ? (
<button onClick={handleConnect}>Connect MetaMask</button>
) : (
<div>
<p>{account}</p>
<p>{balance}</p>
</div>
)}
</div>
);
}
async function sendTokens(claw: OpenClaw, recipient: string, amount: string) {
const state = claw.getState();
if (!state.account) {
throw new Error("No wallet connected");
}
const balance = await claw.getBalance();
if (parseFloat(balance.formatted) < parseFloat(amount)) {
throw new Error("Insufficient balance");
}
const txHash = await claw.sendNative({ to: recipient, amount });
console.log(`Transfer initiated: ${txHash}`);
return txHash;
}
async function checkBalanceOnChains(claw: OpenClaw, chains: string[]) {
const balances: Record<string, string> = {};
for (const chainId of chains) {
await claw.switchChain(chainId);
const balance = await claw.getBalance();
balances[chainId] = `${balance.formatted} ${balance.symbol}`;
}
return balances;
}
// Usage
const balances = await checkBalanceOnChains(claw, ["0x1", "0x89", "0x2105"]);
console.log(balances);
// { "0x1": "1.5 ETH", "0x89": "100 POL", "0x2105": "0.5 ETH" }
async function signAuthMessage(claw: OpenClaw, nonce: string) {
const state = claw.getState();
if (!state.account) {
throw new Error("No wallet connected");
}
const message = `Sign to authenticate\nAddress: ${state.account}\nNonce: ${nonce}`;
const signature = await claw.signMessage(message);
return { message, signature, address: state.account };
}
Solution: Ensure MetaMask extension is installed and enabled. On mobile, use the in-app browser or scan the QR code.
if (!window.ethereum) {
alert("Please install MetaMask: https://metamask.io/download/");
}
Cause: Waiting for MetaMask Mobile QR scan.
Solution: The CLI prints a QR code. Open MetaMask Mobile and scan it.
Cause: User clicked "Cancel" or "Reject" in MetaMask.
Solution: Catch the error and prompt the user to try again.
try {
await claw.connect();
} catch (error) {
if (error.code === 4001) {
console.log("User rejected connection");
}
}
Cause: No funds in the test account.
Solution: Get testnet ETH from a faucet:
Cause: Network not configured in MetaMask.
Solution: OpenClaw automatically adds the network (user approves). Ensure chain details are correct in src/chains.ts.
Cause: No Infura API key or exceeded free tier.
Solution: Sign up at https://infura.io/ and set INFURA_API_KEY environment variable.
const claw = new OpenClaw({
dappMetadata: { name: "App", url: "https://app.example" },
infuraApiKey: process.env.INFURA_API_KEY // Add this
});
OpenClaw never:
Always:
Never enter your Secret Recovery Phrase anywhere except the official MetaMask app when restoring a wallet. OpenClaw will never ask for it.
When helping users with OpenClaw:
sendNative()getBalance() for read-only balance checksExample safe agent response:
I can help you prepare a transaction using OpenClaw. Here's the code:
await claw.sendNative({ to: "0xRecipient", amount: "0.001" });
This will show a MetaMask popup where YOU approve the amount and gas.
OpenClaw never handles your keys — you stay in full control.
examples/basic-dapp for a working browser demoSECURITY.md in the repositoryCONTRIBUTING.md in the repositoryKeywords: metamask, wallet integration, web3, ethereum, evm, polygon, base, arbitrum, sign message, send transaction, dapp, typescript, sdk
Browser-based interface for viewing and filtering OpenClaw session tool call history with zero dependencies for local network deployment.
AI-powered quantitative research and backtesting platform with end-to-end workflow from research to strategy publication
Give your AI assistant a phone — OpenClaw plugin for real phone calls via Twilio + OpenAI Realtime API with in-call tools, transcripts, and call screening
Run multi-model consensus panels (Lite or Heavy) with your own agent backends—no hosted middleware, your models, your rules.
Build a multi-role JARVIS-style voice assistant with local ASR/TTS, OpenClaw LLM gateway, voice wake words, HUD effects, and speaker verification
Use 37 battle-tested marketing skills covering CRO, copywriting, SEO, paid ads, email, growth, and strategy with real data connectors for Google Ads, Search Console, Meta Ads, and X/Twitter