This contract represents a Tezos contract written in JsLIGO in which users can bet on events added by the Admin or an Oracle.
The current implementation of the contract is as follows :
- a
Betting
contract, the main contract - (optional) a
mock Oracle
contract - (optional) a
callback
contract for theBetting
- (optional) a
callback
contract for themock Oracle
type storage = {
manager: address,
oracle_address: address,
bet_config: bet_config_type,
events: map<nat, event_type>,
events_bets: map<nat, event_bets>,
events_index: nat,
metadata: map<string, bytes>
}
manager
: Manager account of the Betting contractoracle_address
: Oracle contract allowed to add Events and update themevents
,events_bets
,events_index
: Events mapped to their info, their attached bets, and the latest index
type bet_config_type = {
is_betting_paused: bool,
is_event_creation_paused: bool,
min_bet_amount: tez,
retained_profit_quota: nat
}
is_betting_paused
: is Betting on Events paused (true), or is it allowed (false)is_event_creation_paused
: is the creation of new Events paused (true), or is it allowed (false)min_bet_amount
: the minimum amount to Bet on an Event in a single transactionretainedProfit
: the quota to be retained from Betting profits (deduced as operating gains to the contract, shown as percentage, theorical max is 100)
- Deploy the Betting contract with an initial storage
- The
storage.bet_config.is_betting_paused
andstorage.bet_config.is_event_creation_paused
must have as valuefalse
- Add an Event using the
storage.manager
address - Add a Bet to the Event using an address that is not
storage.manager
norstorage.oracle_address
- (optional) Add more bets to the first team or second team on the Event
- Update the Bet to specify the outcome in
is_draw
, and the winning Team inis_team_one_win
if it is not a draw, usingstorage.manager
orstorage.oracle_address
- Finalize the Bet using
storage.manager
let init_bet_config : bet_config_type = {
is_betting_paused: false,
is_event_creation_paused: false,
min_bet_amount: 5 as tez,
retained_profit_quota: 10 as nat
};
let init_storage : storage = {
manager: "tz1******************",
oracle_address: "KT1******************",
bet_config: init_bet_config,
events: (Map.empty as map<nat, event_type>),
events_bets: (Map.empty as map<nat, event_bets>),
events_index: 0 as nat,
metadata: (Map.empty as map<string, bytes>)
};
- To compile the Betting contract to Michelson code :
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile contract src/contracts/jsligo/betting/main.jsligo > src/compiled/betting.tz
- To compile the Betting contract to Michelson code in JSON format :
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile contract src/contracts/jsligo/betting/main.jsligo --michelson-format json > src/compiled/betting.json
- Using
tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT
as example forstorage.manager
- Using
KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi
as example forstorage.oracle_address
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile storage ./contracts/jsligo/betting/main.jsligo '{manager: ("tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" as address), oracle_address: ("KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi" as address), bet_config: {is_betting_paused: false, is_event_creation_paused: false, min_bet_amount: 5 as tez, retained_profit_quota: 10 as nat}, events: (Map.empty as map<nat, TYPES.event_type>), events_bets: (Map.empty as map<nat, TYPES.event_bets>), events_index: 0 as nat, metadata: (Map.empty as map<string, bytes>)}' -e main
- For entrypoint SendValue
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable run dry-run src/contracts/jsligo/betting/main.jsligo 'SendValue()' '37' -e main
- Compile the storage into Michelson expression :
- Using
tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT
as example forstorage.manager
- Using
KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi
as example forstorage.oracle_address
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile storage ./contracts/jsligo/betting/main.jsligo '{manager: ("tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" as address), oracle_address: ("KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi" as address), bet_config: {is_betting_paused: false, is_event_creation_paused: false, min_bet_amount: 5 as tez, retained_profit_quota: 10 as nat}, events: (Map.empty as map<nat, TYPES.event_type>), events_bets: (Map.empty as map<nat, TYPES.event_bets>), events_index: 0 as nat; metadata: (Map.empty as map<string, bytes>)}' -e main
- This command produces the following Michelson storage :
(Pair (Pair (Pair (Pair (Pair False False) 5000000 10) {}) {} 0)
(Pair "tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" {})
"KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi")
- Deploy with tezos-client CLI using the above Michelson code :
tezos-client originate contract betting transferring 1 from '$USER_ADDRESS' running 'src/compiled/betting.tz' --init '(Pair (Pair (Pair (Pair (Pair False False) 5000000 10) {}) {} 0)(Pair "tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" {})"KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi")'
type storage = {
isPaused: bool,
manager: address,
signer: address,
events: map<nat, event_type>,
events_index: nat,
metadata: map<string, bytes>
}
isPaused
: If the creation of events on the contract is pausedmanager
: Manager account of the Betting contractsigner
: Signer contract allowed to add Events and update them (usually a backend script)events
,events_index
: Events mapped to their info and the latest index
type event_type =
// @layout:comb
{
name: string,
videogame: string,
begin_at: timestamp,
end_at: timestamp,
modified_at: timestamp,
opponents: { team_one: string, team_two: string},
game_status: game_status
}
The following entrypoints are available :
- ChangeManager
- ChangeSigner
- SwitchPause
- AddEvent
- GetEvent
- UpdateEvent
For full details, please consult the Oracle contracts in src/contracts/jsligo/oracle
let store : storage = {
isPaused: False,
manager: "tz1******************",
signer: "tz1******************",
events: (Map.empty as map<nat, event_type>),
events_index: 0 as nat
}
It is possible to use an external API to collect sample game data about eSports titles such as CS:GO, DOTA 2, and others.
Some sample requests to get data from a third-party API can be found in the Backend folder. We are using here the API provider : Pandascore.
The API access tokens can be requested by creating an account on Pandascore here
The API reference documentation can be viewed here
The scripts can be executed as follows :
node backend/matches_past.js
node backend/matches_running.js
node backend/matches_upcoming.js
The result of the queries will be a JSON file in the Backend folder, which will contain game info.
It is possible to inject this data to the Oracle after formatting manually, or automatically using a signer/broadcaster.