<feed xmlns='http://www.w3.org/2005/Atom'>
<title>guess-market/service, branch master</title>
<subtitle>definitely not polymarket
</subtitle>
<id>https://git.sartin.in/guess-market/atom?h=master</id>
<link rel='self' href='https://git.sartin.in/guess-market/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/'/>
<updated>2026-09-10T08:55:50Z</updated>
<entry>
<title>tests: cover the ex-2 loader, order book trading and desktop state</title>
<updated>2026-09-10T08:55:50Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-09-10T08:55:50Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=1a8b75f96f0c6855581be3a38069f09eca37d1f5'/>
<id>urn:sha1:1a8b75f96f0c6855581be3a38069f09eca37d1f5</id>
<content type='text'>
Add tests for the behaviour introduced in the last few commits, so
later changes to matching, settlement or the UI state can't quietly
break it.

On the service side, Ex2LoaderTest loads the ex-2 fixtures and checks
that every invalid file is rejected for its own reason, including
events with no market maker or two of them, and v1 files. The order
book tests cover buys and sells that match or rest in the ladder,
self-trade prevention, cash and shares reserved by resting orders,
price bounds, risk rejections, and resolution cancelling resting
orders and paying the holders. A simulation checks that LMSR
settlement conserves money.

LedgerMapperTest used to pin the unmapped seq and at fields to their
defaults. Now that the mapper fills them from the entry id and time,
assert the real values and add a case for a null time.

On the desktop side, AppStateTest drives the real ServiceEngine through
loading, event creation, LMSR and order book trading, and checks that
the observable state updates. Smaller tests check chart timestamps,
money and probability formatting, and that every animation settles on
its final frame, which is what the UI shows when animations are off.
</content>
</entry>
<entry>
<title>service: add sell orders, event lifecycle and order book matching</title>
<updated>2026-09-07T13:03:14Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-09-07T13:03:14Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=8d7cecd9cf9fb2b0b45607b8efd7ca8f19a89fc6'/>
<id>urn:sha1:8d7cecd9cf9fb2b0b45607b8efd7ca8f19a89fc6</id>
<content type='text'>
Carry the order side from the context through risk, the trading
mechanisms, fulfillment and settlement, so users can sell shares as
well as buy them.

The order book now matches priced limit orders from named users, rests
any unfilled remainder, and prevents self-trades. In a binary market
with minting enabled, a buy can also match a bid on the other option
to mint a new YES/NO pair, and a sell can match an ask there to merge
a pair back into the pool. LMSR gains a sell that refunds the cost
difference from the pool.

Add createEvent and openEvent to the catalog. Events start as DRAFT and
only take the market maker's subsidy when they are opened, which fails
if the market maker can't cover it. Add LocalAccountContext to expose
user ledgers.

Tighten the risk checks: reject orders from blocked accounts, on events
that aren't ACTIVE, and at prices outside (0, d). Sells need enough
unreserved shares; buys need enough balance to cover commission and
cash already committed to resting bids.

Settlement now cancels resting orders, pays out on shares still held
rather than shares ever bought, sends order book commission to the
market maker, and returns unused LMSR subsidy. Events also track
per-user cash flow, so the event detail can list participants with
their holdings, fees and P&amp;L next to the order books.
</content>
</entry>
<entry>
<title>service: add ex-2 XML loader and carry order side through matching</title>
<updated>2026-09-06T12:42:59Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-09-06T12:42:59Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=1cf436ccd3efd45d67749102363b9a7f0d242c54'/>
<id>urn:sha1:1cf436ccd3efd45d67749102363b9a7f0d242c54</id>
<content type='text'>
Ex-2 documents declare users and their market-maker assignments next
to the events, and the loader has to reject files that are
schema-valid but logically inconsistent, which the v1 loader has no
notion of.

Add XMLLoaderV2, which checks the extension, unmarshals the document,
runs it through XMLValidatorV2 and only then replaces the event and
user repositories, so a rejected file leaves the previous catalog
intact. The validator enforces unique positive event ids, non-empty
names and descriptions, commission within 0..90 with a known type, at
least two distinct options, a positive LMSR b or order-book d with
non-negative initial inventory, unique user names, positive initial
cash, and exactly one existing event per market-maker reference. Let
EventMapperV2 take the resolved market maker's name so it lands on the
domain event.

Give Order a side and the placing user, and Trade the seller, so an
order book can match a buyer against a seller. Keep the previous
constructors, defaulting to a BUY with no user or seller, so existing
LMSR call sites stay unchanged. Route LocalMatchingEngine through the
mechanism's placeOrder with side, user and limit price instead of
buy(), and have cancelOrder take the order to cancel.

Also add an isBlocked query to User and Ledger for accounts that went
negative.
</content>
</entry>
<entry>
<title>ex-2: add invalid-input fixtures and wire ui-desktop to the service</title>
<updated>2026-09-06T07:36:54Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-09-06T07:36:54Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=508898f52c16cc737bc7d08b8ee4c29fab8d1146'/>
<id>urn:sha1:508898f52c16cc737bc7d08b8ee4c29fab8d1146</id>
<content type='text'>
The ex-2 loader has to reject documents that are schema-valid but
logically broken, and so far only error-2.xml and error-3.xml exercised
that path. Add one fixture per validation rule under
test-data/ex-2/invalid, each a copy of small.xml with a single defect
described in a leading comment: a non-.xml extension, a duplicate event
id, commission outside 0..90 on either side, a duplicate user name,
zero or negative initial cash, a market maker referencing an unknown
event, and an event with no market maker or with two.

Teach LedgerMapper to map individual LedgerEntry records to
LedgerEntryDTO, renaming id to seq and time to at and rendering the
timestamp through InstantOptions.humanize, so callers can show a ledger
history rather than only the account summary.

Make ui-desktop depend on api and service in the build tooling and in
its Eclipse classpath, since the desktop UI now talks to the service
layer directly, and put lib/openjfx on java.library.path for the test
run so tests touching JavaFX can load its native libraries.
</content>
</entry>
<entry>
<title>catalog: add generated v3 JAXB binding and ex-2 test data</title>
<updated>2026-09-06T06:21:37Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-09-06T06:21:37Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=da82f3b492c3cd36f2e8723632a63a6cc1f4e39b'/>
<id>urn:sha1:da82f3b492c3cd36f2e8723632a63a6cc1f4e39b</id>
<content type='text'>
The ex-2 schema describes a nested Guess-Market/GM-events document in
which every event carries its pricing mechanism inline, as either a
GM-LMSR element holding the liquidity parameter b or a GM-order-book
element holding the allow-mint, initial and d attributes, instead of
naming a mechanism and passing its parameters separately.

Add the xjc-generated classes for that schema under catalog.model.v3,
along with the fixtures the loader will be tested against: small.xml
with two events, one per mechanism, multiple.xml with four, and two
negative cases -- error-2.xml, where a market maker is funded with
zero initial cash, and error-3.xml, where a market maker points at
event id 12, which no event declares -- so the cross-reference and
funding checks have something to reject.

The binding covers the GM-events subtree only. The GM-users half of
the document and the per-event id element are not bound yet, so
nothing reads these classes so far.
</content>
</entry>
<entry>
<title>model: relocate market DTOs out of the flat api package</title>
<updated>2026-08-23T14:05:29Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-08-23T14:05:29Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=843820ea9f357220d69f3795f3289ee41eed355c'/>
<id>urn:sha1:843820ea9f357220d69f3795f3289ee41eed355c</id>
<content type='text'>
Move AccountDTO/MarketDTO/MarketStateDTO/PurchaseReceiptDTO/TradeRowDTO
out of the catch-all api package into model.market (and LedgerDTO into
model.ledger), matching the existing model.event convention so DTOs
live next to the domain they describe rather than in the interface
package. Relocate LedgerMapper from mapper.v2 to infrastructure.adapter
to match the module's established package layout, and update all call
sites and imports accordingly.

Also register the ui-desktop module in the build tooling: add it to
MODULES, add openjfx to the shipped runtime libs, and generalize
package.sh so each executable module (ui-console, ui-desktop) gets its
own Main-Class/Class-Path manifest and run script instead of
special-casing ui-console. Fold long Class-Path manifest lines at 72
bytes per the JAR spec, since adding ui-desktop's dependencies pushed
the line past the limit.
</content>
</entry>
<entry>
<title>Add MapStruct LedgerMapper and wire annotation processing into build.sh</title>
<updated>2026-08-20T14:39:50Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-08-20T14:39:50Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=fbfd2e275e9d645e4ec8a1874bc57d98b1c38300'/>
<id>urn:sha1:fbfd2e275e9d645e4ec8a1874bc57d98b1c38300</id>
<content type='text'>
build.sh now passes -processorpath/-s so MapStruct's generated impl
compiles alongside hand-written sources.
</content>
</entry>
<entry>
<title>Move CommissionTiming and MechanismType into model.event package</title>
<updated>2026-08-20T09:09:20Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-08-20T09:09:20Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=0fc488c3f9e29f5e9f1092f8081714c9e820f178'/>
<id>urn:sha1:0fc488c3f9e29f5e9f1092f8081714c9e820f178</id>
<content type='text'>
Groups them with the other event-domain enums instead of the general
api package, and updates all call sites accordingly.
</content>
</entry>
<entry>
<title>Add MapStruct jars to service module</title>
<updated>2026-08-20T08:27:49Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-08-20T08:27:49Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=5f5236af81b4a9f286e927bc9e36226e1ba05b70'/>
<id>urn:sha1:5f5236af81b4a9f286e927bc9e36226e1ba05b70</id>
<content type='text'>
lib/*/*.jar is auto-globbed onto the build classpath, so this makes
mapstruct available for future DTO&lt;-&gt;domain mappers without any build
script changes.
</content>
</entry>
<entry>
<title>Break down purchase receipts by cost/commission, harden XML validation and state I/O</title>
<updated>2026-08-18T15:19:50Z</updated>
<author>
<name>Kostya</name>
<email>mail@sartin.in</email>
</author>
<published>2026-08-18T15:19:50Z</published>
<link rel='alternate' type='text/html' href='https://git.sartin.in/guess-market/commit/?id=755d2265054e5140e82d322681566c3034583c95'/>
<id>urn:sha1:755d2265054e5140e82d322681566c3034583c95</id>
<content type='text'>
Adds a full pre-load validation pass for GM XML seeds (ids, names,
options, commission, LMSR liquidity), replaces IO.print with
System.out, and surfaces detailed error messages across load/save
commands instead of generic failures.
</content>
</entry>
</feed>
