Skip to content

Conversation

@karamble
Copy link
Member

@karamble karamble commented Oct 9, 2025

go mod tidy adds protobuf dependency for websocket data parsing of mexc websocket market data api

@karamble karamble force-pushed the mexc-adapter branch 3 times, most recently from bdbd182 to ce2efe5 Compare October 23, 2025 15:44
@karamble
Copy link
Member Author

Depends on: #3354

Comment on lines 269 to 273
if syncChan != nil {
close(syncChan)
}
syncChan = make(chan struct{})
b.syncChan = syncChan
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of syncChan is different than binance. It doesn't seem to be used at all. I guess can remove it?

Comment on lines 290 to 293
// MEXC protobuf doesn't provide sequence IDs, accept all updates after sync.
if !acceptedUpdate {
acceptedUpdate = true
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

acceptedUpdate doesn't seem to do anything. Can remove I think.

defer syncMtx.Unlock()
syncCache = make([]*mxctypes.BookUpdate, 0)
acceptedUpdate = false
if updateID != updateIDUnsynced {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like updateID isn't necessary. The value is never used except to see if it's unsynced. Can just check and swap b.synced I think.

Comment on lines +300 to +281
// MEXC sends full snapshots; clear stale data before applying.
b.book.clear()
b.book.update(bids, asks)
return true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, you don't need a syncCache?

b.book.clear()
b.book.update(bids, asks)

return processSyncCache(snapshot.LastUpdateID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If snapshot, err := b.getSnapshot() worked, does that not mean that processing the cache would replace everything with older info? We only want the latest snapshot? We don't need the old snapshots or a cache at all do we?

}
}()

// Market WS connection is deferred until first SubscribeMarket call
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

binance does this but mexc does not.

Comment on lines 2220 to 2203
minNotionalStr := m.getFilterValue(symbol, "MIN_NOTIONAL")
if minNotionalStr == "" {
return true
}
minNotional, err := strconv.ParseFloat(minNotionalStr, 64)
if err != nil {
return true
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this sometimes not there? Can you log the error if ParseFloat fails? Seems like that would be false as well?

Comment on lines 2211 to 2189
stepSize, err := strconv.ParseFloat(stepSizeStr, 64)
if err != nil {
return qty
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is good to ignore the error. It cannot work correctly if there is error.

Copy link
Member

@JoeGruffins JoeGruffins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing some of the issues, still unsure about one. Left another comment inline.

Comment on lines 291 to 296
// Process all cached updates received during sync
for _, update := range syncCache {
if !acceptUpdate(update) {
return false
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may not be understanding correctly, but if every update has the whole book, then processing the syncCache is not necessary and worse than that it will replace the newest book with one that is older. Am I misunderstanding how it works? Binance gives us diffs, but mexc will give us the entire state?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, we subscribe to the MEXC market websocket for the orderbook with depth@20. The websocket sends the entire state, not a diff. BUT on initialization, we use the REST api for the initial snapshot.

Initial Sync:

  1. Subscribe to websocket
  2. Websocket updates start arriving → CACHED (not applied yet)
  3. Fetch REST snapshot (223 bids, 314 asks)
  4. Apply REST snapshot to orderbook
  5. Process cache: Apply any websocket updates received during step 3
  6. Mark as synced
  7. Result: Orderbook has top 20 levels (from most recent websocket snapshot)

Post-Sync:

  1. Websocket update arrives (20 bids, 20 asks)
  2. Clear orderbook
  3. Apply update immediately
  4. Result: Orderbook always has top 20 levels from latest websocket snapshot

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an update happens while fetching the snapshot? A snapshot is saved in the cache if not synced. So, it could be older than that if unsynced for a while.

I still think I understand, and if I do we don't need a cache, and if we do it only needs to be one snapshot, the latest. If the cache is being used ONLY in the case where an update comes in while we are processing the snapshot we asked for, then we should use something else. The new update should just wait to be applied.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the processing logic can be simplified like this JoeGruffins@c9086d2
The updateQueue should be all we need to process updates in order. UNTESTED

Comment on lines 254 to 255
if b.synced.Load() {
b.synced.Store(false)
Copy link
Member

@JoeGruffins JoeGruffins Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be atomic using "Swap", currently it is not really as there is a gap between checking and setting. https://pkg.go.dev/sync/atomic#Bool.Swap

go tidy adds protobuf dependency for websocket data parsing of mexc api
@JoeGruffins JoeGruffins merged commit dd7febe into decred:master Nov 6, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants