> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rekt.money/llms.txt
> Use this file to discover all available pages before exploring further.

# Read the protocol

> Read the protocol from a cluster, price an open before you send it, and see exactly what a trader would be charged.

This page goes from an empty file to a priced, gated open — reading only, sending nothing. It is
the sequence every client performs before it shows anyone a button. For a bot that also sends,
start with the [Quickstart](/sdk/quickstart).

<Note>
  Everything here is a **read**. No keys, no signatures, nothing spent. Sending is
  [the next page](/sdk/opening).
</Note>

## 1. Read the protocol

Three accounts describe the whole system: the config (every governed parameter), the vault (the
pool), and one market per asset. Their addresses are derived locally, so you never have to trust an
address printed on a web page.

```ts read-protocol.ts theme={"dark"}
import { Connection, PublicKey } from '@solana/web3.js';
import {
  assetId,
  chainNowSeconds,
  configPda,
  decodeConfig,
  decodeMarket,
  decodeVault,
  marketPda,
  vaultGauges,
  vaultPda,
  type ConfigView,
  type MarketView,
  type VaultGauges,
  type VaultView,
} from '@rekt/1000x';

export interface Protocol {
  config: ConfigView;
  vault: VaultView;
  gauges: VaultGauges;
  market: MarketView;
  nowUnix: bigint;
  nowSlot: bigint;
}

async function mustRead(connection: Connection, address: PublicKey, what: string) {
  const info = await connection.getAccountInfo(address, 'confirmed');
  if (!info) throw new Error(`${what} does not exist at ${address.toBase58()}`);
  return new Uint8Array(info.data);
}

export async function readProtocol(connection: Connection, symbol: string): Promise<Protocol> {
  const config = decodeConfig(await mustRead(connection, configPda().address, 'the config'));
  const vault = decodeVault(await mustRead(connection, vaultPda().address, 'the vault'));
  const market = decodeMarket(
    await mustRead(connection, marketPda(assetId(symbol)).address, `the ${symbol} market`),
  );

  // The pool's gauges need the vault's own token balance, read from the account the vault names.
  const vaultToken = new PublicKey(Buffer.from(vault.tokenAccount, 'hex'));
  const balance = await connection.getTokenAccountBalance(vaultToken, 'confirmed');

  const nowSlot = await connection.getSlot('confirmed');
  // The chain's clock, never this machine's: the program judges against `Clock.unix_timestamp`.
  // `getBlockTime` on one recent slot can answer null or throw; `chainNowSeconds` walks back to a
  // slot that answers.
  const nowUnix = BigInt(await chainNowSeconds(connection));

  return {
    config,
    vault,
    gauges: vaultGauges(vault, BigInt(balance.value.amount)),
    market,
    nowUnix,
    nowSlot: BigInt(nowSlot),
  };
}
```

<Warning>
  **Never cache `config.params`.** Every field in it is governed and can move on chain without a
  program upgrade. Re-read it, and show the reader how old your copy is.
</Warning>

## 2. Read how the market is priced

An instruction that reads a price carries a **signed quote inside the transaction**, not a price
account you can read, so a read-only client has no price to fetch from the chain. What it can read
is the shape of the market's oracle: which kind it is, and the floors a settle or a `stamp_book` must clear.

```ts read-oracle.ts theme={"dark"}
import { benchmarkSourceFloor, settlementIdentity, type MarketView } from '@rekt/1000x';

export function oracleShape(market: MarketView) {
  const identity = settlementIdentity(market);
  return {
    // 'benchmark' with `pull: true`: the price rides in the caller's own transaction.
    vendor: identity.vendor,
    pull: identity.pull,
    // The fewest distinct oracle signatures a quote must carry.
    minSignatures: market.minSignatures,
    // The fewest sources a quote must aggregate to settle.
    settleSources: benchmarkSourceFloor(market, 'settle'),
    // How many slots old a quote may be when the program reads it.
    maxAgeSlots: market.maxOracleAgeSlots,
  };
}
```

[Quotes and freshness](/sdk/quotes) is the reference for the quote itself: how a transaction carries
it, and the checks the program applies.

## 3. Price the open before you offer it

`openPreview` answers everything a trader needs to see, for the exact terms they are about to
take, at the parameters currently in force.

```ts preview.ts theme={"dark"}
import { openPreview, type ConfigView, type MarketView } from '@rekt/1000x';

export function quote(config: ConfigView, market: MarketView, nowUnix: bigint) {
  // The fourth argument is the rung in basis points of stake: 20_000 is 2.00x, the floor below
  // which the protocol will not price a take-profit. A bare `2` here asks for 2 bps and refuses.
  const preview = openPreview(config, market, 1_000_000n, 20_000, nowUnix);

  return {
    collateral: preview.collateral,   // what is at risk
    entryFee: preview.entryFee,       // taken from inside the budget; 0 at an entry fee of 0
    totalDebit: preview.totalDebit,   // what actually leaves the wallet
    maxPayout: preview.maxPayout,     // the gross payout at the target, before the exit fee and the share of the gain the terms withhold
    reserved: preview.reserved,       // its maximum payout and closing fee; the pool sets aside only the stake
    barrierPayout: preview.barrierPayout, // what the trader receives at the barrier
    barrierMicroBp: preview.barrierMicroBp,
    takeProfitMicroBp: preview.takeProfitMicroBp,
  };
}
```

<Note>
  Show `barrierPayout` next to the confirm button, at the same visual weight as the payout you are
  excited about — see [the venue](/venue#what-you-sign-on-an-open).
</Note>

## 4. Ask what would refuse it

Before you build a transaction, ask the SDK which gate would stop it. `openGates` evaluates the
refusals the program raises for an open, in the program's order.

<Note>
  An open carries no quote: the fill judges the price, and the price rows do not decide the order.
  See [orders and closes](/sdk/orders). The checks a quote meets are in
  [quotes and freshness](/sdk/quotes#what-the-program-checks).
</Note>

```ts what-would-refuse.ts theme={"dark"}
import { openGates, type GateReport, type OpenContext, type OpenRequest } from '@rekt/1000x';

export function whatWouldRefuse(ctx: OpenContext, req: OpenRequest): GateReport {
  const report = openGates(ctx, req);

  if (report.refusal) {
    // `value` and `threshold` are already formatted for a human:
    //   "stake $0.10" against "at least $0.20"
    console.log(`${report.refusal.label}: ${report.refusal.value} / ${report.refusal.threshold}`);
    console.log(report.refusal.detail);
  }
  return report;
}
```

Building the `OpenContext` and rendering the whole table is [the next page](/sdk/gates).

## 5. Put it together

```ts summary.ts theme={"dark"}
import { Connection } from '@solana/web3.js';
import { openPreview } from '@rekt/1000x';
import { readProtocol } from './read-protocol';
import { oracleShape } from './read-oracle';

export async function summary(symbol: string): Promise<string> {
  const url = process.env['SOLANA_RPC_URL'];
  if (!url) throw new Error('SOLANA_RPC_URL is not set');
  const connection = new Connection(url, 'confirmed');

  const p = await readProtocol(connection, symbol);
  const oracle = oracleShape(p.market);
  const preview = openPreview(p.config, p.market, p.config.params.minCollateral, 20_000, p.nowUnix);

  return [
    `${symbol}: priced by ${oracle.vendor}, a settle needs ${oracle.settleSources} sources and ${oracle.minSignatures} signatures`,
    `pool: openable ${p.gauges.openable}, withdrawable ${p.gauges.withdrawable}`,
    `open at minimum stake: debit ${preview.totalDebit}, max payout ${preview.maxPayout}`,
  ].join('\n');
}
```

## What you have, and what you do not

You now have every number a trader needs to decide, read from chain rather than typed, and every
refusal that could stop the trade, before you send anything.

What you do not have yet is a signature. An open, an add and a close request carry no price, so
there is no quote to obtain for them: see [orders and closes](/sdk/orders). A settle, a `stamp_book` and
`set_take_profit` carry a signed quote in the same transaction, and a quote's age is judged **at
execution**, against a governed bound of a small number of slots. Who signs, and how fast, decides
whether one of those lands at all. Read [session keys](/sdk/sessions) before you write the send path.

<CardGroup cols={2}>
  <Card title="Session keys" icon="key" href="/sdk/sessions">
    Who signs a trade, and how the program's session-key delegate works.
  </Card>

  <Card title="Quotes and freshness" icon="satellite-dish" href="/sdk/quotes">
    What a quote is, why `6007` happens, and how to handle it without lying to the trader.
  </Card>

  <Card title="Reading gates" icon="traffic-light" href="/sdk/gates">
    Build the context, render the table, and explain a refusal properly.
  </Card>

  <Card title="Opening a position" icon="paper-plane" href="/sdk/opening">
    Build the order, size it, simulate, send, and read its sequence number.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.