Search docs

Find a documentation page

Trader integration guide

Book a lease and route transactions through the staked-QUIC path with the Rust, TypeScript, or Python SDK.

Pre-requisites

  • An API token issued from the marketplace dashboard (Authorization: Bearer <token> on every request).
  • A Solana wallet able to send SOL (the booking returns a Solana Pay transaction request your wallet fetches, signs, and submits on-chain).
  • The marketplace API base URL: https://api.swqos.dev in production, http://localhost:8080 in dev.

Step 1: Discover validators

GET /v1/validators returns a paginated list with stake, 30-day uptime, and effectiveness. Pick the one whose price / uptime profile fits your workload.

Step 2: Book a lease

POST /v1/leases with an Idempotency-Key header. The marketplace is epoch-based, not slot-based: the request body is { validator_id, epoch_start, epoch_count }, where validator_id is the target validator's ULID public_id, epoch_start is the first Solana epoch to cover (inclusive), and epoch_count is how many epochs to lease (1..=30). The response is { lease_id, payment }, wrapped in a { "data": ... } envelope, where payment is the Solana Pay instructions { solana_pay_url, amount_lamports, memo }. Open solana_pay_url with a wallet: it is a Solana Pay transaction request, so the wallet fetches the exact transaction the marketplace built (the atomic split to the validator and the platform, with the memo already embedded) and you sign it. The settlement worker matches that transaction to the lease by its memo. Then poll the lease until it activates (Step 3).

The Idempotency-Key must be a 26-character ULID. A non-ULID value (including a UUID) is rejected with 400 idempotency-key-malformed. Retries with the same key return the cached response for 24 hours per Design Doc §5.2.3.

Rust

The Rust SDK lives in the sibling repo at client-sdk/:

use staked_quic_client_sdk::{Client, CreateLeaseRequest};
use ulid::Ulid;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Client::builder()
        .base_url("https://api.swqos.dev")
        .bearer_token(std::env::var("MARKETPLACE_TOKEN")?)
        .build()?;

    let lease = client
        .create_lease(
            CreateLeaseRequest {
                validator_id: "01HXY...".into(),
                epoch_start: 720,
                epoch_count: 10,
            },
            Ulid::new().to_string(),
        )
        .await?;

    println!("lease {}: pay at {}", lease.lease_id, lease.payment.solana_pay_url);
    Ok(())
}

TypeScript

The TypeScript snippet mirrors the frontend's lib/domains/leases/api/mutations.ts pattern: a typed wrapper over fetch plus a ULID for the idempotency header.

import { ulid } from "ulid";

type CreateLeaseInput = {
  validator_id: string;
  epoch_start: number;
  epoch_count: number;
};

export async function createLease(input: CreateLeaseInput, token: string) {
  const res = await fetch("https://api.swqos.dev/v1/leases", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${token}`,
      "Idempotency-Key": ulid(),
    },
    body: JSON.stringify(input),
  });
  if (!res.ok) throw new Error(`createLease failed: ${res.status}`);
  return (await res.json()) as {
    data: {
      lease_id: string;
      payment: {
        solana_pay_url: string;
        amount_lamports: number;
        memo: string;
      };
    };
  };
}

Python

A requests-based illustration. No SDK package required, the API contract is the same on the wire.

import os
import requests
from ulid import ULID  # pip install python-ulid

def create_lease(validator_id: str, epoch_start: int, epoch_count: int) -> dict:
    response = requests.post(
        "https://api.swqos.dev/v1/leases",
        headers={
            "Authorization": f"Bearer {os.environ['MARKETPLACE_TOKEN']}",
            "Idempotency-Key": str(ULID()),
            "Content-Type": "application/json",
        },
        json={
            "validator_id": validator_id,
            "epoch_start": epoch_start,
            "epoch_count": epoch_count,
        },
        timeout=10,
    )
    response.raise_for_status()
    # data = { "lease_id": ..., "payment": { "solana_pay_url",
    #          "amount_lamports", "memo" } }
    return response.json()["data"]

The Idempotency-Key must be a 26-character ULID. A UUID or any other non-ULID value is rejected with 400 idempotency-key-malformed. ULIDs also sort lexically by time, which makes the keys easier to debug.

Step 3: Wait for payment confirmation

Open solana_pay_url with a wallet and sign the transaction it fetches (the marketplace builds it with the split and memo already embedded), then poll GET /v1/leases/:id until status flips from pending_payment to active. The settlement worker matches the on-chain transaction by its memo and activates the lease within a few seconds of confirmation. The transaction-request endpoint refuses to build a transaction for an expired booking, so a lease left unpaid past its window cannot be paid late.

Step 4: Issue a signing JWT and route traffic

Once the lease is active, request a short-lived ES256 JWT (POST /v1/leases/:id/token) and pass it to the TPU client. The sibling repo's staked-quic-tpu-client crate handles handshake forwarding to the validator's TEE for you. See the Rust SDK reference for the full surface.