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

# Примеры кода для Perps

> Программный доступ к Raydium Perps через API Orderly Network: депозит USDC, регистрация торгового счета, размещение / отмена / редактирование ордеров, получение позиций, подписка на WebSocket рынка и вывод средств.

<Info>
  **Эта страница переведена с помощью ИИ. За эталон принимается английская версия.**

  [Открыть английскую версию →](/products/perps/code-demos)
</Info>

<Info>
  **Raydium Perps — это белый лейбл на базе Orderly Network.** Биржевой стакан, механизм маршрутизации заявок и состояние счета полностью размещены в Orderly. SDK Raydium v2 (`@raydium-io/raydium-sdk-v2`) не покрывает perps — для программного доступа используйте REST и WebSocket API Orderly напрямую. Приведённые ниже примеры показывают наиболее распространённые сценарии; полная справка находится на сайте [orderly.network/docs](https://orderly.network/docs/build-on-omnichain/evm-api/introduction).
</Info>

<Info>
  **Информация о версии.**

  * Бэкенд: Orderly Network REST + WebSocket API
  * Примеры кода проверены относительно API Orderly на апрель 2026 г.
  * Кластер Solana для внесения депозитов: `mainnet-beta`
  * Подпись: ed25519 Solana над полезной нагрузкой в стиле EIP-712 Orderly (Orderly использует схему EIP-712 даже для немейнетов; см. документацию Orderly для актуального списка полей)

  API-поверхность Orderly эволюционирует; перед использованием этих примеров в боевом коде проверьте [orderly.network/docs](https://orderly.network/docs/build-on-omnichain/evm-api/introduction).
</Info>

## Содержание страницы

Приведённые ниже сценарии охватывают основные этапы жизненного цикла:

1. Настройка счета — внесение USDC и регистрация счета в Orderly.
2. Аутентифицированные REST-запросы — запрос подписей для размещения ордеров, отмены и запросов состояния счета.
3. Торговля — размещение рыночных / лимитных ордеров, отмена, получение позиций и истории сделок.
4. Данные рынка — подписка на WebSocket стакана и сделок.
5. Вывод — инициирование вывода средств в кошелёк.

Эти примеры предназначены для Node.js + TypeScript с `@solana/web3.js` и `tweetnacl` для подписи Ed25519. Это **отправные точки** — API-поверхность Orderly обширна и изменяется быстрее, чем эта страница; перед выпуском боевого кода всегда проверяйте живую документацию Orderly.

## Настройка

```ts theme={null}
import { Connection, Keypair, PublicKey, clusterApiUrl } from "@solana/web3.js";
import nacl from "tweetnacl";
import bs58 from "bs58";
import fs from "node:fs";

// 1. Кошелёк Solana — владеет USDC, подписывает транзакции депозита/вывода.
const connection = new Connection(process.env.RPC_URL ?? clusterApiUrl("mainnet-beta"));
const owner = Keypair.fromSecretKey(
  new Uint8Array(JSON.parse(fs.readFileSync(process.env.KEYPAIR!, "utf8"))),
);

// 2. Ключ торговли Orderly — отдельная пара Ed25519, используемая для подписи API-запросов.
//    НЕ кошелёк Solana. Сгенерируйте один раз, храните в секрете, переиспользуйте между сеансами.
const orderlyKey = nacl.sign.keyPair();   // ed25519
const orderlyPubB58 = "ed25519:" + bs58.encode(orderlyKey.publicKey);

// 3. Базовый URL Orderly. Raydium использует мейннет-хост Orderly.
const ORDERLY_BASE = "https://api.orderly.org";
const BROKER_ID    = "raydium";   // Пространство имён брокера Raydium на Orderly
const CHAIN_ID     = "solana";    // для регистрации кроссчейн-счета
```

Ключ торговли Orderly — это **не** ваша пара ключей кошелька. Это ключ для подписи запросов, который вы регистрируете по отношению к вашему кошельку при первом использовании; вы можете ротировать его без изменения средств. Обращайтесь с ним как с учётными данными сеанса.

## Регистрация счета

Перед размещением каких-либо ордеров зарегистрируйте кошелёк в Orderly:

```ts theme={null}
import { encodeUserSettlement } from "./eip712-helpers"; // см. документацию Orderly для точной полезной нагрузки

// 1. Запросите nonce регистрации из Orderly.
const nonceResp = await fetch(`${ORDERLY_BASE}/v1/registration_nonce`).then(r => r.json());
const registrationNonce = nonceResp.data.registration_nonce;

// 2. Подпишите полезную нагрузку регистрации кошельком Solana (EIP-712-стиль на Solana
//    реализован как структурированное сообщение; SDK Orderly предоставляет кодировщик).
const payload = encodeUserSettlement({
  brokerId: BROKER_ID,
  chainId: CHAIN_ID,
  registrationNonce,
  timestamp: Date.now(),
});
const walletSig = nacl.sign.detached(Buffer.from(payload), owner.secretKey);

// 3. Зарегистрируйтесь, включив ключ торговли Ed25519 Orderly.
const reg = await fetch(`${ORDERLY_BASE}/v1/register_account`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    message: payload,
    signature: bs58.encode(walletSig),
    userAddress: owner.publicKey.toBase58(),
    orderlyKey: orderlyPubB58,
  }),
}).then(r => r.json());

console.log("Account ID:", reg.data.account_id);
```

ID счетов детерминированы для каждой пары `(broker_id, wallet_address)` — регистрация идемпотентна. Если кошелёк уже зарегистрирован с брокером Raydium, вызов вернёт тот же ID счета без создания нового.

## Внесение USDC

Депозиты переводят USDC из ATA кошелька в хранилище расчётов Orderly. Это транзакции на Solana:

```ts theme={null}
// Создайте инструкцию депозита, используя программу Solana Orderly (ID программы хранилища
// опубликован в их документации; извлекайте его динамически, а не жёсткое кодирование).
const vaultProgramId = new PublicKey("<orderly_solana_vault_program_id>");

const depositIx = await buildOrderlyDepositIx({
  vaultProgramId,
  user: owner.publicKey,
  brokerId: BROKER_ID,
  amountUsdc: BigInt(100_000_000),    // 100 USDC (6 десятичных знаков)
});

const tx = new Transaction().add(depositIx);
const sig = await connection.sendTransaction(tx, [owner]);
await connection.confirmTransaction(sig, "confirmed");
console.log("Deposit tx:", sig);
```

Через \~30 секунд реле Orderly индексирует депозит и баланс появляется в свободной маржа счета. Запросите `/v1/client/holding` для подтверждения:

```ts theme={null}
const holdingResp = await orderlyAuthGet("/v1/client/holding");
console.log("Balances:", holdingResp.data.holding);
```

(`orderlyAuthGet` определён ниже — каждый аутентифицированный вызов проходит через него.)

## Вспомогательный для подписи запросов

Каждый аутентифицированный REST-вызов к Orderly содержит подпись Ed25519 над `(timestamp + method + path + body)`:

```ts theme={null}
async function orderlyAuthRequest(
  method: "GET" | "POST" | "PUT" | "DELETE",
  path: string,
  body?: unknown,
): Promise<any> {
  const ts   = Date.now().toString();
  const json = body ? JSON.stringify(body) : "";
  const msg  = `${ts}${method}${path}${json}`;
  const sig  = nacl.sign.detached(Buffer.from(msg), orderlyKey.secretKey);

  const resp = await fetch(ORDERLY_BASE + path, {
    method,
    headers: {
      "Content-Type": "application/json",
      "orderly-account-id":  /* зарегистрированный account_id */ "",
      "orderly-key":         orderlyPubB58,
      "orderly-signature":   bs58.encode(sig),
      "orderly-timestamp":   ts,
    },
    body: json || undefined,
  });
  return resp.json();
}

const orderlyAuthGet  = (p: string)            => orderlyAuthRequest("GET",  p);
const orderlyAuthPost = (p: string, b: object) => orderlyAuthRequest("POST", p, b);
const orderlyAuthDel  = (p: string)            => orderlyAuthRequest("DELETE", p);
```

Защита от повтора: запросы с `timestamp` отличающимся более чем на 5 секунд от серверных часов отклоняются. Синхронизируйте часы (NTP) и избегайте подписания запросов заранее.

## Размещение рыночного ордера

```ts theme={null}
const marketResp = await orderlyAuthPost("/v1/order", {
  symbol:        "PERP_SOL_USDC",
  order_type:    "MARKET",
  side:          "BUY",
  order_quantity: 1.0,        // 1 SOL позиции
  reduce_only:    false,
});

if (marketResp.success) {
  console.log("Order ID:", marketResp.data.order_id);
} else {
  console.error("Reject:", marketResp.message);
}
```

Рыночные ордера исполняются немедленно. Ответ возвращает полученный `order_id` плюс статус. Сделки приходят через WebSocket (см. ниже); сам REST-ответ не блокирует до полного исполнения.

## Размещение лимитного ордера с Post-Only

```ts theme={null}
const limitResp = await orderlyAuthPost("/v1/order", {
  symbol:         "PERP_SOL_USDC",
  order_type:     "LIMIT",
  side:           "SELL",
  order_quantity: 0.5,
  order_price:    140.50,
  // комбинации флагов:
  // post_only: true делает это ордером только для маркета — отменяется, если пересекает.
  // reduce_only / time_in_force устанавливаются независимо.
  post_only:      true,
});
console.log(limitResp);
```

Для `IOC` / `FOK` установите `time_in_force: "IOC"` или `"FOK"`. См. [`products/perps/order-types`](/ru/products/perps/order-types) для семантики каждого флага.

## Отмена ордера

```ts theme={null}
// По ID ордера
await orderlyAuthDel(`/v1/order?order_id=${orderId}&symbol=PERP_SOL_USDC`);

// Отменить ВСЕ ордера на символе
await orderlyAuthDel(`/v1/orders?symbol=PERP_SOL_USDC`);
```

Отмена подтверждается синхронно, но фактическая отмена может совпасть с исполнением. Всегда выполняйте переверку, опрашивая `/v1/orders` или наблюдая WebSocket — предположение успешной отмены без подтверждения может привести к дублирующимся или непредусмотренным позициям.

## Получение открытых позиций

```ts theme={null}
const posResp = await orderlyAuthGet("/v1/positions");
for (const p of posResp.data.rows) {
  console.log(
    p.symbol,
    "size:",  p.position_qty,
    "entry:", p.average_open_price,
    "unrealized:", p.unsettled_pnl,
  );
}
```

Отрицательный `position_qty` — это шорт, положительный — длинная позиция. `position_qty == 0` означает, что позиция закрыта, но строка может оставаться до следующей очистки.

## Получение истории сделок

```ts theme={null}
const fills = await orderlyAuthGet(
  "/v1/trades?symbol=PERP_SOL_USDC&start_t=" + (Date.now() - 86_400_000)
);
for (const t of fills.data.rows) {
  console.log(t.executed_timestamp, t.side, t.executed_quantity, "@", t.executed_price);
}
```

Аргументы времени — это миллисекундные временные метки Unix. Размер страницы по умолчанию — 25 строк; используйте параметры запроса `page` и `size` для разбиения на страницы.

## WebSocket: данные рынка

```ts theme={null}
import WebSocket from "ws";

const ws = new WebSocket(`wss://ws.orderly.org/ws/stream/${accountId}`);

ws.on("open", () => {
  // Общедоступные данные рынка: дельты стакана + сделки для одного символа
  ws.send(JSON.stringify({ id: "ob1", topic: "orderbook@PERP_SOL_USDC" }));
  ws.send(JSON.stringify({ id: "tr1", topic: "trade@PERP_SOL_USDC" }));
});

ws.on("message", (raw) => {
  const msg = JSON.parse(raw.toString());
  if (msg.topic?.startsWith("orderbook@")) {
    // дельта глубины: { bids: [[price, qty], ...], asks: [[price, qty], ...] }
    applyOrderbookDelta(msg.data);
  } else if (msg.topic?.startsWith("trade@")) {
    console.log("trade:", msg.data);
  }
});
```

Для **приватного** потока (ваши сделки, обновления позиций, изменения баланса) WebSocket должен быть аутентифицирован. Отправьте полезную нагрузку `subscribe`, подписанную так же, как REST-запросы, ограниченную вашим ID счета. Документация Orderly содержит точную форму полезной нагрузки; она иногда меняется, поэтому не жёстко кодируйте конкретную схему здесь.

## Вывод USDC

```ts theme={null}
// 1. Запросите вывод.
const wRes = await orderlyAuthPost("/v1/withdraw_request", {
  token:  "USDC",
  chain_id: CHAIN_ID,
  amount: 50.0,                          // единицы человека
  receiver: owner.publicKey.toBase58(),
});

console.log("Withdrawal request id:", wRes.data.withdraw_id);
```

Orderly передаёт вывод в цепь получателю. Взимается фиксированная комиссия в размере **1 USDC** (см. [`products/perps/fees`](/ru/products/perps/fees)). Внутрицепочечный перевод происходит в течение 1–2 минут при нормальных условиях; ожидайте более длительного периода при перегруженности.

## Типичные ошибки

* **Не переиспользуйте ключ торговли между окружениями.** Один ключ торговли Orderly, зарегистрированный для вашего кошелька, связан с одним счетом мейннета Solana. Если вам также нужен devnet или staging, сгенерируйте отдельный ключ для каждого.
* **Синхронизация времени.** Допуск на сдвиг часов Orderly плотный (±5 сек). На долгоживущих сервисах дрейф NTP в конечном итоге сломает подпись. Периодически синхронизируйте заново.
* **Переподключения WebSocket.** Общедоступный WS иногда разрывает соединения во время обновлений Orderly. Реализуйте экспоненциальную задержку и переподпишитесь при повторном открытии.
* **Ограничения на частоту.** REST-вызовы ограничены по скорости уровня на счёт. Используйте `cancel_all` для массовой отмены, а не цикл `cancel`-по-id при наличии >5 ордеров на отмену.
* **Направление позиции неявно.** Ордер `BUY` на `PERP_SOL_USDC` открывает или расширяет длинную позицию; `SELL` открывает или расширяет короткую позицию — но если вы уже длинны, `SELL` *сокращает* (и может развернуть) позицию, потому что Raydium Perps находится в одностороннем режиме. Всегда проверяйте текущую позицию перед размещением ордера, если направление имеет значение.
* **Финансирование и ликвидации отделены от потока ордеров.** Платежи финансирования и ликвидации отображаются как отдельные потоки событий; они не являются "ордерами". Подпишитесь на соответствующие приватные WS-темы, если вам нужно их наблюдать.

## Что дальше

* [`products/perps/trading-basics`](/ru/products/perps/trading-basics) — концептуальное введение в механику перпетуалов.
* [`products/perps/order-types`](/ru/products/perps/order-types) — семантика каждого типа ордера и флага.
* [`products/perps/collateral`](/ru/products/perps/collateral) — поддерживаемые активы залога и пределы для каждой цепи.
* [`products/perps/fees`](/ru/products/perps/fees) — расписание makerа/taker'а и комиссия на вывод.

Источники:

* [Документация разработчика Orderly Network](https://orderly.network/docs/build-on-omnichain/evm-api/introduction) — каноническая справка для API-поверхности, используемой выше. Raydium Perps потребляет это напрямую.
* [TypeScript SDK Orderly](https://github.com/OrderlyNetwork/orderly-sdk-js) — обёртывает тот же уровень REST/WebSocket с типизированными помощниками; полезно, если вы хотите пропустить написание самого уровня подписи.
