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

@nadohq/nuanze-client

v0.50.0

Published

HTTP client for the Nuanze public analytics API - markets, wallets, trades, candles, flows, positioning, and open positions

Readme

@nadohq/nuanze-client

HTTP client for the Nuanze public analytics API. Serves markets, wallets, trades, candles, collateral flows, positioning, and globally ranked current open positions. Read-only and credential-free, so unlike the other service clients it takes no wallet client or linked signer. Leaderboard lookups take explicit public identifiers and require no authentication: collection viewer lookups take a wallet address (getLeaderboard viewAs) or bytes32 subaccount hex (getSubaccountLeaderboard and getFollowedLeaderboard viewAs), while dedicated point reads (getWalletLeaderboardPosition, getSubaccountLeaderboardPosition, getFollowedLeaderboardPosition) fetch one rank by path identifier.

Full SDK Documentation

Usage

import { NuanzeClient, NUANZE_CLIENT_ENDPOINTS } from '@nadohq/nuanze-client';

const nuanze = new NuanzeClient({
  url: NUANZE_CLIENT_ENDPOINTS.inkMainnet,
});

const { markets, asOf } = await nuanze.getMarkets({ venue: 'perp' });

It is also available on a NadoClient context, configured from the chain env like the other service clients:

const markets = await nadoClient.context.nuanzeClient.getMarkets();

Nuanze runs a single public deployment that serves mainnet data, so every entry in NUANZE_CLIENT_ENDPOINTS points at the same host.

Market selectors

Scoped market methods (getMarketByTicker, getMarketTrades, getMarketCandles, getMarketPositioning, and getMarketPositions) require at least ticker or productId. When both are supplied, productId is used for the path segment and ticker is ignored.

// Ticker only (case-insensitive; canonical ticker or legacy symbol)
const eth = await nuanze.getMarketByTicker({ ticker: 'ETH' });

// Product ID only
const ethPerp = await nuanze.getMarketByTicker({ productId: 4 });

// Both: productId wins; ticker is ignored (BTC here is only illustrative)
const candles = await nuanze.getMarketCandles({
  ticker: 'BTC',
  productId: 4,
  interval: '1h',
});

API Surface

Each method maps one-to-one onto a public GET operation:

  • getNews
  • getMarkets
  • getMarketByTicker
  • getFundingRates
  • getLeaderboard
  • getWalletLeaderboardPosition
  • getSubaccountLeaderboard
  • getSubaccountLeaderboardPosition
  • getPlatformSummary
  • getFollowedLeaderboard
  • getFollowedLeaderboardPosition
  • getWalletSummary
  • getWalletPositions
  • getMarketTrades
  • getMarketCandles
  • getWalletTrades
  • getWalletPnl
  • getWalletPnlSeries
  • getCollateralFlows
  • getCollateralFlowSummary
  • getCollateralFlowSeries
  • getMarketPositioning
  • getMarketPositions
  • getOpenPositions

Decimal fields are mapped to BigNumber; timestamps stay UTC ISO 8601 strings, matching the API contract. All leaderboard collections accept an optional viewAs viewer selector: getLeaderboard takes an EVM address and returns the wallet's full row plus rank as viewer; getSubaccountLeaderboard and getFollowedLeaderboard take a bytes32 subaccount hex and return { filteredRank, item } as viewer. A viewer is null when viewAs is omitted or has no source row (for the followed leaderboard: when the follower does not actively follow it). For subaccounts, privacy, trading, and username-claim filters define the filtered-rank population without removing an existing full item or its globalRank; exclusion sets only filteredRank to null. On the followed leaderboard filteredRank counts only the follower's filter-passing followed subaccounts, while globalRank stays global.

The dedicated point reads coexist with viewAs: getWalletLeaderboardPosition({ address }) GETs /leaderboard/wallets/{address}, getSubaccountLeaderboardPosition({ subaccountHex }) GETs /leaderboard/subaccounts/{subaccountHex}, and getFollowedLeaderboardPosition({ subaccountHex, viewAs }) GETs /wallets/leaderboard/followed/{viewAs} scoped to the subaccountHex follower, each returning the same row shape without pagination. Use a point read when only one rank is needed; use viewAs for an inline lookup scoped to a ranked page. Position item is null only when no leaderboard source row exists for the identifier, and a filter-excluded subaccount keeps its full item (including globalRank) with filteredRank null.

const board = await nuanze.getLeaderboard({
  timeframe: '30d',
  limit: 10,
  viewAs: '0x1234567890123456789012345678901234567890',
});
if (board.viewer) {
  console.log(board.viewer.rank, board.viewer.accountPnl.toFixed());
}

const subs = await nuanze.getSubaccountLeaderboard({
  timeframe: '30d',
  viewAs: '0x1234...0012',
});
if (subs.viewer) {
  console.log(subs.viewer.filteredRank, subs.viewer.item?.globalRank);
}

const position = await nuanze.getWalletLeaderboardPosition({
  address: '0x1234567890123456789012345678901234567890',
  timeframe: '30d',
});
if (position.item) {
  console.log(position.item.rank, position.item.accountPnl.toFixed());
}

const subPosition = await nuanze.getSubaccountLeaderboardPosition({
  subaccountHex: '0x1234...0012',
  timeframe: '30d',
});
if (subPosition.item) {
  console.log(subPosition.filteredRank, subPosition.item.globalRank);
}

const followedPosition = await nuanze.getFollowedLeaderboardPosition({
  subaccountHex: '0xabcd...0000', // follower
  viewAs: '0x1234...0012', // followed subaccount to position
  timeframe: '30d',
});
if (followedPosition.item) {
  console.log(followedPosition.filteredRank, followedPosition.item.globalRank);
}

Errors

Failures arrive as NuanzeServerFailureError, carrying errorCode (comparable against NUANZE_ERROR_CODES), httpStatus, and the requestId to quote when reporting the failure.

License

ISC