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.devin production,http://localhost:8080in 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.