Skip to main content

Bet blueprint — interface

Introduction

This article is the interface reference for the blueprint Bet. It requires the prior reading of Bet contract: how it works.

warning

Currently, this blueprint is available for testing purposes only. It was conceived to demonstrate how blueprints function and provide insight into the design, implementation, and documentation processes for future blueprints.

tip

Every nano contract provides its blueprint's interface, which specifies how to create, execute, and read it. This interface is wrapped by the API used to integrate a given client with Hathor Network.

In practice, this means that to interact with a contract, the developer should use their client's integration API (whether it is a DApp or any other system) for the generic part of the request, and the specific interface of that contract's blueprint to know which methods to call, how to call them, and which attributes and balances can be read.

Index

Blueprint Bet and its instantiated contracts provide the following JSON interface:

State:Methods:

Attributes

token_uid

  • Description: a token UID that defines the token the contract works with — i.e., the token used to place bets and to pay out winning bettors. A bet contract works with one and only one token. This token can be any fungible token registered in Hathor blockchain (either a custom token or 'HTR'). It is set once by initialize and does not change anymore.
  • Type: string
  • Possible values: 00 for 'HTR' or any 32-byte hexadecimal (e.g., 00000000059dfb65633acacc402c881b128cc7f5c04b6cea537ea2136f1b97fb)

date_last_bet

  • Description: a UNIX epoch timestamp that defines the date and time limit for bettors to place bets. Beyond this limit, the contract does not accept bets anymore. Usually, this limit relates to the date and time when the betting event occurs. A bet contract works with one and only one date and time limit. It is set once by initialize and does not change anymore.
  • Type: number
  • Possible values: integer timestamps following the Unix epoch timestamp standard, meaning they denote the time in seconds elapsed since January 1st, 1970 00:00:00 UTC. For example, the timestamp for July 11, 2024, at noon UTC is 1720699200.

oracle_script

  • Description: a lock script that defines the contract oracle — i.e., the script the oracle must resolve to provide the outcome of the bet event. A bet contract has one and only one oracle. It is set once by initialize and does not change anymore.
  • Type: string
  • Possible values: byte streams as hexadecimal encoding scripts — e.g., 76a9141ed32ccd0d28acea3afcf4798e2d4db21401edef88ac.

final_result

  • Description: keeps the result of the betting event. A bet contract works with one and only one event result. It is set once by the oracle, after the ocurrence of the event, and does not change anymore.
  • Type: string
  • Possible values: bettors should be informed of the format in which the oracle will set the result. This can be a finite set of possible outcomes — e.g., ["Barcelona", "Real-Madrid"] — or a regular expression for infinite possible outcomes — e.g., "^Barcelona(\\d+)x(\\d+)Real-Madrid$".

total

  • Description: keeps the 'handle' of the bet contract — i.e., the total amount of tokens wagered by all bettors. It increases as bettors place bets, until date_last_bet is reached. After that, since there will be no new bets, it won't change anymore.
  • Type: number
  • Possible values: any non-negative integer

bets_total

  • Description: tracks the total amount wagered for each result within the universe of possible outcomes that bets were placed. For example, suppose a betting event with only three possible results: (1) victory for Real Madrid, (2) victory for Barcelona, or (3) a draw. And suppose 2 bettors wagered a total of 20 tokens on Real Madrid's victory, 3 bettors wagered 100 tokens on Barcelona's victory, and no bets were placed on a draw. In this case, bets_total would keep the following name/value pairs:

    "bets_total": {
    "Real-Madrid": 20,
    "Barcelona": 100
    }
  • Type: object

  • Possible values: the entire object cannot be read at once. State reading should be done by name/value — i.e., a name is provided, and its corresponding value is returned. To read how much was bet on a specific result, use the name "bets_total.<result>", replacing <result> with the desired result. For example, querying "bets_total.Real-Madrid" would return:

    "bets_total.Real-Madrid": {
    "value": 20
    }

address_details

  • Description: tracks the total amount each bettor (represented by an address) wagered on each result. For example, suppose Alice placed several bets on three different results for an event. The sum of her bets consolidates as follows:

    • Real Madrid 2 x 2 Barcelona: 20 tokens
    • Real Madrid 1 x 0 Barcelona: 100 tokens
    • Real Madrid 0 x 2 Barcelona: 50 tokens

    This information will be stored for each bettor (i.e., address). In this case, supposing Alice is address WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq, address_details would keep the following name/value pairs:

    "address_details": {
    "WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq": {
    "Real-Madrid2x2Barcelona": 20,
    "Real-Madrid1x0Barcelona": 100,
    "Real-Madrid0x2Barcelona": 50
    },
    "<address_bob>": {
    "Real-Madrid0x0Barcelona": 60
    },
    "<address_charlie>": {
    "Real-Madrid2x3Barcelona": 50
    }
    ...
    }
  • Type: object

  • Possible values: the entire object cannot be read at once. State reading should be done by name/value — i.e., a name is provided, and its corresponding value is returned. To read how much a bettor wagered in each result, use the name "address_details.a'<address>'", replacing <address> with the bettor's address. For example, querying "address_details.a'WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq'" would return:

    "address_details.a'WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq'": {
    "value": {
    "Real-Madrid2x2Barcelona": 20,
    "Real-Madrid1x0Barcelona": 100,
    "Real-Madrid0x2Barcelona": 50
    }
    }

withdrawals

  • Description: tracks how much each winning bettor has already withdrawn from their winnings. For example, suppose Alice correctly predicted the result and won 1000 tokens. She has already withdrawn 400 tokens and decided to leave the remaining balance for a future withdrawal. This information will be stored for each bettor (i.e., address). In this case, assuming Alice is address WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq, withdrawals would keep the following name/value pair:

    "withdrawals": {
    "WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq": 400,
    "<winning_bettor_nr2>": 1000,
    "<winning_bettor_nr3>": 800,
    ...
    }
  • Type: object

  • Possible values: the entire object cannot be read at once. State reading should be done by name/value — i.e., a name is provided, and its corresponding value is returned. To read how much a bettor wagered in each result, use the name "withdrawals.a'<address>'", replacing <address> with the bettor's address. For example, querying "withdrawals.a'WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq'" would return:

    "withdrawals.a'WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq'": {
    "value": 400
    }

Balances

Holds balance of one and only one fungible token as specified by attribute token_uid. For example, suppose token_uid is 00000000059dfb65633acacc402c881b128cc7f5c04b6cea537ea2136f1b97fb. In this case:

"balances": {
"00000000059dfb65633acacc402c881b128cc7f5c04b6cea537ea2136f1b97fb": 2000
}

Public methods

initialize

  • Description: used by bookmaker to create new bet contract. If method call succeeds, a new contract is registered on Hathor blockchain.
  • Parameters: requires exactly three positional parameters represented by tuple validation [oracle_script, token_uid, date_last_bet] where:
  • Actions: requires exactly zero actions.
  • Common errors:
    • NCFail: "must be a single call": contract creator sent more than zero actions.

bet

  • Description: used by bettors to place a bet. If method call succeeds, a new bet is placed on contract. For example: bettor A (identified by address), bet x amount of tokens X (deposit made in the contract), that the event result will be score.
  • Parameters: requires exactly two positional parameters represented by tuple validation [address, score] where:
    • address:
      • Description: identifies the bettor. Two different addresses are considered two different bettors. Anyone can place bets on behalf of a given address.
      • Type: string
      • Possible values: 25 bytes in base58check
    • score:
      • Description: describes the outcome the bettor is betting on for the event.
      • Type: string
      • Possible values: any string is considered valid by the contract, but only strings that perfectly match final_result will be considered correct bets — i.e., winning bets. Thus, bettors should follow guidances from bookmaker and oracle regarding formatting score strings.
    • Example:
      "args": [
      "WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq",
      "Real-Madrid0x0Barcelona"
      ]
  • Actions: requires exactly one and only one deposit action of the token specified by attribute token_uid. Example:
    "actions": [
    {
    "type": "deposit",
    "token": "00",
    "amount": 1000
    }
    ],
  • Common errors:
    • TooManyActions: "only one action supported": bettor sent more than one single action.
    • WithdrawalNotAllowed: "must be a deposit": bettor sent a withdrawal action.
    • ResultAlreadySet: bettor attempted to place bet after oracle send result.
    • InvalidToken: "token different from <token_uid>": bettor attempted to place bet with a token different than specified by token_uid.
    • TooLate: "cannot place bets after <date_last_bet>": bettor attempted to place a bet after date_last_bet.

set_result

  • Description: used one single time by the oracle, to set the result of the betting event in attribute final_result. This method call will succeed only if oracle provides an unlock script within signedResult that satisfies the lock script specified by attribute oracle_script. Otherwise, it fails. If this method call succeeds, final_result is set and does not change anymore.

  • Parameters: requires exactly one parameter, as follows:

    • signedResult:

      • Description: result of the event signed by oracle.
      • Type: string
      • Possible values: string have format <unlock_script>,<result>,<type_result>, where: (i) <unlock_script> script that contains the signature of the result and satisfies contract attribute oracle_script; (ii) <result> is the outcome of the event; (iii) <type_result> is the Python type of the result (e.g., str, int, etc.).
    • Example: suppose oracle wants to send the result "Real Madrid 3 x 1 Barcelona" to the contract:

      "args": [
      "4630440220397d62202a93863ea1918e44e6fc9135bdcb495b4743fbbe66dd99ac2a8b83a902204ba0d6b5b73111f1936bfcd7f11c5a1e7a0aa06fcb13ba9db084cb21e3cb1b3121022e7b7a71a9c252f415ec3e80888cc722b0db083662380ecc43ddb6e489bf4b8a,Real-Madrid3x1Barcelona,str"
      ]
  • Actions: requires exactly zero actions.

  • Common errors:

    • ResultAlreadySet: oracle attempted to set result for the second time.
    • InvalidOracleSignature: result is not properly signed.

withdraw

  • Description: used by winning bettors to cash out their winnings. A bettor can withdraw any fraction of their winnings and send it to any address; the withdrawal does not have to be made to the address that identifies them in the contract. If this method call succeeds, the winning bettor receives a payout and the contract updates how much of their winnings can still be withdrawn.
  • Parameters: requires exactly zero parameters.
  • Actions: requires exactly one and only one withdrawal action of the token specified by attribute token_uid. Example:
    "actions": [
    {
    "type": "withdrawal",
    "token": "00",
    "amount": 1000
    }
    ],
  • Common errors:
    • TooManyActions: "only one action supported": bettor sent more than one single action.
    • InvalidToken: "token different from <token_uid>": bettor attempted to place bet with a token different than specified by token_uid.
    • DepositNotAllowed: "action must be withdrawal": bettor sent a deposit action.
    • ResultNotAvailable: bettor attempted to cash out even before winners were defined.
    • InsufficientBalance: "withdrawal amount is greater than available": bettor tried to cash out more than their available winnings.

View methods

has_result

  • Description: used to check whether oracle has already set the result of the betting event in the contract.
  • Parameters: requires exactly zero parameters.
  • Return: true if oracle has already set result; false otherwise. Example:
    "calls": {
    "has_result()": {
    "value": false
    }
    }

get_winner_amount

  • Description: used to check the amount of winnings for a specific bettor.
  • Parameters: requires exactly one parameter, as follows:
    • address:
      • Description: identifies the bettor. Two different addresses are considered two different bettors.
      • Type: string
      • Possible values: 25 bytes in base58check
      • Example:
        get_winner_amount(%22a%27WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq%27%22)
  • Return: integer; denotes total amount bettor has won. Example:
    "calls": {
    "get_winner_amount(\"a'WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq'\")": {
    "value": 2500
    }
    }

get_max_withdrawal

  • Description: used to check how much of their winnings a given bettor still has for withdrawing.
  • Parameters: requires exactly one parameter, as follows:
    • address:
      • Description: identifies the bettor. Two different addresses are considered two different bettors.
      • Type: string
      • Possible values: 25 bytes in base58check
    • Example:
      get_max_withdrawal(%22a%27WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq%27%22)
  • Return: integer; denotes the amount of winnings remaining for withdrawing (drawable). It returns zero if bettor does not have winning bets, or if a winning bettor has already been withdrawn all their winnings. Example:
    "calls": {
    "get_max_withdrawal(\"a'WRV28Nwa6hdA6ntRtw264qtEZMX7p5EJCq'\")": {
    "value": 1500
    }
    }

What's next?