Skip to main content

Read Data from PWR Chain

Reading data from the PWR Chain is a crucial aspect of building decentralized applications (dApps) on the PWR platform. The PWR SDK provides a simple and efficient way to retrieve data from the blockchain, allowing your application to access and utilize the information stored on the chain.

In this guide, we'll explore how to read data from the PWR Chain using the PWR SDK, with a focus on retrieving transaction data and block information.

Reading Data

The PWR SDK provides various methods to retrieve data from the PWR Chain. Let's look at some common use cases and how to achieve them using the SDK.

Retrieving Account Balances and Nonces

To retrieve the PWR balance or nonce of a specific account.

const { PWRJS } = require('@pwrjs/core');

// Setting up the rpc api
const rpc = new PWRJS("https://pwrrpc.pwrlabs.io/");

async function account() {
const address = "0x3b3b69093879e7b6f28366fa3c32762590ff547e";

// get balance of address
const balance = await rpc.getBalanceOfAddress(address);
console.log(`Balance: ${balance}`);
// get nonce of address
const nonce = await rpc.getNonceOfAddress(address);
console.log(`Nonce: ${nonce}`);
}
account()

Retrieving Blocks

Blocks will help us access a lot of data through the set of transactions they contain. In this example, we retrieve a specific block by its block number:

const { PWRJS } = require('@pwrjs/core');

// Setting up the rpc api
const rpc = new PWRJS("https://pwrrpc.pwrlabs.io/");

async function getBlock() {
// the block number we want fetch
const blockNumber = 20000;
// get the block by number
const block = await rpc.getBlockByNumber(blockNumber);

for (let i in block.transactions) {
console.log(`Sender ${i}: ${block.transactions[i].sender}`);
}
}
getBlock()

You can access and process the block data according to your application's needs, such as analyzing transaction patterns, tracking specific events, or updating your application's state based on the block information.

Retrieving VM Data Transactions

One of the fetch operations that you will need a lot is fetching VM transactions to process data and sender and many more ideas that we will explain in the upcoming lessons.

In this example, we retrieve all VM data transactions sent to a specific VM (identified by vmId) within a given block range (startBlock to endBlock):

const { PWRJS } = require('@pwrjs/core');

// Setting up the rpc api
const rpc = new PWRJS("https://pwrrpc.pwrlabs.io/");

async function getVmData() {
const startBlock = 843500;
const endBlock = 843750;
const vmId = 123;

// fetch the transactions sent from `startBlock` to `endBlock` in `vmId`
const transactions = await rpc.getVMDataTransactions(startBlock, endBlock, vmId);

// prints the trasnactions data
for (let txs of transactions) {
console.log("Data:", txs.data);
}
}
getVmData()

You can process the transaction data according to your application's requirements, such as decoding it, storing it, or triggering specific actions based on the data.

Handling Data Encoding and Decoding

When reading data from the PWR Chain, it's important to consider the encoding and decoding of data. The PWR SDK provides utility classes and methods to assist with these tasks.

For example, if you are working with hexadecimal-encoded data in Java, you can use the Hex class provided by the SDK to decode the data into byte arrays or strings.

async function decoding() {
const hexData = "0x48656C6C6F20576F726C6421";

// Remove the '0x' prefix and decode the hexadecimal data to bytes data
const decodedData = Buffer.from(hexData.slice(2), 'hex');
// Convert the decoded data to a UTF-8 string
const stringData = decodedData.toString('utf8');

console.log(`Outputs: ${stringData}`); // Outputs: Hello World!
}
decoding()

Handling Retrieved Data

Once you have retrieved data from the PWR Chain, you can process and handle it according to your application's requirements. Here are a few examples of handling the retrieved data:

const { PWRJS } = require('@pwrjs/core');

// Setting up the rpc api
const rpc = new PWRJS("https://pwrrpc.pwrlabs.io/");

async function getVmDataActive() {
const startBlock = 843500;
const endBlock = 843750;
const vmId = 123;

// fetch the transactions sent from `startBlock` to `endBlock` in `vmId`
const transactions = await rpc.getVMDataTransactions(startBlock, endBlock, vmId);

for (let txs of transactions) {
const sender = txs.sender;
const data = txs.data;

// Remove the '0x' prefix and decode the hexadecimal data to bytes data
const decodedData = Buffer.from(data.slice(2), 'hex');
// Convert the bytes data to a UTF-8 string
const stringData = decodedData.toString('utf8');

if (stringData.startsWith("Hi")) {
const word = stringData.substring(3);
console.log(`${sender}: ${word}`);
}
else if (stringData.startsWith("Hello")) {
const word = stringData.substring(6);
console.log(`${sender}: ${word}`)
}
}
}
getVmDataActive()

As you see, in the implementation of Rust we did not convert the data from hex to bytes data because in Rust we get the data value as bytes directly.

Best Practices

When reading data from the PWR Chain, consider the following best practices:

  1. Efficient Data Retrieval: Optimize your data retrieval logic to minimize the number of requests made to the PWR Chain. Retrieve data in batches or use caching mechanisms to reduce network overhead and improve performance.
  2. Asynchronous Processing: Utilize asynchronous programming techniques to prevent blocking the main application thread while waiting for data retrieval. This ensures a responsive user experience and allows for parallel processing of data.
  3. Error Handling and Logging: Implement robust error handling mechanisms and logging to diagnose and troubleshoot issues related to data retrieval. Log relevant information such as error messages, stack traces, and request/response details for debugging purposes.
  4. Data Validation and Sanitization: Validate and sanitize the data retrieved from the PWR Chain before using it in your application. Ensure that the data conforms to expected formats, ranges, and constraints to prevent security vulnerabilities or unexpected behavior.
  5. Secure Data Handling: When dealing with sensitive or confidential data retrieved from the PWR Chain, employ secure practices such as encryption, access controls, and secure storage to protect the data from unauthorized access or tampering.

By following these best practices and leveraging the PWR SDK's data retrieval capabilities, you can efficiently and securely read data from the PWR Chain and build robust decentralized applications on the PWR platform.