Skip to content

bustabit/autobet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bustabit Scripts

This repository documents https://bustabit.com's autobetter / scripting system.

Table of Contents

How to write a script

Bits vs Satoshis

Important: The client and server talk in satoshis even though the user interface shows bits.

  • bits -> satoshis: Math.round(bits * 100)
  • bits -> bitcoins: bits / 1e6
  • satoshis -> bits: satoshis / 100
  • satoshis -> bitcoins: satoshis / 1e8
  • bitcoins -> bits : Math.round(bitcoins * 1e8) / 1e6
  • bitcoins -> satoshis : Math.round(bitcoins * 1e8)

The UI Config

One of the key features of bustabit's new scripting system is that scripts can specify a user interface for the user to fill out before clicking "Start Script".

This allows the script to read user-defined variables, and it makes scripts more user-friendly for the player.


At the top of every script, you must define the UI Config.

var config = {
};

// Simulation begins down here ...

Bustabit parses the config object into a user interface that is used to configure and drive the script.

The user uses the generated form components to feed input into the script, and then your script can access these values while it's running.

Here's a simple script:

var config = {
  name: { value: '', type: 'text', label: 'What is your name?' },
  maxBet: { value: 1e8, type: 'balance', label: 'Max Bet' },
  colors: {
    value: 'red', type: 'radio', label: 'Pick a color',
    options: {
      red: { value: 'red', type: 'noop', label: 'Red' },
      blue: { value: 'blue', type: 'noop', label: 'Blue' },
    }
  }
};

log('hello', config.name.value, 'you chose the color', config.colors.value)

And here's the UI it generates:

Input Objects

As you can see, the UI Config contains values that we will call Input Objects since they get turned into form input components.

Every Input Object has a type which is one of:

  • text: Maps to an <input type="text"> field.

    var config = {
      name: { value: '', type: 'text', label: 'What is your name?' },
      name2: { value: 'initial value', type: 'text', label: 'Another field' }
    }

  • noop: A noop input just means that it does not embed an interactive control. You usually use them inside a radio input.

    var config = {
      noopExample: { type: 'noop', label: 'Demonstrating noop' },
      // If you don't specify a label, the key is used.
      noopExample2: { type: 'noop' }
    }

  • radio: Maps to HTML radio buttons.

    Notice that value: 'red' means that options.red will be the initially-selected radio button.

    var config = {
      colors: {
        value: 'red', type: 'radio', label: 'Pick a color',
        options: {
          red: { value: 'red', type: 'noop', label: 'Red' },
          blue: { value: 'blue', type: 'noop', label: 'Blue' },
        }
      }
    }

  • checkbox: Maps to HTML check boxes.

    var config = {
      red: { type: 'checkbox', label: 'Red', value: true },
      yellow: { type: 'checkbox', label: 'Yellow', value: false },
      blue: { type: 'checkbox', label: 'Blue', value: true }
    };

  • balance: Creates a type="number" input that accepts values in bits but exposes the value as satoshis to the script.

    var config = {
      baseBet: { value: 100, type: 'balance', label: 'base bet' }
    };

    Important: Notice how the value is 100 (satoshis), but it's exposed as 1 to the user in the UI.

  • multiplier: Creates a text field input that accepts payout multiplier inputs like 2.0.

    var config = {
      basePayout: { value: 2, type: 'multiplier', label: 'payout' }
    };

  • combobox: Maps to HTML <select> dropdown options.

    Notice that value: 'red' means that options.red will be the initially-selected radio button.

    var config = {
      colors: {
        value: 'red', 
        type: 'combobox', 
        label: 'Pick a color',
        options: {
          red: { label: 'Red' },
          blue: { label: 'Blue' },
        }
      }
    }

Required vs optional inputs

By default, all inputs are required which means that the user must fill them in (text inputs) or select an option (radio buttons) before the "Start Script" button will launch the script.

You can mark an input as optional with optional: true.

For example, in the following example, the "name" field is required, so our script can assume it exists. But the user is not required to choose a color, so config.colors.value may be "red", "blue", or undefined.

var config = {
  name: { value: '', type: 'text', label: 'What is your name?' },
  colors: {
    optional: true,
    type: 'radio', label: 'Pick a color',
    options: {
      red: { value: 'red', type: 'noop', label: 'Red' },
      blue: { value: 'blue', type: 'noop', label: 'Blue' },
    }
  }
};

log('hello', config.name.value);

if (config.colors.value) {
  log('you chose the color', config.colors.value);
} else {
  log('you did not choose a color');
}

Interacting with the game

After the var config = { ... } block, the rest of the script is run when the user clicks "Run Script."

Bustabit provides you with some variables that you can access to interact with the game and respond to events.

The Engine API

The script has access to an engine variable which is an Event Emitter. You attach listeners to the engine to respond to events.

engine.on('GAME_STARTING', function () {
  log('a game is starting')
})

Events:

  • "GAME_STARTING": Emitted when the server starts accepting bets 5 seconds before the game actually starts.
  • "GAME_STARTED": Bets are no longer accepted.
  • "GAME_ENDED"
  • "BET_PLACED" bet: Whenever a player places a bet, your listener will receive the bet object. This event is not emitted for simulated bets.
  • "PLAYERS_CHANGED": Is emitted whenever a player makes a bet or cashes out. This means that engine.players and engine.cashOuts have been updated, respectively.
  • "CASHED_OUT" object: Whenever a player cashed out, this event broadcasts an object that looks like { uname: string, wager: int, cashedAt: float (multiplier) }.
  • ...

Methods:

  • engine.bet(satoshis: Integer, payout: Float): So, engine.bet(100, 2) means that you are betting 100 satoshis (1 bit) with an autocashout at 2x. If you don't want an autocashout, just set it really high: engine.bet(100, Number.MAX_VALUE).
  • engine.getState(): Serializes the state of the engine into a javascript object. Can be useful for debugging.
  • engine.getCurrentBet(): Returns falsey if you have no bet placed, else it returns { wager: number, payout: number }.
  • engine.isBetQueued(): Returns boolean, true if you have a bet enqueued for next game.
  • engine.cancelQueuedBet(): Cancels the bet that you have enqueued for next game.
  • engine.cashOut(): Attempts to cash out the current game.

Properties:

  • engine.history: A circular buffer of games (not a Javascript array).
    • engine.history.first(): the latest game. If game.crashedAt is not set, then it's the current game-in-progress.
    • engine.history.last(): the oldest game in the buffer which only stores the latest 50 games.
    • engine.history.toArray(): returns an Array<Game> so that you can use regular array methods to process the history.
  • engine.playing: A Map() of usernames to their bet amount. Only includes players that have not yet cashed out.
  • engine.cashOuts: An array of { wager: satoshis, uname: String, cashedAt: Float } of all cashed out players.

A Game object

engine.history contains game objects with these keys:

  • game.id (integer)
  • game.hash (string)
  • game.bust (nullable float, ex: 1.32): The multiplier that the game crashed at. If it is not set, then the game is currently in progress.
  • game.cashedAt (nullable float, ex: 103.45): The multiplier that WE cashed-out at. If it is not set, then we either did not play that game or the game busted before you cashed out. You can check the existence of this value to determine if we won that game or not.
  • game.wager (satoshis, integer, ex: 100)

Example:

{
  id: 114124,
  hash: '92a2adb04da8231447104f9668ac1f646e1046bbdb77333f75e8bc23e871052d',
  bust: 3.21, // or null
  cashedAt: null, // or 102.34
  wager: 1000, // that's 10 bits
}

The UserInfo Store

Scripts have access to another variable, userInfo, which emits events and exposes info about you, the currently logged-in user.

Useful Events:

  • BALANCE_CHANGED: User balance changed

Useful Properties:

  • userInfo.balance: User balance in satoshis
  • userInfo.bets: Total amount of user's bets
  • userInfo.wagered: Total amount of satoshis user has wagered
  • userInfo.profit

The Chat Store

Scripts have access to another variable, chat, which emits events and exposes info about public chat channels.

Useful Events:

  • FRIENDS_CHANGED: When you have added/removed a friend.

Useful Properties:

  • chat.channels (Map): Map of joined channels which maps channel name to { unread: int, history: Array<{message, uname, created}> }

Displaying Output

Your script can use log('hello', 'world') which will println info to a textbox beneath the script while the script is running.

It's useful for debugging but also providing the user with a feed of script activity so that they know what's going on.

Notifications

If you want to emit browser notifications from the script, use notify(message). This is good for sending yourself messages about notable events (like if the script is stopping itself) when you are viewing another browser tab or application.

Note that you must have browser notifications enabled for bustabit.com.

You may not always want a script to bother you with browser notifications. You can toggle this behavior in bustabit.com's global settings. When script notifications are disabled, messages will simply appear in the script logs.

Stopping the Script

A script can stop itself with stop(reason).

The reason (a string) will be published to the scripts logs so that the player understands why the script stopped itself.

if (userInfo.balance < config.wager.value) {
  stop('Insufficient balance to make the bet')
}

Verifying Game Results

Four convenience functions are provided to aid in verifying game results: gameResultFromSignature, gameResultFromHash, SHA256FromHex and SHA256.

gameResultFromSignature(hash, id) returns the game result equivalent to the given game hash and game id:

const gameHash = "e1d3966787cb0ce17e9690a1f518fa58bd61a14fb556c55621fd6f061d430172";
const gameId = 10004381;
gameResultFromSignature(gameHash, gameId).then(log); // logs 8.16

gameResultFromHash(hash) returns the game result equivalent to the given game hash:

// for backward compatibility with bustabit's previous chain and game salt
const hash = "6774ddd3dfe94e2c966d4ca5c5ed6dcd1f6a4fdab87ad12677ee7c5b96d6a3f5";
gameResultFromHash(hash).then(log); // logs 3.74

SHA256FromHex(value) returns the hash of the binary 256-bit value of value:

log(SHA256FromHex("cafe0123")); // logs 0dce08a9fb89bf0bef8d8b3960db34d21f3b3a77142692bf608ab87b5c1bc7d5

SHA256(value) returns the hash of the hex-encoded string representation of value:

// for backward compatibility
log(SHA256("cafe0123")); // logs 34840c8af8ef4c93baa37aa9de666dd26d808317defcbc99093096cc67703648

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published