Contract Address: 0x09AcB861808f014673dAED424c1ACa4a9462559E
Backend Endpoint: https://roastwager-production.up.railway.app App Front-end Endpoint: https://roast-wager.vercel.app/ Landing App Front-end Endpoint: https://landing-roast-wager.vercel.app/
RoastWager adalah aplikasi "opini + taruhan" di mana user bisa:
- membuat postingan opini (hot take),
- memilih
AgreeatauNah, - menaruh stake token (contoh: USDC),
- melihat hasil setelah market ditutup,
- klaim reward kalau menang (atau refund kalau kondisi tertentu).
Repository ini berisi 3 bagian utama:
roastwager-sc→ smart contract (aturan on-chain)roastwager-be→ backend/indexer (membaca event blockchain, simpan ke database, sediakan API)roastwager-fe→ frontend web app (UI untuk user)
Ada juga folder landing-page untuk halaman promosi terpisah.
- User membuat post dari frontend.
- Frontend kirim transaksi
createWagerke smart contract. - Smart contract emit event (contoh
WagerCreated,Voted,Resolved,Claimed). - Backend listener menangkap event dari chain Monad.
- Backend simpan/update data ke Supabase.
- Frontend membaca data dari backend API (bukan baca chain langsung untuk semua tampilan), jadi UI lebih cepat dan konsisten.
Intinya: smart contract = sumber kebenaran, backend = mesin sinkronisasi data, frontend = pengalaman pengguna.
- Buat market:
createWager(content, imageUrl) - Vote sekali per wallet per post:
vote(postId, isBull, amount) - Tutup market:
resolve(postId)oleh owner atau creator post - Klaim reward/refund:
claim(postId) - Kondisi refund otomatis:
- salah satu sisi tidak ada bettor, atau
- total pool dua sisi sama (imbang)
- REST API untuk posts, user, wagers, upload image
- Event listener on-chain dengan auto reconnect
- Sinkronisasi block terlewat (
syncMissedEvents) - Rate limit sederhana per IP
- Penyimpanan data ke Supabase
- Scoping ID berdasarkan
CONTRACT_ADDRESS(aman jika ganti kontrak) - Sistem XP/level user:
- +10 XP saat vote
- saat market resolve: pemenang +25 XP, kalah +5 XP
- Feed market aktif + pending post optimistic
- Explore (filter status, search, viral/discover)
- Profile (level, win rate, riwayat, claim all)
- Post detail
- Create post dengan optional upload image ke Pinata
- Vote via ERC-20 (approve + vote)
.
├─ roastwager-sc/ # Smart contract (Foundry)
├─ roastwager-be/ # Backend/indexer (Node + Hono + Supabase + viem)
├─ roastwager-fe/ # Frontend (Next.js + wagmi + RainbowKit)
└─ landing-page/ # Landing page terpisah (opsional)
- Node.js 20+
- npm
- Foundry (untuk build/deploy contract)
- Akun Supabase (database)
- RPC Monad Testnet
- Wallet private key deployer (jika deploy kontrak sendiri)
- (Opsional) Pinata untuk upload image
Masuk folder:
cd roastwager-scInstall dependency Foundry (jika belum):
forge install foundry-rs/forge-std --no-commitCopy env:
cp .env.example .envIsi .env minimal:
MONAD_RPC_URLPRIVATE_KEYSTABLE_TOKEN_ADDRESSMIN_VOTE_AMOUNT(raw unit token, contoh USDC 6 desimal:500000= 0.5 USDC)OWNER_ADDRESS(opsional)
Build:
forge buildDeploy:
source .env
forge script script/Deploy.s.sol:DeployRoastWager \
--rpc-url "$MONAD_RPC_URL" \
--broadcastCatat address kontrak hasil deploy. Ini akan dipakai di backend + frontend.
Masuk roastwager-be/supabase/migrations lalu jalankan SQL berikut di Supabase SQL Editor:
001_init_roastwager.sql002_scope_by_contract.sql
Tujuannya membuat tabel:
postswagersuserssync_state
Masuk folder:
cd roastwager-be
npm install
cp .env.example .envIsi .env minimal:
MONAD_RPC_URLCONTRACT_ADDRESS(hasil deploy smart contract)SUPABASE_URLSUPABASE_SERVICE_ROLE_KEYPORT(default3001)
Opsional:
SYNC_START_BLOCK(kalau mau sync dari block tertentu)STABLE_SYMBOL(defaultUSDC)STABLE_DECIMALS(default6)- Pinata credentials (
PINATA_JWTatau API key/secret) untuk upload gambar
Jalankan backend:
npm run devCek health:
curl http://localhost:3001/healthMasuk folder:
cd roastwager-fe
npm install
cp .env.example .env.localIsi .env.local minimal:
NEXT_PUBLIC_API_URL=http://localhost:3001NEXT_PUBLIC_CONTRACT_ADDRESS=<alamat kontrak>NEXT_PUBLIC_STABLE_TOKEN_ADDRESS=<alamat token stake>
Disarankan juga isi:
NEXT_PUBLIC_STABLE_SYMBOL=USDCNEXT_PUBLIC_STABLE_DECIMALS=6NEXT_PUBLIC_MIN_BET=0.5NEXT_PUBLIC_VOTE_MODE=erc20
Jalankan frontend:
npm run devBuka app di browser (biasanya http://localhost:3000).
Base URL default: http://localhost:3001
GET /healthGET /api/posts?limit=20&offset=0&status=active|settled|refundedGET /api/posts/:idGET /api/posts/:id/wagersGET /api/users/:addressGET /api/users/:address/wagersGET /api/users/:address/unclaimedGET /api/wagers/:postId/:addressPOST /api/uploads/pinata
Catatan penting:
- Untuk
status=active, backend menyembunyikan pool/count detail (blind market behavior).
- Connect wallet di frontend.
- Buat post (opsional upload gambar).
- Pilih
AgreeatauNah, lalu konfirmasi approve + vote. - Tunggu market berakhir.
- Creator/owner resolve market.
- Jika menang/refund, klaim reward dari halaman profile.
-
Error
Missing CONTRACT_ADDRESS(backend):.envbackend belum diisi atau salah. -
Frontend error
NEXT_PUBLIC_CONTRACT_ADDRESS is not configured:.env.localfrontend belum benar. -
Data tidak muncul padahal transaksi sukses: tunggu beberapa detik sampai backend listener memproses event; cek log backend.
-
Upload image gagal: periksa env Pinata (
PINATA_JWTatauPINATA_API_KEY+PINATA_API_SECRET). -
Bet gagal karena limit: cek level user dan batas max stake di profile.
- Smart contract sudah terdeploy dan address valid.
- Backend
GET /healthmengembalikan statusok. - Frontend bisa load feed tanpa error API.
- Bisa create post, vote, lalu data muncul di feed/profile.
- Event on-chain terlihat masuk ke database Supabase.
- Proyek ini fokus ke Monad testnet flow.
landing-pagetidak wajib untuk flow utama app taruhan.