Agent Integration
Build bots and automated agents that interact with AvaloBet games on Avalanche C-Chain.
Overview
AvaloBet V3 contracts are fully on-chain and permissionless. Any wallet — including automated agents, bots, and scripts — can interact with game contracts directly via standard EVM transactions.
What agents can do:
- Place bets on any game type (roulette, slots, crash, plinko, mines, dice, wheel, coinflip)
- Provide liquidity / stake into game pools
- Monitor bet events and pool state in real-time
- Automate commit-reveal flow for provably fair betting
- Claim staking rewards programmatically
Requirements
- Avalanche C-Chain (chain ID 43114)
- AVAX for gas fees
- ERC-20 token matching the game's pool token
- ethers.js v6, viem, or any EVM-compatible library
Quick Start
Get a bot placing bets in under 5 minutes:
import { ethers } from "ethers";
// 1. Connect to Avalanche
const provider = new ethers.JsonRpcProvider("https://api.avax.network/ext/bc/C/rpc");
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
// 2. Game contract (e.g. Coinflip)
const GAME_ABI = [
"function commitBet(uint256 betAmount, bytes32 commitHash, bool isHeads) external",
"function revealBet(uint256 nonce) external",
"function minBet() view returns (uint256)",
"function maxBet() view returns (uint256)",
"function poolBalance() view returns (uint256)",
];
const game = new ethers.Contract(GAME_ADDRESS, GAME_ABI, wallet);
// 3. Approve token spend
const token = new ethers.Contract(TOKEN_ADDRESS, [
"function approve(address,uint256) external",
"function balanceOf(address) view returns (uint256)",
], wallet);
await token.approve(GAME_ADDRESS, ethers.MaxUint256);
// 4. Generate commit
const nonce = ethers.toBigInt(ethers.randomBytes(32));
const commitHash = ethers.keccak256(
ethers.AbiCoder.defaultAbiCoder().encode(["uint256"], [nonce])
);
// 5. Commit bet (Heads, 1 token)
const betAmount = ethers.parseUnits("1", 18);
await game.commitBet(betAmount, commitHash, true);
// 6. Wait 1 block, then reveal
const currentBlock = await provider.getBlockNumber();
while ((await provider.getBlockNumber()) <= currentBlock) {
await new Promise(r => setTimeout(r, 2000));
}
const tx = await game.revealBet(nonce);
const receipt = await tx.wait();
console.log("Bet resolved!", receipt.hash);Commit-Reveal Flow
All AvaloBet games use a 2-step commit-reveal pattern for provably fair randomness:
Generate a random nonce, hash it (keccak256), and send the hash + bet params to commitBet().
Wait at least 1 block. The next block's hash will be used as part of the random seed.
Call revealBet(nonce) to reveal your original nonce. The contract combines it with the blockhash to determine the outcome.
// Commit hash generation
const nonce = ethers.toBigInt(ethers.randomBytes(32));
const commitHash = ethers.keccak256(
ethers.AbiCoder.defaultAbiCoder().encode(["uint256"], [nonce])
);
// IMPORTANT: Store the nonce — you need it for reveal!
// The blockhash is auto-cached, so there's no 256-block expiry.Game Types
Roulette
commitBet(uint256 betAmount, bytes32 commitHash, uint8[] betTypes, uint256[] betAmounts)13 bet types (straight, split, street, corner, line, column, dozen, red/black, odd/even, high/low, green). Multi-bet up to 10× at once.
Slots
commitBet(uint256 betAmount, bytes32 commitHash)3-reel, 10 symbols. Payouts from 2x to 100x jackpot. Simple commit with a single bet amount.
Crash
commitBet(uint256 betAmount, bytes32 commitHash)Multiplier increases from 1.00x. Call cashOut() before it crashes. Reveal determines the crash point.
Plinko
commitBet(uint256 betAmount, bytes32 commitHash, uint8 riskLevel)riskLevel: 0=Low, 1=Medium, 2=High. Ball drops through a Plinko board.
Mines
commitBet(uint256 betAmount, bytes32 commitHash, uint8 mineCount)mineCount: 1-24 mines in a 5×5 grid. Call revealTile(index) to uncover tiles, cashOut() to take winnings.
Range (Dice)
commitBet(uint256 betAmount, bytes32 commitHash, uint256 targetNumber, bool isOver)Predict if the random number (0-99) is over or under your target. Lower probability = higher payout.
Wheel
commitBet(uint256 betAmount, bytes32 commitHash, uint8 segmentCount)Spin wheel with variable segments. segmentCount determines risk/reward multipliers.
Coinflip
commitBet(uint256 betAmount, bytes32 commitHash, bool isHeads)Simple heads/tails. Nearly 2x payout (minus fees).
SDK Reference
Import the SDK for TypeScript types and ABI fragments:
import {
GAME_ABI_FRAGMENTS,
FACTORY_ABI_FRAGMENTS,
COINFLIP_ABI_EXTRAS,
DICE_ABI_EXTRAS,
MINES_ABI_EXTRAS,
CRASH_ABI_EXTRAS,
PLINKO_ABI_EXTRAS,
ROULETTE_ABI_EXTRAS,
WHEEL_ABI_EXTRAS,
SLOT_ABI_EXTRAS,
AVALANCHE_CONFIG,
} from "@/lib/agent-sdk";
// Types available:
// BetResult, PlayerStats, GameInfoCommon ABI Functions (all games)
| Function | Description |
|---|---|
| poolBalance() | Current pool balance (total liquidity) |
| totalStaked() | Total staked tokens |
| minBet() / maxBet() | Bet limits for the game |
| getRecentBets(count) | Last N bet results |
| getPlayerStats(address) | Player's total bets, wagered, won |
| addLiquidity(amount) | Stake tokens into the pool |
| removeLiquidity(shares) | Withdraw from the pool |
| claimRewards() | Claim accumulated staking rewards |
Events & Monitoring
Listen to contract events for real-time monitoring:
// Listen for all bets on a game
game.on("BetRevealed", (player, payout, won) => {
console.log(`${player} ${won ? "won" : "lost"} ${ethers.formatUnits(payout, 18)} tokens`);
});
// Listen for liquidity changes
game.on("LiquidityAdded", (provider, amount) => {
console.log(`${provider} added ${ethers.formatUnits(amount, 18)} liquidity`);
});
// Get past events
const filter = game.filters.BetRevealed(YOUR_ADDRESS);
const events = await game.queryFilter(filter, -1000); // last 1000 blocksAvailable Events
- BetCommitted(address indexed player, bytes32 commitHash)
- BetRevealed(address indexed player, uint256 payout, bool won)
- LiquidityAdded(address indexed provider, uint256 amount)
- LiquidityRemoved(address indexed provider, uint256 amount)
Examples
Auto-Staking Bot
// Automatically stake into pools when balance exceeds threshold
async function autoStake(gameAddress: string, tokenAddress: string, threshold: bigint) {
const game = new ethers.Contract(gameAddress, GAME_ABI_FRAGMENTS, wallet);
const token = new ethers.Contract(tokenAddress, ["function balanceOf(address) view returns (uint256)"], wallet);
const balance = await token.balanceOf(wallet.address);
if (balance > threshold) {
const stakeAmount = balance - threshold;
await token.approve(gameAddress, stakeAmount);
await game.addLiquidity(stakeAmount);
console.log(`Staked ${ethers.formatUnits(stakeAmount, 18)} tokens`);
}
}Multi-Game Scanner
// Scan all games from a factory to find the best pool
const FACTORY_ABI = [
"function gameCount() view returns (uint256)",
"function allGames(uint256) view returns (address)",
];
const factory = new ethers.Contract(FACTORY_ADDRESS, FACTORY_ABI, provider);
const count = await factory.gameCount();
for (let i = 0; i < count; i++) {
const addr = await factory.allGames(i);
const game = new ethers.Contract(addr, GAME_ABI_FRAGMENTS, provider);
const pool = await game.poolBalance();
console.log(`Game ${addr}: pool = ${ethers.formatUnits(pool, 18)}`);
}Batch Bet Loop (Coinflip)
async function batchBet(game: ethers.Contract, count: number, betAmount: bigint) {
for (let i = 0; i < count; i++) {
const nonce = ethers.toBigInt(ethers.randomBytes(32));
const commitHash = ethers.keccak256(
ethers.AbiCoder.defaultAbiCoder().encode(["uint256"], [nonce])
);
// Commit (isHeads = true)
await game.commitBet(betAmount, commitHash, true);
// Wait 1 block
const block = await game.runner?.provider?.getBlockNumber();
while (true) {
const cur = await game.runner?.provider?.getBlockNumber();
if (cur && cur > block!) break;
await new Promise(r => setTimeout(r, 2000));
}
// Reveal
const tx = await game.revealBet(nonce);
const receipt = await tx.wait();
console.log(`Bet ${i + 1}/${count} done: ${receipt.hash}`);
}
}