feat(sdk): LMSR pool admin adjust/close with review fixes#55
feat(sdk): LMSR pool admin adjust/close with review fixes#55
Conversation
Store limit order creation metadata (txid, market_id, direction_label, offered_amount) in SQLite so the wallet can label order-creation transactions instead of showing them as generic sends. - Add migration for 4 new nullable columns on maker_orders - Extend MakerOrderInfo, schema, models, and conversions - Add record_order_creation() store method - Persist order to store after on-chain creation in create_limit_order - Add list_own_orders Tauri command returning OwnOrderSummary - Frontend: fetch own orders on unlock/create/cancel, build txid->label map, render amber badges on limit order transactions in wallet activity Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds end-to-end LMSR pool admin transitions (adjust/close) to the Rust SDK + Tauri layer, and wires new UI capabilities around limit orders, pool listing/scanning, and price-history-driven charting.
Changes:
- Implement LMSR pool admin adjust/close in the SDK with full Simplicity witness + evaluator validation and regtest coverage.
- Add limit order create/cancel + order fetching, and persist “own order” metadata for wallet/tx labeling.
- Introduce pool store queries + price history plumbing, and update UI to show orderbook, user orders/pools, and chart from history.
Reviewed changes
Copilot reviewed 47 out of 49 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/market.ts | Remove synthetic depth; add full orderbook helper |
| src/types.ts | Add limit-order + LMSR pool + price history types |
| src/state.ts | Add UI state for orders/pools/history + market-maker mode |
| src/services/pools.ts | Add Tauri invocations for LMSR pool operations + history |
| src/services/markets.ts | Add order fetch/create/cancel + preserve per-market cached data |
| src/main.ts | Background load of orders/pools/history during navigation/boot |
| src/lifecycle/subscriptions.ts | Refresh orders on discovery events with in-flight coalescing |
| src/handlers/click.ts | Wire UI actions for limit orders + market-maker toggles |
| src/components/wallet/unlocked.ts | Show user limit orders + pools; add tx labeling map |
| src/components/wallet/activity.ts | Render tx rows with limit-order badge/links |
| src/components/shell.ts | Gate “My Markets” behind market-maker mode; add toggle UI |
| src/components/market-chart.ts | Prefer chart series from stored price history |
| src/components/home.ts | Gate “Create New Market” behind market-maker mode |
| src/components/detail.ts | Add market/limit order selector; show full orderbook + pools panel |
| src/components/chart-series.ts | Build chart series from price history entries |
| src/actions.ts | Add pool-create action IDs |
| src-tauri/tauri.conf.json | Update Tauri app identifier |
| src-tauri/src/lib.rs | Register new Tauri commands (orders + pools) |
| src-tauri/src/discovery.rs | Export DiscoveredOrder from SDK into Tauri layer |
| src-tauri/src/commands.rs | Implement fetch/create/cancel/list orders; pool list/scan/history; stubs for adjust/close |
| src-tauri/src/chain_adapter.rs | Improve irreversible confirmation lookup + header-hash derivation |
| src-tauri/crates/deadcat-sdk/tests/maker_order.rs | Fix test outpoints; add combined-UTXO coverage |
| src-tauri/crates/deadcat-sdk/tests/lmsr_pool.rs | Add regtest admin adjust tests + genesis override setup |
| src-tauri/crates/deadcat-sdk/src/sdk.rs | Implement pool admin adjust/close + genesis override; combined-UTXO order creation |
| src-tauri/crates/deadcat-sdk/src/node.rs | Add scan_for_adjust + adjust/close wrappers; expose genesis/admin pubkey helpers |
| src-tauri/crates/deadcat-sdk/src/network.rs | Add “simplicity byte-order” genesis helper |
| src-tauri/crates/deadcat-sdk/src/maker_order/pset/create_order.rs | Support combined funding+fee UTXO path + tests |
| src-tauri/crates/deadcat-sdk/src/lmsr_pool/table.rs | Add LMSR table generation utility + tests |
| src-tauri/crates/deadcat-sdk/src/lmsr_pool/mod.rs | Gate C evaluator module behind testing feature |
| src-tauri/crates/deadcat-sdk/src/lmsr_pool/c_eval.rs | Add corrected C evaluator FFI pipeline |
| src-tauri/crates/deadcat-sdk/src/lmsr_pool/assembly.rs | Add genesis param; BitMachine + C evaluator checks during witness attach |
| src-tauri/crates/deadcat-sdk/src/lmsr_pool/api.rs | Add Adjust/Close request/response API types |
| src-tauri/crates/deadcat-sdk/src/lib.rs | Re-export new LMSR APIs + table generator |
| src-tauri/crates/deadcat-sdk/src/chain.rs | Add chain backend genesis hash API |
| src-tauri/crates/deadcat-sdk/docs/simplicity-test-methodology.md | Document Simplicity evaluation tiers/testing guidance |
| src-tauri/crates/deadcat-sdk/docs/lmsr-admin-adjust-testing.md | Document admin-adjust bugs/fixes + methodology |
| src-tauri/crates/deadcat-sdk/deadcat-store/src/store.rs | Add pool + price history storage/query + order creation metadata |
| src-tauri/crates/deadcat-sdk/deadcat-store/src/schema.rs | Extend maker_orders schema with creation metadata fields |
| src-tauri/crates/deadcat-sdk/deadcat-store/src/models/maker_order.rs | Add new maker order fields to models |
| src-tauri/crates/deadcat-sdk/deadcat-store/src/lib.rs | Re-export new store types (pools/history) |
| src-tauri/crates/deadcat-sdk/deadcat-store/src/conversions.rs | Populate new maker order fields in conversions |
| src-tauri/crates/deadcat-sdk/deadcat-store/migrations/2026-03-20-000001_create_price_history/up.sql | Add price history table/indexes |
| src-tauri/crates/deadcat-sdk/deadcat-store/migrations/2026-03-20-000001_create_price_history/down.sql | Drop price history table |
| src-tauri/crates/deadcat-sdk/deadcat-store/migrations/2026-03-19-000001_add_order_creation_fields/up.sql | Add maker order creation metadata columns |
| src-tauri/crates/deadcat-sdk/deadcat-store/migrations/2026-03-19-000001_add_order_creation_fields/down.sql | Document SQLite drop-column no-op |
| src-tauri/crates/deadcat-sdk/Cargo.toml | Enable testing feature for simplicity-sys test-utils |
| src-tauri/Cargo.toml | Patch simplicity-lang/simplicity-sys to specific upstream rev |
| .gitignore | Keep SDK docs while ignoring root docs drafts |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (isLimitOrder) { | ||
| const badgeContent = escapeHtml(orderInfo.label); | ||
| if (orderInfo.marketId) { | ||
| label = | ||
| '<button data-open-market="' + | ||
| escapeAttr(orderInfo.marketId) + | ||
| '" class="rounded bg-amber-500/20 px-1.5 py-0.5 text-[10px] font-medium text-amber-300 hover:bg-amber-500/30 transition cursor-pointer">' + | ||
| badgeContent + | ||
| "</button>"; |
There was a problem hiding this comment.
The limit-order transaction label uses data-open-market with orderInfo.marketId, but data-open-market is expected to be the UI/internal market id (see existing creationTxToMarket mapping). OwnOrderSummary.market_id appears to be the canonical 32-byte market_id hex, so clicking the badge likely won’t open the market. Consider storing/using the internal market id here (e.g., resolve market_id -> Market.id before building orderTxLabel).
| // Convert history entries to timestamped probability values | ||
| const historyPoints = history | ||
| .map((entry) => ({ | ||
| time: new Date(entry.recorded_at).getTime(), | ||
| probability: Math.max(0.02, Math.min(0.98, entry.implied_yes_price_bps / 10000)), | ||
| })) | ||
| .filter((p) => p.time >= startTime.getTime() && p.time <= endTime.getTime()) | ||
| .sort((a, b) => a.time - b.time); |
There was a problem hiding this comment.
new Date(entry.recorded_at) is parsing a SQLite datetime('now') string (typically YYYY-MM-DD HH:MM:SS), which is not reliably parseable across browsers/environments and can be interpreted in local time. Consider returning RFC3339/ISO-8601 timestamps from the backend (or normalizing to YYYY-MM-DDTHH:MM:SSZ before parsing) to avoid chart time skew/NaN dates.
| // Fetch limit orders for the selected market in the background | ||
| fetchOrders(market.marketId).then((orders) => { | ||
| mergeOrdersIntoMarket(market.marketId, orders); | ||
| render(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
These background fetchOrders(...) calls don’t have a .catch(...) handler. If the invoke fails (e.g., Tauri not ready / relay unreachable), this can produce unhandled promise rejections. Consider adding .catch(...) (or using void + try/catch in an async IIFE) to keep the app resilient.
| let params: deadcat_sdk::PredictionMarketParams = | ||
| serde_json::from_str(&request.contract_params_json) | ||
| .map_err(|e| format!("invalid contract params: {e}"))?; | ||
| let side = parse_trade_side(&request.side)?; | ||
| let direction = parse_trade_direction(&request.direction)?; | ||
|
|
||
| let base_asset_id = match side { | ||
| deadcat_sdk::TradeSide::Yes => params.yes_token_asset, | ||
| deadcat_sdk::TradeSide::No => params.no_token_asset, | ||
| }; | ||
| let quote_asset_id = params.collateral_asset_id; | ||
|
|
There was a problem hiding this comment.
create_limit_order trusts request.market_id for labeling/persistence, but it’s not validated against the canonical market_id derived from contract_params_json (i.e., PredictionMarketParams::market_id()). A mismatched market_id would silently mislabel the order in the local store/UI. Consider validating equality and returning an error on mismatch.
7ad97f0 to
f35ab2f
Compare
Implement AdminAdjust and Close transitions for LMSR pools, fixing 20 issues from the initial LMSR pool implementation review. SDK: - adjust_lmsr_pool / close_lmsr_pool with locator-based params (no redundant pool_params field) - Reserve-value consistency validation (UTXO values must match declared reserves) - Per-asset wallet-input change with correct PSET-indexed blinding - Fee absorption from explicit collateral surplus for decrease path - Admin signature with chain genesis hash (not hardcoded LWK constant) - set_chain_genesis_hash / chain_genesis_hash for regtest support - attach_lmsr_pool_witnesses takes genesis_hash parameter (was all-zeros) - scan_for_adjust / pool_admin_pubkey on DeadcatNode - generate_lmsr_table: q_step_lots > 0 validation, depth-20 comment - Import ordering, dead code removal Store: - #[derive(Debug)] on PriceTransitionInput - Parameterized LIMIT binding (was format! string interpolation) - 8 new tests for list_lmsr_pools and price history Tauri: - scan_lmsr_pool initial outpoints from creation_txid:0/1/2 (was current reserve outpoints) - adjust_lmsr_pool / close_lmsr_pool stub commands - ScanLmsrPoolResponse TS type fix Frontend: - Price history chart integration (buildChartFromHistory) - Pool UI scaffolding, poolsLoading removal Tests (256 SDK unit + 13 store + 6 integration): - BitMachine execution for swap primary and both secondary inputs - C evaluator (corrected FFI) for admin adjust - PSET structure verification for decrease path - Close reclaimed amounts - Regtest: admin adjust increase (blinding) and decrease (fee absorption) Dependencies: - Pin simplicity-lang/sys to upstream post-PR-#348 (value bit corruption) - simplicity-sys optional dep with test-utils for C evaluator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f35ab2f to
43572e9
Compare
Summary
Implements AdminAdjust and Close transitions for LMSR pools, fixing 20 issues from the initial LMSR pool implementation review. Includes the full Simplicity witness pipeline (signature computation, witness satisfaction, C evaluator verification) tested end-to-end on regtest.
Key changes
set_chain_genesis_hash) instead of LWK's hardcoded constant, which doesn't match on regtestattach_lmsr_pool_witnessesgenesis hash parameter — was hardcoded toall_zeros, breaking any path that hashesgenesis_block_hash()explicitly#[derive(Debug)]onPriceTransitionInputscan_lmsr_poolinitial outpoints fromcreation_txid:0/1/2,ScanLmsrPoolResponsetype, adjust/close stub commandsc_eval.rsprovides a corrected FFI binding forsimplicity-sys'sevalTCOExpression(upstream has a missingminCostparameter, reported in rust-simplicity#355)simplicity-lang/simplicity-syspinned to upstream master post-PR #348 (value bit corruption fix)Test plan
Docs
docs/lmsr-admin-adjust-testing.md— testing design decisions and the four bugs found during implementationdocs/simplicity-test-methodology.md— when to use BitMachine unit tests vs C evaluator vs regtest integration tests🤖 Generated with Claude Code