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

usingtellorpull

v0.1.0

Published

Tellor Layer → EVM pull oracle: fetch attested reports from Tellor Layer for use on Ethereum and other EVM chains

Readme

UsingTellorPull

Pull oracle: Tellor Layer → EVM. Fetch attested reports from Tellor Layer API, re-encode for EVM, include in your tx. Your contract verifies via Tellor's DataBridge and uses the value in one tx.

Use this package with your own npm project. See the SampleTellorUserPull repo for a complete usage example.

Contents

  • API – Fetch/encoding helpers + explicit pull modes (consensus-first, consensus-only, optimistic-only). Build output in dist/.

Flow

  • Caller uses this library to fetch attestation + validator set + signatures from Tellor Layer and encode them for EVM.
  • If the DataBridge's validator set is stale, caller uses getValsetUpdatePayloads to build update transactions (skip relay).
  • Caller passes attestData, validators, sigs into your contract (e.g. as calldata).
  • Your contract verifies via dataBridge.verifyOracleData(...) and uses the value in the same tx.

Assumption: User deploys on an EVM chain where Tellor's DataBridge is deployed.

Install

npm install usingtellorpull ethers

Quick start

Production integrations should bind the pull payload to the destination DataBridge state before submitting calldata. Your contract still verifies via DataBridge and must enforce application policy (expected queryId, freshness, power, and bounds) before using the value.

import {
  getVerifiedPullPayload,
  encodeBridgeCallArgsFromPayload,
  spotPriceQueryId,
  TELLOR_LAYER_API,
  type BridgeState,
} from "using-tellor-pull";

const queryIdHex = spotPriceQueryId("eth", "usd");

const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};

const payload = await getVerifiedPullPayload(queryIdHex, TELLOR_LAYER_API, bridgeState);
const { attestData, validators, sigs } = encodeBridgeCallArgsFromPayload(payload);
// Pass attestData, validators, sigs to your contract; it calls dataBridge.verifyOracleData(...)

getPullPayload is still available as a raw fetch/assembly helper, but production code should prefer getVerifiedPullPayload or the mode helpers with bridgeState so checkpoint and recovered signature power are checked before gas is spent.

Explicit pull modes

Use mode helpers when you want the library to enforce acceptance policy before you submit calldata.

import {
  getConsensusFirstPayload,
  getConsensusOnlyPayload,
  getOptimisticOnlyPayload,
  encodeBridgeCallArgsFromPayload,
  spotPriceQueryId,
  TELLOR_LAYER_API,
} from "using-tellor-pull";
import type { BridgeState } from "using-tellor-pull";

const queryId = spotPriceQueryId("eth", "usd");
const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};
const powerThreshold = Number(await dataBridge.powerThreshold());

const result = await getConsensusFirstPayload(queryId, TELLOR_LAYER_API, {
  bridgeState,
  filterOptions: { powerThreshold },
});

if (result.status !== "ok" || !result.payload) {
  console.log(result.status, result.reason, result.message);
  return;
}

const { attestData, validators, sigs } = encodeBridgeCallArgsFromPayload(result.payload);

Mode behavior:

  • getConsensusFirstPayload: matches SampleTellorUserPull semantics (consensus first, controlled optimistic fallback).
  • getConsensusOnlyPayload: requires consensus report + freshness checks.
  • getOptimisticOnlyPayload: requires optimistic report + freshness + dispute delay + optimistic power gate.

All mode helpers return a structured PullModeResult with status: "ok" | "unsatisfied" | "error" and reason.

Validator set skip relay

If the DataBridge's on-chain validator set is behind Layer, oracle attestations will fail verification. Use getValsetUpdatePayloads to update it before submitting oracle data:

import { getValsetUpdatePayloads, TELLOR_LAYER_API } from "using-tellor-pull";
import type { BridgeState } from "using-tellor-pull";

// Read the bridge's current state (ethers.js example)
const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};

// Loop until the bridge is caught up
while (true) {
  const payloads = await getValsetUpdatePayloads(bridgeState, TELLOR_LAYER_API);
  if (payloads.length === 0) break; // bridge is current
  for (const p of payloads) {
    const tx = await dataBridge.updateValidatorSet(
      p.newValsetHash, p.newPowerThreshold, p.newTimestamp,
      p.currentValidators, p.sigs
    );
    await tx.wait();
  }
  // Re-read bridge state for next iteration
  bridgeState.timestamp = (await dataBridge.validatorTimestamp()).toString();
  bridgeState.powerThreshold = (await dataBridge.powerThreshold()).toString();
  bridgeState.checkpoint = await dataBridge.lastValidatorSetCheckpoint();
}

Solidity

Your contract verifies attestations via Tellor's DataBridge. Get the DataBridge interface (structs + verifyOracleData) from Tellor's DataBridge repository. Off-chain production flow: getVerifiedPullPayload or a mode helper with bridgeStateencodeBridgeCallArgsFromPayload → pass attestData, validators, sigs to your contract. See SampleTellorUserPull for a full consumer example.

API (npm package)

| Function | Description | | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | getReport(queryIdHex, apiBase, options?) | Current aggregate value + timestamp for queryId. | | getAttestationBundle(queryIdHex, reportTimestamp, apiBase, options?) | Validator set + signatures for that report. | | getPullPayload(queryIdHex, apiBase, options?) | Raw report + attestation assembly. Validates returned queryId/timestamp, but does not check destination bridge state. | | getVerifiedPullPayload(queryIdHex, apiBase, bridgeState, options?) | Production helper: raw payload plus destination DataBridge checkpoint and recovered signature power checks. | | getConsensusFirstPayload(queryIdHex, apiBase, options?) | Consensus-first with controlled optimistic fallback (Sample-compatible defaults). | | getConsensusOnlyPayload(queryIdHex, apiBase, options?) | Consensus-only with freshness checks. | | getOptimisticOnlyPayload(queryIdHex, apiBase, options?) | Optimistic-only with freshness, delay, and power checks. | | encodeBridgeCallArgs(attestation) | { attestData, validators, sigs } for useOracleData. | | encodeBridgeCallArgsFromPayload(payload) | Same from PullPayload. | | spotPriceQueryId(asset, currency) | QueryId for SpotPrice (e.g. "btc", "usd"). | | spotPriceQueryIdBytes32(asset, currency) | Same as bytes32 (0x-prefixed) for Solidity. | | generateWithdrawalQueryId(withdrawalId) | TRBBridge withdrawal (Layer → Ethereum). | | generateDepositQueryId(depositId) | TRBBridge deposit (Ethereum → Layer). | | queryIdFromData(queryData) | Generic: keccak256(queryData). | | getValsetUpdatePayloads(bridgeState, apiBase, options?) | Skip relay: build updateValidatorSet payloads to bring the DataBridge up to date. |

Types: BridgeState, ValsetUpdatePayload, PullPayload, PullModeResult, PullModeOptions, VerifiedPullPayloadOptions, AttestationBundle, BridgeCallArgsEncodable, etc.

Constants: TELLOR_LAYER_API (https://mainnet.tellorlayer.com), LAYER_MAINNET_API, LAYER_TESTNET_API.

Fetch options (optional last param for getReport, getPullPayload, getAttestationBundle): { timeoutMs?: number, maxRetries?: number, reportTimestampMs?: number }. Default: 30s timeout, 2 retries with exponential backoff on 5xx/network errors.

When **reportTimestampMs** is set on getPullPayload (or on PullModeOptions passed to mode helpers), the client does not call get_current_aggregate_report; it only loads the attestation bundle for that report time. Use this with a real apiBase after you discover a report timestamp T (e.g. via npm run discover-report) so getOptimisticOnlyPayload can evaluate optimistic-only rules against Layer-backed signatures instead of the latest consensus aggregate.

import {
  getOptimisticOnlyPayload,
  encodeBridgeCallArgsFromPayload,
  spotPriceQueryId,
  TELLOR_LAYER_API,
} from "using-tellor-pull";
import type { BridgeState } from "using-tellor-pull";

const queryId = spotPriceQueryId("eth", "usd");
const reportTimestampMs = 1730000000000; // ms — must exist on Layer for this queryId
const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};
const powerThreshold = Number(await dataBridge.powerThreshold());

const result = await getOptimisticOnlyPayload(queryId, TELLOR_LAYER_API, {
  bridgeState,
  reportTimestampMs,
  filterOptions: { powerThreshold },
});

if (result.status !== "ok" || !result.payload) {
  console.log(result.status, result.reason, result.message);
  return;
}

const { attestData, validators, sigs } = encodeBridgeCallArgsFromPayload(result.payload);

Manual Sepolia fork (optional): point an Anvil/Hardhat fork at Sepolia, use Layer TELLOR_API with discover-report / getOptimisticOnlyPayload + reportTimestampMs, then submit encoded args to your contract. Environment-specific; not part of default CI.

Mode helper options: PullModeOptions = fetch options (including optional reportTimestampMs) + optional bridgeState + filterOptions:

  • nowSec (optional test override)
  • maxDataAgeSec (default 24h)
  • maxAttestationAgeSec (default 10m)
  • optimisticDelaySec (default 12h)
  • powerThreshold (required for optimistic checks)
  • requiredSignaturePower (optional; defaults to bridgeState.powerThreshold when bridgeState is supplied)

When bridgeState is supplied, mode helpers reject status: "ok" if the attestation checkpoint does not equal the destination DataBridge checkpoint or recovered signature power is below the configured threshold.

Raw vs production helpers

  • Use getVerifiedPullPayload or mode helpers with bridgeState for production calldata.
  • Use getPullPayload for inspection, tests, or custom flows that perform equivalent bridge-state checks elsewhere.
  • Use encodeBridgeCallArgsFromPayload only after the payload has passed your desired policy checks.

DataBridge verifies validator signatures and current validator-set quorum. It does not know the consumer's intended feed or business rules, so consuming contracts should also check:

  • attestData.queryId is the expected queryId.
  • attestData.report.timestamp and attestData.attestationTimestamp meet freshness requirements.
  • attestData.report.aggregatePower meets the integration's consensus/optimistic policy.
  • The decoded value is within application-specific bounds before state changes are made.

Testing this repo

This library is validated by unit tests (mocked fetch for deterministic mode logic), plus live API checks. For a full flow including contracts and e2e tests, see SampleTellorUserPull.

npm install
npm test         # deterministic unit tests
npm run test:smoke   # pull ETH/USD from mainnet API (requires network)
npm run live:modes   # live mode helper checks (requires network)
npm run discover-report -- <queryIdHex> <reportTimestampMs>   # inspect Layer bundle for T (requires network)

Secure Integrations

For secure integrations, refer to the Tellor docs. Also, see example integrations in the SampleTellorUserPull repo.

Repository

Maintainers

@themandalore @brendaloya

How to Contribute

Check out our issues log here on Github or in our Discord.

Contributors

This repository is maintained by the Tellor team - www.tellor.io

Copyright

Tellor Inc. 2026