1. Introduction
Welcome to the GRIDNET OS Blockchain Explorer API documentation. This API provides UI dApps running within the GRIDNET OS web-browser subsystem the ability to query and interact with the underlying decentralized blockchain state machine. It allows developers to build applications that can visualize, search, and analyze blockchain data, including blocks, transactions, domain information (accounts), and various network statistics.
This document is intended for developers building UI dApps for GRIDNET OS who need to access blockchain information. It covers the API’s architecture, core concepts, method reference, data object descriptions, and event handling mechanisms.
Resources:
- For a technical overview of an UI dApp already using this API see here
- For GRIDNE OS UI dApp best design practices see here
- For a Tutorial including sample deployment described see here
- Want to see how it works? Just launch the Blockchain Explorer UI dApp here (available from GRIDNET OS’ Start Menu).
2. Architecture Overview
The Blockchain Explorer API is primarily exposed through the CVMContext singleton object, which acts as the central bridge between the in-browser UI dApp environment and the remote GRIDNET Core nodes forming the decentralized network.

Key Architectural Points:
- Decentralized Nature: Unlike traditional client-server models, requests are processed by the distributed network of GRIDNET Core nodes.
CVMContexthandles selecting appropriate nodes (based on proximity or randomness) and managing the connection (typically WebSocket). - CVMContext: This singleton JavaScript object is the main entry point for all interactions with the GRIDNET OS backend, including the Blockchain Explorer API.
- GridScript: Under the hood, most Blockchain Explorer API calls are translated into specific
#GridScriptcommands (e.g.,context -c getBlockDetails ...). These commands are sent to a Core node for execution within a secure, sandboxed environment. - Decentralized Processing Threads: GRIDNET OS utilizes the concept of decentralized threads. API calls can optionally target specific threads (
threadID). If not specified, they often default to system-managed threads (like the main data thread). - Asynchronous Communication: Communication between the UI dApp and Core nodes is inherently asynchronous. The API provides both non-async (returning a Request ID immediately) and async (
Asuffix, returning a Promise) methods. - Event-Driven Responses: Results from API calls are typically delivered back to the UI dApp via events. The dApp registers specific listeners (e.g.,
addNewBlockDetailsListener) withCVMContextto receive and process these responses. - BER Encoding & Meta Data Protocol: Data exchanged between the browser and Core nodes (especially complex data like block or transaction details) uses the GRIDNET Meta Data Protocol, which is BER (Basic Encoding Rules) encoded for efficient and standardized data representation.
CVMContexthandles the encoding/decoding internally. - Security: Communication can be secured using end-to-end encryption and authentication mechanisms managed by
CVMContextbased on session state and configuration.

Simplified Flow:
[UI dApp] --(JS API Call)--> [CVMContext] --(GridScript/BER)--> [WebSocket] --> [GRIDNET Core Node(s)]
^ |
| (BER/Event) |
+------------------------------------------------------------------------------------+
Under the Hood: GridScript Execution and the Decentralized Paradigm
Beneath the familiar JavaScript interface of the Blockchain Explorer API lies a fundamentally decentralized execution model powered by #GridScript. When a UI dApp calls an API method like CVMContext.getBlockDetailsA(), CVMContext doesn’t query a local database or send a request to a traditional centralized backend. Instead, it seamlessly translates the JavaScript call and its parameters into a specific #GridScript command string (e.g., context -c getBlockDetails -search “<blockID>” -tx). This GridScript command, representing the data request, is then packaged using the GRIDNET OS’s BER-encoded VM Meta Data exchange protocol and dispatched via WebSocket to a connected GRIDNET Core node. The Core node routes this command to an appropriate Decentralized Processing Thread (DPT), which hosts its own sandboxed GridScript virtual machine instance. This VM executes the received command, interacting directly with the node’s local view of the decentralized blockchain state machine to retrieve the requested block details.

The results are then packaged back into a BER-encoded VM Meta Data response, sent back through the network to the originating CVMContext, which decodes it and delivers the structured data (like a CBlockDesc object) back to the UI dApp, either by resolving the corresponding Promise or triggering a registered event listener. This entire process represents a paradigm shift from traditional Service-Oriented Architectures (SOA); requests are not handled by a centralized server running PHP or .NET against a central database, but are executed decentrally across the network by capable Core nodes running GridScript. This architecture inherently supports a future where such computational or data retrieval tasks performed by nodes could be incentivized, potentially through mechanisms like off-chain cryptocurrency micropayments, truly decentralizing not just data storage but also application logic execution.

Let’s take a look at how the execution environment is structured:

Now let’s better understand involvement of BER encoding as it’s involved:

Now, let’s go with a complete Blockchain Explorer API execution Cycle:

3. Core Concepts
3.1 Synchronous vs. Asynchronous API Methods
The API offers two styles for many methods:
- Non-Async (Synchronous-like Invocation): Methods like
getBlockDetails(...)execute the request immediately and return a uniquerequest identifier(a number > 0) if the request was successfully sent. The actual result arrives later via an event. The UI dApp needs to register a corresponding listener (e.g.,addNewBlockDetailsListener) to handle the response, matching it using thereqIDfield in the event argument. - Async (Promise-based): Methods ending with
A(e.g.,getBlockDetailsA(...)) return a JavaScriptPromise. This Promise resolves with the result data when the response is received from the network or rejects if an error or timeout occurs. This simplifies handling asynchronous operations compared to managing request IDs and listeners manually.
Recommendation: Use the asynchronous (A suffix) methods whenever possible for cleaner code structure using async/await or .then()/.catch().
3.2 Event-Driven Architecture

Responses to API calls and real-time blockchain updates are delivered through events. UI dApps must register listener functions with CVMContext using specific add...Listener methods.
- Listeners: Functions provided by the UI dApp to handle specific types of data (e.g., block details, search results).
- Notifiers: Internal
CVMContextmethods (notify...) that trigger the registered listeners when relevant data arrives. - Event Arguments: Listener functions receive an argument object, typically containing:
reqID: The original request identifier (if applicable).dataor specific properties: The payload, often an instance of a data object class (e.g.,CBlockDesc).- Other contextual information (e.g.,
processID,source).
3.3 Request/Response Flow & IDs
- API Call: The UI dApp calls an API method (e.g.,
CVMContext.getTransactionDetails(...)). - Request ID Generation:
CVMContextgenerates a uniquerequest identifier(reqID). - GridScript Formulation: The API method formats the corresponding
#GridScriptcommand. - Dispatch:
CVMContext(viaprocessGridScriptKM) sends the command (encapsulated in Meta Data) over the network. The non-async method returns thereqIDimmediately. The async method registers the Promise internally using thisreqID. - Network Processing: GRIDNET Core nodes process the request.
- Response Delivery: The result is sent back via WebSocket, BER-encoded within the Meta Data protocol.
- Response Processing:
CVMContextreceives the message, decrypts/authenticates if necessary, parses the Meta Data, and identifies the relevant data and originalreqID. - Notification/Resolution:
CVMContexttriggers the appropriate notifier function (e.g.,notifyNewTransactionDetails).- The notifier function iterates through registered listeners, calling their callback functions with the response data and
reqID. - If the request was made using an async (
A) method,CVMContextfinds the corresponding pending Promise using thereqIDand resolves it with the data (viaresolvePendingRequest).

3.4 Decentralized Processing Threads (threadID)
GRIDNET OS allows operations to be executed within specific decentralized processing threads. Most Blockchain Explorer API methods accept an optional threadID (as an ArrayBuffer).
- If provided, the operation targets that specific thread.
- If omitted or an empty
ArrayBufferis provided, it usually defaults to a system-managed thread (often the main Data Thread, accessible viaCVMContext.getDataThreadID). - The main System Thread (
CVMContext.getSystemThreadID) handles core system operations.
3.5 Process Handles (processHandle)
Many API methods require a processHandle. This is typically the instance of the UI dApp’s main class (which usually extends CWindow). It’s used for:
- Authorization: Ensuring that API calls originate from a registered, valid UI dApp process. Anonymous calls are often disallowed.
- Context: Linking the API request to the specific application making the call.
- Resource Management: Potentially used by the system to manage resources associated with the dApp’s requests.
3.6 Execution Modes (mode)
The mode parameter (using the eVMMetaCodeExecutionMode enum) specifies how the underlying GridScript command should be executed and how results should be returned. For the Blockchain Explorer API:
eVMMetaCodeExecutionMode.RAW: Typically used. Returns raw, structured data objects (likeCBlockDesc) suitable for programmatic use.eVMMetaCodeExecutionMode.GUI: Might return data formatted for direct display in a terminal-like UI (less common for this API).
3.7 Data Objects
The API uses specific classes to represent blockchain entities:
CBlockDesc: Block details.CTransactionDesc: Transaction details.CDomainDesc: Domain/account details.CSearchResults: Container for search results, holding multiple items of the above types.CSearchFilter: Used to define complex search criteria.
These objects provide methods for accessing properties and often include serialization (getPackedData) and deserialization (instantiate) methods for BER encoding.
4. API Reference
This section details the public methods provided by CVMContext for the Blockchain Explorer API.
4.1 Data Retrieval Methods
getRecentTransactions(size, page, includeMem, threadID, processHandle, mode, reqID)
Retrieves a list of recent transactions from the blockchain.
- Parameters:
size{number} [Optional, Default: 10] – Number of transactions per page.page{number} [Optional, Default: 1] – Page number to retrieve (1-based).includeMem{boolean} [Optional, Default: false] – If true, includes transactions from the memory pool (unconfirmed).threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process (required for user-mode calls).mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use (0 generates a new one).
- Returns: {
number} – A request identifier (reqID > 0) if the request was sent successfully, otherwise 0. - Underlying GridScript:
context -c getRecentTransactions -size <size> -page <page> [-mem] - Response Event:
addNewSearchResultsListener(Results delivered within aCSearchResultsobject containingCTransactionDescinstances). - Async Version:
getRecentTransactionsA(...)->Promise<CSearchResults> - Example (Non-Async):
const vmContext = CVMContext.getInstance();
const processHandle = this; // Assuming 'this' is the UI dApp instance
const listenerId = vmContext.addNewSearchResultsListener((event) => {
if (event.reqID === myReqId && event.results instanceof CSearchResults) {
console.log(`Received ${event.results.getResultCount()} recent transactions.`);
// Process event.results containing CTransactionDesc objects
vmContext.unregisterEventListenerByID(listenerId); // Clean up listener
}
});
const myReqId = vmContext.getRecentTransactions(20, 1, false, undefined, processHandle);
if (!myReqId) {
console.error("Failed to send request for recent transactions.");
vmContext.unregisterEventListenerByID(listenerId);
} else {
console.log("Request sent with ID:", myReqId);
}
- Example (Async):
async function fetchRecentTxs() {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const searchResults = await vmContext.getRecentTransactionsA(20, 1, false, undefined, processHandle);
console.log(`Received ${searchResults.getResultCount()} recent transactions.`);
searchResults.getAllResults().forEach(resultData => {
if (resultData.getValue() instanceof CTransactionDesc) {
const tx = resultData.getValue();
console.log(`TX ID: ${tx.verifiableID}, Value: ${tx.value}`);
}
});
} catch (error) {
console.error("Error fetching recent transactions:", error);
}
}
fetchRecentTxs();
getRecentBlocks(size, page, sortBlocksByEnumVal, threadID, processHandle, mode, reqID)
Retrieves a list of recent blocks from the blockchain.
- Parameters:
size{number} [Optional, Default: 10] – Number of blocks per page.page{number} [Optional, Default: 1] – Page number to retrieve (1-based).sortBlocksByEnumVal{eSortBlocksBy} [Optional, Default:timestampDesc] – The sorting criteria (use values fromeSortBlocksByenum).threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c getRecentBlocks -size <size> -page <page> -sort <sortBlocksByEnumVal> - Response Event:
addNewSearchResultsListener(Results delivered within aCSearchResultsobject containingCBlockDescinstances). - Async Version:
getRecentBlocksA(...)->Promise<CSearchResults> - Example (Async):
async function fetchRecentBlocks() {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const searchResults = await vmContext.getRecentBlocksA(15, 1, eSortBlocksBy.heightDesc, undefined, processHandle);
console.log(`Received ${searchResults.getResultCount()} recent blocks.`);
searchResults.getAllResults().forEach(resultData => {
if (resultData.getValue() instanceof CBlockDesc) {
const block = resultData.getValue();
console.log(`Block Height: ${block.height}, ID: ${block.blockID}`);
}
});
} catch (error) {
console.error("Error fetching recent blocks:", error);
}
}
fetchRecentBlocks();
getTransactionDailyStats(days, includeMem, threadID, processHandle, mode, reqID)
Retrieves daily statistics about transaction activity over a specified number of days.
-
- Parameters:
days{number} [Optional, Default: 14] – The number of past days to retrieve statistics for.includeMem{boolean} [Optional, Default: false] – If true, includes unconfirmed transactions in the statistics.threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c getTransactionDailyStats -days <days> [-mem] - Response Event:
addBlockchainStatsListener(Event argumentarg.datacontains the statistics, usually an array or object with date/count/volume pairs). - Async Version:
getTransactionDailyStatsA(...)->Promise<Object|Array> - Example (Async):
async function fetchTxStats() {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const stats = await vmContext.getTransactionDailyStatsA(30, false, undefined, processHandle);
// Assuming stats is { dates: [...], counts: [...], volumes: [...] }
console.log(`Received stats for ${stats.dates.length} days.`);
// Process stats for charting or display
} catch (error) {
console.error("Error fetching transaction stats:", error);
}
}
fetchTxStats();
- Parameters:
<code
getBlockchainStatus(threadID, processHandle, mode, reqID)
Retrieves the overall status of the blockchain, potentially including total supply, current heights, and network status.
- Parameters:
threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c getBlockchainStatus - Response Event:
addBlockchainStatsListener(Event argumentarg.datacontains status information liketotalSupply,height,keyHeight). - Async Version:
getBlockchainStatusA(...)->Promise<Object> - Example (Async):
async function fetchStatus() {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const status = await vmContext.getBlockchainStatusA(undefined, processHandle);
console.log(`Blockchain Status: Height=${status.height}, KeyHeight=${status.keyHeight}, Supply=${status.totalSupply}`);
} catch (error) {
console.error("Error fetching blockchain status:", error);
}
}
fetchStatus();
getMarketData(getMarketCap, getBalances, page, pageSize, sortType, sortOrder, threadID, processHandle, mode, reqID)
Retrieves market data, including total market capitalization and/or domain balances, with sorting and pagination.
- Parameters:
getMarketCap{boolean} [Optional, Default: false] – If true, retrieve total market cap (-dflag).getBalances{boolean} [Optional, Default: true] – If true, retrieve domain balances (-bflag).page{number} [Optional, Default: 1] – Page number for balance results.pageSize{number} [Optional, Default: 50] – Number of domain balances per page.sortType{eMarketSortType} [Optional, Default: null] – Criteria for sorting domain balances (e.g.,eMarketSortType.balance).sortOrder{eSortOrder} [Optional, Default:ascending] – Sort order (ascendingordescending).threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process (required).mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
market [-d] [-b] -page <page> -size <pageSize> [-sort <sortTypeStr>] [-asc | -desc] - Response Event:
addBlockchainStatsListener(for market cap) and/oraddNewSearchResultsListener(for domain balances, delivered inCSearchResultscontainingCDomainDesc). - Async Version:
getMarketDataA(...)->Promise<Object>(The resolved object structure depends ongetMarketCapandgetBalancesflags). - Example (Async – Get Top 10 Richest Domains):
async function fetchTopDomains() {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
// Request balances, sort by balance descending, page 1, size 10
const marketResults = await vmContext.getMarketDataA(
false, // Don't need total market cap
true, // Need domain balances
1,
10,
eMarketSortType.balance,
eSortOrder.descending,
undefined,
processHandle
);
// marketResults likely contains the data within a CSearchResults structure
// accessible through the listener or directly if the promise resolves with it.
console.log(`Received ${marketResults.getResultCount()} top domains.`);
marketResults.getAllResults().forEach(resultData => {
if (resultData.getValue() instanceof CDomainDesc) {
const domain = resultData.getValue();
console.log(`Domain: ${domain.domain}, Balance: ${domain.balanceTxt}`);
}
});} catch (error) {
console.error("Error fetching market data:", error);
}
}
fetchTopDomains();
searchBlockchain(query, size, page, flags, threadID, processHandle, mode, reqID)
Performs a general search across the blockchain for blocks, transactions, or domains matching the query.
-
- Parameters:
query{string} – The search term (e.g., block ID, transaction ID, domain name).size{number} [Optional, Default: 10] – Maximum number of results per page.page{number} [Optional, Default: 1] – Page number for results.flags{CSearchFilter|number|string|Array<string>} [Optional, Default: null] – Search filter. Can be:- A
CSearchFilterinstance for complex filtering. - A number representing a bitmask of standard flags (
TRANSACTIONS,DOMAINS,BLOCKS). - A Base58Check encoded string representing the filter.
- An array of standard flag names (e.g.,
['TRANSACTIONS', 'BLOCKS']). - If
null, defaults may apply on the Core node.
- A
threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c searchBlockchain -search "<query>" -size <size> -page <page> [-flags <flags>] - Response Event:
addNewSearchResultsListener(Results delivered within aCSearchResultsobject, potentially containing mixed types). - Async Version:
searchBlockchainA(...)->Promise<CSearchResults> - Example (Async – Search for a specific ID):
async function search(queryTerm) {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
// Search only for blocks and transactions
const filter = new CSearchFilter(CSearchFilter.NO_STANDARD); // Start with no standard flags
filter.setStandardFlags(CSearchFilter.StandardFlags.BLOCKS);
filter.setStandardFlags(CSearchFilter.StandardFlags.TRANSACTIONS);const searchResults = await vmContext.searchBlockchainA(queryTerm, 10, 1, filter, undefined, processHandle);
console.log(`Found ${searchResults.getTotalResultCount()} results.`);
// Process results (could be CBlockDesc or CTransactionDesc)
} catch (error) {
console.error(`Error searching for "${queryTerm}":`, error);
}
}
search("some_block_or_tx_id");
- Parameters:
getNetworkUtilization24h(threadID, processHandle, mode, reqID)
Retrieves the average network utilization percentage over the last 24 hours.
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getNetworkUtilization24h - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the utilization percentage). - Async Version:
getNetworkUtilization24hA(...)->Promise<number>
getBlockSize24h(threadID, processHandle, mode, reqID)
Retrieves the average block size in bytes over the last 24 hours.
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getBlockSize24h - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the average size in bytes). - Async Version:
getBlockSize24hA(...)->Promise<number>
getBlockRewards24h(threadID, processHandle, mode, reqID)
Retrieves the average block rewards (in attoGNC) over the last 24 hours.
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getBlockRewards24h - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the average reward as BigInt). - Async Version:
getBlockRewards24hA(...)->Promise<BigInt>
getAverageKeyBlockTime24h(threadID, processHandle, mode, reqID)
Retrieves the average time between key blocks in seconds over the last 24 hours.
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getAverageKeyBlockTime24h(Note: CVMContext code currently usesgetAverageBlockTime24hGridScript, might be an inconsistency). - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the average time in seconds). - Async Version:
getAverageKeyBlockTime24hA(...)->Promise<number>
getAverageBlockTime24h(threadID, processHandle, mode, reqID)
Retrieves the average time between all blocks (data and key) in seconds over the last 24 hours.
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getAverageBlockTime24h - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the average time in seconds). - Async Version:
getAverageBlockTime24hA(...)->Promise<number>
getBlockDetails(blockID, includeTX, includeMem, includeSec, threadID, processHandle, mode, reqID)
Retrieves detailed information for a specific block.
- Parameters:
blockID{string} – The ID of the block to retrieve.includeTX{boolean} [Optional, Default: true] – If true, include the list of transactions within the block (-txflag).includeMem{boolean} [Optional, Default: false] – (Likely unused for block details, but present in signature) Include mempool data (-memflag).includeSec{boolean} [Optional, Default: false] – If true, include a security report related to the block/miner (-secflag).threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c getBlockDetails -search "<blockID>" [-tx] [-mem] [-sec] - Response Event:
addNewBlockDetailsListener(Eventarg.datacontains aCBlockDescinstance). - Async Version:
getBlockDetailsA(...)->Promise<CBlockDesc> - Example (Async):
async function fetchBlock(id) {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const blockDetails = await vmContext.getBlockDetailsA(id, true, false, false, undefined, processHandle);
console.log(`Block Height: ${blockDetails.height}`);
console.log(`Number of Transactions: ${blockDetails.transactionsCount}`);
// Access other blockDetails properties (CBlockDesc instance)
} catch (error) {
console.error(`Error fetching block ${id}:`, error);
}
}
fetchBlock("some_block_id");
getDomainHistory(address, size, page, eSortTransactionsByVal, stateID, threadID, processHandle, mode, reqID)
Retrieves the transaction history for a specific domain address.
- Parameters:
address{string} – The domain address to query.size{number} [Optional, Default: 10] – Number of transactions per page.page{number} [Optional, Default: 1] – Page number to retrieve.eSortTransactionsByVal{eSortTransactionsBy} [Optional, Default:timestampDesc] – Sorting criteria for transactions.stateID{string} [Optional, Default: “”] – State ID for restoring iterators (used for deep pagination, currently experimental).threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c getDomainHistory -search "<address>" -size <size> -page <page> -sort <eSortTransactionsByVal> [-state "<stateID>"] - Response Event:
addNewSearchResultsListener(Results delivered within aCSearchResultsobject containingCTransactionDescinstances relevant to the domain). - Async Version:
getDomainHistoryA(...)->Promise<CSearchResults> - Example (Async):
async function fetchDomainHistory(domainAddr) {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const historyResults = await vmContext.getDomainHistoryA(domainAddr, 25, 1, eSortTransactionsBy.timestampDesc, "", undefined, processHandle);
console.log(`Found ${historyResults.getTotalResultCount()} transactions for domain ${domainAddr}.`);
// Process historyResults containing CTransactionDesc objects
} catch (error) {
console.error(`Error fetching history for domain ${domainAddr}:`, error);
}
}
fetchDomainHistory("some_domain_address");
getDomainDetails(address, perspective, includeSec, threadID, processHandle, mode, reqID)
Retrieves detailed information about a specific domain address.
- Parameters:
address{string} – The domain address to query.perspective{string} [Optional, Default: “”] – Specifies a perspective for viewing domain state (advanced feature).includeSec{boolean} [Optional, Default: false] – If true, includes the operator security report (-secflag).threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0. - Underlying GridScript:
context -c getDomainDetails -search "<address>" [-perspective "<perspective>"] [-sec] - Response Event:
addNewDomainDetailsListener(Eventarg.datacontains aCDomainDescinstance). - Async Version:
getDomainDetailsA(...)->Promise<CDomainDesc> - Example (Async):
async function fetchDomain(domainAddr) {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const domainDetails = await vmContext.getDomainDetailsA(domainAddr, "", false, undefined, processHandle);
console.log(`Domain: ${domainDetails.domain}`);
console.log(`Balance: ${domainDetails.balanceTxt}`);
// Access other domainDetails properties (CDomainDesc instance)
} catch (error) {
console.error(`Error fetching details for domain ${domainAddr}:`, error);
}
}
fetchDomain("some_domain_address");
getTransactionDetails(transactionID, threadID, processHandle, mode, reqID)
Retrieves detailed information about a specific transaction.
- Parameters:
transactionID{string} – The verifiable ID of the transaction.threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – A request identifier (reqID > 0) if sent successfully, otherwise 0 or false iftransactionIDis invalid. - Underlying GridScript:
context -c getTransactionDetails -search "<transactionID>" - Response Event:
addNewTransactionDetailsListener(Eventarg.datacontains aCTransactionDescinstance). - Async Version:
getTransactionDetailsA(...)->Promise<CTransactionDesc> - Example (Async):
async function fetchTxDetails(txId) {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const txDetails = await vmContext.getTransactionDetailsA(txId, undefined, processHandle);
console.log(`Transaction Sender: ${txDetails.sender}`);
console.log(`Transaction Value: ${txDetails.valueTxt}`);
// Access other txDetails properties (CTransactionDesc instance)
} catch (error) {
console.error(`Error fetching details for TX ${txId}:`, error);
}
}
fetchTxDetails("some_transaction_id");
getLiveness(threadID, processHandle, mode, reqID)
Retrieves the current network liveness state.
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getLiveness - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the liveness state, typically a value fromeLivenessStateenum). - Async Version:
getLivenessA(...)->Promise<number>
getUSDTPrice(threadID, processHandle, mode, reqID)
Retrieves the current approximate price of GNC in USDT (fetched from oracle sources by Core nodes).
- Parameters: See
getBlockchainStatus. - Returns: {
number} – Request ID (reqID > 0). - Underlying GridScript:
context -c getUSDTPrice - Response Event:
addBlockchainStatsListener(Eventarg.datacontains the price, likely as a BigInt representing atto-USDT per GNC or similar fixed-point representation). - Async Version:
getUSDTPriceA(...)->Promise<BigInt>
getHeight(isKeyHeight, threadID, processHandle, mode, reqID)
Retrieves the current height of the blockchain (either regular block height or key block height). Includes internal caching for efficiency.
- Parameters:
isKeyHeight{boolean} – If true, retrieves the latest key block height; otherwise, retrieves the latest regular block height.threadID{ArrayBuffer} [Optional, Default: Data Thread] – The target decentralized thread ID.processHandle{Object} [Optional, Default: null] – Handle of the calling UI dApp process.mode{eVMMetaCodeExecutionMode} [Optional, Default:RAW] – Execution mode.reqID{number} [Optional, Default: 0] – Specific request ID to use.
- Returns: {
number} – Request ID (reqID > 0) if a network request is sent, or the samereqID(potentially generated) if returning a cached value via a scheduled event. - Underlying GridScript:
context -c getHeight [-key] - Response Event:
addNewGridScriptResultListener(Eventarg.datacontains the height number). The method internally uses caching (mCachedHeight,mCachedKeyHeight) and may return a cached value via asetTimeoutevent ifallowCacheis true (in async version) and the cache is fresh. - Async Version:
getHeightA(isKeyHeight, ..., allowCache)->Promise<number>(TheallowCacheparameter controls cache usage). - Example (Async – Get Key Height):
async function fetchKeyHeight() {
try {
const vmContext = CVMContext.getInstance();
const processHandle = this;
const keyHeight = await vmContext.getHeightA(true, undefined, processHandle, undefined, 0, 5000, true); // Allow cache
console.log(`Current Key Block Height: ${keyHeight}`);
} catch (error) {
console.error("Error fetching key height:", error);
}
}
fetchKeyHeight();
4.2 Subscription Methods
subscribeToBlockchainUpdates(threadID, processHandle, mode, reqID)
Subscribes the current CVMContext instance to receive real-time updates about new blocks and potentially other blockchain events from the connected Core node. Registered listeners (e.g., addNewBlockDetailsListener, addNewTransactionDetailsListener) will be triggered as new data arrives.
- Parameters: See
getBlockchainStatus. - Returns: {
number|boolean} – A request identifier (reqID > 0) ortrueif already subscribed. Returnsfalseon failure to send the request. - Underlying GridScript:
context -c startBlockchainUpdates - Response Event: No direct response event. Success enables receiving blockchain update notifications via standard listeners.
- Async Version:
subscribeToBlockchainUpdatesA(...)->Promise<boolean> - Example (Non-Async):
const vmContext = CVMContext.getInstance();
const processHandle = this;
if (vmContext.subscribeToBlockchainUpdates(undefined, processHandle)) {
console.log("Subscription request sent successfully.");
// Register listeners like addNewBlockDetailsListener here
} else {
console.error("Failed to send subscription request.");
}
unsubscribeFromBlockchainUpdates(threadID, processHandle, mode, reqID)
Stops receiving real-time blockchain updates for this CVMContext instance.
- Parameters: See
getBlockchainStatus. - Returns: {
number|boolean} – A request identifier (reqID > 0) ortrueif already unsubscribed. Returnsfalseon failure to send the request. - Underlying GridScript:
context -c stopBlockchainUpdates - Response Event: No direct response event. Success stops the flow of update notifications.
- Async Version:
unsubscribeFromBlockchainUpdatesA(...)->Promise<boolean> - Example (Non-Async):
const vmContext = CVMContext.getInstance();
const processHandle = this;
if (vmContext.unsubscribeFromBlockchainUpdates(undefined, processHandle)) {
console.log("Unsubscription request sent successfully.");
} else {
console.error("Failed to send unsubscription request.");
}
5. Data Objects
The API uses several custom classes to represent blockchain data structures. These classes handle BER serialization/deserialization and provide convenient getters for accessing data.
5.1 CBlockDesc
Represents a blockchain block.
- Key Properties/Getters:
blockID: {string} Unique block identifier.height: {number} Block height.keyHeight: {number} Corresponding key block height.type: {eBlockType} Type of block (Key or Data).solvedAt: {number} Unix timestamp (seconds) when mined.minerID: {string} Address of the miner.parentID: {string} ID of the previous block.difficulty: {number} Mining difficulty.transactionsCount: {number} Number of transactions included.ergUsed: {BigInt} Computational units used.ergLimit: {BigInt} Maximum computational units allowed.blockReward: {BigInt} Base reward for mining the block (attoGNC).totalReward: {BigInt} Total reward including fees (attoGNC).transactions: {Array<CTransactionDesc>} Array of transaction objects included (if requested).size: {number} Size of the block in bytes.
- Serialization:
getPackedData()->ArrayBuffer(BER encoded). - Deserialization:
static instantiate(packedData)->CBlockDesc.
5.2 CTransactionDesc
Represents a blockchain transaction.
- Key Properties/Getters:
verifiableID: {string} Unique transaction identifier.blockID: {string} ID of the block containing the transaction (if confirmed).height: {number} Height of the block containing the transaction.keyHeight: {number} Key height of the block containing the transaction.sender: {string} Sender’s domain address.receiver: {string} Receiver’s domain address.value: {BigInt} Amount transferred (attoGNC).fee: {BigInt} Transaction fee paid (attoGNC).tax: {BigInt} Tax paid (attoGNC).type: {eTXType} Type of transaction.result: {eTransactionValidationResult} Validation result code.status: {string} Human-readable status (e.g., “Pending”, “Finalized (Safe)”). UseupdateStatus()orrefreshStatus()for accuracy.statusColor: {string} CSS color code for the status.confirmedTimestamp: {number} Unix timestamp (seconds) when confirmed.unconfirmedTimestamp: {number} Unix timestamp (seconds) when first seen.sourceCode: {string} GridScript source code (if applicable).log: {Array<string>} Execution log entries.ERGUsed: {BigInt} Computational units consumed.ERGLimit: {BigInt} Maximum computational units requested.nonce: {number} Sender’s transaction sequence number.size: {number} Size of the transaction in bytes.
- Serialization:
getPackedData()->ArrayBuffer(BER encoded). - Deserialization:
static instantiate(packedData)->CTransactionDesc. - Helper Methods:
async updateStatus(): Asynchronously fetches current heights and updates the status.refreshStatus(): Synchronously updates the status based on cached heights.
5.3 CDomainDesc
Represents a domain (account) on the blockchain.
- Key Properties/Getters:
domain: {string} The domain address.balance: {BigInt} Current available balance (attoGNC).lockedBalance: {BigInt} Balance locked in contracts or processes (attoGNC).txCount: {number} Total number of transactions (in + out).txInCount: {number} Number of incoming transactions.txOutCount: {number} Number of outgoing transactions.txTotalReceived: {BigInt} Total amount received (attoGNC).txTotalSent: {BigInt} Total amount sent (attoGNC).GNCTotalMined: {BigInt} Total GNC mined (attoGNC).identityToken: {CIdentityToken | null} Associated identity token object.securityInfo: {COperatorSecurityInfo | null} Associated security information.nonce: {number} Current nonce for the domain.
- Serialization:
getPackedData()->ArrayBuffer(BER encoded). - Deserialization:
static instantiate(packedData)->CDomainDesc.
5.4 CSearchResults
A container for search results returned by searchBlockchain, getRecentBlocks, getRecentTransactions, and getDomainHistory.
- Key Properties/Getters:
resultCount/getResultCount(): {number} Number of results in the current page.totalResultCount/getTotalResultCount(): {number} Total number of results available across all pages.currentPage/getCurrentPage(): {number} The current page number.itemsPerPage/getItemsPerPage(): {number} Number of items requested per page.results/getAllResults(): {Array<ResultData>} Array containing the actual result items for the current page.
- Key Methods:
getResult(index): {ResultData} Retrieves a specific result item by index. The item is wrapped inResultData. Useresult.getValue()to get the underlyingCBlockDesc,CTransactionDesc, orCDomainDesc.
- Serialization:
getPackedData()->ArrayBuffer(BER encoded). - Deserialization:
static instantiate(packedData)->CSearchResults.
5.5 CSearchFilter
Used to specify detailed search criteria beyond simple keywords.
- Key Concepts:
- Standard Flags: Predefined flags for common entity types (
TRANSACTIONS,DOMAINS,BLOCKS,ADDRESSES). Use bitwise OR (|) to combine. Access viaCSearchFilter.StandardFlags. ConstantsCSearchFilter.NO_STANDARD(0n) andCSearchFilter.ALL_STANDARDare available. - Arbitrary Flags: Custom key-value pairs for backend-specific filtering.
- Standard Flags: Predefined flags for common entity types (
- Key Methods:
constructor(flags): Creates a filter, optionally setting initial standard flags.setStandardFlags(...flags): Adds one or more standard flags.setArbitraryFlag(name, value): Sets a custom flag and its value (value defaults to empty string if omitted, booleanfalseremoves the flag).hasStandardFlag(flag): Checks if a standard flag is set.hasArbitraryFlag(name): Checks if a custom flag exists.getArbitraryFlagValue(name): Gets the value of a custom flag.toBytes(): Serializes the filter toUint8Array.toString(): Serializes the filter to a Base58Check encoded string (used when passing tosearchBlockchain).
- Static Methods:
fromBytes(buffer): Deserializes fromUint8Array.fromNumber(number): Creates a filter with only standard flags from a bitmask.
6. Event Handling
UI dApps interact with the API primarily through events. Register listeners using the add...Listener methods on the CVMContext instance.
Key Listener Methods for Blockchain Explorer API:
addNewSearchResultsListener(callback, appID): Handles responses fromsearchBlockchain,getRecentBlocks,getRecentTransactions,getDomainHistory,getMarketData(for balances). The callback receives aneventobject whereevent.resultsis aCSearchResultsinstance. Matchevent.reqIDto your original request ID.addNewBlockDetailsListener(callback, appID): Handles responses fromgetBlockDetails. The callback receiveseventwhereevent.datais aCBlockDescinstance.addNewTransactionDetailsListener(callback, appID): Handles responses fromgetTransactionDetails. The callback receiveseventwhereevent.datais aCTransactionDescinstance.addNewDomainDetailsListener(callback, appID): Handles responses fromgetDomainDetails. The callback receiveseventwhereevent.datais aCDomainDescinstance.addBlockchainStatsListener(callback, appID): Handles responses from various statistics methods likegetBlockchainStatus,getNetworkUtilization24h,getHeight,getUSDTPrice,getLiveness, etc. Theeventobject containsevent.type(a string identifying the statistic, e.g., ‘blockchainHeight’) andevent.data(containing the actual statistic value(s)).addNewGridScriptResultListener(callback, appID): A more general listener for GridScript results. Blockchain Explorer API responses might also trigger this, often containing BER-encoded data within theevent.datastructure that needs further parsing based on the original request context (event.reqID).
Important: Always remember to unregister listeners when they are no longer needed (e.g., when a UI component is destroyed) to prevent memory leaks, using CVMContext.unregisterEventListenerByID(listenerId).
7. Conclusion and Best Practices
- Use Async Methods: Prefer the
Asuffix methods (getBlockDetailsA, etc.) withasync/awaitfor cleaner code. - Handle Process Context: Always pass the UI dApp’s instance (
this) as theprocessHandleparameter where required. - Manage Request IDs: When using non-async methods, store the returned
reqIDand use it to correlate responses in your event listeners. - Check Event Data: In listeners, always check the type of the received data (e.g.,
event.results instanceof CSearchResults) before processing. - Unregister Listeners: Clean up listeners using
unregisterEventListenerByIDwhen they are no longer needed. - Error Handling: Wrap API calls in
try...catchblocks, especially when usingawait. Implement robust error handling in event listeners. - Use Data Object Getters: Access data using the provided getters (e.g.,
block.height,tx.valueTxt) on theCBlockDesc,CTransactionDesc, etc., objects. - Leverage Caching: Be aware that
CVMContextperforms some internal caching (e.g., forgetHeight). Use theallowCacheparameter in async methods if you need to force a refresh. - Consult
CTools: Utilize methods fromCTools.getInstance()for common formatting tasks (e.g.,formatGNCValue,formatByteSize,transactionStatusText).
This API provides a powerful interface for interacting with the GRIDNET blockchain. By understanding its architecture and utilizing the provided methods and data objects correctly, developers can build sophisticated and informative blockchain exploration tools within the GRIDNET OS ecosystem.
Appendix A
CSearchFilter Class Documentation
1. Overview
The CSearchFilter class is a fundamental component within the GRIDNET OS ecosystem for specifying criteria when searching the blockchain via the CVMContext Blockchain Explorer API. It provides a flexible and efficient mechanism to filter search results based on both predefined standard entity types (Blocks, Transactions, Domains, Addresses) and arbitrary, developer-defined custom flags.
This class is designed for use within UI dApps to construct search parameters that are then serialized and sent to GRIDNET Core nodes for processing. Its support for both standard and dynamic flags allows for powerful and extensible search capabilities across the decentralized network.
Rationale: Instead of using complex query strings or numerous parameters, CSearchFilter uses a combination of a bitmask for standard types and a map for custom key-value filters. This structure is easily serializable into a compact format suitable for network transmission within the GRIDNET Meta Data Protocol.
2. Key Features
- Standard Flags: Supports predefined flags for common blockchain entities (Transactions, Domains, Addresses, Blocks) using efficient bitwise operations.
- Arbitrary Flags: Allows developers to define and use custom flags (key-value pairs) for more granular or application-specific filtering processed by the backend.
- Serialization: Provides methods to serialize the filter state into:
- A compact byte array (
toBytes). - A Base58Check encoded string (
toString), suitable for embedding in GridScript commands used by the Blockchain Explorer API.
- A compact byte array (
- Deserialization: Allows recreating a
CSearchFilterinstance from:- A byte array (
fromBytes). - A number representing only standard flags (
fromNumber).
- A byte array (
- Flexibility: Combines the ease of use of standard flags with the extensibility of arbitrary flags.
- Readability: Offers a method (
getSearchDomainDescription) to get a human-readable summary of the active filters.
3. Class Definition
import { CTools } from '/lib/tools.js';
export class CSearchFilter {
// Static properties (StandardFlags, ALL_STANDARD, etc.)
// Constructor
// Methods (setStandardFlags, setArbitraryFlag, has…, toBytes, toString, etc.)
// Static methods (fromBytes, fromNumber)
// Private validation methods
}
4. Static Properties
StandardFlags
An object containing predefined BigInt values representing standard blockchain entity types. These flags can be combined using the bitwise OR operator (|).
TRANSACTIONS:1n << 0n(Value:1n) – Filter for transactions.DOMAINS:1n << 1n(Value:2n) – Filter for domains (accounts).ADDRESSES:1n << 2n(Value:4n) – Filter for addresses (often used interchangeably with domains).BLOCKS:1n << 3n(Value:8n) – Filter for blocks.
NO_STANDARD
A BigInt constant representing no standard flags set (Value: 0n). Useful for starting with a clean slate before adding specific standard flags.
ALL_STANDARD
A BigInt constant representing all standard flags combined (Value: 15n). This is not the default constructor value anymore (default is NO_STANDARD).
Constants
MAX_ARBITRARY_FLAGS: Maximum number of arbitrary flags allowed (currently 1,000,000 – a high theoretical limit).MAX_FLAG_NAME_LENGTH: Maximum length for an arbitrary flag name (256 characters).MAX_FLAG_VALUE_LENGTH: Maximum length for an arbitrary flag value (1024 characters).
5. Constructor
constructor(flags = CSearchFilter.NO_STANDARD)
Creates a new CSearchFilter instance.
- Parameters:
flags{bigint} [Optional, Default:CSearchFilter.NO_STANDARD] – An initial bitmask of standard flags to set. Only bits corresponding to definedStandardFlagsare considered.
- Throws:
TypeError: Ifflagsis not aBigInt.Error: Ifflagscontains bits not defined inStandardFlags.
6. Methods
setStandardFlags(...flags)
Sets one or more standard flags on the filter instance. This method uses bitwise OR, so it adds flags without removing existing ones unless you start with NO_STANDARD.
- Parameters:
...flags{(keyof typeof CSearchFilter.StandardFlags | bigint)} – A variable number of arguments, each being either:- A string matching a key in
CSearchFilter.StandardFlags(e.g.,"TRANSACTIONS"). - A
BigIntvalue corresponding to a standard flag (e.g.,CSearchFilter.StandardFlags.BLOCKS).
- A string matching a key in
- Returns: {
CSearchFilter} – TheCSearchFilterinstance for method chaining. - Throws:
Error: If an invalid flag name or value is provided.TypeError: If an argument is not a string or BigInt.
- Example:
const filter = new CSearchFilter(); // Starts with NO_STANDARD
filter.setStandardFlags("TRANSACTIONS", CSearchFilter.StandardFlags.BLOCKS);
// filter now searches for Transactions OR Blocks
setArbitraryFlag(flagName, value = '')
Sets a custom, arbitrary flag with an associated value. Arbitrary flags are used for backend-specific filtering beyond the standard types. If the value is boolean false, the flag is removed.
- Parameters:
flagName{string} – The name of the custom flag (case-sensitive). Must be non-empty and within length limits.value{string|number|bigint|boolean|ArrayBuffer} [Optional, Default:''] – The value associated with the flag.- Booleans:
truesets the flag with an empty string value,falseremoves the flag. - Numbers/BigInts: Converted to strings.
- ArrayBuffers: Decoded as UTF-8 strings.
- Strings: Used directly (must be within length limits).
- Booleans:
- Returns: {
CSearchFilter} – TheCSearchFilterinstance for method chaining. - Throws:
TypeError: IfflagNameis not a string orvalueis an unsupported type.Error: IfflagNameorvalueviolates length constraints or if the maximum number of arbitrary flags is exceeded.
- Example:
const filter = new CSearchFilter();
filter.setArbitraryFlag("block_type", "key"); // Search for key blocks
filter.setArbitraryFlag("min_height", 100000); // Search blocks >= height 100000
filter.setArbitraryFlag("HAS_CODE", true); // Flag existence (value stored as '')
filter.setArbitraryFlag("HAS_CODE", false); // Removes the "HAS_CODE" flag
setArbitraryFlagBoolean(flagName, value)
A convenience method equivalent to setArbitraryFlag(flagName, value) specifically for boolean values. true sets the flag (with an empty string value), false removes it.
- Parameters:
flagName{string} – The name of the custom flag.value{boolean} –trueto set the flag,falseto remove it.
- Returns: {
CSearchFilter} – TheCSearchFilterinstance for method chaining.
getArbitraryFlags()
Returns an iterator over the arbitrary flags currently set in the filter.
- Returns: {
IterableIterator<[string, string]>} – An iterator yielding[flagName, flagValue]pairs.
hasStandardFlag(flag)
Checks if a specific standard flag is currently set.
- Parameters:
flag{keyof typeof CSearchFilter.StandardFlags|bigint} – The standard flag to check (by name or BigInt value).
- Returns: {
boolean} –trueif the flag is set,falseotherwise. - Throws:
Error: If an invalid flag name or value is provided.TypeError: If the argument is not a string or BigInt.
hasArbitraryFlag(flagName)
Checks if a specific arbitrary flag exists (regardless of its value).
- Parameters:
flagName{string} – The name of the arbitrary flag.
- Returns: {
boolean} –trueif the flag exists,falseotherwise.
getArbitraryFlagValue(flagName)
Retrieves the string value associated with a specific arbitrary flag.
- Parameters:
flagName{string} – The name of the arbitrary flag.
- Returns: {
string} – The value of the flag, or an empty string ('') if the flag does not exist or was set withtrueor an empty string.
getArbitraryFlagCount()
Returns the number of arbitrary flags currently set.
- Returns: {
number} – The count of arbitrary flags.
getSearchDomainDescription()
Generates a human-readable string summarizing the currently active standard and arbitrary flags. Useful for logging or debugging.
- Returns: {
string} – A comma-separated description of the search domain (e.g.,"TRANSACTIONS, BLOCKS, block_type=key").
toBytes()
Serializes the entire filter state (version, standard flags, arbitrary flags count, and all arbitrary flag name-value pairs) into a compact binary format.
- Returns: {
Uint8Array} – The byte array representing the serialized filter. - Format:
[1 byte]Version (currently 1)[8 bytes]Standard Flags (BigUint64, little-endian)[4 bytes]Number of Arbitrary Flags (Uint32, little-endian)[variable]Sequence of Arbitrary Flags:[variable bytes]Flag Name (UTF-8)[1 byte]Null Terminator (\0)[variable bytes]Flag Value (UTF-8)[1 byte]Null Terminator (\0)- … (repeated for each flag)
toString()
Serializes the filter using toBytes() and then encodes the resulting byte array using Base58Check encoding. This is the format expected by the CVMContext.searchBlockchain API method’s flags parameter.
- Returns: {
string} – The Base58Check encoded string representation of the filter. - Dependencies: Relies on
CTools.getInstance().encodeBase58Check().
static fromBytes(buffer)
Deserializes a CSearchFilter instance from a byte array previously created by toBytes(). This method restores both standard and arbitrary flags (including names and values).
- Parameters:
buffer{Uint8Array} – The byte array containing the serialized filter data.
- Returns: {
CSearchFilter} – A newCSearchFilterinstance. - Throws:
TypeError: Ifbufferis not aUint8Array.Error: If the buffer is invalid, too short, contains an unsupported version, or exceeds limits.
static fromNumber(number)
Creates a CSearchFilter instance setting only the standard flags based on a provided number (bitmask). Arbitrary flags are not preserved or set by this method.
- Parameters:
number{bigint|number} – A number or BigInt where bits correspond to standard flags.
- Returns: {
CSearchFilter} – A newCSearchFilterinstance with only standard flags set.
7. Custom Flag Convention
As noted in the specification, while not enforced by the CSearchFilter class itself, a recommended convention for naming arbitrary flags when filtering based on object properties is:
OBJECT_NAME||_||PROPERTY_NAME
Where || denotes string concatenation.
- Examples:
block_height: To filter blocks based on theheightproperty ofCBlockDesc.transaction_sender: To filter transactions based on thesenderproperty ofCTransactionDesc.block_keyHeight: To filter based on thekeyHeightproperty.
Adhering to this convention helps maintain consistency when interacting with backend implementations that might expect these specific flag names for property-based filtering.
8. Usage Example (API Call)
import { CSearchFilter } from './searchFilter.js'; // Adjust path as needed
import { CVMContext } from './VMContext.js'; // Adjust path as needed
async function performAdvancedSearch(query) {
const vmContext = CVMContext.getInstance();
const processHandle = window.magicButton; // Assuming magicButton is the process handle
// Create a filter: search for Transactions OR Blocks, only key blocks
const filter = new CSearchFilter(CSearchFilter.NO_STANDARD); // Start empty
filter.setStandardFlags("TRANSACTIONS", "BLOCKS"); // Add standard flags
filter.setArbitraryFlag("block_type", "key"); // Add custom flag
console.log("Search Domain:", filter.getSearchDomainDescription());
// Output: Search Domain: TRANSACTIONS, BLOCKS, block_type=key
// Serialize for API call using toString() -> Base58Check(toBytes())
const filterString = filter.toString();
console.log("Serialized Filter for API:", filterString);
try {
// Use the async API method with the serialized filter string
const searchResults = await vmContext.searchBlockchainA(
query,
20, // size
1, // page
filterString, // Pass the Base58Check encoded filter string
undefined, // threadID (default)
processHandle
);
console.log(`Found ${searchResults.getTotalResultCount()} results.`);
// ... process results ...
} catch (error) {
console.error("Blockchain search failed:", error);
}
}
// Example usage:
performAdvancedSearch("some_query_term");
9. Best Practices and Notes
- Use Standard Flags First: Leverage the predefined
StandardFlagsfor common entity types (Transactions, Blocks, Domains, Addresses) as they are optimized and universally understood. - Arbitrary Flags for Extension: Use arbitrary flags for backend-specific or advanced filtering not covered by standard flags. Follow the naming convention (
OBJECT_NAME||_||PROPERTY_NAME) where applicable. - Serialization for API: Always use the
toString()method to get the Base58Check encoded representation when passing the filter toCVMContext.searchBlockchainorsearchBlockchainA. - Serialization for Storage: Use
toBytes()if you need to store the filter’s binary representation locally or send it through other channels expecting raw bytes. UsefromBytesto restore it. fromNumberLimitations: Remember thatstatic fromNumber(flags)only restores standard flags based on the provided bitmask. Arbitrary flags are lost in this conversion.- Immutability: Methods like
setStandardFlagsandsetArbitraryFlagmodify the instance in place and returnthisfor chaining.


