npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2026 – Pkg Stats / Ryan Hefner

relockeql

v5.3.1

Published

A GraphQL implementation for interacting with Relocke based blockchains.

Readme

relockeql logo

RelockeQL

NPM Package License: MIT CI

RelockeQL is a GraphQL client and server library that allows developers to interact with Relocke-based blockchains (EOSIO, WAX, Telos, XPR Network, Vaulta, and WIRE Network) using GraphQL. It provides a unified interface to communicate with different chains in the ecosystem, enabling developers and agentic tools to leverage the unique features and capabilities of each blockchain while still benefiting from a consistent development experience.

As a GraphQL client library, RelockeQL simplifies the process of building and executing GraphQL queries and mutations, handling errors, and signing transactions. As a server library, it provides a framework for building GraphQL APIs that can interact with Relocke-based blockchains and other data sources.

With RelockeQL, developers can focus on building the frontend and business logic of their DApps, while relying on the library to handle the complexities of interacting with multiple blockchains in the ecosystem.

Live working example can be found here.

relockeql screenshot

Supported chains

RelockeQL supports the following chains:

  • Jungle (jungle)
  • WAX (wax)
  • Vaulta (EOS) (vaulta)
  • Telos (telos)
  • XPR Network (xpr)
  • WIRE Network (wire)

This list is not an allowlist. Applications may configure any other compatible chain using their own GraphQL-safe chain name and explicit RPC and, where required, Hyperion endpoints.

Installation

For Node.js, to install RelockeQL and the peer dependency graphql run:

npm install relockeql graphql

Examples

See the examples folder on how to run RelockeQL as a Node.js endpoint.

Configure endpoints

RelockeQL does not choose network providers. Every RPC endpoint must be supplied by the application in the required chains option:

const endpoints = {
  vaulta: "https://your-vaulta-rpc.example",
  wax: "https://your-wax-rpc.example",
  wire: "https://your-wire-rpc.example"
};

Hyperion history endpoints are configured separately by prefixing the chain name with hyperion_. They do not create additional top-level GraphQL fields:

const endpoints = {
  vaulta: "https://your-vaulta-rpc.example",
  hyperion_vaulta: "https://your-vaulta-hyperion.example"
};

This explicit configuration prevents the package from silently sending requests to infrastructure that the application owner did not select.

Run the example HTTP server

The example server accepts the complete multi-chain endpoint map as JSON. Every configured RPC chain is exposed by the same GraphQL server, while matching hyperion_<chain> entries enable that chain's history queries. It does not contain fallback providers:

Copy the environment template. It contains the tested ReLocke RPC providers and the EOSphere Vaulta Hyperion provider; you may replace or extend the map with providers you select:

cp .env.example .env

The .env file is ignored by Git. Once configured, start the server normally:

npm run server

You can alternatively provide the same configuration inline:

RELOCKEQL_CHAINS='{
  "vaulta": "https://eos.relocke.io",
  "hyperion_vaulta": "https://vaulta-hyperion.eosphere.io",
  "telos": "https://telos.relocke.io",
  "xpr": "https://proton.relocke.io",
  "wax": "https://wax.relocke.io",
  "jungle": "https://jungle.relocke.io"
}' \
RELOCKEQL_CONTRACTS='{
  "vaulta": ["eosio.token", "eosio"],
  "telos": ["eosio.token"],
  "xpr": ["eosio.token"],
  "wax": ["eosio.token"],
  "jungle": ["eosio.token"]
}' \
npm run server

RELOCKEQL_CHAINS is required and may contain any number of tested or custom GraphQL-safe chain names. The server loads .env automatically when it exists, but still refuses to start without an explicit chain map. RELOCKEQL_CONTRACTS is an optional JSON map of chain names to contract account arrays. PORT defaults to 3002. Send GraphQL requests as JSON over HTTP POST; browser GET requests return 405 without stopping the server.

Serialize a contract ABI

serialize_abi converts an EOSIO-compatible ABI JSON document into the hexadecimal bytes required by eosio::setabi. Its self-contained encoder supports UTF-8 Ricardian text and ordered ABI 1.1/1.2 binary extensions without requiring an ABI serialization dependency.

import { serialize_abi } from "relockeql";

const rawAbi = serialize_abi({
  version: "eosio::abi/1.2",
  types: [],
  structs: [],
  actions: [],
  tables: [],
  ricardian_clauses: [
    { id: "ui.contract", body: "---\nschema: relocke.ui/1\n---\nPurpose" }
  ],
  error_messages: [],
  abi_extensions: []
});

Trailing binary-extension fields remain absent unless supplied. If action_results is present, variants must also be present because ABI binary extensions cannot skip an earlier field and then encode a later one.

Query a Blockchain Account Info

import { RelockeQL } from "relockeql";
import { sign_transaction } from "your-signing-library";

const query = /* GraphQL */ `
  {
    vaulta {
      get_blockchain {
        get_account(account_name: "relockeblock") {
          core_liquid_balance
          ram_quota
          net_weight
          cpu_weight
          ram_usage
        }
      }
    }
  }
`;

const { data } = await RelockeQL(
  { query },
  { chains: { vaulta: "https://your-vaulta-rpc.example" } }
);

console.log(data);

Logged output included an account infomation.

Query smart contract code and hashes

get_smart_contract resolves only the selected contract fields. For example, this query retrieves both deployment hashes with one raw-ABI RPC request and does not download the contract WASM:

const query = /* GraphQL */ `
  {
    vaulta {
      get_blockchain {
        get_smart_contract(account_name: "rloc") {
          abi_hash
          wasm_hash
        }
      }
    }
  }
`;

const { data } = await RelockeQL(
  { query },
  { chains: { vaulta: "https://your-vaulta-rpc.example" } }
);

The same field can select wasm and abi as base64-encoded content. A wasm_hash-only selection uses the dedicated code-hash endpoint, while compatible selections share in-flight RPC requests within the GraphQL operation.

Query a Contract Table

Contract table fields return the table rows together with the blockchain pagination metadata.

const query = /* GraphQL */ `
  {
    vaulta {
      eosio {
        powup_order(arg: { scope: "" }) {
          rows {
            id
            owner
            cpu_weight
            net_weight
          }
          more
          next_key
        }
      }
    }
  }
`;

const { data } = await RelockeQL(
  { query },
  {
    chains: { vaulta: "https://your-vaulta-rpc.example" },
    contracts: {
      vaulta: ["eosio"]
    }
  }
);

const page = data.vaulta.eosio.powup_order;

if (page.more) {
  console.log("Next lower bound:", page.next_key);
}

Query a transaction through Hyperion

get_transaction_by_id returns a normalized transaction and all of its actions. The action data field is decoded JSON, so callers do not need to parse a JSON string.

const query = /* GraphQL */ `
  {
    vaulta {
      get_blockchain {
        get_transaction_by_id(
          id: "690878b888dd70c339df268ae68019c097b1d4ded649a50c9b5723f734d84837"
        ) {
          transaction_id
          block_num
          timestamp
          executed
          actions {
            contract
            action
            actors
            receivers
            data
          }
        }
      }
    }
  }
`;

const result = await RelockeQL(
  { query },
  {
    chains: {
      vaulta: "https://your-vaulta-rpc.example",
      hyperion_vaulta: "https://your-vaulta-hyperion.example"
    }
  }
);

A Hyperion executed: false not-found response resolves to null. Missing, unavailable, timed-out, or malformed providers return GraphQL errors with specific extensions.code values.

List specific contract actions

get_actions requires a notified account, contract, and action name, which Hyperion combines as indexed account and contract:action filters. Omit both time boundaries to retrieve the latest matching actions. When after is supplied, the search window may span at most seven days. Searches request newest-first results, disable total-result counting, omit large binary data, default to 10 results, and return at most 25. They do not assume that a provider maintains Hyperion's optional hot-index alias. Offset, ascending scans, and arbitrary indexed-field filters are intentionally unavailable.

The optional after and before boundaries use the iso8601_datetime GraphQL scalar rather than unrestricted strings. It accepts YYYY-MM-DDTHH:mm:ss, optional fractional seconds, and an optional Z or ±HH:mm offset. For latest-action pagination, omit both boundaries on the first request and pass the oldest returned action timestamp as before on the next request. For explicit date-window pagination, keep after fixed and move before backward inside the seven-day window.

const latestQuery = /* GraphQL */ `
  {
    vaulta {
      get_blockchain {
        get_actions(
          account: "alice"
          contract: "eosio.token"
          action: "transfer"
          limit: 10
        ) {
          actions {
            transaction_id
            block_num
            timestamp
            data
          }
        }
      }
    }
  }
`;
const query = /* GraphQL */ `
  {
    vaulta {
      get_blockchain {
        get_actions(
          account: "alice"
          contract: "eosio.token"
          action: "transfer"
          after: "2026-08-08T10:00:00Z"
          before: "2026-08-15T10:00:00Z"
          limit: 10
        ) {
          query_time_ms
          actions {
            transaction_id
            block_num
            timestamp
            data
          }
        }
      }
    }
  }
`;

const result = await RelockeQL(
  { query },
  {
    chains: {
      vaulta: "https://your-vaulta-rpc.example",
      hyperion_vaulta: "https://your-vaulta-hyperion.example"
    }
  }
);

Hyperion resource policy for block producers

ReLockeQL history queries are read-only HTTP requests. They do not submit blockchain transactions or consume on-chain CPU, NET, or RAM. They do consume the selected provider's API capacity, outbound bandwidth, and Hyperion/Elasticsearch CPU and I/O.

get_actions is intentionally narrower than the underlying Hyperion endpoint. A valid request produces one upstream request shaped like this:

GET /v2/history/get_actions
  ?account=<notified-account>
  &filter=<contract>:<action>
  &after=<optional-ISO-8601-lower-bound>
  &before=<optional-ISO-8601-upper-bound>
  &limit=<1-25>
  &sort=desc
  &track=false
  &noBinary=true

The library enforces the following provider protections before sending that request:

  • Notified account, contract, and action are required.
  • Omitting both time boundaries retrieves the latest matching actions.
  • When a lower time boundary is supplied, a request may cover no more than seven days.
  • The default result limit is 10 and the hard maximum is 25.
  • track=false prevents total-result counting.
  • noBinary=true excludes large binary action payloads.
  • Only newest-first ordering is available; ascending scans are not exposed.
  • Offset pagination, arbitrary indexed-field filters, and unbounded result counts are not exposed.
  • The selected Hyperion provider receives one request with an eight-second timeout and no fallback request to another producer.
  • Returned actions are rejected unless they still match the requested notified account, contract, and action.

get_transaction_by_id makes one exact transaction-ID lookup against the selected provider. It does not perform a broad action search or fall back to another endpoint.

These controls bound the cost of an individual query; they cannot limit how many queries a public deployment receives. API operators should additionally apply per-user or per-credential rate limits, concurrency limits, short-lived deduplication for identical reads, and provider monitoring. Hyperion operators remain free to enforce stricter reverse-proxy limits and Elasticsearch query timeouts.

Cache transaction bodies and refresh headers

serialize_transaction only performs the work required by its selected output fields. A body-only selection serializes the actions without requesting current chain or reference-block data, so applications can cache the deterministic body while the actions, authorization, order, and contract ABI remain unchanged:

mutation CacheTransactionBody {
  wax {
    serialize_transaction(actions: [...]) {
      transaction_body
    }
  }
}

When the cached body needs a fresh expiration and reference block, submit the same action input but select only the live values. ReLockeQL skips action serialization for this request:

mutation RefreshTransactionHeader {
  wax {
    serialize_transaction(actions: [...]) {
      chain_id
      transaction_header
    }
  }
}

Combine the refreshed chain_id and transaction_header with the cached transaction_body, then calculate a new signing hash. Selecting hash or non-empty required_keys automatically builds all of their required transaction components. ReLockeQL does not persist transaction bodies across GraphQL operations; applications control the cache lifetime and must invalidate entries when any serialized input or the contract ABI changes.

Transfer Tokens

import { RelockeQL } from "relockeql";

const query = /* GraphQL */ `
  mutation {
    jungle {
      send_transaction(
        actions: [
          {
            eosio_token: {
              transfer: {
                authorization: { actor: "relockeblock" }
                to: "relockechain"
                from: "relockeblock"
                memo: ""
                quantity: "0.0002 EOS"
              }
            }
          }
        ]
      ) {
        transaction_id
        block_num
      }
    }
  }
`;

const { data } = await RelockeQL(
  { query },
  {
    chains: { jungle: "https://your-jungle-rpc.example" },
    contracts: {
      // List your smart contract accounts for each chain.
      jungle: ["eosio.token"]
    },
    signTransaction: async (hash) => {
      const wif_private_key = "PVT_K1_…"; // your private key
      const signature = await sign_transaction({ hash, wif_private_key });
      return [signature]; // signatures must return array
    }
  }
);

console.log(data);

Logged output includes transaction_id and block_num

Requirements

Supported runtime environments: