Build against the current Xian DEX contracts. Use when quoting, swapping, adding or removing liquidity, reading DEX events, or designing autonomous trading flows on Xian.
Use this skill when working with the current Xian DEX contracts.
Default client stack:
xian-tech-pyxian_pyCurrent DEX surface:
con_pairs
PairCreated, Mint, Burn, Swap, Synccon_dex
con_dex_helper
buy(...) and sell(...)Prefer:
con_dex_helper.buy(...) / sell(...) for simple single-pair tradescon_dex calls for multi-hop routes and liquidity operationsThat matches the current contract split.
pip install xian-tech-py
from datetime import datetime, timedelta, timezone
from xian_py import Xian, Wallet
wallet = Wallet("your_private_key")
xian = Xian("http://127.0.0.1:26657", wallet=wallet)
def deadline(minutes: int = 5) -> str:
return datetime.now(timezone.utc) + timedelta(minutes=minutes)
Pairs are keyed by canonical token ordering.
def canonical_tokens(token_a: str, token_b: str) -> tuple[str, str]:
return (token_a, token_b) if token_a < token_b else (token_b, token_a)
token0, token1 = canonical_tokens("currency", "con_my_token")
pair_id = xian.get_state("con_pairs", "toks_to_pair", token0, token1)
if pair_id is None:
raise ValueError("pair does not exist")
reserve0, reserve1, _ = xian.call("con_pairs", "getReserves", {"pair": pair_id})
amounts = xian.call("con_dex", "getAmountsOut", {
"amountIn": 100,
"src": "currency",
"path": [pair_id],
})
expected_out = amounts[-1]
fee_bps = xian.call("con_dex", "getTradeFeeBps", {})
input_needed = xian.call("con_dex", "getAmountIn", {
"amountOut": 50,
"reserveIn": reserve0,
"reserveOut": reserve1,
"feeBps": fee_bps,
})
Which contract you approve depends on the path:
con_dex_helpercon_dexxian.approve(
contract="con_dex_helper",
token="currency",
amount=250,
mode="commit",
)
xian.approve(
contract="con_dex",
token="currency",
amount=250,
mode="commit",
)
con_dex_helpertx = xian.send_tx(
contract="con_dex_helper",
function="buy",
kwargs={
"buy_token": "con_my_token",
"sell_token": "currency",
"amount": 50,
"slippage": 1,
"deadline": deadline(5),
},
mode="commit",
)
tx = xian.send_tx(
contract="con_dex_helper",
function="sell",
kwargs={
"sell_token": "con_my_token",
"buy_token": "currency",
"amount": 25,
"slippage": 1,
"deadline": deadline(5),
},
mode="commit",
)
tx = xian.send_tx(
contract="con_dex",
function="swapExactTokenForTokenSupportingFeeOnTransferTokens",
kwargs={
"amountIn": 100,
"amountOutMin": 90,
"pair": pair_id,
"src": "currency",
"to": wallet.public_key,
"deadline": deadline(5),
},
mode="commit",
)
path = [pair_a, pair_b]
quoted = xian.call("con_dex", "getAmountsOut", {
"amountIn": 100,
"src": "currency",
"path": path,
})
min_out = quoted[-1] * 0.99
tx = xian.send_tx(
contract="con_dex",
function="swapExactTokensForTokens",
kwargs={
"amountIn": 100,
"amountOutMin": min_out,
"path": path,
"src": "currency",
"to": wallet.public_key,
"deadline": deadline(5),
},
mode="commit",
)
Approve both tokens to con_dex first, then:
tx = xian.send_tx(
contract="con_dex",
function="addLiquidity",
kwargs={
"tokenA": "currency",
"tokenB": "con_my_token",
"amountADesired": 1000,
"amountBDesired": 500,
"amountAMin": 990,
"amountBMin": 495,
"to": wallet.public_key,
"deadline": deadline(10),
},
mode="commit",
)
LP balances and LP allowances live in con_pairs.
tx = xian.send_tx(
contract="con_dex",
function="removeLiquidity",
kwargs={
"tokenA": "currency",
"tokenB": "con_my_token",
"liquidity": 10,
"amountAMin": 9,
"amountBMin": 4,
"to": wallet.public_key,
"deadline": deadline(10),
},
mode="commit",
)
Key indexed DEX events are on con_pairs:
PairCreatedMintBurnSwapSyncTransferLiqApproveLiqRouter admin events such as ZeroFeeTraderUpdated are on con_dex.
swaps = xian.list_events("con_pairs", "Swap", limit=50)
pair_created = xian.list_events("con_pairs", "PairCreated", limit=25)
router_events = xian.list_events("con_dex", "ZeroFeeTraderUpdated", limit=25)
For restart-safe consumers, store the last processed event_id and use
after_id=... on the next poll.
Current DEX assertions use SNAKX:* messages. Expect errors such as:
SNAKX: EXPIREDSNAKX: INVALID_PATHSNAKX: NO_PAIRSNAKX: INSUFFICIENT_OUTPUT_AMOUNTSNAKX: INSUFFICIENT_LIQUIDITYTreat them as normal routing/market validation failures, not transport errors.
Today, the clean autonomous posture is polling-based:
Swap / Sync / token events with an after_id cursorIf you are implementing this inside xian-intentkit, the current building
blocks are:
xian_list_eventsxian_call_contractxian_send_contract_transactiontwitter_post_tweetThe current xian-intentkit trigger model is scheduled polling, not true push
subscription. Design the strategy around periodic checks.
amountOutMin / slippage bounds.contracts/dex/src/con_dex.pycontracts/dex/src/con_dex_helper.pycontracts/dex/src/con_pairs.py