# Building a Stateless VIDA

Stateless VIDAs are lightweight, fast, and simple applications that do not require validating or maintaining historical data or consistent state across its execution instances. They are ideal for non-critical use cases such as chat rooms, simple games, or other applications where speed and ease of development are prioritized over strict consistency.

***

#### **Steps to Build a Stateless VIDA**

#### **1. Select an ID for Your VIDA**

Every VIDA requires a unique identifier, which is an 8-byte variable. This ID ensures the PWR Chain knows which transactions belong to your application.

* **Why 8 bytes?**\
  It minimizes storage requirements while allowing for 18 quintillion unique IDs.

{% tabs %}
{% tab title="Java" %}

```java
//generate a random long value
long vidaId = new SecureRandom().nextLong();
System.out.println(vidaId);
        
//Save the vidaId
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const crypto = require('crypto');

// Generate a random 64-bit integer
const vidaId = BigInt('0x' + crypto.randomBytes(8).toString('hex'));

console.log(vidaId.toString());
```

{% endtab %}

{% tab title="Python" %}

```python
# Generate a random 64-bit signed integer
vida_id = secrets.randbits(64) - (1 << 63)

print(vida_id)
```

{% endtab %}

{% tab title="Rust" %}

```rust
use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    let veda_id: i64 = rng.gen();
    
    println!("{}", veda_id);
}
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
    "crypto/rand"
    "encoding/binary"
    "fmt"
)

func main() {
    var vedaId int64
    err := binary.Read(rand.Reader, binary.LittleEndian, &vedaId)
    if err != nil {
	fmt.Println("Error generating random number:", err)
	return
    }

    fmt.Println(vedaId)
}
```

{% endtab %}
{% endtabs %}

***

#### **2. Import the PWR SDK**

The PWR SDK is your toolkit for interacting with the PWR Chain. It allows you to create wallets, send transactions, and read data from the blockchain.

{% tabs %}
{% tab title="Java (Maven)" %}

```xml
<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.github.pwrlabs</groupId>
        <artifactId>pwrj</artifactId>
        <version>11.4.1</version>
    </dependency>
</dependencies>
```

Make sure to use the latest version. Check <https://github.com/pwrlabs/pwrj> for the latest release

```java
import com.github.pwrlabs.pwrj.protocol.PWRJ;
```

{% endtab %}

{% tab title="Java (Gradle)" %}

```gradle
dependencyResolutionManagement {
	repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
	repositories {
		mavenCentral()
		maven { url 'https://jitpack.io' }
	}
}

dependencies {
	implementation 'com.github.pwrlabs:pwrj:8.7.0'
}
```

Make sure to use the latest version. Check <https://github.com/pwrlabs/pwrj> for the latest release

```java
import com.github.pwrlabs.pwrj.protocol.PWRJ;
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
import { PWRJS, PWRWallet } from '@pwrjs/core';
// or
const { PWRJS, PWRWallet } = require('@pwrjs/core');
```

{% endtab %}

{% tab title="Python" %}

```python
from pwrpy.pwrapisdk import PWRPY
from pwrpy.pwrwallet import PWRWallet
```

{% endtab %}

{% tab title="Rust" %}

```rust
use pwr_rs::{ Wallet, RPC };
```

{% endtab %}

{% tab title="Go" %}

```go
import (
    "github.com/pwrlabs/pwrgo/wallet"
    "github.com/pwrlabs/pwrgo/rpc"
)
```

{% endtab %}
{% endtabs %}

***

#### **3. Initializing PWR with an RPC Endpoint**

To interact with the PWR Chain, initialize a PWR object (e.g., `PWRJ` for Java, `PWRPY` for Python). This object serves as your gateway to the blockchain.

**What is an RPC Node?**

An RPC (Remote Procedure Call) node processes blockchain requests, such as transactions and data queries. You can use a public node (e.g., `https://pwrrpc.pwrlabs.io`) or run your own for better control and security.

{% tabs %}
{% tab title="Java" %}

```java
PWRJ pwrj = new PWRJ("https://pwrrpc.pwrlabs.io");
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const pwrjs = new PWRJS("https://pwrrpc.pwrlabs.io/");
```

{% endtab %}

{% tab title="Python" %}

```python
pwrpy = PWRPY()
```

{% endtab %}

{% tab title="Rust" %}

```rust
let pwrrs = RPC::new("https://pwrrpc.pwrlabs.io/").await.unwrap();
```

{% endtab %}
{% endtabs %}

This setup enables seamless interaction with the PWR Chain for your VIDA.

#### **4. Create and Fund a Wallet**

A wallet is essential for signing transactions and paying minimal fees on the PWR Chain.

* **Steps:**
  1. Create a new wallet or load an existing one.
  2. Save the wallet securely in an encrypted file.
  3. Fund it using the [PWR Chain faucet](http://faucet.pwrlabs.io/) (for test coins). You can check your PWR coins balance on the[ PWR Chain Explorer](https://explorer.pwrlabs.io/) by putting your address in the search bar.&#x20;

{% tabs %}
{% tab title="Java" %}

```java
    private static PWRFalconWallet createWallet(PWRJ pwrj, String password) {
        try {
            //Try to load an existing wallet
            PWRFalconWallet wallet = PWRFalconWallet.loadWallet(pwrj, "wallet", password);
            
            // If the wallet is null, it means it was not found or could not be loaded
            // Create new wallet
            if(wallet == null) {
                wallet = new PWRFalconWallet(12, pwrj);
                wallet.storeWallet("wallet", password);
            }
            
            return wallet;
        } catch (Exception e) {
            System.err.println("Failed to create or load wallet: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const { PWRWallet, PWRJS} = require('@pwrjs/core');

const pwrjs = new PWRJS("https://pwrrpc.pwrlabs.io/");

// generate and save wallet
const wallet = new PWRWallet();
console.log("Address: " + wallet.getAddress());
wallet.storeWallet("wallet.dat", "password");

//load wallet
const loadedWallet = PWRWallet.loadWallet("wallet.dat", "password", pwrjs);
console.log("Address: " + loadedWallet.getAddress());
```

{% endtab %}

{% tab title="Python" %}

```python
from pwrpy.pwrwallet import PWRWallet

# generate and save wallet
wallet = PWRWallet()
print(f"Address: {wallet.get_address()}")
PWRWallet(private_key).store_wallet("wallet.dat", "password")

# load wallet
loaded_wallet = PWRWallet.load_wallet("wallet.dat", "password")
print(f"Address: {loaded_wallet.get_address()}")
```

{% endtab %}

{% tab title="Rust" %}

```rust
use pwr_rs::Wallet;

fn main() {
    // generate and save wallet
    let wallet = Wallet::random();
    println!("Address: {:?}", wallet.get_address());
    wallet.store_wallet("wallet.dat", "password")
        .expect("Failed to store wallet");

    // load wallet
    let loaded_wallet = Wallet::load_wallet("wallet.dat", "password")
        .expect("Failed to load wallet");
    println!("Address: {:?}", loaded_wallet.get_address());
}
```

{% endtab %}

{% tab title="Go" %}

```go
import (
    "fmt"
    "github.com/pwrlabs/pwrgo/wallet"
)

func main() {
    // generate and save wallet
    var new_wallet = wallet.NewWallet()
    fmt.Printf("Address: %s\n", new_wallet.GetAddress())
    new_wallet.StoreWallet("wallet.dat", "password")

    // load wallet
    var loaded_wallet, _ = wallet.LoadWallet("wallet.dat", "password")
    fmt.Printf("Address: %s\n", loaded_wallet.GetAddress())
}
```

{% endtab %}
{% endtabs %}

***

#### **5. Define Transaction Data Structure**

While PWR Chain stores all transaction data as raw byte arrays, VIDAs can encode this data into structured formats like JSON. Defining a **schema for your transactions** ensures consistency, simplifies development, and enables collaboration across teams.

#### **Why Define a Schema?**

* **Consistency**: Ensures all transactions follow a predictable format.
* **Documentation**: Serves as a reference for developers interacting with your VIDA.
* **Validation**: Helps catch malformed data early.

Example:&#x20;

```json
[
    {
        "action": "send-message-v1",
        "message": "Hello World!"
    },
    
    {
        "action": "add-reaction-v1",
        "message-hash": "0x54ef...",
        "reaction": "thumbs-up"
    }
]
```

***

#### **6. Send Data to PWR Chain**

After defining your transaction's data structure, you can start sending transactions to PWR Chain. Submit transactions to the PWR Chain to record user actions or data.

{% tabs %}
{% tab title="Java" %}

```java
//Write transaction data
JSONObject jsonObject = new JSONObject();
jsonObject.put("action", "send-message-v1");
jsonObject.put("message", "Hello World!");
byte[] data = jsonObject.toString().getBytes(StandardCharsets.UTF_8);

//Send transaction
Response response = wallet.sendVmDataTransaction(vidaId, data, loadedWallet.getNonce());
if(response.isSuccess()) {
    System.out.println("Transaction sent successfully!");
    System.out.println("Transaction hash: " + response.getTransactionHash());
}
else System.out.println("Transaction failed: " + response.getError());
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
// Write transaction data
const obj = {
    action: 'send-message-v1',
    message: 'Hello World!',
};

const data = new TextEncoder().encode(obj);

//Send transaction
const response = wallet.sendVMDataTxn(vidaId, data);

if(response.sucuccess) {
    console.log("Transaction sent successfully!");
    console.log("Transaction hash: " + response.transactionHash);
}
else console.log("Transaction failed: " + response.message);
```

{% endtab %}

{% tab title="Python" %}

```python
# Write transaction data
json_object = {
    "action": "send-message-v1",
    "message": "Hello World!"
}
data = json.dumps(json_object).encode("utf-8")

# Send transaction
response = wallet.send_vm_data_transaction(vidaId, data)
if response.success:
    print("Transaction sent successfully!")
    print(f"Transaction hash: 0x{response.data.hex()}")
else:
    print(f"Transaction failed: {response.message}")
```

{% endtab %}

{% tab title="Rust" %}

```rust
// Write transaction data
let json_object = json!({
    "action": "send-message-v1",
    "message": "Hello World!"
});
let data: Vec<u8> = serde_json::to_string(&json_object).unwrap().into_bytes();

// Send transaction
let response_tx = wallet.send_vm_data(vidaId, data).await;
if response_tx.success {
    println!("Transaction sent successfully!");
    println!("Transaction hash: {:?}", response_tx.data.unwrap());
} else {
    println!("Transaction failed: {:?}", response_tx.message);
}
```

{% endtab %}

{% tab title="Go" %}

<pre class="language-go"><code class="lang-go">// Write transaction data
<strong>jsonObject := map[string]string{
</strong>    "action":  "send-message-v1",
    "message": "Hello World!",
}
data, _ := json.Marshal(jsonObject)

// Send transaction
response := wallet.SendVMData(vidaId, data)
if response.Success {
   fmt.Println("Transaction sent successfully!")
   fmt.Printf("Transaction hash: %s\n", response.TxHash)
} else {
   fmt.Printf("Transaction failed: %s\n", response.Error)
}
</code></pre>

{% endtab %}
{% endtabs %}

***

#### **7. Read Data from PWR Chain & Handle it.**

The PWR SDK provides functions to easily read and handle data from PWR Chain.

{% tabs %}
{% tab title="Java" %}

```java
PWRJ pwrj = new PWRJ("https://pwrrpc.pwrlabs.io/");

long vidaId = 1; // Replace with your VIDA's ID  

/*Since our VIDA is global chat room and we don't care about historical messages,
we will start reading transactions startng from the latest PWR Chain block*/
long startingBlock = pwrj.getBlockNumber();

VidaTransactionSubscription vidaTransactionSubscription = pwrj.subscribeToVidaTransactions(pwrj, vidaId, startingBlock, (transaction) -> {
    VmDataTransaction vmDataTransaction = transaction;

    //Get the address of the transaction sender
    String sender = vmDataTransaction.getSender();

    //Get the data sent in the transaction (In Hex Format)
    String data = vmDataTransaction.getData();

    try {
        //Decode the data from Hex to byte array
        if (data.startsWith("0x")) data = data.substring(2);
        byte[] dataBytes = Hex.decode(data);

        //Convert the byte array to a JSON Object
        JSONObject jsonObject = new JSONObject(new String(dataBytes));
        String action = jsonObject.optString("action", "no-action");

        //Check the action and execute the necessary code
        if (action.equalsIgnoreCase("send-message-v1")) {
            String message = jsonObject.getString("message");
            System.out.println("Message from " + sender + ": " + message);
        } else {
            //ignore
        }
    } catch (Exception e) {
        e.printStackTrace();

        //This most likely indicates Malformed data from the sender
    }
});

//To pause, resume, and stop the subscription
vidaTransactionSubscription.pause();
vidaTransactionSubscription.resume();
vidaTransactionSubscription.stop();
vidaTransactionSubscription.start();

//To get the block number of the latest checked PWR Chain block
vidaTransactionSubscription.getLatestCheckedBlock();
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
const pwrj = new PWRJS("https://pwrrpc.pwrlabs.io/");

const vidaId = 1n; // Replace with your VIDA's ID

// Since our VIDA is global chat room and we don't care about historical messages, we will start reading transactions startng from the latest PWR Chain block/ long startingBlock = pwrj.getBlockNumber();
function handler(transaction: VmDataTransaction){
    
    //Get the address of the transaction sender
    const sender = VmDataTransaction.sender;
    
    //Get the data sent in the transaction (In Hex Format)
    let data = VmDataTransaction.data;
    
    try {
    
      // convert data string to bytes 
      if (data.startsWith("0x")) data = data.substring(2);
      const bytes = hexToBytes(data);
      const dataStr = new TextDecoder().decode(bytes);
      const dataJson = JSON.parse(dataStr);
      
      //Check the action and execute the necessary cod
      if (dataJson.action === "send-message-v1") {
          const message = data.message;
          console.log("Message from " + sender + ": " + message);
      }
    } catch (e) {
        console.error(e)
    }
}


const subscription = pwrjs.subscribeToVidaTransactions(
    pwrjs, 
    vidaId, 
    startingBlock, 
    {handler}
);
//To pause, resume, and stop the subscription vidaTransactionSubscription.pause(); vidaTransactionSubscription.resume(); vidaTransactionSubscription.stop(); vidaTransactionSubscription.start();
//To get the block number of the latest checked PWR Chain block vidaTransactionSubscription.getLatestCheckedBlock();
```

{% endtab %}

{% tab title="Python" %}

```python
from pwrpy.pwrsdk import PWRPY
from pwrpy.models.Transaction import VmDataTransaction
import json
import time

rpc = PWRPY()
vida_id = 1

# Since our VIDA is global chat room and we don't care about historical messages,
# we will start reading transactions startng from the latest PWR Chain block
starting_block = rpc.get_latest_block_number()

def handle_transaction(txn: VmDataTransaction):
    try:
        sender = txn.sender
        data_hex = txn.data
        data_bytes = bytes.fromhex(data_hex[2:])
        obj = json.loads(data_bytes.decode('utf-8'))

        if obj["action"] == "send-message-v1":
            print(f"Message from {sender}: {obj['message']}")

    except Exception as e:
        print(f"Error processing transaction: {e}")

rpc.subscribe_to_vida_transactions(vida_id, starting_block, handler=handle_transaction)

while True:
    time.sleep(1)
```

{% endtab %}

{% tab title="Rust" %}

```rust
use pwr_rs::{
    RPC,
    transaction::types::VMDataTransaction,
    rpc::tx_subscription::VidaTransactionHandler
};
use std::sync::Arc;
use serde_json::Value;

#[tokio::main]
async fn main() {
    let rpc = Arc::new(RPC::new("https://pwrrpc.pwrlabs.io/").await.unwrap());

    let vida_id = 1;
    let starting_block = rpc.get_latest_block_number().await.unwrap();

    struct Handler(Box<dyn Fn(VMDataTransaction) + Send + Sync>);
    impl VidaTransactionHandler for Handler {
        fn process_vida_transactions(&self, tx: VMDataTransaction) {
            (self.0)(tx)
        }
    }

    let handler = Arc::new(Handler(Box::new(|txn: VMDataTransaction| {
        let sender = txn.sender;
        let data = txn.data;
        let data_str = String::from_utf8(data).unwrap();
        let object: Value = serde_json::from_str(&data_str).unwrap();
        let obj_map = object.as_object().unwrap();

        if obj_map.get("action").and_then(|val| val.as_str()) == Some("send-message-v1")
        {
            if let Some(message_str) = obj_map
                .get("message")
                .and_then(|val| val.as_str())
            {
                println!("Message from {}: {}", sender, message_str);
            }
        }
    })));

    rpc.subscribe_to_vida_transactions(vida_id, starting_block, handler, None);

    loop {
        tokio::time::sleep(std::time::Duration::from_millis(1)).await;
    }
}
```

{% endtab %}

{% tab title="Go" %}

<pre class="language-go"><code class="lang-go"><strong>import (
</strong>    "fmt"
    "encoding/json"
    "encoding/hex"

    "github.com/pwrlabs/pwrgo/rpc"
)

type MyHandler struct{}

func (h *MyHandler) ProcessVidaTransactions(tx rpc.VMDataTransaction) {
    sender := tx.Sender
    data := tx.Data
    
    dataBytes, _ := hex.DecodeString(data[2:])
    var obj map[string]interface{}

    if err := json.Unmarshal(dataBytes, &#x26;obj); err != nil {
        fmt.Println("Error parsing JSON:", err)
    }

    if action, _ := obj["action"].(string); action == "send-message-v1" {
        message, _ := obj["message"].(string)
        fmt.Printf("Message from %s: %s\n", sender, message)
    }
}

func main() {
    vidaId := 1
    startingBlock := rpc.GetLatestBlockNumber()

    handler := &#x26;MyHandler{}

    rpc.SubscribeToVidaTransactions(
        vidaId,
        startingBlock,
        handler,
    )

    select {}
}
</code></pre>

{% endtab %}
{% endtabs %}

***

#### **8. Make Your App Public**

Once your VIDA is ready, share it with others by publishing it:

* **Option 1:** Open-source your code on GitHub with clear instructions.
* **Option 2:** Publish it on the PWR Chain registry for decentralized discovery. *(Coming Soon)*

***

#### **Key Considerations for Stateless VIDAs**

* **No State Management:** Stateless VIDAs do not track or validate past transactions, making them fast but unsuitable for critical use cases.
* **Ideal Use Cases:** Applications prioritizing speed and simplicity over consistency (e.g., chat apps, simple games).

By following these steps, you can build a lightweight and efficient Stateless VIDA that leverages the power of PWR Chain while keeping development simple!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://whitepaperv2.pwrlabs.io/how-to/how-to-build-a-vida/building-a-stateless-vida.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
