Belajar Web3 - Events & Real-time UI
Series/Belajar Web3/Episode 12
Episode 12 of 23

Belajar Web3 - Events & Real-time UI

Membuat UI DApp real-time: useWatchContractEvent untuk mendengarkan event seperti Transfer, perbandingan poll dan subscription, refresh saldo setelah transaksi, serta optimistic updates agar antarmuka terasa instan

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 11 kalian bisa read dan write, pada episode ini kita membuat UI merespons perubahan on-chain secara real-time. DApp yang bagus tidak menunggu user menekan refresh — ia tahu ketika transaksi selesai, ketika saldo berubah, atau ketika ada transfer masuk.

Mengapa episode ini penting? Karena data on-chain terus bergerak: harga, saldo, dan state kontrak berubah di luar kontrol user. Memahami event dan subscription membuat kalian membangun UI yang "hidup" alih-alih snapshot statis.

Event: Bahasa Perubahan On-chain

Ketika kontrak memancarkan event (misalnya Transfer saat token berpindah), blockchain menyimpan log tersebut. Frontend bisa membaca log ini dengan dua strategi:

StrategiCara kerjaCocok untuk
PollingQuery berkala (setiap N detik)Data sederhana, jumlah query kecil
SubscriptionListen real-time via websocketEvent aktif, UX real-time
100%

useWatchContractEvent

Hook ini mendengarkan event dari kontrak. Contoh memantau transfer masuk ke address user:

src/components/TransferWatcher.tsx
import { useWatchContractEvent, useAccount } from "wagmi"
import { erc20Abi } from "viem"
import { TOKEN_ADDRESSES } from "../contracts"
 
export function TransferWatcher() {
  const { address } = useAccount()
 
  useWatchContractEvent({
    address: TOKEN_ADDRESSES[1],
    abi: erc20Abi,
    eventName: "Transfer",
    args: { to: address },
    onLogs(logs) {
      console.log("Transfer masuk:", logs)
    },
  })
 
  return <p>Memantau transfer masuk...</p>
}

Poin penting:

  • args memfilter event — di sini hanya Transfer dengan to = address user.
  • onLogs dipanggil setiap blok yang mengandung event yang cocok.
  • Subscription butuh RPC websocket; dengan http() wagmi akan otomatis fallback ke polling.

Perbedaan dengan Event Log di ABI

Untuk memfilter event dengan benar, pastikan ABI mencantumkan deklarasi indexed parameter yang difilter. Contoh pada ABI ERC-20: parameter from dan to bersifat indexed, sehingga bisa dipakai sebagai filter; value tidak. Filter non-indexed tidak bisa dilakukan — ini batas protokol, bukan bug wagmi.

Refresh Balances Setelah Transaksi

Saldo yang ditampilkan harus segar. Dua pendekatan yang sering digabung:

Refresh setelah transaksi konfirmasi
const { refetch: refetchBalance } = useReadContract({
  address: TOKEN_ADDRESSES[1],
  abi: erc20Abi,
  functionName: "balanceOf",
  args: [address],
})
 
const { isConfirmed } = useWaitForTransactionReceipt({ hash })
 
useEffect(() => {
  if (isConfirmed) refetchBalance()
}, [isConfirmed, refetchBalance])

Selain refetch manual, react-query mengelola cache: panggil invalidateQueries agar query dengan key yang sama dibaca ulang otomatis. Ini pola yang lebih scalable untuk banyak data on-chain.

Optimistic Updates

Optimistic update = UI langsung menampilkan hasil seolah transaksi sudah sukses, lalu "memutar balik" jika ternyata gagal. Efeknya: tombol terasa instan, bukan menunggu blok.

Contoh konsep optimistic update
// Asumsi: saldo lama 100
setBalance(prev => prev - amount) // langsung tampil 100 - amount
// lalu saat receipt gagal / revert:
setBalance(prev => prev + amount) // kembalikan

Kapan memakai:

  • Ya untuk transaksi yang hampir pasti sukses (misalnya optimis di UI internal).
  • Tidak untuk transaksi yang bisa gagal mahal (misalnya swap dengan slippage) — tampilkan status nyata.

Pola umum di produksi: tampilkan state "pending" dengan data optimis, lalu sinkronkan dengan data on-chain begitu receipt terkonfirmasi — dan rollback jika error.

Tip

Kombinasi terbaik untuk UI real-time: event untuk trigger (ada yang berubah), invalidateQueries untuk refresh cache, dan optimistic update untuk ilusi kecepatan. Jangan pakai polling 1 detik untuk semuanya — itu membebani RPC dan tidak lebih baik daripada event.

Ringkasan Konsep

Rangkuman yang sudah kalian pelajari di episode 12:

  • Event adalah log on-chain; polling dan subscription adalah dua cara membaca perubahan.
  • useWatchContractEvent + filter args untuk mendengarkan event spesifik.
  • Refresh state dengan refetch atau invalidateQueries setelah transaksi konfirmasi.
  • Optimistic update membuat UI cepat, tetapi harus punya mekanisme rollback.

Penutup

Inti yang harus dibawa pulang:

  • UI real-time = event sebagai trigger + cache refresh sebagai sumber kebenaran.
  • Subscription butuh websocket; polling adalah fallback aman.
  • Optimistic update adalah gula — pastikan rollback-nya solid.

Di episode 13 selanjutnya, kita membahas storage: IPFS, Arweave, dan Filecoin — konsep CID dan pinning, metadata NFT di IPFS lewat Pinata, perbedaan permanen vs berbayar, serta strategi kapan data on-chain dan kapan off-chain. Sampai jumpa di episode 13!