Mengintegrasikan MetaMask ke website Anda adalah langkah fundamental untuk membangun aplikasi Web3 (dApps) yang interaktif. MetaMask tidak hanya berfungsi sebagai dompet kripto, tetapi juga sebagai penyedia (provider) Web3 yang memungkinkan website Anda berinteraksi dengan jaringan blockchain (seperti Ethereum, Polygon, Binance Smart Chain, dll.) dan memicu transaksi atas nama pengguna.
Proses integrasi melibatkan penggunaan JavaScript di frontend website Anda untuk mendeteksi MetaMask, menghubungkan akun pengguna, dan kemudian menggunakan library seperti ethers.js atau web3.js untuk berinteraksi dengan blockchain.
1. Memahami Peran MetaMask sebagai Jembatan Web3
MetaMask menyuntikkan objek ethereum
(atau window.ethereum
) ke dalam browser setiap kali website dimuat. Objek ini bertindak sebagai API yang memungkinkan website Anda:
-
Mendeteksi Keberadaan MetaMask: Memeriksa apakah pengguna memiliki MetaMask yang terinstal.
-
Meminta Akses Akun: Meminta izin pengguna untuk melihat alamat dompet mereka.
-
Mengirim Transaksi: Meminta pengguna untuk menandatangani dan mengirim transaksi ke blockchain (misalnya, mengirim kripto, berinteraksi dengan smart contract).
-
Membaca Data Blockchain: Menggunakan provider yang disuntikkan MetaMask untuk membaca data dari blockchain.
2. Persiapan Awal
A. Lingkungan Pengembangan
-
HTML, CSS, JavaScript: Struktur website dasar Anda.
-
Ekstensi MetaMask: Pastikan Anda telah menginstal ekstensi MetaMask di browser Anda (misalnya Chrome, Firefox).
-
Jaringan Testnet: Untuk pengembangan dan pengujian, gunakan jaringan testnet (seperti Sepolia, Goerli). Pastikan dompet Anda memiliki sedikit testnet ETH dari faucet yang relevan.
-
Library Ethers.js atau Web3.js: Ini adalah library JavaScript yang sangat memudahkan interaksi dengan blockchain. Ethers.js lebih modern dan sering direkomendasikan.
-
Untuk Ethers.js: Tambahkan ini di tag
HTML<head>
atau sebelum script Anda diindex.html
:<script src="https://cdn.ethers.io/lib/ethers-5.7.esm.min.js"></script>
-
Untuk Web3.js:
HTML<script src="https://cdn.jsdelivr.net/npm/web3@1.7.0/dist/web3.min.js"></script
-
B. Struktur File Dasar
Buat folder proyek Anda:
my-web3-website/
├── index.html
├── style.css
└── app.js
3. Langkah-Langkah Integrasi MetaMask
Kita akan menggunakan Ethers.js sebagai contoh.
A. index.html
(Struktur HTML)
Buat file index.html
dengan elemen UI dasar:
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Integrasi MetaMask</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdn.ethers.io/lib/ethers-5.7.esm.min.js"></script>
</head>
<body>
<div class="container">
<h1>Integrasi MetaMask Sederhana</h1>
<div id="metamask-status">
<p>Status MetaMask: <span id="statusText">Tidak Terdeteksi</span></p>
<button id="connectWalletBtn">Hubungkan Dompet</button>
</div>
<div id="wallet-info" style="display: none;">
<p>Alamat Dompet: <span id="walletAddress"></span></p>
<p>Saldo ETH: <span id="ethBalance"></span> ETH</p>
<p>ID Jaringan: <span id="chainId"></span></p>
<button id="sendEthBtn">Kirim 0.001 ETH</button>
<p id="transactionStatus"></p>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
B. style.css
(CSS Dasar)
Tambahkan sedikit CSS agar tampilannya lebih rapi:
CSS
body {
font-family: sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #f4f4f4;
}
.container {
background-color: #fff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
text-align: center;
max-width: 500px;
width: 90%;
}
button {
padding: 10px 20px;
margin: 10px 5px;
border: none;
border-radius: 5px;
background-color: #007bff;
color: white;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #0056b3;
}
p span {
font-weight: bold;
}
#transactionStatus {
word-break: break-all;
margin-top: 15px;
color: green;
}
C. app.js
(Logika Integrasi)
Ini adalah bagian inti yang akan mendeteksi, menghubungkan, dan berinteraksi dengan MetaMask.
JavaScript
// Elemen DOM
const statusText = document.getElementById('statusText');
const connectWalletBtn = document.getElementById('connectWalletBtn');
const walletInfoDiv = document.getElementById('wallet-info');
const walletAddressDisplay = document.getElementById('walletAddress');
const ethBalanceDisplay = document.getElementById('ethBalance');
const chainIdDisplay = document.getElementById('chainId');
const sendEthBtn = document.getElementById('sendEthBtn');
const transactionStatusDisplay = document.getElementById('transactionStatus');
let provider; // Untuk membaca data dari blockchain
let signer; // Untuk menandatangani transaksi (menulis ke blockchain)
let currentAccount = null; // Menyimpan alamat akun yang terhubung
// --- Fungsi Utama ---
// Fungsi untuk memeriksa dan menghubungkan MetaMask
async function connectWallet() {
// 1. Periksa apakah MetaMask terinstal
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask terdeteksi!');
statusText.textContent = 'Terdeteksi';
try {
// 2. Minta akses ke akun pengguna
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
currentAccount = accounts[0]; // Ambil akun pertama
console.log('Akun terhubung:', currentAccount);
// 3. Inisialisasi Ethers.js provider dan signer
// Web3Provider menggunakan window.ethereum (MetaMask) sebagai sumber
provider = new ethers.providers.Web3Provider(window.ethereum);
signer = provider.getSigner();
// 4. Perbarui UI dan muat informasi dompet
updateUI();
await getWalletInfo();
// 5. Tambahkan event listener untuk perubahan akun/jaringan MetaMask
window.ethereum.on('accountsChanged', handleAccountsChanged);
window.ethereum.on('chainChanged', handleChainChanged);
window.ethereum.on('disconnect', handleDisconnect);
} catch (error) {
console.error('Error saat menghubungkan dompet:', error);
statusText.textContent = 'Gagal Terhubung (Izin Ditolak / Error)';
walletInfoDiv.style.display = 'none';
}
} else {
statusText.textContent = 'Tidak Terdeteksi (Silakan instal MetaMask)';
connectWalletBtn.textContent = 'Instal MetaMask';
connectWalletBtn.onclick = () => window.open('https://metamask.io/download/', '_blank');
}
}
// Fungsi untuk memperbarui informasi dompet (alamat, saldo, chain ID)
async function getWalletInfo() {
if (provider && currentAccount) {
try {
// Dapatkan saldo ETH
const balance = await provider.getBalance(currentAccount);
ethBalanceDisplay.textContent = ethers.utils.formatEther(balance); // Ubah dari wei ke ETH
// Dapatkan Chain ID
const network = await provider.getNetwork();
chainIdDisplay.textContent = `${network.chainId} (${network.name})`;
walletAddressDisplay.textContent = currentAccount;
console.log('Info Dompet Dimuat:', { balance: ethers.utils.formatEther(balance), chainId: network.chainId });
} catch (error) {
console.error('Error saat memuat info dompet:', error);
ethBalanceDisplay.textContent = 'Error';
chainIdDisplay.textContent = 'Error';
}
}
}
// Fungsi untuk mengirim transaksi ETH sederhana
async function sendEth() {
if (!signer) {
alert('Silakan hubungkan dompet terlebih dahulu.');
return;
}
const recipientAddress = '0xYourRecipientAddressHere'; // Ganti dengan alamat penerima (bisa alamat dompet Anda sendiri di testnet lain)
const amountToSend = ethers.utils.parseEther('0.001'); // Mengirim 0.001 ETH (diubah ke wei)
transactionStatusDisplay.textContent = 'Mengirim transaksi... Tunggu konfirmasi di MetaMask.';
transactionStatusDisplay.style.color = 'orange';
try {
const tx = await signer.sendTransaction({
to: recipientAddress,
value: amountToSend
});
console.log('Transaksi dikirim:', tx.hash);
transactionStatusDisplay.textContent = `Transaksi dikirim! Hash: ${tx.hash}. Menunggu konfirmasi...`;
await tx.wait(); // Tunggu hingga transaksi dikonfirmasi
console.log('Transaksi berhasil dikonfirmasi!');
transactionStatusDisplay.textContent = `Transaksi berhasil dikonfirmasi! Hash: ${tx.hash}`;
transactionStatusDisplay.style.color = 'green';
await getWalletInfo(); // Perbarui saldo setelah transaksi
} catch (error) {
console.error('Error saat mengirim ETH:', error);
transactionStatusDisplay.textContent = `Transaksi gagal: ${error.message || error.code}`;
transactionStatusDisplay.style.color = 'red';
}
}
// --- Event Handlers untuk MetaMask (Listener) ---
// Dipanggil saat akun di MetaMask berubah
function handleAccountsChanged(accounts) {
if (accounts.length === 0) {
console.log('MetaMask terputus atau tidak ada akun yang dipilih.');
currentAccount = null;
updateUI();
statusText.textContent = 'Terhubung, tapi tidak ada akun yang dipilih';
} else if (accounts[0] !== currentAccount) {
currentAccount = accounts[0];
console.log('Akun berubah ke:', currentAccount);
updateUI();
getWalletInfo();
}
}
// Dipanggil saat jaringan di MetaMask berubah
function handleChainChanged(chainId) {
console.log('Jaringan berubah ke Chain ID:', chainId);
// Disarankan untuk me-reload halaman agar aplikasi terhubung ke jaringan yang benar
// Ini membantu mengatasi potensi masalah saat mengubah jaringan secara manual
window.location.reload();
}
// Dipanggil saat MetaMask terputus dari situs (misal: dari pengaturan MetaMask)
function handleDisconnect(error) {
console.log('MetaMask terputus dari situs:', error);
currentAccount = null;
updateUI();
statusText.textContent = 'Terputus dari MetaMask';
// Anda bisa menawarkan untuk reconnect atau membersihkan state aplikasi
}
// --- Fungsi Pembantu UI ---
function updateUI() {
if (currentAccount) {
document.getElementById('metamask-status').style.display = 'none';
walletInfoDiv.style.display = 'block';
} else {
document.getElementById('metamask-status').style.display = 'block';
connectWalletBtn.textContent = 'Hubungkan Dompet'; // Reset teks jika sebelumnya berubah
connectWalletBtn.onclick = connectWallet; // Reset onclick jika sebelumnya berubah
walletInfoDiv.style.display = 'none';
}
}
// --- Event Listeners DOM ---
connectWalletBtn.addEventListener('click', connectWallet);
sendEthBtn.addEventListener('click', sendEth);
// Coba hubungkan secara pasif saat halaman dimuat (jika izin sudah diberikan sebelumnya)
// Tapi tetap berikan tombol untuk koneksi eksplisit
(async () => {
if (typeof window.ethereum !== 'undefined') {
const accounts = await window.ethereum.request({ method: 'eth_accounts' }); // Jangan request! Hanya cek
if (accounts.length > 0) {
currentAccount = accounts[0];
provider = new ethers.providers.Web3Provider(window.ethereum);
signer = provider.getSigner();
updateUI();
await getWalletInfo();
window.ethereum.on('accountsChanged', handleAccountsChanged);
window.ethereum.on('chainChanged', handleChainChanged);
window.ethereum.on('disconnect', handleDisconnect);
} else {
statusText.textContent = 'Terdeteksi, tapi belum terhubung';
updateUI(); // Pastikan UI awal benar
}
} else {
statusText.textContent = 'Tidak Terdeteksi (Silakan instal MetaMask)';
connectWalletBtn.textContent = 'Instal MetaMask';
connectWalletBtn.onclick = () => window.open('https://metamask.io/download/', '_blank');
}
})();
4. Menjalankan Website Anda
-
Simpan semua file (
index.html
,style.css
,app.js
) di foldermy-web3-website
. -
Buka file
index.html
di browser Chrome atau Firefox (dengan ekstensi MetaMask terinstal). -
Klik tombol "Hubungkan Dompet". MetaMask akan muncul dan meminta Anda untuk memilih akun dan memberikan izin.
-
Setelah terhubung, Anda akan melihat alamat dompet, saldo ETH, dan ID jaringan Anda.
-
Coba klik "Kirim 0.001 ETH" (pastikan Anda memiliki testnet ETH yang cukup). MetaMask akan meminta konfirmasi transaksi.
Bagaimana Integrasi Ini Bekerja?
-
Deteksi MetaMask: Kode pertama-tama memeriksa
window.ethereum
. Jika ada, berarti MetaMask (atau penyedia Web3 kompatibel lainnya) terinstal. -
Permintaan
eth_requestAccounts
: Ini adalah metode kunci yang memicu pop-up MetaMask agar pengguna memilih akun dan memberikan izin kepada website Anda untuk mengaksesnya. Ini menginisialisasiprovider
dansigner
dari ethers.js. -
Provider (
ethers.providers.Web3Provider(window.ethereum)
): Objek ini digunakan untuk melakukan operasi "baca" dari blockchain (misalnya,getBalance()
,getNetwork()
). -
Signer (
provider.getSigner()
): Ini adalah abstraksi dari akun pengguna yang memungkinkan Anda untuk melakukan operasi "tulis" ke blockchain yang membutuhkan tanda tangan (misalnya,sendTransaction()
, berinteraksi dengan smart contract). -
Event Listeners (
accountsChanged
,chainChanged
,disconnect
): Ini sangat penting untuk menjaga website Anda tetap sinkron dengan perubahan di MetaMask (misalnya, pengguna mengganti akun atau jaringan). Anda harus menangani event ini untuk memperbarui UI dan state aplikasi Anda.
Langkah Selanjutnya
-
Interaksi Smart Contract: Ini adalah langkah paling umum setelah menghubungkan dompet. Anda akan menggunakan
new ethers.Contract(contractAddress, contractAbi, signer)
untuk membuat instance kontrak, lalu memanggil fungsi-fungsi kontrak tersebut. -
Penanganan Kesalahan yang Robust: Implementasikan error handling yang lebih komprehensif untuk berbagai skenario (pengguna menolak transaksi, gas fee tidak cukup, dll.).
-
UI/UX: Tingkatkan pengalaman pengguna dengan memberikan feedback yang jelas (status transaksi, notifikasi, dll.).
-
Keamanan: Selalu pastikan Anda tidak pernah meminta private key pengguna. MetaMask menangani aspek keamanan dompet.
-
Penyimpanan Data Pengguna: Untuk aplikasi yang lebih kompleks, Anda mungkin perlu menyimpan subscription dompet pengguna di backend Anda untuk mengirim push notification atau melacak session.
Mengintegrasikan MetaMask adalah pintu gerbang Anda menuju pengembangan Web3. Dengan memahami konsep dasarnya, Anda dapat mulai membangun aplikasi terdesentralisasi yang kuat dan interaktif.
0 Komentar
Artikel Terkait
