|
| 1 | +# Percolator — Permissionless Perpetual Futures |
| 2 | + |
| 3 | +> ⚠️ **Work in progress.** The Percolator perps engine is not yet production-ready and currently runs on **Solana devnet** only. Mainnet support is planned. Use at your own risk. |
| 4 | +
|
| 5 | +Create and operate your own on-chain perpetual futures exchange on Solana. The `PercolatorAdapter` is a standalone class (not `IDexAdapter` — perps are fundamentally different from spot). |
| 6 | + |
| 7 | +## Why This Matters |
| 8 | + |
| 9 | +First mover creates the perp market for a trending token and captures ALL leveraged volume fees. Nobody else has done AI-operated perp exchanges yet. This is the Percolator alpha. |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +## CLI |
| 14 | + |
| 15 | +All prices in USD, all amounts in SOL. Requires `DEVNET_ENDPOINT` env var. |
| 16 | + |
| 17 | +### perp create-market |
| 18 | + |
| 19 | +Create a new perp market. You become the admin/oracle authority. |
| 20 | + |
| 21 | +```bash |
| 22 | +outsmart perp create-market --price 150 --lp 2 |
| 23 | +outsmart perp create-market --price 0.00001 --lp 5 --tier medium --network mainnet |
| 24 | +``` |
| 25 | + |
| 26 | +| Flag | Description | Default | |
| 27 | +|------|-------------|---------| |
| 28 | +| `--price <usd>` | Initial oracle price in USD (required) | | |
| 29 | +| `--lp <sol>` | Initial LP collateral in SOL (required) | | |
| 30 | +| `--tier <size>` | `small` \| `medium` \| `large` | `small` | |
| 31 | +| `--network <net>` | `devnet` \| `mainnet` | `devnet` | |
| 32 | + |
| 33 | +### perp long / short |
| 34 | + |
| 35 | +Open a leveraged position. |
| 36 | + |
| 37 | +```bash |
| 38 | +outsmart perp long -m <MARKET> -s 0.1 |
| 39 | +outsmart perp short -m <MARKET> -s 0.05 |
| 40 | +``` |
| 41 | + |
| 42 | +| Flag | Description | |
| 43 | +|------|-------------| |
| 44 | +| `-m, --market <address>` | Market (slab) address (required) | |
| 45 | +| `-s, --size <sol>` | Position size in SOL (required) | |
| 46 | + |
| 47 | +### perp close |
| 48 | + |
| 49 | +Close your open position. |
| 50 | + |
| 51 | +```bash |
| 52 | +outsmart perp close -m <MARKET> |
| 53 | +``` |
| 54 | + |
| 55 | +### perp status |
| 56 | + |
| 57 | +View your position and market state. |
| 58 | + |
| 59 | +```bash |
| 60 | +outsmart perp status -m <MARKET> |
| 61 | +``` |
| 62 | + |
| 63 | +### perp deposit / withdraw |
| 64 | + |
| 65 | +Manage collateral in your trading account. |
| 66 | + |
| 67 | +```bash |
| 68 | +outsmart perp deposit -m <MARKET> -a 1.0 |
| 69 | +outsmart perp withdraw -m <MARKET> -a 0.5 |
| 70 | +outsmart perp withdraw -m <MARKET> -a all |
| 71 | +``` |
| 72 | + |
| 73 | +### perp init-user |
| 74 | + |
| 75 | +Register a trading account on a market (required before first deposit/trade). |
| 76 | + |
| 77 | +```bash |
| 78 | +outsmart perp init-user -m <MARKET> |
| 79 | +``` |
| 80 | + |
| 81 | +### perp set-price |
| 82 | + |
| 83 | +Push a new oracle price (admin-oracle markets only). |
| 84 | + |
| 85 | +```bash |
| 86 | +outsmart perp set-price -m <MARKET> --price 155.50 |
| 87 | +``` |
| 88 | + |
| 89 | +### perp crank |
| 90 | + |
| 91 | +Run the permissionless keeper crank (updates funding rates). |
| 92 | + |
| 93 | +```bash |
| 94 | +outsmart perp crank -m <MARKET> |
| 95 | +``` |
| 96 | + |
| 97 | +### perp keeper |
| 98 | + |
| 99 | +Start the WebSocket oracle keeper — watches DEX pool accounts in real-time and pushes prices to your market. |
| 100 | + |
| 101 | +```bash |
| 102 | +# Single pool |
| 103 | +outsmart perp keeper --pool <POOL> --market <MARKET> --dex raydium-cpmm |
| 104 | + |
| 105 | +# Multi-pool config |
| 106 | +outsmart perp keeper --config ~/.outsmart/keeper.json |
| 107 | +``` |
| 108 | + |
| 109 | +| Flag | Description | |
| 110 | +|------|-------------| |
| 111 | +| `-p, --pool <address>` | DEX pool address | |
| 112 | +| `-m, --market <address>` | Percolator market address | |
| 113 | +| `-d, --dex <type>` | DEX type (see supported list below) | |
| 114 | +| `-c, --config <path>` | JSON config for multi-pool mode | |
| 115 | +| `-n, --network <net>` | `devnet` \| `mainnet` (default: devnet) | |
| 116 | + |
| 117 | +Supported DEX types: `raydium-cpmm`, `raydium-amm-v4`, `raydium-clmm`, `raydium-launchlab`, `pumpswap`, `meteora-damm-v2`, `meteora-dbc`, `meteora-dlmm` |
| 118 | + |
| 119 | +Config format (`keeper.json`): |
| 120 | +```json |
| 121 | +[ |
| 122 | + { "pool": "<POOL>", "market": "<SLAB>", "dex": "raydium-cpmm", "network": "devnet" } |
| 123 | +] |
| 124 | +``` |
| 125 | + |
| 126 | +### perp grpc-keeper |
| 127 | + |
| 128 | +Same as `perp keeper` but uses Yellowstone gRPC (Geyser) instead of WebSocket. More reliable for production — handles reconnects and works with dedicated gRPC endpoints. |
| 129 | + |
| 130 | +```bash |
| 131 | +outsmart perp grpc-keeper --pool <POOL> --market <MARKET> --dex pumpswap |
| 132 | +``` |
| 133 | + |
| 134 | +Requires `GRPC_URL` and `GRPC_XTOKEN` env vars. |
| 135 | + |
| 136 | +### perp markets |
| 137 | + |
| 138 | +Discover all markets on-chain. |
| 139 | + |
| 140 | +```bash |
| 141 | +outsmart perp markets |
| 142 | +outsmart perp markets --network mainnet |
| 143 | +``` |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## Programmatic API |
| 148 | + |
| 149 | +```typescript |
| 150 | +import { PercolatorAdapter } from "outsmart"; |
| 151 | + |
| 152 | +const percolator = new PercolatorAdapter(); |
| 153 | + |
| 154 | +// 1. Create a perp market (devnet, BONK collateral, $1 initial price) |
| 155 | +const market = await percolator.createMarket({ |
| 156 | + collateralMint: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", // BONK |
| 157 | + initialPriceE6: 1_000_000n, // $1.00 |
| 158 | + tier: "small", |
| 159 | + network: "devnet", |
| 160 | + lpCollateral: 1_000_000_000n, // 1B BONK for LP |
| 161 | +}); |
| 162 | +console.log("Market:", market.slabAddress); |
| 163 | + |
| 164 | +// 2. Register a trader |
| 165 | +const { userIdx } = await percolator.initUser(market.slabAddress, "devnet"); |
| 166 | + |
| 167 | +// 3. Deposit collateral |
| 168 | +await percolator.deposit(market.slabAddress, userIdx, 500_000_000n, "devnet"); |
| 169 | + |
| 170 | +// 4. Open a long position (positive size = long, negative = short) |
| 171 | +await percolator.trade({ |
| 172 | + slabAddress: market.slabAddress, |
| 173 | + userIdx, |
| 174 | + lpIdx: market.lpIndex, |
| 175 | + size: 100_000_000n, // long 100M units |
| 176 | + network: "devnet", |
| 177 | +}); |
| 178 | + |
| 179 | +// 5. Push oracle price (admin-oracle mode) |
| 180 | +await percolator.pushOraclePrice(market.slabAddress, 1_100_000n, "devnet"); // $1.10 |
| 181 | + |
| 182 | +// 6. Read market state |
| 183 | +const state = await percolator.getMarketState(market.slabAddress, "devnet"); |
| 184 | +console.log("Open interest:", state.engine.openInterestLong); |
| 185 | + |
| 186 | +// 7. Check your position |
| 187 | +const pos = await percolator.getMyPosition(market.slabAddress, "devnet"); |
| 188 | +console.log("PnL:", pos?.account.unrealizedPnl); |
| 189 | +``` |
| 190 | + |
| 191 | +## PercolatorAdapter Methods (20) |
| 192 | + |
| 193 | +| Method | Description | |
| 194 | +|--------|-------------| |
| 195 | +| `createMarket(params)` | Full 10-step market creation (slab → init → oracle → crank → vAMM → LP) | |
| 196 | +| `initUser(slab, network?, tier?)` | Register a trader account, returns assigned index | |
| 197 | +| `deposit(slab, idx, amount, network?, tier?)` | Deposit collateral | |
| 198 | +| `withdraw(slab, idx, amount, network?, tier?)` | Withdraw collateral | |
| 199 | +| `trade(params)` | Open/close/modify positions via TradeCpi | |
| 200 | +| `closeAccount(slab, idx, network?, tier?)` | Close account and recover rent | |
| 201 | +| `crank(slab, network?, tier?)` | Permissionless keeper crank | |
| 202 | +| `pushOraclePrice(slab, priceE6, network?, tier?)` | Update oracle price (admin only) | |
| 203 | +| `liquidate(slab, targetIdx, network?, tier?)` | Permissionless liquidation | |
| 204 | +| `createInsuranceMint(slab, network?, tier?)` | One-time insurance LP mint creation | |
| 205 | +| `depositInsuranceLP(slab, amount, network?, tier?)` | Deposit into insurance fund | |
| 206 | +| `withdrawInsuranceLP(slab, lpAmount, network?, tier?)` | Withdraw from insurance fund | |
| 207 | +| `getMarketState(slab, network?)` | Read full slab state (header, config, engine, params, accounts) | |
| 208 | +| `getMyPosition(slab, network?)` | Find user's account by owner pubkey | |
| 209 | +| `discoverMarkets(network?)` | Find all markets across all program tiers | |
| 210 | +| `adminForceClose(slab, targetIdx, network?, tier?)` | Admin force-close a position | |
| 211 | +| `resolveMarket(slab, network?, tier?)` | Resolve/freeze market (admin only) | |
| 212 | +| `withdrawInsurance(slab, network?, tier?)` | Withdraw insurance fund balance | |
| 213 | +| `closeSlab(slab, network?, tier?)` | Close slab account and recover rent | |
| 214 | +| `teardownMarket(slab, network?, tier?)` | Full teardown: resolve → force-close all → withdraw → close | |
| 215 | + |
| 216 | +## Math Utilities |
| 217 | + |
| 218 | +Exported for PnL calculation, risk analysis, and pre-trade simulation: |
| 219 | + |
| 220 | +```typescript |
| 221 | +import { |
| 222 | + computeMarkPnl, |
| 223 | + computeLiqPrice, |
| 224 | + computePreTradeLiqPrice, |
| 225 | + computeTradingFee, |
| 226 | + computePnlPercent, |
| 227 | + computeEstimatedEntryPrice, |
| 228 | + computeFundingRateAnnualized, |
| 229 | + computeRequiredMargin, |
| 230 | + computeMaxLeverage, |
| 231 | + computeVammQuote, |
| 232 | +} from "outsmart"; |
| 233 | +``` |
| 234 | + |
| 235 | +## Deployed Programs |
| 236 | + |
| 237 | +| Tier | Devnet | Mainnet | |
| 238 | +|------|--------|---------| |
| 239 | +| Small | `FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD` | `GM8zjJ8LTBMv9xEsverh6H6wLyevgMHEJXcEzyY3rY24` | |
| 240 | +| Medium | `FwfBKZXbYr4vTK23bMFkbgKq3npJ3MSDxEaKmq9Aj4Qn` | — | |
| 241 | +| Large | `g9msRSV3sJmmE3r5Twn9HuBsxzuuRGTjKCVTKudm9in` | — | |
| 242 | +| Matcher | `4HcGCsyjAqnFua5ccuXyt8KRRQzKFbGTJkVChpS7Yfzy` | `DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX` | |
| 243 | + |
| 244 | +## Testing |
| 245 | + |
| 246 | +```bash |
| 247 | +npm run test:percolator # Percolator perps (devnet — requires DEVNET_ENDPOINT) |
| 248 | +``` |
| 249 | + |
| 250 | +## Environment Variables |
| 251 | + |
| 252 | +| Variable | Description | |
| 253 | +|----------|-------------| |
| 254 | +| `DEVNET_ENDPOINT` | Solana devnet RPC endpoint (required for all perp commands) | |
| 255 | +| `GRPC_URL` | Yellowstone gRPC endpoint (for `perp grpc-keeper`) | |
| 256 | +| `GRPC_XTOKEN` | Yellowstone gRPC auth token | |
0 commit comments