txline 0.4.0

Devnet-only Rust SDK for TxLINE.
Documentation

txline

Devnet-only Rust SDK for TxLINE.

This crate is the Rust package in the txline multi-language SDK workspace.

This crate intentionally supports TxLINE Devnet only. Mainnet constants, feature flags, examples, and transaction flows are out of scope for this SDK version.

Overview

txline provides typed Rust helpers for the current TxLINE Devnet APIs and Solana program addresses:

  • Devnet configuration and client construction.
  • Guest JWT and activated API token handling.
  • REST clients for fixtures, odds, scores, validation, and purchase quotes.
  • SSE odds and scores streams with reconnect support and heartbeat filtering.
  • Typed soccer PlayerStats support on score records.
  • Legacy and V2 score stat-validation DTOs.
  • Devnet PDA and Token-2022 ATA helpers.
  • High-level Devnet setup flow for wallet, pricing matrix, subscribe, activation, and API token storage.
  • subscribe, request_devnet_faucet, purchase_subscription_token_usdt, and on-chain validation instruction builders.
  • Low-level public TxODDS trading builders for intents, direct trades, matching, settlement, claims, refunds, and audit checks.
  • View-like validation simulation helpers for fixtures, odds, legacy stats, and V2 stats.
  • Paid purchase quote transaction safety checks.

Published crate: https://crates.io/crates/txline

For paid purchase signing flows, use TxlineClient::purchase_quote_checked. It requires the expected backend signer and returns transaction bytes only after SDK safety validation succeeds.

Quick Start

use txline::{ApiToken, GuestJwt, TxlineClient, TxlineConfig};

# async fn run() -> txline::Result<()> {
let client = TxlineClient::new(TxlineConfig::devnet())?;

let guest = client.start_guest_session().await?;
let message = client.activation_preimage("SUBSCRIBE_TX_SIGNATURE", &[])?;

client.set_guest_jwt(GuestJwt::new(guest.token.as_str())?);
client.set_api_token(ApiToken::new("activated-api-token")?);

let fixtures = client.fixtures().snapshot(None, None).await?;
println!("fixtures: {}", fixtures.len());
# Ok(())
# }

Wallet setup is available through client.devnet_user_setup(). It fetches the pricing matrix, ensures the user's Token-2022 ATA exists, submits subscribe(service_level_id, weeks), signs the activation preimage, calls /api/token/activate, and stores the returned API token on the client. If an existing API token is supplied, on-chain subscribe and activation are skipped.

The activation preimage is:

${txSig}:${selectedLeagues.join(",")}:${jwt}

For the standard bundle with no selected leagues:

${txSig}::${jwt}

Only sign this compatibility-bound message for the matching TxLINE Devnet host, network, and subscription transaction.

Trading Builders

txline::solana::trading includes typed builders for the public, non-admin TxODDS Devnet trading instructions in the pinned PR #3 IDL (1.5.5). They are explicit-account instruction builders only; callers remain responsible for PDA selection and review. The builders do not validate mints, token programs, vault accounts, or PDA derivations, and callers remain responsible for market lifecycle orchestration, signing, simulation where appropriate, and sending.

The Devnet V2 score examples include Rust counterparts for the upstream PR #3 subscription_scores_1stat.ts, subscription_scores_v2.ts, and subscription_scores_v2a.ts flows.

World Cup Trading Lifecycle

txline::trading_lifecycle adds a Rust helper layer for World Cup-style prediction-market demos that settle from TxLINE score data. It composes the published Devnet pieces rather than introducing a private trading API:

  1. Subscribe or use the World Cup free tier, start a guest session, and activate an API token. Data requests require both Authorization: Bearer <guest-jwt> and X-Api-Token: <activated-api-token>.
  2. Define ScoreMarketTerms for final outcome, total-goals, or spread-style markets. Final-outcome soccer defaults use period=100, participant 1 goals stat key 1, and participant 2 goals stat key 2.
  3. Pass an explicit TermsHash into create_intent_plan or create_trade_plan. The public Devnet docs and IDL do not define a production terms-hash preimage, so the coordinating application or backend owns that hash format.
  4. Build intent, direct trade, match, close, settlement, claim, refund, and audit plans from caller-supplied accounts. The SDK does not derive unpublished trading PDAs or choose vaults.
  5. Observe live or historical scores through the REST clients or scores stream. Final outcome detection requires action=game_finalised, statusId=100, and period=100.
  6. Fetch the V2 proof payload with stat_validation_v2(fixture_id, seq, stat_keys). The helper checks that proof stat-key order matches the market order before building a validation instruction.
  7. Build and simulate or submit validate_stat_v2, then use the caller-owned trade accounts to settle, claim, refund, or audit where the public Devnet IDL supports it.
use txline::{
    ApiToken, FinalOutcomeConfig, GuestJwt, TxlineClient, TxlineConfig,
    extract_final_outcome, final_outcome_validation_plan, is_final_outcome_record,
};
use txline::solana::pda::parse_pubkey;

# async fn run() -> txline::Result<()> {
let client = TxlineClient::new(TxlineConfig::devnet())?;
client.set_guest_jwt(GuestJwt::new("guest-jwt")?);
client.set_api_token(ApiToken::new("activated-api-token")?);

let fixture_id = 17_952_170;
let scores = client.scores().historical_by_fixture(fixture_id).await?;
let Some(final_score) = scores.iter().find(|score| is_final_outcome_record(score)) else {
    return Ok(());
};
let outcome = extract_final_outcome(final_score, FinalOutcomeConfig::soccer_default())?;

let validation = client
    .scores()
    .stat_validation_v2(outcome.fixture_id, outcome.seq, outcome.stat_keys())
    .await?;

let program_id = parse_pubkey(client.config().program_id.as_str())?;
let plan = final_outcome_validation_plan(program_id, &validation, &outcome)?;
let validation_ix = plan.instructions[0].clone();
# let _ = validation_ix;
# Ok(())
# }

For direct settle_trade and settle_matched_trade helpers, the current Devnet IDL uses the legacy score-proof shape. Use settle_trade_params_from_legacy_validation or settle_matched_trade_params_from_legacy_validation after fetching the matching legacy stat_validation_legacy proof, or pass fully reviewed low-level params yourself.

Useful references:

Documentation

Normal Rust tests use checked-in validation golden fixtures and do not require Node, Anchor, or a local txodds/tx-on-chain checkout.

License

Licensed under either of:

  • Apache License, Version 2.0
  • MIT license

at your option.