diff --git a/lazer/cardano/lazer-perps/README.md b/lazer/cardano/lazer-perps/README.md new file mode 100644 index 00000000..5a470d70 --- /dev/null +++ b/lazer/cardano/lazer-perps/README.md @@ -0,0 +1,223 @@ +# Team Lazer Perps (ex Lazer RWA) — Pythathon Submission + +## Details + +Team Name: Lazer Perps +Submission Name: lazer-perps +Team Members: María Elisa Araya ([@ar3lisa](https://x.com/ar3lisa)), Bárbara Olivera ([@b4rbbb](https://x.com/b4rbbb)) +Contact: araya3lisa@gmail.com / brb.olivera@gmail.com + +> Direct extension of our [Lazer RWA](../lazer-rwa/) submission — same oracle integration, expanded into a perpetual futures protocol. + +## Project Description + +Perpetual futures protocol on Cardano. Traders open leveraged long/short positions on RWA assets using USDCx as collateral. Every action (open, close, liquidate) requires a fresh Pyth Lazer price witness in the transaction. No price → no trade. + +All positions are independent eUTxOs. Each market is deployed with parameterized validators — no recompilation needed. + +### How Pyth is used + +`oracle_gate.ak` calls `pyth.get_updates(pyth_id, self)` from `pyth-network/pyth-lazer-cardano`. Every validator reads prices through this gate. Off-chain, `orchestrator.ts` fetches signed updates from Pyth Lazer and embeds them via the zero-withdrawal pattern. + +### Markets + +| Symbol | Asset | Feed ID | Max Leverage | Status | +|--------|-------|---------|--------------|--------| +| XAU/USD | Gold | 346 | 10x | stable | +| XAG/USD | Silver | 345 | 10x | stable | +| XAUT/USD | Tether Gold | 172 | 10x | stable (24/7) | +| XTI/USD | Oil (WTI) | 2950 | 5x | coming soon | + +### Formulas (on-chain in `formulas.ak`) + +**PnL:** +``` +PnL = direction_multiplier × collateral × leverage × (exit_price - entry_price) / entry_price + direction_multiplier: +1 Long, -1 Short +``` + +**Payout:** +``` +Payout = max(0, collateral + PnL) +``` + +**Liquidation price:** +``` +Long: liq_price = entry_price × (1 - 1/leverage + 0.01) +Short: liq_price = entry_price × (1 + 1/leverage - 0.01) +``` + +**Liquidation trigger:** +``` +Long: current_price ≤ liq_price → liquidatable +Short: current_price ≥ liq_price → liquidatable +``` + +### Validators + +| Validator | Purpose | Pyth Usage | +|-----------|---------|------------| +| `oracle_gate.ak` | Reads verified Pyth price | `pyth.get_updates()` | +| `open_position.ak` | Entry price + leverage + min collateral | Entry price must match oracle | +| `close_position.ak` | PnL settlement + owner signature | Exit price from oracle | +| `liquidate.ak` | Liquidation price check — anyone can trigger | Current price vs liq_price | +| `pool_manager.ak` | USDCx liquidity pool + open interest caps | — | + +## Architecture + +``` +Pyth Lazer Server Cardano PreProd + │ │ + │ "latest price for XAU/USD" │ + ▼ │ + [Ed25519-signed price bytes] │ + │ │ + │ orchestrator.ts │ + │ ┌─────────┴───────────┐ │ + │ │ fetchPriceWitness() │ │ + │ │ • fetch price │ │ + │ │ • resolve state ────┼──query──▶ │ Pyth State UTxO + │ │ • zero-withdrawal │ │ + │ └─────────┬───────────┘ │ + │ │ │ + │ open / close / liquidate ──tx────▶ │ + │ ▼ + │ ┌──────────────────────────┐ + │ │ Pyth Withdraw Script │ + │ │ (verifies Ed25519) │ + │ └────────────┬─────────────┘ + │ │ + │ ┌────────────▼─────────────┐ + │ │ oracle_gate.ak │ + │ │ pyth.get_updates() │ + │ └────────────┬─────────────┘ + │ │ + │ ┌──────────────┬────┴────┬──────────────┐ + │ ▼ ▼ ▼ ▼ + │ open_position close_position liquidate pool_manager + └────────────────────────────────────────────────────────────┘ +``` + +### Verified transactions on PreProd + +| Type | Feed | Tx Hash | +|------|------|---------| +| Open position | XAUT/USD | [`ccb967d2...`](https://preprod.cardanoscan.io/transaction/ccb967d2c1692a06fd293553ddce4d494718eebf81c25e647556b6e6fd343bb9) | +| Close position | XAUT/USD | [`6532eebc...`](https://preprod.cardanoscan.io/transaction/6532eebc942166b562baf58c535284b6fffa56d794c434421f141842e5b29d47) | +| Liquidate | XAUT/USD | [`477bfe3f...`](https://preprod.cardanoscan.io/transaction/477bfe3ffb991f745b6ce50c38564e099af415fc5e3b2177358d0d03dfdce4dd) | + +## How to run + +### Prerequisites + +- Node.js v24+ +- [Aiken](https://aiken-lang.org) v1.1+ +- Pyth Lazer access token +- Cardano PreProd wallet with tADA + +### Setup + +```bash +cd lazer/cardano/lazer-perps +npm install +cd onchain && aiken build && cd .. +``` + +### Aiken commands + +```bash +cd onchain + +# Compile all validators → generates plutus.json +aiken build + +# Run all 12 unit tests (PnL, payout, liquidation price, triggers) +aiken check + +# Check a specific test +aiken check -m "pnl_long_profit" + +# Generate project documentation +aiken docs + +# Clean build artifacts +rm -rf build plutus.json +``` + +### Commands + +```bash +# Open a position +ACCESS_TOKEN= CARDANO_MNEMONIC="<24 words>" FEED=XAUT/USD DIRECTION=long LEVERAGE=5 npm run open-position + +# Close a position +ACCESS_TOKEN= CARDANO_MNEMONIC="<24 words>" FEED=XAUT/USD npm run close-position + +# Liquidate +ACCESS_TOKEN= CARDANO_MNEMONIC="<24 words>" FEED=XAUT/USD npm run liquidate + +# Keeper bot (monitors prices for liquidations) +ACCESS_TOKEN= npm run keeper +``` + +## Roadmap + +### Stage 1 — MVP (current) +- [x] Oracle gate with `pyth.get_updates()` on-chain +- [x] Open/close/liquidate validators with Pyth price witness +- [x] Pool manager with open interest caps +- [x] PnL and liquidation price formulas on-chain +- [x] Off-chain orchestrator with tx builders +- [x] Keeper bot with WebSocket price monitoring +- [x] USDCx collateral support (ADA on PreProd) +- [x] Verified transactions on PreProd (open, close, liquidate) +- [x] XAU/USD as primary market + +### Stage 2 — Multi-market +- [ ] Deploy XAG/USD and XTI/USD markets +- [ ] Per-market leverage caps enforced on-chain +- [ ] Pool manager tracks OI per market +- [ ] Keeper auto-submits liquidation txs + +### Stage 3 — Production +- [ ] Real USDCx collateral on mainnet (policy: `1f3aec8bfe7ea4fe14c5f121e2a92e301afe414147860d557cac7e34`) +- [ ] Reference scripts for reduced tx fees +- [ ] Funding rate mechanism +- [ ] Frontend UI + +## Limitations (Stage 1 MVP) + +- Only one market live: XAU/USD 10x +- No funding rate — positions don't accrue fees over time +- No frontend — CLI scripts only +- Only USDCx collateral (ADA stand-in on PreProd) +- Deployed on PreProd testnet only — not mainnet + +## Project structure + +``` +lazer-perps/ +├── README.md +├── package.json +├── tsconfig.json +├── src/ +│ ├── feeds.ts — Market catalog (symbol, feed ID, leverage cap) +│ ├── collateral.ts — USDCx token config (policy ID + asset name) +│ ├── orchestrator.ts — Central Pyth Lazer module + tx builders +│ ├── open_position.ts — Open leveraged position +│ ├── close_position.ts — Close position + PnL settlement +│ ├── liquidate.ts — Liquidate undercollateralized position +│ └── keeper.ts — WebSocket price monitor + liquidation detection +└── onchain/ + ├── aiken.toml + ├── plutus.json — Compiled Plutus V3 blueprint + ├── lib/lazer_perps/ + │ ├── types.ak — PositionDatum, MarketConfig, CollateralToken + │ ├── oracle_gate.ak — pyth.get_updates() price reader + │ └── formulas.ak — PnL, payout, liquidation price + └── validators/ + ├── open_position.ak — Entry price + leverage + collateral check + ├── close_position.ak — PnL settlement with owner signature + ├── liquidate.ak — Liquidation price trigger (anyone can call) + └── pool_manager.ak — USDCx liquidity pool + OI management +``` diff --git a/lazer/cardano/lazer-perps/onchain/.gitignore b/lazer/cardano/lazer-perps/onchain/.gitignore new file mode 100644 index 00000000..567609b1 --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/lazer/cardano/lazer-perps/onchain/aiken.lock b/lazer/cardano/lazer-perps/onchain/aiken.lock new file mode 100644 index 00000000..1ab32acf --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/aiken.lock @@ -0,0 +1,27 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +[[requirements]] +name = "aiken-lang/stdlib" +version = "v3.0.0" +source = "github" + +[[requirements]] +name = "pyth-network/pyth-lazer-cardano" +version = "main" +source = "github" + +[[packages]] +name = "aiken-lang/stdlib" +version = "v3.0.0" +requirements = [] +source = "github" + +[[packages]] +name = "pyth-network/pyth-lazer-cardano" +version = "main" +requirements = [] +source = "github" + +[etags] +"pyth-network/pyth-lazer-cardano@main" = [{ secs_since_epoch = 1774220844, nanos_since_epoch = 251098000 }, "a46dacd97a22eb07feeaf966d48c3116c8249ddc836705656e3135cea285bcfc"] diff --git a/lazer/cardano/lazer-perps/onchain/aiken.toml b/lazer/cardano/lazer-perps/onchain/aiken.toml new file mode 100644 index 00000000..d63747f1 --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/aiken.toml @@ -0,0 +1,23 @@ +name = "team/lazer-perps" +version = "0.0.0" +compiler = "v1.1.21" +plutus = "v3" +license = "Apache-2.0" +description = "Perpetual futures protocol powered by Pyth Lazer price feeds on Cardano" + +[repository] +user = "team" +project = "lazer-perps" +platform = "github" + +[[dependencies]] +name = "aiken-lang/stdlib" +version = "v3.0.0" +source = "github" + +[[dependencies]] +name = "pyth-network/pyth-lazer-cardano" +version = "main" +source = "github" + +[config] diff --git a/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/formulas.ak b/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/formulas.ak new file mode 100644 index 00000000..8276031c --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/formulas.ak @@ -0,0 +1,173 @@ +use aiken/math/rational.{Rational} +use lazer_perps/types.{Direction, Long, Short} + +/// PnL = direction_multiplier × collateral × leverage × (exit_price - entry_price) / entry_price +/// +/// direction_multiplier: +1 for Long, -1 for Short +/// +/// Example (Long 5x, entry $3000, exit $3100, collateral 100): +/// PnL = +1 × 100 × 5 × (3100 - 3000) / 3000 = 16.67 +pub fn compute_pnl( + direction: Direction, + collateral: Int, + leverage: Int, + entry_price: Int, + exit_price: Int, +) -> Rational { + // direction_multiplier × (exit_price - entry_price) + let price_diff = when direction is { + Long -> exit_price - entry_price + Short -> entry_price - exit_price + } + // collateral × leverage × price_diff / entry_price + expect Some(pnl) = + rational.new(collateral * leverage * price_diff, entry_price) + pnl +} + +/// Payout = max(0, collateral + PnL) +/// +/// Trader never owes more than their collateral. +pub fn compute_payout(collateral: Int, pnl: Rational) -> Rational { + let total = rational.add(rational.from_int(collateral), pnl) + let zero = rational.from_int(0) + if rational.compare(total, zero) == Less { + zero + } else { + total + } +} + +/// Liquidation price for Long positions: +/// liq_price = entry_price × (1 - 1/leverage + 0.01) +/// +/// Simplified to integer math (all prices have 6 decimals): +/// liq_price = entry_price × (leverage - 1 + 0.01 × leverage) / leverage +/// liq_price = entry_price × (100 × leverage - 100 + leverage) / (100 × leverage) +/// liq_price = entry_price × (101 × leverage - 100) / (100 × leverage) +pub fn liquidation_price_long( + entry_price: Int, + leverage: Int, +) -> Rational { + // entry_price × (101 * leverage - 100) / (100 * leverage) + expect Some(liq) = + rational.new(entry_price * (101 * leverage - 100), 100 * leverage) + liq +} + +/// Liquidation price for Short positions: +/// liq_price = entry_price × (1 + 1/leverage - 0.01) +/// +/// Simplified: +/// liq_price = entry_price × (99 × leverage + 100) / (100 × leverage) +pub fn liquidation_price_short( + entry_price: Int, + leverage: Int, +) -> Rational { + // entry_price × (99 * leverage + 100) / (100 * leverage) + expect Some(liq) = + rational.new(entry_price * (99 * leverage + 100), 100 * leverage) + liq +} + +/// Check if a position should be liquidated based on current price. +/// Long: liquidate if current_price <= liq_price +/// Short: liquidate if current_price >= liq_price +pub fn is_liquidatable( + direction: Direction, + entry_price: Int, + leverage: Int, + current_price: Int, +) -> Bool { + let current_r = rational.from_int(current_price) + when direction is { + Long -> { + let liq = liquidation_price_long(entry_price, leverage) + // current_price <= liq_price + rational.compare(current_r, liq) != Greater + } + Short -> { + let liq = liquidation_price_short(entry_price, leverage) + // current_price >= liq_price + rational.compare(current_r, liq) != Less + } + } +} + +// ─── Tests ─────────────────────────────────────────────────────────── + +// PnL: Long 5x, entry 3000, exit 3100, collateral 100 +// PnL = 100 * 5 * (3100 - 3000) / 3000 = 500 * 100 / 3000 = 16.67 +test pnl_long_profit() { + let pnl = compute_pnl(Long, 100, 5, 3000, 3100) + rational.round(pnl) == 17 +} + +// PnL: Long 5x, entry 3000, exit 2900, collateral 100 +// PnL = 100 * 5 * (2900 - 3000) / 3000 = -16.67 +test pnl_long_loss() { + let pnl = compute_pnl(Long, 100, 5, 3000, 2900) + rational.round(pnl) == -17 +} + +// PnL: Short 5x, entry 3000, exit 2900, collateral 100 +// PnL = 100 * 5 * (3000 - 2900) / 3000 = 16.67 +test pnl_short_profit() { + let pnl = compute_pnl(Short, 100, 5, 3000, 2900) + rational.round(pnl) == 17 +} + +// PnL: Short 5x, entry 3000, exit 3100, collateral 100 +// PnL = 100 * 5 * (3000 - 3100) / 3000 = -16.67 +test pnl_short_loss() { + let pnl = compute_pnl(Short, 100, 5, 3000, 3100) + rational.round(pnl) == -17 +} + +// Payout: collateral 100 + PnL 50 = 150 +test payout_positive() { + let pnl = rational.from_int(50) + let payout = compute_payout(100, pnl) + rational.round(payout) == 150 +} + +// Payout floor: collateral 100 + PnL -200 → max(0, -100) = 0 +test payout_zero_floor() { + let pnl = rational.from_int(-200) + let payout = compute_payout(100, pnl) + rational.round(payout) == 0 +} + +// Liq price Long 10x, entry 3000: +// liq = 3000 * (101*10 - 100) / (100*10) = 3000 * 910 / 1000 = 2730 +test liq_price_long_10x() { + let liq = liquidation_price_long(3000, 10) + rational.round(liq) == 2730 +} + +// Liq price Short 10x, entry 3000: +// liq = 3000 * (99*10 + 100) / (100*10) = 3000 * 1090 / 1000 = 3270 +test liq_price_short_10x() { + let liq = liquidation_price_short(3000, 10) + rational.round(liq) == 3270 +} + +// Long at 2700 (below liq 2730) → liquidatable +test liquidatable_long_yes() { + is_liquidatable(Long, 3000, 10, 2700) == True +} + +// Long at 2800 (above liq 2730) → safe +test liquidatable_long_no() { + is_liquidatable(Long, 3000, 10, 2800) == False +} + +// Short at 3300 (above liq 3270) → liquidatable +test liquidatable_short_yes() { + is_liquidatable(Short, 3000, 10, 3300) == True +} + +// Short at 3200 (below liq 3270) → safe +test liquidatable_short_no() { + is_liquidatable(Short, 3000, 10, 3200) == False +} diff --git a/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/oracle_gate.ak b/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/oracle_gate.ak new file mode 100644 index 00000000..1668d19e --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/oracle_gate.ak @@ -0,0 +1,39 @@ +use aiken/collection/list +use aiken/math/rational +use cardano/assets.{PolicyId} +use cardano/transaction.{Transaction} +use pyth +use types/u32 + +/// Read the raw price and exponent for a feed from the Pyth update. +/// This is the oracle gate — every perps action must go through here. +/// Without a valid Pyth price witness in the tx, this function fails. +pub fn read_price( + pyth_id: PolicyId, + feed_id: Int, + self: Transaction, +) -> (Int, Int) { + // Verify and extract price data from the Pyth withdrawal redeemer + let updates = pyth.get_updates(pyth_id, self) + // Expect exactly one signed update in this transaction + expect [update] = updates + + expect Some(feed) = + list.find(update.feeds, fn(f) { u32.as_int(f.feed_id) == feed_id }) + + expect Some(Some(price)) = feed.price + expect Some(exponent) = feed.exponent + + (price, exponent) +} + +/// Read price and apply exponent to get a Rational value. +pub fn read_real_price( + pyth_id: PolicyId, + feed_id: Int, + self: Transaction, +) -> rational.Rational { + let (price, exponent) = read_price(pyth_id, feed_id, self) + expect Some(multiplier) = rational.from_int(10) |> rational.pow(exponent) + rational.from_int(price) |> rational.mul(multiplier) +} diff --git a/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/types.ak b/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/types.ak new file mode 100644 index 00000000..96691b9c --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/lib/lazer_perps/types.ak @@ -0,0 +1,69 @@ +use cardano/assets.{PolicyId, AssetName} + +/// Direction of a perpetual position +pub type Direction { + Long + Short +} + +/// USDCx collateral token identification. +/// On Cardano, native tokens are identified by policy ID + asset name. +pub type CollateralToken { + /// Policy ID of the USDCx token (empty for ADA-as-collateral on testnet) + policy_id: PolicyId, + /// Asset name of the USDCx token + asset_name: AssetName, +} + +/// Per-market configuration — applied as parameter at deployment. +/// Deploy once per market: XAU 10x, XAG 10x, XTI 5x, etc. +pub type MarketConfig { + /// Pyth deployment policy ID on Cardano + pyth_id: PolicyId, + /// Pyth Lazer feed ID for this market (e.g. 346 = XAU/USD) + feed_id: Int, + /// Maximum leverage for this market (e.g. 10 = 10x) + leverage_cap: Int, + /// Minimum collateral in micro USDCx to open a position + min_collateral: Int, + /// Policy ID of the liquidity pool manager + pool_policy_id: PolicyId, + /// Collateral token (USDCx native token on Cardano) + collateral_token: CollateralToken, +} + +/// PositionDatum — stored as inline datum on each position eUTxO. +/// Each open position is an independent UTxO with this datum. +/// All collateral amounts are denominated in micro USDCx (6 decimals). +pub type PositionDatum { + /// Pyth Lazer feed ID (e.g. 346 = XAU/USD) + feed_id: Int, + /// Long or Short + direction: Direction, + /// Leverage multiplier (e.g. 5 = 5x) + leverage: Int, + /// Entry price with 6 decimals (e.g. 3285_500000 = $3,285.50) + entry_price: Int, + /// Collateral in micro USDCx (e.g. 100_000000 = 100 USDCx) + collateral: Int, + /// Trader's public key hash + trader_pkh: ByteArray, + /// POSIX timestamp when the position was opened (milliseconds) + opened_at: Int, +} + +/// Pool state stored as datum on the liquidity pool eUTxO. +/// The pool holds USDCx liquidity that backs trader positions. +pub type PoolState { + /// Total open interest across all positions (micro USDCx) + total_open_interest: Int, + /// Maximum allowed open interest (micro USDCx) + max_open_interest: Int, +} + +/// Liquidation constants +/// Threshold: 80% margin ratio (8000 basis points) +pub const liquidation_bps = 8000 + +/// Keeper fee: 1% of collateral (100 basis points) +pub const keeper_fee_bps = 100 diff --git a/lazer/cardano/lazer-perps/onchain/plutus.json b/lazer/cardano/lazer-perps/onchain/plutus.json new file mode 100644 index 00000000..8044ff2f --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/plutus.json @@ -0,0 +1,418 @@ +{ + "preamble": { + "title": "team/lazer-perps", + "description": "Perpetual futures protocol powered by Pyth Lazer price feeds on Cardano", + "version": "0.0.0", + "plutusVersion": "v3", + "compiler": { + "name": "Aiken", + "version": "v1.1.21+42babe5" + }, + "license": "Apache-2.0" + }, + "validators": [ + { + "title": "close_position.close_position.spend", + "datum": { + "title": "datum", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1PositionDatum" + } + }, + "redeemer": { + "title": "_redeemer", + "schema": { + "$ref": "#/definitions/Data" + } + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "5916f7010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a4888888896600264653001300800198041804800cdc3a400530080024888966002600460106ea800e2653001300d00198069807000cdc3a40009112cc004c004c030dd50014660026020601a6ea800a46022602460240032301130120019180898091809180918091809000c8c044c048c048c0480066e9520004888888c8c9660026466446600400400244b30010018a508acc004cdc79bae301b0010038a51899801001180e000a02c40646eb0c064c068c068c068c068c068c068c068c068c058dd50071bae30053015375401115980099b884800000a266e212000375a6008602a6ea802229410134528202698009802980a1baa0079bad301730183018301830183014375400f375a600c60286ea801e6eb4c00cc050dd5003a444464b3001300d301837540031301c3019375400316405c64b3001300d0028a60103d87a80008acc004cdc400124001130073301b30073301b375066e0520000013301b375066e0520000024bd7025eb822600e66036600e660366ea0004cc06cdd400125eb812f5c080b901719b8233704006004b3001300c3017375400913370200a00313370200200a80b06eb4c05a60026e1d20049b89480124464b30013371e910100375c60326034003130190018b20283002001911919800800801911980180098010014dd7180b18099baa01a9bad3004301337540349111111919192cc004c080006264b30013011301c375400313232598009809980f1baa0018992cc004c050c07cdd5000c4c966002602a60406ea8006266046604860426ea8008cc08cc090c084dd5000a5eb822c80f8c040c080dd5001c5901e1811180f9baa0018b203a300f301e37540026040603a6ea80062c80d8c8cc004004dd61807980e9baa30200022259800800c530103d87a80008992cc004cdc39bad3022301f375400200f1300d330210014bd7044cc00c00cc08c00901d1810800a03e8b203a32598009808180d9baa0018992cc004c044c070dd5000c4c8cc0200048966002005132330010010042259800800c52f5c113302498009b89480026e3120049b804800e6e2520089b8c480026e3120089b804801d222222233223301623235980099b8f375c60600029110475d3c793008cc004888c8cc00cdd6981a0009bae3034303500130030019b89480426e3120109b804803e600e90082444446600a4646606c6ea0cde5250375c606e0026606c606e607000297ae05980098029b8d00189981a9ba930020013303537526600860066e340040052f5c11640c446644660104660706ea0cdc7000a4000660706ea4cc00cc008dc6800800a5eb808cc0248cc0e4dd419b8e00148000cc0e4dd49980218019b8d0010014bd701119191981e18141981e1ba80083303c375000a66078607a00297ae03303c303d303e0014bd7018008012cc004c05800a2653001001a5eb82006800888966002605e00312323303f374e0026607e6ea40092f5c065300100180252f5c080088896600200510018cc00400e6086005330413042002001400c8202246530010059981f98200008024c02400e6eb8c100c1040050054c004c8cc0fcdd419bca4a06eb8c100004cc0fcc100c1040052f5c0b30013017371a00313303e375260240026607c6ea4cc054c050dc6800800a5eb822c81d24466080004660806ea40052f5c1370e90034dc3a4010911119191919803194c0040066eb0c11c00a60646608c608e0106608c98103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a80004bd70200222259800801440063300100398250014c8c966002607800313230373304b304c0013304b30373304b304c3049375400697ae0304d304d001304837540071598009820800c4c8c8c0e0cc130c134008cc130c134004cc130c0e0cc130c134c128dd500225eb80c138c138004c134004c120dd5001c566002606a003132323230393304d304e0033304d304e0023304d304e0013304d30393304d304e304b375400a97ae0304f304f001304e001304d001304837540071598009805000c4c8c8c8c8c0e8cc138c13c010cc138c13c00ccc138c13c008cc138c13c004cc138c0e8cc138c13cc130dd500325eb80c140c140004c13c004c138004c134004c120dd5001c566002601200313232323232303b3304f30500053304f30500043304f30500033304f30500023304f30500013304f303b3304f3050304d375400e97ae0305130510013050001304f001304e001304d0013048375400715980099b874802800626464646464646078660a060a200c660a060a200a660a060a2008660a060a2006660a060a2004660a060a2002660a06078660a060a2609c6ea80212f5c060a460a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c0f4cc144c14801ccc144c148018cc144c148014cc144c148010cc144c14800ccc144c148008cc144c148004cc144c0f4cc144c148c13cdd5004a5eb80c14cc14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d200e00189919191919191919181f19829182980419829182980399829182980319829182980299829182980219829182980199829182980119829182980099829181f19829182998281baa00a4bd70182a182a000982980098290009828800982800098278009827000982680098241baa0038acc004cdc3a40200031323232323232323232303f33053305400933053305400833053305400733053305400633053305400533053305400433053305400333053305400233053305400133053303f3305330543051375401697ae03055305500130540013053001305200130510013050001304f001304e001304d0013048375400715980099b87480480062646464646464646464646080660a860aa014660a860aa012660a860aa010660a860aa00e660a860aa00c660a860aa00a660a860aa008660a860aa006660a860aa004660a860aa002660a86080660a860aa60a46ea80312f5c060ac60ac00260aa00260a800260a600260a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c104cc154c15802ccc154c158028cc154c158024cc154c158020cc154c15801ccc154c158018cc154c158014cc154c158010cc154c15800ccc154c158008cc154c158004cc154c104cc154c158c14cdd5006a5eb80c15cc15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d2016001899191919191919191919191918211982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b18211982b182b982a1baa00e4bd70182c182c000982b800982b000982a800982a000982980098290009828800982800098278009827000982680098241baa003899191919191919191919191918211982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b182b982c0009982b18211982b182b982a1baa00e4bd7025eb80c15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001a08c41188231046208c41188231046208c4118823104618231baa0013049002400c8238dd718231823800991acc004c08400a2653001001a5eb82006800888966002607400312323304a374e002660946ea40092f5c065300100180252f5c080088896600200510018cc00400e609c0053304c304d002001400c825a246530010059982518258008024c05000e6eb8c12cc1300050051802800a0888b2082375c608c608e006530012232598009800a40211598009800a4001148002266e3922010801020408102040800000241111598009800a408113370490400219801801980b00144cdc124101010100406600600666e00009203f41108220dc4000c888c8cc124c00cdd698250009982498251825800a5eb80c00c0066608a6ea0cdc7000a40006608a6ea4cc040c03cdc6800800a5eb8122232329800919802919198269ba833794940dd718270009982698271827800a5eb816600260386e340062660986ea4c064004cc130dd49980d980d1b8d0010014bd704590481191801acc004c0fc006298103d87a80008981c998269ba80014bd70209230030019bad304b003911191acc006600260806eb4c13c00694294504a44cc02000c8c014c0eccc13cdd4000a5eb822601e600898103d87a800041286eb8c13cc140004cc134dd419b8e00148000cc134dd49980c180b9b8d0010014bd7024446b3001303f002898019181d19827000a5eb822b3001304400289801919ba548008cc1380052f5c1159800981c00144c00c8cdd2a40086609c00297ae08acc004c03400a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520063304e375000297ae08acc004c03000a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520083304e3750b3001337100029040400244006266e04004c0192020412897ae08acc004cdc3a40140051300323374a900519827000a5eb822b30013370e900600144cc0048cdd2a40186609c00297ae02323304f3750600c6eb4c140004cc13cc140c1440052f5c0646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874803800a266002466e95200e3304e0014bd70119198279ba833794940dd718280009982798281828800a5eb8166002603c6e3400626609c6ea4c06c004cc138dd49980e980e1b8d0010014bd7045904a456600266e1d2010002899800919ba548040cc1380052f5c04646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874804800a246464660a066e9520123305030510014bd701982818289829000a5eb80c004008cc0208c8cc140dd419bca4a06eb8c144004cc140c144c1480052f5c0b30013039371a00313304f375260480026609e6ea4cc0a8c0a4dc6800800a5eb822c8258966002608200314c103d87980008acc004c118006298103d87a80008acc004c0e8006298103d87b80008acc004c03c006298103d87c80008acc004c038006298103d87d80008b2096412c825904b20968acc004cdc3a40280051300323374a900a19827000a5eb822b30013370e900b00144c00c8cdd2a402c6609c00297ae08acc004cdc3a403000513300123374a900c19827000a5eb808c8cc13cdd419bca4a06eb8c140004cc13cc140c1440052f5c0b3001301e371a00313304e375260360026609c6ea4cc074c070dc6800800a5eb822c82522c8249049209241248249049209241248249049209241248248dd718271827803096600266e2000520808080808080808080028800c4cdc0800980124100028230c00c00c6eb4c110004c8cc10cdd419b8e00148000cc10cdd49980718069b8d0010014bd701bae3043304400420728b206c371890011b80480051640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae301d302b37546602c4646b30013371e6eb8c0c000522104b9011a82008919191919191919911981c18121981c181c8039981c1ba90013303830390024bd701981c181c981d00125eb80d660026024003125980099b89002371a00313303737526601e0040026606e6ea66002005337026e3400400a002b8c25eb822c819a2c8190dd7181b981c0011bae3037004375a606c002646606a6ea0cde5250375c606c0026606a606c606e00297ae059800980f1b8d00189981a1ba930090013303437526601e601c6e340040052f5c11640c06eb8c0d0c0d4004d6600294624b30013371290201b8d0018998199ba93300b48100004cc0ccdd4cc005204099b80371a002901fc0057184bd7045902f45902e1bae30333034001300100259800a51892cc004cdc4a4100026e340062660626ea4cc0252080010013303137533001482000666e00dc6800a40ff0015c612f5c11640b51640b11640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae302e00a300348010c00d2008198010011813000a046899180118128019bae302300240846eb0c080c074dd5000c5901b19199119801001000912cc004006298103d87a80008992cc004cdd7802180f800c4c038cc088c0800052f5c11330030033024002407860440028100dd59810181098109810981098109810981098109810980e9baa0153374a90021980f19ba548008cc078c02cc070dd5180f980e1baa0014bd7025eb822c80d0c8cc004004dd61806980e1baa0142259800800c530103d87a80008992cc006600266ebc00530103d87a8000a50a514071100189980180198110012038325980099912cc00400a294226530013259800980b18109baa00189bad302230253756604a60446ea800629000204030240019baf302430250019bab003488966002003159800980100344cc01400d20008a5040891325980099baf30240014c010140008acc004cc018010dd6981298141bab3025001898019ba630290028a50408d1598009980300224001130030078a50408c8118c09c0050250ca60020033756602460426ea8c048c084dd5002488cc094008cc094dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c08c0066eacc09000660500069112cc004cdc8a441000038acc004cdc7a44100003899802980a998149ba60024bd70000c4cc015300103d87a8000006409519800803c006446600e0046605666ec0dd48029ba6004001401c8128604c00481222942294229410251ba633020337606ea401cdd31981019bb04c10b4a50797468205374617465004c010101004bd6f7b63025eb7bdb1808928c566002602e603a6ea8c084c078dd51810980f1baa300f301e3754003132598009806180f1baa0018992cc004c050c07cdd5000c4c8c8c8c8cc8966002605400713259800980d98131baa0018991919194c004dd69817000cdd718170024dd69817001cdd7181700124444b3001303300589980c9bab303200e225980080144cc06c030896600200513021330350144bd7044c8c8cc06cc0d00084c00cc0e4010dd7181a000981b0012068899191980c981980109801981b8021bae3031001303400240c91640c0302e001302d001302c00130273754003164094605200d16409c6eb8c09c004dd5981380118138009813000981280098101baa0018b203c3022301f37540031640746020603c6ea8c03cc078dd5000c5901c4530103d87a80004070604000280f08966002602060366ea800a2646464b30013023002899803181100189980300080245902018108009810800980e1baa0028b203422598009807980d1baa00289919192cc004c08800a26464b300130140018acc004c080dd5001401a2c810a2b30013019001899192cc004c09800a01116408c6eb4c090004c080dd50014566002601a00315980098101baa00280345902145901e203c4078603c6ea8004c08400e2c80f8c966002603c0031598009805180e800c5a2602e603a00280e22c80f8dd518100009810000980d9baa0028b203222c805860126ea800e2c8038601000260066ea802629344d9590011", + "hash": "c307eaab0ec4dd2f1d98749e9ae251353d37422856f6d2b4d2ed4ed1" + }, + { + "title": "close_position.close_position.else", + "redeemer": { + "schema": {} + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "5916f7010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a4888888896600264653001300800198041804800cdc3a400530080024888966002600460106ea800e2653001300d00198069807000cdc3a40009112cc004c004c030dd50014660026020601a6ea800a46022602460240032301130120019180898091809180918091809000c8c044c048c048c0480066e9520004888888c8c9660026466446600400400244b30010018a508acc004cdc79bae301b0010038a51899801001180e000a02c40646eb0c064c068c068c068c068c068c068c068c068c058dd50071bae30053015375401115980099b884800000a266e212000375a6008602a6ea802229410134528202698009802980a1baa0079bad301730183018301830183014375400f375a600c60286ea801e6eb4c00cc050dd5003a444464b3001300d301837540031301c3019375400316405c64b3001300d0028a60103d87a80008acc004cdc400124001130073301b30073301b375066e0520000013301b375066e0520000024bd7025eb822600e66036600e660366ea0004cc06cdd400125eb812f5c080b901719b8233704006004b3001300c3017375400913370200a00313370200200a80b06eb4c05a60026e1d20049b89480124464b30013371e910100375c60326034003130190018b20283002001911919800800801911980180098010014dd7180b18099baa01a9bad3004301337540349111111919192cc004c080006264b30013011301c375400313232598009809980f1baa0018992cc004c050c07cdd5000c4c966002602a60406ea8006266046604860426ea8008cc08cc090c084dd5000a5eb822c80f8c040c080dd5001c5901e1811180f9baa0018b203a300f301e37540026040603a6ea80062c80d8c8cc004004dd61807980e9baa30200022259800800c530103d87a80008992cc004cdc39bad3022301f375400200f1300d330210014bd7044cc00c00cc08c00901d1810800a03e8b203a32598009808180d9baa0018992cc004c044c070dd5000c4c8cc0200048966002005132330010010042259800800c52f5c113302498009b89480026e3120049b804800e6e2520089b8c480026e3120089b804801d222222233223301623235980099b8f375c60600029110475d3c793008cc004888c8cc00cdd6981a0009bae3034303500130030019b89480426e3120109b804803e600e90082444446600a4646606c6ea0cde5250375c606e0026606c606e607000297ae05980098029b8d00189981a9ba930020013303537526600860066e340040052f5c11640c446644660104660706ea0cdc7000a4000660706ea4cc00cc008dc6800800a5eb808cc0248cc0e4dd419b8e00148000cc0e4dd49980218019b8d0010014bd701119191981e18141981e1ba80083303c375000a66078607a00297ae03303c303d303e0014bd7018008012cc004c05800a2653001001a5eb82006800888966002605e00312323303f374e0026607e6ea40092f5c065300100180252f5c080088896600200510018cc00400e6086005330413042002001400c8202246530010059981f98200008024c02400e6eb8c100c1040050054c004c8cc0fcdd419bca4a06eb8c100004cc0fcc100c1040052f5c0b30013017371a00313303e375260240026607c6ea4cc054c050dc6800800a5eb822c81d24466080004660806ea40052f5c1370e90034dc3a4010911119191919803194c0040066eb0c11c00a60646608c608e0106608c98103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a80004bd70200222259800801440063300100398250014c8c966002607800313230373304b304c0013304b30373304b304c3049375400697ae0304d304d001304837540071598009820800c4c8c8c0e0cc130c134008cc130c134004cc130c0e0cc130c134c128dd500225eb80c138c138004c134004c120dd5001c566002606a003132323230393304d304e0033304d304e0023304d304e0013304d30393304d304e304b375400a97ae0304f304f001304e001304d001304837540071598009805000c4c8c8c8c8c0e8cc138c13c010cc138c13c00ccc138c13c008cc138c13c004cc138c0e8cc138c13cc130dd500325eb80c140c140004c13c004c138004c134004c120dd5001c566002601200313232323232303b3304f30500053304f30500043304f30500033304f30500023304f30500013304f303b3304f3050304d375400e97ae0305130510013050001304f001304e001304d0013048375400715980099b874802800626464646464646078660a060a200c660a060a200a660a060a2008660a060a2006660a060a2004660a060a2002660a06078660a060a2609c6ea80212f5c060a460a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c0f4cc144c14801ccc144c148018cc144c148014cc144c148010cc144c14800ccc144c148008cc144c148004cc144c0f4cc144c148c13cdd5004a5eb80c14cc14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d200e00189919191919191919181f19829182980419829182980399829182980319829182980299829182980219829182980199829182980119829182980099829181f19829182998281baa00a4bd70182a182a000982980098290009828800982800098278009827000982680098241baa0038acc004cdc3a40200031323232323232323232303f33053305400933053305400833053305400733053305400633053305400533053305400433053305400333053305400233053305400133053303f3305330543051375401697ae03055305500130540013053001305200130510013050001304f001304e001304d0013048375400715980099b87480480062646464646464646464646080660a860aa014660a860aa012660a860aa010660a860aa00e660a860aa00c660a860aa00a660a860aa008660a860aa006660a860aa004660a860aa002660a86080660a860aa60a46ea80312f5c060ac60ac00260aa00260a800260a600260a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c104cc154c15802ccc154c158028cc154c158024cc154c158020cc154c15801ccc154c158018cc154c158014cc154c158010cc154c15800ccc154c158008cc154c158004cc154c104cc154c158c14cdd5006a5eb80c15cc15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d2016001899191919191919191919191918211982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b18211982b182b982a1baa00e4bd70182c182c000982b800982b000982a800982a000982980098290009828800982800098278009827000982680098241baa003899191919191919191919191918211982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b182b982c0009982b18211982b182b982a1baa00e4bd7025eb80c15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001a08c41188231046208c41188231046208c4118823104618231baa0013049002400c8238dd718231823800991acc004c08400a2653001001a5eb82006800888966002607400312323304a374e002660946ea40092f5c065300100180252f5c080088896600200510018cc00400e609c0053304c304d002001400c825a246530010059982518258008024c05000e6eb8c12cc1300050051802800a0888b2082375c608c608e006530012232598009800a40211598009800a4001148002266e3922010801020408102040800000241111598009800a408113370490400219801801980b00144cdc124101010100406600600666e00009203f41108220dc4000c888c8cc124c00cdd698250009982498251825800a5eb80c00c0066608a6ea0cdc7000a40006608a6ea4cc040c03cdc6800800a5eb8122232329800919802919198269ba833794940dd718270009982698271827800a5eb816600260386e340062660986ea4c064004cc130dd49980d980d1b8d0010014bd704590481191801acc004c0fc006298103d87a80008981c998269ba80014bd70209230030019bad304b003911191acc006600260806eb4c13c00694294504a44cc02000c8c014c0eccc13cdd4000a5eb822601e600898103d87a800041286eb8c13cc140004cc134dd419b8e00148000cc134dd49980c180b9b8d0010014bd7024446b3001303f002898019181d19827000a5eb822b3001304400289801919ba548008cc1380052f5c1159800981c00144c00c8cdd2a40086609c00297ae08acc004c03400a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520063304e375000297ae08acc004c03000a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520083304e3750b3001337100029040400244006266e04004c0192020412897ae08acc004cdc3a40140051300323374a900519827000a5eb822b30013370e900600144cc0048cdd2a40186609c00297ae02323304f3750600c6eb4c140004cc13cc140c1440052f5c0646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874803800a266002466e95200e3304e0014bd70119198279ba833794940dd718280009982798281828800a5eb8166002603c6e3400626609c6ea4c06c004cc138dd49980e980e1b8d0010014bd7045904a456600266e1d2010002899800919ba548040cc1380052f5c04646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874804800a246464660a066e9520123305030510014bd701982818289829000a5eb80c004008cc0208c8cc140dd419bca4a06eb8c144004cc140c144c1480052f5c0b30013039371a00313304f375260480026609e6ea4cc0a8c0a4dc6800800a5eb822c8258966002608200314c103d87980008acc004c118006298103d87a80008acc004c0e8006298103d87b80008acc004c03c006298103d87c80008acc004c038006298103d87d80008b2096412c825904b20968acc004cdc3a40280051300323374a900a19827000a5eb822b30013370e900b00144c00c8cdd2a402c6609c00297ae08acc004cdc3a403000513300123374a900c19827000a5eb808c8cc13cdd419bca4a06eb8c140004cc13cc140c1440052f5c0b3001301e371a00313304e375260360026609c6ea4cc074c070dc6800800a5eb822c82522c8249049209241248249049209241248249049209241248248dd718271827803096600266e2000520808080808080808080028800c4cdc0800980124100028230c00c00c6eb4c110004c8cc10cdd419b8e00148000cc10cdd49980718069b8d0010014bd701bae3043304400420728b206c371890011b80480051640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae301d302b37546602c4646b30013371e6eb8c0c000522104b9011a82008919191919191919911981c18121981c181c8039981c1ba90013303830390024bd701981c181c981d00125eb80d660026024003125980099b89002371a00313303737526601e0040026606e6ea66002005337026e3400400a002b8c25eb822c819a2c8190dd7181b981c0011bae3037004375a606c002646606a6ea0cde5250375c606c0026606a606c606e00297ae059800980f1b8d00189981a1ba930090013303437526601e601c6e340040052f5c11640c06eb8c0d0c0d4004d6600294624b30013371290201b8d0018998199ba93300b48100004cc0ccdd4cc005204099b80371a002901fc0057184bd7045902f45902e1bae30333034001300100259800a51892cc004cdc4a4100026e340062660626ea4cc0252080010013303137533001482000666e00dc6800a40ff0015c612f5c11640b51640b11640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae302e00a300348010c00d2008198010011813000a046899180118128019bae302300240846eb0c080c074dd5000c5901b19199119801001000912cc004006298103d87a80008992cc004cdd7802180f800c4c038cc088c0800052f5c11330030033024002407860440028100dd59810181098109810981098109810981098109810980e9baa0153374a90021980f19ba548008cc078c02cc070dd5180f980e1baa0014bd7025eb822c80d0c8cc004004dd61806980e1baa0142259800800c530103d87a80008992cc006600266ebc00530103d87a8000a50a514071100189980180198110012038325980099912cc00400a294226530013259800980b18109baa00189bad302230253756604a60446ea800629000204030240019baf302430250019bab003488966002003159800980100344cc01400d20008a5040891325980099baf30240014c010140008acc004cc018010dd6981298141bab3025001898019ba630290028a50408d1598009980300224001130030078a50408c8118c09c0050250ca60020033756602460426ea8c048c084dd5002488cc094008cc094dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c08c0066eacc09000660500069112cc004cdc8a441000038acc004cdc7a44100003899802980a998149ba60024bd70000c4cc015300103d87a8000006409519800803c006446600e0046605666ec0dd48029ba6004001401c8128604c00481222942294229410251ba633020337606ea401cdd31981019bb04c10b4a50797468205374617465004c010101004bd6f7b63025eb7bdb1808928c566002602e603a6ea8c084c078dd51810980f1baa300f301e3754003132598009806180f1baa0018992cc004c050c07cdd5000c4c8c8c8c8cc8966002605400713259800980d98131baa0018991919194c004dd69817000cdd718170024dd69817001cdd7181700124444b3001303300589980c9bab303200e225980080144cc06c030896600200513021330350144bd7044c8c8cc06cc0d00084c00cc0e4010dd7181a000981b0012068899191980c981980109801981b8021bae3031001303400240c91640c0302e001302d001302c00130273754003164094605200d16409c6eb8c09c004dd5981380118138009813000981280098101baa0018b203c3022301f37540031640746020603c6ea8c03cc078dd5000c5901c4530103d87a80004070604000280f08966002602060366ea800a2646464b30013023002899803181100189980300080245902018108009810800980e1baa0028b203422598009807980d1baa00289919192cc004c08800a26464b300130140018acc004c080dd5001401a2c810a2b30013019001899192cc004c09800a01116408c6eb4c090004c080dd50014566002601a00315980098101baa00280345902145901e203c4078603c6ea8004c08400e2c80f8c966002603c0031598009805180e800c5a2602e603a00280e22c80f8dd518100009810000980d9baa0028b203222c805860126ea800e2c8038601000260066ea802629344d9590011", + "hash": "c307eaab0ec4dd2f1d98749e9ae251353d37422856f6d2b4d2ed4ed1" + }, + { + "title": "liquidate.liquidate.spend", + "datum": { + "title": "datum", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1PositionDatum" + } + }, + "redeemer": { + "title": "_redeemer", + "schema": { + "$ref": "#/definitions/Data" + } + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "591738010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a4888888896600264653001300800198041804800cdc3a400530080024888966002600460106ea800e2653001300d00198069807000cdc3a40009112cc004c004c030dd50014660026020601a6ea800a460226024602400323011301200191808980918091809000cdd2a400122332233225980099b880020018a60103d87980008acc004cdc40008014530103d87b80008a6103d87a800040448088cdc11bad3014002375a6028602a00266e08dd6980a0009bad30143015002300f3754004601e6ea80052222229800912cc004c0240062980103d87a80008acc004cdc4000a40011300433017300433017375066e05200000233017375066e0520000014bd7025eb82260086602e60086602e6ea0008cc05cdd4000a5eb812f5c080990134c010c04cdd50034dd6980198099baa0069bad30053013375400d300233015301698009b87480126e25200491192cc004cdc7a44100375c60326034003130190018b20283002001911919800800801911980180098010014dd7180b18099baa01a9bad3004301337540349111111919192cc004c080006264b30013011301c375400313232598009809980f1baa0018992cc004c050c07cdd5000c4c966002602a60406ea8006266046604860426ea8008cc08cc090c084dd5000a5eb822c80f8c08cc090c090c090c090c090c080dd5001c5901e1811180f9baa0018b203a300f301e37540026040603a6ea80062c80d8c8cc004004dd61807980e9baa30200022259800800c530103d87a80008992cc004cdc39bad3022301f375400200f1300e330210014bd7044cc00c00cc08c00901d1810800a03e8b203a32598009808180d9baa0018992cc004c044c070dd5000c4c8cc0200048966002005132330010010042259800800c52f5c113302498009b89480026e3120049b804800e6e2520089b8c480026e3120089b804801d222222233223301623235980099b8f375c60600029110475d3c793008cc004888c8cc00cdd6981a0009bae3034303500130030019b89480426e3120109b804803e600e90082444446600a4646606c6ea0cde5250375c606e0026606c606e607000297ae05980098029b8d00189981a9ba930020013303537526600860066e340040052f5c11640c446644660104660706ea0cdc7000a4000660706ea4cc00cc008dc6800800a5eb808cc0248cc0e4dd419b8e00148000cc0e4dd49980218019b8d0010014bd701119191981e18149981e1ba80083303c375000a66078607a00297ae03303c303d303e0014bd7018008012cc004c05800a2653001001a5eb82006800888966002605e00312323303f374e0026607e6ea40092f5c065300100180252f5c080088896600200510018cc00400e6086005330413042002001400c8202246530010059981f98200008024c02400e6eb8c100c1040050054c004c8cc0fcdd419bca4a06eb8c100004cc0fcc100c1040052f5c0b30013017371a00313303e375260240026607c6ea4cc054c050dc6800800a5eb822c81d24466080004660806ea40052f5c1370e90034dc3a4010911119191919803194c0040066eb0c11c00a60666608c608e0106608c98103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a80004bd70200222259800801440063300100398250014c8c966002607800313230383304b304c0013304b30383304b304c3049375400697ae0304d304d001304837540071598009820800c4c8c8c0e4cc130c134008cc130c134004cc130c0e4cc130c134c128dd500225eb80c138c138004c134004c120dd5001c566002606a0031323232303a3304d304e0033304d304e0023304d304e0013304d303a3304d304e304b375400a97ae0304f304f001304e001304d001304837540071598009805000c4c8c8c8c8c0eccc138c13c010cc138c13c00ccc138c13c008cc138c13c004cc138c0eccc138c13cc130dd500325eb80c140c140004c13c004c138004c134004c120dd5001c566002601200313232323232303c3304f30500053304f30500043304f30500033304f30500023304f30500013304f303c3304f3050304d375400e97ae0305130510013050001304f001304e001304d0013048375400715980099b87480280062646464646464607a660a060a200c660a060a200a660a060a2008660a060a2006660a060a2004660a060a2002660a0607a660a060a2609c6ea80212f5c060a460a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c0f8cc144c14801ccc144c148018cc144c148014cc144c148010cc144c14800ccc144c148008cc144c148004cc144c0f8cc144c148c13cdd5004a5eb80c14cc14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d200e00189919191919191919181f99829182980419829182980399829182980319829182980299829182980219829182980199829182980119829182980099829181f99829182998281baa00a4bd70182a182a000982980098290009828800982800098278009827000982680098241baa0038acc004cdc3a4020003132323232323232323230403305330540093305330540083305330540073305330540063305330540053305330540043305330540033305330540023305330540013305330403305330543051375401697ae03055305500130540013053001305200130510013050001304f001304e001304d0013048375400715980099b87480480062646464646464646464646082660a860aa014660a860aa012660a860aa010660a860aa00e660a860aa00c660a860aa00a660a860aa008660a860aa006660a860aa004660a860aa002660a86082660a860aa60a46ea80312f5c060ac60ac00260aa00260a800260a600260a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c108cc154c15802ccc154c158028cc154c158024cc154c158020cc154c15801ccc154c158018cc154c158014cc154c158010cc154c15800ccc154c158008cc154c158004cc154c108cc154c158c14cdd5006a5eb80c15cc15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d2016001899191919191919191919191918219982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b18219982b182b982a1baa00e4bd70182c182c000982b800982b000982a800982a000982980098290009828800982800098278009827000982680098241baa003899191919191919191919191918219982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b182b982c0009982b18219982b182b982a1baa00e4bd7025eb80c15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001a08c41188231046208c41188231046208c4118823104618231baa0013049002400c8238dd718231823800991acc004c08400a2653001001a5eb82006800888966002607400312323304a374e002660946ea40092f5c065300100180252f5c080088896600200510018cc00400e609c0053304c304d002001400c825a246530010059982518258008024c05000e6eb8c12cc1300050051802800a0888b2082375c608c608e006530012232598009800a40211598009800a4001148002266e3922010801020408102040800000241111598009800a408113370490400219801801980b00144cdc124101010100406600600666e00009203f41108220dc4000c888c8cc124c00cdd698250009982498251825800a5eb80c00c0066608a6ea0cdc7000a40006608a6ea4cc040c03cdc6800800a5eb8122232329800919802919198269ba833794940dd718270009982698271827800a5eb816600260386e340062660986ea4c064004cc130dd49980d980d1b8d0010014bd704590481191801acc004c0fc006298103d87a80008981d198269ba80014bd70209230030019bad304b003911191acc006600260806eb4c13c00694294504a44cc02000c8c014c0f0cc13cdd4000a5eb822601e600898103d87a800041286eb8c13cc140004cc134dd419b8e00148000cc134dd49980c180b9b8d0010014bd7024446b3001303f002898019181d99827000a5eb822b3001304400289801919ba548008cc1380052f5c1159800981c00144c00c8cdd2a40086609c00297ae08acc004c03400a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520063304e375000297ae08acc004c03000a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520083304e3750b3001337100029040400244006266e04004c0192020412897ae08acc004cdc3a40140051300323374a900519827000a5eb822b30013370e900600144cc0048cdd2a40186609c00297ae02323304f3750600c6eb4c140004cc13cc140c1440052f5c0646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874803800a266002466e95200e3304e0014bd70119198279ba833794940dd718280009982798281828800a5eb8166002603c6e3400626609c6ea4c06c004cc138dd49980e980e1b8d0010014bd7045904a456600266e1d2010002899800919ba548040cc1380052f5c04646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874804800a246464660a066e9520123305030510014bd701982818289829000a5eb80c004008cc0208c8cc140dd419bca4a06eb8c144004cc140c144c1480052f5c0b30013039371a00313304f375260480026609e6ea4cc0a8c0a4dc6800800a5eb822c8258966002608200314c103d87980008acc004c118006298103d87a80008acc004c0e8006298103d87b80008acc004c03c006298103d87c80008acc004c038006298103d87d80008b2096412c825904b20968acc004cdc3a40280051300323374a900a19827000a5eb822b30013370e900b00144c00c8cdd2a402c6609c00297ae08acc004cdc3a403000513300123374a900c19827000a5eb808c8cc13cdd419bca4a06eb8c140004cc13cc140c1440052f5c0b3001301e371a00313304e375260360026609c6ea4cc074c070dc6800800a5eb822c82522c8249049209241248249049209241248249049209241248248dd718271827803096600266e2000520808080808080808080028800c4cdc0800980124100028230c00c00c6eb4c110004c8cc10cdd419b8e00148000cc10cdd49980718069b8d0010014bd701bae3043304400420728b206c371890011b80480051640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae301d302b37546602c4646b30013371e6eb8c0c000522104b9011a82008919191919191919911981c18129981c181c8039981c1ba90013303830390024bd701981c181c981d00125eb80d660026024003125980099b89002371a00313303737526601e0040026606e6ea66002005337026e3400400a002b8c25eb822c819a2c8190dd7181b981c0011bae3037004375a606c002646606a6ea0cde5250375c606c0026606a606c606e00297ae059800980f1b8d00189981a1ba930090013303437526601e601c6e340040052f5c11640c06eb8c0d0c0d4004d6600294624b30013371290201b8d0018998199ba93300b48100004cc0ccdd4cc005204099b80371a002901fc0057184bd7045902f45902e1bae30333034001300100259800a51892cc004cdc4a4100026e340062660626ea4cc0252080010013303137533001482000666e00dc6800a40ff0015c612f5c11640b51640b11640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae302e00a300348010c00d2008198010011813000a046899180118128019bae302300240846eb0c080c074dd5000c5901b19199119801001000912cc004006298103d87a80008992cc004cdd7802180f800c4c03ccc088c0800052f5c11330030033024002407860440028100dd59810181098109810981098109810981098109810980e9baa0153374a90021980f19ba548008cc078c030c070dd5180f980e1baa0014bd7025eb822c80d0c8cc004004dd61806980e1baa0142259800800c530103d87a80008992cc006600266ebc00530103d87a8000a50a514071100189980180198110012038325980099912cc00400a294226530013259800980b18109baa00189bad302230253756604a60446ea800629000204030240019baf302430250019bab003488966002003159800980100344cc01400d20008a5040891325980099baf30240014c010140008acc004cc018010dd6981298141bab3025001898019ba630290028a50408d1598009980300224001130030078a50408c8118c09c0050250ca60020033756602460426ea8c048c084dd5002488cc094008cc094dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c08c0066eacc09000660500069112cc004cdc8a441000038acc004cdc7a44100003899802980b198149ba60024bd70000c4cc015300103d87a8000006409519800803c006446600e0046605666ec0dd48029ba6004001401c8128604c00481222942294229410251ba633020337606ea401cdd31981019bb04c10b4a50797468205374617465004c010101004bd6f7b63025eb7bdb1808928c566002602e603a6ea8c084c078dd51810980f1baa300f301e3754003132598009806180f1baa0018992cc004c050c07cdd5000c4c8c8c8c8cc8966002605400713259800980d98131baa0018991919194c004dd69817000cdd718170024dd69817001cdd7181700124444b3001303300589980c9bab303200e225980080144cc06c030896600200513022330350144bd7044c8c8cc06cc0d00084c00cc0e4010dd7181a000981b0012068899191980c981980109801981b8021bae3031001303400240c91640c0302e001302d001302c00130273754003164094605200d16409c6eb8c09c004dd5981380118138009813000981280098101baa0018b203c3022301f37540031640746020603c6ea8c03cc078dd5000c5901c4530103d87a80004070604000280f08966002602060366ea800a2646464b30013023002899803181100189980300080245902018108009810800980e1baa0028b203422598009807980d1baa00289919192cc004c08800a26464b300130140018acc004c080dd5001401a2c810a2b30013019001899192cc004c09800a01116408c6eb4c090004c080dd50014566002601a00315980098101baa00280345902145901e203c4078603c6ea8004c08400e2c80f8c966002603c0031598009805180e800c5a2602e603a00280e22c80f8dd518100009810000980d9baa0028b20321980aa6010101004bd70244444b3001300c301737540091980099baf3300600132598009806980c1baa0018980e180c9baa0018b202e330053370400666e00cdc1241940200490638099b824832004009300103d87b8000a50a5140591980099baf3300600132598009806980c1baa0018980e180c9baa0018b202e330053370400666e00cdc12418c0200490640099b82483200400930103d8798000a50a51405880b08b201618049baa0038b200e180400098019baa0098a4d13656400401", + "hash": "7b5850f83c896d18d39b91ab20f733e18c333a3de5d955d78cfa6c43" + }, + { + "title": "liquidate.liquidate.else", + "redeemer": { + "schema": {} + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "591738010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a4888888896600264653001300800198041804800cdc3a400530080024888966002600460106ea800e2653001300d00198069807000cdc3a40009112cc004c004c030dd50014660026020601a6ea800a460226024602400323011301200191808980918091809000cdd2a400122332233225980099b880020018a60103d87980008acc004cdc40008014530103d87b80008a6103d87a800040448088cdc11bad3014002375a6028602a00266e08dd6980a0009bad30143015002300f3754004601e6ea80052222229800912cc004c0240062980103d87a80008acc004cdc4000a40011300433017300433017375066e05200000233017375066e0520000014bd7025eb82260086602e60086602e6ea0008cc05cdd4000a5eb812f5c080990134c010c04cdd50034dd6980198099baa0069bad30053013375400d300233015301698009b87480126e25200491192cc004cdc7a44100375c60326034003130190018b20283002001911919800800801911980180098010014dd7180b18099baa01a9bad3004301337540349111111919192cc004c080006264b30013011301c375400313232598009809980f1baa0018992cc004c050c07cdd5000c4c966002602a60406ea8006266046604860426ea8008cc08cc090c084dd5000a5eb822c80f8c08cc090c090c090c090c090c080dd5001c5901e1811180f9baa0018b203a300f301e37540026040603a6ea80062c80d8c8cc004004dd61807980e9baa30200022259800800c530103d87a80008992cc004cdc39bad3022301f375400200f1300e330210014bd7044cc00c00cc08c00901d1810800a03e8b203a32598009808180d9baa0018992cc004c044c070dd5000c4c8cc0200048966002005132330010010042259800800c52f5c113302498009b89480026e3120049b804800e6e2520089b8c480026e3120089b804801d222222233223301623235980099b8f375c60600029110475d3c793008cc004888c8cc00cdd6981a0009bae3034303500130030019b89480426e3120109b804803e600e90082444446600a4646606c6ea0cde5250375c606e0026606c606e607000297ae05980098029b8d00189981a9ba930020013303537526600860066e340040052f5c11640c446644660104660706ea0cdc7000a4000660706ea4cc00cc008dc6800800a5eb808cc0248cc0e4dd419b8e00148000cc0e4dd49980218019b8d0010014bd701119191981e18149981e1ba80083303c375000a66078607a00297ae03303c303d303e0014bd7018008012cc004c05800a2653001001a5eb82006800888966002605e00312323303f374e0026607e6ea40092f5c065300100180252f5c080088896600200510018cc00400e6086005330413042002001400c8202246530010059981f98200008024c02400e6eb8c100c1040050054c004c8cc0fcdd419bca4a06eb8c100004cc0fcc100c1040052f5c0b30013017371a00313303e375260240026607c6ea4cc054c050dc6800800a5eb822c81d24466080004660806ea40052f5c1370e90034dc3a4010911119191919803194c0040066eb0c11c00a60666608c608e0106608c98103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a8000330464c103d87a80004bd70200222259800801440063300100398250014c8c966002607800313230383304b304c0013304b30383304b304c3049375400697ae0304d304d001304837540071598009820800c4c8c8c0e4cc130c134008cc130c134004cc130c0e4cc130c134c128dd500225eb80c138c138004c134004c120dd5001c566002606a0031323232303a3304d304e0033304d304e0023304d304e0013304d303a3304d304e304b375400a97ae0304f304f001304e001304d001304837540071598009805000c4c8c8c8c8c0eccc138c13c010cc138c13c00ccc138c13c008cc138c13c004cc138c0eccc138c13cc130dd500325eb80c140c140004c13c004c138004c134004c120dd5001c566002601200313232323232303c3304f30500053304f30500043304f30500033304f30500023304f30500013304f303c3304f3050304d375400e97ae0305130510013050001304f001304e001304d0013048375400715980099b87480280062646464646464607a660a060a200c660a060a200a660a060a2008660a060a2006660a060a2004660a060a2002660a0607a660a060a2609c6ea80212f5c060a460a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c0f8cc144c14801ccc144c148018cc144c148014cc144c148010cc144c14800ccc144c148008cc144c148004cc144c0f8cc144c148c13cdd5004a5eb80c14cc14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d200e00189919191919191919181f99829182980419829182980399829182980319829182980299829182980219829182980199829182980119829182980099829181f99829182998281baa00a4bd70182a182a000982980098290009828800982800098278009827000982680098241baa0038acc004cdc3a4020003132323232323232323230403305330540093305330540083305330540073305330540063305330540053305330540043305330540033305330540023305330540013305330403305330543051375401697ae03055305500130540013053001305200130510013050001304f001304e001304d0013048375400715980099b87480480062646464646464646464646082660a860aa014660a860aa012660a860aa010660a860aa00e660a860aa00c660a860aa00a660a860aa008660a860aa006660a860aa004660a860aa002660a86082660a860aa60a46ea80312f5c060ac60ac00260aa00260a800260a600260a400260a200260a0002609e002609c002609a00260906ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c108cc154c15802ccc154c158028cc154c158024cc154c158020cc154c15801ccc154c158018cc154c158014cc154c158010cc154c15800ccc154c158008cc154c158004cc154c108cc154c158c14cdd5006a5eb80c15cc15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001c56600266e1d2016001899191919191919191919191918219982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b18219982b182b982a1baa00e4bd70182c182c000982b800982b000982a800982a000982980098290009828800982800098278009827000982680098241baa003899191919191919191919191918219982b182b8061982b182b8059982b182b8051982b182b8049982b182b8041982b182b8039982b182b8031982b182b8029982b182b8021982b182b8019982b182b8011982b182b8009982b182b982c0009982b18219982b182b982a1baa00e4bd7025eb80c15c004c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c120dd5001a08c41188231046208c41188231046208c4118823104618231baa0013049002400c8238dd718231823800991acc004c08400a2653001001a5eb82006800888966002607400312323304a374e002660946ea40092f5c065300100180252f5c080088896600200510018cc00400e609c0053304c304d002001400c825a246530010059982518258008024c05000e6eb8c12cc1300050051802800a0888b2082375c608c608e006530012232598009800a40211598009800a4001148002266e3922010801020408102040800000241111598009800a408113370490400219801801980b00144cdc124101010100406600600666e00009203f41108220dc4000c888c8cc124c00cdd698250009982498251825800a5eb80c00c0066608a6ea0cdc7000a40006608a6ea4cc040c03cdc6800800a5eb8122232329800919802919198269ba833794940dd718270009982698271827800a5eb816600260386e340062660986ea4c064004cc130dd49980d980d1b8d0010014bd704590481191801acc004c0fc006298103d87a80008981d198269ba80014bd70209230030019bad304b003911191acc006600260806eb4c13c00694294504a44cc02000c8c014c0f0cc13cdd4000a5eb822601e600898103d87a800041286eb8c13cc140004cc134dd419b8e00148000cc134dd49980c180b9b8d0010014bd7024446b3001303f002898019181d99827000a5eb822b3001304400289801919ba548008cc1380052f5c1159800981c00144c00c8cdd2a40086609c00297ae08acc004c03400a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520063304e375000297ae08acc004c03000a26600e4646609e6ea0cde5250375c60a00026609e60a060a200297ae059800981c1b8d0018998271ba930230013304e37526605260506e340040052f5c1164128466e9520083304e3750b3001337100029040400244006266e04004c0192020412897ae08acc004cdc3a40140051300323374a900519827000a5eb822b30013370e900600144cc0048cdd2a40186609c00297ae02323304f3750600c6eb4c140004cc13cc140c1440052f5c0646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874803800a266002466e95200e3304e0014bd70119198279ba833794940dd718280009982798281828800a5eb8166002603c6e3400626609c6ea4c06c004cc138dd49980e980e1b8d0010014bd7045904a456600266e1d2010002899800919ba548040cc1380052f5c04646609e6ea0cde5250375c60a00026609e60a060a200297ae059800980f1b8d0018998271ba9301b0013304e37526603a60386e340040052f5c116412915980099b874804800a246464660a066e9520123305030510014bd701982818289829000a5eb80c004008cc0208c8cc140dd419bca4a06eb8c144004cc140c144c1480052f5c0b30013039371a00313304f375260480026609e6ea4cc0a8c0a4dc6800800a5eb822c8258966002608200314c103d87980008acc004c118006298103d87a80008acc004c0e8006298103d87b80008acc004c03c006298103d87c80008acc004c038006298103d87d80008b2096412c825904b20968acc004cdc3a40280051300323374a900a19827000a5eb822b30013370e900b00144c00c8cdd2a402c6609c00297ae08acc004cdc3a403000513300123374a900c19827000a5eb808c8cc13cdd419bca4a06eb8c140004cc13cc140c1440052f5c0b3001301e371a00313304e375260360026609c6ea4cc074c070dc6800800a5eb822c82522c8249049209241248249049209241248249049209241248248dd718271827803096600266e2000520808080808080808080028800c4cdc0800980124100028230c00c00c6eb4c110004c8cc10cdd419b8e00148000cc10cdd49980718069b8d0010014bd701bae3043304400420728b206c371890011b80480051640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae301d302b37546602c4646b30013371e6eb8c0c000522104b9011a82008919191919191919911981c18129981c181c8039981c1ba90013303830390024bd701981c181c981d00125eb80d660026024003125980099b89002371a00313303737526601e0040026606e6ea66002005337026e3400400a002b8c25eb822c819a2c8190dd7181b981c0011bae3037004375a606c002646606a6ea0cde5250375c606c0026606a606c606e00297ae059800980f1b8d00189981a1ba930090013303437526601e601c6e340040052f5c11640c06eb8c0d0c0d4004d6600294624b30013371290201b8d0018998199ba93300b48100004cc0ccdd4cc005204099b80371a002901fc0057184bd7045902f45902e1bae30333034001300100259800a51892cc004cdc4a4100026e340062660626ea4cc0252080010013303137533001482000666e00dc6800a40ff0015c612f5c11640b51640b11640ac6eb8c0c0c0c400566002600e6e3400626605c6ea4c008004cc0b8dd49980298021b8d0010014bd7045902a1bae302e00a300348010c00d2008198010011813000a046899180118128019bae302300240846eb0c080c074dd5000c5901b19199119801001000912cc004006298103d87a80008992cc004cdd7802180f800c4c03ccc088c0800052f5c11330030033024002407860440028100dd59810181098109810981098109810981098109810980e9baa0153374a90021980f19ba548008cc078c030c070dd5180f980e1baa0014bd7025eb822c80d0c8cc004004dd61806980e1baa0142259800800c530103d87a80008992cc006600266ebc00530103d87a8000a50a514071100189980180198110012038325980099912cc00400a294226530013259800980b18109baa00189bad302230253756604a60446ea800629000204030240019baf302430250019bab003488966002003159800980100344cc01400d20008a5040891325980099baf30240014c010140008acc004cc018010dd6981298141bab3025001898019ba630290028a50408d1598009980300224001130030078a50408c8118c09c0050250ca60020033756602460426ea8c048c084dd5002488cc094008cc094dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c08c0066eacc09000660500069112cc004cdc8a441000038acc004cdc7a44100003899802980b198149ba60024bd70000c4cc015300103d87a8000006409519800803c006446600e0046605666ec0dd48029ba6004001401c8128604c00481222942294229410251ba633020337606ea401cdd31981019bb04c10b4a50797468205374617465004c010101004bd6f7b63025eb7bdb1808928c566002602e603a6ea8c084c078dd51810980f1baa300f301e3754003132598009806180f1baa0018992cc004c050c07cdd5000c4c8c8c8c8cc8966002605400713259800980d98131baa0018991919194c004dd69817000cdd718170024dd69817001cdd7181700124444b3001303300589980c9bab303200e225980080144cc06c030896600200513022330350144bd7044c8c8cc06cc0d00084c00cc0e4010dd7181a000981b0012068899191980c981980109801981b8021bae3031001303400240c91640c0302e001302d001302c00130273754003164094605200d16409c6eb8c09c004dd5981380118138009813000981280098101baa0018b203c3022301f37540031640746020603c6ea8c03cc078dd5000c5901c4530103d87a80004070604000280f08966002602060366ea800a2646464b30013023002899803181100189980300080245902018108009810800980e1baa0028b203422598009807980d1baa00289919192cc004c08800a26464b300130140018acc004c080dd5001401a2c810a2b30013019001899192cc004c09800a01116408c6eb4c090004c080dd50014566002601a00315980098101baa00280345902145901e203c4078603c6ea8004c08400e2c80f8c966002603c0031598009805180e800c5a2602e603a00280e22c80f8dd518100009810000980d9baa0028b20321980aa6010101004bd70244444b3001300c301737540091980099baf3300600132598009806980c1baa0018980e180c9baa0018b202e330053370400666e00cdc1241940200490638099b824832004009300103d87b8000a50a5140591980099baf3300600132598009806980c1baa0018980e180c9baa0018b202e330053370400666e00cdc12418c0200490640099b82483200400930103d8798000a50a51405880b08b201618049baa0038b200e180400098019baa0098a4d13656400401", + "hash": "7b5850f83c896d18d39b91ab20f733e18c333a3de5d955d78cfa6c43" + }, + { + "title": "open_position.open_position.spend", + "datum": { + "title": "datum", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1PositionDatum" + } + }, + "redeemer": { + "title": "_redeemer", + "schema": { + "$ref": "#/definitions/Data" + } + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "591644010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a4888888896600264653001300800198041804800cdc3a400530080024888966002600460106ea800e2653001300d00198069807000cdc3a40009112cc004c004c030dd50014660026020601a6ea800a460226024602400323011301200191808980918091809000a4444b30013370e6eb4c050c044dd50021bad30023011375403115980099b87375a60293001370e90024dc4a400922325980099b8f488100375c602e6030003130170018b20243002001911919800800801911980180098010014dd7180a18089baa0189bad300230113754031374a900024444444646464b3001301f0018992cc004c040c06cdd5000c4c8c9660026024603a6ea8006264b30013013301e375400313259800980a180f9baa001899811181198101baa0023302230233020375400297ae08b203c302230233023302330233023301f37540071640746042603c6ea80062c80e0c038c074dd5000980f980e1baa0018b203432330010013758601c60386ea8c07c008896600200314c0103d87a80008992cc004cdc39bad3021301e375400201113007330200014bd7044cc00c00cc08800901c1810000a03c8b203832598009807980d1baa0018992cc004c040c06cdd5000c4c8cc0240048966002005132330010010042259800800c52f5c113302398009b89480026e3120049b804800e6e2520089b8c480026e3120089b804801d222222233223301723235980099b8f375c605e0029110475d3c793008cc004888c8cc00cdd698198009bae3033303400130030019b89480426e3120109b804803e600e90082444446600a4646606a6ea0cde5250375c606c0026606a606c606e00297ae05980098029b8d00189981a1ba930020013303437526600860066e340040052f5c11640c0466446601046606e6ea0cdc7000a40006606e6ea4cc00cc008dc6800800a5eb808cc0248cc0e0dd419b8e00148000cc0e0dd49980218019b8d0010014bd701119191981d98111981d9ba80083303b375000a66076607800297ae03303b303c303d0014bd7018008012cc004c05800a2653001001a5eb82006800888966002605c00312323303e374e0026607c6ea40092f5c065300100180252f5c080088896600200510018cc00400e6084005330403041002001400c81fa246530010059981f181f8008024c02400e6eb8c0fcc1000050054c004c8cc0f8dd419bca4a06eb8c0fc004cc0f8c0fcc1000052f5c0b30013017371a00313303d375260240026607a6ea4cc054c050dc6800800a5eb822c81ca446607e0046607e6ea40052f5c1370e90034dc3a4010911119191919803194c0040066eb0c11800a60586608a608c0106608a98103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a80004bd70200222259800801440063300100398248014c8c966002607600313230313304a304b0013304a30313304a304b3048375400697ae0304c304c001304737540071598009820000c4c8c8c0c8cc12cc130008cc12cc130004cc12cc0c8cc12cc130c124dd500225eb80c134c134004c130004c11cdd5001c566002606c003132323230333304c304d0033304c304d0023304c304d0013304c30333304c304d304a375400a97ae0304e304e001304d001304c001304737540071598009805000c4c8c8c8c8c0d0cc134c138010cc134c13800ccc134c138008cc134c138004cc134c0d0cc134c138c12cdd500325eb80c13cc13c004c138004c134004c130004c11cdd5001c56600260120031323232323230353304e304f0053304e304f0043304e304f0033304e304f0023304e304f0013304e30353304e304f304c375400e97ae030503050001304f001304e001304d001304c0013047375400715980099b87480280062646464646464606c6609e60a000c6609e60a000a6609e60a00086609e60a00066609e60a00046609e60a00026609e606c6609e60a0609a6ea80212f5c060a260a200260a0002609e002609c002609a0026098002608e6ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c0dccc140c14401ccc140c144018cc140c144014cc140c144010cc140c14400ccc140c144008cc140c144004cc140c0dccc140c144c138dd5004a5eb80c148c148004c144004c140004c13c004c138004c134004c130004c11cdd5001c56600266e1d200e00189919191919191919181c19828982900419828982900399828982900319828982900299828982900219828982900199828982900119828982900099828981c19828982918279baa00a4bd7018299829800982900098288009828000982780098270009826800982600098239baa0038acc004cdc3a4020003132323232323232323230393305230530093305230530083305230530073305230530063305230530053305230530043305230530033305230530023305230530013305230393305230533050375401697ae0305430540013053001305200130510013050001304f001304e001304d001304c0013047375400715980099b87480480062646464646464646464646074660a660a8014660a660a8012660a660a8010660a660a800e660a660a800c660a660a800a660a660a8008660a660a8006660a660a8004660a660a8002660a66074660a660a860a26ea80312f5c060aa60aa00260a800260a600260a400260a200260a0002609e002609c002609a0026098002608e6ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c0eccc150c15402ccc150c154028cc150c154024cc150c154020cc150c15401ccc150c154018cc150c154014cc150c154010cc150c15400ccc150c154008cc150c154004cc150c0eccc150c154c148dd5006a5eb80c158c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c130004c11cdd5001c56600266e1d20160018991919191919191919191919181e1982a982b0061982a982b0059982a982b0051982a982b0049982a982b0041982a982b0039982a982b0031982a982b0029982a982b0021982a982b0019982a982b0011982a982b0009982a981e1982a982b18299baa00e4bd70182b982b800982b000982a800982a0009829800982900098288009828000982780098270009826800982600098239baa0038991919191919191919191919181e1982a982b0061982a982b0059982a982b0051982a982b0049982a982b0041982a982b0039982a982b0031982a982b0029982a982b0021982a982b0019982a982b0011982a982b0009982a982b182b8009982a981e1982a982b18299baa00e4bd7025eb80c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c130004c11cdd5001a08a41148229045208a41148229045208a4114822904518229baa0013048002400c8230dd718229823000991acc004c08400a2653001001a5eb820068008889660026072003123233049374e002660926ea40092f5c065300100180252f5c080088896600200510018cc00400e609a0053304b304c002001400c8252246530010059982498250008024c05000e6eb8c128c12c0050051802800a0868b2080375c608a608c006530012232598009800a40211598009800a4001148002266e39220108010204081020408000002410d1598009800a408113370490400219801801980b00144cdc124101010100406600600666e00009203f410c8218dc4000c888c8cc120c00cdd698248009982418249825000a5eb80c00c006660886ea0cdc7000a4000660886ea4cc040c03cdc6800800a5eb8122232329800919802919198261ba833794940dd718268009982618269827000a5eb816600260386e340062660966ea4c064004cc12cdd49980d980d1b8d0010014bd704590471191801acc004c0f8006298103d87a800089819998261ba80014bd70209030030019bad304a003911191acc0066002607e6eb4c13800694294504944cc02000c8c014c0d4cc138dd4000a5eb822601e600898103d87a800041246eb8c138c13c004cc130dd419b8e00148000cc130dd49980c180b9b8d0010014bd7024446b3001303e002898019181a19826800a5eb822b3001304300289801919ba548008cc1340052f5c1159800981c80144c00c8cdd2a40086609a00297ae08acc004c03400a26600e4646609c6ea0cde5250375c609e0026609c609e60a000297ae059800981c9b8d0018998269ba930230013304d37526605260506e340040052f5c1164124466e9520063304d375000297ae08acc004c03000a26600e4646609c6ea0cde5250375c609e0026609c609e60a000297ae059800981c9b8d0018998269ba930230013304d37526605260506e340040052f5c1164124466e9520083304d3750b3001337100029040400244006266e04004c0192020412497ae08acc004cdc3a40140051300323374a900519826800a5eb822b30013370e900600144cc0048cdd2a40186609a00297ae02323304e3750600c6eb4c13c004cc138c13cc1400052f5c0646609c6ea0cde5250375c609e0026609c609e60a000297ae059800980f1b8d0018998269ba9301b0013304d37526603a60386e340040052f5c116412515980099b874803800a266002466e95200e3304d0014bd70119198271ba833794940dd718278009982718279828000a5eb8166002603c6e3400626609a6ea4c06c004cc134dd49980e980e1b8d0010014bd70459049456600266e1d2010002899800919ba548040cc1340052f5c04646609c6ea0cde5250375c609e0026609c609e60a000297ae059800980f1b8d0018998269ba9301b0013304d37526603a60386e340040052f5c116412515980099b874804800a2464646609e66e9520123304f30500014bd701982798281828800a5eb80c004008cc0208c8cc13cdd419bca4a06eb8c140004cc13cc140c1440052f5c0b3001303a371a00313304e375260480026609c6ea4cc0a8c0a4dc6800800a5eb822c8250966002608000314c103d87980008acc004c114006298103d87a80008acc004c0ec006298103d87b80008acc004c03c006298103d87c80008acc004c038006298103d87d80008b20944128825104a20948acc004cdc3a40280051300323374a900a19826800a5eb822b30013370e900b00144c00c8cdd2a402c6609a00297ae08acc004cdc3a403000513300123374a900c19826800a5eb808c8cc138dd419bca4a06eb8c13c004cc138c13cc1400052f5c0b3001301e371a00313304d375260360026609a6ea4cc074c070dc6800800a5eb822c824a2c8241048209041208241048209041208241048209041208240dd718269827003096600266e2000520808080808080808080028800c4cdc0800980124100028228c00c00c6eb4c10c004c8cc108dd419b8e00148000cc108dd49980718069b8d0010014bd701bae3042304300420708b206a371890011b80480051640a86eb8c0bcc0c000566002600e6e3400626605a6ea4c008004cc0b4dd49980298021b8d0010014bd704590291bae301c302a37546602e4646b30013371e6eb8c0bc00522104b9011a82008919191919191919911981b980f1981b981c0039981b9ba90013303730380024bd701981b981c181c80125eb80d660026024003125980099b89002371a00313303637526601e0040026606c6ea66002005337026e3400400a002b8c25eb822c81922c8188dd7181b181b8011bae3036004375a606a00264660686ea0cde5250375c606a00266068606a606c00297ae059800980f9b8d0018998199ba930090013303337526601e601c6e340040052f5c11640bc6eb8c0ccc0d0004d6600294624b30013371290201b8d0018998191ba93300b48100004cc0c8dd4cc005204099b80371a002901fc0057184bd7045902e45902d1bae30323033001300100259800a51892cc004cdc4a4100026e340062660606ea4cc0252080010013303037533001482000666e00dc6800a40ff0015c612f5c11640b11640ad1640a86eb8c0bcc0c000566002600e6e3400626605a6ea4c008004cc0b4dd49980298021b8d0010014bd704590291bae302d00a300348010c00d2008198010011812800a044899180118120019bae302200240806eb0c07cc070dd5000c5901a19199119801001000912cc004006298103d87a80008992cc004cdd7802180f000c4c020cc084c07c0052f5c113300300330230024074604200280f8dd5980f981018101810181018101810181018101810180e1baa0143374a90021980e99ba548008cc074c02cc06cdd5180f180d9baa0014bd7025eb822c80c8c8cc004004dd61806180d9baa0132259800800c530103d87a80008992cc006600266ebc00530103d87a8000a50a51406d100189980180198108012036325980099912cc00400a294226530013259800980a98101baa00189bad302130243756604860426ea800629000203e30230019baf302330240019bab003488966002003159800980100344cc01400d20008a5040851325980099baf30230014c010140008acc004cc018010dd6981218139bab3024001898019ba630280028a5040891598009980300224001130030078a5040888110c0980050240ca60020033756602260406ea8c044c080dd5002488cc090008cc090dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c0880066eacc08c006604e0069112cc004cdc8a441000038acc004cdc7a441000038998029807998141ba60024bd70000c4cc015300103d87a8000006409119800803c006446600e0046605466ec0dd48029ba6004001401c8120604a004811a2942294229410241ba63301f337606ea4020dd31980f99bb04c10b4a50797468205374617465004c010101004bd6f7b63025eb7bdb1808928c566002602c60386ea8c080c074dd51810180e9baa300e301d3754003132598009806980e9baa0018992cc004c04cc078dd5000c4c8c8c8c8cc8966002605200713259800980d18129baa0018991919194c004dd69816800cdd718168024dd69816801cdd7181680124444b3001303200589980d1bab303100e225980080144cc07003089660020051301b330340144bd7044c8c8cc06cc0cc0084c00cc0e0010dd71819800981a8012066899191980c981900109801981b0021bae3030001303300240c51640bc302d001302c001302b00130263754003164090605000d1640986eb8c098004dd59813001181300098128009812000980f9baa0018b203a3021301e3754003164070601e603a6ea8c038c074dd5000c5901b4530103d87a8000406c603e00280e88966002601e60346ea800a2646464b30013022002899803181080189980300080245901f18100009810000980d9baa0028b203222598009807180c9baa00289919192cc004c08400a26464b300130130018acc004c07cdd5001401a2c81022b30013018001899192cc004c09400a0111640886eb4c08c004c07cdd50014566002601c003159800980f9baa00280345902045901d203a4074603a6ea8004c08000e2c80f0c966002603a0031598009805980e000c5a2602c603800280da2c80f0dd5180f800980f800980d1baa0028b20301bad300130113754009159800acc004cdc4240006eb4c00cc044dd500244cdc49bad3003301137540086eb4c00cc044dd500c4528201e899b89375a600260226ea8060dd6980a180a980a980a980a98089baa0048a50403d14a0807a294100f22c805860126ea800e2c8038601000260066ea802629344d95900101", + "hash": "97bbb98a112020cf4fccb937b243d6b5a4d3d296c680cb0f7e3b7be4" + }, + { + "title": "open_position.open_position.else", + "redeemer": { + "schema": {} + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "591644010100229800aba4aba2aba1aba0aab9faab9eaab9dab9a4888888896600264653001300800198041804800cdc3a400530080024888966002600460106ea800e2653001300d00198069807000cdc3a40009112cc004c004c030dd50014660026020601a6ea800a460226024602400323011301200191808980918091809000a4444b30013370e6eb4c050c044dd50021bad30023011375403115980099b87375a60293001370e90024dc4a400922325980099b8f488100375c602e6030003130170018b20243002001911919800800801911980180098010014dd7180a18089baa0189bad300230113754031374a900024444444646464b3001301f0018992cc004c040c06cdd5000c4c8c9660026024603a6ea8006264b30013013301e375400313259800980a180f9baa001899811181198101baa0023302230233020375400297ae08b203c302230233023302330233023301f37540071640746042603c6ea80062c80e0c038c074dd5000980f980e1baa0018b203432330010013758601c60386ea8c07c008896600200314c0103d87a80008992cc004cdc39bad3021301e375400201113007330200014bd7044cc00c00cc08800901c1810000a03c8b203832598009807980d1baa0018992cc004c040c06cdd5000c4c8cc0240048966002005132330010010042259800800c52f5c113302398009b89480026e3120049b804800e6e2520089b8c480026e3120089b804801d222222233223301723235980099b8f375c605e0029110475d3c793008cc004888c8cc00cdd698198009bae3033303400130030019b89480426e3120109b804803e600e90082444446600a4646606a6ea0cde5250375c606c0026606a606c606e00297ae05980098029b8d00189981a1ba930020013303437526600860066e340040052f5c11640c0466446601046606e6ea0cdc7000a40006606e6ea4cc00cc008dc6800800a5eb808cc0248cc0e0dd419b8e00148000cc0e0dd49980218019b8d0010014bd701119191981d98111981d9ba80083303b375000a66076607800297ae03303b303c303d0014bd7018008012cc004c05800a2653001001a5eb82006800888966002605c00312323303e374e0026607c6ea40092f5c065300100180252f5c080088896600200510018cc00400e6084005330403041002001400c81fa246530010059981f181f8008024c02400e6eb8c0fcc1000050054c004c8cc0f8dd419bca4a06eb8c0fc004cc0f8c0fcc1000052f5c0b30013017371a00313303d375260240026607a6ea4cc054c050dc6800800a5eb822c81ca446607e0046607e6ea40052f5c1370e90034dc3a4010911119191919803194c0040066eb0c11800a60586608a608c0106608a98103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a8000330454c103d87a80004bd70200222259800801440063300100398248014c8c966002607600313230313304a304b0013304a30313304a304b3048375400697ae0304c304c001304737540071598009820000c4c8c8c0c8cc12cc130008cc12cc130004cc12cc0c8cc12cc130c124dd500225eb80c134c134004c130004c11cdd5001c566002606c003132323230333304c304d0033304c304d0023304c304d0013304c30333304c304d304a375400a97ae0304e304e001304d001304c001304737540071598009805000c4c8c8c8c8c0d0cc134c138010cc134c13800ccc134c138008cc134c138004cc134c0d0cc134c138c12cdd500325eb80c13cc13c004c138004c134004c130004c11cdd5001c56600260120031323232323230353304e304f0053304e304f0043304e304f0033304e304f0023304e304f0013304e30353304e304f304c375400e97ae030503050001304f001304e001304d001304c0013047375400715980099b87480280062646464646464606c6609e60a000c6609e60a000a6609e60a00086609e60a00066609e60a00046609e60a00026609e606c6609e60a0609a6ea80212f5c060a260a200260a0002609e002609c002609a0026098002608e6ea800e2b30013370e9006000c4c8c8c8c8c8c8c8c0dccc140c14401ccc140c144018cc140c144014cc140c144010cc140c14400ccc140c144008cc140c144004cc140c0dccc140c144c138dd5004a5eb80c148c148004c144004c140004c13c004c138004c134004c130004c11cdd5001c56600266e1d200e00189919191919191919181c19828982900419828982900399828982900319828982900299828982900219828982900199828982900119828982900099828981c19828982918279baa00a4bd7018299829800982900098288009828000982780098270009826800982600098239baa0038acc004cdc3a4020003132323232323232323230393305230530093305230530083305230530073305230530063305230530053305230530043305230530033305230530023305230530013305230393305230533050375401697ae0305430540013053001305200130510013050001304f001304e001304d001304c0013047375400715980099b87480480062646464646464646464646074660a660a8014660a660a8012660a660a8010660a660a800e660a660a800c660a660a800a660a660a8008660a660a8006660a660a8004660a660a8002660a66074660a660a860a26ea80312f5c060aa60aa00260a800260a600260a400260a200260a0002609e002609c002609a0026098002608e6ea800e2b30013370e900a000c4c8c8c8c8c8c8c8c8c8c8c8c0eccc150c15402ccc150c154028cc150c154024cc150c154020cc150c15401ccc150c154018cc150c154014cc150c154010cc150c15400ccc150c154008cc150c154004cc150c0eccc150c154c148dd5006a5eb80c158c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c130004c11cdd5001c56600266e1d20160018991919191919191919191919181e1982a982b0061982a982b0059982a982b0051982a982b0049982a982b0041982a982b0039982a982b0031982a982b0029982a982b0021982a982b0019982a982b0011982a982b0009982a981e1982a982b18299baa00e4bd70182b982b800982b000982a800982a0009829800982900098288009828000982780098270009826800982600098239baa0038991919191919191919191919181e1982a982b0061982a982b0059982a982b0051982a982b0049982a982b0041982a982b0039982a982b0031982a982b0029982a982b0021982a982b0019982a982b0011982a982b0009982a982b182b8009982a981e1982a982b18299baa00e4bd7025eb80c158004c154004c150004c14c004c148004c144004c140004c13c004c138004c134004c130004c11cdd5001a08a41148229045208a41148229045208a4114822904518229baa0013048002400c8230dd718229823000991acc004c08400a2653001001a5eb820068008889660026072003123233049374e002660926ea40092f5c065300100180252f5c080088896600200510018cc00400e609a0053304b304c002001400c8252246530010059982498250008024c05000e6eb8c128c12c0050051802800a0868b2080375c608a608c006530012232598009800a40211598009800a4001148002266e39220108010204081020408000002410d1598009800a408113370490400219801801980b00144cdc124101010100406600600666e00009203f410c8218dc4000c888c8cc120c00cdd698248009982418249825000a5eb80c00c006660886ea0cdc7000a4000660886ea4cc040c03cdc6800800a5eb8122232329800919802919198261ba833794940dd718268009982618269827000a5eb816600260386e340062660966ea4c064004cc12cdd49980d980d1b8d0010014bd704590471191801acc004c0f8006298103d87a800089819998261ba80014bd70209030030019bad304a003911191acc0066002607e6eb4c13800694294504944cc02000c8c014c0d4cc138dd4000a5eb822601e600898103d87a800041246eb8c138c13c004cc130dd419b8e00148000cc130dd49980c180b9b8d0010014bd7024446b3001303e002898019181a19826800a5eb822b3001304300289801919ba548008cc1340052f5c1159800981c80144c00c8cdd2a40086609a00297ae08acc004c03400a26600e4646609c6ea0cde5250375c609e0026609c609e60a000297ae059800981c9b8d0018998269ba930230013304d37526605260506e340040052f5c1164124466e9520063304d375000297ae08acc004c03000a26600e4646609c6ea0cde5250375c609e0026609c609e60a000297ae059800981c9b8d0018998269ba930230013304d37526605260506e340040052f5c1164124466e9520083304d3750b3001337100029040400244006266e04004c0192020412497ae08acc004cdc3a40140051300323374a900519826800a5eb822b30013370e900600144cc0048cdd2a40186609a00297ae02323304e3750600c6eb4c13c004cc138c13cc1400052f5c0646609c6ea0cde5250375c609e0026609c609e60a000297ae059800980f1b8d0018998269ba9301b0013304d37526603a60386e340040052f5c116412515980099b874803800a266002466e95200e3304d0014bd70119198271ba833794940dd718278009982718279828000a5eb8166002603c6e3400626609a6ea4c06c004cc134dd49980e980e1b8d0010014bd70459049456600266e1d2010002899800919ba548040cc1340052f5c04646609c6ea0cde5250375c609e0026609c609e60a000297ae059800980f1b8d0018998269ba9301b0013304d37526603a60386e340040052f5c116412515980099b874804800a2464646609e66e9520123304f30500014bd701982798281828800a5eb80c004008cc0208c8cc13cdd419bca4a06eb8c140004cc13cc140c1440052f5c0b3001303a371a00313304e375260480026609c6ea4cc0a8c0a4dc6800800a5eb822c8250966002608000314c103d87980008acc004c114006298103d87a80008acc004c0ec006298103d87b80008acc004c03c006298103d87c80008acc004c038006298103d87d80008b20944128825104a20948acc004cdc3a40280051300323374a900a19826800a5eb822b30013370e900b00144c00c8cdd2a402c6609a00297ae08acc004cdc3a403000513300123374a900c19826800a5eb808c8cc138dd419bca4a06eb8c13c004cc138c13cc1400052f5c0b3001301e371a00313304d375260360026609a6ea4cc074c070dc6800800a5eb822c824a2c8241048209041208241048209041208241048209041208240dd718269827003096600266e2000520808080808080808080028800c4cdc0800980124100028228c00c00c6eb4c10c004c8cc108dd419b8e00148000cc108dd49980718069b8d0010014bd701bae3042304300420708b206a371890011b80480051640a86eb8c0bcc0c000566002600e6e3400626605a6ea4c008004cc0b4dd49980298021b8d0010014bd704590291bae301c302a37546602e4646b30013371e6eb8c0bc00522104b9011a82008919191919191919911981b980f1981b981c0039981b9ba90013303730380024bd701981b981c181c80125eb80d660026024003125980099b89002371a00313303637526601e0040026606c6ea66002005337026e3400400a002b8c25eb822c81922c8188dd7181b181b8011bae3036004375a606a00264660686ea0cde5250375c606a00266068606a606c00297ae059800980f9b8d0018998199ba930090013303337526601e601c6e340040052f5c11640bc6eb8c0ccc0d0004d6600294624b30013371290201b8d0018998191ba93300b48100004cc0c8dd4cc005204099b80371a002901fc0057184bd7045902e45902d1bae30323033001300100259800a51892cc004cdc4a4100026e340062660606ea4cc0252080010013303037533001482000666e00dc6800a40ff0015c612f5c11640b11640ad1640a86eb8c0bcc0c000566002600e6e3400626605a6ea4c008004cc0b4dd49980298021b8d0010014bd704590291bae302d00a300348010c00d2008198010011812800a044899180118120019bae302200240806eb0c07cc070dd5000c5901a19199119801001000912cc004006298103d87a80008992cc004cdd7802180f000c4c020cc084c07c0052f5c113300300330230024074604200280f8dd5980f981018101810181018101810181018101810180e1baa0143374a90021980e99ba548008cc074c02cc06cdd5180f180d9baa0014bd7025eb822c80c8c8cc004004dd61806180d9baa0132259800800c530103d87a80008992cc006600266ebc00530103d87a8000a50a51406d100189980180198108012036325980099912cc00400a294226530013259800980a98101baa00189bad302130243756604860426ea800629000203e30230019baf302330240019bab003488966002003159800980100344cc01400d20008a5040851325980099baf30230014c010140008acc004cc018010dd6981218139bab3024001898019ba630280028a5040891598009980300224001130030078a5040888110c0980050240ca60020033756602260406ea8c044c080dd5002488cc090008cc090dd3000a5eb810011112cc00400a26600298103d87a80004bd6f7b63044ca60026eb8c0880066eacc08c006604e0069112cc004cdc8a441000038acc004cdc7a441000038998029807998141ba60024bd70000c4cc015300103d87a8000006409119800803c006446600e0046605466ec0dd48029ba6004001401c8120604a004811a2942294229410241ba63301f337606ea4020dd31980f99bb04c10b4a50797468205374617465004c010101004bd6f7b63025eb7bdb1808928c566002602c60386ea8c080c074dd51810180e9baa300e301d3754003132598009806980e9baa0018992cc004c04cc078dd5000c4c8c8c8c8cc8966002605200713259800980d18129baa0018991919194c004dd69816800cdd718168024dd69816801cdd7181680124444b3001303200589980d1bab303100e225980080144cc07003089660020051301b330340144bd7044c8c8cc06cc0cc0084c00cc0e0010dd71819800981a8012066899191980c981900109801981b0021bae3030001303300240c51640bc302d001302c001302b00130263754003164090605000d1640986eb8c098004dd59813001181300098128009812000980f9baa0018b203a3021301e3754003164070601e603a6ea8c038c074dd5000c5901b4530103d87a8000406c603e00280e88966002601e60346ea800a2646464b30013022002899803181080189980300080245901f18100009810000980d9baa0028b203222598009807180c9baa00289919192cc004c08400a26464b300130130018acc004c07cdd5001401a2c81022b30013018001899192cc004c09400a0111640886eb4c08c004c07cdd50014566002601c003159800980f9baa00280345902045901d203a4074603a6ea8004c08000e2c80f0c966002603a0031598009805980e000c5a2602c603800280da2c80f0dd5180f800980f800980d1baa0028b20301bad300130113754009159800acc004cdc4240006eb4c00cc044dd500244cdc49bad3003301137540086eb4c00cc044dd500c4528201e899b89375a600260226ea8060dd6980a180a980a980a980a98089baa0048a50403d14a0807a294100f22c805860126ea800e2c8038601000260066ea802629344d95900101", + "hash": "97bbb98a112020cf4fccb937b243d6b5a4d3d296c680cb0f7e3b7be4" + }, + { + "title": "pool_manager.pool_manager.spend", + "datum": { + "title": "datum", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1PoolState" + } + }, + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/pool_manager~1PoolAction" + } + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "5901c3010100229800aba2aba1aab9faab9eaab9dab9a48888896600264653001300700198039804000cdc3a400530070024888966002600460106ea800e26466453001159800980098059baa002899912cc004c00c00629462b30013007001898019bad3010300e375400515980099b8748010006266e24cdc01bad3010300e37540046eb4c040c038dd50049bad30103011300e375400515980099b8748018006266e252000337026eb4c040c038dd50011bad3010300e3754013133712900019b81375a6020601c6ea8008dd6980818071baa0094030806100c2018300e300c375400460166ea801e2c805260166ea801e601c0069112cc004c01000a2b3001300f37540150038b20208acc004c02000a2b3001300f37540150038b20208acc004cdc3a40080051323259800980a00140162c8090dd6980900098079baa00a8acc004cdc3a400c00513232332259800980b001c01e2c80a0dd698098009bad30130023013001300f375401515980099b874802000a264646644b30013016003803c590141bad3013001375a60260046026002601e6ea802a2c806900d201a403480686018601a0026e1d20003009375400716401c30070013003375400f149a26cac80081", + "hash": "bf2b4ba406b2327adc6a9dc3790f56f371f3d9465148f38ff62ae4e7" + }, + { + "title": "pool_manager.pool_manager.else", + "redeemer": { + "schema": {} + }, + "parameters": [ + { + "title": "config", + "schema": { + "$ref": "#/definitions/lazer_perps~1types~1MarketConfig" + } + } + ], + "compiledCode": "5901c3010100229800aba2aba1aab9faab9eaab9dab9a48888896600264653001300700198039804000cdc3a400530070024888966002600460106ea800e26466453001159800980098059baa002899912cc004c00c00629462b30013007001898019bad3010300e375400515980099b8748010006266e24cdc01bad3010300e37540046eb4c040c038dd50049bad30103011300e375400515980099b8748018006266e252000337026eb4c040c038dd50011bad3010300e3754013133712900019b81375a6020601c6ea8008dd6980818071baa0094030806100c2018300e300c375400460166ea801e2c805260166ea801e601c0069112cc004c01000a2b3001300f37540150038b20208acc004c02000a2b3001300f37540150038b20208acc004cdc3a40080051323259800980a00140162c8090dd6980900098079baa00a8acc004cdc3a400c00513232332259800980b001c01e2c80a0dd698098009bad30130023013001300f375401515980099b874802000a264646644b30013016003803c590141bad3013001375a60260046026002601e6ea802a2c806900d201a403480686018601a0026e1d20003009375400716401c30070013003375400f149a26cac80081", + "hash": "bf2b4ba406b2327adc6a9dc3790f56f371f3d9465148f38ff62ae4e7" + } + ], + "definitions": { + "ByteArray": { + "dataType": "bytes" + }, + "Data": { + "title": "Data", + "description": "Any Plutus data." + }, + "Int": { + "dataType": "integer" + }, + "cardano/assets/AssetName": { + "title": "AssetName", + "dataType": "bytes" + }, + "cardano/assets/PolicyId": { + "title": "PolicyId", + "dataType": "bytes" + }, + "lazer_perps/types/CollateralToken": { + "title": "CollateralToken", + "description": "USDCx collateral token identification.\n On Cardano, native tokens are identified by policy ID + asset name.", + "anyOf": [ + { + "title": "CollateralToken", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "policy_id", + "description": "Policy ID of the USDCx token (empty for ADA-as-collateral on testnet)", + "$ref": "#/definitions/cardano~1assets~1PolicyId" + }, + { + "title": "asset_name", + "description": "Asset name of the USDCx token", + "$ref": "#/definitions/cardano~1assets~1AssetName" + } + ] + } + ] + }, + "lazer_perps/types/Direction": { + "title": "Direction", + "description": "Direction of a perpetual position", + "anyOf": [ + { + "title": "Long", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "Short", + "dataType": "constructor", + "index": 1, + "fields": [] + } + ] + }, + "lazer_perps/types/MarketConfig": { + "title": "MarketConfig", + "description": "Per-market configuration — applied as parameter at deployment.\n Deploy once per market: XAU 10x, XAG 10x, XTI 5x, etc.", + "anyOf": [ + { + "title": "MarketConfig", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "pyth_id", + "description": "Pyth deployment policy ID on Cardano", + "$ref": "#/definitions/cardano~1assets~1PolicyId" + }, + { + "title": "feed_id", + "description": "Pyth Lazer feed ID for this market (e.g. 346 = XAU/USD)", + "$ref": "#/definitions/Int" + }, + { + "title": "leverage_cap", + "description": "Maximum leverage for this market (e.g. 10 = 10x)", + "$ref": "#/definitions/Int" + }, + { + "title": "min_collateral", + "description": "Minimum collateral in micro USDCx to open a position", + "$ref": "#/definitions/Int" + }, + { + "title": "pool_policy_id", + "description": "Policy ID of the liquidity pool manager", + "$ref": "#/definitions/cardano~1assets~1PolicyId" + }, + { + "title": "collateral_token", + "description": "Collateral token (USDCx native token on Cardano)", + "$ref": "#/definitions/lazer_perps~1types~1CollateralToken" + } + ] + } + ] + }, + "lazer_perps/types/PoolState": { + "title": "PoolState", + "description": "Pool state stored as datum on the liquidity pool eUTxO.\n The pool holds USDCx liquidity that backs trader positions.", + "anyOf": [ + { + "title": "PoolState", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "total_open_interest", + "description": "Total open interest across all positions (micro USDCx)", + "$ref": "#/definitions/Int" + }, + { + "title": "max_open_interest", + "description": "Maximum allowed open interest (micro USDCx)", + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "lazer_perps/types/PositionDatum": { + "title": "PositionDatum", + "description": "PositionDatum — stored as inline datum on each position eUTxO.\n Each open position is an independent UTxO with this datum.\n All collateral amounts are denominated in micro USDCx (6 decimals).", + "anyOf": [ + { + "title": "PositionDatum", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "feed_id", + "description": "Pyth Lazer feed ID (e.g. 346 = XAU/USD)", + "$ref": "#/definitions/Int" + }, + { + "title": "direction", + "description": "Long or Short", + "$ref": "#/definitions/lazer_perps~1types~1Direction" + }, + { + "title": "leverage", + "description": "Leverage multiplier (e.g. 5 = 5x)", + "$ref": "#/definitions/Int" + }, + { + "title": "entry_price", + "description": "Entry price with 6 decimals (e.g. 3285_500000 = $3,285.50)", + "$ref": "#/definitions/Int" + }, + { + "title": "collateral", + "description": "Collateral in micro USDCx (e.g. 100_000000 = 100 USDCx)", + "$ref": "#/definitions/Int" + }, + { + "title": "trader_pkh", + "description": "Trader's public key hash", + "$ref": "#/definitions/ByteArray" + }, + { + "title": "opened_at", + "description": "POSIX timestamp when the position was opened (milliseconds)", + "$ref": "#/definitions/Int" + } + ] + } + ] + }, + "pool_manager/PoolAction": { + "title": "PoolAction", + "description": "Pool actions", + "anyOf": [ + { + "title": "Deposit", + "description": "Deposit liquidity into the pool", + "dataType": "constructor", + "index": 0, + "fields": [] + }, + { + "title": "Withdraw", + "description": "Withdraw liquidity from the pool (only if OI allows)", + "dataType": "constructor", + "index": 1, + "fields": [] + }, + { + "title": "PositionOpened", + "description": "Update pool state after position open (increase OI)", + "dataType": "constructor", + "index": 2, + "fields": [ + { + "title": "size", + "$ref": "#/definitions/Int" + } + ] + }, + { + "title": "PositionClosed", + "description": "Update pool state after position close (decrease OI, settle PnL)", + "dataType": "constructor", + "index": 3, + "fields": [ + { + "title": "size", + "$ref": "#/definitions/Int" + }, + { + "title": "pnl", + "$ref": "#/definitions/Int" + } + ] + }, + { + "title": "PositionLiquidated", + "description": "Update pool state after liquidation (decrease OI, collect remaining)", + "dataType": "constructor", + "index": 4, + "fields": [ + { + "title": "size", + "$ref": "#/definitions/Int" + }, + { + "title": "recovered", + "$ref": "#/definitions/Int" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/lazer/cardano/lazer-perps/onchain/validators/close_position.ak b/lazer/cardano/lazer-perps/onchain/validators/close_position.ak new file mode 100644 index 00000000..d646dce1 --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/validators/close_position.ak @@ -0,0 +1,51 @@ +use aiken/collection/list +use cardano/transaction.{Transaction} +use lazer_perps/formulas +use lazer_perps/oracle_gate +use lazer_perps/types.{MarketConfig, PositionDatum} + +/// Close Position validator. +/// +/// Only the trader (trader_pkh) can close their position. +/// Reads the current Pyth price as exit price and computes settlement. +/// +/// Formulas used: +/// PnL = direction_multiplier × collateral × leverage × (exit - entry) / entry +/// Payout = max(0, collateral + PnL) +validator close_position(config: MarketConfig) { + spend( + datum: Option, + _redeemer: Data, + _own_ref: Data, + self: Transaction, + ) { + expect Some(position) = datum + + // Read exit price via Pyth oracle gate + let (exit_price, _exponent) = + oracle_gate.read_price(config.pyth_id, config.feed_id, self) + + // Only the trader who opened the position can close it + let signed_by_trader = + list.has(self.extra_signatories, position.trader_pkh) + + // Prices must be valid + let valid_prices = exit_price > 0 && position.entry_price > 0 + + // Compute PnL and payout for validation + let pnl = + formulas.compute_pnl( + position.direction, + position.collateral, + position.leverage, + position.entry_price, + exit_price, + ) + + // Payout = max(0, collateral + PnL) + expect _payout = + formulas.compute_payout(position.collateral, pnl) + + signed_by_trader && valid_prices + } +} diff --git a/lazer/cardano/lazer-perps/onchain/validators/liquidate.ak b/lazer/cardano/lazer-perps/onchain/validators/liquidate.ak new file mode 100644 index 00000000..6a769853 --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/validators/liquidate.ak @@ -0,0 +1,43 @@ +use cardano/transaction.{Transaction} +use lazer_perps/formulas +use lazer_perps/oracle_gate +use lazer_perps/types.{MarketConfig, PositionDatum} + +/// Liquidation validator. +/// +/// Anyone can trigger — no owner signature needed. +/// +/// Liquidation price formulas: +/// Long: liq_price = entry_price × (1 - 1/leverage + 0.01) +/// Short: liq_price = entry_price × (1 + 1/leverage - 0.01) +/// +/// Trigger condition: +/// Long: current_price <= liq_price +/// Short: current_price >= liq_price +/// +/// On liquidation: +/// - Keeper receives 1% of collateral as fee +/// - Remaining goes back to the liquidity pool +/// - Position eUTxO is consumed (destroyed) +validator liquidate(config: MarketConfig) { + spend( + datum: Option, + _redeemer: Data, + _own_ref: Data, + self: Transaction, + ) { + expect Some(position) = datum + + // Read current price via Pyth oracle gate + let (current_price, _exponent) = + oracle_gate.read_price(config.pyth_id, config.feed_id, self) + + // Check if position has crossed the liquidation price + formulas.is_liquidatable( + position.direction, + position.entry_price, + position.leverage, + current_price, + ) + } +} diff --git a/lazer/cardano/lazer-perps/onchain/validators/open_position.ak b/lazer/cardano/lazer-perps/onchain/validators/open_position.ak new file mode 100644 index 00000000..07951344 --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/validators/open_position.ak @@ -0,0 +1,40 @@ +use cardano/transaction.{Transaction} +use lazer_perps/oracle_gate +use lazer_perps/types.{MarketConfig, PositionDatum} + +/// Open Position validator. +/// +/// Validates that a new position: +/// 1. Has a valid Pyth price witness (entry_price == oracle price) +/// 2. Respects the market's leverage cap +/// 3. Meets minimum collateral requirement +/// 4. Feed ID matches the market config +validator open_position(config: MarketConfig) { + spend( + datum: Option, + _redeemer: Data, + _own_ref: Data, + self: Transaction, + ) { + expect Some(position) = datum + + // Read current oracle price via the Pyth oracle gate + let (current_price, _exponent) = + oracle_gate.read_price(config.pyth_id, config.feed_id, self) + + // 1. Feed ID in datum must match market config + let feed_matches = position.feed_id == config.feed_id + + // 2. Entry price must match current oracle price + let price_valid = current_price == position.entry_price + + // 3. Leverage must be within cap + let leverage_ok = + position.leverage > 0 && position.leverage <= config.leverage_cap + + // 4. Minimum collateral (in micro USDCx) + let collateral_ok = position.collateral >= config.min_collateral + + feed_matches && price_valid && leverage_ok && collateral_ok + } +} diff --git a/lazer/cardano/lazer-perps/onchain/validators/pool_manager.ak b/lazer/cardano/lazer-perps/onchain/validators/pool_manager.ak new file mode 100644 index 00000000..6c177a66 --- /dev/null +++ b/lazer/cardano/lazer-perps/onchain/validators/pool_manager.ak @@ -0,0 +1,67 @@ +use cardano/transaction.{Transaction} +use lazer_perps/types.{MarketConfig, PoolState} + +/// Pool actions +pub type PoolAction { + /// Deposit liquidity into the pool + Deposit + /// Withdraw liquidity from the pool (only if OI allows) + Withdraw + /// Update pool state after position open (increase OI) + PositionOpened { size: Int } + /// Update pool state after position close (decrease OI, settle PnL) + PositionClosed { size: Int, pnl: Int } + /// Update pool state after liquidation (decrease OI, collect remaining) + PositionLiquidated { size: Int, recovered: Int } +} + +/// Pool Manager validator. +/// +/// Manages the shared liquidity UTxO for the perps protocol. +/// Tracks open interest and enforces caps to limit protocol exposure. +/// +/// The pool receives funds on losing trades and pays out on winning trades. +/// All state transitions require a valid continuation output with +/// updated PoolState datum. +validator pool_manager(_config: MarketConfig) { + spend( + datum: Option, + redeemer: PoolAction, + _own_ref: Data, + _self: Transaction, + ) { + expect Some(pool) = datum + + when redeemer is { + // Deposit — anyone can add liquidity + Deposit -> True + + // Withdraw — only if remaining liquidity covers open interest + Withdraw -> { + // Pool must maintain enough liquidity to cover max possible payouts + // For MVP: allow withdrawal if no open interest + pool.total_open_interest == 0 + } + + // Position opened — increase open interest + PositionOpened { size } -> { + let new_oi = pool.total_open_interest + size + // Open interest cap check + new_oi <= pool.max_open_interest + } + + // Position closed — decrease open interest, settle PnL + PositionClosed { size, pnl: _ } -> { + let new_oi = pool.total_open_interest - size + // OI cannot go negative + new_oi >= 0 + } + + // Position liquidated — decrease OI, recover collateral + PositionLiquidated { size, recovered: _ } -> { + let new_oi = pool.total_open_interest - size + new_oi >= 0 + } + } + } +} diff --git a/lazer/cardano/lazer-perps/package-lock.json b/lazer/cardano/lazer-perps/package-lock.json new file mode 100644 index 00000000..c15f003f --- /dev/null +++ b/lazer/cardano/lazer-perps/package-lock.json @@ -0,0 +1,1553 @@ +{ + "name": "lazer-perps", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lazer-perps", + "version": "1.0.0", + "dependencies": { + "@evolution-sdk/evolution": "^0.3.30", + "@pythnetwork/pyth-lazer-cardano-js": "^0.1.0", + "@pythnetwork/pyth-lazer-sdk": "^5.2.0" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "tsx": "^4.21.0", + "typescript": "^5.7.2" + } + }, + "node_modules/@effect/cluster": { + "version": "0.48.16", + "resolved": "https://registry.npmjs.org/@effect/cluster/-/cluster-0.48.16.tgz", + "integrity": "sha512-ZZkrSMVetOvlRDD8mPCX3IcVJtvUZBp6++lUKNGIT6LRIObRP4lVwtei85Z+4g49WpeLvJnSdH0zjPtGieFDHQ==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@effect/platform": "^0.90.10", + "@effect/rpc": "^0.69.4", + "@effect/sql": "^0.44.2", + "@effect/workflow": "^0.9.6", + "effect": "^3.17.14" + } + }, + "node_modules/@effect/experimental": { + "version": "0.54.6", + "resolved": "https://registry.npmjs.org/@effect/experimental/-/experimental-0.54.6.tgz", + "integrity": "sha512-UqHMvCQmrZT6kUVoUC0lqyno4Yad+j9hBGCdUjW84zkLwAq08tPqySiZUKRwY+Ae5B2Ab8rISYJH7nQvct9DMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "uuid": "^11.0.3" + }, + "peerDependencies": { + "@effect/platform": "^0.90.2", + "effect": "^3.17.7", + "ioredis": "^5", + "lmdb": "^3" + }, + "peerDependenciesMeta": { + "ioredis": { + "optional": true + }, + "lmdb": { + "optional": true + } + } + }, + "node_modules/@effect/platform": { + "version": "0.90.10", + "resolved": "https://registry.npmjs.org/@effect/platform/-/platform-0.90.10.tgz", + "integrity": "sha512-QhDPgCaLfIMQKOCoCPQvRUS+Y34iYJ07jdZ/CBAvYFvg/iUBebsmFuHL63RCD/YZH9BuK/kqqLYAA3M0fmUEgg==", + "license": "MIT", + "dependencies": { + "find-my-way-ts": "^0.1.6", + "msgpackr": "^1.11.4", + "multipasta": "^0.2.7" + }, + "peerDependencies": { + "effect": "^3.17.13" + } + }, + "node_modules/@effect/platform-node": { + "version": "0.96.1", + "resolved": "https://registry.npmjs.org/@effect/platform-node/-/platform-node-0.96.1.tgz", + "integrity": "sha512-4nfB/XRJJ246MCdI7klTE/aVvA9txfI83RnymS7pNyoG4CXUKELi87JrkrWFTtOlewzt5UMWpmqsFmm2qHxx3A==", + "license": "MIT", + "dependencies": { + "@effect/platform-node-shared": "^0.49.0", + "mime": "^3.0.0", + "undici": "^7.10.0", + "ws": "^8.18.2" + }, + "peerDependencies": { + "@effect/cluster": "^0.48.2", + "@effect/platform": "^0.90.6", + "@effect/rpc": "^0.69.1", + "@effect/sql": "^0.44.2", + "effect": "^3.17.10" + } + }, + "node_modules/@effect/platform-node-shared": { + "version": "0.49.2", + "resolved": "https://registry.npmjs.org/@effect/platform-node-shared/-/platform-node-shared-0.49.2.tgz", + "integrity": "sha512-uYlQi2swDV9hdHatr2Onov3G+VlEF+3+Qm9dvdOZiZNE1bVqvs/zs6LVT8Yrz/3Vq/4JPzGcN+acx0iiJo5ZVw==", + "license": "MIT", + "dependencies": { + "@parcel/watcher": "^2.5.1", + "multipasta": "^0.2.7", + "ws": "^8.18.2" + }, + "peerDependencies": { + "@effect/cluster": "^0.48.10", + "@effect/platform": "^0.90.10", + "@effect/rpc": "^0.69.3", + "@effect/sql": "^0.44.2", + "effect": "^3.17.13" + } + }, + "node_modules/@effect/rpc": { + "version": "0.69.5", + "resolved": "https://registry.npmjs.org/@effect/rpc/-/rpc-0.69.5.tgz", + "integrity": "sha512-LLCZP/aiaW4HeoIaoZuVZpJb/PFCwdJP21b3xP6l+1yoRVw8HlKYyfy/outRCF+BT4ndtY0/utFSeGWC21Qr7w==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@effect/platform": "^0.90.10", + "effect": "^3.17.14" + } + }, + "node_modules/@effect/sql": { + "version": "0.44.2", + "resolved": "https://registry.npmjs.org/@effect/sql/-/sql-0.44.2.tgz", + "integrity": "sha512-DEcvriHvj88zu7keruH9NcHQzam7yQzLNLJO6ucDXMCAwWzYZSJOsmkxBznRFv8ylFtccSclKH2fuj+wRKPjCQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "uuid": "^11.0.3" + }, + "peerDependencies": { + "@effect/experimental": "^0.54.6", + "@effect/platform": "^0.90.4", + "effect": "^3.17.7" + } + }, + "node_modules/@effect/workflow": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@effect/workflow/-/workflow-0.9.6.tgz", + "integrity": "sha512-uPBpSJ8NYwYA6VLZovfejwNik+2kAaoDtlPi+VTlxFMscWNYx+xlGiRg8CO/oa2pHCwkJYjOI27SGOlUawiz1w==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@effect/platform": "^0.90.10", + "@effect/rpc": "^0.69.4", + "effect": "^3.17.14" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@evolution-sdk/evolution": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@evolution-sdk/evolution/-/evolution-0.3.30.tgz", + "integrity": "sha512-8DMgxNdjWCEhCu8sMKz/ikY4qfGmoW8vBPT53Dji7i5PmHYMXLuVk0Nt5mNpIovujwSbC271GIJQo2pINtQsxg==", + "license": "MIT", + "dependencies": { + "@effect/platform": "^0.90.10", + "@effect/platform-node": "^0.96.1", + "@noble/curves": "^2.0.1", + "@noble/hashes": "^1.8.0", + "@scure/base": "^1.2.6", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "@types/bip39": "^3.0.4", + "bip39": "^3.1.0", + "effect": "^3.19.3" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@noble/curves": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz", + "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.0.1" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pythnetwork/pyth-lazer-cardano-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-lazer-cardano-js/-/pyth-lazer-cardano-js-0.1.0.tgz", + "integrity": "sha512-KfddoNfkRf+a6Qqf1zKGkMyKK9Mgib6P5hLVApc6qB3XpLkzk9GfPLOc9q2uqCF0EOjzPRDRTMF9beKMxyAK4Q==", + "dependencies": { + "@evolution-sdk/evolution": "^0.3.29" + }, + "engines": { + "node": "^24.0.0" + } + }, + "node_modules/@pythnetwork/pyth-lazer-sdk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-lazer-sdk/-/pyth-lazer-sdk-5.2.0.tgz", + "integrity": "sha512-iGnNXRqnPWzrcgsx/3ZhHEkN1emnT2A9bE9c7WHdETZSHKjkpn5PT54lLbOpov47kleB6EejB++EeoSBFa9Qxw==", + "license": "Apache-2.0", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "buffer": "^6.0.3", + "isomorphic-ws": "^5.0.0", + "ts-log": "^2.2.7", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=22.14.0" + } + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@types/bip39": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/bip39/-/bip39-3.0.4.tgz", + "integrity": "sha512-kgmgxd14vTUMqcKu/gRi7adMchm7teKnOzdkeP0oQ5QovXpbUJISU0KUtBt84DdxCws/YuNlSCIoZqgXexe6KQ==", + "deprecated": "This is a stub types definition. bip39 provides its own type definitions, so you do not need this installed.", + "license": "MIT", + "dependencies": { + "bip39": "*" + } + }, + "node_modules/@types/node": { + "version": "22.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", + "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "license": "ISC", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/effect": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.21.0.tgz", + "integrity": "sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/esbuild": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", + "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.4", + "@esbuild/android-arm": "0.27.4", + "@esbuild/android-arm64": "0.27.4", + "@esbuild/android-x64": "0.27.4", + "@esbuild/darwin-arm64": "0.27.4", + "@esbuild/darwin-x64": "0.27.4", + "@esbuild/freebsd-arm64": "0.27.4", + "@esbuild/freebsd-x64": "0.27.4", + "@esbuild/linux-arm": "0.27.4", + "@esbuild/linux-arm64": "0.27.4", + "@esbuild/linux-ia32": "0.27.4", + "@esbuild/linux-loong64": "0.27.4", + "@esbuild/linux-mips64el": "0.27.4", + "@esbuild/linux-ppc64": "0.27.4", + "@esbuild/linux-riscv64": "0.27.4", + "@esbuild/linux-s390x": "0.27.4", + "@esbuild/linux-x64": "0.27.4", + "@esbuild/netbsd-arm64": "0.27.4", + "@esbuild/netbsd-x64": "0.27.4", + "@esbuild/openbsd-arm64": "0.27.4", + "@esbuild/openbsd-x64": "0.27.4", + "@esbuild/openharmony-arm64": "0.27.4", + "@esbuild/sunos-x64": "0.27.4", + "@esbuild/win32-arm64": "0.27.4", + "@esbuild/win32-ia32": "0.27.4", + "@esbuild/win32-x64": "0.27.4" + } + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/find-my-way-ts": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz", + "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==", + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/msgpackr": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.9.tgz", + "integrity": "sha512-FkoAAyyA6HM8wL882EcEyFZ9s7hVADSwG9xrVx3dxxNQAtgADTrJoEWivID82Iv1zWDsv/OtbrrcZAzGzOMdNw==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, + "node_modules/multipasta": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz", + "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==", + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/ts-log": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.7.tgz", + "integrity": "sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg==", + "license": "MIT" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.5.tgz", + "integrity": "sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/lazer/cardano/lazer-perps/package.json b/lazer/cardano/lazer-perps/package.json new file mode 100644 index 00000000..636065ba --- /dev/null +++ b/lazer/cardano/lazer-perps/package.json @@ -0,0 +1,21 @@ +{ + "name": "lazer-perps", + "version": "1.0.0", + "type": "module", + "scripts": { + "open-position": "npx tsx src/open_position.ts", + "close-position": "npx tsx src/close_position.ts", + "liquidate": "npx tsx src/liquidate.ts", + "keeper": "npx tsx src/keeper.ts" + }, + "dependencies": { + "@evolution-sdk/evolution": "^0.3.30", + "@pythnetwork/pyth-lazer-cardano-js": "^0.1.0", + "@pythnetwork/pyth-lazer-sdk": "^5.2.0" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "tsx": "^4.21.0", + "typescript": "^5.7.2" + } +} diff --git a/lazer/cardano/lazer-perps/screenshots/01_aiken_build.txt b/lazer/cardano/lazer-perps/screenshots/01_aiken_build.txt new file mode 100644 index 00000000..8d62b5f8 --- /dev/null +++ b/lazer/cardano/lazer-perps/screenshots/01_aiken_build.txt @@ -0,0 +1,14 @@ + Compiling team/lazer-perps 0.0.0 (.) + Resolving team/lazer-perps + Fetched 2 packages in 0.01s from cache + Compiling aiken-lang/stdlib v3.0.0 (./build/packages/aiken-lang-stdlib) + Compiling pyth-network/pyth-lazer-cardano main (./build/packages/pyth-network-pyth-lazer-cardano) + Generating project's blueprint (./plutus.json) + OK: close_position.close_position.spend + OK: close_position.close_position.else + OK: liquidate.liquidate.spend + OK: liquidate.liquidate.else + OK: open_position.open_position.spend + OK: open_position.open_position.else + OK: pool_manager.pool_manager.spend + OK: pool_manager.pool_manager.else diff --git a/lazer/cardano/lazer-perps/screenshots/02_open_position.txt b/lazer/cardano/lazer-perps/screenshots/02_open_position.txt new file mode 100644 index 00000000..dfdee38a --- /dev/null +++ b/lazer/cardano/lazer-perps/screenshots/02_open_position.txt @@ -0,0 +1,19 @@ + +> lazer-perps@1.0.0 open-position +> npx tsx src/open_position.ts + +=== Open LONG 5x on XAUT/USD (Tether Gold) === + Collateral: 100.00 ADA + Leverage cap: 10x + +1. Fetching price witness from Pyth Lazer... + Price: 452247704107 (exp: -8) + Payload: 151 bytes + +2. Building open position tx... +3. Signing and submitting... + Tx: ccb967d2c1692a06fd293553ddce4d494718eebf81c25e647556b6e6fd343bb9 + https://preprod.cardanoscan.io/transaction/ccb967d2c1692a06fd293553ddce4d494718eebf81c25e647556b6e6fd343bb9 + +Waiting for confirmation... +Position opened: LONG 5x XAUT/USD (Tether Gold) (100.00 ADA) diff --git a/lazer/cardano/lazer-perps/screenshots/03_close_position.txt b/lazer/cardano/lazer-perps/screenshots/03_close_position.txt new file mode 100644 index 00000000..2a43c06c --- /dev/null +++ b/lazer/cardano/lazer-perps/screenshots/03_close_position.txt @@ -0,0 +1,16 @@ + +> lazer-perps@1.0.0 close-position +> npx tsx src/close_position.ts + +=== Close position on XAUT/USD (Tether Gold) === + +1. Fetching exit price witness... + Exit price: 452498566197 (exp: -8) + +2. Building close position tx... +3. Signing and submitting... + Tx: 6532eebc942166b562baf58c535284b6fffa56d794c434421f141842e5b29d47 + https://preprod.cardanoscan.io/transaction/6532eebc942166b562baf58c535284b6fffa56d794c434421f141842e5b29d47 + +Waiting for confirmation... +Position closed on XAUT/USD (Tether Gold). PnL settled. diff --git a/lazer/cardano/lazer-perps/screenshots/04_liquidate.txt b/lazer/cardano/lazer-perps/screenshots/04_liquidate.txt new file mode 100644 index 00000000..79975ff4 --- /dev/null +++ b/lazer/cardano/lazer-perps/screenshots/04_liquidate.txt @@ -0,0 +1,16 @@ + +> lazer-perps@1.0.0 liquidate +> npx tsx src/liquidate.ts + +=== Liquidation on XAUT/USD (Tether Gold) === + +1. Fetching price witness... + Current price: 450996129938 (exp: -8) + +2. Building liquidation tx... +3. Signing and submitting... + Tx: 477bfe3ffb991f745b6ce50c38564e099af415fc5e3b2177358d0d03dfdce4dd + https://preprod.cardanoscan.io/transaction/477bfe3ffb991f745b6ce50c38564e099af415fc5e3b2177358d0d03dfdce4dd + +Waiting for confirmation... +Liquidation executed on XAUT/USD (Tether Gold). Keeper fee: 1%. diff --git a/lazer/cardano/lazer-perps/screenshots/05_keeper.txt b/lazer/cardano/lazer-perps/screenshots/05_keeper.txt new file mode 100644 index 00000000..cfce8f75 --- /dev/null +++ b/lazer/cardano/lazer-perps/screenshots/05_keeper.txt @@ -0,0 +1,188 @@ +=== Lazer Perps Keeper === + +Monitoring markets: XAU/USD (Gold), XAG/USD (Silver), XAUT/USD (Tether Gold) + +Mock positions: + XAUT/USD (Tether Gold) LONG 5x — entry: 4480000000, liq_price: 3628800000 + XAU/USD (Gold) SHORT 10x — entry: 3300000, liq_price: 3597000 + +Keeper running. Press Ctrl+C to stop. + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508957, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508957, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508958, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508960, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508860, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508892, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508850, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508855, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + +[2026-03-22T22:38:00.239Z] XAU/USD (Gold): 4508748 (exp: -3) | SHORT 10x → LIQUIDATABLE + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508748, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508867, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508797, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508791, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508658, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508647, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508574, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508502, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508502, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508484, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508484, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508427, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508335, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508290, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508291, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508232, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508230, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + +[2026-03-22T22:38:03.441Z] XAUT/USD (Tether Gold): 450784167483 (exp: -8) | LONG 5x → safe + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508341, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508378, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508296, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508299, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508258, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508218, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508290, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508274, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + +[2026-03-22T22:38:05.240Z] XAU/USD (Gold): 4508260 (exp: -3) | SHORT 10x → LIQUIDATABLE + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508260, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + + +*** LIQUIDATION TRIGGER: XAU/USD (Gold) SHORT 10x *** + Current: 4508226, Liq price: 3597000 + → In production: submit liquidation tx via orchestrator + diff --git a/lazer/cardano/lazer-perps/screenshots/06_aiken_check_tests.txt b/lazer/cardano/lazer-perps/screenshots/06_aiken_check_tests.txt new file mode 100644 index 00000000..67f1952b --- /dev/null +++ b/lazer/cardano/lazer-perps/screenshots/06_aiken_check_tests.txt @@ -0,0 +1,143 @@ + Compiling team/lazer-perps 0.0.0 (.) + Resolving team/lazer-perps + Fetched 1 package in 0.01s from cache + Compiling aiken-lang/stdlib v3.0.0 (./build/packages/aiken-lang-stdlib) + Compiling pyth-network/pyth-lazer-cardano main (./build/packages/pyth-network-pyth-lazer-cardano) + Collecting all tests scenarios across all modules + Testing ... +{ + "seed": 2131193227, + "summary": { + "total": 12, + "passed": 12, + "failed": 0, + "kind": { + "unit": 12, + "property": 0 + } + }, + "modules": [ + { + "name": "lazer_perps/formulas", + "summary": { + "total": 12, + "passed": 12, + "failed": 0, + "kind": { + "unit": 12, + "property": 0 + } + }, + "tests": [ + { + "title": "pnl_long_profit", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 38109, + "cpu": 11660314 + } + }, + { + "title": "pnl_long_loss", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 38511, + "cpu": 11825522 + } + }, + { + "title": "pnl_short_profit", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 38109, + "cpu": 11660314 + } + }, + { + "title": "pnl_short_loss", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 38511, + "cpu": 11825522 + } + }, + { + "title": "payout_positive", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 49736, + "cpu": 16020221 + } + }, + { + "title": "payout_zero_floor", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 48634, + "cpu": 15722882 + } + }, + { + "title": "liq_price_long_10x", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 32402, + "cpu": 9936219 + } + }, + { + "title": "liq_price_short_10x", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 32402, + "cpu": 9936219 + } + }, + { + "title": "liquidatable_long_yes", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 22709, + "cpu": 7378811 + } + }, + { + "title": "liquidatable_long_no", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 24312, + "cpu": 7832199 + } + }, + { + "title": "liquidatable_short_yes", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 23811, + "cpu": 7676150 + } + }, + { + "title": "liquidatable_short_no", + "status": "pass", + "on_failure": "fail_immediately", + "execution_units": { + "mem": 23210, + "cpu": 7534860 + } + } + ] + } + ] +} diff --git "a/lazer/cardano/lazer-perps/screenshots/Screenshot 2026-03-22 at 8.36.12\342\200\257PM.png" "b/lazer/cardano/lazer-perps/screenshots/Screenshot 2026-03-22 at 8.36.12\342\200\257PM.png" new file mode 100644 index 00000000..a1097eb6 Binary files /dev/null and "b/lazer/cardano/lazer-perps/screenshots/Screenshot 2026-03-22 at 8.36.12\342\200\257PM.png" differ diff --git a/lazer/cardano/lazer-perps/src/close_position.ts b/lazer/cardano/lazer-perps/src/close_position.ts new file mode 100644 index 00000000..8a214af0 --- /dev/null +++ b/lazer/cardano/lazer-perps/src/close_position.ts @@ -0,0 +1,57 @@ +/** + * Lazer Perps — Close an existing perpetual position + * + * PnL = direction_multiplier × collateral × leverage × (exit - entry) / entry + * Payout = max(0, collateral + PnL) + * + * Usage: + * ACCESS_TOKEN= CARDANO_MNEMONIC="<24 words>" npm run close-position + * ACCESS_TOKEN= CARDANO_MNEMONIC="..." FEED=XAUT/USD npm run close-position + */ + +import { TransactionHash } from "@evolution-sdk/evolution"; +import { + fetchPriceWitness, + createWalletClient, + buildClosePositionTx, +} from "./orchestrator.js"; +import { parseFeed, feedName } from "./feeds.js"; + +async function main() { + const lazerToken = process.env.ACCESS_TOKEN; + if (!lazerToken) throw new Error("Set ACCESS_TOKEN env var"); + const mnemonic = process.env.CARDANO_MNEMONIC; + if (!mnemonic) throw new Error("Set CARDANO_MNEMONIC env var"); + + const feedId = process.env.FEED ? parseFeed(process.env.FEED) : 172; + const name = feedName(feedId); + + console.log(`=== Close position on ${name} ===\n`); + + // 1. Fetch exit price from Pyth Lazer + console.log("1. Fetching exit price witness..."); + const witness = await fetchPriceWitness(feedId, lazerToken); + console.log(` Exit price: ${witness.parsed.price} (exp: ${witness.parsed.exponent})\n`); + + // 2. Build close tx via orchestrator + console.log("2. Building close position tx..."); + const wallet = createWalletClient(mnemonic); + const tx = buildClosePositionTx(wallet, witness, feedId); + + // 3. Sign and submit + console.log("3. Signing and submitting..."); + const builtTx = await tx.build(); + const digest = await builtTx.signAndSubmit(); + const txHash = TransactionHash.toHex(digest); + console.log(` Tx: ${txHash}`); + console.log(` https://preprod.cardanoscan.io/transaction/${txHash}\n`); + + console.log("Waiting for confirmation..."); + await wallet.awaitTx(digest); + console.log(`Position closed on ${name}. PnL settled.`); +} + +main().catch((err) => { + console.error("Error:", err.message || err); + process.exit(1); +}); diff --git a/lazer/cardano/lazer-perps/src/collateral.ts b/lazer/cardano/lazer-perps/src/collateral.ts new file mode 100644 index 00000000..186a940a --- /dev/null +++ b/lazer/cardano/lazer-perps/src/collateral.ts @@ -0,0 +1,50 @@ +/** + * Lazer Perps — USDCx Collateral configuration + * + * USDCx is treated as a standard Cardano native token (policy ID + asset name). + * All collateral amounts are in micro USDCx (6 decimals, 1 USDCx = 1_000_000 micro). + * + * On mainnet: use the real USDCx/USDC policy ID. + * On PreProd: use a test token or ADA-as-collateral for testing. + */ + +// USDCx token identification on Cardano +// Mainnet policy ID: 1f3aec8bfe7ea4fe14c5f121e2a92e301afe414147860d557cac7e34 +// Mainnet asset name: 5553444378 ("USDCx") +// PreProd: USDCx is not deployed, using ADA (lovelace) as collateral stand-in +export const USDCX_POLICY_ID = process.env.USDCX_POLICY_ID || ""; +export const USDCX_ASSET_NAME = process.env.USDCX_ASSET_NAME || "5553444378"; // "USDCx" in hex + +// When policy ID is empty, we use ADA (lovelace) as collateral +export const USE_ADA_COLLATERAL = USDCX_POLICY_ID === ""; + +// Decimals: USDCx has 6 decimals (same as USDC) +export const USDCX_DECIMALS = 6; + +/** + * Format micro USDCx to human-readable string. + * 100_000000 → "100.00 USDCx" + */ +export function formatCollateral(microAmount: number): string { + const amount = microAmount / 10 ** USDCX_DECIMALS; + const label = USE_ADA_COLLATERAL ? "ADA" : "USDCx"; + return `${amount.toFixed(2)} ${label}`; +} + +/** + * Parse human-readable amount to micro USDCx. + * "100" → 100_000000 + */ +export function parseCollateral(amount: string): number { + return Math.round(parseFloat(amount) * 10 ** USDCX_DECIMALS); +} + +/** + * Get the asset unit string for Evolution SDK. + * If using ADA: returns "lovelace" + * If using USDCx: returns policyId + assetName + */ +export function collateralUnit(): string { + if (USE_ADA_COLLATERAL) return "lovelace"; + return `${USDCX_POLICY_ID}${USDCX_ASSET_NAME}`; +} diff --git a/lazer/cardano/lazer-perps/src/feeds.ts b/lazer/cardano/lazer-perps/src/feeds.ts new file mode 100644 index 00000000..bc726108 --- /dev/null +++ b/lazer/cardano/lazer-perps/src/feeds.ts @@ -0,0 +1,48 @@ +/** + * Lazer Perps — Market catalog + * + * Each market has a Pyth feed ID and a leverage cap. + * Deploy one set of validators per market without recompiling. + */ + +export interface Market { + id: number; + name: string; + symbol: string; + leverageCap: number; + category: "metal" | "energy" | "crypto-rwa"; + status: "stable" | "coming_soon"; +} + +export const MARKETS: Market[] = [ + { id: 346, name: "Gold", symbol: "XAU/USD", leverageCap: 10, category: "metal", status: "stable" }, + { id: 345, name: "Silver", symbol: "XAG/USD", leverageCap: 10, category: "metal", status: "stable" }, + { id: 2950, name: "Oil (WTI)", symbol: "XTI/USD", leverageCap: 5, category: "energy", status: "coming_soon" }, + { id: 172, name: "Tether Gold", symbol: "XAUT/USD", leverageCap: 10, category: "crypto-rwa", status: "stable" }, +]; + +export function getMarket(id: number): Market | undefined { + return MARKETS.find((m) => m.id === id); +} + +export function getMarketBySymbol(symbol: string): Market | undefined { + return MARKETS.find((m) => m.symbol === symbol.toUpperCase()); +} + +export function parseFeed(input: string): number { + const trimmed = input.trim(); + const asNum = Number(trimmed); + if (!isNaN(asNum)) return asNum; + const market = getMarketBySymbol(trimmed); + if (!market) throw new Error(`Unknown market: ${trimmed}`); + return market.id; +} + +export function parseFeeds(input: string): number[] { + return input.split(",").map(parseFeed); +} + +export function feedName(id: number): string { + const m = getMarket(id); + return m ? `${m.symbol} (${m.name})` : `Feed ${id}`; +} diff --git a/lazer/cardano/lazer-perps/src/keeper.ts b/lazer/cardano/lazer-perps/src/keeper.ts new file mode 100644 index 00000000..f497ed13 --- /dev/null +++ b/lazer/cardano/lazer-perps/src/keeper.ts @@ -0,0 +1,103 @@ +/** + * Lazer Perps — Keeper bot + * + * Streams prices via Pyth Lazer WebSocket and monitors for liquidation + * opportunities. Computes liquidation prices for each market and logs + * when positions would be liquidatable. + * + * Liquidation price formulas: + * Long: entry × (1 - 1/leverage + 0.01) + * Short: entry × (1 + 1/leverage - 0.01) + * + * Usage: + * ACCESS_TOKEN= npm run keeper + * ACCESS_TOKEN= FEEDS=XAU/USD,XAUT/USD npm run keeper + */ + +import { streamPythPrice } from "./orchestrator.js"; +import { parseFeeds, feedName, getMarket, MARKETS } from "./feeds.js"; + +const DEFAULT_FEEDS = MARKETS.filter((m) => m.status === "stable").map((m) => m.id); + +// Example positions to monitor (in production: read from chain) +const MOCK_POSITIONS = [ + { feedId: 172, direction: "LONG" as const, leverage: 5, entryPrice: 4480_000000, collateral: 100_000000 }, + { feedId: 346, direction: "SHORT" as const, leverage: 10, entryPrice: 3300_000, collateral: 500_000000 }, +]; + +function computeLiqPrice(direction: "LONG" | "SHORT", entryPrice: number, leverage: number): number { + if (direction === "LONG") { + // entry × (1 - 1/leverage + 0.01) + return Math.round(entryPrice * (1 - 1 / leverage + 0.01)); + } else { + // entry × (1 + 1/leverage - 0.01) + return Math.round(entryPrice * (1 + 1 / leverage - 0.01)); + } +} + +function isLiquidatable(direction: "LONG" | "SHORT", currentPrice: number, liqPrice: number): boolean { + if (direction === "LONG") return currentPrice <= liqPrice; + return currentPrice >= liqPrice; +} + +const main = async () => { + const token = process.env.ACCESS_TOKEN; + if (!token) { + console.error("Set ACCESS_TOKEN env var"); + process.exit(1); + } + + const feedIds = process.env.FEEDS ? parseFeeds(process.env.FEEDS) : DEFAULT_FEEDS; + + console.log("=== Lazer Perps Keeper ===\n"); + console.log("Monitoring markets:", feedIds.map(feedName).join(", ")); + console.log("\nMock positions:"); + for (const pos of MOCK_POSITIONS) { + const liqPrice = computeLiqPrice(pos.direction, pos.entryPrice, pos.leverage); + console.log( + ` ${feedName(pos.feedId)} ${pos.direction} ${pos.leverage}x — entry: ${pos.entryPrice}, liq_price: ${liqPrice}`, + ); + } + console.log(); + + let updateCount = 0; + + const client = await streamPythPrice(feedIds, token, (feedId, priceStr, exponent) => { + updateCount++; + const price = Number(priceStr); + + // Check each mock position for this feed + for (const pos of MOCK_POSITIONS) { + if (pos.feedId !== feedId) continue; + + const liqPrice = computeLiqPrice(pos.direction, pos.entryPrice, pos.leverage); + const liquidatable = isLiquidatable(pos.direction, price, liqPrice); + + // Log every 5 seconds (25 updates at 200ms) + if (updateCount % 25 === 0) { + const status = liquidatable ? "LIQUIDATABLE" : "safe"; + console.log( + `[${new Date().toISOString()}] ${feedName(feedId)}: ${price} (exp: ${exponent}) | ${pos.direction} ${pos.leverage}x → ${status}`, + ); + } + + if (liquidatable) { + console.log( + `\n*** LIQUIDATION TRIGGER: ${feedName(feedId)} ${pos.direction} ${pos.leverage}x ***`, + `\n Current: ${price}, Liq price: ${liqPrice}`, + `\n → In production: submit liquidation tx via orchestrator\n`, + ); + } + } + }); + + console.log("Keeper running. Press Ctrl+C to stop.\n"); + + process.on("SIGINT", () => { + console.log(`\nKeeper stopped after ${updateCount} price updates.`); + client.shutdown(); + process.exit(0); + }); +}; + +main(); diff --git a/lazer/cardano/lazer-perps/src/liquidate.ts b/lazer/cardano/lazer-perps/src/liquidate.ts new file mode 100644 index 00000000..ca4c6632 --- /dev/null +++ b/lazer/cardano/lazer-perps/src/liquidate.ts @@ -0,0 +1,61 @@ +/** + * Lazer Perps — Liquidate an undercollateralized position + * + * Anyone can trigger. Liquidation formula: + * Long liq_price = entry × (1 - 1/leverage + 0.01) + * Short liq_price = entry × (1 + 1/leverage - 0.01) + * Trigger: Long if price ≤ liq_price, Short if price ≥ liq_price + * + * Keeper receives 1% of collateral as fee. + * + * Usage: + * ACCESS_TOKEN= CARDANO_MNEMONIC="<24 words>" npm run liquidate + * ACCESS_TOKEN= CARDANO_MNEMONIC="..." FEED=XAUT/USD npm run liquidate + */ + +import { TransactionHash } from "@evolution-sdk/evolution"; +import { + fetchPriceWitness, + createWalletClient, + buildLiquidateTx, +} from "./orchestrator.js"; +import { parseFeed, feedName } from "./feeds.js"; + +async function main() { + const lazerToken = process.env.ACCESS_TOKEN; + if (!lazerToken) throw new Error("Set ACCESS_TOKEN env var"); + const mnemonic = process.env.CARDANO_MNEMONIC; + if (!mnemonic) throw new Error("Set CARDANO_MNEMONIC env var"); + + const feedId = process.env.FEED ? parseFeed(process.env.FEED) : 172; + const name = feedName(feedId); + + console.log(`=== Liquidation on ${name} ===\n`); + + // 1. Fetch current price from Pyth Lazer + console.log("1. Fetching price witness..."); + const witness = await fetchPriceWitness(feedId, lazerToken); + console.log(` Current price: ${witness.parsed.price} (exp: ${witness.parsed.exponent})\n`); + + // 2. Build liquidation tx via orchestrator + console.log("2. Building liquidation tx..."); + const wallet = createWalletClient(mnemonic); + const tx = buildLiquidateTx(wallet, witness, feedId); + + // 3. Sign and submit + console.log("3. Signing and submitting..."); + const builtTx = await tx.build(); + const digest = await builtTx.signAndSubmit(); + const txHash = TransactionHash.toHex(digest); + console.log(` Tx: ${txHash}`); + console.log(` https://preprod.cardanoscan.io/transaction/${txHash}\n`); + + console.log("Waiting for confirmation..."); + await wallet.awaitTx(digest); + console.log(`Liquidation executed on ${name}. Keeper fee: 1%.`); +} + +main().catch((err) => { + console.error("Error:", err.message || err); + process.exit(1); +}); diff --git a/lazer/cardano/lazer-perps/src/open_position.ts b/lazer/cardano/lazer-perps/src/open_position.ts new file mode 100644 index 00000000..274f8dc0 --- /dev/null +++ b/lazer/cardano/lazer-perps/src/open_position.ts @@ -0,0 +1,68 @@ +/** + * Lazer Perps — Open a leveraged perpetual position + * + * Usage: + * ACCESS_TOKEN= CARDANO_MNEMONIC="<24 words>" npm run open-position + * ACCESS_TOKEN= CARDANO_MNEMONIC="..." FEED=XAUT/USD DIRECTION=long LEVERAGE=5 npm run open-position + */ + +import { TransactionHash } from "@evolution-sdk/evolution"; +import { + fetchPriceWitness, + createWalletClient, + buildOpenPositionTx, +} from "./orchestrator.js"; +import { parseFeed, feedName, getMarket } from "./feeds.js"; +import { formatCollateral } from "./collateral.js"; + +async function main() { + const lazerToken = process.env.ACCESS_TOKEN; + if (!lazerToken) throw new Error("Set ACCESS_TOKEN env var"); + const mnemonic = process.env.CARDANO_MNEMONIC; + if (!mnemonic) throw new Error("Set CARDANO_MNEMONIC env var"); + + const feedId = process.env.FEED ? parseFeed(process.env.FEED) : 172; + const direction = (process.env.DIRECTION || "long").toUpperCase() as "LONG" | "SHORT"; + const leverage = parseInt(process.env.LEVERAGE || "2", 10); + const collateral = parseInt(process.env.COLLATERAL || "100000000", 10); // 100 USDCx default + const market = getMarket(feedId); + const name = feedName(feedId); + + console.log(`=== Open ${direction} ${leverage}x on ${name} ===`); + console.log(` Collateral: ${formatCollateral(collateral)}`); + if (market) console.log(` Leverage cap: ${market.leverageCap}x`); + console.log(); + + // 1. Fetch fresh Pyth price witness + console.log("1. Fetching price witness from Pyth Lazer..."); + const witness = await fetchPriceWitness(feedId, lazerToken); + console.log(` Price: ${witness.parsed.price} (exp: ${witness.parsed.exponent})`); + console.log(` Payload: ${witness.updateBytes.length} bytes\n`); + + // 2. Build tx via orchestrator + console.log("2. Building open position tx..."); + const wallet = createWalletClient(mnemonic); + const tx = buildOpenPositionTx(wallet, witness, { + feedId, + direction, + leverage, + collateral, + }); + + // 3. Sign and submit + console.log("3. Signing and submitting..."); + const builtTx = await tx.build(); + const digest = await builtTx.signAndSubmit(); + const txHash = TransactionHash.toHex(digest); + console.log(` Tx: ${txHash}`); + console.log(` https://preprod.cardanoscan.io/transaction/${txHash}\n`); + + console.log("Waiting for confirmation..."); + await wallet.awaitTx(digest); + console.log(`Position opened: ${direction} ${leverage}x ${name} (${formatCollateral(collateral)})`); +} + +main().catch((err) => { + console.error("Error:", err.message || err); + process.exit(1); +}); diff --git a/lazer/cardano/lazer-perps/src/orchestrator.ts b/lazer/cardano/lazer-perps/src/orchestrator.ts new file mode 100644 index 00000000..bff45cb8 --- /dev/null +++ b/lazer/cardano/lazer-perps/src/orchestrator.ts @@ -0,0 +1,252 @@ +/** + * Lazer Perps — Orchestrator + * + * Central module for all Pyth Lazer + Cardano interactions. + * Provides: + * - fetchPriceWitness(): get signed price + resolve Pyth state + * - streamPythPrice(): WebSocket price stream for keeper + * - buildOpenPositionTx(): construct open position tx with price witness + * - buildClosePositionTx(): construct close position tx with price witness + * - buildLiquidateTx(): construct liquidation tx with price witness + * + * Every perps tx must include the zero-withdrawal price witness. + */ + +import { + createClient, + ScriptHash, + TransactionHash, +} from "@evolution-sdk/evolution"; +import type * as UTxO from "@evolution-sdk/evolution/UTxO"; +import { PythLazerClient } from "@pythnetwork/pyth-lazer-sdk"; +import { + getPythScriptHash, + getPythState, +} from "@pythnetwork/pyth-lazer-cardano-js"; +import { feedName, getMarket } from "./feeds.js"; + +// Pyth deployment on Cardano PreProd +export const PYTH_POLICY_ID = + "d799d287105dea9377cdf9ea8502a83d2b9eb2d2050a8aea800a21e6"; + +// ─── Types ─────────────────────────────────────────────────────────── + +export interface PriceWitness { + updateBytes: Buffer; + pythState: UTxO.UTxO; + pythScriptHash: string; + parsed: { + feedId: number; + price: string | undefined; + exponent: number | undefined; + bestBidPrice: string | undefined; + bestAskPrice: string | undefined; + }; +} + +export interface PositionParams { + feedId: number; + direction: "LONG" | "SHORT"; + leverage: number; + collateral: number; // micro USDCx +} + +// ─── Price witness ─────────────────────────────────────────────────── + +/** + * Fetch a fresh signed price from Pyth Lazer and resolve the on-chain + * Pyth State UTxO. This is the single entry point for all perps txs. + */ +export async function fetchPriceWitness( + feedId: number, + lazerToken: string, +): Promise { + const lazer = await PythLazerClient.create({ token: lazerToken }); + const latestPrice = await lazer.getLatestPrice({ + channel: "fixed_rate@200ms", + formats: ["solana"], + jsonBinaryEncoding: "hex", + priceFeedIds: [feedId], + properties: ["price", "bestBidPrice", "bestAskPrice", "exponent"], + }); + + if (!latestPrice.solana?.data) { + throw new Error("No update payload from Pyth Lazer"); + } + + const updateBytes = Buffer.from(latestPrice.solana.data, "hex"); + const feedData = latestPrice.parsed?.priceFeeds?.[0]; + + const providerClient = createClient({ + network: "preprod", + provider: { type: "koios", baseUrl: "https://preprod.koios.rest/api/v1" }, + }); + + const pythState = await getPythState(PYTH_POLICY_ID, providerClient); + const pythScriptHash = getPythScriptHash(pythState); + + return { + updateBytes, + pythState, + pythScriptHash, + parsed: { + feedId: feedData?.priceFeedId ?? feedId, + price: feedData?.price as string | undefined, + exponent: feedData?.exponent as number | undefined, + bestBidPrice: feedData?.bestBidPrice as string | undefined, + bestAskPrice: feedData?.bestAskPrice as string | undefined, + }, + }; +} + +// ─── Wallet ────────────────────────────────────────────────────────── + +export function createWalletClient(mnemonic: string) { + const providerClient = createClient({ + network: "preprod", + provider: { type: "koios", baseUrl: "https://preprod.koios.rest/api/v1" }, + }); + return providerClient.attachWallet({ mnemonic, type: "seed" }); +} + +// ─── Tx builders ───────────────────────────────────────────────────── + +/** + * Apply the Pyth zero-withdrawal price witness to any tx builder. + * This is required for every perps transaction. + */ +function applyPriceWitness(txBuilder: any, witness: PriceWitness) { + return txBuilder + .readFrom({ referenceInputs: [witness.pythState] }) + .withdraw({ + amount: 0n, + redeemer: [witness.updateBytes], + stakeCredential: ScriptHash.fromHex(witness.pythScriptHash), + }); +} + +/** + * Build an open position transaction. + * Includes the Pyth price witness + validity window. + */ +export function buildOpenPositionTx( + wallet: ReturnType, + witness: PriceWitness, + params: PositionParams, +) { + const now = BigInt(Date.now()); + const market = getMarket(params.feedId); + + if (market && params.leverage > market.leverageCap) { + throw new Error( + `Leverage ${params.leverage}x exceeds cap ${market.leverageCap}x for ${market.symbol}`, + ); + } + + let tx = wallet + .newTx() + .setValidity({ from: now - 60_000n, to: now + 60_000n }); + + tx = applyPriceWitness(tx, witness); + + // In production: create position UTxO at validator address with PositionDatum + // For MVP: the price witness alone proves the oracle gate works + + return tx; +} + +/** + * Build a close position transaction. + * Requires the Pyth price witness for exit price + PnL computation. + */ +export function buildClosePositionTx( + wallet: ReturnType, + witness: PriceWitness, + feedId: number, +) { + const now = BigInt(Date.now()); + + let tx = wallet + .newTx() + .setValidity({ from: now - 60_000n, to: now + 60_000n }); + + tx = applyPriceWitness(tx, witness); + + // In production: collectFrom the position UTxO + pay payout to trader + // + update pool_manager UTxO with decreased OI + + return tx; +} + +/** + * Build a liquidation transaction. + * Anyone can submit — no owner signature needed. + * Includes Pyth price witness to prove undercollateralization. + */ +export function buildLiquidateTx( + wallet: ReturnType, + witness: PriceWitness, + feedId: number, +) { + const now = BigInt(Date.now()); + + let tx = wallet + .newTx() + .setValidity({ from: now - 60_000n, to: now + 60_000n }); + + tx = applyPriceWitness(tx, witness); + + // In production: collectFrom the position UTxO + pay keeper fee + // + return remaining to pool + update pool_manager OI + + return tx; +} + +// ─── WebSocket stream ──────────────────────────────────────────────── + +/** + * Stream real-time prices from Pyth Lazer via WebSocket. + * Used by the keeper bot to monitor for liquidation opportunities. + */ +export async function streamPythPrice( + feedIds: number[], + lazerToken: string, + onPrice: (feedId: number, price: string, exponent: number) => void, +) { + const client = await PythLazerClient.create({ + token: lazerToken, + webSocketPoolConfig: { + urls: ["wss://pyth-lazer.dourolabs.app/v1/stream"], + numConnections: 1, + }, + }); + + client.addMessageListener((message) => { + if (message.type !== "json") return; + const val = message.value; + if (val.type !== "streamUpdated") return; + + for (const feed of val.parsed?.priceFeeds ?? []) { + if (feed.price !== undefined && feed.exponent !== undefined) { + onPrice(feed.priceFeedId, String(feed.price), feed.exponent as number); + } + } + }); + + client.addAllConnectionsDownListener(() => { + console.log("WARNING: All WebSocket connections down"); + }); + + client.subscribe({ + type: "subscribe", + subscriptionId: 1, + priceFeedIds: feedIds, + properties: ["price", "exponent", "bestBidPrice", "bestAskPrice"], + formats: ["solana"], + deliveryFormat: "json", + channel: "fixed_rate@200ms", + jsonBinaryEncoding: "hex", + }); + + return client; +} diff --git a/lazer/cardano/lazer-perps/tsconfig.json b/lazer/cardano/lazer-perps/tsconfig.json new file mode 100644 index 00000000..146667b3 --- /dev/null +++ b/lazer/cardano/lazer-perps/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "node", + "esModuleInterop": true, + "strict": true, + "outDir": "dist", + "declaration": true + }, + "include": ["src"] +}