跳轉到主要內容

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.

本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
Raydium Perps 是在 Orderly Network 上的白標部署。 訂單簿、撮合引擎和帳戶狀態都存在於 Orderly 上。Raydium SDK v2(@raydium-io/raydium-sdk-v2不涵蓋 Perps — 若要以程式方式存取,請直接使用 Orderly 的 REST 和 WebSocket API。以下片段展示最常見的流程;規範參考位於 orderly.network/docs
版本資訊。
  • 後端:Orderly Network REST + WebSocket API
  • 程式碼片段已驗證至 2026-04 的 Orderly API
  • 鏈上存款的 Solana 叢集:mainnet-beta
  • 簽名:Solana ed25519 簽署 Orderly EIP-712 風格負載(Orderly 即使在非 EVM 鏈上也使用 EIP-712 架構;查看 Orderly 文件以取得最新欄位列表)
Orderly 的 API 介面會演進;在將這些程式碼片段複製到生產環境之前,請檢查 orderly.network/docs

本頁內容

以下流程涵蓋整合商相關的生命週期:
  1. 帳戶設置 — 存入 USDC 並向 Orderly 註冊帳戶。
  2. 認證的 REST 呼叫 — 請求簽名以進行下單、取消和帳戶查詢。
  3. 交易 — 下市價單/限價單、取消、獲取持倉和成交紀錄。
  4. 市場數據 — 訂閱訂單簿和交易 WebSocket。
  5. 提現 — 向錢包發起提現。
這些程式碼片段針對 Node.js + TypeScript,使用 @solana/web3.jstweetnacl 進行 Ed25519 簽名。它們是起點 — Orderly 的 API 介面廣泛且變化快速;在部署生產程式碼前,請務必檢查 Orderly 的即時文件。

設置

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 交易金鑰 — 用於簽署 API 請求的獨立 Ed25519 金鑰對。
//    不是 Solana 錢包。產生一次,保持機密,跨階段段重複使用。
const orderlyKey = nacl.sign.keyPair();   // ed25519
const orderlyPubB58 = "ed25519:" + bs58.encode(orderlyKey.publicKey);

// 3. Orderly 基底 URL。Raydium 使用 Orderly 的主網主機。
const ORDERLY_BASE = "https://api.orderly.org";
const BROKER_ID    = "raydium";   // Raydium 在 Orderly 上的代理人命名空間
const CHAIN_ID     = "solana";    // 用於跨鏈帳戶註冊
Orderly 交易金鑰不是你的錢包金鑰對。它是一個請求簽名金鑰,你在首次使用時針對你的錢包進行註冊;你可以在不接觸資金的情況下輪換它。將其視為會話憑證。

帳戶註冊

在下任何訂單之前,向 Orderly 註冊錢包:
import { encodeUserSettlement } from "./eip712-helpers"; // 查看 Orderly 文件以取得確切的負載

// 1. 從 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 上
//    實現為結構化消息;Orderly 的 SDK 提供編碼器)。
const payload = encodeUserSettlement({
  brokerId: BROKER_ID,
  chainId: CHAIN_ID,
  registrationNonce,
  timestamp: Date.now(),
});
const walletSig = nacl.sign.detached(Buffer.from(payload), owner.secretKey);

// 3. 註冊,包括 Orderly Ed25519 交易金鑰。
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("帳戶 ID:", reg.data.account_id);
帳戶 ID 對每個 (broker_id, wallet_address) 對是確定的 — 註冊是冪等的。如果一個錢包已經用 Raydium 的代理人註冊,該呼叫會返回相同的帳戶 ID,而不會建立新的。

存入 USDC

存款將 USDC 從錢包 ATA 移至 Orderly 的結算保管庫。它們是鏈上 Solana 交易:
// 使用 Orderly 的 Solana 程式構建存款指令(保管庫程式 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("存款交易:", sig);
約 30 秒後,Orderly 的中繼器索引該存款,餘額出現在帳戶的可用保證金下。查詢 /v1/client/holding 以確認:
const holdingResp = await orderlyAuthGet("/v1/client/holding");
console.log("餘額:", holdingResp.data.holding);
orderlyAuthGet 定義如下 — 每個認證呼叫都通過它。)

請求簽名助手

每個對 Orderly 的認證 REST 呼叫都攜帶 Ed25519 簽名,涵蓋 (timestamp + method + path + body)
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);
重放保護:時間戳與伺服器時鐘偏差超過 5 秒的請求會被拒絕。同步你的時鐘(NTP),避免提前簽署請求。

下市價單

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("訂單 ID:", marketResp.data.order_id);
} else {
  console.error("拒絕:", marketResp.message);
}
市價單立即執行。回應返回結果的 order_id 加上狀態。成交通過 WebSocket 出現(見下文);REST 回應本身不會阻塞到完全成交。

下限價單(Post-Only)

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 瞭解每個標誌的語義。

取消訂單

// 按訂單 ID
await orderlyAuthDel(`/v1/order?order_id=${orderId}&symbol=PERP_SOL_USDC`);

// 取消一個標的所有訂單
await orderlyAuthDel(`/v1/orders?symbol=PERP_SOL_USDC`);
取消會同步確認,但實際取消可能與成交競爭。始終通過輪詢 /v1/orders 或監視 WebSocket 進行協調 — 假設取消成功而不確認會導致重複或意外持倉。

獲取開放持倉

const posResp = await orderlyAuthGet("/v1/positions");
for (const p of posResp.data.rows) {
  console.log(
    p.symbol,
    "大小:",  p.position_qty,
    "開倉價:", p.average_open_price,
    "未實現盈虧:", p.unsettled_pnl,
  );
}
負的 position_qty 是空頭,正數是多頭。position_qty == 0 表示持倉已關閉,但該行可能在下次清理前仍顯示。

獲取成交歷史

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 行;使用 pagesize 查詢參數進行分頁。

WebSocket:市場數據

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("交易:", msg.data);
  }
});
對於私有流(你的成交、持倉更新、餘額變化),WebSocket 必須經過認證。發送一個 subscribe 負載,以與 REST 請求相同的方式簽署,限定於你的帳戶 ID。Orderly 的文件有確切的負載形狀;它不時變化,所以不要在這裡硬編碼特定架構。

提現 USDC

// 1. 請求提現。
const wRes = await orderlyAuthPost("/v1/withdraw_request", {
  token:  "USDC",
  chain_id: CHAIN_ID,
  amount: 50.0,                          // 人類單位
  receiver: owner.publicKey.toBase58(),
});

console.log("提現請求 ID:", wRes.data.withdraw_id);
Orderly 將提現中繼到接收地址的鏈上。有一筆1 USDC 的固定提現費用(查看 products/perps/fees)。鏈上轉帳在正常情況下會在 1–2 分鐘內發生;在擁塞期間預期時間更長。

陷阱

  • 不要在環境之間重複使用交易金鑰。 針對你的錢包註冊的單一 Orderly 交易金鑰與一個 Solana 主網帳戶相關聯。如果你還需要 devnet 或測試環境,為每個環境產生獨立的金鑰。
  • 時間同步。 Orderly 的時鐘偏差容差很緊(±5 秒)。在長期運行的服務上,NTP 漂移最終會破壞簽名。定期重新同步。
  • WebSocket 重新連接。 公開 WS 在 Orderly 升級期間偶爾會丟棄連接。實現指數退避並在重新打開時重新訂閱。
  • 速率限制。 REST 呼叫按帳戶分層速率限制。當你有 >5 訂單要取消時,使用 cancel_all 批量取消而不是迴圈 cancel-by-id。
  • 持倉方向是隱含的。PERP_SOL_USDC 上的 BUY 訂單開啟或擴展多頭;SELL 開啟或擴展空頭 — 但如果你已經是多頭,SELL 減少(並可能翻轉)持倉,因為 Raydium Perps 是單向模式。如果方向重要,在下訂單前始終檢查當前持倉。
  • 資金和清算與訂單流分離。 資金費用和清算顯示為獨立事件流;它們不是「訂單」。如果你需要觀察它們,訂閱相關的私有 WS 主題。

接下來

資源: