AI trading terminal: instant off-chain trades via Yellow state channels
AI-powered DeFi trading assistant that combines instant off-chain execution (Yellow/Nitrolite state channels), cross-chain liquidity (LI.FI), and portable DeFi identity (ENS) into a unified conversational trading terminal.
Users connect their wallet and the app automatically resolves their ENS name and loads their trading preferences stored as ENS text records (slippage, risk level, favorite pairs, max trade size, take-profit/stop-loss targets). They can deposit funds from any blockchain via LI.FI cross-chain routing, then open a Yellow Network state channel session for instant, zero-gas trading.
The AI copilot accepts natural language commands like "Buy $50 of ETH" or "Show my portfolio" and executes trades instantly through off-chain state channel updates. The AI validates every trade against the user's ENS-stored risk profile before execution. When the session ends, final balances are settled on-chain through the Nitrolite protocol.
Key innovation: Trading preferences as portable on-chain identity. Your slippage tolerance, risk level, and trading targets are stored as ENS text records that any DeFi app can read. FlowDesk reads them automatically to personalize the AI copilot's behavior.
User FLOW DIAGRAM - https://github.com/kamalbuilds/flowdesk/blob/main/FLOW-DIAGRAM.md
Yellow Network / Nitrolite SDK (@erc7824/nitrolite)
This is the deepest technical integration. We built a full Nitrolite RPC client that implements:
Session Key Architecture: Uses generatePrivateKey() from viem to create an ephemeral session key for signing RPC messages. The user's main wallet only signs once during EIP-712 authentication after that, all trades are signed by the session key with zero wallet popups.
WebSocket Connection: Connects to the ClearNode sandbox at wss://clearnet-sandbox.yellow.com/ws with automatic reconnection and heartbeat ping/pong via createPingMessageV2().
Full Authentication Flow (3-step):
createAuthRequestMessage() sends wallet address, session key address, application name, scope, and expiryauth_challenge response, signs the EIP-712 typed data with createEIP712AuthMessageSigner() using the connected wallet client from wagmicreateAuthVerifyMessage() completes auth and receives JWT tokenSession Key Allowances: Auth request includes spending caps for ytest.usd and eth assets, enabling the session key to execute transfers without wallet popups. Uses createECDSAMessageSigner() from the SDK for proper ECDSA signing.
State Channel Operations:
createCreateChannelMessage() opens a state channel on Base Sepolia (chain 84532) with ytest.usd token (0xDB9F293e3898c9E5536A3be1b0C56c89d2b32DEb)createTransferMessage() executes instant off-chain trades via the unified balance layercreateGetLedgerBalancesMessage() checks off-chain unified balancecreateCloseChannelMessage() initiates on-chain settlement with funds destinationgenerateRequestId() and 15-second timeoutsFaucet Integration: On session open, automatically requests ytest.usd tokens from clearnet-sandbox.yellow.com/faucet/requestTokens to fund the unified balance.
Response Handling: Uses parseAnyRPCResponse() with typed RPCMethod switch handling for AuthChallenge, AuthVerify, CreateChannel, ResizeChannel, Transfer, CloseChannel, Error, BalanceUpdate, ChannelUpdate, TransferNotification, GetLedgerBalances, Pong, and more.
Verified E2E on ClearNode Sandbox: Full lifecycle tested faucet tokens received, authentication successful (JWT issued), channel created, transfer of 5 ytest.usd executed (txId: 35437), balance correctly debited from 30M to 29,999,995.
React Integration (app/src/hooks/useYellowSession.ts): Uses wagmi's useAccount() and useWalletClient() hooks to automatically pass the wallet client to the Yellow client for EIP-712 signing whenever the wallet connects.
Supported chains: Base Sepolia, Ethereum Sepolia, Polygon Amoy, Linea Sepolia (sandbox). Production: Ethereum, Base, Polygon, BNB Chain, Linea, Flare, Flow, Ronin.
Files: app/src/hooks/useCrossChainDeposit.ts + app/src/components/deposit/CrossChainDeposit.tsx
Uses the LI.FI REST API (li.quest/v1/quote) programmatically to enable deposits from any blockchain:
fromChain, toChain, fromToken, toToken, fromAmount, fromAddress and fetches optimal cross-chain routesThe AI copilot integrates with LI.FI deposits by suggesting deposits when session balance is low, completing the AI strategy loop: monitor -> decide -> execute.
Files: app/src/hooks/useENSProfile.ts + app/src/components/ens/ENSProfile.tsx + app/src/components/ens/ENSSettings.tsx
We created a custom ENS text record schema for portable DeFi trading preferences, deployed as a Basename (flowdesk.basetest.eth) on Base Sepolia:
com.flowdesk.slippage = "0.5" (tolerance %)
com.flowdesk.risk-level = "moderate" (conservative|moderate|aggressive)
com.flowdesk.favorite-pairs = "ETH/USDC,WBTC/USDC"
com.flowdesk.max-trade-size = "1000" (max single trade in USDC)
com.flowdesk.take-profit = "5" (auto target %)
com.flowdesk.stop-loss = "3" (auto target %)
com.flowdesk.preferred-chain = "84532" (default chain ID)
com.flowdesk.session-budget = "500" (default session funding)
Real on-chain registration: We registered flowdesk.basetest.eth via the Basenames RegistrarController (0x49aE3cC2e3AA768B1e5654f5D3C6002144A59581) on Base Sepolia, set the L2 Resolver (0x6533C94869D28fAA8dF77cc63f9e2b2D6Cf77eBA), set the address record, configured the reverse record via the ReverseRegistrar (0x876eF94ce0773052a2f81921E70FF25a5e76841f), and wrote all 8 com.flowdesk.* text records on-chain. Registration script: app/register-basename.mjs.
Direct L2 contract integration (no Universal Resolver): Since Basenames on Base Sepolia doesn't deploy a Universal Resolver, we built custom resolution by directly calling the Basenames contracts with wagmi's useReadContracts():
ReverseRegistrar.node(address) to compute the reverse node (Basenames uses a different node hash than standard ENS addr.reverse)L2Resolver.name(reverseNode) to get flowdesk.basetest.ethnamehash(name) and batch 8 L2Resolver.text(node, key) calls for all com.flowdesk.* preferencesAI integration: The AI system prompt (app/src/lib/ai/prompts.ts) includes the user's ENS preferences, so the copilot validates trades against max trade size, warns about risk levels, and suggests take-profit/stop-loss based on the user's on-chain settings.
Why it's creative: ENS text records become a portable DeFi identity layer. Deployed on Base via Basenames, the preferences live on the same chain as the trading session. Any DeFi protocol can read com.flowdesk.* keys to auto-configure a user's trading experience. The preferences travel with the user's Basename across all of DeFi.
Notable Technical Decisions that I made for this project
Dual AI system: OpenRouter API (Gemini 2.0 Flash) for natural language understanding + local regex-based trade parser as fallback. The app works fully offline with zero API dependencies.
Session key pattern: After one EIP-712 wallet signature, all subsequent trades are signed by the ephemeral session key. This eliminates wallet popup fatigue during active trading sessions.
Zero mocks: The entire system uses real infrastructure only real ClearNode WebSocket, real Pyth oracle prices, real LI.FI quotes. No mock fallbacks anywhere.
PnL tracking: Tracks initialDeposit at session open and calculates PnL = currentPortfolioValue - initialDeposit using real-time Pyth Hermes oracle prices (10s revalidation).

