Overview
Pokeliquid is the first on-chain perpetual futures DEX for Pokémon TCG products. Built on Solana using the Anchor framework, it lets traders go long or short on sealed products and single cards with up to 10x leverage. Prices are sourced from TCGPlayer market data via an automated Playwright scraper with adaptive EWMA smoothing.
Currently live on Solana Devnet with test USDC. No real money.
Current Markets
| Market | Card | Set | Card # | Live |
|---|---|---|---|---|
| PRISMATIC-ETB-PERP | Prismatic Evolutions ETB | Sealed Product | — | Yes |
| CHARIZARD-125/094-PFL-PERP | Mega Charizard X ex | Phantasmal Flames | 125/094 | Yes |
| CHARMANDER-038-MEP-PERP | Charmander | Mega Evolution Promo | #038 | Yes |
| PIKACHU-276/217-AH-PERP | Pikachu ex | Ascended Heroes | 276/217 | Yes |
Network
Solana Devnet. All addresses are devnet PDAs derived from the program.
Getting Started
1. Visit the app
Go to pokeliquid.xyz.
2. Create an account
Click “Start Trading” on the landing page. You can create an account with email and password, or continue as a guest with no account.
3. Session Wallet
No browser wallet extension (Phantom, Solflare) is required. Pokeliquid automatically generates a Solana keypair stored in your browser’s localStorage. This “session wallet” signs all transactions locally. If you create an account, your encrypted private key is stored server-side for email recovery (AES-256-GCM encryption).
4. Get Test USDC
Click “GET TEST USDC” in the trading interface. This calls the mint_devnet_usdc instruction which mints 1,000 test USDC to your wallet. This is devnet-only and requires no authorization.
5. Deposit Collateral
Click “DEPOSIT/WITHDRAW” and deposit USDC into your margin account. Your margin account is a PDA derived from your wallet address with the seed margin.
6. Open a Position
Select a market, choose Long or Short, set your collateral amount and leverage (1-10x), optionally set Stop Loss and Take Profit prices, then click to open your position.
7. Password Reset
If you forget your password, click “Forgot password?” on the login screen. Enter your email and you’ll receive a reset link via email. The link expires in 1 hour and is single-use.
Trading
Opening a Position
The open_position instruction accepts:
| Parameter | Type | Description |
|---|---|---|
| direction | Long | Short | Trade direction |
| collateral | u64 | USDC collateral amount (6 decimals, e.g. 10_000_000 = $10) |
| leverage | u8 | Leverage multiplier (1–10) |
| sl_price | Option<u64> | Optional stop-loss price (6 decimal scale) |
| tp_price | Option<u64> | Optional take-profit price (6 decimal scale) |
Notional value = collateral \u00D7 leverage. A 2% fee (200 bps) is deducted from collateral on open. The position is stored in your MarginAccount which supports up to 5 simultaneous positions.
Order Types
Currently only Market orders are supported on-chain. The frontend also shows Limit and Stop order UI, but these are executed as market orders when the price condition is met by the keeper.
Closing a Position
Call close_position with the position slot index (0\u20134). PnL is calculated as:
Long PnL = notional * (exit_price - entry_price) / entry_price Short PnL = notional * (entry_price - exit_price) / entry_price
A 2% close fee is deducted. Profit is capped at the profit cap (500%, or 50,000 bps). The settlement amount (collateral + PnL - fees) is transferred from/to the fee vault.
Stop Loss / Take Profit
Set SL/TP on any open position via set_sl_tp. The keeper monitors prices and calls execute_sl_tp permissionlessly when conditions are met. The executor receives a 0.1% reward (10 bps of position collateral) for executing the order.
Multiple Positions
Each MarginAccount supports up to 5 simultaneous positions across any market. Positions are stored in a fixed-size array. MarginAccount size = 546 bytes.
Fees & Costs
| Fee | Rate | Notes |
|---|---|---|
| Open Fee | 2% (200 bps) | Deducted from collateral when opening |
| Close Fee | 2% (200 bps) | Deducted from settlement when closing |
| Profit Cap | 500% (50,000 bps) | Max profit per position |
| Min Position Size | $1.00 (1,000,000 raw) | Minimum collateral |
Fee Distribution
Trading fees collected on open and close are distributed:
| Destination | Share | Description |
|---|---|---|
| LP Pool | 30% (3,000 bps) | Distributed to liquidity providers |
| Fee Vault | 60% | Protocol revenue |
| Insurance Fund | 10% (1,000 bps) | Bad debt coverage |
Funding Rate
Funding is settled hourly by the keeper via settle_funding (permissionless crank). The funding rate has two components:
Base Rate: 30 / 100,000 per hour = 0.03%/hr = 0.72%/day
Skew Rate: skew_factor * (long_OI - short_OI) / (long_OI + short_OI)
where skew_factor = 1,000 / 100,000 = 1%
Total Funding = base_rate + skew_rate (per hour)
Longs pay when long OI > short OI (and vice versa)Risk Management
Liquidation
A position is liquidatable when its margin ratio falls below 5% (500 bps).
Margin Ratio = (collateral + unrealized_PnL) / notional Liquidation Price (Long): entry_price * (1 - (collateral - notional * 0.05) / notional) Liquidation Price (Short): entry_price * (1 + (collateral - notional * 0.05) / notional)
Liquidation is permissionless — anyone can call liquidate. The keeper checks every 10 seconds and liquidates undercollateralized positions.
Liquidation Distribution
| Recipient | Share | Description |
|---|---|---|
| Liquidator | 1% (100 bps) | Reward for calling liquidate |
| Insurance Fund | 9% (900 bps) | Bad debt reserve |
| Fee Vault | 90% | Remaining collateral |
Add / Remove Margin
Use add_margin to move free collateral into a position (lowering liquidation price). Use remove_margin to withdraw margin back to free collateral (health-checked — cannot reduce margin ratio below the liquidation threshold).
Oracle
Price Source
Prices are scraped from TCGPlayer product pages using Playwright (headless Chromium). The keeper runs a browser instance, navigates to each product page, and extracts the current market price. All 4 live markets are scraped in parallel.
| Market | TCGPlayer Product ID | Oracle Address |
|---|---|---|
| PRISMATIC-ETB-PERP | 593355 | 4v5ogQ...jW12 |
| CHARIZARD-125/094-PFL-PERP | 662184 | 8UWP5Y...HAfg |
| CHARMANDER-038-MEP-PERP | 684462 | 6WQUKKr...a3XD |
| PIKACHU-276/217-AH-PERP | 676088 | B1BWNQ...QRYs |
Update Frequency
The oracle updates every 5 minutes (300,000ms). Each market has its own on-chain oracle account (PDA seeded with ["oracle", market_id]).
Adaptive EWMA Smoothing
Raw scraped prices are smoothed using an Adaptive Exponential Weighted Moving Average (EWMA) with 4 tiers based on price deviation from the current EWMA:
| Deviation | Alpha | Mode | Behavior |
|---|---|---|---|
| < 3% | 1.0 | Direct | Price passes through unchanged |
| 3–5% | 0.3 | Moderate | Moderate smoothing applied |
| 5–15% | 0.1 | Heavy | Heavy smoothing, slow convergence |
| > 15% | 0.01 | Spike | Near-total rejection, spike protection |
EWMA formula: new_ewma = alpha * raw_price + (1 - alpha) * prev_ewma Price floor protection: if candidate < floor, update is rejected entirely. ETB floor: $100 | Charizard-X floor: $200 Charmander floor: $1 | Pikachu floor: $10
Staleness Protection
On-chain, the oracle has a staleness threshold of 30 minutes (1,800 seconds). Anyone can call check_and_pause (permissionless) to automatically pause the protocol if the oracle is stale beyond the auto-pause threshold of 1 hour.
Secondary Authority
The oracle accepts updates from either the admin wallet or a secondary authority keypair. The keeper automatically fails over to the secondary keypair after 3 consecutive primary failures, and sends Telegram alerts when failover occurs.
Liquidity Pool
How It Works
Liquidity providers deposit USDC into the pool via lp_deposit and receive LP shares. Shares represent proportional ownership of the pool. The share price = total_usdc / total_shares.
Earning Fees
30% of all trading fees are directed to the LP pool. LPs can claim their proportional share of accumulated fees via claim_fees at any time.
Withdrawing
Call lp_withdraw with the number of shares to burn. USDC is returned proportionally. There is no lockup period — withdraw anytime.
Protocol
Program Details
| Property | Value |
|---|---|
| Program ID | 7DVf9oEMcKPV6VUUz5BpptbwqpgBfXunwxjTNNQmZvbJ |
| Network | Solana Devnet |
| Framework | Anchor 1.0.2 |
| Frontend | pokeliquid.xyz |
Deployed Addresses
All Instructions
| Instruction | Auth | Description |
|---|---|---|
| initialize | Admin | One-time protocol setup, creates all PDAs |
| initialize_pool | Admin | One-time LP pool setup |
| deposit_collateral | User | Deposit USDC into margin account |
| withdraw_collateral | User | Withdraw free collateral |
| close_margin_account | User | Close margin account, return rent |
| realloc_margin | User | Resize margin account (migration helper) |
| open_position | User | Open a leveraged perpetual position |
| close_position | User | Close a position, settle PnL |
| add_margin | User | Add collateral to an open position |
| remove_margin | User | Remove margin (health-checked) |
| set_sl_tp | User | Set stop-loss / take-profit prices |
| execute_sl_tp | Permissionless | Execute triggered SL/TP orders |
| liquidate | Permissionless | Liquidate undercollateralized position |
| settle_funding | Permissionless | Settle hourly funding on all positions |
| check_and_pause | Permissionless | Pause protocol if oracle stale > 1hr |
| lp_deposit | User | Deposit USDC into LP pool for shares |
| lp_withdraw | User | Burn shares to withdraw USDC |
| claim_fees | User | Claim accumulated LP fee share |
| update_oracle | Admin/Secondary | Push price to default oracle |
| init_market_oracle | Admin | Create a market-specific oracle PDA |
| init_market_state | Admin | Create per-market OI tracking state |
| update_market_oracle | Admin/Secondary | Push price to market oracle |
| update_params | Admin | Update protocol parameters |
| withdraw_fees | Admin | Withdraw from fee vault |
| withdraw_insurance | Admin | Withdraw from insurance fund |
| mint_devnet_usdc | Anyone | Mint 1,000 test USDC (devnet only) |
API Reference
The keeper exposes an HTTP API on port 3001. On the frontend, endpoints are proxied via Vercel rewrites at /api/keeper/*.
GET /ping
Health check. Returns {"ok":true,"timestamp":"..."}
GET /health
Comprehensive system health including oracle status, liquidation stats, funding stats, Solana RPC health, and per-market oracle data.
GET /prices
Historical price data for charting.
| Param | Type | Default | Description |
|---|---|---|---|
| market | string | ETB | Market ID (ETB, CHARIZARD-X, CHARMANDER, PIKACHU) |
| limit | number | 50 | Number of rows (max 500) |
| from | number | — | Unix timestamp range start |
| to | number | — | Unix timestamp range end |
Response: [
{ "id": 1, "timestamp": 1717401600, "raw_price": 161.5, "ewma": 161.6, "deviation": 0.001, "alpha": 1, "tx_signature": "..." },
...
]GET /candles
OHLC candle data aggregated from raw 5-minute price records. Used for charting.
| Param | Type | Default | Description |
|---|---|---|---|
| market | string | ETB | Market ID (ETB, CHARIZARD-X, CHARMANDER, PIKACHU) |
| resolution | string | 1h | Candle resolution: 1h (hourly) or 1d (daily) |
| limit | number | 100 | Max candles returned |
Response: [
{ "time": 1717401600, "open": 161.5, "high": 162.0, "low": 160.8, "close": 161.9 },
...
]GET /trades/recent
Recent trades across all users.
| Param | Type | Default | Description |
|---|---|---|---|
| limit | number | 50 | Number of trades (max 200) |
Response: {
"trades": [
{ "id": 1, "timestamp": ..., "user_pubkey": "...", "direction": "long", "notional": 100, "entry_price": 156.19, ... },
...
]
}GET /trades
Trades for a specific user. Requires user parameter.
GET /stats
Protocol statistics (24h/7d volume, trades, liquidations, fees, unique traders).
FAQ
Roadmap
- Devnet deployment
- 4 live markets (ETB, Charizard X, Charmander, Pikachu)
- 10x max leverage
- Session wallet — no extension needed
- LP pool with 30% fee share
- Adaptive EWMA oracle with spike protection
- Automated keeper (liquidations, funding, SL/TP)
- Email/password auth with password reset
- OHLC charts (1H / 1D candles)
- Mobile-responsive UI
- Custom domain (pokeliquid.xyz)
- Telegram monitoring & alerts
- Mainnet launch
- 25x max leverage
- Additional card markets
- Mobile-optimized UI
- 50x max leverage
- Vintage card oracle committee
- Governance token
- 100x max leverage
- BASE-SET-CHARIZARD-PERP
- $POKE governance live