This pallet implements a basic protocol for decentralized betting.
Every account can create a match where rest of the users can bet. To create a match it is needed to place a deposit that will be returned after distribute the prizes.
The number of bets a user can create now are limited to 1.
Everyone can bet in the match, for a basic result: victory team 1, draw or victory team 2.
When the match is over a user with SUDO priviliges can set the result of the match.
RuntimeEvent
– The overarching event type.Currency
– The currency type.WeightInfo
– Information on runtime weights.
PalletId
– Pallet ID. Used for account derivation.MaxTeamNameLength
– Maximum length for team names.MatchDeposit
- Deposite needed to create a matchMaxBetsPerMatch
– Maximum number of bets per match.
Creates a match to bet on. This function must be dispatched by a signed extrinsic.
Emit an event on success: MatchCreated
.
origin
– Origin for the call. Must be signed.team1
– Name of the first team.team2
– Name of the second team.start
– Time when the match starts and a bet can not be placed (in blocks).lenght
– Duration of the match (in blocks).
MatchAlreadyExists
– A match for the specified values already exists.OriginHasAlreadyOpenMatch
– An origin can only have one match open.TimeMatchOver
– The match is created when the match time is over.
Create bet for a match.
Emit an event on success: BetPlaced
.
origin
– Origin for the call. Must be signed.match_id
– Id of the match, in our case the creator of the bet accountId.amount_to_bet
– Amount placed for the bet.result
– The result for the bet.
MatchDoesNotExist
– A match selected for the bet doesn't exist.OriginHasAlreadyOpenMatch
– If the match has started, betting is not allowed.TimeMatchOver
– The match is created when the match time is over.MaxBets
– The match has reach its betting limit.AlreadyBet
– You already place the same bet in that match.
Notify the result of an existing match.
The dispatch origin for this call must be Root.
Emit an event on success: MatchResult
.
origin
– Origin for the call. Must be signed.match_id
– Id of the match, in our case the creator of the bet accountId.result
– The result of the match.
MatchDoesNotExist
– A match selected for the bet doesn't exist.TimeMatchNotOver
– If the match is not over, set the result is not allowed.
When a match ends someone the owner of the match can distribute the money from the winers and delete the match. Distribute winnings: take all the prizes on the pot and distribute the prizes evenly.
Example:
Person A bets 10 UNITS on team1.
Person B bets 10 UNITS on team2.
Person C bets 30 UNITS on team1.
The total Pot is 50 UNITS.
If team1 is the winner, with weighted distribution the person A have to receive the 25% of the pot and the person C the 75%. The maths for this weighted distribution are simple: the amount that one deposit / the total amount of the winners deposit in the case of Person A = 10/40 = 0.25
origin
– Origin for the call. Must be signed.
MatchDoesNotExist
– A match selected for the bet doesn't exist.MatchNotResult
– The match still has not a result.
Get a match stored.
match_id
– ID of the match to retrieve (accountId of the creator).
ℹ️ The pallet is compatible with Substrate version polkadot-v0.9.35.
ℹ️ This section is based on
Substrate node template.
Integrating pallet-betting
with another node might look slightly different.
Add pallet-betting
, and the RPC runtime API, to dependencies.
[dependencies.pallet-betting]
version = "0.0.3"
default-features = false
git = "https://github.com/AlexD10S/substrate-betting.git"
branch = "main"
[dependencies.pallet-betting-rpc-runtime-api]
version = "0.0.1"
default-features = false
git = "https://github.com/AlexD10S/substrate-betting.git"
branch = "main"
Update the runtime's std
feature:
std = [
# --snip--
"pallet-betting/std",
"pallet-betting-rpc-runtime-api/std",
# --snip--
]
Add pallet-betting-rpc
to dependencies.
[dependencies.pallet-betting-rpc]
version = "0.0.1"
default-features = false
git = "https://github.com/AlexD10S/substrate-betting.git"
branch = "main"
Configure the betting pallet.
parameter_types! {
pub const MatchDeposit: u64 = 10;
pub const BettingPalletId: PalletId = PalletId(*b"py/betts");
}
impl pallet_betting::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type PalletId = BettingPalletId;
type Currency = Balances;
type MaxTeamNameLength = ConstU32<64>;
type MaxBetsPerMatch = ConstU32<10>;
type MatchDeposit = MatchDeposit;
type WeightInfo = pallet_betting::weights::SubstrateWeight<Runtime>;
}
Add configured pallets to the construct_runtime
macro call.
construct_runtime!(
pub enum Runtime where
// --snip--
{
// --snip---
Betting: pallet_betting,
// --snip---
}
);
Add the RPC implementation.
pub type TeamName = BoundedVec<u8, ConstU32<64>>;
pub type Bet = pallet_betting::Bet<AccountId, pallet_betting::MatchResult, Balance>;
pub type Match = pallet_betting::Match<BlockNumber, TeamName, BoundedVec<Bet, ConstU32<10>>, Balance>;
impl_runtime_apis! {
impl pallet_betting_rpc_runtime_api::BettingApi<Block, AccountId, Match> for Runtime {
fn get_match(match_id: AccountId) -> pallet_betting_rpc_runtime_api::RpcResult<Match>
{
Betting::get_match(match_id)
}
}
Instantiate the RPC extension and merge it into the RPC module.
pub fn create_full<C, P>(
deps: FullDeps<C, P>,
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
where
// --snip--
C::Api: pallet_betting_rpc::BettingRuntimeApi<Block, Balance>,
{
use pallet_betting_rpc::{Betting, BettingApiServer};
// --snip--
module.merge(Betting::new(client).into_rpc())?;
Ok(module)
}