Schemas
The relational model behind every Pair Market: the token’s internet market on one side, the financial Pair and its ledger on the other, and the status enums that govern both.
Two histories per Pair Market
PairStreet stores each 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. as two separate histories. The internet market (the coin, its Pump curve, trades, candles and holders) lives in tokens, token_markets, trades and holder_balances. The financial Pair (the instrument, the vault, settlements, purchases and rewards) lives in pair_markets and the ledger tables beneath it. The two never share a row. Market cap describes the first history; Pair ValuePair ValueThe current tracked value of Pair Assets associated with a Pair Market according to PairStreet accounting: Σ quantity × reference price. Independent of the token's market cap. describes the second.
The schema is Postgres, defined with Drizzle. Three conventions hold across every table:
- *_raw
- Integer base-unit amounts as
numeric(40,0), read as decimal strings. No floating-point drift in balances or allocations. - *_usd
numeric(24,6)read as numbers. Display and aggregation values, never the source of truth for a balance.- ledger_mode
- Every financial row carries
liveordev_simulated. Production reads and writesliverows only. See Ledger modeLedger modeEvery financial ledger row carries live or development. Production reads and writes live rows only..
- pair_vault_fundingsIN
Economic value credited to a market’s Pair Vault, by source.
- pair_settlementsPLAN
One row per settlement run: amount, route mode, persisted plan, status.
- pair_purchasesACQUIRE
Each acquisition: input mint and amount, output amount, execution price, signature.
- reward_epochsEPOCH
The pool, methodology, total weight and Merkle root for one epoch.
- reward_allocationsALLOCATE
One row per eligible wallet per epoch: weight and amount.
- reward_claimsOUT
Claims paid to holders, linked back to the allocations they settle.
Figure summary: Value enters through pair_vault_fundings, is converted in pair_settlements and pair_purchases, is divided in reward_epochs and reward_allocations, and leaves through reward_claims. pair_markets and pair_vaults are read models rebuilt from these rows.
Pair Market
Table pair_markets. One row per token (token_id is unique): the canonical TOKEN × 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. relationship. The aggregate columns are a read model maintained by the Pair engine from the ledger tables.
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. The pairMarketId used across the API. |
| tokenId | uuid → tokens | The launched coin. Unique: a token has exactly one Pair Market. |
| pairInstrumentId | uuid → pair_instruments | The Pair Instrument this market is PAIRED WITH. |
| creatorWallet | text → wallets | The creator’s wallet. |
| pumpLaunchAddress | text | The Pump bonding curve account. |
| pumpMarketAddress | text, nullable | The PumpSwap pool once the coin graduates. |
| pairVaultAddress | text, nullable | The market’s Pair Vault. Set when vault custody activates for the instrument’s route. |
| status | pair_market_status | pending, active, paused, settlement_disabled, closed. Default active. |
| ledgerMode | ledger_mode | live on mainnet. |
| configuration | jsonb | PairMarketConfiguration: economic sources, reward rules, fee split. See below. |
| pairValueUsd | numeric(24,6) | Tracked value of Pair Assets held for this market. |
| pairAssetBalanceRaw | numeric(40,0) | Pair Asset currently held, in the instrument’s base units. |
| pairAssetAcquiredLifetimeUsd | numeric(24,6) | USD value of all Pair Asset acquired. |
| pairAssetAcquiredLifetimeRaw | numeric(40,0) | Base units of all Pair Asset acquired. |
| holderRewardsLifetimeUsd | numeric(24,6) | Value allocated to holders across all epochs. |
| holderRewardsClaimableUsd | numeric(24,6) | Allocated and not yet claimed. |
| holderRewardsClaimedUsd | numeric(24,6) | Claimed by holders. |
| eligibleHolders | integer | Eligible holders in the latest epoch. |
| settlementsCount | integer | Completed settlements. |
| nextSettlementAt | timestamptz, nullable | Next scheduled settlement. Null while settlement is disabled. |
| lastSettlementAt | timestamptz, nullable | Most recent settlement. |
| createdAt | timestamptz | Registration time. |
| graduatedAt | timestamptz, nullable | When the coin graduated from the curve. |
Live markets register with status settlement_disabled (shown as “Settlement pending”) and nextSettlementAt null. Each instrument’s settlement route and vault custody activate the status change to active. See Pair Markets for the lifecycle.
PairMarketConfiguration
The configuration column holds the rules that turn trading activity into Pair Asset for holders. New markets get PairStreet’s default configuration; the feeSplit block is written from the chain by the fee-split sync after launch.
| Field | Type | Meaning |
|---|---|---|
| economicSources | { source, bps? }[] | Streams that fund the Pair VaultPair VaultThe account that receives settlement value allocated to one Pair Market, holds it until conversion, and holds the acquired Pair Asset until it is allocated to holders.. Sources: creator_fees, launch_economics, protocol_fees, other. bps appears only when explicitly configured. |
| rewardMethodology | enum | time_weighted_balance (default), average_balance or snapshot_min_hold. |
| epochReleaseBps | number, optional | Share of unallocated Pair Asset released to holders each epoch. Absent means not configured. |
| settlementCadenceSec | number | Seconds between settlements. Default 3600 (hourly). |
| minHoldingRaw | string, optional | Minimum balance for eligibility, in token base units. |
| excludeCreator | boolean | Creator wallet excluded from rewards. Default true. |
| excludeLiquidityAccounts | boolean | Curve and pool accounts excluded. Default true. |
| excludedWallets | string[] | Further wallets excluded from rewards. |
| feeSplit | object, optional | The creator-fee split as read from chain. Fields below. |
| feeSplit field | Type | Meaning |
|---|---|---|
| creatorBps | number | 5000: creator share of creator fees. |
| protocolBps | number | 2500: PairStreet protocol share. |
| pairVaultBps | number | 2500: Pair Vault reserve share. |
| treasury | string | The PairStreet treasury wallet that receives the 50% on-chain share (protocol plus reserve). |
| status | locked | pending | mismatch | locked: Pump reports creator 50%, treasury 50% with admin revoked. pending: no split yet. mismatch: a different split. |
| sharingConfig | string, optional | The Pump fee-sharing config account for this mint. |
| shareholders | { address, shareBps }[], optional | Shareholders exactly as stored on-chain. |
| checkedAt | ISO timestamp | When the chain was last read. |
{
"economicSources": [
{ "source": "creator_fees", "bps": 2500 },
{ "source": "launch_economics" }
],
"rewardMethodology": "time_weighted_balance",
"settlementCadenceSec": 3600,
"excludeCreator": true,
"excludeLiquidityAccounts": true,
"excludedWallets": [],
"feeSplit": {
"creatorBps": 5000,
"protocolBps": 2500,
"pairVaultBps": 2500,
"treasury": "5XAwPtXHkA2F68tEj5ZAZePJfJWH4tzGkeQiqK5ggfRg",
"status": "locked",
"sharingConfig": "<sharing-config-pda>",
"shareholders": [
{ "address": "<creator-wallet>", "shareBps": 5000 },
{ "address": "5XAwPtXHkA2F68tEj5ZAZePJfJWH4tzGkeQiqK5ggfRg", "shareBps": 5000 }
],
"checkedAt": "<timestamp>"
}
}On-chain there are two shareholders. The 50/25/25 split is the accounting view: the treasury’s 50% is protocol revenue (25%) plus the market’s Pair Vault reservePair Vault reserveThe 25% share of a Pair Market's creator fees earmarked for its Pair Vault. Held by the PairStreet treasury until the market's settlement route activates. (25%). That is why economicSources lists creator_fees at 2,500 bps. See Protocol Economics.
Pair Instrument
Table pair_instruments. The catalog of financial exposures a creator can pair with. 44 instruments today. The slug is the stable human key used in URLs and the API; the id is a UUID.
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| slug | text, unique | Stable key, for example tokyo-residential. |
| name, shortName, symbol | text | Display names and the instrument symbol (TKYRES). |
| description | text | What exposure the instrument represents. |
| category | instrument_category | countries, bonds, housing, real_estate, credit, equities, sectors, commodities, rates, funds, crypto, other. |
| subcategory | text, nullable | Free-form, for example Sovereign or Residential. |
| country | text | ISO-3166 alpha-2; XX for global. |
| region | region | americas, europe, asia, middle_east, africa, global. |
| providerId | text → pair_providers | The provider that lists or delivers the instrument. |
| issuer | text, nullable | Issuer of the onchain asset, when one exists. |
| network | text | solana. |
| mintAddress | text, nullable | The Pair Asset mint. Null for registry-listed instruments until their route connects. |
| decimals | integer | Pair Asset decimals. Default 6. |
| assetType | asset_type | sovereign_bond, municipal_bond, corporate_credit, treasury_note, real_estate, housing_index, equity_index, sector_basket, commodity, fund, rate, other. |
| settlementAsset | text | The settlement assetSettlement assetThe asset a Pair Vault accumulates before conversion. USDC by default. mint the router spends: USDC. |
| status | instrument_status | active, paused, coming_soon, provider_unavailable, deprecated. |
| verification | instrument_verification | How the onchain asset is verified. Enum below. |
| isMock | boolean | True only for development-network instruments. False across the mainnet catalog. |
| transferRestrictions | jsonb, nullable | { summary, tokenProgram? }: how the asset transfers. |
| priceSource | text, nullable | Reference source: jupiter for onchain assets, index-reference for registry listings. |
| providerReference | text, nullable | The provider’s key: spl:<mint> or registry:<slug>. |
| documentationUrl | text, nullable | Issuer documentation. |
| icon, heroImage | text, nullable | UI glyph key and optional hero image. |
| referencePriceUsd, referencePriceAt | numeric(24,6), timestamptz | Last reference price and when it was taken. |
| searchTerms | text | Space-separated synonyms used by search. |
| metadata | jsonb | Additional instrument metadata. Default {}. |
| createdAt, updatedAt | timestamptz | Row timestamps. |
Example record
The Tokyo Residential record as the catalog stores it. Tokyo Residential is a Pair Instrument representing the target financial exposure configured for the Pair Market. It is listed by the PairStreet Pair Registry, so mintAddress is null and verification is listed: settlement into a Pair Asset activates when its provider route connects.
{
"id": "<instrument-uuid>",
"slug": "tokyo-residential",
"name": "Tokyo Residential",
"shortName": "Tokyo Residential",
"symbol": "TKYRES",
"description": "Exposure to Tokyo's residential property market: condominiums and rental housing across the 23 wards, tracked as a residential real-estate basket.",
"category": "real_estate",
"subcategory": "Residential",
"country": "JP",
"region": "asia",
"providerId": "pairstreet-registry",
"issuer": "PairStreet Pair Registry",
"network": "solana",
"mintAddress": null,
"decimals": 6,
"assetType": "housing_index",
"settlementAsset": "<usdc-mint>",
"status": "active",
"verification": "listed",
"isMock": false,
"transferRestrictions": { "summary": "Onchain settlement asset connects when this Pair's provider route goes live." },
"priceSource": "index-reference",
"providerReference": "registry:tokyo-residential",
"documentationUrl": null,
"icon": "home",
"heroImage": null,
"referencePriceUsd": 100,
"referencePriceAt": "<timestamp>",
"searchTerms": "tokyo housing homes residential property real estate japan condo apartments rent japan",
"metadata": {},
"createdAt": "<timestamp>",
"updatedAt": "<timestamp>"
}Spec fields and where they live
- provider
providerId, joined topair_providersfor name, kind and adapter.- restrictions
transferRestrictionson the instrument, plus eligibility rules ininstrument_eligibility.- reference source
priceSource, withreferencePriceUsdandreferencePriceAt.- documentation
documentationUrl; the provider interface also returns issuer documents.
instrument_eligibility
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| instrumentId | uuid → pair_instruments | The instrument the rule applies to. Cascades on delete. |
| rule | eligibility_rule | allow_countries, block_countries, allow_regions, block_regions, kyc_required, accredited_only. |
| countries | text[] | ISO alpha-2 codes the rule names. |
| regions | text[] | Regions the rule names. |
| note | text, nullable | Why the rule exists, for example issuer terms. |
pair_providers
id (stable slug, also the adapter registry key), name, kind (provider_kind), adapterKey (registry or spl-onchain today), website, description, isMock, status and createdAt. See Providers.
Pair Vault
Table pair_vaults. One vault per Pair Market. A vault row is written when the market’s vault custody activates; until then a live market’s Pair Vault reserve accrues to the treasuryPairStreet treasuryThe protocol wallet that receives the protocol share and Pair Vault reserve of creator fees plus the 0.5% trading fee., earmarked per market, and the market detail API reports custodyModel: "pending". See Pair Vault.
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| pairMarketId | uuid → pair_markets, unique | The market this vault serves. |
| address | text | Vault address. |
| custodyModel | custody_model | dev_simulated, program_pda, multisig, provider_custody. |
| settlementAssetMint | text | Mint of the asset the vault accumulates before conversion. |
| settlementBalanceRaw / Usd | numeric | Settlement asset awaiting conversion. |
| pairAssetBalanceRaw | numeric(40,0) | Pair Asset held, acquired and not yet claimed. |
| totalDepositedUsd | numeric(24,6) | Lifetime value credited. |
| totalConvertedUsd | numeric(24,6) | Lifetime value converted into Pair Asset. |
| totalAllocatedUsd | numeric(24,6) | Lifetime value allocated to holders. |
| totalClaimedUsd | numeric(24,6) | Lifetime value claimed by holders. |
| ledgerMode, updatedAt | ledger_mode, timestamptz | Ledger mode and last update. |
pair_vault_fundings
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| vaultId | uuid → pair_vaults | Vault credited. |
| pairMarketId | uuid → pair_markets | Market credited. |
| source | economic_source | creator_fees, launch_economics, protocol_fees, other. |
| amountRaw | numeric(40,0) | Amount in settlement-asset base units. |
| usdValue | numeric(24,6) | USD value at funding time. |
| txSignature | text, nullable | The funding transaction. |
| ledgerMode, createdAt | ledger_mode, timestamptz | Ledger mode and time. |
Settlement and purchase
A settlementSettlementOne turn of a Pair Market's flywheel: the Pair Vault balance is routed, the Pair Asset acquired, accounting finalized and a reward epoch funded. converts a vault’s settlement balance into the Pair Asset through the Pair RouterPair RouterThe execution layer that converts a Pair Vault's settlement balance into an acquisition plan for the Pair Asset and hands it to the right executor.. The plan is persisted for audit, and each acquisition is its own row. See Settlement.
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| pairMarketId, vaultId | uuid | Market and vault settled. |
| sequence | integer | Per-market sequence number. Unique with pairMarketId. |
| status | settlement_status | scheduled, planning, executing, completed, failed, cancelled. |
| routeMode | route_mode | ONCHAIN_SWAP, PROVIDER_API, RFQ, ISSUER_MINT, BROKER_ROUTE, DEV_SIMULATED. |
| settlementAmountRaw / Usd | numeric | Value settled. |
| plan | jsonb | The Pair Router acquisition plan, persisted for audit. |
| error | text, nullable | Failure reason. |
| ledgerMode | ledger_mode | Ledger mode. |
| startedAt, completedAt | timestamptz | Start and finish. |
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| settlementId | uuid → pair_settlements | The settlement this acquisition belongs to. |
| pairMarketId, instrumentId | uuid | Market and instrument. |
| providerId | text → pair_providers | Provider that executed. |
| routeMode | route_mode | Route used. |
| inputMint, inputAmountRaw, inputUsd | text, numeric | What was spent. |
| outputAmountRaw, outputUsd | numeric | Pair Asset received. |
| executionPriceUsd | double | Effective price per Pair Asset unit. |
| txSignature | text, nullable | Execution transaction. |
| status | purchase_status | planned, submitted, confirmed, failed. |
| ledgerMode, executedAt | ledger_mode, timestamptz | Ledger mode and time. |
Reward epoch, allocation and claim
A reward epochReward EpochA window over which acquired Pair Asset is allocated to eligible holders by their holder weight. Produces exact integer allocations and a Merkle root. divides the Pair Asset acquired in a settlement across eligible holders by holder weightHolder WeightA holder's share basis inside a reward epoch. Under the time-weighted method: the integral of balance over time held inside the epoch (token-seconds).. Allocations sum exactly to the pool, and the epoch stores a Merkle root over (wallet, amountRaw) leaves for an onchain distributor. See Holder Rewards.
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| pairMarketId | uuid → pair_markets | Market. |
| epochNumber | integer | Unique per market. |
| startAt, endAt | timestamptz | Epoch window. |
| methodology | reward_methodology | time_weighted_balance, average_balance, snapshot_min_hold. |
| rewardInstrumentId | uuid → pair_instruments | The instrument REWARDS PAID IN. |
| totalPoolRaw / Usd | numeric | Pair Asset distributed in this epoch. |
| eligibleHolderCount | integer | Holders with non-zero weight. |
| totalWeight | numeric(60,0) | Sum of holder weights. |
| allocationRoot | text, nullable | Merkle root over allocation leaves. |
| status | epoch_status | open, calculating, allocated, finalized. |
| ledgerMode | ledger_mode | Ledger mode. |
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| epochId | uuid → reward_epochs | Epoch. Unique with wallet. |
| pairMarketId | uuid → pair_markets | Market. |
| wallet | text | Holder wallet. |
| weight | numeric(60,0) | The holder’s weight under the epoch methodology. |
| amountRaw, usdValue | numeric | Pair Asset allocated. |
| status | allocation_status | claimable, claimed, expired. Default claimable. |
| claimId | uuid → reward_claims, nullable | The claim that settled this allocation. |
| ledgerMode, createdAt | ledger_mode, timestamptz | Ledger mode and time. |
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| wallet | text | Claiming wallet. |
| pairMarketId, instrumentId | uuid | Market and the instrument paid. |
| amountRaw, usdValue | numeric | Amount claimed. |
| txSignature | text, nullable | Claim transaction. |
| status | claim_status | pending, confirmed, failed. |
| ledgerMode, createdAt | ledger_mode, timestamptz | Ledger mode and time. |
Pair Request
Demand for instruments not yet in the catalog. Requests aggregate by a normalized key, and each voter counts once. See Pair Requests.
| Column | Type | Meaning |
|---|---|---|
| id | uuid | Primary key. |
| normalizedKey | text, unique | Normalized title used to merge duplicate requests. |
| title, description | text | What was requested. |
| country | text, nullable | ISO alpha-2. |
| category | instrument_category, nullable | Requested category. |
| requestCount | integer | Distinct voters. |
| creatorInterestCount | integer | Voters who intend to launch a market on it. |
| status | pair_request_status | open, under_review, planned, live, declined. |
| matchedInstrumentId | uuid → pair_instruments, nullable | The instrument added for this request. |
| createdAt, updatedAt | timestamptz | Row timestamps. |
pair_request_votes holds one row per voter per request (requestId, voterKey, wallet, creatorIntent, note), unique on request and voter. The voter key is the wallet when one is connected, otherwise an anonymous visitor id.
Token and token market
The internet-market side, summarized. These tables are written by launch and kept current by the indexer.
- tokens
id,mint(unique),name,symbol,description,imageUrl,website,twitter,telegram,creatorWallet,launchVenue(pump),decimals(6),totalSupplyRaw,metadataUri,launchTxSignature,ledgerMode,createdAt.- token_markets
- Latest venue state, one row per token:
bondingCurveAddress,ammPoolAddress, reserves (reserveQuoteRaw,reserveTokenRaw,realQuoteRaw),priceUsd,priceSol,marketCapUsd,liquidityUsd,volume24hUsd,volumeLifetimeUsd,change24hPct,holders,txns24h,bondingProgressPct,graduationStatus,graduatedAt,trendingScore,lastTradeAt,updatedAt. - trades
- One row per trade: side, token and quote (lamport) amounts, USD value, price, signature, block time.
- holder_balances
- Balance per token and wallet,
firstHeldAt, andexcludedReasonfor accounts excluded from Pair rewards (creator, vault, curve or pool, configured). - supporting
wallets,creator_profiles,activity_events(see Events),protocol_metrics(daily snapshots for analytics),indexer_cursors,uploadsandmetadata_docs.
Status enums
Every enum is defined once in the shared domain module and generated into Postgres. The API returns these exact strings.
Pair Market and token
| Enum | Value | Meaning |
|---|---|---|
| pair_market_status | pending | Registration not yet complete. |
| active | Settlement runs on the configured cadence. | |
| paused | Pair activity paused by the protocol. | |
| settlement_disabled | Trading and fee accrual live; settlement activates with the instrument’s route and vault custody. Shown as “Settlement pending”. | |
| closed | Pair Market closed. | |
| graduation_status | bonding | Trading on the Pump bonding curve. |
| graduating | Bonding progress at or above 75%. | |
| graduated | Curve complete; the coin trades on PumpSwap. |
Instrument and provider
| Enum | Value | Meaning |
|---|---|---|
| instrument_status | active | Accepting new Pair Markets. |
| paused | Temporarily closed to new markets. | |
| coming_soon | Announced, not yet selectable. | |
| provider_unavailable | The provider route is unavailable; selection reopens when it returns. | |
| deprecated | Retired; closed to new Pair Markets. | |
| instrument_verification | dev_mock | Development network only. |
| listed | Listed for pairing; the onchain settlement asset connects with the provider route. | |
| issuer_listed | Mint published by the issuer and routable. | |
| aggregator_verified | Verified by a token-list aggregator such as Jupiter. | |
| pairstreet_verified | Reviewed by PairStreet. | |
| provider_kind | tokenized_bonds, tokenized_securities, tokenized_fund, real_estate, commodity, onchain_dex_route, pair_registry, dev_mock | The kind of provider behind an instrument. |
| eligibility_rule | allow_countries, block_countries, allow_regions, block_regions, kyc_required, accredited_only | Rule types evaluated by the Eligibility Engine. |
Settlement, rewards and ledger
| Enum | Values | Used by |
|---|---|---|
| route_mode | ONCHAIN_SWAP, PROVIDER_API, RFQ, ISSUER_MINT, BROKER_ROUTE, DEV_SIMULATED | pair_settlements, pair_purchases |
| settlement_status | scheduled, planning, executing, completed, failed, cancelled | pair_settlements |
| purchase_status | planned, submitted, confirmed, failed | pair_purchases |
| custody_model | dev_simulated, program_pda, multisig, provider_custody | pair_vaults |
| economic_source | creator_fees, launch_economics, protocol_fees, other | pair_vault_fundings, configuration |
| reward_methodology | time_weighted_balance, average_balance, snapshot_min_hold | reward_epochs, configuration |
| epoch_status | open, calculating, allocated, finalized | reward_epochs |
| allocation_status | claimable, claimed, expired | reward_allocations |
| claim_status | pending, confirmed, failed | reward_claims |
| ledger_mode | live, dev_simulated | Every financial row |
| pair_request_status | open, under_review, planned, live, declined | pair_requests |
| activity_type | TOKEN_CREATED, TOKEN_TRADE, GRADUATED, PAIR_SELECTED, PAIR_VAULT_FUNDED, PAIR_ASSET_PURCHASED, PAIR_SETTLEMENT, PAIR_REWARD_ALLOCATED, PAIR_REWARD_CLAIMED, PAIR_REQUESTED, PAIR_INSTRUMENT_ADDED, PAIR_INSTRUMENT_PAUSED | activity_events |
Categories, regions and asset types are listed with the Pair Instrument columns above. The HTTP shapes built from these tables are documented in API.