Начало работы
Аутентификация
Sign-In With Solana для API Seeryx: сообщение для входа, токен в X-Auth-Token или Bearer и ключ торговой сессии, который подписывает ордера.
Обзор
| Вызовы | Что нужно |
|---|---|
| Рыночные данные: рынки, раунды, стаканы, сделки, события, профили | Ничего |
| Ваш аккаунт: средства, позиции, ордера, активность | Токен входа в X-Auth-Token |
| Ордера, отмена, разделение, объединение | Токен и Idempotency-Key; на seeryx.com каждый ордер, разделение и объединение также содержит signed, созданный ключом вашей торговой сессии |
| Пополнения, выводы, сама сессия | Токен и подпись вашего кошелька под транзакцией, которую готовит сервер |
Вход через кошелёк
Seeryx использует Sign-In With Solana: кошелёк подписывает короткое текстовое сообщение — это бесплатно и ничего не отправляет в блокчейн.
POST /api/auth/nonceс телом{ "address": "<your wallet>" }возвращает сообщение. Оно действительно 5 минут и только для одного входа.- Проверьте, что в строке 1 указан этот сайт, а в строке 2 — ваш адрес, затем подпишите точные байты сообщения в UTF-8 ключом Ed25519 кошелька и закодируйте 64-байтовую подпись в base58.
POST /api/auth/verifyсaddress,messageиsignatureвозвращаетtoken. Первый вход создаёт аккаунт.
seeryx.com wants you to sign in with your Solana account:
4hfqTJ6sVSszXZGCYjXEr4YuAXz9nyLut8725NP9mVvm
Sign in to Seeryx. This does not send a transaction or cost a fee.
URI: https://seeryx.com
Version: 1
Chain ID: mainnet
Nonce: a4b5fb6f571c43b4b1c5057abaa8cea2
Issued At: 2026-10-13T18:29:28.000Z
Expiration Time: 2026-10-13T18:34:28.000Z// seeryx.ts: a small client for the Seeryx API. Node 22+, npm i @solana/kit
import { readFileSync } from 'node:fs';
import { createKeyPairFromBytes, getAddressFromPublicKey, getBase58Decoder, signBytes } from '@solana/kit';
import type { Address } from '@solana/kit';
import { apiUrl } from './api-url.mjs';
export const BASE = process.env.SEERYX_URL ?? 'https://seeryx.com';
export const ACCESS = process.env.SEERYX_ACCESS ?? ''; // only on a site with access codes
let token = '';
export interface Round {
slug: string; start: number; end: number; open: number | null; close: number | null;
outcome: 'up' | 'down' | null; status: 'upcoming' | 'live' | 'settled';
}
export interface Book { bids: [price: number, shares: number][]; asks: [price: number, shares: number][] }
export interface Account {
positions: { slug: string; side: 'up' | 'down'; shares: number; cost: number }[];
orders: {
id: number; slug: string; side: 'up' | 'down'; action: 'buy' | 'sell'; shares: number; limit: number;
}[];
balance: { available: number; total: number };
}
export class ApiError extends Error {
constructor(
message: string, readonly status: number, readonly code?: string, readonly retryAfter?: number,
) {
super(message);
}
}
// One request. Writes get a fresh Idempotency-Key unless you pass the key of the attempt you are retrying.
export async function api<T>(path: string, init: { method?: string; body?: unknown; key?: string } = {}) {
const method = init.method ?? 'GET';
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
if (token) headers['X-Auth-Token'] = token;
if (ACCESS) headers['X-Access-Token'] = ACCESS;
if (method !== 'GET') headers['Idempotency-Key'] = init.key ?? crypto.randomUUID();
const body = init.body === undefined ? undefined : JSON.stringify(init.body);
const res = await fetch(apiUrl(BASE, path), { method, headers, body, redirect: 'error' });
const data = await res.json().catch(() => ({}));
if (!res.ok) {
const wait = Number(res.headers.get('Retry-After')) || undefined;
throw new ApiError(data.error ?? `HTTP ${res.status}`, res.status, data.code, wait);
}
return data as T;
}
export interface Wallet { pair: CryptoKeyPair; address: Address }
// A wallet file as solana-keygen writes it: a JSON array of 64 numbers.
export async function loadWallet(path = process.env.SEERYX_WALLET ?? 'wallet.json'): Promise<Wallet> {
const pair = await createKeyPairFromBytes(new Uint8Array(JSON.parse(readFileSync(path, 'utf8'))));
return { pair, address: await getAddressFromPublicKey(pair.publicKey) };
}
// Sign-In With Solana: ask for the message, check it, sign its exact bytes, trade the signature for a token.
export async function signIn(wallet: Wallet) {
const { address } = wallet;
const { message } = await api<{ message: string }>('/auth/nonce', { method: 'POST', body: { address } });
const [first, second] = message.split('\n');
const site = `${new URL(BASE).hostname} wants you to sign in with your Solana account:`;
if (first !== site || second !== address) {
throw new Error('Unexpected sign-in message: not this site or not this wallet');
}
const bytes = await signBytes(wallet.pair.privateKey, new TextEncoder().encode(message));
const signature = getBase58Decoder().decode(bytes);
const body = { address, message, signature };
({ token } = await api<{ token: string }>('/auth/verify', { method: 'POST', body }));
return token; // valid for 7 days
}Токены входа
- Заголовок
- Отправляйте токен как
X-Auth-Token: <token>илиAuthorization: Bearer <token>в каждом запросе, требующем входа, а в подписке WebSocket на аккаунт — какtoken. - Срок действия
- 7 дней. Войдите заново до истечения срока или когда вызов вернёт 403 (seeryx.com) или 401 с «Invalid or expired token».
- Файлы cookie
- Сам сайт выполняет вход с помощью файла cookie HttpOnly и CSRF-токена, которыми могут пользоваться только страницы сайта. API-клиенты используют заголовок с токеном, и ни то ни другое им не нужно.
- Лимиты
- 30 запросов в минуту с одного IP-адреса для каждого из
/auth/nonceи/auth/verify.
Ключ торговой сессии
На seeryx.com каждая сделка проходит расчёт в Solana через программу Seeryx, а программа принимает только ордера, подписанные для вашего счёта. Чтобы не запрашивать подпись кошелька для каждого ордера, кошелёк один раз подтверждает ключ сессии:
| Поле | Тип | Описание |
|---|---|---|
key | публичный ключ | Новый ключ Ed25519, созданный вашим ботом. Он подписывает ордера, разделения и объединения. |
expiresAt | секунды Unix | Когда ключ перестанет действовать: не позднее чем через maxSessionTtl из GET /api/funds от текущего момента (24 часа). |
limit | USDC | Максимальная общая сумма, которую ключ может потратить на покупки и разделения. |
maxTrade | USDC | Максимальная сумма одного ордера; не больше limit. |
- Торговать может, выводить — нет. Ключ может подписывать только ордера, разделения и объединения для вашего счёта в пределах своих лимитов. Для вывода всегда нужен сам кошелёк.
- Одна сессия за раз. Новая сессия заменяет старый ключ; ордера в стакане, подписанные старым ключом, отменяются, как только начинает использоваться новый.
- Лимитные ордера не должны пережить сессию. Ордер отклоняется, если он остался бы в стакане после окончания сессии: откройте новую сессию, прежде чем выставлять котировки в раунде, который закрывается позже (например, в раундах длительностью 1 день).
- Бесплатно. Комиссию сети и ренту за аккаунт Solana для транзакции сессии оплачивает Seeryx. Но сначала ваш счёт должно открыть первое пополнение (до этого — 409 «Deposit first»).
- Закрыть досрочно можно через
POST /api/relay{ "action": "close_session" }: ваши ордера в стакане отменяются, и ключ сразу перестаёт действовать.
Как открыть сессию и подписывать её ключом, байт за байтом: Подпись ордеров.
Выход
POST /api/auth/logoutзавершает действие отправленного токена;POST /api/auth/logout-all— всех токенов аккаунта.- Ни один из них не завершает действие ключа торговой сессии: закройте его через
close_sessionили дождитесь истечения срока.
curl -s -X POST https://seeryx.com/api/auth/logout-all -H "X-Auth-Token: $TOKEN"
# {"success":true}Эндпоинты входа
Вход через кошелёк Solana: запросите сообщение, подпишите его точные байты ключом кошелька и обменяйте подпись на токен. В блокчейн ничего не отправляется, комиссия не взимается.
/api/auth/nonceПолучить сообщение для подписи
| Поле | Тип | Описание |
|---|---|---|
address | string | Адрес кошелька Solana (base58) |
curl -X POST "https://seeryx.com/api/auth/nonce" \
-H "Content-Type: application/json" \
-d '{"address":"4hfqTJ6sVSszXZGCYjXEr4YuAXz9nyLut8725NP9mVvm"}'{
"message": "seeryx.com wants you to sign in with your Solana account:\n4hfqTJ6sVSszXZGCYjXEr4YuAXz9nyLut8725NP9mVvm\n\nSign in to Seeryx. This does not send a transaction or cost a fee.\n\nURI: https://seeryx.com\nVersion: 1\nChain ID: mainnet\nNonce: a4b5fb6f571c43b4b1c5057abaa8cea2\nIssued At: 2026-10-13T18:29:28.000Z\nExpiration Time: 2026-10-13T18:34:28.000Z",
"nonce": "a4b5fb6f571c43b4b1c5057abaa8cea2"
}- Сообщение действительно 5 минут и может быть использовано один раз. Chain ID указывает кластер Solana, в котором работает сервер.
| Статус | Когда |
|---|---|
| 400 | Не адрес Solana |
| 429 | Больше 30 запросов в минуту с вашего IP-адреса |
/api/auth/verifyОбменять подписанное сообщение на токен
| Поле | Тип | Описание |
|---|---|---|
address | string | Тот же адрес кошелька |
message | string | Сообщение точно в том виде, в каком оно получено |
signature | string | Подпись Ed25519 байтов сообщения (UTF-8), base58 |
curl -X POST "https://seeryx.com/api/auth/verify" \
-H "Content-Type: application/json" \
-d '{"address":"4hfqTJ6sVSszXZGCYjXEr4YuAXz9nyLut8725NP9mVvm","message":"...","signature":"5Kq3..."}'{ "token": "eyJ0eXAiOiJKV1Qi...", "user": { "id": 3, "address": "4hfqTJ6sVSszXZGCYjXEr4YuAXz9nyLut8725NP9mVvm", "createdAt": "2026-10-13 18:29:28" } }- Токен действителен 7 дней. Отправляйте его как X-Auth-Token (или Authorization: Bearer) в каждом запросе, требующем входа. Первый вход создаёт аккаунт.
| Статус | Когда |
|---|---|
| 401 | «Signature verification failed» или «Invalid or expired login message» |
| 403 | Этот аккаунт заблокирован |
| 429 | Больше 30 запросов в минуту с вашего IP-адреса |
/api/auth/meАккаунт, в который выполнен вход, и его средства
curl "https://seeryx.com/api/auth/me" \
-H "X-Auth-Token: $TOKEN"{ "user": { "id": 3, "address": "4hfqTJ6sVSszXZGCYjXEr4YuAXz9nyLut8725NP9mVvm", "username": null, "avatar": null },
"balance": { "total": 474.097965, "available": 474.097965, "locked": 0, "currency": "USDC" } }/api/auth/logoutЗавершить действие этого токена входа
curl -X POST "https://seeryx.com/api/auth/logout" \
-H "X-Auth-Token: $TOKEN"{ "success": true }- Другие токены аккаунта продолжают работать. Ключ торговой сессии при этом продолжает действовать: закройте его через POST /api/relay close_session.
/api/auth/logout-allЗавершить действие всех токенов входа аккаунта
curl -X POST "https://seeryx.com/api/auth/logout-all" \
-H "X-Auth-Token: $TOKEN"{ "success": true }- Все выданные до сих пор токены, включая этот, перестают работать; чтобы получить новый, войдите заново.
/api/auth/usernameЗадать или изменить публичное имя пользователя
| Поле | Тип | Описание |
|---|---|---|
username | string | 2–20 букв, цифр или _; уникально без учёта регистра |
curl -X POST "https://seeryx.com/api/auth/username" \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"username":"satoshi_bot"}'{ "success": true, "username": "satoshi_bot" }- Имя показывается в рейтинге и в вашем публичном профиле; без него там отображается сокращённый адрес кошелька.