Skip to content

Commit f030a0d

Browse files
committed
pkg/exchange: add more tests to place order
1 parent 38a155d commit f030a0d

4 files changed

+347
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"code":"00000",
3+
"msg":"success",
4+
"requestTime":1709649001209,
5+
"data":[
6+
{
7+
"userId":"8672173294",
8+
"symbol":"BTCUSDT",
9+
"orderId":"1148903850645331968",
10+
"clientOid":"684a79df-f931-474f-a9a5-f1deab1cd770",
11+
"price":"0",
12+
"size":"6.0000000000000000",
13+
"orderType":"market",
14+
"side":"buy",
15+
"status":"filled",
16+
"priceAvg":"67360.8700000000000000",
17+
"baseVolume":"0.0000890000000000",
18+
"quoteVolume":"5.9951174300000000",
19+
"enterPointSource":"API",
20+
"feeDetail":"{\"BTC\":{\"deduction\":false,\"feeCoinCode\":\"BTC\",\"totalDeductionFee\":0,\"totalFee\":-8.90000000E-8},\"newFees\":{\"c\":0,\"d\":0,\"deduction\":false,\"r\":-8.9E-8,\"t\":-8.9E-8,\"totalDeductionFee\":0}}",
21+
"orderSource":"market",
22+
"cTime":"1709645944272",
23+
"uTime":"1709645944272"
24+
}
25+
]
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"code":"00000",
3+
"msg":"success",
4+
"requestTime":1709692258790,
5+
"data":[
6+
{
7+
"userId":"8672173294",
8+
"symbol":"BTCUSDT",
9+
"orderId":"1148903850645331968",
10+
"clientOid":"684a79df-f931-474f-a9a5-f1deab1cd770",
11+
"priceAvg":"0",
12+
"size":"6",
13+
"orderType":"market",
14+
"side":"buy",
15+
"status":"live",
16+
"basePrice":"0",
17+
"baseVolume":"0",
18+
"quoteVolume":"0",
19+
"enterPointSource":"API",
20+
"orderSource":"market",
21+
"cTime":"1709645944272",
22+
"uTime":"1709645944272"
23+
}
24+
]
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"code":"00000",
3+
"msg":"success",
4+
"requestTime":1709692258790,
5+
"data":[
6+
{
7+
"userId":"8672173294",
8+
"symbol":"BTCUSDT",
9+
"orderId":"1148903850645331968",
10+
"clientOid":"684a79df-f931-474f-a9a5-f1deab1cd770",
11+
"priceAvg":"0",
12+
"size":"0.00009",
13+
"orderType":"market",
14+
"side":"sell",
15+
"status":"live",
16+
"basePrice":"0",
17+
"baseVolume":"0",
18+
"quoteVolume":"0",
19+
"enterPointSource":"API",
20+
"orderSource":"market",
21+
"cTime":"1709645944272",
22+
"uTime":"1709645944272"
23+
}
24+
]
25+
}

pkg/exchange/bitget/exchange_test.go

+271-1
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ func TestExchange_SubmitOrder(t *testing.T) {
549549
ex = New("key", "secret", "passphrase")
550550
placeOrderUrl = "/api/v2/spot/trade/place-order"
551551
openOrderUrl = "/api/v2/spot/trade/unfilled-orders"
552+
tickerUrl = "/api/v2/spot/market/tickers"
552553
clientOrderId = "684a79df-f931-474f-a9a5-f1deab1cd770"
553554
expBtcSymbol = "BTCUSDT"
554555
expOrder = &types.Order{
@@ -642,7 +643,276 @@ func TestExchange_SubmitOrder(t *testing.T) {
642643
assert.Equal(expOrder, acct)
643644
})
644645

645-
// TODO: add market buy, limit maker
646+
t.Run("Limit Maker order", func(t *testing.T) {
647+
transport := &httptesting.MockTransport{}
648+
ex.client.HttpClient.Transport = transport
649+
650+
placeOrderFile, err := os.ReadFile("bitgetapi/v2/testdata/place_order_request.json")
651+
assert.NoError(err)
652+
653+
transport.POST(placeOrderUrl, func(req *http.Request) (*http.Response, error) {
654+
raw, err := io.ReadAll(req.Body)
655+
assert.NoError(err)
656+
657+
reqq := &NewOrder{}
658+
err = json.Unmarshal(raw, &reqq)
659+
assert.NoError(err)
660+
assert.Equal(&NewOrder{
661+
ClientOid: expOrder.ClientOrderID,
662+
Force: string(v2.OrderForcePostOnly),
663+
OrderType: string(v2.OrderTypeLimit),
664+
Price: "66000.00",
665+
Side: string(v2.SideTypeBuy),
666+
Size: "0.000090",
667+
Symbol: expBtcSymbol,
668+
}, reqq)
669+
670+
return httptesting.BuildResponseString(http.StatusOK, string(placeOrderFile)), nil
671+
})
672+
673+
unfilledFile, err := os.ReadFile("bitgetapi/v2/testdata/get_unfilled_orders_request_limit_order.json")
674+
assert.NoError(err)
675+
676+
transport.GET(openOrderUrl, func(req *http.Request) (*http.Response, error) {
677+
query := req.URL.Query()
678+
assert.Len(query, 1)
679+
assert.Contains(query, "orderId")
680+
assert.Equal(query["orderId"], []string{strconv.FormatUint(expOrder.OrderID, 10)})
681+
return httptesting.BuildResponseString(http.StatusOK, string(unfilledFile)), nil
682+
})
683+
684+
reqLimitOrder2 := reqLimitOrder
685+
reqLimitOrder2.Type = types.OrderTypeLimitMaker
686+
acct, err := ex.SubmitOrder(context.Background(), reqLimitOrder2)
687+
assert.NoError(err)
688+
assert.Equal(expOrder, acct)
689+
})
690+
691+
t.Run("Market order", func(t *testing.T) {
692+
t.Run("Buy", func(t *testing.T) {
693+
transport := &httptesting.MockTransport{}
694+
ex.client.HttpClient.Transport = transport
695+
696+
// get ticker to calculate btc amount
697+
tickerFile, err := os.ReadFile("bitgetapi/v2/testdata/get_ticker_request.json")
698+
assert.NoError(err)
699+
700+
transport.GET(tickerUrl, func(req *http.Request) (*http.Response, error) {
701+
assert.Contains(req.URL.Query(), "symbol")
702+
assert.Equal(req.URL.Query()["symbol"], []string{expBtcSymbol})
703+
return httptesting.BuildResponseString(http.StatusOK, string(tickerFile)), nil
704+
})
705+
706+
// place order
707+
placeOrderFile, err := os.ReadFile("bitgetapi/v2/testdata/place_order_request.json")
708+
assert.NoError(err)
709+
710+
transport.POST(placeOrderUrl, func(req *http.Request) (*http.Response, error) {
711+
raw, err := io.ReadAll(req.Body)
712+
assert.NoError(err)
713+
714+
reqq := &NewOrder{}
715+
err = json.Unmarshal(raw, &reqq)
716+
assert.NoError(err)
717+
assert.Equal(&NewOrder{
718+
ClientOid: expOrder.ClientOrderID,
719+
Force: string(v2.OrderForceGTC),
720+
OrderType: string(v2.OrderTypeMarket),
721+
Price: "",
722+
Side: string(v2.SideTypeBuy),
723+
Size: reqLimitOrder.Market.FormatQuantity(fixedpoint.MustNewFromString("66554").Mul(fixedpoint.MustNewFromString("0.00009"))), // ticker: 66554, size: 0.00009
724+
Symbol: expBtcSymbol,
725+
}, reqq)
726+
727+
return httptesting.BuildResponseString(http.StatusOK, string(placeOrderFile)), nil
728+
})
729+
730+
// unfilled order
731+
unfilledFile, err := os.ReadFile("bitgetapi/v2/testdata/get_unfilled_orders_request_market_buy_order.json")
732+
assert.NoError(err)
733+
734+
transport.GET(openOrderUrl, func(req *http.Request) (*http.Response, error) {
735+
query := req.URL.Query()
736+
assert.Len(query, 1)
737+
assert.Contains(query, "orderId")
738+
assert.Equal(query["orderId"], []string{strconv.FormatUint(expOrder.OrderID, 10)})
739+
return httptesting.BuildResponseString(http.StatusOK, string(unfilledFile)), nil
740+
})
741+
742+
reqMarketOrder := reqLimitOrder
743+
reqMarketOrder.Side = types.SideTypeBuy
744+
reqMarketOrder.Type = types.OrderTypeMarket
745+
acct, err := ex.SubmitOrder(context.Background(), reqMarketOrder)
746+
assert.NoError(err)
747+
expOrder2 := *expOrder
748+
expOrder2.Side = types.SideTypeBuy
749+
expOrder2.Type = types.OrderTypeMarket
750+
expOrder2.Quantity = fixedpoint.Zero
751+
expOrder2.Price = fixedpoint.Zero
752+
assert.Equal(&expOrder2, acct)
753+
})
754+
755+
t.Run("Sell", func(t *testing.T) {
756+
transport := &httptesting.MockTransport{}
757+
ex.client.HttpClient.Transport = transport
758+
759+
// get ticker to calculate btc amount
760+
tickerFile, err := os.ReadFile("bitgetapi/v2/testdata/get_ticker_request.json")
761+
assert.NoError(err)
762+
763+
transport.GET(tickerUrl, func(req *http.Request) (*http.Response, error) {
764+
assert.Contains(req.URL.Query(), "symbol")
765+
assert.Equal(req.URL.Query()["symbol"], []string{expBtcSymbol})
766+
return httptesting.BuildResponseString(http.StatusOK, string(tickerFile)), nil
767+
})
768+
769+
// place order
770+
placeOrderFile, err := os.ReadFile("bitgetapi/v2/testdata/place_order_request.json")
771+
assert.NoError(err)
772+
773+
transport.POST(placeOrderUrl, func(req *http.Request) (*http.Response, error) {
774+
raw, err := io.ReadAll(req.Body)
775+
assert.NoError(err)
776+
777+
reqq := &NewOrder{}
778+
err = json.Unmarshal(raw, &reqq)
779+
assert.NoError(err)
780+
assert.Equal(&NewOrder{
781+
ClientOid: expOrder.ClientOrderID,
782+
Force: string(v2.OrderForceGTC),
783+
OrderType: string(v2.OrderTypeMarket),
784+
Price: "",
785+
Side: string(v2.SideTypeSell),
786+
Size: "0.000090", // size: 0.00009
787+
Symbol: expBtcSymbol,
788+
}, reqq)
789+
790+
return httptesting.BuildResponseString(http.StatusOK, string(placeOrderFile)), nil
791+
})
792+
793+
// unfilled order
794+
unfilledFile, err := os.ReadFile("bitgetapi/v2/testdata/get_unfilled_orders_request_market_sell_order.json")
795+
assert.NoError(err)
796+
797+
transport.GET(openOrderUrl, func(req *http.Request) (*http.Response, error) {
798+
query := req.URL.Query()
799+
assert.Len(query, 1)
800+
assert.Contains(query, "orderId")
801+
assert.Equal(query["orderId"], []string{strconv.FormatUint(expOrder.OrderID, 10)})
802+
return httptesting.BuildResponseString(http.StatusOK, string(unfilledFile)), nil
803+
})
804+
805+
reqMarketOrder := reqLimitOrder
806+
reqMarketOrder.Side = types.SideTypeSell
807+
reqMarketOrder.Type = types.OrderTypeMarket
808+
acct, err := ex.SubmitOrder(context.Background(), reqMarketOrder)
809+
assert.NoError(err)
810+
expOrder2 := *expOrder
811+
expOrder2.Side = types.SideTypeSell
812+
expOrder2.Type = types.OrderTypeMarket
813+
expOrder2.Price = fixedpoint.Zero
814+
assert.Equal(&expOrder2, acct)
815+
})
816+
817+
t.Run("failed to get ticker on buy", func(t *testing.T) {
818+
transport := &httptesting.MockTransport{}
819+
ex.client.HttpClient.Transport = transport
820+
821+
// get ticker to calculate btc amount
822+
requestErrFile, err := os.ReadFile("bitgetapi/v2/testdata/request_error.json")
823+
assert.NoError(err)
824+
825+
transport.GET(tickerUrl, func(req *http.Request) (*http.Response, error) {
826+
assert.Contains(req.URL.Query(), "symbol")
827+
assert.Equal(req.URL.Query()["symbol"], []string{expBtcSymbol})
828+
return httptesting.BuildResponseString(http.StatusBadRequest, string(requestErrFile)), nil
829+
})
830+
831+
reqMarketOrder := reqLimitOrder
832+
reqMarketOrder.Side = types.SideTypeBuy
833+
reqMarketOrder.Type = types.OrderTypeMarket
834+
_, err = ex.SubmitOrder(context.Background(), reqMarketOrder)
835+
assert.ErrorContains(err, "Invalid IP")
836+
})
837+
838+
t.Run("get order from history due to unfilled order not found", func(t *testing.T) {
839+
transport := &httptesting.MockTransport{}
840+
ex.client.HttpClient.Transport = transport
841+
842+
// get ticker to calculate btc amount
843+
tickerFile, err := os.ReadFile("bitgetapi/v2/testdata/get_ticker_request.json")
844+
assert.NoError(err)
845+
846+
transport.GET(tickerUrl, func(req *http.Request) (*http.Response, error) {
847+
assert.Contains(req.URL.Query(), "symbol")
848+
assert.Equal(req.URL.Query()["symbol"], []string{expBtcSymbol})
849+
return httptesting.BuildResponseString(http.StatusOK, string(tickerFile)), nil
850+
})
851+
852+
// place order
853+
placeOrderFile, err := os.ReadFile("bitgetapi/v2/testdata/place_order_request.json")
854+
assert.NoError(err)
855+
856+
transport.POST(placeOrderUrl, func(req *http.Request) (*http.Response, error) {
857+
raw, err := io.ReadAll(req.Body)
858+
assert.NoError(err)
859+
860+
reqq := &NewOrder{}
861+
err = json.Unmarshal(raw, &reqq)
862+
assert.NoError(err)
863+
assert.Equal(&NewOrder{
864+
ClientOid: expOrder.ClientOrderID,
865+
Force: string(v2.OrderForceGTC),
866+
OrderType: string(v2.OrderTypeMarket),
867+
Price: "",
868+
Side: string(v2.SideTypeBuy),
869+
Size: reqLimitOrder.Market.FormatQuantity(fixedpoint.MustNewFromString("66554").Mul(fixedpoint.MustNewFromString("0.00009"))), // ticker: 66554, size: 0.00009
870+
Symbol: expBtcSymbol,
871+
}, reqq)
872+
873+
return httptesting.BuildResponseString(http.StatusOK, string(placeOrderFile)), nil
874+
})
875+
876+
// unfilled order
877+
requestErrFile, err := os.ReadFile("bitgetapi/v2/testdata/request_error.json")
878+
assert.NoError(err)
879+
880+
transport.GET(openOrderUrl, func(req *http.Request) (*http.Response, error) {
881+
query := req.URL.Query()
882+
assert.Len(query, 1)
883+
assert.Contains(query, "orderId")
884+
assert.Equal(query["orderId"], []string{strconv.FormatUint(expOrder.OrderID, 10)})
885+
return httptesting.BuildResponseString(http.StatusBadRequest, string(requestErrFile)), nil
886+
})
887+
888+
// order history
889+
historyOrderFile, err := os.ReadFile("bitgetapi/v2/testdata/get_history_orders_request_market_buy.json")
890+
assert.NoError(err)
891+
892+
transport.GET(openOrderUrl, func(req *http.Request) (*http.Response, error) {
893+
query := req.URL.Query()
894+
assert.Len(query, 1)
895+
assert.Contains(query, "orderId")
896+
assert.Equal(query["orderId"], []string{strconv.FormatUint(expOrder.OrderID, 10)})
897+
return httptesting.BuildResponseString(http.StatusOK, string(historyOrderFile)), nil
898+
})
899+
900+
reqMarketOrder := reqLimitOrder
901+
reqMarketOrder.Side = types.SideTypeBuy
902+
reqMarketOrder.Type = types.OrderTypeMarket
903+
acct, err := ex.SubmitOrder(context.Background(), reqMarketOrder)
904+
assert.NoError(err)
905+
expOrder2 := *expOrder
906+
expOrder2.Side = types.SideTypeBuy
907+
expOrder2.Type = types.OrderTypeMarket
908+
expOrder2.Status = types.OrderStatusFilled
909+
expOrder2.ExecutedQuantity = fixedpoint.MustNewFromString("0.000089")
910+
expOrder2.Quantity = fixedpoint.MustNewFromString("0.000089")
911+
expOrder2.Price = fixedpoint.MustNewFromString("67360.87")
912+
expOrder2.IsWorking = false
913+
assert.Equal(&expOrder2, acct)
914+
})
915+
})
646916

647917
t.Run("error on query open orders", func(t *testing.T) {
648918
transport := &httptesting.MockTransport{}

0 commit comments

Comments
 (0)