Client side gateway to access ORBS nodes by IP with filtering and iteration support
npm install @orbs-network/orbs-clientimport { Client } from '@orbs-network/orbs-client';
async function example() {
// Create client with a seed node IP
const seedIP = '13.112.58.64';
const client = new Client(seedIP);
// Initialize - fetches topology and committee data
await client.init();
// Check if initialized
if (client.initialized()) {
console.log('Client initialized successfully');
}
}The getNodes() method accepts an optional NodeFilter object to filter nodes based on various criteria. All filter options are optional and can be combined.
When set to true, returns only nodes that are members of the current committee.
// Get only committee nodes
const committeeNodes = await client.getNodes({ committeeOnly: true });
// Get all nodes (committee and non-committee)
const allNodes = await client.getNodes({ committeeOnly: false });
// or simply
const allNodes = await client.getNodes();When set to true, the client will check each node's status by fetching from its management service endpoint. Only nodes that respond successfully will be returned.
Important Notes:
- Status checks are performed in parallel with a 5-second timeout per node
- This operation may take several seconds depending on network conditions
- Each node's
onlineproperty will be set totruefor returned nodes - The
updatedTimefield stores when the status was checked - The
statusDatafield contains the full status JSON response
// Get only online nodes
const onlineNodes = await client.getNodes({ onlineOnly: true });
// Get online committee nodes
const onlineCommittee = await client.getNodes({
committeeOnly: true,
onlineOnly: true
});Filters nodes based on whether they have TEE (Trusted Execution Environment) hardware.
// Get nodes with TEE hardware
const teeNodes = await client.getNodes({ teeHardware: true });
// Get nodes without TEE hardware
const nonTeeNodes = await client.getNodes({ teeHardware: false });You can combine multiple filters to get exactly the nodes you need:
// Get online committee nodes without TEE hardware
const filtered = await client.getNodes({
committeeOnly: true,
onlineOnly: true,
teeHardware: false
});Filter Order:
- First,
committeeOnlyfilter is applied (if specified) - Then,
teeHardwarefilter is applied (if specified) - Finally,
onlineOnlyfilter is applied (if specified) - this checks status for each remaining node
// Example 1: All committee nodes
const committee = await client.getNodes({ committeeOnly: true });
// Example 2: All online nodes (checks all nodes in topology)
const online = await client.getNodes({ onlineOnly: true });
// Example 3: Online committee nodes
const onlineCommittee = await client.getNodes({
committeeOnly: true,
onlineOnly: true
});
// Example 4: Committee nodes with TEE hardware
const teeCommittee = await client.getNodes({
committeeOnly: true,
teeHardware: true
});
// Example 5: Online committee nodes without TEE hardware
const onlineNonTeeCommittee = await client.getNodes({
committeeOnly: true,
onlineOnly: true,
teeHardware: false
});import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
// Get only committee nodes
const committeeNodes = await client.getNodes({ committeeOnly: true });
// Iterate through committee nodes
let node = committeeNodes.next();
while (node !== null) {
console.log(`Committee Node: ${node.name} (${node.ip})`);
console.log(`Effective Stake: ${node.effectiveStake}`);
node = committeeNodes.next();
}
// Or get by index
const firstCommitteeNode = committeeNodes.get(0);
const lastCommitteeNode = committeeNodes.get(-1); // -1 means last
// Get count
console.log(`Committee size: ${committeeNodes.size()}`);import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
// Get all nodes (topology)
const allNodes = await client.getNodes();
// Iterate through all nodes
let node = allNodes.next();
while (node !== null) {
console.log(`Node: ${node.name}`);
console.log(`In Committee: ${node.inCommittee}`);
node = allNodes.next();
}
// Get total count
console.log(`Total nodes: ${allNodes.size()}`);import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
// Get online committee nodes (checks each node's status)
const onlineCommitteeNodes = await client.getNodes({
committeeOnly: true,
onlineOnly: true
});
// All returned nodes are guaranteed to be online
let node = onlineCommitteeNodes.next();
while (node !== null) {
console.log(`Online Node: ${node.name}`);
console.log(`Status checked at: ${node.updatedTime}`);
console.log(`Status data:`, node.statusData);
node = onlineCommitteeNodes.next();
}Note: When
onlineOnly: true, the client fetches status from each node's management service endpoint. This may take a few seconds as it checks nodes in parallel with a 5-second timeout per node.
import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
// Get nodes without TEE hardware
const nonTeeNodes = await client.getNodes({
teeHardware: false
});
// Get nodes with TEE hardware
const teeNodes = await client.getNodes({
teeHardware: true
});import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
// Get online committee nodes without TEE hardware
const filteredNodes = await client.getNodes({
committeeOnly: true,
onlineOnly: true,
teeHardware: false
});Each node object contains the following properties:
interface Node {
name: string; // Node name
ip: string; // Node IP address
port: number; // Node port
website: string; // Guardian website
guardianAddress: string; // Ethereum address (guardian)
nodeAddress: string; // Orbs address
reputation: number; // Node reputation
online: boolean; // Online status (updated when onlineOnly filter is used)
effectiveStake: number; // Effective stake (sorted descending)
enterTime: number; // Timestamp when guardian entered
weight: number; // Guardian weight
inCommittee: boolean; // Whether node is in committee
updatedTime?: number; // Timestamp when status was last checked
statusData?: any; // Full status JSON from node
teeHardware?: boolean; // Whether node has TEE hardware
}Each Node instance provides methods to make RPC calls directly to the node's service endpoints. These methods allow you to interact with the node's management and other services.
The get() method makes an HTTP GET request to a node's service endpoint.
async get(path: string, timeoutMs?: number): Promise<Response>Parameters:
path: string- The service endpoint path (e.g.,'signer/status'or'/management-service/status')timeoutMs?: number- Optional timeout in milliseconds (default: 5000)
Returns: A Promise<Response> that resolves to a Response object (standard fetch API response)
Example:
import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
// Get a node
const nodes = await client.getNodes({ committeeOnly: true });
const node = nodes.get(0);
if (node) {
// Make GET request to signer status endpoint
const response = await node.get('signer/status');
if (response.ok) {
const data = await response.json();
console.log('Signer status:', data);
} else {
console.error('Request failed:', response.status);
}
// With custom timeout
const quickResponse = await node.get('signer/status', 2000);
}URL Construction: The method automatically constructs the full URL as:
http://{node.ip}:{node.port}/services/{path}- If
portis0, the port is omitted (defaults to port 80) - Leading slashes in the path are normalized
The post() method makes an HTTP POST request to a node's service endpoint.
async post(path: string, body?: any, timeoutMs?: number): Promise<Response>Parameters:
path: string- The service endpoint pathbody?: any- Optional request body. Can be:string- Sent astext/plainobject- Automatically JSON stringified and sent asapplication/jsonundefined- No body is sent
timeoutMs?: number- Optional timeout in milliseconds (default: 5000)
Returns: A Promise<Response> that resolves to a Response object (standard fetch API response)
Example:
import { Client } from '@orbs-network/orbs-client';
const client = new Client('13.112.58.64');
await client.init();
const nodes = await client.getNodes({ committeeOnly: true });
const node = nodes.get(0);
if (node) {
// POST with JSON object
const jsonBody = { action: 'start', params: { key: 'value' } };
const response = await node.post('management-service/command', jsonBody);
if (response.ok) {
const result = await response.json();
console.log('Command result:', result);
}
// POST with string body
const stringResponse = await node.post('some-endpoint', 'plain text data');
// POST without body
const noBodyResponse = await node.post('trigger-action');
}Content-Type Handling:
- If
bodyis astring: SetsContent-Type: text/plain - If
bodyis anobject: SetsContent-Type: application/jsonand JSON stringifies the body - If
bodyisundefined: NoContent-Typeheader is set and no body is sent
import { Client } from '@orbs-network/orbs-client';
async function rpcExamples() {
const client = new Client('13.112.58.64');
await client.init();
// Get online committee nodes
const nodes = await client.getNodes({
committeeOnly: true,
onlineOnly: true
});
// Iterate through nodes and make RPC calls
let node = nodes.next();
while (node !== null) {
try {
// GET request example
const statusResponse = await node.get('signer/status');
if (statusResponse.ok) {
const status = await statusResponse.json();
console.log(`${node.name} status:`, status);
}
// POST request example
const commandResponse = await node.post('management-service/command', {
action: 'get-info'
});
if (commandResponse.ok) {
const info = await commandResponse.json();
console.log(`${node.name} info:`, info);
}
} catch (error) {
console.error(`Error calling ${node.name}:`, error);
}
node = nodes.next();
}
}Important Notes:
- Both
get()andpost()methods useAbortControllerfor timeout handling - If a timeout occurs, the request is aborted and the promise may reject
- The default timeout is 5 seconds (5000ms)
- Always check
response.okbefore parsing JSON - Handle errors appropriately as network requests can fail
Creates a new Client instance with a seed node IP address.
const client = new Client('13.112.58.64');Initializes the client by fetching topology and committee data from the seed node.
await client.init();Returns true if the client has been successfully initialized.
if (client.initialized()) {
// Safe to call getNodes()
}Returns a Nodes iterator with filtered nodes.
Filter Options:
committeeOnly?: boolean- Iftrue, only returns nodes in the committeeonlineOnly?: boolean- Iftrue, checks each node's status and only returns online nodesteeHardware?: boolean- Filter by TEE hardware presence (true/false)
const nodes = await client.getNodes({
committeeOnly: true,
onlineOnly: true
});Returns the next node in the iterator, or null when iteration is complete.
let node = nodes.next();
while (node !== null) {
console.log(node.name);
node = nodes.next();
}Gets a node by index. Use -1 to get the last node.
const first = nodes.get(0);
const last = nodes.get(-1);Returns the total number of nodes in the iterator.
const count = nodes.size();Nodes are automatically sorted by effectiveStake in descending order (highest stake first). This ensures that when you iterate through nodes, you get them in order of stake.
import { Client } from '@orbs-network/orbs-client';
async function main() {
const seedIP = '13.112.58.64';
const client = new Client(seedIP);
try {
await client.init();
if (!client.initialized()) {
console.error('Failed to initialize client');
return;
}
// Get online committee nodes
const onlineCommittee = await client.getNodes({
committeeOnly: true,
onlineOnly: true
});
console.log(`Found ${onlineCommittee.size()} online committee nodes`);
// Iterate through nodes
let node = onlineCommittee.next();
while (node !== null) {
console.log(`\n${node.name}`);
console.log(` IP: ${node.ip}:${node.port}`);
console.log(` Stake: ${node.effectiveStake}`);
console.log(` Guardian: ${node.guardianAddress}`);
console.log(` Online: ${node.online}`);
node = onlineCommittee.next();
}
// Get first and last nodes
const firstNode = onlineCommittee.get(0);
const lastNode = onlineCommittee.get(-1);
if (firstNode && lastNode) {
console.log(`\nHighest stake: ${firstNode.effectiveStake}`);
console.log(`Lowest stake: ${lastNode.effectiveStake}`);
}
} catch (error) {
console.error('Error:', error);
}
}
main();For browser usage, include the bundled script:
<script src="https://unpkg.com/@orbs-network/orbs-client/dist/index.min.js"></script>
<script>
async function init() {
const seedIP = '13.112.58.64';
const client = new window.orbsClient.Client(seedIP);
await client.init();
const nodes = await client.getNodes({ committeeOnly: true });
let node = nodes.next();
while (node !== null) {
console.log(node.name);
node = nodes.next();
}
}
init();
</script>- Nodes are sorted by
effectiveStakein descending order - When using
onlineOnly: true, status is checked with a 5-second timeout per node - Status checks are performed in parallel for better performance
- The
updatedTimefield stores when the node's status was last checked - The
statusDatafield contains the full status JSON response from the node