---
# System prepended metadata

title: 'Bootcamp #1 Fall 2024: AO 101'

---

# AO Technical 101 Workshop

## Introduction to AO

**AO** is a compute layer built on top of **Arweave**. It provides **hyper parallel computing**, which means you can easily create and run an arbitrary number of independent computational processes — similar to creating containers in AWS, but decentralized. Currently, each **process** is a lightweight, scriptable container that runs Lua code.

![image](https://hackmd.io/_uploads/rkcS50vlyl.png)

</br>

## Two Ways to Interact with AO

1. **AOS**: Command Line Interface
2. **AOConnect**: JavaScript Library

![image](https://hackmd.io/_uploads/B1udqCvgkl.png)

</br>

## Getting Started with AOS

### Installation

To install **AOS**, simply run:

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

After installing, launch **AOS** by running:

```bash
aos
```

### Difference Between `aos` and `aos process_name`

- Running `aos` starts a **default AO terminal**.
- Running `aos process_name` creates a **new process** with the given name and opens a Lua terminal for that process.

This is the equivalent of setting up a container on AWS but so much simpler. In just two commands, we’ve created an AO process that is ready for computations.

### Process IDs and Wallets

- Each **AO process** is associated with a **process ID**.
- By default, every process has a wallet stored at `~/.aos.json`, similar to Arweave keyfiles.
- You can replace this wallet with your custom keyfile, if needed.

To retrieve your **process ID**:

```lua
ao.id
```

The **process ID** can be used in messages, functions, and interactions with other processes.

## AO Terminal Basics

The **AOS terminal** is a Lua environment with some AO-specific enhancements.

- **Simple Math**: Perform simple calculations:

  ```lua
  > 5 * 5
  25
  ```

- **Storing Variables**: Assign values to variables:

  ```lua
  > count = 10
  > count = count + 5  -- Now count is 15
  ```

- **Inline Functions**: You can define functions:

  ```lua
  > function greet(name) return "Hello, " .. name end
  > greet("Alice")
  "Hello, Alice"
  ```

- **Multi-Line Code**: To write multi-line code, use:

  ```lua
  .editor
  ```

  Example:

  ```lua
  while num < 50 do
    num = num + 1  -- Note: Lua doesn’t have `++` or `+=` syntax
  end
  ```

### Using `.pad` Editor

If you need a more powerful editor, `.pad` gives a **Vim-like editor** for working with code, which is handy for power users.

---

## Messaging Between Processes in AO

In AO, processes **communicate via messages**. Let’s send a simple message to ourselves:

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

This message is added to the **Inbox** of the process. Inbox is a default table that every process has. To read incoming messages:

```lua
> Inbox[#Inbox]
```

## Creating Multiple Processes and Messaging

1. Create a second process:

   ```bash
   aos process_two
   ```

2. Send a message from the new process:

   ```lua
   Send({ Target = "process_id_of_first_process", Data = "Hello from process_two" })
   ```

3. Read the message in the first process:

   ```lua
   > Inbox[#Inbox]
   ```

---

## Using Handlers in AO

**Handlers** are special instructions that enable auto-execution of functions when certain conditions or patterns are met.

![image](https://hackmd.io/_uploads/Bk_q5CDlyl.png)

</br>

Example: Let’s create a **ping-pong handler**:

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

This handler listens for any message containing `"ping"` and replies with `"pong"`.

### Additional Handler Features

- **`Handlers.once`**: This will create a handler that removes itself after running once.
- **Specifying Max Runs (Optional)**: You can also specify the number of times a handler should run before it removes itself:

  ```lua
  Handlers.add(
    "pingpong",
    Handlers.utils.hasMatchingData("ping"),
    Handlers.utils.reply("pong"),
    3  -- Maximum number of runs
  )
  ```

## BetterIDEa IDE

Writing multi-line code can be cumbersome in the AOS terminal. For a better experience, use **BetterIDEa IDE**:

- Head to **[https://ide.betteridea.dev/](https://ide.betteridea.dev/)**
- The IDE provides:
  - **Syntax highlighting**
  - **Line navigation** and **editing tools**
  - **Auto-completions**
  - **Easy installation of blueprints** and **dependencies**

---

## Building a Mini Utility: Chatroom

Let’s build a simple chatroom in AO.

### Step 1: Initialize Members List

First, we initialize a list to track participants:

```lua
Members = Members or {}
```

### Step 2: Add a Register Handler

To allow processes to join the chatroom:

```lua
Handlers.add(
  "Register",
  { Action = "Register" },
  function(msg)
    table.insert(Members, msg.From)
    print(msg.From .. " Registered")
    msg.reply({ Data = "Registered." })
  end
)
```

- This handler adds the sender process to the members list and replies to confirm registration.

### Step 3: Register Yourself to the Chatroom

Send a message to register:

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

Check the members list:

```lua
Members  -- You should see your process ID listed
```

### Step 4: Add a Broadcast Handler

Now, let’s create a handler that broadcasts messages to all members:

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

Test broadcasting:

```lua
Send({ Target = ao.id, Action = "Broadcast", Data = "Hello Members!" }).receive().Data
```

## Using Blueprints for Common Utilities

AOS provides **blueprints** for common utilities like chatrooms:

```lua
.load-blueprint chatroom
```

This installs a pre-configured chatroom handler for you to use directly.

---

## AOS 2.0 Updates

- **`.forward`**: Every message can be forwarded to another process:

  ```lua
  msg.forward(msg['Some-Address'], {})
  ```

- **`.reply`**: Send a response to the original sender:

  ```lua
  msg.reply({ Test = "Successful message receipt", Status = "Success" })
  ```

- **`.onReply`**: Set up an action that should happen when a reply is received:

  ```lua
  Send({
    Target = target,
    Test = "1"
  }).onReply(printMsg('Test'))
  ```
  
- **`.receive`**: This is similar to the `async/await` function in JavaScript:

  ```lua
  Send({
    Target = target,
    Action = "Get-Reply"
  }).receive()
  ```

- **`.dryrun`**: DryRun sends a message to a specific process and gets the result without saving the state. Useful for read operations like checking balances.

---

## Handling Larger Datasets with SQLite

The basic setup is great for lightweight operations, but for larger datasets, we need structured storage. This is where **SQLite** comes in.

### SQLite with AO

**DbAdmin** is a module that makes SQLite interactions easier within AO.

## Building a Database Utility Using DbAdmin

### Step 1: Set Up SQLite and DbAdmin

```lua
local sqlite3 = require("lsqlite3")
local dbAdmin = require("@rakis/DbAdmin")

-- Open an in-memory database
db = sqlite3.open_memory()

-- Create a DbAdmin instance
admin = dbAdmin.new(db)
```

### Step 2: Create a Table

```lua
admin:exec[[
  CREATE TABLE leaderboard (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    score INTEGER DEFAULT 0,
    profile_image TEXT
  );
]]
```

### Step 3: Insert Records

```lua
admin:apply('INSERT INTO leaderboard (name, score, profile_image) VALUES (?, ?, ?);', { "Alice", 10, "image_url_1" })
admin:apply('INSERT INTO leaderboard (name, score, profile_image) VALUES (?, ?, ?);', { "Bob", 15, "image_url_2" })
```

### Step 4: Update and Delete Records

You can also update or delete records using the `apply` method:

```lua
-- Update a user's score
admin:apply('UPDATE leaderboard SET score = ? WHERE name = ?;', { 20, "Alice" })
```

### Step 5: Query Records

To retrieve records from the database:

```lua
local results = admin:select('SELECT * FROM leaderboard WHERE name = ?;', { "Alice" })
```

---

## Using Bazaar Profiles APM Package

For managing user profiles, you can use the Bazaar Profiles APM Package.

Install the package:

```lua
APM.install("@ankush/bazar")
```

Fetch user profiles:

```lua
bazarProfiles = require("@ankush/bazar")
res = bazarProfiles.GetProfile(wallet_address)
print(res)
```

---

## Summary

In this workshop, we covered:

- AO Basics: Understanding AO and hyper parallel computing.
- AOS CLI: Installation, process creation, and messaging.
- Handlers: Automating responses to messages.
- BetterIDEa IDE: A better development experience for AO.
- Chatroom Utility: Building and managing chatrooms in AO.
- SQLite with DbAdmin: Handling larger datasets in AO.
- APM Packages: Leveraging existing modules for complex functionality.