Premiers pas
Authentification
Sign-In With Solana pour l’API Seeryx : le message, le jeton dans X-Auth-Token ou Bearer, et la clé de session de trading qui signe vos ordres.
Vue d’ensemble
| Appels | Prérequis |
|---|---|
| Données de marché : marchés, manches, carnets, transactions, événements, profils | Rien |
| Votre compte : liquidités, positions, ordres, activité | Un jeton de connexion dans X-Auth-Token |
| Ordres, annulations, scissions, fusions | Le jeton et un en-tête Idempotency-Key ; sur seeryx.com, chaque ordre, scission et fusion porte aussi signed, produit par votre clé de session de trading |
| Dépôts, retraits, la session elle-même | Le jeton, et la signature de votre portefeuille sur la transaction préparée par le serveur |
Connexion avec un portefeuille
Seeryx utilise Sign-In With Solana : votre portefeuille signe un court message texte, ce qui ne coûte rien et n’envoie rien sur la blockchain.
POST /api/auth/nonceavec{ "address": "<your wallet>" }renvoie le message. Il est valable 5 minutes et ne peut servir qu’une fois.- Vérifiez que la ligne 1 nomme ce site et la ligne 2 votre adresse, puis signez les octets UTF-8 exacts du message avec la clé Ed25519 du portefeuille et encodez la signature de 64 octets en base58.
POST /api/auth/verifyavecaddress,messageetsignaturerenvoietoken. La première connexion crée le compte.
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
}Jetons de connexion
- En-tête
- Envoyez le jeton sous la forme
X-Auth-Token: <token>ouAuthorization: Bearer <token>dans chaque requête authentifiée, et commetokendans l’abonnement au compte du WebSocket. - Durée de validité
- 7 jours. Reconnectez-vous avant leur expiration, ou lorsqu’un appel répond 403 (seeryx.com) ou 401 avec "Invalid or expired token".
- Cookies
- Le site lui-même se connecte avec un cookie HttpOnly et un jeton CSRF, que seules les pages du site peuvent utiliser. Les clients de l’API utilisent l’en-tête du jeton et n’ont besoin ni de l’un ni de l’autre.
- Limites
- 30 requêtes par minute et par adresse IP pour chacun des endpoints
/auth/nonceet/auth/verify.
La clé de session de trading
Sur seeryx.com, chaque opération est réglée sur Solana par le programme Seeryx, et le programme n’accepte que des ordres signés pour votre compte. Au lieu de solliciter le portefeuille à chaque ordre, le portefeuille approuve une seule fois une clé de session :
| Champ | Type | Description |
|---|---|---|
key | clé publique | Une nouvelle clé Ed25519 créée par votre bot. Elle signe les ordres, les scissions et les fusions. |
expiresAt | secondes Unix | Le moment où la clé cesse de fonctionner : au plus maxSessionTtl de GET /api/funds à partir de maintenant (24 heures). |
limit | USDC | Le montant maximal que la clé peut dépenser au total en achats et en scissions. |
maxTrade | USDC | Le montant maximal qu’un ordre peut dépenser ; au plus limit. |
- Elle peut négocier, jamais retirer. La clé ne peut signer que des ordres, des scissions et des fusions pour votre compte, dans ses limites. Les retraits nécessitent toujours le portefeuille lui-même.
- Une seule à la fois. Une nouvelle session remplace l’ancienne clé ; les ordres en attente signés par l’ancienne clé sont annulés dès que la nouvelle est utilisée.
- Les ordres à cours limité ne doivent pas lui survivre. Un ordre en attente est refusé s’il devait rester dans le carnet au-delà de la fin de la session : ouvrez une nouvelle session avant de coter une manche qui se clôture plus tard (les manches d’un jour, par exemple).
- Gratuite. Seeryx paie les frais de réseau et le loyer du compte de la transaction de session. Votre premier dépôt doit d’abord avoir ouvert votre compte (d’ici là : 409 "Deposit first").
- Fermez-la plus tôt avec
POST /api/relay{ "action": "close_session" }: vos ordres en attente sont annulés et la clé cesse aussitôt de fonctionner.
Comment ouvrir la session et signer avec elle, octet par octet : Signature des ordres.
Déconnexion
POST /api/auth/logoutmet fin au jeton que vous envoyez ;POST /api/auth/logout-allmet fin à tous les jetons du compte.- Aucun des deux ne met fin à la clé de session de trading : fermez-la avec
close_session, ou laissez-la expirer.
curl -s -X POST https://seeryx.com/api/auth/logout-all -H "X-Auth-Token: $TOKEN"
# {"success":true}Endpoints de connexion
Connexion avec un portefeuille Solana : demandez un message, signez ses octets exacts avec la clé du portefeuille, échangez la signature contre un jeton. Rien n’est envoyé sur la blockchain et rien n’est payé.
/api/auth/nonceObtenir le message à signer
| Champ | Type | Description |
|---|---|---|
address | string | Adresse du portefeuille 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"
}- Le message est valable 5 minutes et ne peut servir qu’une fois. Chain ID désigne le cluster Solana du serveur.
| Statut | Cas |
|---|---|
| 400 | Ce n’est pas une adresse Solana |
| 429 | Plus de 30 requêtes par minute depuis votre adresse IP |
/api/auth/verifyÉchanger le message signé contre un jeton
| Champ | Type | Description |
|---|---|---|
address | string | La même adresse de portefeuille |
message | string | Le message exactement tel que reçu |
signature | string | Signature Ed25519 des octets du message (UTF-8), en 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" } }- Le jeton est valable 7 jours. Envoyez-le dans X-Auth-Token (ou Authorization: Bearer) dans chaque requête authentifiée. La première connexion crée le compte.
| Statut | Cas |
|---|---|
| 401 | "Signature verification failed" ou "Invalid or expired login message" |
| 403 | Ce compte est bloqué |
| 429 | Plus de 30 requêtes par minute depuis votre adresse IP |
/api/auth/meLe compte connecté et ses liquidités
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/logoutMettre fin à ce jeton de connexion
curl -X POST "https://seeryx.com/api/auth/logout" \
-H "X-Auth-Token: $TOKEN"{ "success": true }- Les autres jetons du compte continuent de fonctionner. Cela ne met pas fin à la clé de session de trading : fermez-la avec POST /api/relay close_session.
/api/auth/logout-allMettre fin à tous les jetons de connexion du compte
curl -X POST "https://seeryx.com/api/auth/logout-all" \
-H "X-Auth-Token: $TOKEN"{ "success": true }- Tous les jetons émis jusqu’ici cessent de fonctionner, celui-ci compris ; reconnectez-vous pour en obtenir un nouveau.
/api/auth/usernameDéfinir ou modifier le nom d’utilisateur public
| Champ | Type | Description |
|---|---|---|
username | string | De 2 à 20 lettres, chiffres ou _ ; unique sans tenir compte de la casse |
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" }- Le nom apparaît dans le classement et sur votre profil public ; sans nom, ceux-ci affichent votre adresse de portefeuille abrégée.