Infrastructure

Data Architecture

PairStreet runs across three zones. Value lives onchain. The Pair Registry, the ledger and the indexer live offchain. Prices, quotes and issuer facts arrive from external sources. This chapter maps how they connect.

Three zones

A Pair MarketPair MarketThe canonical pairing of an internet asset with a financial Pair: TOKEN × PAIR INSTRUMENT, plus the Pair Vault, configuration and accounting that connect them. is assembled from facts held in different places. The token, its bonding curve, its fee-sharing config and every wallet balance are Solana accounts. The relationship between the token and its Pair InstrumentPair InstrumentThe financial exposure a Pair Market is paired with, such as Tokyo Residential or Swiss Government Debt. A catalog object with a provider, an eligibility policy and a status., the instrument catalog, the ledger and the demand data are PairStreet records in Postgres. Market statistics, SOL pricing, instrument quotes and issuer documentation come from external services.

The three zones carry three kinds of traffic. Value movement happens only onchain: SOL, tokens and Pair AssetsPair AssetThe transferable onchain asset the implementation acquires and distributes for a Pair Instrument. Holders receive the Pair Asset, not the reference market itself. move between accounts through signed transactions. Data flows from chain and from external sources into the offchain store. Metadata, such as issuer documents and eligibility terms, describes instruments without moving anything.

PairStreet system mapARCHITECTURE
ONCHAINOFFCHAIN / INDEXEDEXTERNALSolanaPump programPump fees programPumpSwap AMMWalletsPair Assets (SPL)Claim transactionsPair RegistryInstrument RegistryProvider metadataIndexerLedger (Postgres)Reward engineAnalyticsSearchEligibility metadataFinancial providers / issuersJupiter (quotes, SOL price)DexScreenerGeckoTerminalIssuer documentation
value movementdatametadataHover a component to trace its connections.
Solid lines move value, dashed lines carry data, dotted lines carry metadata. Value paths inside the onchain zone are listed in the table below the map. Claim transactions and holder-level indexing are part of the settlement architecture and activate per Pair Instrument route.

Figure summary: Three columns. Onchain: Solana, Pump program, Pump fees program, PumpSwap AMM, wallets, Pair Assets as SPL tokens, claim transactions. Offchain and indexed: Pair Registry, Instrument Registry, provider metadata, indexer, Postgres ledger, reward engine, analytics, search, eligibility metadata. External: financial providers and issuers, Jupiter for quotes and SOL price, DexScreener, GeckoTerminal, issuer documentation. Solid lines are value movement, dashed lines are data, dotted lines are metadata.

Value paths inside the onchain zone

Every value movement is a Solana transaction that a wallet signs. PairStreet builds the transaction; the wallet authorizes it; the programs below execute it.

Value paths onchain
FromToWhat movesProgram
WalletPump bonding curveSOL for tokens (buy) or tokens for SOL (sell)Pump program
WalletPairStreet treasury0.5% of the SOL side of a PairStreet-built trade, in the same transactionSystem Program transfer
Pump bonding curveFee-sharing configCreator fees accrued on the coin’s tradesPump program, Pump fees program
Fee-sharing configCreator wallet and treasuryAccrued creator fees, 50% / 50%, via distribute_creator_feesPump fees program
Bonding curvePumpSwap poolLiquidity at graduationPump program, PumpSwap AMM
Pair VaultHolder walletPair Asset claims against a reward epoch’s Merkle rootActivates per route

What each zone holds

Onchain

PairStreet composes Pump’s programs on Solana mainnet: the Pump program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P for creation, bonding-curve trading and graduation; the Pump fees program pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ for the per-mint fee-sharing config; and the PumpSwap AMM pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA where graduated coins trade. PairStreet deploys no program of its own today. See Pump and Solana for the division of responsibilities.

Pair Assets are issuer tokens on Solana. Five instruments in the catalog reference SPL assets with live onchain routes (USDY, CETES, GILTS, XAUt0, PAXG). Pair Vault custody and claim transactions are the settlement half of the onchain zone; they activate per Pair Instrument route.

Offchain and indexed

Pair Registry
The pair_markets table: one row per Pair Market binding a token to its Pair Instrument, with status, Ledger modeLedger modeEvery financial ledger row carries live or development. Production reads and writes live rows only., configuration (fee split, reward methodology, cadence, exclusions) and read-model aggregates.
Instrument Registry
The pair_instruments and pair_providers tables, upserted idempotently from the catalog at build time. 44 instruments today, each with category, provider, mint (where one exists), status, verification and reference price.
Provider metadata
Issuer, provider reference, transfer restrictions, price source and documentation URL per instrument.
Indexer
Ingestion sources with checkpoints. Every external fact enters through a source, never through per-wallet polling from the browser.
Ledger (Postgres)
Insert-oriented financial tables: pair_vault_fundings, pair_settlements, pair_purchases, reward_epochs, reward_allocations, reward_claims. See Accounting.
Reward engine
Pure functions that turn holder segments into weights, allocations and a Merkle root. Tested for exact pool allocation and proof verification.
Analytics
Aggregations of Pair Markets by instrument, category and country behind /analytics and What Is Crypto Buying?
Search
Instrument search terms (names, countries, synonyms) and Pair Market lookup, plus Pair Requests for instruments not yet listed.
Eligibility metadata
Rules in instrument_eligibility: allow or block countries and regions, KYC required, accredited only. Evaluated by the Eligibility EngineEligibility EngineEvaluates a viewer's region and verification state against a Pair Instrument's rules and returns allow or restrict before any Pair interaction..

External

External sources supply data and metadata only. None of them holds PairStreet value. Issuers such as Ondo Finance, Etherfuse, Tether Gold and Paxos publish the SPL assets that five instruments reference; PairStreet references their tokens and documentation and has no commercial arrangement with them. Jupiter supplies the SOL/USD price and the quotes for SPL instrument routes. DexScreener and GeckoTerminal supply market statistics and candles.

How a market page is assembled

A Pair Market page reads from the database first and refreshes from chain second. The database row is the read model; the refresh keeps it current. Rendering never waits on a slow external service for longer than a fixed bound.

  1. Step 01GET /token/[mint]
    Validate and read the read model

    The mint is checked against the base58 address pattern. getMarketByMint joins tokens, token_markets, pair_markets and pair_instruments, filtered to visible ledger modes. Production reads live rows only.

  2. Step 02refreshLiveMarket
    Refresh from chain, with a bound

    For a live market the page races a chain refresh against a 2.5 second timer. The refresh reads the Pump bonding-curve account, DexScreener and the SOL price in parallel, then patches token_markets. If the timer wins, the page renders the stored row and later polls bring the fresh values.

  3. Step 03eligibilityFor
    Re-read and evaluate eligibility

    The page re-reads the market, then evaluates the viewer’s eligibility for the instrument from the edge country header and the instrument’s rules, and loads the creator profile. These run in parallel.

  4. Step 04GET /api/markets/[mint]
    Client polling and after-response refresh

    The market API responds from the read model with cache-control: no-store and schedules a refresh after the response is sent (Next.js after). List endpoints refresh up to six live markets whose data is older than 30 seconds, in the background.

Live data sources

Each source is cached in process with a short time to live. A failed fetch never blanks a value: the last good value stays in place until the next successful read.

Live data sources and what each suppliesLIVE
Live data sources
SourceSuppliesCache / throttleOn failure
Pump bonding-curve account (Pump SDK over Solana RPC)Price, reserves, market cap, liquidity, bonding progress, graduation flagPer-mint refresh window, 10 to 30 sStored values remain
Pump fees program (sharing config)Shareholders, admin revoked flag, fee-split statusRead at launch confirmation and on the fees endpointLast recorded status remains
DexScreener24h volume, 24h change, transaction count, pool address, price and market cap after graduation20 sPrevious columns kept
GeckoTerminalOHLCV candles for the market’s pool (1m, 5m, 15m, 1h, 4h)45 sEmpty series; chart waits
Jupiter price API v3SOL/USD60 sLast good price
Jupiter quote APIUSDC to instrument routes, output amount, price impact, hops30 sRoute reports provider_unavailable with a blocker
Jupiter token APICanonical asset check for SPL instruments (verified tag, token program)10 minCatalog verification level used
Solana RPCLaunch transaction confirmation, treasury balance for the rent guardPer requestClient retries confirmation
Edge geo headerViewer country (x-vercel-ip-country)Per requestUnknown country under geographic rules resolves to UNKNOWN_REGION in production

Figure summary: Pump bonding-curve account: price, reserves, market cap, liquidity, bonding progress, graduation, refreshed per mint every 10 to 30 seconds. Pump fees program: fee-sharing config and split status. DexScreener: 24 hour volume, change, transactions, pool address and post-graduation price, cached 20 seconds. GeckoTerminal: OHLCV candles, cached 45 seconds. Jupiter price API: SOL/USD, cached 60 seconds. Jupiter quote API: instrument routes, cached 30 seconds. Jupiter token API: canonical asset verification, cached 10 minutes. Solana RPC: launch confirmation. Edge geo header: viewer country.

Quotes and token checks use a small in-process cache that is reserved for remote reads. Economic state is never cached this way: balances, settlements and allocations are always read from the ledger.

Indexing

Every external fact PairStreet shows enters through an indexer source. A source declares a name and an interval and processes everything after its cursor. Runs are idempotent, and each source keeps one checkpoint row with its last run time, status and last error.

src/server/indexer/index.tsIndexerSource
// src/server/indexer/index.ts
export interface IndexerSource {
  name: string;
  intervalMs: number;
  /** Process everything after `cursor`; return the new cursor. Must be idempotent. */
  run(cursor: string | null): Promise<string | null>;
}

// One checkpoint row per ingestion source.
// indexer_cursors: source (pk), cursor, last_run_at, status ("idle" | "ok" | "error"), error

On Vercel, background timers do not persist between invocations, so sources run as throttled, request-driven ticks scheduled after a response has been sent.

Indexer sources
IngestionFeedsStatus
Market-level chain refreshPrice, reserves, market cap, liquidity, progress and graduation per live marketLive
Fee-split readsPer-mint fee-sharing config recorded on the Pair MarketLive
Pump program event stream (Helius webhook or Geyser)Trades and holder balances decoded from Pump program events (decodeTradeEventBc, decodeCompleteEventBc), feeding live reward weightsIn integration
Pair Vault eventsVault deposits, acquisitions and claims for custody-enabled marketsActivates per route

Holder-level indexing is the input to reward epochs. The reward engine weights each wallet by balance held over time, so it needs every balance change with its block time, which the Pump event stream supplies.

Stack

Application
Next.js 16 with the App Router and React 19. Pages are server components; the API lives in route handlers under /api. The docs are served from the same application at docs.pairstreet.xyz.
Database
Postgres on Neon, accessed through Drizzle ORM with a small connection pool per instance. Image uploads and token metadata JSON are stored in Postgres so every serverless instance serves the same files.
Hosting
Vercel. Server secrets are encrypted environment variables; the edge supplies the viewer country.
Solana
@solana/web3.js for versioned transactions and RPC, @pump-fun/pump-sdk v2.0.0 for Pump instructions and curve math, the Solana wallet adapter for signing in the browser.
  • ·Every write endpoint validates its body with a schema and rejects bodies above 64 KB.
  • ·Every error returns the same envelope. See API.
  • ·Every ledger row carries its ledger mode, and production queries filter to live rows. See Accounting.