Skip to content

Conversation

thrasher-
Copy link
Collaborator

PR Description

Introduces order status and type unmarshalling and rolls it out across the codebase where possible and some other minor fixes along the way.

Depends on #1948

Type of change

  • New feature (non-breaking change which adds functionality)

How has this been tested

  • go test ./... -race
  • golangci-lint run

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation and regenerated documentation via the documentation tool
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally and on Github Actions with my changes
  • Any dependent changes have been merged and published in downstream modules

@thrasher- thrasher- self-assigned this Jun 26, 2025
@thrasher- thrasher- added the nomerge requires dependency This pull request is dependent on another, so it can't be merged until the dependent one is merged label Jun 26, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR standardizes timestamp parsing by introducing a new DateTime type alongside the existing Time wrapper, and applies these types across the codebase to replace raw numeric/unparse logic. It also streamlines exchange wrappers and WebSocket handlers to use strongly typed fields for order sides, statuses, and times, eliminating repetitive manual parsing.

  • Added DateTime type with JSON unmarshal support and tests.
  • Replaced raw int64/float64 timestamps with types.Time/types.DateTime in exchange models.
  • Simplified wrapper and WS code by using direct .Time() and typed order.Side/order.Type/order.Status fields.

Reviewed Changes

Copilot reviewed 121 out of 121 changed files in this pull request and generated no comments.

Show a summary per file
File Description
types/time.go Added DateTime type and UnmarshalJSON implementation
types/time_test.go New tests for DateTime unmarshalling
exchanges/yobit/yobit_wrapper.go Switched raw timestamps to types.Time and removed manual parsing
exchanges/yobit/yobit_types.go Updated model fields to use types.Time and order.Side
exchanges/order/orders.go Extended StringToOrderSide/Type/Status and JSON hooks
Comments suppressed due to low confidence (2)

types/time.go:86

  • The UnmarshalJSON method uses fmt.Errorf but the fmt package is not imported. Add import "fmt" at the top.
func (d *DateTime) UnmarshalJSON(data []byte) error {

exchanges/order/orders.go:1086

  • The code calls reflect.TypeFor but the reflect package is not imported. Add import "reflect" to this file.
		return &json.UnmarshalTypeError{Value: string(data), Type: reflect.TypeFor[Side](), Offset: 1}

Copy link
Collaborator

@shazbert shazbert left a comment

Choose a reason for hiding this comment

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

Sexy clean. Here have some nits.

CommissionAsset currency.Code `json:"N"`
TransactionTime types.Time `json:"T"`
TradeID int64 `json:"t"`
Ignored int64 `json:"I"` // Must be ignored explicitly, otherwise it overwrites 'i'.
Copy link
Collaborator

Choose a reason for hiding this comment

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

int64 -> json.RawMessage

Ignored int64 `json:"I"` // Must be ignored explicitly, otherwise it overwrites 'i'.
IsOnOrderBook bool `json:"w"`
IsMaker bool `json:"m"`
Ignored2 bool `json:"M"` // See the comment for "I".
Copy link
Collaborator

Choose a reason for hiding this comment

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

bool -> json.RawMessage

CommissionAsset currency.Code `json:"N"`
TransactionTime types.Time `json:"T"`
TradeID int64 `json:"t"`
Ignored int64 `json:"I"` // Must be ignored explicitly, otherwise it overwrites 'i'.
Copy link
Collaborator

Choose a reason for hiding this comment

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

type to json.RawMessage

Ignored int64 `json:"I"` // Must be ignored explicitly, otherwise it overwrites 'i'.
IsOnOrderBook bool `json:"w"`
IsMaker bool `json:"m"`
Ignored2 bool `json:"M"` // See the comment for "I".
Copy link
Collaborator

Choose a reason for hiding this comment

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

type to json.RawMessage

case len(channels) == 5:
// on the “5-item” feed we always treat every push as a snapshot
return d.Websocket.Orderbook.LoadSnapshot(book)

Copy link
Collaborator

Choose a reason for hiding this comment

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

rm spaces between cases

})

case len(channels) == 5:
Copy link
Collaborator

Choose a reason for hiding this comment

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

merge with first case and only allocate orderbook.Book on LoadSnapshot call.

}
asks := buildLevels(ob.Asks)
bids := buildLevels(ob.Bids)
if len(asks) == 0 && len(bids) == 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This happening a lot? If you can check that the LastUpdateID is sequential even when no action has occurred on the books between the update frequency window we can actually load zero values in now.

@thrasher- thrasher- added the reconstructing Based on PR feedback, this is currently being reworked and is not to be merged label Jul 1, 2025
@thrasher- thrasher- removed the nomerge requires dependency This pull request is dependent on another, so it can't be merged until the dependent one is merged label Jul 2, 2025
Copy link

codecov bot commented Jul 2, 2025

Codecov Report

❌ Patch coverage is 41.02142% with 358 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.94%. Comparing base (d5b2cf1) to head (0fb38ca).

Files with missing lines Patch % Lines
exchanges/kucoin/kucoin_wrapper.go 5.26% 36 Missing ⚠️
exchanges/btcmarkets/btcmarkets_wrapper.go 3.03% 32 Missing ⚠️
exchanges/okx/okx_wrapper.go 4.00% 24 Missing ⚠️
exchanges/deribit/deribit_websocket.go 58.92% 16 Missing and 7 partials ⚠️
exchanges/deribit/deribit_wrapper.go 17.85% 23 Missing ⚠️
exchanges/poloniex/poloniex_wrapper.go 0.00% 18 Missing ⚠️
exchanges/binance/binance_wrapper.go 39.28% 17 Missing ⚠️
exchanges/gateio/gateio_wrapper.go 29.16% 17 Missing ⚠️
exchanges/bitmex/bitmex_wrapper.go 11.11% 16 Missing ⚠️
exchanges/btse/btse_wrapper.go 6.66% 14 Missing ⚠️
... and 27 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1957      +/-   ##
==========================================
+ Coverage   39.70%   39.94%   +0.24%     
==========================================
  Files         434      434              
  Lines      171748   170185    -1563     
==========================================
- Hits        68185    67979     -206     
+ Misses      96417    95166    -1251     
+ Partials     7146     7040     -106     
Files with missing lines Coverage Δ
exchanges/binance/binance_types.go 100.00% <ø> (ø)
exchanges/binance/binance_ufutures.go 30.44% <100.00%> (-0.15%) ⬇️
exchanges/binance/cfutures_types.go 100.00% <ø> (ø)
exchanges/binanceus/binanceus_types.go 100.00% <ø> (ø)
exchanges/bitfinex/bitfinex_types.go 90.90% <ø> (ø)
exchanges/bitflyer/bitflyer_types.go 50.00% <ø> (ø)
exchanges/bitflyer/bitflyer_wrapper.go 42.64% <100.00%> (+0.26%) ⬆️
exchanges/bithumb/bithumb_types.go 100.00% <ø> (ø)
exchanges/bitstamp/bitstamp_wrapper.go 56.88% <100.00%> (+0.18%) ⬆️
exchanges/btcmarkets/btcmarkets_types.go 100.00% <ø> (ø)
... and 48 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@gbjk gbjk left a comment

Choose a reason for hiding this comment

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

Nice cleanup! 🎉

A few 🚧 changes, 🐒 nitpicks and 🦍 groomings.

Copy link
Collaborator

@samuael samuael left a comment

Choose a reason for hiding this comment

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

The PR looks grea. just added minor reviews for now

@@ -61,7 +62,7 @@ type TransactionHistory struct {
Data []struct {
ContNumber int64 `json:"cont_no,string"`
TransactionDate types.DateTime `json:"transaction_date"`
Type string `json:"type"`
Side order.Side `json:"type"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this really a side or type?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

"%s GetOrderInfo unable to parse currency pair: %s\n",
e.Name,
err)
}
od.Exchange = e.Name
Copy link
Collaborator

Choose a reason for hiding this comment

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

can't we instantiate this like ```
od = order.Detail{
Exchange: e.Name,
...
}

Amount float64 `json:"amount"`
TradeID int64 `json:"trade_id"`
Date types.Time `json:"date"`
Side order.Side `json:"type"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

side or type??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Side, despite them using type as well 😆

json
{
  "BTC_USD": [
    {
      "order_id": "14",
      "client_id": "100500",
      "created": "1435517311",
      "type": "buy",
      "pair": "BTC_USD",
      "price": "100",
      "quantity": "1",
      "amount": "100"
    }
  ]
}

Timestamp types.Time `json:"dt"`
Type string `json:"type"`
Currency currency.Code `json:"curr"`
Status string `json:"status"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this not order.Status?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nope this one is for wallet transactions

@thrasher- thrasher- added review me This pull request is ready for review and removed reconstructing Based on PR feedback, this is currently being reworked and is not to be merged labels Aug 10, 2025
@thrasher- thrasher- linked an issue Aug 10, 2025 that may be closed by this pull request
Copy link
Collaborator

@gloriousCode gloriousCode left a comment

Choose a reason for hiding this comment

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

What a slog! 😴
Tried to focus on areas where custom functions were used versus straight type replacement occurred.

resp.Status = order.Cancelled
case orderPartiallyCancelled:
resp.Status = order.PartiallyCancelled
case orderFailed:
Copy link
Collaborator

Choose a reason for hiding this comment

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

This and a few other strings here are unused as a result of this change and should be removed

@@ -161,7 +162,7 @@ type TradeHistory struct {
Amount float64 `json:"amount,string"`
Timestamp types.Time `json:"timestamp"`
TimestampMS types.Time `json:"timestampms"`
Type string `json:"type"`
Side order.Side `json:"side"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

@@ -140,7 +141,7 @@ type Order struct {
Exchange string `json:"exchange"`
Price float64 `json:"price,string"`
AvgExecutionPrice float64 `json:"avg_execution_price,string"`
Side string `json:"side"`
Side order.Side `json:"side"`
Type string `json:"type"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

@@ -344,7 +345,7 @@ type wsTrade struct {
Timestamp types.Time `json:"timestamp"`
Price float64 `json:"price,string"`
Quantity float64 `json:"quantity,string"`
Side string `json:"side"`
Side order.Side `json:"side"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure I see this type even present in Gemini api docs


func stringToOrderType(oType string) (order.Type, error) {
switch oType {
case "exchange limit", "auction-only limit", "indication-of-interest limit":
Copy link
Collaborator

Choose a reason for hiding this comment

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

Auction only limit support dropped by this PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

@gloriousCode gloriousCode Aug 20, 2025

Choose a reason for hiding this comment

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

Has the API changed?AUCTION-ONLY LIMIT YOU MAY BE HOLDING DOWN SHIFT TO YELL INTO THE IDE

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah I see now, it needs a -

}
orderType, tif, err := orderTypeFromString(orderDetail.OrderType)

_, tif, err := orderTypeFromString(orderDetail.OrderType.String())
Copy link
Collaborator

@gloriousCode gloriousCode Aug 19, 2025

Choose a reason for hiding this comment

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

Could have changed param to order.Type and calledString() from the func once, instead of 4 times. FAR OUT 😄
Function could be improved further: GetTIFFromOrderType seems better

func setOrderTypeAndSide(rawOrderType string, origSide order.Side, d *order.Detail) error {
var err error
if origSide == order.UnknownSide {
d.Side, err = stringToOrderSide(rawOrderType)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like a typo, therefore you should add a test for this function

@thrasher- thrasher- requested a review from cranktakular August 19, 2025 06:07
@thrasher- thrasher- added reconstructing Based on PR feedback, this is currently being reworked and is not to be merged and removed review me This pull request is ready for review labels Aug 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reconstructing Based on PR feedback, this is currently being reworked and is not to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bithumb: Add zero filter for orderbook amount
5 participants