VeztaVezta
Architecture

Trading Engine

SmartRouter, exchange adapters, custody models, and order state machine

The trading engine handles order submission, routing, execution, and lifecycle management. It routes orders to the correct exchange, manages state transitions, and supports advanced order types including TP/SL, sniper orders, and counter-trade automation.

Vezta integrates two exchanges with very different custody and signing models:

ExchangeCustodySignerSettlement chain
PolymarketPer-user Gnosis Safe (1-of-1) on PolygonBackend-derived EOA (encrypted)Polygon (USDC.e)
Kalshi (via DFlow)User's own Solana walletUser's wallet (Phantom/Solflare)Solana (USDC)

Order Submission Flow

SmartRouter

SmartRouterService selects the adapter based on the market's source. Before invoking an adapter, it:

  1. Computes a deterministic SHA-256 idempotency key (userId:marketId:side:amount:5minBucket) and skips if seen in Redis (5-min TTL)
  2. Checks the per-exchange circuit breaker (circuit-breaker:{exchange} Redis key, 5-min auto-reset TTL)
  3. Validates pending balance: subtracts totals of SUBMITTING / OPEN / PARTIALLY_FILLED orders before approving the new one
  4. For DFlow (Kalshi): the DFlow adapter checks the maintenance window (Thursdays 3-5 AM ET) and rejects with KALSHI_MAINTENANCE error during it

For markets that exist on both Polymarket and Kalshi, the router considers price and liquidity to find the best execution venue.

Exchange Adapters

Adapters live in src/modules/trading/adapters/ and implement a common interface.

Polymarket Adapter

  • Submits orders via the Polymarket CLOB API
  • CLOB API credentials are auto-derived from the user's wallet signature (no manual input needed)
  • The user's EOA signs the order; the Safe holds USDC.e and settles
  • Safe deployment + USDC approvals are gasless via the Builder Relayer
  • Supports market orders, limit orders, FAK, FOK, GTC, Post Only

DFlow Adapter

  • Submits orders via the DFlow Trade API proxied through the backend (/api/v1/dflow/*) due to CORS
  • Returns an unsigned VersionedTransaction (base64) for the frontend to sign with the user's Solana wallet
  • After the user signs and the frontend submits to Solana RPC, the backend polls GET /api/v1/dflow/order-status?signature={sig} until status = closed
  • Positions are SPL Token-2022 outcome tokens in the user's Solana wallet
  • Market orders only (limit orders not yet supported by DFlow)

Adapter Retry

Both adapters retry failed orders 3x with exponential backoff (100ms base). 4xx errors are not retried.

Order State Machine

OrderStateMachine enforces valid state transitions. The Prisma OrderStatus enum values used:

StateDescription
CREATEDOrder validated and saved
SUBMITTINGSubmitted to exchange, awaiting confirmation
OPENResting on the order book (limit only)
PARTIALLY_FILLEDSome quantity executed
FILLEDFully executed (terminal)
CANCELLING / CANCELLEDIn-progress / cancelled (terminal)
REJECTEDExchange rejected the order
FAILEDSubmission or execution failed (terminal)

The state machine maps its own internal string states to the Prisma enum. Once an order reaches a terminal state (FILLED, CANCELLED, REJECTED, FAILED), no further transitions are allowed.

Order Reconciliation

reconcileStaleOrders() runs periodically and catches orders stuck in SUBMITTING for >2 minutes:

  • If no external order ID exists, marks as FAILED
  • If an external order ID exists, logs the mismatch for manual review

Take-Profit and Stop-Loss (TP/SL)

Positions can have optional takeProfitPrice and stopLossPrice fields. The price-sync cycle monitors all open positions and submits market sell orders when the trigger condition fires:

  • Take-Profit: Sell when currentPrice >= takeProfitPrice (long YES) / <= takeProfitPrice (long NO)
  • Stop-Loss: Sell when currentPrice <= stopLossPrice (long YES) / >= stopLossPrice (long NO)

Sniper Orders

Sniper orders are price-triggered buy orders managed by SniperMonitorScheduler:

FieldTypeDescription
triggerPriceDecimal(10,6)Price threshold that triggers execution
amountDecimal(18,6)Order size in USD
slippageDecimal(5,4)Maximum acceptable slippage (default 2%)
statusSniperStatusWATCHING, EXECUTING, FILLED, EXPIRED, CANCELLED, INSUFFICIENT_BALANCE, FAILED
expiresAtDateTimeExpiration timestamp
repeatBooleanWhether to re-arm after filling

Counter-Trade Automation

CounterTradeConfig allows users to automatically trade inversely against a target wallet:

FieldTypeDescription
targetWalletAddressStringWallet to counter-trade against
strategyStringinverse (default) or mirror
sizeMultiplierDecimal(5,2)Multiplier applied to the target's trade size
executionDelaySecIntOptional delay before executing
maxTradeSizeDecimal?Per-trade size cap
dailyStopLossDecimal?Daily loss limit before pausing
categoriesString[]Market categories to counter-trade in

CounterTradeResetScheduler resets daily PnL and trade counts at midnight UTC.

Counter-trade only works on Polymarket (Kalshi-via-DFlow trades are anonymized at the on-chain layer).

Cross-Chain Withdrawals

Withdrawals from the Polygon Safe to other chains use LI.FI (li.quest/v1/quote):

  • Native chains (Polygon, Solana) -- direct via Safe relayer / Solana keypair
  • Other EVM chains (Ethereum, Arbitrum, Optimism, Base, Avalanche, BNB, Linea, zkSync, Scroll) -- single relayed Safe execution with [approve(USDC, lifiDiamond), call(lifiDiamond, bridgeData)]

Allowlist lives in WITHDRAW_CHAINS (vezta-be/src/modules/account/dto/withdraw.dto.ts); must stay in sync with USDC_ADDRESSES / LIFI_CHAIN_KEYS in lifi-bridge.service.ts and the frontend CHAINS array in withdraw-modal.tsx.

Bridge withdrawals always source from the Polygon Safe balance, not the destination chain's balance. Make sure the user has enough USDC.e in the Safe before initiating a withdrawal.

Order Fields Reference

Key fields on the Order model:

FieldTypeDescription
sideStringyes or no
typeStringmarket or limit
actionStringbuy or sell
priceDecimal(10,6)Order price
quantityDecimal(18,6)Requested quantity
filledQuantityDecimal(18,6)Quantity filled so far
avgFillPriceDecimal(10,6)?Average execution price
feeDecimal(18,6)Trading fee
exchangeStringpolymarket or dflow
sourceStringmanual, copy-trade, sniper, counter-trade
copyTradeSubIdString?Link to copy trade subscription if applicable

Combo Trades

Beyond single-market orders, Vezta supports combos — multi-leg (parlay-style) Polymarket CLOB orders where several outcomes are bundled into one position that pays out only if every leg resolves in the buyer's favour. This path is handled by the combo/ module rather than the SmartRouter:

  • Eligibility catalogComboCatalogController (/api/v1/combos) exposes which markets can be combined per game (ComboEligibleMarket); the catalog sync runs on the market domain.
  • PlacementComboController (/api/v1/combo) accepts a combo order asynchronously (returns 202 Accepted). Legs are EIP-712 signed (combo-signing.service.ts) and submitted through the Polymarket combo / RFQ gateway.
  • Persistence — a ComboOrder with its ComboLeg rows tracks status; updates are pushed on the user:combo-orders WebSocket channel.
  • Settlement — the combos worker domain (worker-combos) runs settlement reconciliation (combo-settle.processor.ts); an exit closes an open combo early via a SELL RFQ and redeem claims a settled winning combo.

See the Combos API for the full endpoint list.

On this page