Blockchain Explorer API Documentation

No Comment Yet

 

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:

  1. Decentralized Nature: Unlike traditional client-server models, requests are processed by the distributed network of GRIDNET Core nodes. CVMContext handles selecting appropriate nodes (based on proximity or randomness) and managing the connection (typically WebSocket).
  2. CVMContext: This singleton JavaScript object is the main entry point for all interactions with the GRIDNET OS backend, including the Blockchain Explorer API.
  3. GridScript: Under the hood, most Blockchain Explorer API calls are translated into specific #GridScript commands (e.g., context -c getBlockDetails ...). These commands are sent to a Core node for execution within a secure, sandboxed environment.
  4. 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).
  5. 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 (A suffix, returning a Promise) methods.
  6. 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) with CVMContext to receive and process these responses.
  7. 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. CVMContext handles the encoding/decoding internally.
  8. Security: Communication can be secured using end-to-end encryption and authentication mechanisms managed by CVMContext based 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 unique request 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 the reqID field in the event argument.
  • Async (Promise-based): Methods ending with A (e.g., getBlockDetailsA(...)) return a JavaScript Promise. 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 CVMContext methods (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).
    • data or 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

  1. API Call: The UI dApp calls an API method (e.g., CVMContext.getTransactionDetails(...)).
  2. Request ID Generation: CVMContext generates a unique request identifier (reqID).
  3. GridScript Formulation: The API method formats the corresponding #GridScript command.
  4. Dispatch: CVMContext (via processGridScriptKM) sends the command (encapsulated in Meta Data) over the network. The non-async method returns the reqID immediately. The async method registers the Promise internally using this reqID.
  5. Network Processing: GRIDNET Core nodes process the request.
  6. Response Delivery: The result is sent back via WebSocket, BER-encoded within the Meta Data protocol.
  7. Response Processing: CVMContext receives the message, decrypts/authenticates if necessary, parses the Meta Data, and identifies the relevant data and original reqID.
  8. Notification/Resolution:
    • CVMContext triggers 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, CVMContext finds the corresponding pending Promise using the reqID and resolves it with the data (via resolvePendingRequest).

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 ArrayBuffer is provided, it usually defaults to a system-managed thread (often the main Data Thread, accessible via CVMContext.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 (like CBlockDesc) 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 a CSearchResults object containing CTransactionDesc instances).
  • 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 from eSortBlocksBy enum).
    • 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 a CSearchResults object containing CBlockDesc instances).
  • 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 argument arg.data contains 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();

<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 argument arg.data contains status information like totalSupply, 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 (-d flag).
    • getBalances {boolean} [Optional, Default: true] – If true, retrieve domain balances (-b flag).
    • 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 (ascending or descending).
    • 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/or addNewSearchResultsListener (for domain balances, delivered in CSearchResults containing CDomainDesc).
  • Async Version: getMarketDataA(...) -> Promise<Object> (The resolved object structure depends on getMarketCap and getBalances flags).
  • 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 CSearchFilter instance 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.
      • 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 a CSearchResults object, 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");

 


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 (Event arg.data contains 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 (Event arg.data contains 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 (Event arg.data contains 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 uses getAverageBlockTime24h GridScript, might be an inconsistency).
  • Response Event: addBlockchainStatsListener (Event arg.data contains 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 (Event arg.data contains 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 (-tx flag).
    • includeMem {boolean} [Optional, Default: false] – (Likely unused for block details, but present in signature) Include mempool data (-mem flag).
    • includeSec {boolean} [Optional, Default: false] – If true, include a security report related to the block/miner (-sec flag).
    • 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 (Event arg.data contains a CBlockDesc instance).
  • 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 a CSearchResults object containing CTransactionDesc instances 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 (-sec flag).
    • 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 (Event arg.data contains a CDomainDesc instance).
  • 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 if transactionID is invalid.
  • Underlying GridScript: context -c getTransactionDetails -search "<transactionID>"
  • Response Event: addNewTransactionDetailsListener (Event arg.data contains a CTransactionDesc instance).
  • 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 (Event arg.data contains the liveness state, typically a value from eLivenessState enum).
  • 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 (Event arg.data contains 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 same reqID (potentially generated) if returning a cached value via a scheduled event.
  • Underlying GridScript: context -c getHeight [-key]
  • Response Event: addNewGridScriptResultListener (Event arg.data contains the height number). The method internally uses caching (mCachedHeight, mCachedKeyHeight) and may return a cached value via a setTimeout event if allowCache is true (in async version) and the cache is fresh.
  • Async Version: getHeightA(isKeyHeight, ..., allowCache) -> Promise<number> (The allowCache parameter 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) or true if already subscribed. Returns false on 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) or true if already unsubscribed. Returns false on 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)”). Use updateStatus() or refreshStatus() 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 in ResultData. Use result.getValue() to get the underlying CBlockDesc, CTransactionDesc, or CDomainDesc.
  • 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 via CSearchFilter.StandardFlags. Constants CSearchFilter.NO_STANDARD (0n) and CSearchFilter.ALL_STANDARD are available.
    • Arbitrary Flags: Custom key-value pairs for backend-specific filtering.
  • 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, boolean false removes 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 to Uint8Array.
    • toString(): Serializes the filter to a Base58Check encoded string (used when passing to searchBlockchain).
  • Static Methods:
    • fromBytes(buffer): Deserializes from Uint8Array.
    • 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 from searchBlockchain, getRecentBlocks, getRecentTransactions, getDomainHistory, getMarketData (for balances). The callback receives an event object where event.results is a CSearchResults instance. Match event.reqID to your original request ID.
  • addNewBlockDetailsListener(callback, appID): Handles responses from getBlockDetails. The callback receives event where event.data is a CBlockDesc instance.
  • addNewTransactionDetailsListener(callback, appID): Handles responses from getTransactionDetails. The callback receives event where event.data is a CTransactionDesc instance.
  • addNewDomainDetailsListener(callback, appID): Handles responses from getDomainDetails. The callback receives event where event.data is a CDomainDesc instance.
  • addBlockchainStatsListener(callback, appID): Handles responses from various statistics methods like getBlockchainStatus, getNetworkUtilization24h, getHeight, getUSDTPrice, getLiveness, etc. The event object contains event.type (a string identifying the statistic, e.g., ‘blockchainHeight’) and event.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 the event.data structure 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 A suffix methods (getBlockDetailsA, etc.) with async/await for cleaner code.
  • Handle Process Context: Always pass the UI dApp’s instance (this) as the processHandle parameter where required.
  • Manage Request IDs: When using non-async methods, store the returned reqID and 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 unregisterEventListenerByID when they are no longer needed.
  • Error Handling: Wrap API calls in try...catch blocks, especially when using await. Implement robust error handling in event listeners.
  • Use Data Object Getters: Access data using the provided getters (e.g., block.height, tx.valueTxt) on the CBlockDesc, CTransactionDesc, etc., objects.
  • Leverage Caching: Be aware that CVMContext performs some internal caching (e.g., for getHeight). Use the allowCache parameter in async methods if you need to force a refresh.
  • Consult CTools: Utilize methods from CTools.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.
  • Deserialization: Allows recreating a CSearchFilter instance from:
    • A byte array (fromBytes).
    • A number representing only standard flags (fromNumber).
  • 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 defined StandardFlags are considered.
  • Throws:
    • TypeError: If flags is not a BigInt.
    • Error: If flags contains bits not defined in StandardFlags.

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 BigInt value corresponding to a standard flag (e.g., CSearchFilter.StandardFlags.BLOCKS).
  • Returns: {CSearchFilter} – The CSearchFilter instance 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: true sets the flag with an empty string value, false removes the flag.
      • Numbers/BigInts: Converted to strings.
      • ArrayBuffers: Decoded as UTF-8 strings.
      • Strings: Used directly (must be within length limits).
  • Returns: {CSearchFilter} – The CSearchFilter instance for method chaining.
  • Throws:
    • TypeError: If flagName is not a string or value is an unsupported type.
    • Error: If flagName or value violates 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} – true to set the flag, false to remove it.
  • Returns: {CSearchFilter} – The CSearchFilter instance 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} – true if the flag is set, false otherwise.
  • 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} – true if the flag exists, false otherwise.

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 with true or 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 new CSearchFilter instance.
  • Throws:
    • TypeError: If buffer is not a Uint8Array.
    • 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 new CSearchFilter instance 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 the height property of CBlockDesc.
    • transaction_sender: To filter transactions based on the sender property of CTransactionDesc.
    • block_keyHeight: To filter based on the keyHeight property.

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 StandardFlags for 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 to CVMContext.searchBlockchain or searchBlockchainA.
  • 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. Use fromBytes to restore it.
  • fromNumber Limitations: Remember that static fromNumber(flags) only restores standard flags based on the provided bitmask. Arbitrary flags are lost in this conversion.
  • Immutability: Methods like setStandardFlags and setArbitraryFlag modify the instance in place and return this for chaining.
GRIDNET

Author

GRIDNET

Up Next

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *