Skip to main content

Monaco Protocol SDK v1.0.99

This release reports on every order the Monaco fee rates fixed when it was placed, adds a public fee schedule read, fixes each order’s rates at placement for every fill, caps a maker rebate at the taker fee of the same fill, and serves WebSocket connections with permessage-deflate compression. Action item: if your application’s allowed origin list is empty, have your origins added to it, or browser sign-in from your app is refused with 403. Nothing else needs action: the order fields are optional additions, the schedule read is new, and compression is negotiated by the client automatically.

Changed

An order’s fee rates are fixed when it is placed

An order’s Monaco maker and taker rates are fixed when it is placed and charged when it fills, however long it rests. A tier change applies to orders placed after it takes effect, never to orders already resting. A replace is a new placement and takes your current tier. A maker rebate on a fill is never larger than the Monaco taker fee on that fill. When a maker’s rebate rate exceeds the taker’s fee rate, the maker is credited the taker’s rate. A positive maker rate is unchanged. See Fees.

An application with no allowed origins refuses browser sign-in

Sign-in for an application whose allowed origin list is empty now refuses a request that carries an Origin header with 403 Origin not allowed, instead of allowing every origin. A request with no Origin header is not origin-checked, as before. A list containing "*" still allows every origin. Check your list with sdk.applications.getApplicationConfig() (allowedOrigins); if it is empty and your app signs in from a browser, ask the Monaco team to add your origins.

Added

Placement fee rates on orders

Orders carry placementTakerFeeBps and placementMakerFeeBps: the Monaco taker and maker fee rates fixed when the order was placed, re-fixed on replace, in basis points as decimal strings ("4.5", "-0.1"). A negative maker rate is a rebate. They are on the REST order row (sdk.trading.getOrder; GET /api/v1/orders/{orderId}; gRPC OrdersService.GetOrder), on order lists (sdk.trading.getPaginatedOrders; GET /api/v1/orders), on every order WebSocket event, where a maker fill carries the maker order’s own rates, and on orders snapshot rows. Both are absent, never "0", for an order placed before rates were stored. useUserOrders carries them too. See Order lifecycle and WebSockets.

Public fee schedule

sdk.fees.getFeeSchedule(tradingPairId) (GET /api/v1/fees/schedule?tradingPairId=; gRPC FeesService.GetFeeSchedule) returns a trading pair’s Monaco fee tiers without authentication, so it works before sign-in. Each FeeTierScheduleRow has tierLevel, the weighted 14-day volume threshold minVolumeThreshold, and makerFeeBps and takerFeeBps in basis points as decimal strings, ordered by tier level. A malformed tradingPairId is REST 400 / gRPC InvalidArgument, and an unknown pair is 404 / NotFound. Your own tier and rate still come from sdk.fees.getMyFeeTier. useFees adds getFeeSchedule, and the MCP server adds the get_fee_schedule tool. See Fees and Trading.

WebSocket compression

The WebSocket server supports the standard permessage-deflate extension. Browsers and most WebSocket clients, including Node.js, Bun and the ws package, offer it automatically, so frames arrive compressed and are decompressed before your code sees them. Messages are the same JSON either way, and a client that does not offer the extension receives uncompressed frames. Inbound limits count a compressed message at its uncompressed size, or at its compressed size when that is larger. See WebSocket reference.

Upgrade