> ## 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](/sdk/orders).
</Note>

## 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. Every listed market reads
its price this way: read `market.feedKind[0]` to confirm a market's kind, and
`settlementIdentity(market)` to get it as a named vendor.

<Note>
  This page describes what the program verifies and the transaction a quote rides in. **To obtain a
  quote, see [Getting prices](/sdk/prices).**
</Note>

```ts theme={"dark"}
import { settlementIdentity, type MarketView } from '@rekt/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.
</Warning>

<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.
</Note>

## The transaction shape

```text theme={"dark"}
0  ed25519 precompile          the signed 80-byte 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 |
| 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](/sdk/orders#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 and have moved without a redeploy, and so has
  the network slot time in `config.params.slotMs`. Read them.
</Warning>

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/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

<Steps>
  <Step title="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/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;
    }
    ```
  </Step>

  <Step title="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](/sdk/sessions) can sign it.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>
</Steps>

### 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` | 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`, `claim_payout`, `authorize_delegate`, `renew_delegate`, `revoke_delegate`, redemption | **no** | the owner |

<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.
</Note>

## 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) 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 and `lastResort` closes refuse; every other settle fails `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](/sdk/errors).

<CardGroup cols={2}>
  <Card title="Session keys" icon="key" href="/sdk/sessions">
    The session-key delegate the program provides: authorise, fund, sign, revoke.
  </Card>

  <Card title="Opening a position" icon="paper-plane" href="/sdk/opening">
    Building the instruction, the first-trade account, sizing, and sending.
  </Card>
</CardGroup>


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