Skip to main content

IntentVM Developer Guide

IntentVM is Vexidus's declarative transaction engine. Instead of building low-level operations manually, developers describe what they want and the engine figures out the optimal execution path.


Quick Start

Using the Rust SDK

use vexidus_sdk::{IntentBuilder, parse_intent};
use vexidus_types::primitives::{Address, Amount, Timestamp};

// Option 1: Fluent builder
let (goal, constraints) = IntentBuilder::new()
.stake(Amount::from_vxs(1000), None)
.with_slippage(1)
.build()
.unwrap();

// Option 2: Natural language
let parsed = parse_intent("stake 1000 VXS").unwrap();

// Serialize for RPC submission
let json = IntentBuilder::new()
.swap(Address::ZERO, usdc_addr, Amount::from_vxs(100))
.to_json()
.unwrap();

Outcome-Based Intents (Builder API)

use vexidus_sdk::IntentBuilder;

// Acquire: "get me 10 SOL, max 200 USDC"
let (goal, constraints) = IntentBuilder::new()
.acquire("SOL", 10.0)
.with_max_cost("USDC", 200.0)
.build()
.unwrap();

// Liquidate: "sell everything for USDC, keep my VXS"
let (goal, constraints) = IntentBuilder::new()
.liquidate("USDC", 500.0)
.exclude(&["VXS"])
.build()
.unwrap();

// Rebalance portfolio
let (goal, constraints) = IntentBuilder::new()
.rebalance(&[("VXS", 50), ("ETH", 30), ("USDC", 20)])
.build()
.unwrap();

Using RPC Directly

# Submit an intent (natural language)
curl -s https://testnet.vexidus.io \
-d '{"jsonrpc":"2.0","method":"vex_submitIntent","params":["swap 100 VXS for USDC","SENDER_ADDRESS"],"id":1}' | jq .

# Preview for wallet confirmation (human-readable)
curl -s https://testnet.vexidus.io \
-d '{"jsonrpc":"2.0","method":"vex_previewIntent","params":["swap 100 USDC for VXS","SENDER_ADDRESS"],"id":1}' | jq .

# Simulate execution (detailed dry-run)
curl -s https://testnet.vexidus.io \
-d '{"jsonrpc":"2.0","method":"vex_simulateIntent","params":["swap 100 USDC for VXS","SENDER_ADDRESS"],"id":1}' | jq .

# Get price quote
curl -s https://testnet.vexidus.io \
-d '{"jsonrpc":"2.0","method":"vex_getPrice","params":["USDC","VXS"],"id":1}' | jq .

# Check intent status
curl -s https://testnet.vexidus.io \
-d '{"jsonrpc":"2.0","method":"vex_getIntentStatus","params":["VxhBUNDLE_HASH"],"id":1}' | jq .

Wallet Integration (Confirm-Before-Submit)

Wallets should follow a two-step flow for intent submission:

Step 1: Preview -- Call vex_previewIntent to get a human-readable confirmation:

{
"summary": "Swap 100 USDC -> ~1985.5 VXS (via USDC/VXS pool)",
"route_type": "direct",
"estimated_fee_vxs": "0.00042 VXS",
"price_impact": "0.3%",
"slippage_tolerance": "1%",
"balance_sufficient": true,
"warnings": []
}

Step 2: Submit -- If the user approves, call vex_submitIntent with the same intent string.

For auto-routed swaps, the preview shows the routing path:

{
"summary": "Swap 100 DAI -> ~4.2 SOL (via DAI -> VXS -> SOL)",
"route_type": "auto-routed (2 hops)",
"price_impact": "1.2%",
"warnings": ["Auto-routed through VXS. Slippage applied per leg."]
}

Supported Intent Patterns

Token Operations

PatternExampleGoal Type
Swap"swap 100 VXS for USDC"Swap
Swap with slippage"swap 50 ETH for VXS with 3% slippage"Swap + constraints
Buy"buy 100 VXS with USDC"Swap (reversed)
Sell"sell 50 ETH for USDC"Swap
Convert"convert 200 USDT to VXS"Swap
Trade"trade 100 SOL for VXS"Swap
Multi-swap"swap 10 USDC and 10 USDT for VXS"Composite (2 swaps)

Staking & Liquidity

PatternExampleGoal Type
Stake"stake 1000 VXS"Stake
Stake with validator"stake 500 VXS with validator Vx0abc..."Stake
Provide liquidity"add liquidity 100 VXS and 50 USDC"ProvideLiquidity

Transfers & Bridge

PatternExampleGoal Type
Transfer"send 100 VXS to Vx0abc..."Transfer
Transfer (VNS)"send 50 USDC to chris.vex"Transfer
Pay"pay 25 VXS to Vx0abc..."Transfer
Bridge"bridge 10 SOL from solana"Bridge
Bridge + Swap"bridge 10 SOL from solana and swap to VXS"Composite

Outcome-Based Intents

Specify what you want, not the steps. The planner reverse-engineers the execution.

PatternExampleGoal Type
Acquire"get me 10 SOL, max 200 USDC"Acquire
Acquire (no limit)"get me 5 ETH"Acquire
Acquire (I need)"I need 100 VXS, spending at most 50 USDC"Acquire
Liquidate"liquidate to 500 USDC"Liquidate
Liquidate (keep)"sell everything for USDC keeping VXS"Liquidate
Liquidate (exclude)"cash out to 1000 USDC excluding VXS and ETH"Liquidate
Rebalance"rebalance to 50% VXS, 30% USDC, 20% ETH"Rebalance

How Acquire works: The planner queries pool reserves, uses reverse AMM math to calculate the exact input amount needed to receive your target output, validates against your max cost constraint, and executes the swap. If the required cost exceeds your max, the intent is rejected before execution.

How Liquidate works: The planner queries your on-chain token holdings, excludes any tokens you want to keep, sorts remaining holdings by best swap rate to the target token, and greedily sells from best rate until your target amount is covered.

Portfolio Intelligence

PatternExampleGoal Type
Allocate"put 100 VXS split 60 stake 40 liquidity"Allocate
DCA"buy 10 VXS with USDC every day for 7 days"Recurring
DCA (hourly)"swap 5 USDC for VXS every hour for 24 hours"Recurring
DCA (weekly)"buy 100 VXS with USDC every week for 4 weeks"Recurring

Conditional & Limit Orders

PatternExampleGoal Type
Price condition"swap 100 USDC for VXS if price below 0.15"Conditional
Limit buy"limit buy 100 VXS at 0.12 USDC"Conditional
Price above"sell 50 VXS for USDC if price above 1.5"Conditional

Synthetic Assets (VSC-71)

PatternExampleGoal Type
Mint synthetic"buy 10 AAPL with USDC"MintSynthetic
Mint index"buy 5 SPY with USDC"MintSynthetic
Long perpetual"open 5x long ETH perp with 100 USDC"OpenPosition
Short perpetual"short BTC 3x with 200 USDC"OpenPosition
note

VSC-71 synthetic assets are a licensee interface. The Goal types are parsed and accepted by IntentVM, but oracle pricing and margin logic are not built into the base protocol. See the VSC-71 Integration Guide for how to implement.

VNS Registration

PatternExampleGoal Type
Register name"register chris.vex"Custom (VNS)
Register (no suffix)"register myname"Custom (VNS)

Inline Constraints

Constraints can be embedded directly in any intent string. The parser extracts them before processing the goal:

ConstraintSyntaxExample
Slippage"with N% slippage""swap 100 VXS for USDC with 2% slippage"
Deadline"within N minutes", "deadline N seconds""swap 100 VXS for USDC within 5 minutes"
Max fee"max fee N", "gas limit N", "fee cap N""stake 1000 VXS max fee 50000"

Multiple constraints can be combined in a single intent:

"swap 100 USDC for VXS with 2% slippage within 5 minutes max fee 100000"

Multi-Language Support

The NL parser accepts intents in 7 languages. Non-English input is normalized to English equivalents before parsing. All intent types work in all languages -- swaps, transfers, staking, outcome-based intents, and constraints.

Supported Verbs

Languagebuysellswapsendstake
Englishbuy, get, purchasesell, dumpswap, convert, tradesend, paystake, deposit
Spanishcomprarvenderintercambiar, cambiarenviarapostar
Portuguesecomprarvendatrocarenvie--
Frenchachetervendreéchangerenvoyer--
Germankaufenverkaufentauschensenden--
Italiancomprarevenderescambiareinviare--
Japanese買う (kau)売る (uru)交換 (koukan)送る (okuru)--

Connector Words

Language"with""for""to""every"
Spanishconporparacada
Portuguesecom----cada
Frenchavecpour----
Germanmitfür----
Italiancon------

Examples by Language

# English
"buy 10 VXS with USDC" → Acquire (reverse-quotes ~1 USDC from pool)
"swap 100 USDC for VXS" → Swap (100 USDC input)
"get me 5 SOL max 200 USDC" → Acquire with cost cap

# Spanish
"comprar 10 VXS con USDC" → Acquire
"intercambiar 100 USDC por VXS" → Swap
"enviar 50 VXS para Vx0abc..." → Transfer

# Portuguese
"trocar 100 USDC por VXS" → Swap
"comprar 10 VXS com USDC" → Acquire

# French
"acheter 10 VXS avec USDC" → Acquire
"échanger 50 ETH pour VXS" → Swap

# German
"kaufen 10 VXS mit USDC" → Acquire
"tauschen 100 USDC für VXS" → Swap

# Italian
"comprare 10 VXS con USDC" → Acquire
"scambiare 100 USDC per VXS" → Swap
tip

"buy" vs "swap" semantics: "buy 10 VXS with USDC" produces an Acquire intent -- the 10 refers to the desired output, and the planner reverse-calculates the required USDC input from pool reserves. "swap 100 USDC for VXS" produces a Swap -- the 100 is the input amount. This distinction applies in all languages.

Adding a Language

The normalizer is a simple string replacement pipeline. To add a new language, map verbs and connectors to their English equivalents in the normalizer. Longer forms must be listed before shorter ones to prevent partial matching (e.g., Italian "comprare" before Spanish "comprar").


Known Token Symbols

SymbolTokenDecimalsMint Address
VXSNative Vexidus9Address::ZERO
USDCBridged USDC6Blake3("ethereum_USDC")
USDTBridged USDT6Blake3("ethereum_USDT")
DAIBridged DAI18Blake3("ethereum_DAI")
SOLBridged SOL9Blake3("solana_SOL")
ETH/WETHBridged ETH18Blake3("ethereum_ETH")
BTC/WBTCBridged BTC8Blake3("ethereum_WBTC")
BNBBridged BNB18Blake3("bsc_BNB")

Dynamic decimal resolution: The NL parser resolves each token's decimals from the on-chain token registry at parse time. For example, "swap 100 USDC for VXS" correctly uses 6 decimals for USDC (100 × 10^6) and 9 decimals for VXS. Custom tokens created via VexForge are also resolved dynamically.


RPC Methods

Intent Submission & Query

MethodParamsReturns
vex_submitIntent[intent_string, sender_address]Bundle hash
vex_getExecutionPlan[intent_string]Execution steps, estimated gas, savings
vex_getIntentStatus[bundle_hash]Status (pending/completed/failed), gas used

Simulation & Preview

MethodParamsReturns
vex_simulateIntent[intent_string, sender_address]Dry-run result: operations, per-pool quotes, price impact (bps), balance checks, warnings
vex_previewIntent[intent_string, sender_address]Human-readable confirmation: summary text, fee in VXS, price impact %, route type, warnings

Price Queries

MethodParamsReturns
vex_getPrice[from_symbol, to_symbol]Spot price, TWAP, route type (direct or auto-routed)
vex_quoteSwap[from_token, to_token, amount_in]Swap quote with estimated output

Simulation Response Format

vex_simulateIntent returns detailed execution analysis:

{
"success": true,
"operations": [
{
"type": "Swap",
"from_token": "USDC",
"to_token": "VXS",
"amount_in": "100000000",
"estimated_out": "1985500000000",
"price_impact_bps": 30
}
],
"estimated_gas": 42000,
"total_price_impact_bps": 30,
"warnings": [],
"balance_check": {
"sufficient": true,
"required": "100000000",
"available": "500000000"
}
}

For auto-routed swaps, each leg is reported separately:

{
"operations": [
{
"type": "Swap (Leg 1)",
"from_token": "DAI",
"to_token": "VXS",
"price_impact_bps": 15
},
{
"type": "Swap (Leg 2)",
"from_token": "VXS",
"to_token": "SOL",
"price_impact_bps": 22
}
],
"total_price_impact_bps": 37,
"warnings": ["Auto-routed through VXS. Slippage applied per leg."]
}

Price Impact & Warnings

The simulation and preview endpoints include a warnings array. Common warnings:

WarningMeaning
"High price impact (>5%)"Large order relative to pool size
"Auto-routed through VXS"No direct pool, using intermediate token
"Price impact exceeds 25% -- execution will be rejected"Order too large for available liquidity
"Insufficient balance"Sender doesn't have enough tokens

Architecture

User Input (NL or JSON, any supported language)
|
v
Multi-Language Normalizer
| maps non-English verbs to English equivalents
v
Constraint Extractor
| strips deadline, max_fee, slippage from text
v
NL Parser / JSON Deserializer
| pattern matching → Goal enum
v
IntentBuilder
| fluent API, builds Goal + Constraints
v
RPC: vex_previewIntent (wallet confirmation)
| summary, fee, price impact, warnings
v
RPC: vex_submitIntent
| builds intent bundle, submits to leader
v
Execution Engine
| decomposes Goal → native Operations
| auto-routing through intermediate pools
| price impact check (25% max per pool)
| constraint enforcement (deadline, fees, slippage)
v
Block Execution (atomic — all succeed or all revert)

Future: LLM Integration

The NL parser currently uses regex patterns. For more complex intents, integrate an LLM:

User: "Buy VXS with half my USDC and stake it with the highest-APY validator"
-> LLM extracts: Composite([
Swap { from: USDC, to: VXS, amount: 50% of balance },
Stake { token: VXS, amount: all, validator: highest_apy }
])

The Goal::Custom(String) variant is reserved for LLM-processed intents. Integration path:

  1. Client sends NL to LLM API (Grok, Claude, etc.)
  2. LLM returns structured Goal JSON
  3. Client submits structured JSON via vex_submitIntent