npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vara-eth/api

v0.1.0

Published

Typescript library for interacting with Vara.Eth network

Downloads

304

Readme

Vara.Eth TypeScript API

TypeScript client library for Vara.Eth - a decentralized compute network that extends Ethereum with high-performance parallel execution, near-zero gas fees, and instant finalization without requiring asset bridging.

Table of Contents

Installation

npm install @vara-eth/api

Prerequisites

Install required peer dependencies:

npm install viem@^2.39.0 [email protected]

Quick Start

import { VaraEthApi, WsVaraEthProvider, EthereumClient } from '@vara-eth/api';
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';

// Initialize Ethereum clients
const publicClient = createPublicClient({ transport: http('https://eth-rpc-url') });
const account = privateKeyToAccount('0x...');
const walletClient = createWalletClient({ account, transport: http('https://eth-rpc-url') });

// Create EthereumClient wrapper (now requires routerAddress)
const ethereumClient = new EthereumClient(publicClient, walletClient, routerAddress);

await ethereumClient.isInitialized;

// Initialize Vara.Eth API (connects to Vara.Eth node)
const api = new VaraEthApi(
  new WsVaraEthProvider('ws://localhost:9944'),
  ethereumClient
);

// Access Router and WVARA clients through EthereumClient
const router = ethereumClient.router;
const wvara = ethereumClient.wvara;

High-Level API

VaraEthApi

Main API class for interacting with the Vara.Eth network. Provides methods for querying program state and performing read-only operations.

const api = new VaraEthApi(provider, ethereumClient);

// Query methods
await api.query.program.getIds();           // List all program IDs
await api.query.program.readState(hash);    // Read program state
await api.query.program.codeId(programId);  // Get program's code ID

// Call methods (read-only)
await api.call.program.calculateReplyForHandle(source, programId, payload);

// Create and send injected transactions
const injected = await api.createInjectedTransaction({
  destination: programId,
  payload: encodedPayload,
  value: 0n,
});
await injected.send();

EthereumClient

Wrapper around viem's PublicClient and WalletClient that provides unified interface for contract interactions. Automatically initializes Router and WrappedVara contract clients.

const ethereumClient = new EthereumClient(publicClient, walletClient, routerAddress);

// Access underlying clients
ethereumClient.publicClient;
ethereumClient.walletClient;
ethereumClient.accountAddress;

// Access contract clients
ethereumClient.router;      // RouterClient instance
ethereumClient.wvara;       // WrappedVaraClient instance

// Wait for initialization if needed
await ethereumClient.isInitialized;

RouterClient

Interface for interacting with the Router contract - the main entry point for code validation and program creation on Ethereum.

Source: Router.sol

const router = getRouterClient(routerAddress, ethereumClient);

await router.createProgram(codeId);                 // Create program from validated code
await router.createProgramWithAbiInterface(codeId, abiAddress); // Create with Solidity ABI

MirrorClient

Interface for interacting with Mirror contracts - deployed programs on Ethereum. Each program has its own Mirror contract.

Source: Mirror.sol

const mirror = getMirrorClient(programId, ethereumClient);

await mirror.sendMessage(payload, value);          // Send message to program
await mirror.executableBalanceTopUp(amount);       // Top up program's balance
await mirror.stateHash();                          // Get current state hash

WrappedVaraClient

Interface for managing WVARA tokens (ERC20 wrapper for VARA) used for gas payments.

Source: WrappedVara.sol

const wvara = getWrappedVaraClient(wvaraAddress, ethereumClient);

await wvara.approve(spender, amount);              // Approve spending
await wvara.balanceOf(address);                    // Check balance
await wvara.allowance(owner, spender);             // Check allowance

Uploading Program Code

Before creating a program, you must upload and validate your WASM code using the vara-eth CLI.

Getting the CLI

Download from releases (recommended):

Build from source:

cargo build -p ethexe-cli -r

Uploading Your Program

Insert your private key:

./target/release/ethexe key insert $SENDER_PRIVATE_KEY

Upload your compiled WASM:

./target/release/ethexe --cfg none tx \
  --ethereum-rpc "$ETH_RPC" \           # Ethereum node RPC
  --ethereum-router "$ROUTER_ADDRESS" \ # Router contract address
  --sender "$SENDER_ADDRESS" \         # Your account address
  upload -l path/to/program.opt.wasm

The CLI will submit code via EIP-4844 blob transactions, request validation, and return a codeId once validators confirm it. Use this codeId with the API:

const codeId = '0x...'; // From CLI output
const tx = await router.createProgram(codeId);

Ethereum Side Operations

1. Program Creation

Create programs from validated code:

Note: Code must be uploaded and validated before creating programs. Use the Vara.Eth CLI to upload and validate WASM code. The CLI will provide you with a codeId after successful validation.

// Create program from validated code
const codeId = '0x...'; // Code ID from vara-eth CLI

const tx = await router.createProgram(codeId);
await tx.sendAndWaitForReceipt();

// Get the program ID
const programId = await tx.getProgramId();
console.log('Program created:', programId);

// Get Mirror contract for program interaction
const mirror = getMirrorClient(programId, ethereumClient);

Creating Program with Solidity ABI Interface

const codeId = '0x...'; // Code ID from vara-eth CLI

// Deploy Solidity ABI contract
const deployHash = await walletClient.deployContract({
  abi: counterAbi,
  bytecode: counterBytecode,
});

const receipt = await publicClient.waitForTransactionReceipt({ hash: deployHash });
const abiAddress = receipt.contractAddress;

// Create program with ABI interface
const tx = await router.createProgramWithAbiInterface(codeId, abiAddress);
await tx.sendAndWaitForReceipt();

2. Sending Messages to Programs

Send messages and wait for replies:

Note: Programs are typically built with Sails framework. Use sails-js library to encode payloads and decode replies.

// Encode payload using sails-js
const sails = await Sails.new(); // Initialize from IDL
const payload = sails.services.Counter.functions.Increment.encodePayload();

// Send message
const tx = await mirror.sendMessage(payload, 0n);
await tx.send();

// Get message details
const message = await tx.getMessage();
console.log('Message ID:', message.id);

// Setup listener and wait for reply
const { waitForReply } = await tx.setupReplyListener();
const { payload: replyPayload, replyCode, value } = await waitForReply;

// Decode reply using sails-js
const result = sails.services.Counter.functions.Increment.decodeResult(replyPayload);
console.log('Result:', result);

3. Managing Executable Balance

Programs require wVARA balance to execute. Top up using wVARA tokens:

// Check WVARA balance
const balance = await wvara.balanceOf(ethereumClient.accountAddress);
console.log('WVARA balance:', balance);

// Approve program to spend wVARA
const approveTx = await wvara.approve(programId, BigInt(10 * 1e12));
await approveTx.sendAndWaitForReceipt();

const approvalData = await approveTx.getApprovalLog();
console.log('Approved amount:', approvalData.value);

// Top up program's executable balance
const topUpTx = await mirror.executableBalanceTopUp(BigInt(10 * 1e12));
const { status } = await topUpTx.sendAndWaitForReceipt();
console.log('Top-up status:', status);

4. Checking Program State

Query program information from Router and Mirror contracts:

// Check code validation status
const codeState = await router.codeState(codeId);
console.log('Code state:', codeState); // 'Validated' | 'Rejected' | 'Unknown'

// Get program's code ID
const programCodeId = await router.programCodeId(programId);

// Get program's state hash
const stateHash = await mirror.stateHash();

// Read full program state from Vara.Eth
const state = await api.query.program.readState(stateHash);
console.log('Program active:', 'Active' in state.program);

// Get program nonce
const nonce = await mirror.nonce();

5. Working with TxManager

Contract write methods return a TxManager instance that handles transaction lifecycle:

const tx = await router.createProgram(codeId);

// Send transaction and get response
const response = await tx.send();
console.log('Transaction hash:', response.hash);

// Send and wait for receipt
const receipt = await tx.sendAndWaitForReceipt();
console.log('Status:', receipt.status);
console.log('Block number:', receipt.blockNumber);

// Estimate gas before sending
const gasEstimate = await tx.estimateGas();
console.log('Estimated gas:', gasEstimate);

// Access transaction request
const txRequest = tx.getTx();
console.log('Gas limit:', txRequest.gasLimit);

// Find specific events in receipt
await tx.send();
const event = await tx.findEvent('ProgramCreated');
console.log('Event args:', event.args);

// Use transaction-specific helper functions
const programId = await tx.getProgramId(); // Available on createProgram transactions

TxManager Helper Functions:

Each transaction type can have specific helper methods:

  • createProgram: getProgramId() - extracts program ID from event
  • requestCodeValidation: waitForCodeGotValidated() - waits for validation completion
  • approve: getApprovalLog() - gets approval event data
  • sendMessage: getMessage(), setupReplyListener() - message handling

Vara.Eth Side Operations

1. Instantiating VaraEthApi

Connect to Vara.Eth node using HTTP or WebSocket provider:

// HTTP Provider (for queries and calls)
import { VaraEthApi, HttpVaraEthProvider } from '@vara-eth/api';

const api = new VaraEthApi(
  new HttpVaraEthProvider('http://localhost:9944'),
  ethereumClient
);

// WebSocket Provider (for subscriptions and real-time updates)
import { WsVaraEthProvider } from '@vara-eth/api';

const wsApi = new VaraEthApi(
  new WsVaraEthProvider('ws://localhost:9944'),
  ethereumClient
);

// Don't forget to disconnect when done
await api.provider.disconnect();

HTTP vs WebSocket Providers:

  • HttpVaraEthProvider: Best for one-time queries and calls. Simpler, no persistent connection.
  • WsVaraEthProvider: Required for subscriptions and real-time event listening. Maintains persistent connection.

2. Injected Transactions

Injected transactions are Vara.Eth-native transactions sent directly to the network, bypassing Ethereum. They provide faster execution and lower costs for operations that don't require Ethereum settlement.

What are Injected Transactions?

Unlike regular messages sent through Mirror contracts on Ethereum, injected transactions are:

  • Sent directly to Vara.Eth validators
  • Signed with Ethereum private key but submitted off-chain
  • Cheaper and faster (no Ethereum gas costs)
  • Reference an Ethereum block for security

Creating and Sending Injected Transactions:

// Create injected transaction using API
const injected = await api.createInjectedTransaction({
  destination: programId,              // Program to send message to
  payload: '0x1c436f756e74657224496e6372656d656e74', // Encoded message payload
  value: 0n,                           // Optional value to send
  // These are auto-populated if not provided:
  // recipient: validator address (auto-selected)
  // referenceBlock: recent Ethereum block hash (auto-fetched)
  // salt: random salt for uniqueness
});

// Send transaction
const result = await injected.send();

// Wait for full transaction promise (includes reply)
const promise = await injected.sendAndWaitForPromise();

Configuring Transaction Properties:

// Create injected transaction with all properties
const injected = await api.createInjectedTransaction({
  destination: programId,
  payload: encodedPayload,
  value: 1000n,
  referenceBlock: blockHash,          // Specific Ethereum block
  salt: '0x030405',                   // Custom salt
  recipient: validatorAddress,        // Specific validator
});

// Modify transaction using fluent API
injected
  .setValue(2000n)                    // Update value
  .setSalt('0x060708');               // Update salt

// Access transaction properties
const messageId = injected.messageId; // Vara.Eth message ID

// Update transaction fields
await injected.setReferenceBlock();   // Fetch latest Ethereum block
await injected.setRecipient();        // Auto-select next validator
// or specify a validator
await injected.setRecipient(validatorAddress);

// Send transaction
await injected.send();

3. Querying Program Data

Query program information from Vara.Eth network:

// List all program IDs
const programIds = await api.query.program.getIds();
console.log('Total programs:', programIds.length);

// Get program's code ID
const codeId = await api.query.program.codeId(programId);

// Read program state by state hash
const stateHash = await mirror.stateHash(); // Get from Mirror contract
const state = await api.query.program.readState(stateHash);

if ('Active' in state.program) {
  console.log('Program is active');
  console.log('Balance:', state.balance);
}

4. Reading Program State via calculateReplyForHandle

Perform read-only queries on program state without sending transactions:

Note: Use sails-js to encode query payloads and decode results.

// Encode query payload using sails-js
const queryPayload = sails.services.Counter.queries.GetValue.encodePayload();

// Calculate what the program would reply (read-only)
const reply = await api.call.program.calculateReplyForHandle(
  ethereumClient.accountAddress,  // Source address
  programId,                      // Program to query
  queryPayload                    // Encoded query
);

// Decode result using sails-js
const value = sails.services.Counter.queries.GetValue.decodeResult(reply.payload);
console.log('Current counter value:', value);

This method is useful for:

  • Reading program state without modifying it
  • Testing message payloads before sending
  • Querying computed values from programs

Additional Resources

License

GPL 3.0 - see LICENSE