> ## 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.

# Quotes and freshness

> What a quote is, which instructions carry one, how a transaction carries it, what the program checks, and what to do when a priced instruction is refused with 6007.

Every instruction that prices a position carries its own price. This page is the single reference
for that price: its shape, the transaction it rides in, the checks the program applies, and the
refusal you will meet most often.

> [!NOTE]
>
> **An `open`, an `add_collateral`, a `request_close` and a `mark_expiry` carry no quote.** The price
> of an order is written later by a filler, and the price of a requested or marked exit is the
> window quote of the settle. The instructions that carry a quote are `settle`, `stamp_book`,
> `set_take_profit`, `prove_price` (`provePrice`), and the filler's `fill` and proof forms. See
> [orders and closes](https://docs.rekt.money/sdk/orders.md).

## What a quote is

A **quote** is a price signed by the venue's quote service, carried **inside the transaction that
uses it**. There is no price account to read. A market of feed kind 2 reads its price this way. A
market of feed kind 3 (`isKind3Market(market)`) reads a signed tick that the venue's fillers and
keepers attach; a client does not fetch it, and an open, an add and a close request on it carry
none. Read `market.feedKind[0]` for a market's kind on every request: a market's kind can change.
`settlementIdentity(market)` gives its identity. The rest of this page is the kind-2 quote.

> [!NOTE]
>
> This page describes what the program verifies and the transaction a quote rides in. **To obtain a
> quote, see [Getting prices](https://docs.rekt.money/sdk/prices.md).**

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

export function isSignedQuoteMarket(market: MarketView): boolean {
  const s = settlementIdentity(market);
  // `vendor` is 'benchmark' on a market priced by a signed quote, and `pull` is true:
  // the price is posted in the caller's own transaction, never read from an account.
  return s.vendor === 'benchmark' && s.pull;
}
```

The quote names the market's feed (`market.feeds[0]`), a price in US-dollar units and the slot it was
published in. It arrives with the ed25519 signatures of the service's signing keys over those bytes.

> [!WARNING]
>
> **A price stream is not a precondition for a trade.** A chart feed going quiet says nothing about
> whether a trade can land. An open needs no quote at all: a filler writes the entry later. For an
> instruction that does carry a quote, the precondition is whether you can obtain a signed quote at
> send time and land it before it ages out. That is a request you make, not a state you observe.

> [!NOTE]
>
> **The price you draw on a chart and the price the program verifies are different facts**, and may
> come from different sources. Ask `settlementIdentity(market)` which one a market settles on rather
> than inferring it from the chart.

## The transaction shape

```text theme={"dark"}
0  ed25519 precompile          the signed quote and its signatures
1  settle | stamp_book | ...   yours: reads the instruction immediately before it
2  ComputeBudget  setComputeUnitLimit
3  ComputeBudget  setComputeUnitPrice
```

* **The ed25519 instruction must be immediately before yours.** The program reads the instruction at
  relative index −1 and refuses anything that is not the ed25519 program. The indices are exported
  as `BENCHMARK_QUOTED_LAYOUT` (`{ ed25519: 0, instruction: 1 }`).
* **The signature records point at their own instruction.** Every offset in the precompile names the
  precompile itself, so its absolute position does not matter; only its adjacency to yours does. An
  instruction you add goes **in front of** index 0 or **after** the compute-budget pair, never
  between the quote and your instruction.
* **Your instruction carries the Instructions sysvar as its remaining account.** That is how the
  program reaches the precompile. `pricingRemainingAccounts(market)` returns exactly that list for a
  market priced by a signed quote. Do not pass `market.feeds` as accounts: `feeds[0]` is a feed id,
  not an account.
* **`composeBenchmarkTransaction` builds this order and `submitBenchmarkQuoted` sends it.** The
  sender evaluates the protocol gates you hand it, composes, signs, measures the signed bytes,
  checks the distinct-signer count against `market.minSignatures`, simulates, and only then sends.
  `dryRun: true` stops before the send.

## What the program checks

The program re-proves the quote at execution. A quote that fails any check counts as no price at all.

| Check | Result |
| - | - |
| The ed25519 instruction is immediately before yours and every record points at itself | no price |
| The payload's magic, version byte and length agree | no price |
| At least `market.minSignatures` **distinct** signers that the program recognises | not admitted |
| The quote is for this market's feed, in US-dollar units | no price |
| At least `market.minSources` sources aggregated | no price |
| `Clock.slot − publish slot` is at most `market.maxOracleAgeSlots`, and the publish slot is not in the future | not admitted |

"Not admitted" and "no price" both end the same way: **`NoFreshPrice` (6007)**.

**The age row depends on the instruction.** A settle of a requested or marked exit needs the window
quote, which can be any age inside its window. A knockout or take-profit proof must be newer than the
entry and inside its look-back. `market.maxOracleAgeSlots` bounds the quote of `set_take_profit`. A
quote dated ahead of the chain is refused everywhere. The timing settings are on
[orders and closes](https://docs.rekt.money/sdk/orders.md#the-timing-settings).

`benchmarkSourceFloor(market, 'settle')` returns the source floor. None of these are constants: read
them from the market.

## The one rule that explains every refusal

> [!WARNING]
>
> **The freshness clock is read on chain, at execution, never at the moment you obtained the
> quote.**
>
> The program compares `Clock.slot` against the slot the quote was published in and refuses when the
> difference exceeds `market.maxOracleAgeSlots`, or when that age, counted at 400 ms a slot, exceeds
> `market.maxOracleAgeMs`. Both fields are governed: read them. The 400 ms is a constant of the
> program; `config.params.slotMs` does not change this check. Neither figure is the length of a
> mainnet slot, which is shorter (about 213 ms on mainnet today): measure it (`getRecentPerformanceSamples`) when you
> size a timeout.

Everything between obtaining the quote and the transaction landing is charged to that budget:
composing, signing, the network carrying the packet to a leader, and the block itself.

```ts theme={"dark"}
import { freshnessWindowMs, type ConfigView, type MarketView } from '@rekt-trading/1000x';

// Two governed values, multiplied in one place. Use the result to size timeouts and to explain a
// refusal, never to price anything.
export function freshnessBudget(
  market: MarketView,
  config: ConfigView,
): { slots: number; approxMs: number } {
  return { slots: market.maxOracleAgeSlots, approxMs: freshnessWindowMs(config.params, market) };
}
```

## `6007` — `NoFreshPrice`

This is the code you will actually meet. It is `retryable: 'immediately'`, and it means one thing:
**at the instant the program ran, no quote cleared admission.** The quote was too old, carried too
few distinct signers, or, on a settle, failed any of the checks above.

### What it is not

* **Not a failed trade.** Nothing moved. No collateral left the wallet, no position opened, no
  position closed. The only cost is the network fee for the attempt.
* **Not a fault in your code.** A quote has a fixed number of slots to survive between being signed
  and being read. Losing that race sometimes is the normal operating condition.
* **Not something a wider client-side staleness window fixes.** The chain re-proves freshness at
  execution. Accepting older quotes on your side only buys more reverts.

### What to do about it

**1. Obtain a NEW quote for every attempt**

A retry that reuses the quote repeats the failure, because the quote is now older than it was.
Each attempt draws its own quote, composes its own transaction, and signs again. A quote that
is the same as the last one is not a new quote.

```ts theme={"dark"}
import { ProgramRefusal, programErrorCode } from '@rekt-trading/1000x';

/**
 * Retry a quoted send. `attempt` must obtain a new quote and re-compose: it is a whole attempt,
 * not a resend. `slotMs` is `slotMs(config.params)`, read live.
 */
export async function withFreshQuote<T>(
  attempt: () => Promise<T>,
  slotMs: number,
  attempts = 3,
): Promise<T> {
  let last: unknown;
  for (let i = 0; i < attempts; i += 1) {
    try {
      return await attempt();
    } catch (e) {
      last = e;
      const code = e instanceof ProgramRefusal ? e.info.code : programErrorCode(e);
      // 6007 is the only code worth spinning on here. Everything else is a state or a bug.
      if (code !== 6007) throw e;
      // One slot, not a backoff. Waiting longer makes the next quote no fresher.
      await new Promise((r) => setTimeout(r, slotMs));
    }
  }
  throw last;
}
```

**2. Keep a wallet prompt out of the loop**

If the retry re-signs through a person's wallet, every attempt spends seconds inside a budget of
`market.maxOracleAgeSlots × config.params.slotMs`, and every attempt fails for the same reason,
with one popup per failure. Keep the person off the signing path: `set_take_profit` is the one
quote-carrying instruction the owner signs, and a [session key](https://docs.rekt.money/sdk/sessions.md) can sign it.

**3. Check the quote before you sign it**

A quote that is short of the market's floors cannot be admitted however fast it lands. Before
signing, compare its distinct signers with `market.minSignatures` and its source count with
`benchmarkSourceFloor(market, 'settle')`. `submitBenchmarkQuoted` refuses a short signer count
before sending (`wire.signatures`), and `benchmarkQuoteView` carries the quote into the price
gates, so a gate report renders the reason.

**4. Tell the trader the truth**

"Re-pricing…" is accurate and calm. "Trade failed" is neither. Surface a failure only after your
attempts are exhausted, and say what happened: the price moved on before the transaction landed,
and nothing was charged.

### Three failures, counted separately

| Failure | What it looks like | What a retry does |
| - | - | - |
| **No quote** | the quote service refused or timed out | may succeed; count and alarm on it separately |
| **The quote is too old** | a well-formed quote, past `maxOracleAgeSlots` when it lands | succeeds with a new quote |
| **The quote is short** | a prompt quote below a market floor (signers or sources) | do not send it; obtain another |

"I could not get a price", "the price I got was too old" and "the price I got cannot be admitted"
need three different responses, and the third one must never reach `sendTransaction`. A short quote
is not a refusal by the chain: nothing was sent. Say *"waiting for a fresh price"* and keep the
control enabled. Reserve the word *refused*, and a disabled button, for a decision the program made.

## Which instructions carry a quote

| Instruction | Carries a quote | Who signs |
| - | - | - |
| `open`, `add_collateral` | **no** | the owner, **or a session key they authorised** |
| `request_close` | **no** | the owner, **or their session key** |
| `mark_expiry` | **no** | **anyone**, from the deadline |
| `settle` — `knockout`, `takeProfit`, `userExpiry`, `tenorExpiry`, `borrowSpent` | yes | **anyone** |
| `settle` — `voluntary` | yes | **anyone**, once the owner has requested the close |
| `settle` — `lastResort` | **no** | **anyone** |
| `stamp_book` | yes | **anyone** |
| `prove_price` (`provePrice`) | yes | **anyone** |
| `set_take_profit` | yes | the owner, **or their session key** |
| `fill`, and the proof forms of `void_open` and `reverse_add` | yes | **a listed filler only** |
| `void_open`, `reverse_add` by timeout | **no** | **anyone** |
| `init_trader_account`, `set_payout_destination`, `authorize_delegate`, `renew_delegate`, `revoke_delegate` | **no** | the owner |
| `claim_payout` | **no** | **anyone**, to the recorded destination; the owner, to any other account |

> [!NOTE]
>
> **The instructions a person signs to trade carry no price.** Setting up a session, funding an
> account, opening, adding and asking for a close race nothing, so a wallet dialog is fine for them.
> `set_take_profit` is the exception: the owner signs it and it carries a quote, so sign it with a
> session key or locally. Settles and stamps are sent by anyone, and the venue's keepers send them.

## Closing a position

The trader's Close is `request_close`, which carries no quote. The settle that completes it is sent
by anyone with the window quote, and the venue's keepers do. So the freshness budget never reaches a
person who only trades.

* **A position that reaches its barrier, its rung or either clock does not need the trader.** Those
  four reasons are permissionless, so they land without the owner signing. Nobody is paid to submit
  them: what is permissionless is the right to close, not a reward.
* **A trader's own timer** (`userTimerS` at open, zero or 26 seconds or more) turns "close it at
  this time" into a clock that anyone may prove. Offer it.

## Related refusals

| Error | Code | Retry | What it means |
| - | - | - | - |
| `NoFreshPrice` | 6007 | immediately | No quote cleared admission at execution. Obtain a new quote and resend. |
| `BenchmarkQuoteMalformed` | 6178 | never | The quote could not be read: the Instructions sysvar is missing from the remaining accounts, the ed25519 instruction is not immediately before yours, or the payload is not the expected shape. |
| `OracleFrozen` | 6190 | after-governance | The venue's oracle is frozen. Opens, adds, close requests, expiry marks, `stamp_book`, `lastResort` closes and the return of an order or add that needs a price refuse; every other settle and `set_take_profit` fail `NoFreshPrice`. Read `config.oracleFrozen`. |

An open and an add carry no quote. The fill judges the first price instead, and a price that fails
is a returned order (`OpenVoided`), not a refusal.

At settle, a quote that fails any of these checks comes back as `NoFreshPrice`, never as its own
code. If `NoFreshPrice` repeats on a settle, read `config.oracleFrozen` before you retry again.

The full catalogue, with a cause and a fix for each, is in [error handling](https://docs.rekt.money/sdk/errors.md).

> [card] [Session keys](https://docs.rekt.money/sdk/sessions.md)
>
> The session-key delegate the program provides: authorise, fund, sign, revoke.

> [card] [Opening a position](https://docs.rekt.money/sdk/opening.md)
>
> Building the instruction, the first-trade account, sizing, and sending.


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