Ifx Rust SDK (ifx-sdk)
English | 中文
Rust off-chain client for Ifx: build ifx_create_frame, ifx_let, ifx_assert, ifx_patched_cpi, ifx_if_else, and related instructions. Does not wrap RPC or wallets — you get solana_sdk::instruction::Instruction values; your backend signs and sends.
Clusters: Default
program_idis mainnet (DEFAULT_IFX_PROGRAM_ID=IFX_MAINNET_PROGRAM_ID). Local Surfpool / repo integration tests useIFX_LOCALNET_PROGRAM_ID. Devnet:IFX_DEVNET_PROGRAM_ID.
- Crates.io name:
ifx-sdk - Directory:
rust-sdk/(same convention asgo-sdk/) - Shared types:
ifx-core
Two layers
FrameScratch— plan tape bindings (let_*/LetBuilder), emitix_reset,ix_let,ix_assert,ix_cpi(ifx_patched_cpi),ix_if_else, …expr+ScratchValue— build on-chainExprtrees and Frame bindings (binding index, remaining accounts, types)
Prefer FrameScratch in application code; use build_ix_create_frame and friends when you need lower-level control.
Install
Current release: 0.1.3 on crates.io (ifx-core@0.1.2; mainnet default; aligned with @ifx-run/sdk@0.1.3 and go-sdk@v0.1.3).
Monorepo path dependency:
= { = "../rust-sdk" }
Pin in Cargo.toml:
= { = "0.1.3" }
= { = "0.1.2" }
Quick start
Tx 1 — Create a Frame (standalone)
Do not mix create with swap/settlement in the same transaction.
use IFX_DEVNET_PROGRAM_ID;
use ;
let frame_id = ;
let plan = plan_public_frame?;
// Send plan.ix_create alone; persist plan.frame (pubkey) + tape_len (frame_id optional after create)
// plan.scratch.authority == plan.frame (public Frame — no extra signer on reset/let)
Optional — private / closeable Frame (authority: payer, signs reset/let; can close for rent): use plan_new_frame — frame-authority.md.
Tx 2 — Business (reset + let + assert / CPI)
use expr;
use FrameScratch;
let mut s = plan.scratch;
let reset_ix = s.ix_reset;
let target = s.let_const_u64?;
let let_ix = s.ix_let_single?;
let assert_ix = s.ix_assert?;
// Assemble transaction, sign, send
Production: logs, not Frame decode
Confirm behavior via Ifx transaction logs (conditions, CPI arms, patch offsets, assert results). On failure, use logs + error codes (errors).
Do not call decode_frame_account or tape readback helpers in production. These are for tests, examples, and local debugging only. Standalone business txs still start with ix_reset.
Single vs multi binding
Single: s.let_lamports(user)? → s.ix_let_single(&sv)? → later expr::r(&sv).
Multi: s.let_builder() → several lamports / spl_token_amount / … → b.build_ix()? (remaining deduped).
Conditions for ix_assert / ix_if_else: bool Expr or bool ScratchValue.
When to let
- Persist: values used later by assert, CPI patches, or later lets
- Skip persist: nest in
LetEval, or compare insideix_assertonly
Fixed tape_len at create (no extend/shrink). See errors.md for IndexCapReached / TapeOutOfBounds.
Session helpers
| Method | Use |
|---|---|
plan_new_frame |
New Frame: scratch + ix_create + PDA |
plan_public_frame |
authority = Frame PDA (non-closeable; public scratch) |
FrameScratch::new |
New session on an existing Frame (production path) |
Public Frame check after decode (tests / debug only): public_frame_authority(frame) == decoded.authority.
(decode_frame_account — tests & debug only.)
Structured CPI & patched CPI
Use encode_cpi / build_ix_cpi with structured patches from ifx_core::structured_cpi, or raw patched CPI templates via cpi helpers. See structured-cpi-patches.md. Wire parity: rust-sdk/src/parity.rs.
Modules
| Module | Role |
|---|---|
scratch |
Planner |
frame / decode |
PDA, decode, readback (debug) |
expr / binding / typed / wire_ix |
IR + wire |
ix / cpi |
Instructions + CPI |
let_bindings / let_builder |
Let helpers |
frame_authority |
Public / private Frame authority helpers |
constants |
Program IDs, discriminators, tape limits |
Examples
See examples/README.md — reference planners under tests/common/planners/ (L0–L3); localnet e2e in tests/localnet.rs.
Errors
On-chain codes surface as transaction failures; match messages with error reference (6000–6035). Client-side planning errors: ScratchError.
Program IDs
IFX_MAINNET_PROGRAM_ID · IFX_DEVNET_PROGRAM_ID · IFX_LOCALNET_PROGRAM_ID · DEFAULT_IFX_PROGRAM_ID. Set once on FrameScratch via PlanNewFrameParams::program_id.
Tests
Unit + wire parity (no RPC):
Localnet integration (Surfpool / anchor test validator; skips when RPC unavailable):
Or from repo root: npm run rust:test / npm run rust:test:integration.
Other languages
TypeScript: @ifx-run/sdk. Go: go-sdk. Same on-chain wire. See repo docs/ for orchestration patterns.