Node RPC
xrs-node 0.1.1port 5600148 routes
Four routes write; everything else reads.
Base
| Fact | Value |
|---|---|
| base URL | http://<host>:56001 |
| transport | HTTP/1.1, no TLS |
| CORS | * |
| body | JSON |
| errors | {"error":"…"}, HTTP 200; 501 only on the governance and claim stubs |
| write rate | 30 per minute per IP |
| write body | 256 KiB |
| planner body | 16 KiB |
| reads | no limit |
| amounts | lamports unless the key ends _xrs |
| token amounts | the token's decimals |
Write
| Route | First instruction | Pre-checks | Success |
|---|---|---|---|
POST /submit | any | admission | {"status": "ok", "signature"} |
POST /stake | Stake | signer = pubkey; balance ≥ amount; roster key on mainnet | {"status": "queued", "staked", …} |
POST /unstake | Unstake | stake ≥ amount; unstake all or keep ≥ 1,000 XRS; at least 1 XRS | {"status": "queued", "unstaked", "unbonding_period_slots": 151200} |
POST /pq-register | PqKeyRegister | signer = ed25519_pubkey | {"status": "queued", "ed25519_pubkey"} |
Body for all four: {"tx_base64":"…"}, the bincode transaction in base64 (envelope).
curl -s -X POST http://138.197.116.81:56001/submit \
-H 'Content-Type: application/json' \
-d '{"tx_base64":"<base64>"}'
# {"status":"ok","signature":"<base58>"} | {"error":"…"}
await client.sendInstruction(wallet, ix); // POST /submit
await client.stakeXrs(wallet, 1000); // POST /stake
await client.unstakeXrs(wallet, 1000); // POST /unstake
// POST /pq-register, 1,952-byte key
await client.pqKeyRegister(wallet, pqPublicKey, 'dilithium3', 3);
Admission
| Check | Rejection on /submit |
|---|---|
| rate limit | Rate limited. Max 30 write RPCs per minute per IP. |
| base64 | Invalid base64 encoding |
| bincode | Failed to deserialize transaction |
| signature | Transaction validation failed: Invalid transaction signature |
| instruction count | Transaction validation failed: Too many instructions in transaction |
| instruction size | Transaction validation failed: Instruction data exceeds size limit |
| legacy transfer | Transaction validation failed: Legacy SystemInstruction::Transfer is disabled |
SubDelegate | Transaction validation failed: SubDelegate is disabled (XWC-82) |
| federation | Public self-staking is closed during federated beta |
| on chain already | Transaction already processed |
| in the mempool already | Transaction already in mempool |
| blockhash | Transaction rejected: recent_blockhash expired or unknown |
| payer below the fee, quota full | "status":"rejected_underfunded_quota" |
| pool full | "status":"rejected_mempool_full" |
The hint's
/v2/recent_blockhash does not exist. Use JSON-RPC getLatestBlockhash, port 50008.Chain and stake
| Route | Returns |
|---|---|
GET /health | {"status":"ok"} |
GET /blocks | 50 newest blocks, hashes as byte arrays |
GET /stake/{address} | stake, isValidator (≥ 1,000 XRS), earns_staking_rewards (≥ 100 XRS), 7 % APR estimates |
GET /account/ | sessions[]; *_time = slot × 4 s |
GET /network/economics | emission, block reward, halving, fees, staking totals |
curl -s http://138.197.116.81:56001/network/economics
# {"chain_height":…,"current_block_reward_xrs":10.0,
# "emission_cap_xrs":500000000.0,"base_tx_fee_xrs":0.001,…}
Tokens
| Route | Returns |
|---|---|
GET /tokens | {"tokens":[…]}, unpaginated |
GET /token/ | balance, token_info |
GET /token/ | native_xrs (lamports), token_accounts[] |
Contracts and launchpads
| Route | Returns |
|---|---|
GET /contracts | contract_id, type, owner, is_active |
GET /contract/{id} | contract.state, keyed by type |
GET /contract/ | swap quote; price_impact_pct is a string |
GET /contract/ | {"vesting":{"enabled":false}}: deploy refuses vesting |
GET /launchpads | every launchpad, newest first; xeris_fee_bps 77 |
GET /launchpad/ | tokens_out, fees, price_impact_pct (number) |
Agents, capabilities, tasks
| Route | Returns |
|---|---|
GET /agent/ | agents[]: limits, spend, revoked |
GET /agent/ | authorized, revoked, expired, agent |
GET /capabilities | active listings with an active identity |
GET /capabilities/ | filtered, by reputation; limit 50 |
GET /tasks | open_tasks, data[] |
GET /tasks/{id} | one TaskEntry |
Planner
Route, action | Request | Returns |
|---|---|---|
POST /agent/plan | {"action":"…",…} | variant_index, variant_name, params |
transfer | from, to, amount_xrs | NativeTransfer, fee, sufficient_balance |
swap | pool_id, token_in, amount_in, slippage_pct | ContractCall, args as 16 bytes, quote |
buy_launchpad | launchpad_id, xrs_amount, slippage_pct | ContractCall, args as a JSON object, quote |
stake | pubkey, amount_xrs | Stake |
wrap, unwrap | amount_xrs | WrapXrs, UnwrapXrs |
Read-only: returns what to sign, never signs.
curl -s -X POST http://138.197.116.81:56001/agent/plan \
-H 'Content-Type: application/json' \
-d '{"action":"transfer","from":"<from>","to":"<to>","amount_xrs":1.5}'
# {"action":"transfer","variant_index":11,"variant_name":"NativeTransfer",
# "params":{"from":"…","to":"…","amount":1500000000},"amount_xrs":1.5,
# "fee":1000000,"fee_xrs":0.001,"sender_balance":…,
# "sufficient_balance":true}
import { fromPlan } from 'xeris-sdk';
// POST /agent/plan
const plan = await client.planTransfer(wallet.publicKey, to, 1.5);
await client.sendInstruction(wallet, fromPlan(plan)); // signs and submits
Governance, ZK, PQ
| Route | Returns |
|---|---|
GET /governance/ | proposals[]; timestamps are slot × 4,000 ms |
GET /governance/ | locked_amount, locked_xrs, delegate |
GET /zk/ | proofs[] by submitter |
GET /zk/ | one ZkProofRecord |
GET /zk/stats | total_proofs, total_verified |
GET /pq/keys/{address} | has_pq_key, algorithm, security_level, key_hash, active |
GET /pq/status | total_registered, algorithms, quantum_ready_pct |
Prices
| Route | Returns |
|---|---|
GET /price-history?pool_id=&limit= | last limit (500, ≤ 10,080); one per 100 blocks |
GET /pools/price-history | last 100 per pool |
Node-local, not consensus.
Disabled
| Route | Answer |
|---|---|
/ | HTTP 200, "status":501 |
POST /stake/claim | HTTP 501 |
POST /governance/ | HTTP 501, variants 39–41 instead |
POST /token/ | HTTP 200, Direct RPC mutation disabled… |
POST /contract/ | HTTP 200, Direct RPC mutation disabled… |
POST /rwa/ | HTTP 200, Direct RPC mutation disabled… |
State changes go through /submit.