Prompt: This is a Markdown documentation from the AO documentation repository. Filename: post-request.md Path: ../ao-cookbook/src/guides/snacks/0rbit/post-request.md

Response:
---
prev:
  text: "0rbit"
  link: "/guides/snacks/0rbit/get-request"
next:
  text: "BetterIDEa IDE"
  link: "../betteridea/index.md"
---

# First POST Request

In this tutorial, we will learn how to make a POST request on `0rbit` process.

## 🔑 Prerequisites

- aos installed on your system.
- Some $0RBT. _Learn how to get $0RBT [here](https://docs.0rbit.co/protocol/token/how-to-get)_
- Any Code Editor (VSCode, Sublime Text, etc)

If you are ready with the above prerequisites,

## 🛠 Let's Start Building

### Initialize the Project

Create a new file named `0rbit-Post-Request.lua` in your project directory.

```bash
touch 0rbit-Post-Request.lua
```

### Initialize the Variables

```lua
local json = require("json")

_0RBIT = "BaMK1dfayo75s3q1ow6AO64UDpD9SEFbeE8xYrY2fyQ"
_0RBT_POINTS = "BUhZLMwQ6yZHguLtJYA5lLUa9LQzLXMXRfaq9FVcPJc"

FEE_AMOUNT = "1000000000000" -- 1 $0RBT
BASE_URL = "https://arweave.dev/graphql"
-- The data body to be sent in the POST request
BODY = json.encode({
    query = [[
        query {
            transactions(
                owners: ["vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI"]
            ) {
                edges {
                    node {
                        id
                    }
                }
            }
        }
    ]]
});

ReceivedData = ReceivedData or {}
```

### Make the Request

The following code contains the Handler that will send 1 $0RBT to the `0rbit` process and make the POST request for the `BASE_URL`

```lua
Handlers.add(
    "Post-Request",
    Handlers.utils.hasMatchingTag("Action", "First-Post-Request"),
    function(msg)
        Send({
            Target = _0RBT_TOKEN,
            Action = "Transfer",
            Recipient = _0RBIT,
            Quantity = FEE_AMOUNT,
            ["X-Url"] = BASE_URL,
            ["X-Action"] = "Post-Real-Data",
            ["X-Body"] = BODY
        })
        print(Colors.green .. "You have sent a POST Request to the 0rbit process.")
    end
)
```

Breakdown of the above code:

- `Handlers.add` is used to add a new handler to the `ao` process.
- Post-Request\_\_ is the name of the handler.
- `Handlers.utils.hasMatchingTag` is a function that checks if the incoming message has the matching tag same as the **First-Post-Request**.
- `function(msg)` is the function executed when the handler is called.
- `Send` is the function that takes several tags as the arguments and creates a message on the ao:

  | **Tag**      |                                                        **Description**                                                         |
  | :----------- | :----------------------------------------------------------------------------------------------------------------------------: |
  | Target       |                         The processId of the recipient. In this case, it's the $0RBT token processId.                          |
  | Action       |              The tag that defines the handler to be called in the recipient process. In this case it's `Transfer`              |
  | Recipient    |           The tag that accepts the processId to whom the $0RBT will be sent. In this case, it's the 0rbit processId.           |
  | Quantity     |                                                The amount of $0RBT to be sent.                                                 |
  | ["X-Url"]    |        The _forwarded-tag_ which contains the URL and the same will be used by the **0rbit process** to fetch the data.        |
  | ["X-Action"] | The _forwarded-tag_ which contains the action to be performed by the **0rbit process**. In this case, it's **Post-Real-Data**. |
  | ["X-Body"]   |                        The _forwarded-tag_ which contains the data body to be sent in the POST request.                        |

### Receive Data

The following code contains the Handler that will receive the data from the `0rbit` process and print it.

```lua
Handlers.add(
    "Receive-Data",
    Handlers.utils.hasMatchingTag("Action", "Receive-Response"),
    function(msg)
        local res = json.decode(msg.Data)
        ReceivedData = res
        print(Colors.green .. "You have received the data from the 0rbit process.")
    end
)
```

Breakdown of the above code:

- `Handlers.add` is used to add a new handler to the `ao` process.
- **Receive-Data** is the name of the handler.
- `Handlers.utils.hasMatchingTag` is a function that checks if the incoming message has the matching tag same as the **Receive-Response**.
- `function(msg)` is the function executed when the handler is called.
  - `json.decode` is used to decode the JSON data received.
  - `ReceivedData = res` stores the received data in the `ReceivedData` variable.

The 0rbit process always sends the data in the `string` format.
`json.decode` is used above because we know the receiving data, i.e., stringified JSON.
So, you need to decode the data as per your requirements.

## 🏃 Run the process

### Create a new process and load the script

```bash
aos 0rbitPostRequest --load 0rbit-Post-Request.lua
```

The above command will create a new process with the name **0rbitPostRequest** and load `0rbit-Post-Request.lua` into it.

### Fund your process

Transfer some $0RBT to your processID.

### Call the Handler

Call the handler, who will create a request for the 0rbit process.

```bash
Send({ Target= ao.id, Action="First-Post-Request" })
```

### Check the Data

To check the data stored in the `ReceivedData` variable, run the following command:

```bash
ReceivedData
```

Upon the successful execution, you will receive the JSON data in your terminal:

```json
{
    data = {
        transactions = {
        edges = {
            {
            node = {
                id = "nH0NU9rgNqGVHwjtjFvnIyXpsP7YVrj_v7JxFErHNB4"
            }
            },
            //and so on...
            {
            node = {
                id = "9HLUVJo4AcrSxQeapf2hutS2Xp7hx_XDiIvv3vnxDcc"
            }
            }
        }
        }
    }
}
```

---

**_Voila! You have successfully made your first POST request on the 0rbit process. 🎉_**

> You can find the complete code here:
>
> https://github.com/0rbit-co/examples/blob/main/First-Post-Request.lua


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: index.md Path: ../ao-cookbook/src/guides/snacks/0rbit/index.md

Response:
---
prev:
  text: "Bots and Games"
  link: "/guides/aoconnect/monitoring-cron"
next:
  text: "First GET Request"
  link: "/guides/snacks/0rbit/get-request"
---

# 0rbit 💫

[0rbit](https://0rbit.co/) is the first-ever Decentralised Oracle Network on Arweave using `ao`.

0rbit enables Access to ANY Real-World data present and accessible across internet into your `ao` process.

0rbit provides the following features to get access to the data using the HTTP protocol:

- [**Fetch HTTP Data**](https://docs.0rbit.co/developer/get-request): A handler to make a HTTP Get Request from your `ao` process to the web.
- [**Post HTTP Data**](https://docs.0rbit.co/developer/post-request): A handler to make a HTTP Post Request from your `ao` process to the web.

## Tutorials

Learn how to build with 0rbit with the following tutorials:

- [First GET Request](./get-request.md)
- [First POST Request](./post-request.md)

> _Learn more about 0rbit through the [developer docs.](https://docs.0rbit.co/)_


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: troubleshooting.md Path: ../ao-cookbook/src/guides/aos/troubleshooting.md

Response:
# Troubleshooting using ao.link

Working with a decentralized computer and network, you need to be able to troubleshoot more than your own code. You need to be able to track messages, token balances, token transfers of processes. This is where [https://ao.link](https://ao.link) becomes an essential tool in your toolbox.

![ao.link homepage displaying ao network stats](aolink.png)

## Analytics

AOLink has a set of 4 analytic measures:

- Total Messages
- Total Users
- Total Processes
- Total Modules

These analytics give you a quick view into the ao network's total processing health.

## Events

Below, the analytics are the latest events that have appeared on the ao computer. You have a list of messages being scheduled and that have been executed. These events are any of the ao Data Protocol Types. And you can click on the Process ID or the Message ID to get details about each.

![ao.link list of events](aolink-list-example.png)

### Message Details

![ao.link message details displaying the message processed](aolink-message-details.png)

The message details give you key details about:

- From
- To
- Block Height
- Created
- Tags
- Data
- Result Type
- Data

If you want to further troubleshoot and debug, you have the option to look at the result of the CU (Compute Unit) by clicking on "Compute".

![ao.link compute result example for debugging](aolink-compute-example.png)

And further understand linked messages.
![ao.link linked messages](aolink-linked-message-example.png)

### Process Details

![ao.link displaying a process in details](aolink-process-details.png)

The process details provide you with information about the process it's useful to see in the tags with what module this got instantiated from.
If you notice on the left you see the interaction with the process displayed on a graph.
In this case, this is DevChat, and you can see all the processes that have interacted by Registering and Broadcasting Messages.

You can effortless check the Info Handler, by pressing the "Fetch" button.
![ao.link fetching the info handler](aolink-info-handler-example.png)

On the bottom you see the processes balance and all messages send, with the option to break it down into Token transfers and Token balances using the tabs.
![ao.link process message and token info](aolink-message-and-token-example.png)

## Further Questions?

Feel free to reach out on the community Discord of Autonomous Finance, for all questions and support regarding ao.link.
https://discord.gg/4kF9HKZ4Wu

## Summary

AOLink is an excellent tool for tracking events in the ao computer. Give it a try. Also, there is another scanner tool available on the permaweb: https://ao_marton.g8way.io/ - check it out!


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: installing.md Path: ../ao-cookbook/src/guides/aos/installing.md

Response:
# Installing aos

Installing aos only requires `NodeJS` - https://nodejs.org

> NOTE: If you are on windows you may get better results with WSL Console.

```sh
npm i -g https://get_ao.g8way.io
```

Once installed you can run by typing `aos`


Prompt:
This is a Markdown documentation from the AO documentation repository. Filename: token.md Path: ../ao-cookbook/src/guides/aos/token.md
Note: This content continues in the next part.

Response:
# Building a Token in `ao`

When creating tokens, we'll continue to use the [Lua Language](../../references/lua.md) within `ao` to mint a token, guided by the principles outlined in the [Token Specification](../../references/token.md).

### Two Ways to Create Tokens:

**1 - Use the token blueprint:**

`.load-blueprint token`

Using the token blueprint will create a token with all the handlers and state already defined. This is the easiest way to create a token. You'll be able to customize those handlers and state to your after loading the blueprint.

You can learn more about available blueprints here: [Blueprints](../aos/blueprints/index.md)

::: info
Using the token blueprint will definitely get quickly, but you'll still want to understand how to [load and test](token.html#loading-and-testing) the token, so you can customize it to your needs.
:::

**2 - Build from Scratch:**

The following guide will guide you through the process of creating a token from scratch. This is a more advanced way to create a token, but it will give you a better understanding of how tokens work.

## Preparations

### **Step 1: Initializing the Token**

- Open our preferred text editor, preferably from within the same folder you used during the previous tutorial.
- Create a new file named `token.lua`.
- Within `token.lua`, you'll begin by initializing the token's state, defining its balance, name, ticker, and more:

```lua
local json = require('json')

if not Balances then Balances = { [ao.id] = 100000000000000 } end

if Name ~= 'My Coin' then Name = 'My Coin' end

if Ticker ~= 'COIN' then Ticker = 'COIN' end

if Denomination ~= 10 then Denomination = 10 end

if not Logo then Logo = 'optional arweave TxID of logo image' end
```

![token.lua image 1](/token1.png)

Let's break down what we've done here:

- `local json = require('json')`: This first line of this code imports a module for later use.

- `if not Balances then Balances = { [ao.id] = 100000000000000 } end`: This second line is initializing a Balances table which is the way the Process tracks who posses the token. We initialize our token process `ao.id` to start with all the balance.

- The Next 4 Lines, `if Name`, `if Ticker`, `if Denomination`, and `if not Logo` are all optional, except for `if Denomination`, and are used to define the token's name, ticker, denomination, and logo respectively.

::: info
The code `if Denomination ~= 10 then Denomination = 10 end` tells us the number of the token that should be treated as a single unit.
:::

### **Step 2: Info and Balances Handlers**

<br>

#### Incoming Message Handler

Now lets add our first Handler to handle incoming Messages.

```lua
Handlers.add('Info', Handlers.utils.hasMatchingTag('Action', 'Info'), function(msg)
  ao.send(
      { Target = msg.From, Tags = { ["Name"] = Name, ["Ticker"] = Ticker, ["Logo"] = Logo, ["Denomination"] = tostring(Denomination) } })
end)
```

![Token.lua image 2](/token2.png)

::: info
At this point, you've probably noticed that we're building all of the handlers inside the `token.lua` file rather than using `.editor`.

With many handlers and processes, it's perfectly fine to create your handlers using `.editor`, but because we're creating a full process for initializing a token, setting up info and balances handlers, transfer handlers, and a minting handler, it's best to keep everything in one file.

This also allows us to maintain consistency since each handler will be updated every time we reload the `token.lua` file into `aos`.
:::

This code means that if someone Sends a message with the Tag, Action = "Info", our token will Send back a message with all of the information defined above. Note the Target = msg.From, this tells ao we are replying to the process that sent us this message.

#### Info & Token Balance Handlers

Now we can add 2 Handlers which provide information about token Balances.

```lua
Handlers.add('Balance', Handlers.utils.hasMatchingTag('Action', 'Balance'), function(msg)
  local bal = '0'

  -- If not Target is provided, then return the Senders balance
  if (msg.Tags.Target and Balances[msg.Tags.Target]) then
    bal = tostring(Balances[msg.Tags.Target])
  elseif Balances[msg.From] then
    bal = tostring(Balances[msg.From])
  end

  ao.send({
    Target = msg.From,
    Data = json.encode(tonumber(bal)),
    Tags = { ["Balance"] = bal, ["Ticker"] = Ticker }
  })
end)

Handlers.add('Balances', Handlers.utils.hasMatchingTag('Action', 'Balances'),
             function(msg) ao.send({ Target = msg.From, Data = json.encode(Balances) }) end)

```

The first Handler above `Handlers.add('Balance'` handles a process or person requesting their own balance or the balance of a Target. Then replies with a message containing the info. The second Handler `Handlers.add('Balances'` just replies with the entire Balances table.

### **Step 3: Transfer Handlers**

Before we begin testing we will add 2 more Handlers one which allows for the transfer of tokens between processes or users.

```lua
Handlers.add('Transfer', Handlers.utils.hasMatchingTag('Action', 'Transfer'), function(msg)
  assert(type(msg.Tags.Recipient) == 'string', 'Recipient is required!')
  assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')

  if not Balances[msg.From] then Balances[msg.From] = 0 end

  if not Balances[msg.Tags.Recipient] then Balances[msg.Tags.Recipient] = 0 end

  local qty = tonumber(msg.Tags.Quantity)
  assert(type(qty) == 'number', 'qty must be number')

  if Balances[msg.From] >= qty then
    Balances[msg.From] = Balances[msg.From] - qty
    Balances[msg.Tags.Recipient] = Balances[msg.Tags.Recipient] + qty

    --[[
      Only Send the notifications to the Sender and Recipient
      if the Cast tag is not set on the Transfer message
    ]] --
    if not msg.Tags.Cast then
      -- Debit-Notice message template, that is sent to the Sender of the transfer
      local debitNotice = {
        Target = msg.From,
        Action = 'Debit-Notice',
        Recipient = msg.Recipient,
        Quantity = tostring(qty),
        Data = Colors.gray ..
            "You transferred " ..
            Colors.blue .. msg.Quantity .. Colors.gray .. " to " .. Colors.green .. msg.Recipient .. Colors.reset
      }
      -- Credit-Notice message template, that is sent to the Recipient of the transfer
      local creditNotice = {
        Target = msg.Recipient,
        Action = 'Credit-Notice',
        Sender = msg.From,
        Quantity = tostring(qty),
        Data = Colors.gray ..
            "You received " ..
            Colors.blue .. msg.Quantity .. Colors.gray .. " from " .. Colors.green .. msg.From .. Colors.reset
      }

      -- Add forwarded tags to the credit and debit notice messages
      for tagName, tagValue in pairs(msg) do
        -- Tags beginning with "X-" are forwarded
        if string.sub(tagName, 1, 2) == "X-" then
          debitNotice[tagName] = tagValue
          creditNotice[tagName] = tagValue
        end
      end

      -- Send Debit-Notice and Credit-Notice
      ao.send(debitNotice)
      ao.send(creditNotice)
    end
  else
    ao.send({
      Target = msg.Tags.From,
      Tags = { ["Action"] = 'Transfer-Error', ['Message-Id'] = msg.Id, ["Error"] = 'Insufficient Balance!' }
    })
  end
end)
```

In summary, this code checks to make sure the Recipient and Quantity Tags have been provided, initializes the balances of the person sending the message and the Recipient if they dont exist and then attempts to transfer the specified quantity to the Recipient in the Balances table.

```lua
Balances[msg.From] = Balances[msg.From] - qty
Balances[msg.Tags.Recipient] = Balances[msg.Tags.Recipient] + qty
```

If the transfer was successful a Debit-Notice is sent to the sender of the original message and a Credit-Notice is sent to the Recipient.

```lua
-- Send Debit-Notice to the Sender
ao.send({
    Target = msg.From,
    Tags = { ["Action"] = 'Debit-Notice', ["Recipient"] = msg.Tags.Recipient, ["Quantity"] = tostring(qty) }
})
-- Send Credit-Notice to the Recipient
ao.send({
    Target = msg.Tags.Recipient,
    Tags = { ["Action"] = 'Credit-Notice', ["Sender"] = msg.From, ["Quantity"] = tostring(qty) }
})
```

If there was insufficient balance for the transfer it sends back a failure message

```lua
ao.send({
    Target = msg.Tags.From,
    Tags = { ["Action"] = 'Transfer-Error', ['Message-Id'] = msg.Id, ["Error"] = 'Insufficient Balance!' }
})
```

The line `if not msg.Tags.Cast then` Means


Prompt: This is a Markdown documentation from the AO documentation repository. This is a continuation from the previous part. Filename: token.md Path: ../ao-cookbook/src/guides/aos/token.md

Response:
Notice is sent to the sender of the original message and a Credit-Notice is sent to the Recipient.

```lua
-- Send Debit-Notice to the Sender
ao.send({
    Target = msg.From,
    Tags = { ["Action"] = 'Debit-Notice', ["Recipient"] = msg.Tags.Recipient, ["Quantity"] = tostring(qty) }
})
-- Send Credit-Notice to the Recipient
ao.send({
    Target = msg.Tags.Recipient,
    Tags = { ["Action"] = 'Credit-Notice', ["Sender"] = msg.From, ["Quantity"] = tostring(qty) }
})
```

If there was insufficient balance for the transfer it sends back a failure message

```lua
ao.send({
    Target = msg.Tags.From,
    Tags = { ["Action"] = 'Transfer-Error', ['Message-Id'] = msg.Id, ["Error"] = 'Insufficient Balance!' }
})
```

The line `if not msg.Tags.Cast then` Means were not producing any messages to push if the Cast tag was set. This is part of the ao protocol.

### **Step 4: Mint Handler**

Finally, we will add a Handler to allow the minting of new tokens.

```lua
Handlers.add('Mint', Handlers.utils.hasMatchingTag('Action', 'Mint'), function(msg, env)
  assert(type(msg.Tags.Quantity) == 'string', 'Quantity is required!')

  if msg.From == env.Process.Id then
    -- Add tokens to the token pool, according to Quantity
    local qty = tonumber(msg.Tags.Quantity)
    Balances[env.Process.Id] = Balances[env.Process.Id] + qty
  else
    ao.send({
      Target = msg.Tags.From,
      Tags = {
        ["Action"] = 'Mint-Error',
        ["Message-Id"] = msg.Id,
        ["Error"] = 'Only the Process Owner can mint new ' .. Ticker .. ' tokens!'
      }
    })
  end
end)
```

This code checks to make sure the Quantity Tag has been provided and then adds the specified quantity to the Balances table.

## Loading and Testing

Once you've created your `token.lua` file, or you've used `.load-blueprint token`, you're now ready to begin testing.

#### 1 - Start the aos process

Make sure you've started your aos process by running `aos` in your terminal.

#### 2 - Loading the token.lua file

If you've followed along with the guide, you'll have a `token.lua` file in the same directory as your aos process. From the aos prompt, load in the file.

```lua
.load token.lua
```

#### 3 - Testing the Token

Now we can send Messages to our aos process ID, from the same aos prompt to see if is working. If we use ao.id as the Target we are sending a message to ourselves.

```lua
Send({ Target = ao.id, Action = "Info" })
```

This should print the Info defined in the contract. Check the latest inbox message for the response.

```lua
Inbox[#Inbox].Tags
```

This should print the Info defined in the contract.

::: info
Make sure you numerically are checking the last message. To do so, run `#Inbox` first to see the total number of messages are in the inbox. Then, run the last message number to see the data.

**Example:**

If `#Inbox` returns `5`, then run `Inbox[5].Data` to see the data.
:::

#### 4 - Transfer

Now, try to transfer a balance of tokens to another wallet or process ID.

::: info
If you need another process ID, you can run `aos [name]` in another terminal window to get a new process ID. Make sure it's not the same `aos [name]` as the one you're currently using.

**Example:**

If you're using `aos` in one terminal window, you can run `aos test` in another terminal window to get a new process ID.
:::

```lua
Send({ Target = ao.id, Tags = { ["Action"] = "Transfer", ["Recipient"] = 'another wallet or processid', ["Quantity"] = '10000' }})
```

After sending, you'll receive a printed message in the terminal similar to `Debit-Notice` on the sender's side and `Credit-Notice` on the recipient's side.

#### 5 - Check the Balances

Now that you've transferred some tokens, let's check the balances.

```lua
Send({ Target = ao.id, Tags = { ["Action"] = "Balances" }})
```

```lua
Inbox[#Inbox].Data
```

You will see two process IDs or wallet addresses, each displaying a balance. The first should be your sending process ID, the second should be the recipient's process ID.

#### 6 - Minting Tokens

Finally, attempt to mint some tokens.

```lua
Send({ Target = ao.id, Tags = { ["Action"] = "Mint", ["Quantity"] = '1000' }})
```

And check the balances again.

```lua
Send({ Target = ao.id, Tags = { ["Action"] = "Balances" }})
Inbox[#Inbox].Data
```

You'll then see the balance of the process ID that minted the tokens has increased.

## Conclusion

That concludes the "Build a Token" guide. Learning out to build custom tokens will unlock a great deal of potential for your projects; whether that be creating a new currency, a token for a game, a governance token, or anything else you can imagine.


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: load.md Path: ../ao-cookbook/src/guides/aos/load.md

Response:
# Load Lua Files with `.load <filename>`

This feature allows you to load lua code from a source file on your local machine, this simple feature gives you a nice DX experience for working with aos processes.

When creating handlers you may have a lot of code and you want to take advantage of a rich development environment like vscode. You can even install the lua extension to get some syntax checking.

So how do you publish your local lua source code to your ao process? This is where the `.load` command comes into play.

hello.lua

```lua
Handlers.add(
  "ping",
  Handlers.utils.hasMatchingData("ping"),
  Handlers.utils.reply("pong")
)
```

aos shell

```lua
.load hello.lua
```

Easy Peasy! 🐶


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: pingpong.md Path: ../ao-cookbook/src/guides/aos/pingpong.md

Response:
<script setup>
  import {onMounted} from "vue"
  import {renderRepl} from "../../tools/replRenderer.jsx"

  const codes = {
    "step-3": `Handlers.add(
      "pingpong",
      Handlers.utils.hasMatchingData("ping"),
      Handlers.utils.reply("pong")
      )`,
    "step-5": `Send({ Target = ao.id, Data = "ping" })`,
    "step-6": `Inbox[#Inbox].Data`
  }

  onMounted(() => {
      Object.keys(codes).forEach((key) => {
        renderRepl(key, codes[key])
      })
    }
  )
</script>

# Creating a Pingpong Process in aos

This tutorial will guide you through creating a simple "ping-pong" process in aos. In this process, whenever it receives a message with the data "ping", it will automatically reply with "pong". This is a basic example of message handling and interaction between processes in aos.

## Step 1: Open the `aos` CLI

- Start by opening your command-line interface and typing `aos` to enter the aos environment.

## Step 2: Access the Editor

- Type `.editor` in the aos CLI to open the inline text editor. This is where you'll write your ping-pong handler code.

## Step 3: Write the Pingpong Handler

- In the editor, enter the following Lua code to add a handler for the pingpong pattern:

  ```lua
  Handlers.add(
    "pingpong",
    Handlers.utils.hasMatchingData("ping"),
    Handlers.utils.reply("pong")
  )
  ```

  <div id="step-3"></div>

- This lua script does three things:
  1. It adds a new handler named "pingpong".
  2. It uses `Handlers.utils.hasMatchingData("ping")` to check if incoming messages contain the data "ping".
  3. If the message contains "ping", `Handlers.utils.reply("pong")` automatically sends back a message with the data "pong".

## Step 4: Exit the Editor

- After writing your code, type `.done` and press Enter to exit the editor and run the script.

## Step 5: Test the Pingpong Process

- To test the process, send a message with the data "ping" to the process. You can do this by typing the following command in the aos CLI:

  ```lua
  Send({ Target = ao.id, Data = "ping" })
  ```

  <div id="step-5"></div>

- The process should respond with a message containing "pong" in the `Inbox`.

## Step 6: Monitor the Inbox

- Check your Inbox to see the "ping" message and your Outbox to confirm the "pong" reply.

```lua
Inbox[#Inbox].Data
```

<div id="step-6"></div>

## Step 7: Experiment and Observe

- Experiment by sending different messages and observe how only the "ping" messages trigger the "pong" response.

## Step 8: Save Your Process (Optional)

- If you want to use this process in the future, save the handler code in a Lua file for easy loading

into aos sessions.

::: info

**ADDITIONAL TIP:**

- **Handler Efficiency**: The simplicity of the handler function is key. Ensure that it's efficient and only triggers under the correct conditions.

:::

## Conclusion

Congratulations! You have now created a basic ping-pong process in aos. This tutorial provides a foundation for understanding message handling and process interaction within the aos environment. As you become more comfortable with these concepts, you can expand to more complex processes and interactions, exploring the full potential of aos.


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: index.md Path: ../ao-cookbook/src/guides/aos/index.md

Response:
---
prev:
  text: "Tutorials"
  link: "/guides/tutorials/"
next:
  text: "Introduction to aos"
  link: "/guides/aos/intro"
---

# aos: AO Operating System

aos is a powerful operating system built on top of the AO hyper-parallel computer. While AO provides the distributed compute infrastructure, aos offers a simplified interface for interacting with and developing processes in this environment.

## What is aos?

aos enables you to:

- Create and interact with processes on the AO network
- Develop distributed applications using a simple, intuitive approach
- Leverage the Lua programming language for deterministic, reliable operations

All you need to get started is a terminal and a code editor. aos uses [Lua](../../concepts/lua.md) as its primary language - a robust, deterministic, and user-friendly programming language that's ideal for distributed applications.

> **New to AO?** If you're just getting started, we recommend completing our [tutorials](../../tutorials/index) first. They take just 15-30 minutes and provide an excellent foundation.

## Getting Started with aos

Start here if you're new to aos:

- [Introduction to aos](intro) - Overview of aos capabilities and concepts
- [Installation Guide](installing) - Step-by-step instructions for setting up aos
- [aos Command Line Interface](cli) - Learn to use the aos CLI effectively
- [Customizing Your Prompt](prompt) - Personalize your aos development environment
- [Load Lua Files](load) - Learn how to load and execute Lua files in aos
- [Building a Ping-Pong Server](pingpong) - Create your first interactive aos application

## Blueprints

Blueprints in aos are templates that streamline the development of distributed applications by providing a framework for creating consistent and efficient processes across the AO network.

### Available Blueprints

- [Chatroom](blueprints/chatroom) - Template for building chatroom applications
- [Cred Utils](blueprints/cred-utils) - Tools for managing credentials
- [Staking](blueprints/staking) - Framework for implementing staking mechanisms
- [Token](blueprints/token) - Guide for creating and managing tokens
- [Voting](blueprints/voting) - Blueprint for setting up voting systems

## aos Modules

aos includes several built-in modules for common operations:

- [JSON Module](modules/json) - Parse and generate JSON data
- [AO Module](modules/ao) - Interface with the AO ecosystem
- [Crypto Module](modules/crypto) - Perform cryptographic operations
- [Base64 Module](modules/base64) - Encode and decode Base64 data
- [Pretty Module](modules/pretty) - Format data for easier reading
- [Utils Module](modules/utils) - Common utility functions

## Developer Resources

More advanced topics for aos development:

- [Editor Setup & Configuration](editor) - Configure your development environment
- [Understanding the Inbox & Message Handlers](inbox-and-handlers) - Learn how message handling works
- [Troubleshooting with ao.link](troubleshooting) - Debug aos applications
- [Frequently Asked Questions](faq) - Find answers to common questions
- [Build a Token](token) - Create your own token on AO

## Navigation

Use the sidebar to browse through specific aos guides. For a more structured learning path, we recommend following the guides in the order listed above.


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: editor.md Path: ../ao-cookbook/src/guides/aos/editor.md

Response:
# Editor setup

Remembering all the built in ao functions and utilities can sometimes be hard. To enhance your developer experience, it is recommended to install the [Lua Language Server](https://luals.github.io) extension into your favorite text editor and add the [ao addon](https://github.com/martonlederer/ao-definitions). It supports all built in aos [modules](../aos/modules/index) and [globals](../aos/intro#globals).

## VS Code

Install the [sumneko.lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) extension:

1. Search for "Lua" by sumneko in the extension marketplace
2. Download and install the extension
3. Open the VS Code command palette with `Shift + Command + P` (Mac) / `Ctrl + Shift + P` (Windows/Linux) and run the following command:

```
> Lua: Open Addon Manager
```

4. In the Addon Manager, search for "ao", it should be the first result. Click "Enable" and enjoy autocomplete!

## Other editors

1. Verify that your editor supports the [language server protocol](https://microsoft.github.io/language-server-protocol/implementors/tools/)
2. Install Lua Language Server by following the instructions at [luals.github.io](https://luals.github.io/#install)
3. Install the "ao" addon to the language server

## BetterIDEa

[BetterIDEa](https://ide.betteridea.dev) is a custom web based IDE for developing on ao.

It offers a built in Lua language server with ao definitions, so you don't need to install anything. Just open the IDE and start coding!

Features include:

- Code completion
- Cell based notebook ui for rapid development
- Easy process management
- Markdown and Latex cell support
- Share projects with anyone through ao processes
- Tight integration with [ao package manager](https://apm.betteridea.dev)

Read detailed information about the various features and integrations of the IDE in the [documentation](https://docs.betteridea.dev).


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: prompt.md Path: ../ao-cookbook/src/guides/aos/prompt.md

Response:
# Customizing the Prompt in aos

## Step 1: Open aos and Start the Editor

- Launch the aos command-line interface.
- Enter `.editor` to open the inline text editor.

## Step 2: Write the Custom Prompt Function

- In the editor, define your custom prompt function. For example:
  ```lua
  function Prompt()
      return "YourName@aos> "
  end
  ```
  Customize `"YourName@aos> "` to your preferred prompt text.

## Step 3: Exit and Run Your Code

- To exit the editor and execute your code, type `.done` and then press Enter.
- Your aos prompt should now display the new custom format.

## Step 4: Save for Future Use (Optional)

- If you wish to use this prompt in future aos sessions, save your script in a Lua file.
- In subsequent sessions, load this script to apply your custom prompt.

## Maximizing Your Prompt

There's a great deal of utility and creativity that can come from customizing your prompt. Several things you can do within your prompt are:

- Tracking the number of unhandled messages you have in your inbox by creating a function that shows how many messages you have.

  ```lua
    --Example:
    function Prompt()
      return "YourName Inbox: [" .. #Inbox .. "] > "
    end
  ```

- Tracking the number of members are within your process ID's chatroom.
- Tracking the balance of a specified token that your process ID holds.

## Conclusion

Now that you understand how to maximize the utility within your Prompt, you've now gained a crucial step to streamlining your ao development experience.


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: cli.md Path: ../ao-cookbook/src/guides/aos/cli.md

Response:
# CLI

There are some command-line arguments you pass to `aos` to do the following:

- [name] - create a new process or loads an existing process for your wallet
- `--load` \<file> - load a file, you can add one or many of this command
- `--cron` \<interval> - only used when creating a process
- `--wallet` \<walletfile> - use a specific wallet

## Managing multiple processes with aos

```sh
aos
```

Starts or connects to a process with the name `default`

```sh
aos chatroom
```

Starts or connects to a process with the name of `chatroom`

```sh
aos treasureRoom
```

Starts or connects to a process with the name of `treasureRoom`

## Load flag

```sh
aos treasureRoom --load greeting.lua --load treasure.lua --load puzzle.lua
```

With the load flag I can load many source files to my process

## CRON Flag

If you want to setup your process to react on a schedule we need to tell ao, we do that when we spawn the process.

```sh
aos chatroom --cron 2-minutes
```

## Tag flags

With the tag flags, you can start a process with some custom tags (for e.g. using them as static environment variables):

```sh
aos chatroom --tag-name Chat-Theme --tag-value Dark --tag-name Chat-Name --tag-value Mychat
```

The command above will add the extra tags to the transaction that spawns your process:

```ts
// process data item tags
[
  ...
  { name: "Chat-Theme", value: "Dark" },
  { name: "Chat-Name", value: "Mychat" }
  ...
]
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: intro.md Path: ../ao-cookbook/src/guides/aos/intro.md

Response:
# Introduction

aos introduces a new approach to building `processes` — asynchronous, parallel-executing smart contracts. The ao computer is a decentralized computer network that allows compute to run anywhere and aos in a unique, interactive shell. You can use aos as your personal operating system, your development environment for building ao processes, and your bot army.

Lets go over some basic commands.

## Variables

If you want to display the contents of any variable through the console, simply type the variable name.

```lua
Name
```

## Inbox

the `Inbox` is a collection of messages that your Process has received.

```lua
Inbox[1]
```

If you want to get a count of messages, just add the `#` infront of `Inbox`.

```lua
#Inbox
```

The process of checking how many messages are in the inbox is a very common pattern. To make this easier, you can create a function that returns the number of messages within the inbox and displays it in the prompt.

Use either `.editor` or `.load file` to load this function on your process.

```lua
function Prompt()
  return "Inbox: " .. #Inbox .. " > "
end
```

**The Expected Results:**

```lua
undefined
Inbox: 2 >
```

Your prompt now has changed to include the number of messages in your inbox.

::: info
The `Inbox` is a Lua table (similar to an array) that contains messages received by your process that were not handled by any Handlers. The `#` operator is used to get the length of a table in Lua - so `#Inbox` returns the total number of unhandled messages currently in your inbox. This is a common Lua syntax pattern for getting the size/length of tables and strings.
:::

## Globals

In aos process there are some Globals that can make development a little more intuitive.

| Name                   | Description                                                                                | Type         |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| Inbox                  | This is a lua Table that stores all the messages that are received and not handlers by any handlers.                                                                              | Table(Array) |
| Send(Message)          | This is a global function that is available in the interactive environment that allows you to send messages to Processes                                                          | function     |
| Spawn(Module, Message) | This is a global function that is available in the aos interactive environment that allows you to spawn processes                                                                 |
| Name                   | a string that is set on init that describes the name of your process                                                                                | string       |
| Owner                  | a string that is set on the init of the process that documents the owner of the process, warning if you change this value, it can brick you ability to interact with your process | string       |
| Handlers               | a lua Table that contains helper functions that allows you to create handlers that execute functionality based on the pattern matching function on inbound messages               | table        |
| Dump                   | a function that takes any lua Table and generates a print friendly output of the data                                                                                | function     |
| Utils                  | a functional utility library with functions like map, reduce, filter                                                                                | module       |
| ao                     | this is a core function library for sending messages and spawing processes                                                                                | module       |

## Modules

In aos there are some built in common lua modules that are already available for you to work with, these modules can be referenced with a "require" function.

| Name    | Description                                                                |
| ------- | -------------------------------------------------------------------------- |
| json    | a json module that allows you to encode and decode json documents          |
| ao      | contains ao specific functions like send and spawn                         |
| .base64 | a base64 module that allows you to encode and decode base64 text           |
| .pretty | a pretty print module using the function tprint to output formatted syntax |
| .utils  | an utility function library                                                |


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: inbox-and-handlers.md Path: ../ao-cookbook/src/guides/aos/inbox-and-handlers.md

Response:
# Understanding the Inbox

In aos, processes are executed in response to messages via handlers. Unhandled messages are routed to the process's Inbox.

## What are Handlers?

A handler is a function that receives and evaluates messages within your process. It acts upon messages by taking them as parameters.

Handlers are defined using the `Handlers.add()` function.

The function takes three parameters:

1. Name of the Handler
2. Matcher function
3. Handle function

```lua
Handlers.add("name",
  function (Msg)
    -- Does this message match (return true or false)
    return Msg.Action == "Register"
  end,
  function (Msg)
    print("Registered User.")
    table.insert(Members, Msg.From)
    ao.send({Target = Msg.From, Data = "Registered."})
  end
)
```

## What about Inboxes?

An inbox is a storage area for messages that have not yet been processed. Think of it as a holding zone for incoming, or "inbound," items awaiting handling. Once a message is processed, it's no longer considered "inbound" and thus leaves the inbox.

> Example: Consider the inbox like your voicemail. Just as an unanswered phone call is directed to voicemail for you to address later, messages that your Process doesn't immediately handle are sent to the inbox. This way, unhandled messages are stored until you're ready to process them.

## Summary

Initially, it might seem like all messages are meant to land in your Inbox, which can be puzzling if they disappear after being handled. The analogy of a voicemail should clarify this: much like calls you answer don't go to voicemail, messages you handle won't appear in your Inbox. This illustrates the roles of both the Inbox and Handlers.


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: faq.md Path: ../ao-cookbook/src/guides/aos/faq.md

Response:
# FAQ

## Ownership

  Understanding Process Ownership

Start a new process with the aos console, the ownership of the process is set to your wallet address. **aos** uses the **Owner** global variable to define the ownership of the process. If you wish to transfer ownership or lock the process so that no one can own, you simply modify the **Owner** variable to another wallet address or set it to **nil**.

## JSON

  encoding data as json

When sending data to another process or an external service, you may want to use JSON as a way to encode the data for recipients. Using the json module in lua, you can **encode** and **decode** pure lua tables that contain values.

```lua
Send({Target = Router, Data = require('json').encode({hello = "world"})})
```

## Send vs ao.send

  When to use Send vs ao.send

Both functions send a message to a process, the difference is ao.send returns the message, in case you want to log it or troubleshoot. The **Send** function is intended to be used in the console for easier access. It is preferred to use **ao.send** in the **handlers**. But they are both interchangeable in **aos**.


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: chatroom.md Path: ../ao-cookbook/src/guides/aos/blueprints/chatroom.md

Response:
# Chatroom Blueprint

The Chatroom Blueprint is a predesigned template that helps you quickly build a chatroom in `ao`. It is a great way to get started and can be customized to fit your needs.

## Unpacking the Chatroom Blueprint

- **Members**: The `Members` array is used to store the users who have registered to the chatroom.

- **Register Handler**: The `register` handler allows processes to join the chatroom. When a process sends a message with the tag `Action = "Register"`, the handler will add the process to the `Members` array and send a message back to the process confirming the registration.

- **Broadcast Handler**: The `broadcast` handler allows processes to send messages to all the members of the chatroom. When a process sends a message with the tag `Action = "Broadcast"`, the handler will send the message to all the members of the chatroom.

### How To Use:

1. Open your preferred text editor.
2. Open the Terminal.
3. Start your `aos` process.
4. Type in `.load-blueprint chatroom`

### Verify the Blueprint is Loaded:

Type in `Handlers.list` to see the newly loaded handlers.

## What's in the Chatroom Blueprint:

```lua
Members = Members or {}

Handlers.add(
  "register",
  Handlers.utils.hasMatchingTag("Action", "Register"),
  function (msg)
    table.insert(Members, msg.From)
    Handlers.utils.reply("registered")(msg)
  end
)

Handlers.add(
  "broadcast",
  Handlers.utils.hasMatchingTag("Action", "Broadcast"),
  function (msg)
    for _, recipient in ipairs(Members) do
      ao.send({Target = recipient, Data = msg.Data})
    end
    Handlers.utils.reply("Broadcasted.")(msg)
  end
)
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: token.md Path: ../ao-cookbook/src/guides/aos/blueprints/token.md

Response:
# Token Blueprint

The Token Blueprint is a predesigned template that helps you quickly build a token in `ao`. It is a great way to get started and can be customized to fit your needs.

## Unpacking the Token Blueprint

- **Balances**: The `Balances` array is used to store the token balances of the participants.

- **Info Handler**: The `info` handler allows processes to retrieve the token parameters, like Name, Ticker, Logo, and Denomination.

- **Balance Handler**: The `balance` handler allows processes to retrieve the token balance of a participant.

- **Balances Handler**: The `balances` handler allows processes to retrieve the token balances of all participants.

- **Transfer Handler**: The `transfer` handler allows processes to send tokens to another participant.

- **Mint Handler**: The `mint` handler allows processes to mint new tokens.

- **Total Supply Handler**: The `totalSupply` handler allows processes to retrieve the total supply of the token.

- **Burn Handler**: The `burn` handler allows processes to burn tokens.

### How To Use:

1. Open your preferred text editor.
2. Open the Terminal.
3. Start your `aos` process.
4. Type in `.load-blueprint token`

### Verify the Blueprint is Loaded:

Type in `Handlers.list` to see the newly loaded handlers.

## What's in the Token Blueprint:

```lua
local bint = require('.bint')(256)
--[[
  This module implements the ao Standard Token Specification.

  Terms:
    Sender: the wallet or Process that sent the Message

  It will first initialize the internal state, and then attach handlers,
    according to the ao Standard Token Spec API:

    - Info(): return the token parameters, like Name, Ticker, Logo, and Denomination

    - Balance(Target?: string): return the token balance of the Target. If Target is not provided, the Sender
        is assumed to be the Target

    - Balances(): return the token balance of all participants

    - Transfer(Target: string, Quantity: number): if the Sender has a sufficient balance, send the specified Quantity
        to the Target. It will also issue a Credit-Notice to the Target and a Debit-Notice to the Sender

    - Mint(Quantity: number): if the Sender matches the Process Owner, then mint the desired Quantity of tokens, adding
        them the Processes' balance
]]
--
local json = require('json')

--[[
  utils helper functions to remove the bint complexity.
]]
--

local utils = {
  add = function(a, b)
    return tostring(bint(a) + bint(b))
  end,
  subtract = function(a, b)
    return tostring(bint(a) - bint(b))
  end,
  toBalanceValue = function(a)
    return tostring(bint(a))
  end,
  toNumber = function(a)
    return bint.tonumber(a)
  end
}

--[[
     Initialize State

     ao.id is equal to the Process.Id
   ]]
--
Variant = "0.0.3"

-- token should be idempotent and not change previous state updates
Denomination = Denomination or 12
Balances = Balances or { [ao.id] = utils.toBalanceValue(10000 * 10 ^ Denomination) }
TotalSupply = TotalSupply or utils.toBalanceValue(10000 * 10 ^ Denomination)
Name = Name or 'Points Coin'
Ticker = Ticker or 'PNTS'
Logo = Logo or 'SBCCXwwecBlDqRLUjb8dYABExTJXLieawf7m2aBJ-KY'

--[[
     Add handlers for each incoming Action defined by the ao Standard Token Specification
   ]]
--

--[[
     Info
   ]]
--
Handlers.add('info', "Info", function(msg)
  msg.reply({
    Name = Name,
    Ticker = Ticker,
    Logo = Logo,
    Denomination = tostring(Denomination)
  })
end)

--[[
     Balance
   ]]
--
Handlers.add('balance', "Balance", function(msg)
  local bal = '0'

  -- If not Recipient is provided, then return the Senders balance
  if (msg.Tags.Recipient) then
    if (Balances[msg.Tags.Recipient]) then
      bal = Balances[msg.Tags.Recipient]
    end
  elseif msg.Tags.Target and Balances[msg.Tags.Target] then
    bal = Balances[msg.Tags.Target]
  elseif Balances[msg.From] then
    bal = Balances[msg.From]
  end

  msg.reply({
    Balance = bal,
    Ticker = Ticker,
    Account = msg.Tags.Recipient or msg.From,
    Data = bal
  })
end)

--[[
     Balances
   ]]
--
Handlers.add('balances', "Balances",
  function(msg) msg.reply({ Data = json.encode(Balances) }) end)

--[[
     Transfer
   ]]
--
Handlers.add('transfer', "Transfer", function(msg)
  assert(type(msg.Recipient) == 'string', 'Recipient is required!')
  assert(type(msg.Quantity) == 'string', 'Quantity is required!')
  assert(bint.__lt(0, bint(msg.Quantity)), 'Quantity must be greater than 0')

  if not Balances[msg.From] then Balances[msg.From] = "0" end
  if not Balances[msg.Recipient] then Balances[msg.Recipient] = "0" end

  if bint(msg.Quantity) <= bint(Balances[msg.From]) then
    Balances[msg.From] = utils.subtract(Balances[msg.From], msg.Quantity)
    Balances[msg.Recipient] = utils.add(Balances[msg.Recipient], msg.Quantity)

    --[[
         Only send the notifications to the Sender and Recipient
         if the Cast tag is not set on the Transfer message
       ]]
    --
    if not msg.Cast then
      -- Debit-Notice message template, that is sent to the Sender of the transfer
      local debitNotice = {
        Action = 'Debit-Notice',
        Recipient = msg.Recipient,
        Quantity = msg.Quantity,
        Data = Colors.gray ..
            "You transferred " ..
            Colors.blue .. msg.Quantity .. Colors.gray .. " to " .. Colors.green .. msg.Recipient .. Colors.reset
      }
      -- Credit-Notice message template, that is sent to the Recipient of the transfer
      local creditNotice = {
        Target = msg.Recipient,
        Action = 'Credit-Notice',
        Sender = msg.From,
        Quantity = msg.Quantity,
        Data = Colors.gray ..
            "You received " ..
            Colors.blue .. msg.Quantity .. Colors.gray .. " from " .. Colors.green .. msg.From .. Colors.reset
      }

      -- Add forwarded tags to the credit and debit notice messages
      for tagName, tagValue in pairs(msg) do
        -- Tags beginning with "X-" are forwarded
        if string.sub(tagName, 1, 2) == "X-" then
          debitNotice[tagName] = tagValue
          creditNotice[tagName] = tagValue
        end
      end

      -- Send Debit-Notice and Credit-Notice
      msg.reply(debitNotice)
      Send(creditNotice)
    end
  else
    msg.reply({
      Action = 'Transfer-Error',
      ['Message-Id'] = msg.Id,
      Error = 'Insufficient Balance!'
    })
  end
end)

--[[
    Mint
   ]]
--
Handlers.add('mint', "Mint", function(msg)
  assert(type(msg.Quantity) == 'string', 'Quantity is required!')
  assert(bint(0) < bint(msg.Quantity), 'Quantity must be greater than zero!')

  if not Balances[ao.id] then Balances[ao.id] = "0" end

  if msg.From == ao.id then
    -- Add tokens to the token pool, according to Quantity
    Balances[msg.From] = utils.add(Balances[msg.From], msg.Quantity)
    TotalSupply = utils.add(TotalSupply, msg.Quantity)
    msg.reply({
      Data = Colors.gray .. "Successfully minted " .. Colors.blue .. msg.Quantity .. Colors.reset
    })
  else
    msg.reply({
      Action = 'Mint-Error',
      ['Message-Id'] = msg.Id,
      Error = 'Only the Process Id can mint new ' .. Ticker .. ' tokens!'
    })
  end
end)

--[[
     Total Supply
   ]]
--
Handlers.add('totalSupply', "Total-Supply", function(msg)
  assert(msg.From ~= ao.id, 'Cannot call Total-Supply from the same process!')

  msg.reply({
    Action = 'Total-Supply',
    Data = TotalSupply,
    Ticker = Ticker
  })
end)

--[[
 Burn
]] --
Handlers.add('burn', 'Burn', function(msg)
  assert(type(msg.Quantity) == 'string', 'Quantity is required!')
  assert(bint(msg.Quantity) <= bint(Balances[msg.From]), 'Quantity must be less than or equal to the current balance!')

  Balances[msg.From] = utils.subtract(Balances[msg.From], msg.Quantity)
  TotalSupply = utils.subtract(TotalSupply, msg.Quantity)

  msg.reply({
    Data = Colors.gray .. "Successfully burned " .. Colors.blue .. msg.Quantity .. Colors.reset
  })
end)
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: index.md Path: ../ao-cookbook/src/guides/aos/blueprints/index.md

Response:
---
prev:
  text: "Build a Token"
  link: "../token"
next:
  text: "Token Blueprint"
  link: "./token"
---

# Blueprints

Blueprints are predesigned templates that help you quickly build in `ao`. They are a great way to get started and can be customized to fit your needs.

## Available Blueprints

- [Chatroom](chatroom)
- [CRED Utils](cred-utils)
- [Staking](staking)
- [Token](token)
- [Voting](voting)


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: cred-utils.md Path: ../ao-cookbook/src/guides/aos/blueprints/cred-utils.md

Response:
# CRED Utils Blueprint

::: warning CRED is now deprecated
CRED was a token used during ao's legacynet phase to reward early developers. It is no longer earnable or redeemable.
:::

The CRED Utils Blueprint is a predesigned template that helps you quickly check your CRED balance in `ao` legacynet.

## Unpacking the CRED Utils Blueprint

### The `CRED` Metatable

- **CRED.balance**: Evaluating `CRED.balance` will print your process's last known balance of your CRED.
  If you have never fetched your CRED balance before, it will be fetched automatically.
  If you think your CRED has recently changed, consider running `CRED.update` first.

- **CRED.process**: Evaluating `CRED.process` will print the process ID of the CRED token issuer.

- **CRED.send**: Invoking `CRED.send(targetProcessId, amount)` like a function will transfer CRED from your `ao` process
  to another `ao` process.

  - `targetProcessId`: **string**: the 43-character process ID of the recipient.
  - `amount`: **integer**: The quantity of CRED units to send. 1 CRED === 1000 CRED units.

- **CRED.update**: Evaluating `CRED.update` will fetch your latest CRED balance by sending a message to the CRED
  issuer process. The `UpdateCredBalance` handler (see below) will ingest the response message.

### Handler Definitions

- **Credit Handler**: The `CRED_Credit` handler allows the CRED issuer process (and `aos`) to automatically notify you when your
  CRED balance increase.

- **Debit Handler**: The `CRED_Debit` handler allows the CRED issuer process (and `aos`) to automatically notify you when your
  CRED balance decreases.

- **Update Balance Handler**: The `UpdateCredBalance` handler ingests the response to any `CRED.update` requests.

## How To Use the Blueprint

1. Open the Terminal.
2. Start your `aos` process.
3. Type in `.load-blueprint credUtils`
4. Type in `CRED.balance`

## What's in the CRED Utils Blueprint:

See the `aos` [source code on GitHub](https://github.com/permaweb/aos/blob/main/blueprints/credUtils.lua)
for the blueprint shipped in the latest version of `aos`.

```lua
CRED_PROCESS = "Sa0iBLPNyJQrwpTTG-tWLQU-1QeUAJA73DdxGGiKoJc"

_CRED = { balance = "Your CRED balance has not been checked yet. Updating now." }

local credMeta = {
    __index = function(t, key)
        -- sends CRED balance request
        if key == "update" then
            Send({ Target = CRED_PROCESS, Action = "Balance", Tags = { ["Target"] = ao.id } })
            return "Balance update requested."
            -- prints local CRED balance, requests it if not set
        elseif key == "balance" then
            if _CRED.balance == "Your CRED balance has not been checked yet. Updating now." then
                Send({ Target = CRED_PROCESS, Action = "Balance", Tags = { ["Target"] = ao.id } })
            end
            return _CRED.balance
            -- prints CRED process ID
        elseif key == "process" then
            return CRED_PROCESS
            -- tranfers CRED
        elseif key == "send" then
            return function(target, amount)
                -- ensures amount is string
                amount = tostring(amount)
                print("sending " .. amount .. "CRED to " .. target)
                Send({ Target = CRED_PROCESS, Action = "Transfer", ["Recipient"] = target, ["Quantity"] = amount })
            end
        else
            return nil
        end
    end
}

CRED = setmetatable({}, credMeta)

-- Function to evaluate if a message is a balance update
local function isCredBalanceMessage(msg)
    if msg.From == CRED_PROCESS and msg.Tags.Balance then
        return true
    else
        return false
    end
end

-- Function to evaluate if a message is a Debit Notice
local function isDebitNotice(msg)
    if msg.From == CRED_PROCESS and msg.Tags.Action == "Debit-Notice" then
        return true
    else
        return false
    end
end

-- Function to evaluate if a message is a Credit Notice
local function isCreditNotice(msg)
    if msg.From == CRED_PROCESS and msg.Tags.Action == "Credit-Notice" then
        return true
    else
        return false
    end
end

local function formatBalance(balance)
    -- Ensure balance is treated as a string
    balance = tostring(balance)
    -- Check if balance length is more than 3 to avoid unnecessary formatting
    if #balance > 3 then
        -- Insert dot before the last three digits
        balance = balance:sub(1, -4) .. "." .. balance:sub(-3)
    end
    return balance
end

-- Handles Balance messages
Handlers.add(
    "UpdateCredBalance",
    isCredBalanceMessage,
    function(msg)
        local balance = nil
        if msg.Tags.Balance then
            balance = msg.Tags.Balance
        end
        -- Format the balance if it's not set
        if balance then
            -- Format the balance by inserting a dot after the first three digits from the right
            local formattedBalance = formatBalance(balance)
            _CRED.balance = formattedBalance
            print("CRED Balance updated: " .. _CRED.balance)
        else
            print("An error occurred while updating CRED balance")
        end
    end
)

-- Handles Debit notices
Handlers.add(
    "CRED_Debit",
    isDebitNotice,
    function(msg)
        print(msg.Data)
    end
)

-- Handles Credit notices
Handlers.add(
    "CRED_Credit",
    isCreditNotice,
    function(msg)
        print(msg.Data)
    end
)
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: voting.md Path: ../ao-cookbook/src/guides/aos/blueprints/voting.md

Response:
# Voting Blueprint

The Voting Blueprint is a predesigned template that helps you quickly build a voting system in `ao`. It is a great way to get started and can be customized to fit your needs.

## Prerequisites

The Staking Blueprint requires the [Token Blueprint](./token.md) to be loaded, first.

## Unpacking the Voting Blueprint

- **Balances**: The `Balances` array is used to store the token balances of the participants.

- **Votes**: The `Votes` array is used to store the votes of the participants.

- **Vote Action Handler**: The `vote` handler allows processes to vote. When a process sends a message with the tag `Action = "Vote"`, the handler will add the vote to the `Votes` array and send a message back to the process confirming the vote.

- **Finalization Handler**: The `finalize` handler allows processes to finalize the voting process. When a process sends a message with the tag `Action = "Finalize"`, the handler will process the votes and finalize the voting process.

### How To Use:

1. Open your preferred text editor.
2. Open the Terminal.
3. Start your `aos` process.
4. Type in `.load-blueprint voting`

### Verify the Blueprint is Loaded:

Type in `Handlers.list` to see the newly loaded handlers.

## What's in the Voting Blueprint:

```lua
Balances = Balances or {}
Votes = Votes or {}

-- Vote Action Handler
Handlers.vote = function(msg)
  local quantity = Stakers[msg.From].amount
  local target = msg.Tags.Target
  local side = msg.Tags.Side
  local deadline = tonumber(msg['Block-Height']) + tonumber(msg.Tags.Deadline)
  assert(quantity > 0, "No staked tokens to vote")
  Votes[target] = Votes[target] or { yay = 0, nay = 0, deadline = deadline }
  Votes[target][side] = Votes[target][side] + quantity
end

-- Finalization Handler
local finalizationHandler = function(msg)
  local currentHeight = tonumber(msg['Block-Height'])
  -- Process voting
  for target, voteInfo in pairs(Votes) do
      if currentHeight >= voteInfo.deadline then
          if voteInfo.yay > voteInfo.nay then
              print("Handle Vote")
          end
          -- Clear the vote record after processing
          Votes[target] = nil
      end
  end
end

-- wrap function to continue handler flow
local function continue(fn)
  return function (msg)
    local result = fn(msg)
    if (result) == -1 then
      return 1
    end
    return result
  end
end

Handlers.add("vote",
  continue(Handlers.utils.hasMatchingTag("Action", "Vote")), Handlers.vote)
-- Finalization handler should be called for every message
Handlers.add("finalize", function (msg) return -1 end, finalizationHandler)
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: staking.md Path: ../ao-cookbook/src/guides/aos/blueprints/staking.md

Response:
# Staking Blueprint

The Staking Blueprint is a predesigned template that helps you quickly build a staking system in `ao`. It is a great way to get started and can be customized to fit your needs.

## Prerequisites

The Staking Blueprint requires the [Token Blueprint](./token.md) to be loaded, first.

## Unpacking the Staking Blueprint

- **Stakers**: The `Stakers` array is used to store the staked tokens of the participants.

- **Unstaking**: The `Unstaking` array is used to store the unstaking requests of the participants.

- **Stake Action Handler**: The `stake` handler allows processes to stake tokens. When a process sends a message with the tag `Action = "Stake"`, the handler will add the staked tokens to the `Stakers` array and send a message back to the process confirming the staking.

- **Unstake Action Handler**: The `unstake` handler allows processes to unstake tokens. When a process sends a message with the tag `Action = "Unstake"`, the handler will add the unstaking request to the `Unstaking` array and send a message back to the process confirming the unstaking.

- **Finalization Handler**: The `finalize` handler allows processes to finalize the staking process. When a process sends a message with the tag `Action = "Finalize"`, the handler will process the unstaking requests and finalize the staking process.

### How To Use:

1. Open your preferred text editor.
2. Open the Terminal.
3. Start your `aos` process.
4. Type in `.load-blueprint staking`

### Verify the Blueprint is Loaded:

Type in `Handlers.list` to see the newly loaded handlers.

## What's in the Staking Blueprint:

```lua
Stakers = Stakers or {}
Unstaking = Unstaking or {}

-- Stake Action Handler
Handlers.stake = function(msg)
  local quantity = tonumber(msg.Tags.Quantity)
  local delay = tonumber(msg.Tags.UnstakeDelay)
  local height = tonumber(msg['Block-Height'])
  assert(Balances[msg.From] and Balances[msg.From] >= quantity, "Insufficient balance to stake")
  Balances[msg.From] = Balances[msg.From] - quantity
  Stakers[msg.From] = Stakers[msg.From] or {}
  Stakers[msg.From].amount = (Stakers[msg.From].amount or 0) + quantity
  Stakers[msg.From].unstake_at = height + delay
end

-- Unstake Action Handler
Handlers.unstake = function(msg)
  local quantity = tonumber(msg.Tags.Quantity)
  local stakerInfo = Stakers[msg.From]
  assert(stakerInfo and stakerInfo.amount >= quantity, "Insufficient staked amount")
  stakerInfo.amount = stakerInfo.amount - quantity
  Unstaking[msg.From] = {
      amount = quantity,
      release_at = stakerInfo.unstake_at
  }
end

-- Finalization Handler
local finalizationHandler = function(msg)
  local currentHeight = tonumber(msg['Block-Height'])
  -- Process unstaking
  for address, unstakeInfo in pairs(Unstaking) do
      if currentHeight >= unstakeInfo.release_at then
          Balances[address] = (Balances[address] or 0) + unstakeInfo.amount
          Unstaking[address] = nil
      end
  end

end

-- wrap function to continue handler flow
local function continue(fn)
  return function (msg)
    local result = fn(msg)
    if (result) == -1 then
      return 1
    end
    return result
  end
end

-- Registering Handlers
Handlers.add("stake",
  continue(Handlers.utils.hasMatchingTag("Action", "Stake")), Handlers.stake)
Handlers.add("unstake",
  continue(Handlers.utils.hasMatchingTag("Action", "Unstake")), Handlers.unstake)
-- Finalization handler should be called for every message
Handlers.add("finalize", function (msg) return -1 end, finalizationHandler)
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: json.md Path: ../ao-cookbook/src/guides/aos/modules/json.md

Response:
# JSON

The JSON module allows you to encode and decode objects using JavaScript Object Notation.

### Example usage

```lua
local json = require("json")

json.encode({
  a_string = "This is a string",
  nums = { 1, 2, 3 }
})
```

## Module functions

### `encode()`

This function returns a string representation of a Lua object in JSON.

- **Parameters:**
  - `val`: `{any}` The object to format as JSON
- **Returns:** JSON string representation of the provided object

#### Example

```lua
--[[
  prints:
  "[{"name":"John Doe","age":23},{"name":"Bruce Wayne",age:34}]"
]]--
print(json.encode({
  { name = "John Doe", age = 23 },
  { name = "Bruce Wayne", age = 34 }
}))

-- prints "false"
print(json.encode(false))
```

### `decode()`

The function takes a JSON string and turns it into a Lua object.

- **Parameters:**
  - `val`: `{any}` The JSON string to decode
- **Returns:** Lua object corresponding to the JSON string (throws an error for invalid JSON strings)

#### Example

```lua
--[[
  creates the following table:
  { hello = "world" }
]]--
json.decode('{ "hello": "world" }')

-- creates a boolean with true value
json.decode("true")
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: utils.md Path: ../ao-cookbook/src/guides/aos/modules/utils.md

Response:
# Utils

A utility library for generic table manipulation and validation. It supports both curry-styled and traditional programming.

> **Note**: It is important to verify that the inputs provided to the following functions match the expected types.

### Example usage

```lua
local utils = require(".utils")

local totalSupply = utils.reduce(
  function (acc, v) return acc + v end,
  0,
  { 2, 4, 9 }
)

print(totalSupply) -- prints 15
```

## Module functions

### `concat()`

This function concatenates array `b` to array `a`.

- **Parameters:**
  - `a`: `{table}` The base array
  - `b`: `{table}` The array to concat to the base array
- **Returns:** An unified array of `a` and `b`

#### Examples

```lua
-- returns { 1, 2, 3, 4, 5, 6 }
concat({ 1, 2, 3 })({ 4, 5, 6 }) -- curry syntax

-- returns { "hello", "world", "and", "you" }
concat({ "hello", "world" }, { "and", "you" }) -- traditional syntax
```

### `reduce()`

This function executes the provided reducer function for all array elements, finally providing one (unified) result.

- **Parameters:**
  - `fn`: `{function}` The reducer function. It receives the previous result, the current element's value and key in this order
  - `initial`: `{any}` An optional initial value
  - `t`: `{table}` The array to reduce
- **Returns:** A single result from running the reducer across all table elements

#### Examples

```lua
local sum = utils.reduce(
  function (acc, v) return acc + v end,
  0,
  { 1, 2, 3 }
)

print(sum) -- prints 6
```

```lua
local sum = utils
  .reduce(function (acc, v) return acc + v end)(0)({ 5, 4, 3 })

print(sum) -- prints 12
```

### `map()`

This function creates a new array filled with the results of calling the provided map function on each element in the provided array.

- **Parameters:**
  - `fn`: `{function}` The map function. It receives the current array element and key
  - `data`: `{table}` The array to map
- **Returns:** A new array composed of the results of the map function

#### Examples

```lua
-- returns { "Odd", "Even", "Odd" }
utils.map(
  function (val, key)
    return (val % 2 == 0 and "Even") or "Odd"
  end,
  { 3, 4, 7 }
)
```

```lua
-- returns { 4, 8, 12 }
utils.map(function (val, key) return val * 2 end)({ 2, 4, 6 })
```

### `filter()`

This function creates a new array from a portion of the original, only keeping the elements that passed a provided filter function's test.

- **Parameters:**
  - `fn`: `{function}` The filter function. It receives the current array element and should return a boolean, deciding whether the element should be kept (`true`) or filtered out (`false`)
  - `data`: `{table}` The array to filter
- **Returns:** The new filtered array

#### Examples

```lua
-- keeps even numbers
utils.filter(
  function (val) return val % 2 == 0 end,
  { 3, 4, 7 }
)
```

```lua
-- keeps only numbers
utils.filter(
  function (val) return type(val) == "number" end,
  { "hello", "world", 13, 44 }
)
```

### `find()`

This function returns the first element that matches in a provided function.

- **Parameters:**
  - `fn`: `{function}` The find function that receives the current element and returns `true` if it matches, `false` if it doesn't
  - `t`: `{table}` The array to find an element in
- **Returns:** The found element or `nil` if no element matched

#### Examples

```lua
local users = {
  { name = "John", age = 50 },
  { name = "Victor", age = 37 },
  { name = "Maria", age = 33 }
}

-- returns the user "John"
utils.find(
  function (val) return user.name == "John" end,
  users
)
```

```lua
-- returns the user "Maria"
utils.find(function (val) return user.age == 33 end)(users)
```

### `reverse()`

Transforms an array into reverse order.

- **Parameters:**
  - `data`: `{table}` The array to reverse
- **Returns:** The original array in reverse order

#### Example

```lua
-- is: { 3, 2, 1 }
utils.reverse({ 1, 2, 3 })
```

### `includes()`

Determines whether a value is part of an array.

- **Parameters:**
  - `val`: `{any}` The element to check for
  - `t`: `{table}` The array to check in
- **Returns:** A boolean indicating whether or not the provided value is part of the array

#### Examples

```lua
-- this is true
utils.includes("John", { "Victor", "John", "Maria" })
```

```lua
-- this is false
utils.includes(4)({ 3, 5, 7 })
```

### `keys()`

Returns the keys of a table.

- **Parameters:**
  - `table`: `{table}` The table to get the keys for
- **Returns:** An array of keys

#### Example

```lua
-- returns { "hello", "name" }
utils.keys({ hello = "world", name = "John" })
```

### `values()`

Returns the values of a table.

- **Parameters:**
  - `table`: `{table}` The table to get the values for
- **Returns:** An array of values

#### Example

```lua
-- returns { "world", "John" }
utils.values({ hello = "world", name = "John" })
```

### `propEq()`

Checks if a specified property of a table equals with the provided value.

- **Parameters:**
  - `propName`: `{string}` The name of the property to compare
  - `value`: `{any}` The value to compare to
  - `object`: `{table}` The object to select the property from
- **Returns:** A boolean indicating whether the property value equals with the provided value or not

#### Examples

```lua
local user = { name = "John", age = 50 }

-- returns true
utils.propEq("age", 50, user)
```

```lua
local user = { name = "Maria", age = 33 }

-- returns false
utils.propEq("age", 45, user)
```

### `prop()`

Returns the property value that belongs to the property name provided from an object.

- **Parameters:**
  - `propName`: `{string}` The name of the property to get
  - `object`: `{table}` The object to select the property value from
- **Returns:** The property value or `nil` if it was not found

#### Examples

```lua
local user = { name = "Maria", age = 33 }

-- returns "Maria"
utils.prop("name", user)
```

```lua
local user = { name = "John", age = 50 }

-- returns 50
utils.prop("age")(user)
```

### `compose()`

This function allows you to chain multiple array mutations together and execute them in reverse order on the provided array.

- **Parameters:**
  - `...`: `{function[]}` The array mutations
  - `v`: `{table}` The object to execute the provided functions on
- **Returns:** The result from the provided mutations

#### Examples

```lua
-- returns 12
utils.compose(
  utils.reduce(function (acc, val) return acc + val end, 0),
  utils.map(function (val) return val * 2 end)
)({ 1, 2, 3 })
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: ao.md Path: ../ao-cookbook/src/guides/aos/modules/ao.md

Response:
# ao

Built-in global library for process communication and management. The `ao` object provides core functionality for sending messages, spawning processes, and logging.

## Core Functions

### `ao.send(msg)`

Sends a message to another process. See the [ao.send](/references/ao.md#ao-send-msg-message) reference for more information.

```lua
-- Send a simple message
ao.send({
  Target = "usjm4PCxUd5mtaon7zc97-dt-3qf67yPyqgzLnLqk5A",
  Data = "Hello!",
  Tags = {
    Action = "Greeting"
  }
})

-- Root-level fields are automatically converted to tags
ao.send({
  Target = "usjm4PCxUd5mtaon7zc97-dt-3qf67yPyqgzLnLqk5A",
  Data = "Transfer tokens",
  Action = "Transfer",     -- Becomes a tag
  Quantity = "1045"       -- Becomes a tag
})
```

### `ao.spawn(module: string, spawn: table)`

Creates a new process from a module. See the [ao.spawn](/references/ao.md#ao-spawn-module-string-spawn-spawn) reference for more information.

```lua
-- Spawn a calculator process
ao.spawn("n0BFH80b73mi9VAWUzyuG9gEC3LI2zU2BFxum0N8A9s", {
  Data = { initial = "state" },
  Tags = {
    ["Process-Type"] = "calculator"
  }
})
```

### `ao.log(string|table)`

Logs messages or data that can be read by process callers.

```lua
-- Log a debug message
ao.log("Processing transfer...")

-- Log structured data
ao.log({
  event = "transfer_complete",
  amount = 100,
  recipient = "addr123..."
})
```

## Environment

The `ao.env` variable contains process initialization info like ID, owner, and tags.

```lua
-- Access process info
local processId = ao.env.Process.Id
local owner = ao.env.Process.Owner
```

For the complete API reference including all properties and functions, see the [ao reference documentation](/references/ao.md).


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: index.md Path: ../ao-cookbook/src/guides/aos/modules/index.md

Response:
---
prev:
  text: "Staking Blueprint"
  link: "../blueprints/staking"
next:
  text: "JSON"
  link: "./json"
---

# Modules

Documentation on all the built-in modules for aos.

## Available Modules

- [JSON](json)
- [ao](ao)
- [crypto](crypto)
- [Base64](base64)
- [pretty](pretty)
- [Utils](utils)


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: pretty.md Path: ../ao-cookbook/src/guides/aos/modules/pretty.md

Response:
# Pretty

This module allows printing formatted, human-friendly and readable syntax.

## Module functions

### `tprint()`

Returns a formatted string of the structure of the provided table.

- **Parameters:**
  - `tbl`: `{table}` The table to format
  - `indent`: `{number}` Optional indentation of each level of the table
- **Returns:** Table structure formatted as a string

#### Examples

```lua
local pretty = require(".pretty")

local formatted = pretty.tprint({
  name = "John Doe",
  age = 22,
  friends = { "Maria", "Victor" }
}, 2)

-- prints the formatted table structure
print(formatted)
```


Prompt: This is a Markdown documentation from the AO documentation repository. Filename: base64.md Path: ../ao-cookbook/src/guides/aos/modules/base64.md

Response:
# Base64

A small `base64` module to encode or decode base64 text.

> **Note:** It is recommended to enable caching for large chunks of texts for up to x2 optimization.

### Example usage

```lua
local base64 = require(".base64")

local str = "This will be encoded"

-- is: "VGhpcyB3aWxsIGJlIGVuY29kZWQ="
local encoded = base64.encode(str)

-- is: "This will be encoded"
local decoded = base64.decode(encoded)

assert(decoded == str)
```

## Module functions

### `encode()`

This function encodes the provided string using the default encoder table. The encoder can be customized and a cache is available for larger chunks of data.

- **Parameters:**
  - `str`: `{string}` The string to encode
  - `encoder`: `{table}` Optional custom encoding table
  - `usecache`: `{boolean}` Optional cache for large strings (turned off by default)
- **Returns:** Base64 encoded string

#### Examples

```lua
-- prints: "SGVsbG8gd29ybGQ="
print(base64.encode("Hello world"))

-- customize encoder and allow caching
base64.encode(
  "Hello world",
  base64.makeencoder(nil, "-"),
  true
)
```

### `decode()`

This function decodes the provided base64 encoded string using the default decoder table. The decoder can be customized and a cache is also available here.

- **Parameters:**
  - `str`: `{string}` The base64 encoded string to decode
  - `decoder`: `{table}` Optional custom decoding table
  - `usecache`: `{boolean}` Optional cache for large strings (turned off by default)
- **Returns:** Decoded string

#### Examples

```lua
-- prints: "Hello world"
print(base64.decode("SGVsbG8gd29ybGQ="))

-- customize decoder and allow caching
base64.decode(
  "SGVsbG8gd29ybGQ=",
  base64.makedecoder(nil, "-"),
  true
)
```

### `makeencoder()`

Allows creating a new encoder table to customize the [`encode()`](#encode) function's result.

- **Parameters:**
  - `s62`: `{string}` Optional custom char for 62 (`+` by default)
  - `s63`: `{string}` Optional custom char for 63 (`/` by default)
  - `spad`: `{string}` Optional custom padding char (`=` by default)
- **Returns:** Custom encoder table

#### Examples

```lua
-- create custom encoder
local encoder = base64.makeencoder(nil, nil, "~")

-- prints "SGVsbG8gd29ybGQ~" instead of "SGVsbG8gd29ybGQ="
print(base64.encode("Hello world", encoder))
```

### `makedecoder()`

Allows creating a new decoder table to be able to decode [custom-encoded](#makeencoder) base64 strings.

- **Parameters:**
  - `s62`: `{string}` Optional custom char for 62 (`+` by default)
  - `s63`: `{string}` Optional custom char for 63 (`/` by default)
  - `spad`: `{string}` Optional custom padding char (`=` by default)
- **Returns:** Custom decoder table

#### Examples

```lua
local encoder = base64.makeencoder(nil, nil, "~")
local decoder = base64.makedecoder(nil, nil, "~")

-- "SGVsbG8gd29ybGQ~"
local encoded = base64.encode("Hello world", encoder)

-- prints "Hello world"
print(base64.decode(encoded, decoder))
```


Prompt:
This is a Markdown documentation from the AO documentation repository. Filename: crypto.md Path: ../ao-cookbook/src/guides/aos/modules/crypto.md
Note: This content continues in the next part.

Response:
# crypto

## Overview

The `crypto` module provides a set of cryptographic primitives like digests, ciphers and other cryptographic algorithms in pure Lua. It offers several functionalities to hash, encrypt and decrypt data, simplifying the development of secure communication and data storage. This document will guide you through the module's functionalities, installation, and usage.

## Usage

```lua
local crypto = require(".crypto");
```

## Primitives

1. Digests (sha1, sha2, sha3, keccak, blake2b, etc.)
2. Ciphers (AES, ISSAC, Morus, NORX, etc.)
3. Random Number Generators (ISAAC)
4. MACs (HMAC)
5. KDFs (PBKDF2)
6. Utilities (Array, Stream, Queue, etc.)

---

# Digests

## MD2

Calculates the MD2 digest of a given message.

- **Parameters:**

  - `stream` (Stream): The message in form of stream

- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = crypto.utils.stream.fromString("ao")

return crypto.digest.md2(str).asHex() -- 0d4e80edd07bee6c7965b21b25a9b1ea
```

## MD4

Calculates the MD4 digest of a given message.

- **Parameters:**

  - `stream` (Stream): The message in form of stream

- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = crypto.utils.stream.fromString("ao")

return crypto.digest.md4(str).asHex() -- e068dfe3d8cb95311b58be566db66954
```

## MD5

Calculates the MD5 digest of a given message.

- **Parameters:**

  - `stream` (Stream): The message in form of stream

- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = crypto.utils.stream.fromString("ao")

return crypto.digest.md5(str).asHex() -- adac5e63f80f8629e9573527b25891d3
```

## SHA1

Calculates the SHA1 digest of a given message.

- **Parameters:**

  - `stream` (Stream): The message in form of stream

- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = crypto.utils.stream.fromString("ao")

return crypto.digest.sha1(str).asHex() -- c29dd6c83b67a1d6d3b28588a1f068b68689aa1d
```

## SHA2_256

Calculates the SHA2-256 digest of a given message.

- **Parameters:**
  - `stream` (Stream): The message in form of stream
- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = crypto.utils.stream.fromString("ao")

return crypto.digest.sha2_256(str).asHex() -- ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
```

## SHA2_512

Calculates the SHA2-512 digest of a given message.

- **Parameters:**
  - `msg` (string): The message to calculate the digest
- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = "ao"

return crypto.digest.sha2_512(str).asHex() -- 6f36a696b17ce5a71efa700e8a7e47994f3e134a5e5f387b3e7c2c912abe94f94ee823f9b9dcae59af99e2e34c8b4fb0bd592260c6720ee49e5deaac2065c4b1
```

## SHA3

It contains the following functions:

1. `sha3_256`
2. `sha3_512`
3. `keccak256`
4. `keccak512`

Each function calculates the respective digest of a given message.

- **Parameters:**

  - `msg` (string): The message to calculate the digest

- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua

local str = "ao"

crypto.digest.sha3_256(str).asHex()  -- 1bbe785577db997a394d5b4555eec9159cb51f235aec07514872d2d436c6e985
crypto.digest.sha3_512(str).asHex()  -- 0c29f053400cb1764ce2ec555f598f497e6fcd1d304ce0125faa03bb724f63f213538f41103072ff62ddee701b52c73e621ed4d2254a3e5e9a803d83435b704d
crypto.digest.keccak256(str).asHex() -- 76da52eec05b749b99d6e62bb52333c1569fe75284e6c82f3de12a4618be00d6
crypto.digest.keccak512(str).asHex() -- 046fbfad009a12cef9ff00c2aac361d004347b2991c1fa80fba5582251b8e0be8def0283f45f020d4b04ff03ead9f6e7c43cc3920810c05b33b4873b99affdea

```

## Blake2b

Calculates the Blake2b digest of a given message.

- **Parameters:**

  - `data` (string): The data to be hashed.
  - `outlen` (number): The length of the output hash (optional) **default is 64**.
  - `key` (string): The key to be used for hashing (optional) **default is ""**.

- **Returns:** A table containing functions to get digest in different formats.
  - `asBytes()`: The digest as byte table.
  - `asHex()`: The digest as string in hexadecimal format.
  - `asString()`: The digest as string format.

Example:

```lua
local str = "ao"

crypto.digest.blake2b(str).asHex() -- 576701fd79a126f2c414ef94adf1117c88943700f312679d018c29c378b2c807a3412b4e8d51e191c48fb5f5f54bf1bca29a714dda166797b3baf9ead862ae1d
crypto.digest.blake2b(str, 32).asHex() -- 7050811afc947ba7190bb3c0a7b79b4fba304a0de61d529c8a35bdcbbb5544f4
crypto.digest.blake2b(str, 32, "secret_key").asHex() -- 203c101980fdf6cf24d78879f2e3db86d73d91f7d60960b642022cd6f87408f8
```

---

# Ciphers

## AES

The Advanced Encryption Standard (AES) is a symmetric block cipher used to encrypt sensitive information. It has two functions encrypt and decrypt.

### Encrypt

Encrypts a given message using the AES algorithm.

- **Parameters:**

  - `data` (string): The data to be encrypted.
  - `key` (string): The key to be used for encryption.
  - `iv` (string) optional: The initialization vector to be used for encryption. **default is ""**
  - `mode` (string) optional: The mode of operation to be used for encryption. **default is "CBC"**. Available modes are `CBC`, `ECB`, `CFB`, `OFB`, `CTR`.
  - `keyLength` (number) optional: The length of the key to use for encryption. **default is 128**.

- **Returns:** A table containing functions to get encrypted


Prompt:
This is a Markdown documentation from the AO documentation repository. This is a continuation from the previous part. Filename: crypto.md Path: ../ao-cookbook/src/guides/aos/modules/crypto.md
Note: This content continues in the next part.

Response:
cd6f87408f8
```

---

# Ciphers

## AES

The Advanced Encryption Standard (AES) is a symmetric block cipher used to encrypt sensitive information. It has two functions encrypt and decrypt.

### Encrypt

Encrypts a given message using the AES algorithm.

- **Parameters:**

  - `data` (string): The data to be encrypted.
  - `key` (string): The key to be used for encryption.
  - `iv` (string) optional: The initialization vector to be used for encryption. **default is ""**
  - `mode` (string) optional: The mode of operation to be used for encryption. **default is "CBC"**. Available modes are `CBC`, `ECB`, `CFB`, `OFB`, `CTR`.
  - `keyLength` (number) optional: The length of the key to use for encryption. **default is 128**.

- **Returns:** A table containing functions to get encrypted data in different formats.
  - `asBytes()`: The encrypted data as byte table.
  - `asHex()`: The encrypted data as string in hexadecimal format.
  - `asString()`: The encrypted data as string format.

## Decrypt

Decrypts a given message using the AES algorithm.

- **Parameters:**

  - `cipher` (string): Hex Encoded encrypted data.
  - `key` (string): The key to be used for decryption.
  - `iv` (string) optional: The initialization vector to be used for decryption. **default is ""**
  - `mode` (string) optional: The mode of operation to be used for decryption. **default is "CBC"**. Available modes are `CBC`, `ECB`, `CFB`, `OFB`, `CTR`.
  - `keyLength` (number) optional: The length of the key to use for decryption. **default is 128**.

- **Returns:** A table containing functions to get decrypted data in different formats.
  - `asBytes()`: The decrypted data as byte table.
  - `asHex()`: The decrypted data as string in hexadecimal format.
  - `asString()`: The decrypted data as string format.

Example:

```lua
local str = "ao"

local iv = "super_secret_shh"
local key_128 = "super_secret_shh"

local encrypted = crypto.cipher.aes.encrypt("ao", key, iv).asHex() -- A3B9E6E1FBD9D46930E5F76807C84B8E
local decrypted = crypto.cipher.aes.decrypt(encrypted, key, iv).asHex() -- 616F0000000000000000000000000000

crypto.utils.hex.hexToString(decrypted) -- ao

```

## ISSAC Cipher

ISAAC is a cryptographically secure pseudo-random number generator (CSPRNG) and stream cipher. It has the following functions

1. `seedIsaac`: Seeds the ISAAC cipher with a given seed.
2. `getRandomChar`: Generates a random character using the ISAAC cipher.
3. `random`: Generates a random number between a given range using the ISAAC cipher.
4. `getRandom`: Generates a random number using the ISAAC cipher.
5. `encrypt`: Encrypts a given message using the ISAAC cipher.
6. `decrypt`: Decrypts a given message using the ISAAC cipher.

### Encrypt

Encrypts a given message using the ISAAC cipher.

- **Parameters:**
  - `msg` (string): The message to be encrypted.
  - `key` (string): The key to be used for encryption.
- **Returns:** A table containing functions to get encrypted data in different formats.
  - `asBytes()`: The encrypted data as byte table.
  - `asHex()`: The encrypted data as string in hexadecimal format.
  - `asString()`: The encrypted data as string format.

### Decrypt

Decrypts a given message using the ISAAC cipher.

- **Parameters:**
  - `cipher` (string): Hex Encoded encrypted data.
  - `key` (string): Key to be used for decryption.
- **Returns:** A table containing functions to get decrypted data in different formats.
  - `asBytes()`: The decrypted data as byte table.
  - `asHex()`: The decrypted data as string in hexadecimal format.
  - `asString()`: The decrypted data as string format.

Example:

```lua
local message = "ao";
local key = "secret_key";

local encrypted = crypto.cipher.issac.encrypt(message, key)
local decrypted = crypto.cipher.issac.decrypt(encrypted.asString(), key) -- ao

encrypted.asHex() -- 7851
```

### random

Generates a random number using the ISAAC cipher.

- **Parameters:**
  - `min` (number) optional: The minimum value of the random number. **defaults to 0**.
  - `max` (number) optional: The maximum value of the random number. **defaults to 2^31 - 1**.
  - `seed` (string) optional: The seed to be used for generating the random number. **defaults to math.random(0,2^32 - 1)**.
- **Returns:** A random number between the given range.

Example:

```lua
crypto.cipher.issac.random(0, 100) -- 42
```

## Morus Cipher

MORUS is a high-performance authenticated encryption algorithm submitted to the CAESAR competition, and recently selected as a finalist.

### Encrypt

Encrypts a given message using the MORUS cipher.

- **Parameters:**
  - `key` (string): The encryption key (16 or 32-byte string).
  - `iv` (string): The nonce or initial value (16-byte string).
  - `msg` (string): The message to encrypt (variable length string).
  - `ad` (string) optional: The additional data (variable length string). **defaults to ""**.
- **Returns:** A table containing functions to get encrypted data in different formats.
  - `asBytes()`: The encrypted data as byte table.
  - `asHex()`: The encrypted data as string in hexadecimal format.
  - `asString()`: The encrypted data as string format.

### Decrypt

Decrypts a given message using the MORUS cipher.

- **Parameters:**
  - `key` (string): The encryption key (16 or 32-byte string).
  - `iv` (string): The nonce or initial value (16-byte string).
  - `cipher` (string): The encrypted message (variable length string).
  - `adLen` (number) optional: The length of the additional data (variable length string). **defaults to 0**.
- **Returns:** A table containing functions to get decrypted data in different formats.
  - `asBytes()`: The decrypted data as byte table.
  - `asHex()`: The decrypted data as string in hexadecimal format.
  - `asString()`: The decrypted data as string format.

Example:

```lua
local m = "ao"
local k = "super_secret_shh"
local iv = "0000000000000000"
local ad= ""

local e = crypto.cipher.morus.encrypt(k, iv, m, ad)
local d = crypto.cipher.morus.decrypt(k, iv, e.asString(), #ad) -- ao

e.asHex() -- 514ed31473d8fb0b76c6cbb17af35ed01d0a
```

## NORX Cipher

NORX is an authenticated encryption scheme with associated data that was selected, along with 14 other primitives, for the third phase of the ongoing CAESAR competition. It is based on the sponge construction and relies on a simple permutation that allows efficient and versatile implementations.

### Encrypt

Encrypts a given message using the NORX cipher.

- **Parameters:**
  - `key` (string): The encryption key (32-byte string).
  - `nonce` (string): The nonce or initial value (32-byte string).
  - `plain` (string): The message to encrypt (variable length string).
  - `header` (string) optional: The additional data (variable length string). **defaults to ""**.
  - `trailer` (string) optional: The additional data (variable length string). **defaults to ""**.
- **Returns:** A table containing functions to get encrypted data in different formats.
  - `asBytes()`: The encrypted data as byte table.
  - `asHex()`: The encrypted data as string in hexadecimal format.
  - `asString()`: The encrypted data as string format.

### Decrypt

Decrypts a given message using the NORX cipher.

- **Parameters:**
  - `key` (string): The encryption key (32-byte string).
  - `nonce` (string): The nonce or initial value (32-byte string).
  - `crypted` (string): The encrypted message (variable length string).
  - `header` (string) optional: The additional data (variable length string). **defaults to ""**.
  - `trailer` (string) optional: The additional data (variable length string). **defaults to ""**.
- **Returns:** A table containing functions to get decrypted data in different formats.
  - `asBytes()`: The decrypted data as byte table.
  - `asHex()`: The decrypted data as string in hexadecimal format.
  - `asString()`: The decrypted data as string format.

Example:

```lua
local key = "super_duper_secret_password_shhh"
local nonce = "00000000000000000000000000000000"

local data = "ao"

--