gitstock
For developers

Docs.

gitstock resolves what the chain doesn't expose: which Chainlink feed belongs to which stock token, and the quirks that quietly break integrations. Read a price the right way, or consume gitstock as a data source. where code meets capital.

Read a price correctly

// Read any Robinhood Chain stock price correctly. ethers v6.
// Get the feed proxy from gitstock: GET /<SYMBOL>/stock.json → feed.proxy
import { ethers } from "ethers";
const feed = new ethers.Contract(feedProxy, [
  "function latestRoundData() view returns (uint80,int256,uint256,uint256,uint80)",
  "function decimals() view returns (uint8)"
], provider);

const dec = await feed.decimals();        // read it, don't hardcode
const rd  = await feed.latestRoundData();
const price = Number(ethers.formatUnits(rd.answer, dec)); // token price (stock × multiplier)
const stale = now - Number(rd.updatedAt) > 86400;      // 24h heartbeat = the guard
// do NOT gate on the L2 sequencer feed — it's hardwired to 'down' on this chain.

Prefer viem?

// Same read, with viem
import { createPublicClient, http, parseAbi } from "viem";

const client = createPublicClient({ transport: http(RPC) });
const abi = parseAbi([
  "function latestRoundData() view returns (uint80,int256,uint256,uint256,uint80)",
  "function decimals() view returns (uint8)"
]);

const [, answer, , updatedAt] = await client.readContract({
  address: feedProxy, abi, functionName: "latestRoundData" });
const dec = await client.readContract({ address: feedProxy, abi, functionName: "decimals" });

const price = Number(answer) / 10 ** dec;   // token price — already × uiMultiplier
const stale = now - Number(updatedAt) > 86400; // the real guard

React (wagmi)

// React — wagmi, ticking every 30s
const { data } = useReadContract({
  address: feedProxy,
  abi,
  functionName: "latestRoundData",
  query: { refetchInterval: 30_000 },
});

README badge

A live price badge for your repo — refreshes every few minutes, links back to the token's page.

NVDA live badge

<!-- live price badge for your README — swap NVDA for any symbol -->
[![NVDA](https://gitstock.io/NVDA/badge.svg)](https://gitstock.io/NVDA)

The SDK

Everything below, wrapped: npmjs.com/package/gitstock — typed, zero dependencies, plus the on-chain constants (FEED_ABI, ADDRESSES, isStale).

# zero-dep client — works in Node ≥18, browsers, edge
npm i gitstock

import { getStock, getRegistry, isStale, FEED_ABI, ADDRESSES } from "gitstock";

const nvda = await getStock("NVDA");
nvda.price.usd     // guarded live price (already stock × multiplier)
nvda.feed.proxy    // canonical Chainlink proxy for on-chain reads
nvda.fieldNotes    // the quirks that break integrations

const { tokens } = await getRegistry(); // all factory-verified tokens

Consume gitstock (no RPC)

Every token is machine-readable. Point at these and skip the on-chain plumbing entirely.

// One token, fully resolved (no RPC):
GET https://gitstock.io/NVDA/stock.json

// The whole registry (all tokens, addresses, feed proxies):
GET https://gitstock.io/registry.json

// Watch new tokens pairing against stocks (newest first):
GET https://gitstock.io/dependents.json

// The guarded price series (30-day retention):
GET https://gitstock.io/NVDA/history.json

/<SYMBOL>/stock.json returns metadata, guarded live price, holders, pool TVL, dependents, field notes and the sequencer state. /registry.json lists every token with its canonical feed proxy. /<SYMBOL>/history.json returns the indexed price series. CORS is open — fetch these from any origin, browser or server. Also: /llms.txt for AI assistants, /dependents.rss to watch new pairings in your feed reader.

Verify it yourself

Don't trust gitstock either. Every real stock token was created by the factory below — match the token's TokenCreated event, never a symbol. Impostor tokens with identical tickers exist on this chain.

Token factory
0x4783C67b63dE2B358Ac5951a7D41F47A38F3C046 explorer ↗
Beacon / registry
0xe10b6f6B275de231345c20D14Ab812db62151b00 explorer ↗

The quirks — what the docs don't tell you

The price feed is not on the token

The Stock token carries no price and no feed pointer on-chain — no latestRoundData(), no priceFeed(). The Chainlink feed is a separate, unlinked contract, and the token→feed mapping isn't published anywhere. gitstock resolves it for you (verified via the token factory's own creation events, not by symbol).

The L2 sequencer gate is hardwired to “down”

Robinhood ships a custom SequencerGate whose source() is currently the zero address — so latestRoundData() returns answer = 1 (down) forever, while the price feeds are healthy. Copy the standard Chainlink pattern require(sequencerUp == 0) and your app will never render a price here. Read the gate for transparency, but don't hard-gate on it yet.

Staleness is the real guard — and it's market-aware

Because the sequencer gate is unusable, freshness on the feed itself is the actual safety check. During US market hours the feed updates every ~17min–1h on deviation; off-hours it slows to a few hours but keeps moving (24/5). A single tight threshold false-flags overnight reads. Weekend-flat is normal, not stale.

Feed price is the TOKEN price, not the stock price

latestRoundData() already returns stock_price × uiMultiplier() — don't apply the multiplier again. Dividends reinvest through the multiplier, so the token tracks total return and drifts above the headline stock price over time. That's why the number here won't match Google Finance.

oraclePaused() is advisory, not enforced

During corporate actions the token oracle is paused. oraclePaused() == true means “price temporarily unavailable”, not zero/error — and it isn't enforced on-chain, so a paused oracle can still return a value. Treat it as a display state; rely on staleness for protection.

Read decimals() on-chain; don't hardcode

Feed answers use the feed's own decimals (8 for these USD feeds). Read decimals() from the proxy every time rather than assuming.