šŸŽ² Dice Game with 0rbit

Off-chain Random Number Generation using 0rbit

Sarthak Shah's photo
Ā·

6 min read

šŸŽ² Dice Game with 0rbit

Imagine a world where blockchain games are truly unpredictable. Generating verifiable randomness on public blockchains has long been a challenge for dApp developers, especially those working on games. Blockchains' deterministic natureā€”crucial for consensusā€”makes it seem like true randomness is impossible.

This post will guide you through a solution using 0rbit, an off-chain oracle service, to bring unpredictable and verifiable randomness to your blockchain applications. Weā€™ll use a simple dice game as an example, but the principles can apply to any dApp that needs randomness.

Whatā€™s the secret?

Weā€™ll leverage 0rbitā€™s GET request to fetch off-chain data (in this case, randomness). The goal is to ensure that every dice roll gives a truly random number, verifiable on-chain. Letā€™s jump right in!

Checkpoint 0:šŸ“¦ Initialize the Project

To start, weā€™ll use a starter kit developed by the team at Autonomous Finance. This kit is designed to give developers a head start in building AO dApps, making the setup process quick and letting you focus on the core functionality.
First, open your terminal and run the following command:

npx create-ao-dapp@latest

You'll be prompted to enter the name of your project. After that, select the following configurations to set up your project environment:

After the project setup is complete, navigate to the project and install the necessary dependencies using npm install.

Checkpoint 1:šŸ“ Understanding the Folder Structure

Letā€™s focus on the AO Process part of the project for this blog. Specifically, weā€™ll be working on generating a random number and bringing it on-chain using 0rbitā€™s GET request.

Our main focus will be the ao directory. This part of the project is responsible for handling the processes. We'll cover the frontend setup and interaction in the upcoming blog.

  • ao/: Root directory for AO processes.

  • random/: Directory for a specific AO process.

    • scripts/: Contains utility scripts (build, deploy, and test).

    • src/: Contains source code for the process.

      • process_lib.lua: Library for the process.

      • process.lua: Entry point for the process.

      • reset_modules.lua: Script to reset preloaded modules.

Checkpoint 2:šŸ›  Functions for AO Process

Next, weā€™ll implement the core logic to generate and receive a random number using 0rbitā€™s GET request. Weā€™ll write these functions in process_lib.lua.

local mod = {}

function mod.getNumber()
    mod.sendReply(
        _0RBT_POINTS,
        "Transfer",
        {
            Action = "Transfer",
            Recipient = _0RBIT,
            Quantity = FEE_AMOUNT,
            ["X-Url"] = BASE_URL,
            ["X-Action"] = "Get-Real-Data"
        },
        ""
    )
end

function mod.receiveNumber(msg)
    local res = msg.Data

    return res[0]
end

function mod.sendReply(target, action, tags, data)
    Send({
        Target = target,
        ["Response-For"] = action,
        Tags = tags,
        Data = data
    })
end

return mod

Hereā€™s a quick breakdown:

  • local mod = {} : This initializes an empty table containing all the process-related functions.

  • getNumber()

    • This function initiates the process to request a random number from 0rbit via a GET request.

    • mod.sendReply(...)Inside getNumber, the sendReply function is called. This handles sending the request to 0rbit.

      • _0RBT_POINTS: Specifies the target process or address where the request will be sent.

      • "Transfer": This defines the action being performed, which is a token transfer.

      • { Action = "Transfer", ... }: The Tags parameter includes the transfer details (action, recipient, amount) and metadata for the request, like the URL and action to fetch real-world data.

      • "": This represents the empty data payload being sent, as weā€™re making a GET request.

  • function mod.receiveNumber(msg)

    This function handles the response received from 0rbit after the GET request.

    • local res = msg.Data: Extracts the Data field from the response message, which contains the requested random number.

    • return res[0]: Returns the first element of the res array, which is the random number received from the GET request.

  • function mod.sendReply(...)

    This utility function is responsible for sending messages to the AO network. Itā€™s used to handle different types of communication.

    • Target = target: The process or address that will receive the message.

    • ["Response-For"] = action: Indicates which action this message is a response to.

    • Tags = tags: Metadata such as the URL or action tags, depending on what the message is about.

    • Data = data: The actual content or data to be sent with the message.

  • return mod

    Finally, the mod object is returned, exposing the functions defined within the module for use in other parts of the process.

Checkpoint 3:šŸ”„ The Process

Now that we have our library functions in place, let's write the main process logic inside src/process.lua. This file contains the core configuration and handler setup for our AO process.

local process = require "lib.process_lib"

Version       = "0.0.1"
_0RBIT        = "BaMK1dfayo75s3q1ow6AO64UDpD9SEFbeE8xYrY2fyQ"
_0RBT_POINTS  = "BUhZLMwQ6yZHguLtJYA5lLUa9LQzLXMXRfaq9FVcPJc"

FEE_AMOUNT    = "1000000000000" -- 1 $0RBT
BASE_URL      = "http://www.randomnumberapi.com/api/v1.0/random?min=1&max=6&count=1"


-- Handler to Get Random Number
Handlers.add("GetNumber",
    Handlers.utils.hasMatchingTag("Action", "GetNumber"),
    process.getNumber
)

-- Handler to Receive Data
Handlers.add(
    "ReceiveData",
    Handlers.utils.hasMatchingTag("Action", "Receive-Response"),
    process.receiveNumber
)

Hereā€™s a quick breakdown:

  • local process = require "lib.process_lib"This imports the process_lib.lua module, which contains the functions we previously defined (getNumber, receiveNumber, and sendReply).

  • Defining the Constants

    • Version: Sets the version of your process.

    • _0RBIT: 0RBT Points Process Address

    • _0RBT_POINTS: 0rbit Primary Process Address

    • FEE_AMOUNT: Fee to send the GET request (equivalent to 1 $0RBT token).

    • BASE_URL: Points to an external API that generates a random number between 1 and 6

  • Handlers.add("GetNumber", ...)This creates a handler with the "GetNumber" action, which triggers the process.getNumber function:

    • "GetNumber": The name of the handler.

    • Handlers.utils.hasMatchingTag("Action", "GetNumber"): This utility function checks if the incoming request has the Action tag set to "GetNumber", and if so, triggers the function.

    • process.getNumber: Calls the getNumber function from process_lib.lua to initiate the GET request.

  • Handlers.add("ReceiveData", ...)This sets up a handler for receiving data once the GET request is complete:

    • "ReceiveData": The name of the handler for handling the received data.

    • Handlers.utils.hasMatchingTag("Action", "Receive-Response"): This utility function checks if the incoming response has the Action tag set to "Receive-Response", and if so, triggers the handler.

    • process.receiveNumber: Calls the receiveNumber function from process_lib.lua to process the received random number.

Checkpoint 4:šŸš€ Build the Process and Deploy It

Before building your Lua process, you must make the build script executable. Run the following command in your root directory:

chmod +x ./ao/random-function/scripts/build.sh

Then, execute the build command:

npm run random-function:build

Similarly, to deploy your Lua process, first make the deploy script executable:

chmod +x ./ao/random-function/scripts/deploy.sh

Finally, deploy the process by running:

npm run random-function:deploy

Checkpoint 5:šŸŽ² Getting a Random Number

With everything deployed, itā€™s time to fetch a random number. Open a new terminal, access the AO interface using aos, and send a message to your process:

Send({ Target = "YOUR_PROCESS_ID", Action = "GetNumber" })

Remember to replace "YOUR_PROCESS_ID" it with your actual process ID. Once sent, youā€™ll receive a random numberā€”verifiably on-chain! šŸŽ‰


Checkout the complete codebase here:

https://github.com/0rbit-co/dice-random-function

Whatā€™s Next?

In the next blog, weā€™ll cover building the frontend for our Dice Game!šŸ˜‰

If you have any questions, please DM us on Twitter or join our Discord community to learn more about 0rbitšŸ’«.

Keep Building! šŸ§±šŸ’«šŸš€

Ā