DEV Community

Cover image for Cách Sử Dụng MetaMask API: Kết Nối dApp với Ví Ethereum
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Cách Sử Dụng MetaMask API: Kết Nối dApp với Ví Ethereum

MetaMask là cổng truy cập Ethereum mặc định cho hàng chục triệu người dùng. Nếu bạn xây dựng dApp, MetaMask API là cầu nối giữa frontend và khóa ký của người dùng. "MetaMask API" thực chất gồm hai phần: nhà cung cấp window.ethereum (chuẩn EIP-1193) được inject vào trình duyệt, và MetaMask SDK mở rộng cho mobile, React Native, Node.js. Nắm chắc provider này, bạn đã kiểm soát được 80% tích hợp ví trên web.

Dùng thử Apidog ngay hôm nay

Bài này hướng dẫn bạn phát hiện provider, yêu cầu tài khoản, đọc chain hiện tại, ký message với personal_sign và EIP-712, gửi transaction, thêm/chuyển chain, và sử dụng MetaMask SDK ngoài browser extension. Ngoài ra, bạn sẽ thấy ethers.js v6, viem đóng vai trò wrapper như thế nào, và Apidog hỗ trợ kiểm thử JSON-RPC mà không cần viết code frontend một lần.

Nếu làm việc với ví, hãy bookmark hướng dẫn API ví tiền điện tử tốt nhất để tổng quan hơn về các provider.

TL;DR (Tóm tắt)

  • MetaMask API là EIP-1193 provider ở window.ethereum + MetaMask SDK cho mobile/Node.
  • Khởi đầu với eth_requestAccounts để kết nối, sau đó lắng nghe accountsChangedchainChanged.
  • Ký message với personal_sign; ký dữ liệu cấu trúc với eth_signTypedData_v4 (EIP-712).
  • Chuyển network bằng wallet_switchEthereumChain (EIP-3326), thêm chain mới với wallet_addEthereumChain (EIP-3085).
  • ethers.js v6, viem và wagmi là wrapper cấp cao; Snaps mở rộng MetaMask.
  • Sử dụng Apidog để test endpoint JSON-RPC, mô phỏng transaction & debug signature trước khi production.

MetaMask API là gì?

MetaMask API cung cấp interface để web/app tương tác với Ethereum hoặc bất kỳ chuỗi EVM nào. Extension sẽ inject object window.ethereum tuân thủ EIP-1193. Mọi dApp tuân EIP-1193 sẽ chạy với MetaMask, Coinbase Wallet, Rabby, Frame v.v mà không cần thay đổi code.

Với mobile, backend, desktop, MetaMask SDK cung cấp provider tương tự cho React Native, Node.js, Electron, script server-side. SDK xử lý deep-link và quy trình QR để ví MetaMask mobile ký các request từ desktop/backend. Tất cả vẫn nói EIP-1193 nên code không đổi.

MetaMask cũng có Snaps, hệ plugin mở rộng ví với chain mới, RPC custom, loại tài khoản mới. Snaps ngoài phạm vi bài này, nhưng rất hữu ích nếu bạn cần hỗ trợ non-EVM chain hoặc custom signing flow.

Xác thực và thiết lập

Không cần API key cho provider. Xác thực dựa vào user approve từng request trên giao diện ví. Bạn cần: cách phát hiện provider và lắng nghe events.

Phát hiện provider:

Dùng helper @metamask/detect-provider hoặc kiểm tra trực tiếp.

// Phát hiện MetaMask với Vanilla JS
import detectEthereumProvider from '@metamask/detect-provider';

const provider = await detectEthereumProvider({ mustBeMetaMask: true });

if (!provider) {
  alert('Vui lòng cài đặt MetaMask');
} else {
  console.log('Đã phát hiện MetaMask');
}
Enter fullscreen mode Exit fullscreen mode

Lắng nghe sự kiện:

Luôn set listener cho accountsChangedchainChanged trước bất kỳ request nào.

window.ethereum.on('accountsChanged', (accounts) => {
  if (accounts.length === 0) {
    console.log('Người dùng đã ngắt kết nối');
  } else {
    console.log('Tài khoản đang hoạt động:', accounts[0]);
  }
});

window.ethereum.on('chainChanged', (chainId) => {
  // Best practice: reload lại app khi chain đổi
  window.location.reload();
});
Enter fullscreen mode Exit fullscreen mode

Nếu dùng React, wagmi sẽ tự động nhận diện MetaMask qua injected connector.

Các điểm cuối cốt lõi

Toàn bộ lệnh gọi qua window.ethereum.request({ method, params }). Dưới đây là các call phổ biến nhất.

Yêu cầu tài khoản và đọc chuỗi

// Nhắc user connect ví
const accounts = await window.ethereum.request({
  method: 'eth_requestAccounts',
});
const account = accounts[0];

// Đọc chain hiện tại
const chainId = await window.ethereum.request({
  method: 'eth_chainId',
});

console.log(account, chainId); // '0x...' '0x1'
Enter fullscreen mode Exit fullscreen mode

Ví dụ gọi thô qua curl:

curl https://mainnet.infura.io/v3/YOUR_KEY \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
Enter fullscreen mode Exit fullscreen mode

Lưu ý: call chỉ-read có thể dùng node provider như Alchemy/Infura, không cần MetaMask. Xem hướng dẫn Alchemy API để biết thêm.

Ký message đơn giản

personal_sign là dạng ký phổ biến, an toàn hơn so với eth_sign.

const message = 'Đăng nhập vào Apidog vào lúc ' + new Date().toISOString();
const signature = await window.ethereum.request({
  method: 'personal_sign',
  params: [message, account],
});
Enter fullscreen mode Exit fullscreen mode

Ký dữ liệu cấu trúc (EIP-712)

Sử dụng eth_signTypedData_v4 để ký structured data.

const typedData = {
  domain: { name: 'Apidog Demo', version: '1', chainId: 1 },
  types: {
    EIP712Domain: [
      { name: 'name', type: 'string' },
      { name: 'version', type: 'string' },
      { name: 'chainId', type: 'uint256' },
    ],
    Login: [
      { name: 'wallet', type: 'address' },
      { name: 'nonce', type: 'uint256' },
    ],
  },
  primaryType: 'Login',
  message: { wallet: account, nonce: 42 },
};

const sig = await window.ethereum.request({
  method: 'eth_signTypedData_v4',
  params: [account, JSON.stringify(typedData)],
});
Enter fullscreen mode Exit fullscreen mode

Gửi transaction

MetaMask tự estimate gas và nonce.

const txHash = await window.ethereum.request({
  method: 'eth_sendTransaction',
  params: [{
    from: account,
    to: '0xRecipientAddressHere',
    value: '0x38d7ea4c68000', // 0.001 ETH (wei, hex)
  }],
});
Enter fullscreen mode Exit fullscreen mode

Chuyển đổi/Thêm chain

EIP-3326/EIP-3085 cho phép chuyển chain hoặc thêm chain mới.

// Chuyển sang Polygon (chainId 137 = 0x89)
try {
  await window.ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: '0x89' }],
  });
} catch (err) {
  if (err.code === 4902) {
    // Chain chưa được thêm
    await window.ethereum.request({
      method: 'wallet_addEthereumChain',
      params: [{
        chainId: '0x89',
        chainName: 'Polygon',
        rpcUrls: ['https://polygon-rpc.com'],
        nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
      }],
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Tích hợp React với MetaMask SDK

SDK hoạt động tốt trên React khi bạn muốn support extension, deep link mobile, hoặc in-app browser.

import { MetaMaskProvider, useSDK } from '@metamask/sdk-react';

function Connect() {
  const { sdk, connected, account } = useSDK();
  return (
    <button onClick={() => sdk?.connect()}>
      {connected ? account : 'Kết nối MetaMask'}
    </button>
  );
}

export default function App() {
  return (
    <MetaMaskProvider sdkOptions={{ dappMetadata: { name: 'dApp của tôi' } }}>
      <Connect />
    </MetaMaskProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Sản xuất nên wrap provider với ethers.js v6 hoặc viem để có contract type, decode ABI, thông báo lỗi tốt hơn. Nếu cần đăng nhập email/social fallback, có thể kết hợp MetaMask với embedded wallet, xem hướng dẫn Privy API.

Lỗi phổ biến & giới hạn tỷ lệ

MetaMask trả về mã lỗi JSON-RPC tiêu chuẩn:

  • 4001: User từ chối request. Không tự động retry.
  • 4100: Chưa ủy quyền. Gọi eth_requestAccounts trước.
  • 4200: Method không hỗ trợ. Xác nhận đúng ví MetaMask.
  • 4902: Chain chưa được thêm. Gọi wallet_addEthereumChain.
  • -32002: Request đang chờ xử lý. Debounce phía frontend.

Provider không giới hạn rate, nhưng RPC (Infura/Alchemy) có hạn mức tùy gói. Đổi sang fiat như ETH-USD, hãy xem API on/off ramp fiat.

Giá của MetaMask API

MetaMask Extension + SDK đều miễn phí, không tính phí kết nối, ký hay transaction. MetaMask thu phí qua swap và thẻ MetaMask Card, không thu từ developer.

Bạn chỉ cần trả phí cho node RPC (Infura/Alchemy). Gói free đủ cho app nhỏ; production dApp thường tốn 49–299 USD/tháng tùy thông lượng.

Kiểm tra MetaMask API với Apidog

Ký trình duyệt rất khó debug do request đi qua extension, web, và có thể cả deep-link mobile. Apidog giúp bạn test endpoint JSON-RPC thô, xác nhận eth_chainId hoặc eth_getBalance trả đúng, và lưu trữ toàn bộ flow thành test collection.

Chỉ cần import đặc tả Ethereum JSON-RPC, set URL node thành biến môi trường là bạn có collection dùng lại cho mọi EVM chain. Apidog mô phỏng response, cho phép frontend dev build trên eth_sendTransaction giả trong khi smart contract đang audit. CI có thể chạy bộ test từ CLI và fail nếu response shape đổi. Nếu bạn từng struggle với Postman collection sync, đọc hướng dẫn kiểm thử API không cần Postman 2026 để hiểu vì sao Apidog phù hợp test dApp đa giao thức.

Tải xuống Apidog để bắt đầu.

Câu hỏi thường gặp

MetaMask API có dùng trên mobile được không?

Có. Dùng MetaMask SDK để deep link sang app mobile. Provider interface y hệt extension nên code không thay đổi. Đọc thêm so sánh SDK ví mobile tại API ví tiền điện tử tốt nhất.

Phân biệt eth_sign, personal_signeth_signTypedData_v4?

eth_sign ký byte thô, nguy hiểm – MetaMask cảnh báo mạnh. personal_sign ký message có tiền tố dễ đọc. eth_signTypedData_v4 ký structured data EIP-712, hiển thị field rõ ràng cho user trên UI. Dùng hai cái sau, tránh eth_sign.

Có cần API key riêng của MetaMask không?

Không. Provider miễn phí, không cần key. Đọc dữ liệu ngoài ví thì cần RPC provider như Infura/Alchemy (có key riêng).

ethers.js hoặc viem dùng với MetaMask được không?

Được, cả hai đều wrap window.ethereum. Ethers v6 dùng BrowserProvider(window.ethereum), viem dùng createWalletClient({ transport: custom(window.ethereum) }). Production dApp nên dùng.

Nếu user cài nhiều ví thì sao?

MetaMask hỗ trợ EIP-6963 giúp dApp phát hiện toàn bộ ví đã cài thay vì tranh chấp window.ethereum. Wagmi, RainbowKit xử lý tự động.

MetaMask Snaps đã production ready chưa?

Có, đã phát hành rộng 2024. Phần lớn dùng cho non-EVM chain, custom transaction info, tích hợp ví phần cứng.

Top comments (0)