diff --git a/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go b/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go index d39f161ccaa..93cf7c6515e 100644 --- a/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go +++ b/cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go @@ -612,8 +612,7 @@ var unsupportedAssets = []asset.Item{ var unsupportedExchangeNames = []string{ "testexch", "bitflyer", // Bitflyer has many "ErrNotYetImplemented, which is true, but not what we care to test for here - "btse", // TODO rm once timeout issues resolved - "poloniex", // outdated API // TODO rm once updated + "btse", // TODO rm once timeout issues resolved } // cryptoChainPerExchange holds the deposit address chain per exchange diff --git a/config/versions/register.go b/config/versions/register.go index 8cd896ef2e6..2aaaad0206e 100644 --- a/config/versions/register.go +++ b/config/versions/register.go @@ -4,6 +4,7 @@ import ( v0 "github.com/thrasher-corp/gocryptotrader/config/versions/v0" v1 "github.com/thrasher-corp/gocryptotrader/config/versions/v1" v10 "github.com/thrasher-corp/gocryptotrader/config/versions/v10" + v11 "github.com/thrasher-corp/gocryptotrader/config/versions/v11" v2 "github.com/thrasher-corp/gocryptotrader/config/versions/v2" v3 "github.com/thrasher-corp/gocryptotrader/config/versions/v3" v4 "github.com/thrasher-corp/gocryptotrader/config/versions/v4" @@ -26,4 +27,5 @@ func init() { Manager.registerVersion(8, &v8.Version{}) Manager.registerVersion(9, &v9.Version{}) Manager.registerVersion(10, &v10.Version{}) + Manager.registerVersion(11, &v11.Version{}) } diff --git a/config/versions/v11/v11.go b/config/versions/v11/v11.go new file mode 100644 index 00000000000..6385dff5264 --- /dev/null +++ b/config/versions/v11/v11.go @@ -0,0 +1,34 @@ +package v11 + +import ( + "context" + "errors" + + "github.com/buger/jsonparser" +) + +// Version is an ExchangeVersion to replace deprecated WS and REST endpoints for Poloniex +type Version struct{} + +// Exchanges returns just Poloniex +func (v *Version) Exchanges() []string { return []string{"Poloniex"} } + +// UpgradeExchange replaces deprecated WS and REST endpoints +func (v *Version) UpgradeExchange(_ context.Context, e []byte) ([]byte, error) { + for _, key := range []string{"WebsocketSpotURL", "RestSpotURL"} { + url, err := jsonparser.GetString(e, "api", "urlEndpoints", key) + if err != nil && !errors.Is(err, jsonparser.KeyPathNotFoundError) { + return e, err + } + switch url { + case "wss://api2.poloniex.com", "https://poloniex.com": + e = jsonparser.Delete(e, "api", "urlEndpoints", key) + } + } + return e, nil +} + +// DowngradeExchange is a no-op for v11 +func (v *Version) DowngradeExchange(_ context.Context, e []byte) ([]byte, error) { + return e, nil +} diff --git a/config/versions/v11/v11_test.go b/config/versions/v11/v11_test.go new file mode 100644 index 00000000000..e01d80c6f8a --- /dev/null +++ b/config/versions/v11/v11_test.go @@ -0,0 +1,54 @@ +package v11_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + v11 "github.com/thrasher-corp/gocryptotrader/config/versions/v11" +) + +func TestExchanges(t *testing.T) { + t.Parallel() + assert.Equal(t, []string{"Poloniex"}, new(v11.Version).Exchanges()) +} + +func TestUpgradeExchange(t *testing.T) { + t.Parallel() + + for _, tt := range []struct { + in string + urlType string + exp string + }{ + {"https://poloniex.com", "RestSpotURL", ""}, + {"https://poloniex.private-proxy.com", "RestSpotURL", `"RestSpotURL": "https://poloniex.private-proxy.com"`}, + {"wss://api2.poloniex.com", "WebsocketSpotURL", ""}, + {"wss://poloniex.private-proxy.com", "WebsocketSpotURL", `"WebsocketSpotURL": "wss://poloniex.private-proxy.com"`}, + } { + t.Run(tt.in, func(t *testing.T) { + t.Parallel() + in := []byte(`{"name":"Poloniex","api":{"urlEndpoints":{"` + tt.urlType + `": "` + tt.in + `"}}}`) + out, err := new(v11.Version).UpgradeExchange(t.Context(), in) + require.NoError(t, err) + exp := `{"name":"Poloniex","api":{"urlEndpoints":{` + tt.exp + `}}}` + assert.Equal(t, exp, string(out)) + }) + } + + in := []byte(`{"name":"Poloniex","api":{}`) + out, err := new(v11.Version).UpgradeExchange(t.Context(), in) + require.NoError(t, err, "UpgradeExchange must not error when urlEndpoints is missing") + assert.Equal(t, string(in), string(out), "UpgradeExchange should return same input and no error when urlEndpoints is missing") + + _, err = new(v11.Version).UpgradeExchange(t.Context(), []byte(`{"name":"Poloniex","api":{"urlEndpoints":{"WebsocketSpotURL": 42}}}`)) + require.ErrorContains(t, err, "Value is not a string", "UpgradeExchange must error correctly on string value") +} + +func TestDowngradeExchange(t *testing.T) { + t.Parallel() + in := []byte(`{"name":"Poloniex","api":{"urlEndpoints":{"WebsocketSpotURL": 42}}}`) + out, err := new(v11.Version).DowngradeExchange(t.Context(), in) + require.NoError(t, err) + require.Equal(t, string(in), string(out), "DowngradeExchange must not change json") +} diff --git a/config_example.json b/config_example.json index 6fea8223440..91e63b9a698 100644 --- a/config_example.json +++ b/config_example.json @@ -2308,31 +2308,36 @@ "delimiter": "_" }, "useGlobalFormat": true, - "assetTypes": [ - "spot" - ], "pairs": { "spot": { + "assetEnabled": true, "enabled": "BTC_LTC,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", "available": "BTC_SC,BTC_GNT,USDC_LTC,PAX_ETH,USDT_BSVBEAR,BUSD_BNB,USDT_WRX,USDT_IBVOL,USDT_ETH,BTC_ETC,USDC_ETH,BTC_POLY,BTC_ATOM,USDT_ATOM,TRX_STEEM,USDT_NEO,USDT_XRPBULL,USDT_AVA,USDT_DASH,USDT_ZRX,USDT_TRXBEAR,USDT_PAX,DAI_ETH,BTC_NEO,TRX_JST,BTC_FXC,USDT_ETC,USDT_ZEC,BTC_STORJ,USDT_GNT,USDT_QTUM,BTC_FOAM,TRX_BTT,USDT_BCHC,BTC_XFIL,USDC_XMR,TRX_WIN,USDT_SNX,BTC_LEND,USDT_BSVBULL,BTC_DOGE,BTC_REP,USDT_REP,BTC_STRAT,USDT_EOS,BTC_BAT,BTC_BCHABC,USDT_BUSD,BTC_XRP,BTC_ARDR,USDT_LINKBULL,BTC_CHR,USDT_CUSDT,TRX_WRX,USDT_XRP,ETH_ZEC,BTC_KNC,USDT_DOGE,BTC_LPT,USDT_BTT,ETH_COMP,USDC_GRIN,USDC_DASH,USDT_GRIN,USDT_XTZ,BTC_GAS,USDT_DAI,TRX_NEO,USDT_LINKBEAR,TRX_CHR,BTC_MDT,USDT_XMR,BTC_DCR,BTC_CVC,USDT_BNB,BTC_NXT,BTC_LSK,BTC_OMG,BTC_QTUM,BTC_BCHSV,BTC_SNX,BTC_MANA,USDC_EOS,DAI_BTC,BTC_SWFTC,TRX_BNB,BTC_STEEM,USDJ_BTC,USDJ_BTT,USDT_LRC,USDT_BAL,BNB_BTC,USDC_DOGE,BTC_TRX,BTC_XTZ,TRX_XTZ,USDT_MATIC,USDT_BCHBEAR,USDT_SWFTC,BTC_LTC,USDC_XRP,BTC_NMR,TRX_MATIC,USDT_XRPBEAR,BTC_ZEC,BTC_SNT,USDT_SC,USDT_BCHSV,TRX_ETH,BUSD_BTC,BTC_DASH,ETH_BAT,BTC_LOOM,TRX_SNX,ETH_ZRX,USDC_BCHABC,USDC_ETC,USDT_BULL,PAX_BTC,USDJ_TRX,BTC_WRX,BTC_BTS,USDT_LTC,BTC_LINK,USDT_USDJ,TRX_SWFTC,USDT_LINK,TRX_AVA,USDC_USDT,USDT_JST,TRX_FXC,USDT_CHR,USDT_XFIL,BTC_ETHBNT,BTC_LRC,USDT_BAT,USDC_ATOM,USDT_WIN,ETH_EOS,USDT_TRX,TRX_MDT,BTC_AVA,BTC_XEM,USDT_BTC,BTC_EOS,USDT_LSK,BTC_MATIC,USDT_FXC,USDT_STEEM,USDC_BCHSV,USDT_TRXBULL,USDT_EOSBULL,USDT_LEND,ETH_ETC,USDT_MANA,USDT_ETHBULL,USDT_REN,USDT_COMP,BTC_XMR,BTC_ETH,BTC_ZRX,USDC_BTC,TRX_XRP,USDT_ETHBEAR,USDT_BVOL,ETH_BAL,USDT_MDT,BTC_BNT,USDC_ZEC,USDT_BCHABC,TRX_LINK,BTC_MKR,USDT_BCN,USDT_EOSBEAR,BTC_REN,USDT_STR,USDC_STR,USDT_BEAR,USDT_BCHBULL,BTC_STR,USDC_TRX,USDT_MKR" + }, + "futures": { + "assetEnabled": true, + "enabled": "XBT_USDT_PERP,ETH_USDT_PERP,BCH_USDT_PERP", + "available": "BNB_USDT_PERP,TRX_USDT_PERP,LTC_USDT_PERP,APT_USDT_PERP,1000PEPE_USDT_PERP,1000SHIB_USDT_PERP,BTC_USDT_PERP,DOGE_USDT_PERP,AVAX_USDT_PERP,XRP_USDT_PERP,SOL_USDT_PERP,ETH_USDT_PERP,BCH_USDT_PERP" } } }, "api": { "authenticatedSupport": false, "authenticatedWebsocketApiSupport": false, - "endpoints": { - "url": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API", - "urlSecondary": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API", - "websocketURL": "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API" - }, "credentials": { - "key": "Key", - "secret": "Secret" + "key": "", + "secret": "" }, "credentialsValidator": { "requiresKey": true, "requiresSecret": true + }, + "urlEndpoints": { + "RestSpotURL": "https://api.poloniex.com", + "WebsocketPrivateURL": "wss://ws.poloniex.com/ws/private", + "WebsocketSpotURL": "wss://ws.poloniex.com/ws/public", + "WebsocketFuturesURL": "wss://ws.poloniex.com/ws/v3/public", + "WebsocketFuturesPrivateURL": "wss://ws.poloniex.com/ws/v3/private" } }, "features": { @@ -2347,7 +2352,7 @@ }, "enabled": { "autoPairUpdates": true, - "websocketAPI": false + "websocketAPI": true } }, "bankAccounts": [ diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 20875f567e9..af37e41fcca 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -1364,6 +1364,10 @@ func (u URL) String() string { return websocketPrivateURL case WebsocketSpotSupplementary: return websocketSpotSupplementaryURL + case WebsocketFutures: + return websocketFuturesURL + case WebsocketFuturesPrivate: + return websocketFuturesPrivateURL case ChainAnalysis: return chainAnalysisURL case EdgeCase1: @@ -1414,6 +1418,10 @@ func getURLTypeFromString(ep string) (URL, error) { return WebsocketPrivate, nil case websocketSpotSupplementaryURL: return WebsocketSpotSupplementary, nil + case websocketFuturesURL: + return WebsocketFutures, nil + case websocketFuturesPrivateURL: + return WebsocketFuturesPrivate, nil case chainAnalysisURL: return ChainAnalysis, nil case edgeCase1URL: diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 2f7528818c9..99187259043 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -1649,6 +1649,8 @@ func TestString(t *testing.T) { {WebsocketTrade, websocketTradeURL}, {WebsocketPrivate, websocketPrivateURL}, {WebsocketSpotSupplementary, websocketSpotSupplementaryURL}, + {WebsocketFutures, websocketFuturesURL}, + {WebsocketFuturesPrivate, websocketFuturesPrivateURL}, {ChainAnalysis, chainAnalysisURL}, {EdgeCase1, edgeCase1URL}, {EdgeCase2, edgeCase2URL}, @@ -1813,6 +1815,8 @@ func TestGetGetURLTypeFromString(t *testing.T) { {Endpoint: websocketTradeURL, Expected: WebsocketTrade}, {Endpoint: websocketPrivateURL, Expected: WebsocketPrivate}, {Endpoint: websocketSpotSupplementaryURL, Expected: WebsocketSpotSupplementary}, + {Endpoint: websocketFuturesURL, Expected: WebsocketFutures}, + {Endpoint: websocketFuturesPrivateURL, Expected: WebsocketFuturesPrivate}, {Endpoint: chainAnalysisURL, Expected: ChainAnalysis}, {Endpoint: edgeCase1URL, Expected: EdgeCase1}, {Endpoint: edgeCase2URL, Expected: EdgeCase2}, diff --git a/exchanges/exchange_types.go b/exchanges/exchange_types.go index da605d73f44..a1fd9c47836 100644 --- a/exchanges/exchange_types.go +++ b/exchanges/exchange_types.go @@ -282,6 +282,8 @@ const ( WebsocketTrade WebsocketPrivate WebsocketSpotSupplementary + WebsocketFutures + WebsocketFuturesPrivate ChainAnalysis EdgeCase1 EdgeCase2 @@ -304,6 +306,8 @@ const ( websocketTradeURL = "WebsocketTradeURL" websocketPrivateURL = "WebsocketPrivateURL" websocketSpotSupplementaryURL = "WebsocketSpotSupplementaryURL" + websocketFuturesURL = "WebsocketFuturesURL" + websocketFuturesPrivateURL = "WebsocketFuturesPrivateURL" chainAnalysisURL = "ChainAnalysisURL" edgeCase1URL = "EdgeCase1URL" edgeCase2URL = "EdgeCase2URL" @@ -328,6 +332,8 @@ var keyURLs = []URL{ WebsocketTrade, WebsocketPrivate, WebsocketSpotSupplementary, + WebsocketFutures, + WebsocketFuturesPrivate, ChainAnalysis, EdgeCase1, EdgeCase2, diff --git a/exchanges/kline/kline_types.go b/exchanges/kline/kline_types.go index bb0132a73e4..0d15d876989 100644 --- a/exchanges/kline/kline_types.go +++ b/exchanges/kline/kline_types.go @@ -147,6 +147,7 @@ type Candle struct { Low float64 Close float64 Volume float64 + QuoteVolume float64 ValidationIssues string } diff --git a/exchanges/mock/server.go b/exchanges/mock/server.go index e529031d511..1928a34516b 100644 --- a/exchanges/mock/server.go +++ b/exchanges/mock/server.go @@ -253,15 +253,13 @@ func MatchAndGetResponse(mockData []HTTPResponse, requestVals url.Values, isQuer } mockVals := url.Values{} - var err error if json.Valid([]byte(data)) { - something := make(map[string]any) - err = json.Unmarshal([]byte(data), &something) - if err != nil { + dataMap := make(map[string]any) + if err := json.Unmarshal([]byte(data), &dataMap); err != nil { return nil, err } - for k, v := range something { + for k, v := range dataMap { switch val := v.(type) { case string: mockVals.Add(k, val) @@ -277,6 +275,7 @@ func MatchAndGetResponse(mockData []HTTPResponse, requestVals url.Values, isQuer } } } else { + var err error mockVals, err = url.ParseQuery(data) if err != nil { return nil, err diff --git a/exchanges/order/order_types.go b/exchanges/order/order_types.go index 7ed63aa74a4..324fe54766c 100644 --- a/exchanges/order/order_types.go +++ b/exchanges/order/order_types.go @@ -34,6 +34,9 @@ var ( ErrCannotLiquidate = errors.New("cannot liquidate position") ErrUnknownTrackingMode = errors.New("unknown tracking mode") + ErrGetFailed = errors.New("get order failed") + ErrPlaceFailed = errors.New("place order failed") + ErrCancelFailed = errors.New("cancel order failed") ) // Submit contains all properties of an order that may be required @@ -104,8 +107,16 @@ type Submit struct { TrackingMode TrackingMode TrackingValue float64 + // LimitTrackingMode specifies the limit price offset used to place a limit order relative to the market price. + LimitTrackingMode TrackingMode + LimitTrackingValue float64 + // RFQDisabled, when set, attempts to route the order to the exchange CLOB. Currently only supported by Coinbase RFQDisabled bool + + // SlippageTolerance used to control the maximum slippage ratio, the value range is greater than 0 and less than 1 + // https://api-docs.poloniex.com/spot/api/private/order + SlippageTolerance float64 } // SubmitResponse is what is returned after submitting an order to an exchange @@ -157,13 +168,14 @@ const ( // are required to be populated type Modify struct { // Order Identifiers - Exchange string - OrderID string - ClientOrderID string - Type Type - Side Side - AssetType asset.Item - Pair currency.Pair + Exchange string + OrderID string + ClientOrderID string + NewClientOrderID string + Type Type + Side Side + AssetType asset.Item + Pair currency.Pair // Change fields TimeInForce TimeInForce @@ -176,6 +188,10 @@ type Modify struct { TriggerPriceType PriceType RiskManagementModes RiskManagementModes + + // SlippageTolerance used to control the maximum slippage ratio, the value range is greater than 0 and less than 1 + // https://api-docs.poloniex.com/spot/api/private/order + SlippageTolerance float64 } // ModifyResponse is an order modifying return type @@ -372,6 +388,7 @@ const ( AnyType Liquidation Trigger + LimitMaker OCO // One-cancels-the-other order ConditionalStop // One-way stop order TWAP // time-weighted average price @@ -380,10 +397,11 @@ const ( MarketMakerProtection // Hybrid order types - StopLimit = Stop | Limit - StopMarket = Stop | Market - TakeProfitMarket = TakeProfit | Market - Bracket = Stop | TakeProfit + StopLimit = Stop | Limit + StopMarket = Stop | Market + TakeProfitMarket = TakeProfit | Market + TrailingStopLimit = TrailingStop | Limit + Bracket = Stop | TakeProfit ) // order-type string representations @@ -399,9 +417,11 @@ const ( orderTakeProfit = "TAKE PROFIT" orderTakeProfitMarket = "TAKE PROFIT MARKET" orderTrailingStop = "TRAILING_STOP" + orderTrailingStopLimit = "TRAILING_STOP_LIMIT" orderIOS = "IOS" orderLiquidation = "LIQUIDATION" orderTrigger = "TRIGGER" + orderLimitMaker = "LIMIT_MAKER" orderOCO = "OCO" orderOptimalLimit = "OPTIMAL_LIMIT" orderMarketMakerProtection = "MMP" @@ -413,22 +433,19 @@ const ( var AllOrderTypes = Limit | Market | Stop | - StopLimit | - StopMarket | TakeProfit | - TakeProfitMarket | TrailingStop | IOS | AnyType | Liquidation | Trigger | + LimitMaker | OCO | ConditionalStop | TWAP | Chase | OptimalLimit | - MarketMakerProtection | - Bracket + MarketMakerProtection // Side enforces a standard for order sides across the code base type Side uint32 diff --git a/exchanges/order/orders.go b/exchanges/order/orders.go index bc91a1b793f..19914060b7e 100644 --- a/exchanges/order/orders.go +++ b/exchanges/order/orders.go @@ -41,6 +41,7 @@ var ( ErrClientOrderIDMustBeSet = errors.New("client order ID must be set") ErrUnknownSubmissionAmountType = errors.New("unknown submission amount type") ErrUnrecognisedOrderType = errors.New("unrecognised order type") + ErrPositionSideUnsupported = errors.New("position side unsupported") ) var ( @@ -688,12 +689,16 @@ func (t Type) String() string { return orderTakeProfitMarket case TrailingStop: return orderTrailingStop + case TrailingStopLimit: + return orderTrailingStopLimit case IOS: return orderIOS case Liquidation: return orderLiquidation case Trigger: return orderTrigger + case LimitMaker: + return orderLimitMaker case OCO: return orderOCO case Bracket: @@ -782,6 +787,18 @@ func (s Side) IsLong() bool { return s != UnknownSide && longSide&s == s } +// Position converts a spot side to a futures position; eg BUY => LONG +// Returns UnknownSide with an ErrPositionSideUnsupported error unless s.IsLong or s.IsShort +func (s Side) Position() (Side, error) { + switch { + case s.IsLong(): + return Long, nil + case s.IsShort(): + return Short, nil + } + return UnknownSide, ErrPositionSideUnsupported +} + // String implements the stringer interface func (s Status) String() string { switch s { @@ -1112,10 +1129,14 @@ func StringToOrderType(oType string) (Type, error) { return StopMarket, nil case orderTrailingStop, "TRAILING STOP", "EXCHANGE TRAILING STOP", "MOVE_ORDER_STOP": return TrailingStop, nil + case orderTrailingStopLimit: + return TrailingStopLimit, nil case orderIOS: return IOS, nil case orderAnyType: return AnyType, nil + case orderLimitMaker, "LIMIT MAKER": + return LimitMaker, nil case orderTrigger: return Trigger, nil case orderOptimalLimit: diff --git a/exchanges/order/order_test.go b/exchanges/order/orders_test.go similarity index 98% rename from exchanges/order/order_test.go rename to exchanges/order/orders_test.go index 7695a4b159e..89240474707 100644 --- a/exchanges/order/order_test.go +++ b/exchanges/order/orders_test.go @@ -312,6 +312,8 @@ func TestOrderIs(t *testing.T) { {Type: StopMarket, Targets: []Type{Stop, Market}}, {Type: TrailingStop, Targets: []Type{TrailingStop}}, {Type: UnknownType | Limit, Targets: []Type{Limit}}, + {Type: TrailingStop | Limit, Targets: []Type{TrailingStopLimit, Limit}}, + {Type: LimitMaker, Targets: []Type{LimitMaker}}, {Type: TakeProfitMarket, Targets: []Type{TakeProfit, Market}}, } for _, oType := range orderComparisonList { @@ -358,6 +360,9 @@ func TestOrderTypeToString(t *testing.T) { {AnyType, "ANY"}, {UnknownType | Limit, "LIMIT"}, {StopMarket | ConditionalStop, "UNKNOWN"}, + {TrailingStop | Limit, "TRAILING_STOP_LIMIT"}, + {TrailingStopLimit, "TRAILING_STOP_LIMIT"}, + {LimitMaker, "LIMIT_MAKER"}, } for _, tt := range orderToToStringsList { t.Run(tt.String, func(t *testing.T) { @@ -847,6 +852,10 @@ func TestStringToOrderType(t *testing.T) { {"TRIGGER_bracket", Bracket, nil}, {"optimal_limit", OptimalLimit, nil}, {"OPTIMAL_LIMIT", OptimalLimit, nil}, + {"TRAILING_STOP_LIMIT", TrailingStopLimit, nil}, + {"trailing_stop_limit", TrailingStopLimit, nil}, + {"LIMIT_MAKER", LimitMaker, nil}, + {"Limit Maker", LimitMaker, nil}, } for i := range cases { testData := &cases[i] @@ -1746,7 +1755,7 @@ func TestMarshalOrder(t *testing.T) { } j, err := json.Marshal(orderSubmit) require.NoError(t, err, "Marshal must not error") - exp := []byte(`{"Exchange":"test","Type":4,"Side":"BUY","Pair":"BTC-USDT","AssetType":"spot","TimeInForce":"","ReduceOnly":false,"Leverage":0,"Price":1000,"Amount":1,"QuoteAmount":0,"TriggerPrice":0,"TriggerPriceType":0,"ClientID":"","ClientOrderID":"","AutoBorrow":false,"MarginType":"multi","RetrieveFees":false,"RetrieveFeeDelay":0,"RiskManagementModes":{"Mode":"","TakeProfit":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0},"StopLoss":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0},"StopEntry":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0}},"Hidden":false,"Iceberg":false,"EndTime":"0001-01-01T00:00:00Z","StopDirection":false,"TrackingMode":0,"TrackingValue":0,"RFQDisabled":false}`) + exp := []byte(`{"Exchange":"test","Type":4,"Side":"BUY","Pair":"BTC-USDT","AssetType":"spot","TimeInForce":"","ReduceOnly":false,"Leverage":0,"Price":1000,"Amount":1,"QuoteAmount":0,"TriggerPrice":0,"TriggerPriceType":0,"ClientID":"","ClientOrderID":"","AutoBorrow":false,"MarginType":"multi","RetrieveFees":false,"RetrieveFeeDelay":0,"RiskManagementModes":{"Mode":"","TakeProfit":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0},"StopLoss":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0},"StopEntry":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0}},"Hidden":false,"Iceberg":false,"EndTime":"0001-01-01T00:00:00Z","StopDirection":false,"TrackingMode":0,"TrackingValue":0,"LimitTrackingMode":0,"LimitTrackingValue":0,"RFQDisabled":false,"SlippageTolerance":0}`) assert.Equal(t, exp, j) } @@ -1756,3 +1765,23 @@ func TestAdd(t *testing.T) { c.Add("order1", "cancelled") assert.Equal(t, "cancelled", c.Status["order1"]) } + +func TestPosition(t *testing.T) { + t.Parallel() + input := []struct { + sides []Side + side Side + err error + }{ + {[]Side{Short, Sell, Ask}, Short, nil}, + {[]Side{Long, Buy, Bid}, Long, nil}, + {[]Side{Side(123)}, UnknownSide, ErrPositionSideUnsupported}, + } + for _, a := range input { + for _, sd := range a.sides { + side, err := sd.Position() + assert.Equal(t, a.side, side) + assert.ErrorIs(t, err, a.err) + } + } +} diff --git a/exchanges/poloniex/currency_details.go b/exchanges/poloniex/currency_details.go deleted file mode 100644 index 71e7b50fe43..00000000000 --- a/exchanges/poloniex/currency_details.go +++ /dev/null @@ -1,235 +0,0 @@ -package poloniex - -import ( - "errors" - "strconv" - "sync" - - "github.com/thrasher-corp/gocryptotrader/currency" -) - -// CurrencyDetails stores a map of currencies associated with their ID -type CurrencyDetails struct { - pairs map[float64]PairSummaryInfo - codes map[float64]CodeSummaryInfo - // Mutex used for future when we will periodically update this table every - // week or so in production - m sync.RWMutex -} - -// PairSummaryInfo defines currency pair information -type PairSummaryInfo struct { - Pair currency.Pair - IsFrozen bool - PostOnly bool -} - -// CodeSummaryInfo defines currency information -type CodeSummaryInfo struct { - Currency currency.Code - WithdrawalTXFee float64 - MinimumConfirmations int64 - DepositAddress string - WithdrawalDepositDisabled bool - Frozen bool -} - -var ( - errCannotLoadNoData = errors.New("cannot load websocket currency data as data is nil") - errNoDepositAddress = errors.New("no public deposit address for currency") - errPairMapIsNil = errors.New("cannot get currency pair, map is nil") - errCodeMapIsNil = errors.New("cannot get currency code, map is nil") - errCurrencyNotFoundInMap = errors.New("currency not found") -) - -// loadPairs loads currency pair associations with unique identifiers from -// ticker data map -func (w *CurrencyDetails) loadPairs(data map[string]Ticker) error { - if data == nil { - return errCannotLoadNoData - } - w.m.Lock() - defer w.m.Unlock() - for k, v := range data { - pair, err := currency.NewPairFromString(k) - if err != nil { - return err - } - - if w.pairs == nil { - w.pairs = make(map[float64]PairSummaryInfo) - } - w.pairs[v.ID] = PairSummaryInfo{ - Pair: pair, - IsFrozen: v.IsFrozen == 1, - PostOnly: v.PostOnly == 1, - } - } - return nil -} - -// loadCodes loads currency codes from currency map -func (w *CurrencyDetails) loadCodes(data map[string]*Currencies) error { - if data == nil { - return errCannotLoadNoData - } - w.m.Lock() - defer w.m.Unlock() - for k, v := range data { - if v.Delisted == 1 { - continue - } - - if w.codes == nil { - w.codes = make(map[float64]CodeSummaryInfo) - } - - w.codes[v.ID] = CodeSummaryInfo{ - Currency: currency.NewCode(k), - WithdrawalTXFee: v.TxFee, - MinimumConfirmations: v.MinConfirmations, - DepositAddress: v.DepositAddress, - WithdrawalDepositDisabled: v.WithdrawalDepositDisabled == 1, - Frozen: v.Frozen == 1, - } - } - return nil -} - -// GetPair returns a currency pair by its ID -func (w *CurrencyDetails) GetPair(id float64) (currency.Pair, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.pairs == nil { - return currency.EMPTYPAIR, errPairMapIsNil - } - - p, ok := w.pairs[id] - if ok { - return p.Pair, nil - } - - // This is here so we can still log an order with the ID as the currency - // pair which you can then cross reference later with the exchange ID list, - // rather than error out. - op, err := currency.NewPairFromString(strconv.FormatFloat(id, 'f', -1, 64)) - if err != nil { - return op, err - } - return op, errIDNotFoundInPairMap -} - -// GetCode returns a currency code by its ID -func (w *CurrencyDetails) GetCode(id float64) (currency.Code, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return currency.EMPTYCODE, errCodeMapIsNil - } - c, ok := w.codes[id] - if ok { - return c.Currency, nil - } - return currency.EMPTYCODE, errIDNotFoundInCodeMap -} - -// GetWithdrawalTXFee returns withdrawal transaction fee for the currency -func (w *CurrencyDetails) GetWithdrawalTXFee(c currency.Code) (float64, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return 0, errCodeMapIsNil - } - for _, v := range w.codes { - if v.Currency == c { - return v.WithdrawalTXFee, nil - } - } - return 0, errCurrencyNotFoundInMap -} - -// GetDepositAddress returns the public deposit address details for the currency -func (w *CurrencyDetails) GetDepositAddress(c currency.Code) (string, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return "", errCodeMapIsNil - } - for _, v := range w.codes { - if v.Currency == c { - if v.DepositAddress == "" { - return "", errNoDepositAddress - } - return v.DepositAddress, nil - } - } - return "", errCurrencyNotFoundInMap -} - -// IsWithdrawAndDepositsEnabled returns if withdrawals or deposits are enabled -func (w *CurrencyDetails) IsWithdrawAndDepositsEnabled(c currency.Code) (bool, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return false, errCodeMapIsNil - } - for _, v := range w.codes { - if v.Currency == c { - return !v.WithdrawalDepositDisabled, nil - } - } - return false, errCurrencyNotFoundInMap -} - -// IsTradingEnabledForCurrency returns if the currency is allowed to be traded -func (w *CurrencyDetails) IsTradingEnabledForCurrency(c currency.Code) (bool, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return false, errCodeMapIsNil - } - for _, v := range w.codes { - if v.Currency == c { - return !v.Frozen, nil - } - } - return false, errCurrencyNotFoundInMap -} - -// IsTradingEnabledForPair returns if the currency pair is allowed to be traded -func (w *CurrencyDetails) IsTradingEnabledForPair(pair currency.Pair) (bool, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return false, errCodeMapIsNil - } - for _, v := range w.pairs { - if v.Pair.Equal(pair) { - return !v.IsFrozen, nil - } - } - return false, errCurrencyNotFoundInMap -} - -// IsPostOnlyForPair returns if an order is allowed to take liquidity from the -// books or reduce positions -func (w *CurrencyDetails) IsPostOnlyForPair(pair currency.Pair) (bool, error) { - w.m.RLock() - defer w.m.RUnlock() - if w.codes == nil { - return false, errCodeMapIsNil - } - for _, v := range w.pairs { - if v.Pair.Equal(pair) { - return v.PostOnly, nil - } - } - return false, errCurrencyNotFoundInMap -} - -// isInitial checks state of maps to determine if they have been loaded or not -func (w *CurrencyDetails) isInitial() bool { - w.m.RLock() - defer w.m.RUnlock() - return w.codes == nil || w.pairs == nil -} diff --git a/exchanges/poloniex/currency_details_test.go b/exchanges/poloniex/currency_details_test.go deleted file mode 100644 index dafd08bbef9..00000000000 --- a/exchanges/poloniex/currency_details_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package poloniex - -import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/thrasher-corp/gocryptotrader/currency" -) - -func TestWsCurrencyMap(t *testing.T) { - var m CurrencyDetails - - if !m.isInitial() { - t.Fatal("unexpected value") - } - - err := m.loadPairs(nil) - require.ErrorIs(t, err, errCannotLoadNoData) - - err = m.loadCodes(nil) - require.ErrorIs(t, err, errCannotLoadNoData) - - _, err = m.GetPair(1337) - require.ErrorIs(t, err, errPairMapIsNil) - - _, err = m.GetCode(1337) - require.ErrorIs(t, err, errCodeMapIsNil) - - _, err = m.GetWithdrawalTXFee(currency.EMPTYCODE) - require.ErrorIs(t, err, errCodeMapIsNil) - - _, err = m.GetDepositAddress(currency.EMPTYCODE) - require.ErrorIs(t, err, errCodeMapIsNil) - - _, err = m.IsWithdrawAndDepositsEnabled(currency.EMPTYCODE) - require.ErrorIs(t, err, errCodeMapIsNil) - - _, err = m.IsTradingEnabledForCurrency(currency.EMPTYCODE) - require.ErrorIs(t, err, errCodeMapIsNil) - - _, err = m.IsTradingEnabledForPair(currency.EMPTYPAIR) - require.ErrorIs(t, err, errCodeMapIsNil) - - _, err = m.IsPostOnlyForPair(currency.EMPTYPAIR) - require.ErrorIs(t, err, errCodeMapIsNil) - - c, err := e.GetCurrencies(t.Context()) - if err != nil { - t.Fatal(err) - } - - err = m.loadCodes(c) - if err != nil { - t.Fatal(err) - } - - tick, err := e.GetTicker(t.Context()) - if err != nil { - t.Fatal(err) - } - - err = m.loadPairs(tick) - if err != nil { - t.Fatal(err) - } - - pTest, err := m.GetPair(1337) - require.ErrorIs(t, err, errIDNotFoundInPairMap) - - if pTest.String() != "1337" { - t.Fatal("unexpected value") - } - - _, err = m.GetCode(1337) - require.ErrorIs(t, err, errIDNotFoundInCodeMap) - - btcusdt, err := m.GetPair(121) - require.NoError(t, err) - - if btcusdt.String() != "USDT_BTC" { - t.Fatal("expecting USDT_BTC pair") - } - - eth, err := m.GetCode(267) - require.NoError(t, err) - - if eth.String() != "ETH" { - t.Fatal("unexpected value") - } - - txFee, err := m.GetWithdrawalTXFee(eth) - if err != nil { - t.Fatal(err) - } - - if txFee == 0 { - t.Fatal("unexpected value") - } - - _, err = m.GetDepositAddress(eth) - require.ErrorIs(t, err, errNoDepositAddress) - - dAddr, err := m.GetDepositAddress(currency.NewCode("BCN")) - require.NoError(t, err) - - if dAddr != "25cZNQYVAi3issDCoa6fWA2Aogd4FgPhYdpX3p8KLfhKC6sN8s6Q9WpcW4778TPwcUS5jEM25JrQvjD3XjsvXuNHSWhYUsu" { - t.Fatal("unexpected deposit address") - } - - wdEnabled, err := m.IsWithdrawAndDepositsEnabled(eth) - require.NoError(t, err) - - if !wdEnabled { - t.Fatal("unexpected results") - } - - tEnabled, err := m.IsTradingEnabledForCurrency(eth) - require.NoError(t, err) - - if !tEnabled { - t.Fatal("unexpected results") - } - - cp := currency.NewPair(currency.USDT, currency.BTC) - - tEnabled, err = m.IsTradingEnabledForPair(cp) - require.NoError(t, err) - - if !tEnabled { - t.Fatal("unexpected results") - } - - postOnly, err := m.IsPostOnlyForPair(cp) - require.NoError(t, err) - - if postOnly { - t.Fatal("unexpected results") - } - - _, err = m.GetWithdrawalTXFee(currency.EMPTYCODE) - require.ErrorIs(t, err, errCurrencyNotFoundInMap) - - _, err = m.GetDepositAddress(currency.EMPTYCODE) - require.ErrorIs(t, err, errCurrencyNotFoundInMap) - - _, err = m.IsWithdrawAndDepositsEnabled(currency.EMPTYCODE) - require.ErrorIs(t, err, errCurrencyNotFoundInMap) - - _, err = m.IsTradingEnabledForCurrency(currency.EMPTYCODE) - require.ErrorIs(t, err, errCurrencyNotFoundInMap) - - _, err = m.IsTradingEnabledForPair(currency.EMPTYPAIR) - require.ErrorIs(t, err, errCurrencyNotFoundInMap) - - _, err = m.IsPostOnlyForPair(currency.EMPTYPAIR) - require.ErrorIs(t, err, errCurrencyNotFoundInMap) -} diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index ab01898ff69..db6ca0fac87 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -3,933 +3,1137 @@ package poloniex import ( "bytes" "context" - "encoding/hex" + "encoding/base64" "errors" "fmt" "net/http" "net/url" "strconv" "strings" + "sync" "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/encoding/json" + "github.com/thrasher-corp/gocryptotrader/exchange/order/limits" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" - "github.com/thrasher-corp/gocryptotrader/exchanges/nonce" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/request" ) const ( - poloniexAPIURL = "https://poloniex.com" - tradeSpot = "/trade/" - tradeFutures = "/futures" + tradeSpot - poloniexAltAPIUrl = "https://api.poloniex.com" - poloniexAPITradingEndpoint = "tradingApi" - poloniexAPIVersion = "1" - poloniexBalances = "returnBalances" - poloniexBalancesComplete = "returnCompleteBalances" - poloniexDepositAddresses = "returnDepositAddresses" - poloniexGenerateNewAddress = "generateNewAddress" - poloniexDepositsWithdrawals = "returnDepositsWithdrawals" - poloniexOrders = "returnOpenOrders" - poloniexTradeHistory = "returnTradeHistory" - poloniexOrderTrades = "returnOrderTrades" - poloniexOrderStatus = "returnOrderStatus" - poloniexOrderCancel = "cancelOrder" - poloniexOrderMove = "moveOrder" - poloniexWithdraw = "withdraw" - poloniexFeeInfo = "returnFeeInfo" - poloniexAvailableBalances = "returnAvailableAccountBalances" - poloniexTradableBalances = "returnTradableBalances" - poloniexTransferBalance = "transferBalance" - poloniexMarginAccountSummary = "returnMarginAccountSummary" - poloniexMarginBuy = "marginBuy" - poloniexMarginSell = "marginSell" - poloniexMarginPosition = "getMarginPosition" - poloniexMarginPositionClose = "closeMarginPosition" - poloniexCreateLoanOffer = "createLoanOffer" - poloniexCancelLoanOffer = "cancelLoanOffer" - poloniexOpenLoanOffers = "returnOpenLoanOffers" - poloniexActiveLoans = "returnActiveLoans" - poloniexLendingHistory = "returnLendingHistory" - poloniexAutoRenew = "toggleAutoRenew" - poloniexCancelByIDs = "/orders/cancelByIds" - poloniexTimestamp = "/timestamp" - poloniexWalletActivity = "/wallets/activity" - poloniexMaxOrderbookDepth = 100 + v3Path = "/v3/" + mainURL = "https://www.poloniex.com" + apiURL = "https://api.poloniex.com" + tradeSpotPath = "/trade/" + tradeFuturesPath = "/futures/trade/" + marketsPath = "/markets/" ) -// Exchange implements exchange.IBotExchange and contains additional specific api methods for interacting with Poloniex +var ( + errAddressRequired = errors.New("address is required") + errInvalidWithdrawalChain = errors.New("invalid withdrawal chain") + errInvalidTimeout = errors.New("invalid timeout") + errAccountIDRequired = errors.New("missing account ID") + errAccountTypeRequired = errors.New("account type required") + errInvalidTrailingOffset = errors.New("invalid trailing offset") + errInvalidOffsetLimit = errors.New("invalid trailing offset limit") +) + +// Exchange is the overarching type across the poloniex package type Exchange struct { exchange.Base - details CurrencyDetails + + // The following mutexes exists to prevent concurrent `subscribe` and `unsubscribe` calls. + // When both run asynchronously and fail, the server may return identical error + // responses (e.g., `{ "event": "error", "message": "invalid symbol" }`), where + // the exact message may vary. Such responses do not indicate which operation + // failed, making synchronization necessary. + spotSubMtx sync.Mutex + futuresSubMtx sync.Mutex } -// GetTicker returns current ticker information -func (e *Exchange) GetTicker(ctx context.Context) (map[string]Ticker, error) { - type response struct { - Data map[string]Ticker +// GetSymbol returns symbol and trade limit info +func (e *Exchange) GetSymbol(ctx context.Context, symbol currency.Pair) ([]*SymbolDetails, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty } + var resp []*SymbolDetails + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, marketsPath+symbol.String(), &resp) +} - resp := response{} - path := "/public?command=returnTicker" +// GetSymbols returns all symbols and their trade limits +func (e *Exchange) GetSymbols(ctx context.Context) ([]*SymbolDetails, error) { + var resp []*SymbolDetails + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, referenceDataEPL, "/markets", &resp) +} - return resp.Data, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp.Data) +// GetCurrencies retrieves currencies and their details +func (e *Exchange) GetCurrencies(ctx context.Context) ([]*Currency, error) { + var resp []*Currency + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, referenceDataEPL, "/v2/currencies", &resp) } -// GetVolume returns a list of currencies with associated volume -func (e *Exchange) GetVolume(ctx context.Context) (any, error) { - var resp any - path := "/public?command=return24hVolume" +// GetCurrency retrieves a currency's details +func (e *Exchange) GetCurrency(ctx context.Context, ccy currency.Code) (*Currency, error) { + if ccy.IsEmpty() { + return nil, currency.ErrCurrencyCodeEmpty + } + var resp *Currency + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, "/v2/currencies/"+ccy.String(), &resp) +} - return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp) +// GetSystemTimestamp retrieves the current server time. +func (e *Exchange) GetSystemTimestamp(ctx context.Context) (time.Time, error) { + var resp ServerSystemTime + err := e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, "/timestamp", &resp) + return resp.ServerTime.Time(), err } -// GetOrderbook returns the full orderbook from poloniex -func (e *Exchange) GetOrderbook(ctx context.Context, currencyPair string, depth int) (OrderbookAll, error) { - vals := url.Values{} +// GetMarketPrices retrieves the latest trade price for all symbols. +func (e *Exchange) GetMarketPrices(ctx context.Context) ([]*MarketPrice, error) { + var resp []*MarketPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, referenceDataEPL, "/markets/price", &resp) +} - if depth != 0 { - vals.Set("depth", strconv.Itoa(depth)) +// GetMarketPrice retrieves the latest trade price for a symbol +func (e *Exchange) GetMarketPrice(ctx context.Context, symbol currency.Pair) (*MarketPrice, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } - - oba := OrderbookAll{Data: make(map[string]Orderbook)} - if currencyPair != "" { - vals.Set("currencyPair", currencyPair) - resp := OrderbookResponse{} - path := "/public?command=returnOrderBook&" + vals.Encode() - if err := e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp); err != nil { - return oba, err - } - if resp.Error != "" { - return oba, fmt.Errorf("%s GetOrderbook() error: %s", e.Name, resp.Error) - } - oba.Data[currencyPair] = Orderbook{ - Bids: resp.Bids.Levels(), - Asks: resp.Asks.Levels(), - } - } else { - vals.Set("currencyPair", "all") - resp := OrderbookResponseAll{} - path := "/public?command=returnOrderBook&" + vals.Encode() - if err := e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp.Data); err != nil { - return oba, err - } - for currency, orderbook := range resp.Data { - oba.Data[currency] = Orderbook{ - Bids: orderbook.Bids.Levels(), - Asks: orderbook.Asks.Levels(), - } - } - } - return oba, nil + var resp *MarketPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, marketsPath+symbol.String()+"/price", &resp) } -// GetTradeHistory returns trades history from poloniex -func (e *Exchange) GetTradeHistory(ctx context.Context, currencyPair string, start, end int64) ([]TradeHistory, error) { - vals := url.Values{} - vals.Set("currencyPair", currencyPair) +// GetMarkPrices retrieves the latest mark prices for all currencies +func (e *Exchange) GetMarkPrices(ctx context.Context) ([]*MarkPrice, error) { + var resp []*MarkPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, referenceDataEPL, "/markets/markPrice", &resp) +} - if start > 0 { - vals.Set("start", strconv.FormatInt(start, 10)) +// GetMarkPrice retrieves the latest mark price for a symbol. +func (e *Exchange) GetMarkPrice(ctx context.Context, symbol currency.Pair) (*MarkPrice, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } + var resp *MarkPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, marketsPath+symbol.String()+"/markPrice", &resp) +} - if end > 0 { - vals.Set("end", strconv.FormatInt(end, 10)) +// GetMarkPriceComponents retrieves the components of a mark price +func (e *Exchange) GetMarkPriceComponents(ctx context.Context, symbol currency.Pair) (*MarkPriceComponents, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } - - var resp []TradeHistory - path := "/public?command=returnTradeHistory&" + vals.Encode() - return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp) + var resp *MarkPriceComponents + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, marketsPath+symbol.String()+"/markPriceComponents", &resp) } -// GetChartData returns chart data for a specific currency pair -func (e *Exchange) GetChartData(ctx context.Context, currencyPair string, start, end time.Time, period string) ([]ChartData, error) { - vals := url.Values{} - vals.Set("currencyPair", currencyPair) - - if !start.IsZero() { - vals.Set("start", strconv.FormatInt(start.Unix(), 10)) +// GetOrderbook retrieves the order book for a symbol +// possible scale values are 0.1, 1, 10, and 100 +func (e *Exchange) GetOrderbook(ctx context.Context, symbol currency.Pair, scale float64, limit uint64) (*OrderbookData, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } - - if !end.IsZero() { - vals.Set("end", strconv.FormatInt(end.Unix(), 10)) + params := url.Values{} + if scale > 0 { + params.Set("scale", strconv.FormatFloat(scale, 'f', -1, 64)) } - - if period != "" { - vals.Set("period", period) + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) } + var resp *OrderbookData + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, common.EncodeURLValues(marketsPath+symbol.String()+"/orderBook", params), &resp) +} - var temp json.RawMessage - path := "/public?command=returnChartData&" + vals.Encode() - err := e.SendHTTPRequest(ctx, exchange.RestSpot, path, &temp) +// GetCandlesticks retrieves candlestick data +func (e *Exchange) GetCandlesticks(ctx context.Context, symbol currency.Pair, interval kline.Interval, startTime, endTime time.Time, limit uint64) ([]*CandlestickData, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty + } + intervalString, err := intervalToString(interval) if err != nil { return nil, err } - - var resp []ChartData - err = json.Unmarshal(temp, &resp) - if err != nil { - var errResp struct { - Error string `json:"error"` - } - if errRet := json.Unmarshal(temp, &errResp); errRet != nil { - return nil, errRet - } - if errResp.Error != "" { - return nil, errors.New(errResp.Error) + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err } } - - return resp, err -} - -// GetCurrencies returns information about currencies -func (e *Exchange) GetCurrencies(ctx context.Context) (map[string]*Currencies, error) { - type Response struct { - Data map[string]*Currencies + params := url.Values{} + if !startTime.IsZero() { + params.Set("startTime", strconv.FormatInt(startTime.UnixMilli(), 10)) } - resp := Response{} - return resp.Data, e.SendHTTPRequest(ctx, - exchange.RestSpot, - "/public?command=returnCurrencies&includeMultiChainCurrencies=true", - &resp.Data, - ) + if !endTime.IsZero() { + params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + params.Set("interval", intervalString) + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*CandlestickData + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, common.EncodeURLValues(marketsPath+symbol.String()+"/candles", params), &resp) } -// GetTimestamp returns server time -func (e *Exchange) GetTimestamp(ctx context.Context) (time.Time, error) { - var resp TimeStampResponse - err := e.SendHTTPRequest(ctx, - exchange.RestSpotSupplementary, - poloniexTimestamp, - &resp, - ) - if err != nil { - return time.Time{}, err +// GetTrades returns a list of recent trades, the request param limit is optional, its default value is 500, and its max value is 1000. +func (e *Exchange) GetTrades(ctx context.Context, symbol currency.Pair, limit uint64) ([]*Trade, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty + } + params := url.Values{} + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) } - return resp.ServerTime.Time(), nil + var resp []*Trade + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, common.EncodeURLValues(marketsPath+symbol.String()+"/trades", params), &resp) } -// GetLoanOrders returns the list of loan offers and demands for a given -// currency, specified by the "currency" GET parameter. -func (e *Exchange) GetLoanOrders(ctx context.Context, ccy string) (LoanOrders, error) { - resp := LoanOrders{} - path := "/public?command=returnLoanOrders¤cy=" + ccy - return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp) +// GetTickers retrieves tickers for the last 24 hours for all symbols. +func (e *Exchange) GetTickers(ctx context.Context) ([]*TickerData, error) { + var resp []*TickerData + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, referenceDataEPL, "/markets/ticker24h", &resp) } -// GetBalances returns balances for your account. -func (e *Exchange) GetBalances(ctx context.Context) (map[currency.Code]float64, error) { - var result any - if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexBalances, url.Values{}, &result); err != nil { - return nil, err - } - - data, ok := result.(map[string]any) - if !ok { - return nil, common.GetTypeAssertError("map[string]any", result, "balance result") +// GetTicker retrieves ticker for the last 24 hours for a symbol +func (e *Exchange) GetTicker(ctx context.Context, symbol currency.Pair) (*TickerData, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } + var resp *TickerData + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, marketsPath+symbol.String()+"/ticker24h", &resp) +} - bals := make(map[currency.Code]float64, len(data)) - - for x, y := range data { - bal, ok := y.(string) - if !ok { - return nil, common.GetTypeAssertError("string", y, "balance amount") - } - - var err error - if bals[currency.NewCode(x)], err = strconv.ParseFloat(bal, 64); err != nil { - return nil, err - } +// GetCollateral retrieves collateral information for a currency +func (e *Exchange) GetCollateral(ctx context.Context, ccy currency.Code) (*CollateralDetails, error) { + if ccy.IsEmpty() { + return nil, currency.ErrCurrencyCodeEmpty } + var resp *CollateralDetails + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, marketsPath+ccy.String()+"/collateralInfo", &resp) +} - return bals, nil +// GetCollaterals retrieves an account's collaterals information +func (e *Exchange) GetCollaterals(ctx context.Context) ([]*CollateralDetails, error) { + var resp []*CollateralDetails + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, referenceDataEPL, "/markets/collateralInfo", &resp) } -// GetCompleteBalances returns complete balances from your account. -func (e *Exchange) GetCompleteBalances(ctx context.Context) (CompleteBalances, error) { - var result CompleteBalances - vals := url.Values{} - vals.Set("account", "all") - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, - http.MethodPost, - poloniexBalancesComplete, - vals, - &result) - return result, err +// GetBorrowRate retrieves borrow rates information for all tiers and currencies. +func (e *Exchange) GetBorrowRate(ctx context.Context) ([]*BorrowRateDetails, error) { + var resp []*BorrowRateDetails + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, publicEPL, "/markets/borrowRatesInfo", &resp) } -// GetDepositAddresses returns deposit addresses for all enabled cryptos. -func (e *Exchange) GetDepositAddresses(ctx context.Context) (DepositAddresses, error) { - var result any - addresses := DepositAddresses{} +// GetAccount retrieves all of a user's accounts. +func (e *Exchange) GetAccount(ctx context.Context) ([]*AccountDetails, error) { + var resp []*AccountDetails + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountInfoEPL, http.MethodGet, "/accounts", nil, nil, &resp) +} - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexDepositAddresses, url.Values{}, &result) - if err != nil { - return addresses, err +// GetBalances retrieves all account balances for the authorised user +func (e *Exchange) GetBalances(ctx context.Context, accountType string) ([]*AccountBalances, error) { + params := url.Values{} + if accountType != "" { + params.Set("accountType", accountType) } + var resp []*AccountBalances + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountBalancesEPL, http.MethodGet, "/accounts/balances", params, nil, &resp) +} - addresses.Addresses = make(map[string]string) - data, ok := result.(map[string]any) - if !ok { - return addresses, errors.New("return val not map[string]any") +// GetAccountBalances gets balances for an account +func (e *Exchange) GetAccountBalances(ctx context.Context, accountID, accountType string) ([]*AccountBalances, error) { + if accountID == "" { + return nil, errAccountIDRequired + } + params := url.Values{} + if accountType != "" { + params.Set("accountType", accountType) } + var resp []*AccountBalances + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountBalancesEPL, http.MethodGet, "/accounts/"+accountID+"/balances", params, nil, &resp) +} - for x, y := range data { - addresses.Addresses[x], ok = y.(string) - if !ok { - return addresses, common.GetTypeAssertError("string", y, "address") +// GetAccountActivities retrieves a list of activities such as airdrop, rebates, staking, credit/debit adjustments, and other (historical adjustments). +// possible account activity types are: 200 for ALL, 201 for AIRDROP, 202 for COMMISSION_REBATE, 203, REFERRAL_REBATE: 204, SWAP: 205, CREDIT_ADJUSTMENT: 104, DEBIT_ADJUSTMENT: 105, OTHER: 199 +func (e *Exchange) GetAccountActivities(ctx context.Context, startTime, endTime time.Time, activityType, limit, from uint64, direction string, ccy currency.Code) ([]*AccountActivity, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err } } - - return addresses, nil + params := url.Values{} + if !startTime.IsZero() { + params.Set("startTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if activityType != 0 { + params.Set("activityType", strconv.FormatUint(activityType, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + if from != 0 { + params.Set("from", strconv.FormatUint(from, 10)) + } + if direction != "" { + params.Set("direction", direction) + } + if !ccy.IsEmpty() { + params.Set("currency", ccy.String()) + } + var resp []*AccountActivity + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountActivityEPL, http.MethodGet, "/accounts/activity", params, nil, &resp) } -// GenerateNewAddress generates a new address for a currency -func (e *Exchange) GenerateNewAddress(ctx context.Context, curr string) (string, error) { - type Response struct { - Success int - Error string - Response string +// AccountsTransfer transfers currencies between accounts +func (e *Exchange) AccountsTransfer(ctx context.Context, arg *AccountTransferRequest) (*AccountTransferResponse, error) { + if arg.Currency.IsEmpty() { + return nil, currency.ErrCurrencyCodeEmpty } - resp := Response{} - values := url.Values{} - values.Set("currency", curr) - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexGenerateNewAddress, values, &resp) - if err != nil { - return "", err + if arg.Amount <= 0 { + return nil, fmt.Errorf("%w, amount has to be greater than zero", order.ErrAmountIsInvalid) } - - if resp.Error != "" { - return "", errors.New(resp.Error) + if arg.FromAccount == "" { + return nil, fmt.Errorf("%w: FromAccount", errAddressRequired) } - - return resp.Response, nil + if arg.ToAccount == "" { + return nil, fmt.Errorf("%w: ToAccount", errAddressRequired) + } + var resp *AccountTransferResponse + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountsTransferEPL, http.MethodPost, "/accounts/transfer", nil, arg, &resp) } -// GetDepositsWithdrawals returns a list of deposits and withdrawals -func (e *Exchange) GetDepositsWithdrawals(ctx context.Context, start, end string) (DepositsWithdrawals, error) { - resp := DepositsWithdrawals{} - values := url.Values{} - - if start != "" { - values.Set("start", start) - } else { - values.Set("start", "0") +// GetAccountsTransferRecords gets a list of a user's transfer records +func (e *Exchange) GetAccountsTransferRecords(ctx context.Context, startTime, endTime time.Time, direction string, ccy currency.Code, from, limit uint64) ([]*AccountTransferRecord, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } } - - if end != "" { - values.Set("end", end) - } else { - values.Set("end", strconv.FormatInt(time.Now().Unix(), 10)) + params := url.Values{} + if !startTime.IsZero() { + params.Set("startTime", strconv.FormatInt(startTime.UnixMilli(), 10)) } - - return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexDepositsWithdrawals, values, &resp) + if !endTime.IsZero() { + params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if !ccy.IsEmpty() { + params.Set("currency", ccy.String()) + } + if direction != "" { + params.Set("direction", direction) + } + if from != 0 { + params.Set("from", strconv.FormatUint(from, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*AccountTransferRecord + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountsTransferRecordsEPL, http.MethodGet, "/accounts/transfer", params, nil, &resp) } -// GetOpenOrders returns current unfilled opened orders -func (e *Exchange) GetOpenOrders(ctx context.Context, ccy string) (OpenOrdersResponse, error) { - values := url.Values{} - values.Set("currencyPair", ccy) - result := OpenOrdersResponse{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexOrders, values, &result.Data) +// GetAccountsTransferRecordByTransferID gets a user's transfer record +func (e *Exchange) GetAccountsTransferRecordByTransferID(ctx context.Context, transferID string) (*AccountTransferRecord, error) { + if transferID == "" { + return nil, errAccountIDRequired + } + var resp *AccountTransferRecord + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountsTransferRecordsEPL, http.MethodGet, "/accounts/transfer/"+transferID, nil, nil, &resp) } -// GetOpenOrdersForAllCurrencies returns all open orders -func (e *Exchange) GetOpenOrdersForAllCurrencies(ctx context.Context) (OpenOrdersResponseAll, error) { - values := url.Values{} - values.Set("currencyPair", "all") - result := OpenOrdersResponseAll{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexOrders, values, &result.Data) +// GetFeeInfo retrieves the fee rate for an account +func (e *Exchange) GetFeeInfo(ctx context.Context) (*FeeInfo, error) { + var resp *FeeInfo + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sFeeInfoEPL, http.MethodGet, "/feeinfo", nil, nil, &resp) } -// GetAuthenticatedTradeHistoryForCurrency returns account trade history -func (e *Exchange) GetAuthenticatedTradeHistoryForCurrency(ctx context.Context, currencyPair string, start, end, limit int64) (AuthenticatedTradeHistoryResponse, error) { - values := url.Values{} - - if start > 0 { - values.Set("start", strconv.FormatInt(start, 10)) +// GetInterestHistory gets a list of a user's interest collection records +func (e *Exchange) GetInterestHistory(ctx context.Context, startTime, endTime time.Time, direction string, from, limit uint64) ([]*InterestHistory, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } } - - if limit > 0 { - values.Set("limit", strconv.FormatInt(limit, 10)) + params := url.Values{} + if !startTime.IsZero() { + params.Set("startTime", strconv.FormatInt(startTime.UnixMilli(), 10)) } - - if end > 0 { - values.Set("end", strconv.FormatInt(end, 10)) + if !endTime.IsZero() { + params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if direction != "" { + params.Set("direction", direction) + } + if from != 0 { + params.Set("from", strconv.FormatUint(from, 10)) } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*InterestHistory + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sInterestHistoryEPL, http.MethodGet, "/accounts/interest/history", params, nil, &resp) +} - values.Set("currencyPair", currencyPair) - result := AuthenticatedTradeHistoryResponse{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexTradeHistory, values, &result.Data) +// GetSubAccount gets a list of all the accounts within a user's Account Group. +func (e *Exchange) GetSubAccount(ctx context.Context) ([]*SubAccount, error) { + var resp []*SubAccount + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSubAccountEPL, http.MethodGet, "/subaccounts", nil, nil, &resp) } -// GetAuthenticatedTradeHistory returns account trade history -func (e *Exchange) GetAuthenticatedTradeHistory(ctx context.Context, start, end, limit int64) (AuthenticatedTradeHistoryAll, error) { - values := url.Values{} +// GetSubAccountBalances retrieves balances by currency and account type (SPOT or FUTURES) for all accounts in the group. Available only to the primary user. +func (e *Exchange) GetSubAccountBalances(ctx context.Context) ([]*SubAccountBalances, error) { + var resp []*SubAccountBalances + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSubAccountBalancesEPL, http.MethodGet, "/subaccounts/balances", nil, nil, &resp) +} - if start > 0 { - values.Set("start", strconv.FormatInt(start, 10)) +// GetSubAccountBalance gets balance information by currency and account type (SPOT and FUTURES) for a given external accountId in the account group. +// Subaccounts should use GetBalances() for SPOT and the Futures API for FUTURES. +func (e *Exchange) GetSubAccountBalance(ctx context.Context, subAccountID string) ([]*SubAccountBalances, error) { + if subAccountID == "" { + return nil, fmt.Errorf("%w: empty subAccountID", errAccountIDRequired) } + var resp []*SubAccountBalances + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSubAccountBalancesEPL, http.MethodGet, "/subaccounts/"+subAccountID+"/balances", nil, nil, &resp) +} - if limit > 0 { - values.Set("limit", strconv.FormatInt(limit, 10)) +// SubAccountTransfer transfers currencies between accounts in the account group +// Primary account can transfer to and from any subaccounts as well as transfer between 2 subaccounts across account types. +// Subaccount can only transfer to the primary account across account types. +func (e *Exchange) SubAccountTransfer(ctx context.Context, arg *SubAccountTransferRequest) (*AccountTransferResponse, error) { + if arg.Currency.IsEmpty() { + return nil, currency.ErrCurrencyCodeEmpty } - - if end > 0 { - values.Set("end", strconv.FormatInt(end, 10)) + if arg.Amount <= 0 { + return nil, order.ErrAmountIsInvalid } + if arg.FromAccountID == "" { + return nil, fmt.Errorf("%w: FromAccountID", errAccountIDRequired) + } + if arg.ToAccountID == "" { + return nil, fmt.Errorf("%w: ToAccountID", errAccountIDRequired) + } + if arg.FromAccountType == "" { + return nil, fmt.Errorf("%w: FromAccountType", errAccountTypeRequired) + } + if arg.ToAccountType == "" { + return nil, fmt.Errorf("%w: ToAccountType", errAccountTypeRequired) + } + var resp *AccountTransferResponse + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSubAccountTransfersEPL, http.MethodPost, "/subaccounts/transfer", nil, arg, &resp) +} - values.Set("currencyPair", "all") - var result json.RawMessage - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexTradeHistory, values, &result) - if err != nil { - return AuthenticatedTradeHistoryAll{}, err +// GetSubAccountTransferRecords gets a list of transfer records involving a user's subaccounts. Max interval for start and end time is 6 months. +func (e *Exchange) GetSubAccountTransferRecords(ctx context.Context, arg *SubAccountTransferRecordRequest) ([]*SubAccountTransfer, error) { + if !arg.StartTime.IsZero() && !arg.EndTime.IsZero() { + if err := common.StartEndTimeCheck(arg.StartTime, arg.EndTime); err != nil { + return nil, err + } } + params := url.Values{} + if !arg.StartTime.IsZero() { + params.Set("startTime", strconv.FormatInt(arg.StartTime.UnixMilli(), 10)) + } + if !arg.EndTime.IsZero() { + params.Set("endTime", strconv.FormatInt(arg.EndTime.UnixMilli(), 10)) + } + if !arg.Currency.IsEmpty() { + params.Set("currency", arg.Currency.String()) + } + if arg.FromAccountID != "" { + params.Set("fromAccountID", arg.FromAccountID) + } + if arg.ToAccountID != "" { + params.Set("toAccountID", arg.ToAccountID) + } + if arg.FromAccountType != "" { + params.Set("fromAccountType", arg.FromAccountType) + } + if arg.ToAccountType != "" { + params.Set("toAccountType", arg.ToAccountType) + } + if arg.Direction != "" { + params.Set("direction", arg.Direction) + } + if arg.From > 0 { + params.Set("from", strconv.FormatUint(arg.From, 10)) + } + if arg.Limit > 0 { + params.Set("limit", strconv.FormatUint(arg.Limit, 10)) + } + var resp []*SubAccountTransfer + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSubAccountTransfersEPL, http.MethodGet, "/subaccounts/transfer", params, nil, &resp) +} - var nodata []any - err = json.Unmarshal(result, &nodata) - if err == nil { - return AuthenticatedTradeHistoryAll{}, nil +// GetSubAccountTransferRecord retrieves a subaccount transfer record. +func (e *Exchange) GetSubAccountTransferRecord(ctx context.Context, id string) ([]*SubAccountTransfer, error) { + if id == "" { + return nil, fmt.Errorf("%w: subAccountID is missing", errAccountIDRequired) } + var resp []*SubAccountTransfer + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSubAccountTransfersEPL, http.MethodGet, "/subaccounts/transfer/"+id, nil, nil, &resp) +} - var mainResult AuthenticatedTradeHistoryAll - return mainResult, json.Unmarshal(result, &mainResult.Data) +// GetDepositAddresses gets all of a user's deposit addresses. +func (e *Exchange) GetDepositAddresses(ctx context.Context, ccy currency.Code) (DepositAddresses, error) { + params := url.Values{} + if !ccy.IsEmpty() { + params.Set("currency", ccy.String()) + } + var addresses DepositAddresses + return addresses, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetDepositAddressesEPL, http.MethodGet, "/wallets/addresses", params, nil, &addresses) } -// GetAuthenticatedOrderStatus returns the status of a given orderId. -func (e *Exchange) GetAuthenticatedOrderStatus(ctx context.Context, orderID string) (o OrderStatusData, err error) { +// WalletActivity returns the wallet activity between the set start and end times +// possible wallet activity types are 'deposits' and 'withdrawals' +func (e *Exchange) WalletActivity(ctx context.Context, start, end time.Time, activityType string) (*WalletActivity, error) { + if err := common.StartEndTimeCheck(start, end); err != nil { + return nil, err + } values := url.Values{} - - if orderID == "" { - return o, errors.New("no orderID passed") + values.Set("start", strconv.FormatInt(start.Unix(), 10)) + values.Set("end", strconv.FormatInt(end.Unix(), 10)) + if activityType != "" { + values.Set("activityType", activityType) } + var resp *WalletActivity + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetWalletActivityRecordsEPL, http.MethodGet, "/wallets/activity", values, nil, &resp) +} - values.Set("orderNumber", orderID) - var rawOrderStatus OrderStatus - err = e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexOrderStatus, values, &rawOrderStatus) - if err != nil { - return o, err +// NewCurrencyDepositAddress creates a new deposit address for a currency. +func (e *Exchange) NewCurrencyDepositAddress(ctx context.Context, ccy currency.Code) (string, error) { + if ccy.IsEmpty() { + return "", currency.ErrCurrencyCodeEmpty } + var resp struct { + Address string `json:"address"` + } + return resp.Address, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetWalletAddressesEPL, http.MethodPost, "/wallets/address", nil, map[string]string{"currency": ccy.String()}, &resp) +} - switch rawOrderStatus.Success { - case 0: // fail - var errMsg GenericResponse - err = json.Unmarshal(rawOrderStatus.Result, &errMsg) - if err != nil { - return o, err - } - return o, errors.New(errMsg.Error) - case 1: // success - var status map[string]OrderStatusData - err = json.Unmarshal(rawOrderStatus.Result, &status) - if err != nil { - return o, err - } +var supportedIntervals = []struct { + key string + val kline.Interval +}{ + {key: "MINUTE_1", val: kline.OneMin}, + {key: "MINUTE_5", val: kline.FiveMin}, + {key: "MINUTE_10", val: kline.TenMin}, + {key: "MINUTE_15", val: kline.FifteenMin}, + {key: "MINUTE_30", val: kline.ThirtyMin}, + {key: "HOUR_1", val: kline.OneHour}, + {key: "HOUR_2", val: kline.TwoHour}, + {key: "HOUR_4", val: kline.FourHour}, + {key: "HOUR_6", val: kline.SixHour}, + {key: "HOUR_8", val: kline.EightHour}, + {key: "HOUR_12", val: kline.TwelveHour}, + {key: "DAY_1", val: kline.OneDay}, + {key: "DAY_3", val: kline.ThreeDay}, + {key: "WEEK_1", val: kline.SevenDay}, + {key: "MONTH_1", val: kline.OneMonth}, +} - for _, o = range status { - return o, err +func stringToInterval(interval string) (kline.Interval, error) { + interval = strings.ToUpper(interval) + for x := range supportedIntervals { + if supportedIntervals[x].key == interval { + return supportedIntervals[x].val, nil } } - - return o, err + return kline.Interval(0), fmt.Errorf("%w: %q", kline.ErrUnsupportedInterval, interval) } -// GetAuthenticatedOrderTrades returns all trades involving a given orderId. -func (e *Exchange) GetAuthenticatedOrderTrades(ctx context.Context, orderID string) (o []OrderTrade, err error) { - values := url.Values{} - - if orderID == "" { - return nil, errors.New("no orderID passed") +func intervalToString(interval kline.Interval) (string, error) { + for x := range supportedIntervals { + if supportedIntervals[x].val == interval { + return supportedIntervals[x].key, nil + } } + return "", kline.ErrUnsupportedInterval +} - values.Set("orderNumber", orderID) - var result json.RawMessage - err = e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexOrderTrades, values, &result) - if err != nil { - return nil, err +// WithdrawCurrency withdraws a currency to a specific designated address +func (e *Exchange) WithdrawCurrency(ctx context.Context, arg *WithdrawCurrencyRequest) (*Withdraw, error) { + if arg.Coin.IsEmpty() { + return nil, currency.ErrCurrencyCodeEmpty } - - if len(result) == 0 { - return nil, errors.New("received unexpected response") + if arg.Amount <= 0 { + return nil, limits.ErrAmountBelowMin } - - switch result[0] { - case '{': // error message received - var resp GenericResponse - err = json.Unmarshal(result, &resp) - if err != nil { - return nil, err - } - if resp.Error != "" { - err = errors.New(resp.Error) - } - case '[': // data received - err = json.Unmarshal(result, &o) - default: - return nil, errors.New("received unexpected response") + if arg.Network == "" { + return nil, errInvalidWithdrawalChain } - - return o, err + if arg.Address == "" { + return nil, errAddressRequired + } + var resp *Withdraw + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sWithdrawCurrencyEPL, http.MethodPost, "/v2/wallets/withdraw", nil, arg, &resp) } -// PlaceOrder places a new order on the exchange -func (e *Exchange) PlaceOrder(ctx context.Context, currencyPair string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) { - result := OrderResponse{} - values := url.Values{} - - var orderType string - if buy { - orderType = order.Buy.Lower() - } else { - orderType = order.Sell.Lower() +// GetAccountMargin retrieves the account's margin information +func (e *Exchange) GetAccountMargin(ctx context.Context, accountType string) (*AccountMargin, error) { + if accountType == "" { + return nil, errAccountTypeRequired } + params := url.Values{} + params.Set("accountType", accountType) + var resp *AccountMargin + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sAccountMarginEPL, http.MethodGet, "/margin/accountMargin", params, nil, &resp) +} - values.Set("currencyPair", currencyPair) - values.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64)) - values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - - if immediate { - values.Set("immediateOrCancel", "1") +// GetBorrowStatus retrieves the borrow status of the provided currency, or all currencies if left empty +func (e *Exchange) GetBorrowStatus(ctx context.Context, ccy currency.Code) ([]*BorrowStatus, error) { + params := url.Values{} + if !ccy.IsEmpty() { + params.Set("currency", ccy.String()) } + var resp []*BorrowStatus + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sBorrowStatusEPL, http.MethodGet, "/margin/borrowStatus", params, nil, &resp) +} - if fillOrKill { - values.Set("fillOrKill", "1") +// GetMarginBuySellAmounts gets the maximum and available margin buy/sell amounts for a given symbol +func (e *Exchange) GetMarginBuySellAmounts(ctx context.Context, symbol currency.Pair) (*MarginBuySellAmount, error) { + if symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } - - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, orderType, values, &result) + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp *MarginBuySellAmount + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sMaxMarginSizeEPL, http.MethodGet, "/margin/maxSize", params, nil, &resp) } -// CancelExistingOrder cancels and order by orderID -func (e *Exchange) CancelExistingOrder(ctx context.Context, orderID int64) error { - result := GenericResponse{} - values := url.Values{} - values.Set("orderNumber", strconv.FormatInt(orderID, 10)) - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexOrderCancel, values, &result) - if err != nil { - return err +func validateOrderRequest(arg *PlaceOrderRequest) error { + if arg.Symbol.IsEmpty() { + return currency.ErrCurrencyPairEmpty } - - if result.Success != 1 { - return errors.New(result.Error) + if arg.Side == order.UnknownSide { + return fmt.Errorf("%w: %s", order.ErrSideIsInvalid, arg.Side) + } + isMarket := arg.Type == OrderType(order.Market) || arg.Type == OrderType(order.UnknownType) + if !isMarket && arg.Price <= 0 { + return fmt.Errorf("%w: price is required for non-market orders", limits.ErrPriceBelowMin) + } + if (arg.Type == OrderType(order.Limit) && arg.BaseAmount <= 0) || + (isMarket && arg.Side == order.Sell && arg.BaseAmount <= 0) { + return fmt.Errorf("%w: base quantity is required for market sell or limit orders", limits.ErrAmountBelowMin) + } + if isMarket && arg.Side == order.Buy && arg.QuoteAmount <= 0 { + return fmt.Errorf("%w: quote amount is required for market buy orders", limits.ErrAmountBelowMin) } - return nil } -// MoveOrder moves an order -func (e *Exchange) MoveOrder(ctx context.Context, orderID int64, rate, amount float64, postOnly, immediateOrCancel bool) (MoveOrderResponse, error) { - result := MoveOrderResponse{} - values := url.Values{} - - if orderID == 0 { - return result, errors.New("orderID cannot be zero") +// PlaceOrder places an order +func (e *Exchange) PlaceOrder(ctx context.Context, arg *PlaceOrderRequest) (*OrderIDResponse, error) { + if err := validateOrderRequest(arg); err != nil { + return nil, err } - - if rate == 0 { - return result, errors.New("rate cannot be zero") - } - - values.Set("orderNumber", strconv.FormatInt(orderID, 10)) - values.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64)) - - if postOnly { - values.Set("postOnly", "true") + var resp OrderIDResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sCreateOrderEPL, http.MethodPost, "/orders", nil, arg, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrPlaceFailed, err) } + return &resp, nil +} - if immediateOrCancel { - values.Set("immediateOrCancel", "true") +// PlaceBatchOrders places a batch of orders +func (e *Exchange) PlaceBatchOrders(ctx context.Context, args []PlaceOrderRequest) ([]*OrderIDResponse, error) { + if len(args) == 0 { + return nil, common.ErrNilPointer } - - if amount != 0 { - values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) + for x := range args { + if err := validateOrderRequest(&args[x]); err != nil { + return nil, err + } } - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, - poloniexOrderMove, - values, - &result) + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*OrderIDResponse](ctx, e, exchange.RestSpot, sBatchOrderEPL, http.MethodPost, "/orders/batch", nil, args) if err != nil { - return result, err + return resp, fmt.Errorf("%w: %w", order.ErrPlaceFailed, err) } - - if result.Success != 1 { - return result, errors.New(result.Error) - } - - return result, nil + return resp, nil } -// Withdraw withdraws a currency to a specific delegated address. -// For currencies where there are multiple networks to choose from (like USDT or BTC), -// you can specify the chain by setting the "currency" parameter to be a multiChain currency -// name, like USDTTRON, USDTETH, or BTCTRON -func (e *Exchange) Withdraw(ctx context.Context, ccy, address string, amount float64) (*Withdraw, error) { - result := &Withdraw{} - values := url.Values{} - - values.Set("currency", strings.ToUpper(ccy)) - values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - values.Set("address", address) - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexWithdraw, values, &result) +// CancelReplaceOrder cancels an existing active order, new or partially filled, and places a new order +func (e *Exchange) CancelReplaceOrder(ctx context.Context, arg *CancelReplaceOrderRequest) (*CancelReplaceOrderResponse, error) { + path, err := orderPath(arg.OrderID, "/orders/", arg.ClientOrderID, "/orders/cid:") if err != nil { return nil, err } - - if result.Error != "" { - return nil, errors.New(result.Error) + var resp *CancelReplaceOrderResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sCancelReplaceOrderEPL, http.MethodPut, path, nil, arg, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } - - return result, nil + return resp, nil } -// GetFeeInfo returns fee information -func (e *Exchange) GetFeeInfo(ctx context.Context) (Fee, error) { - result := Fee{} - - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexFeeInfo, url.Values{}, &result) +// GetOpenOrders retrieves a list of active orders +func (e *Exchange) GetOpenOrders(ctx context.Context, symbol currency.Pair, side, direction, fromOrderID string, limit uint64) ([]*TradeOrder, error) { + params := url.Values{} + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + if side != "" { + params.Set("side", side) + } + if fromOrderID != "" { + params.Set("from", fromOrderID) + } + if direction != "" { + params.Set("direction", direction) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*TradeOrder + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetOpenOrdersEPL, http.MethodGet, "/orders", params, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrGetFailed, err) + } + return resp, nil } -// GetTradableBalances returns tradable balances -func (e *Exchange) GetTradableBalances(ctx context.Context) (map[string]map[string]float64, error) { - type Response struct { - Data map[string]map[string]any +// GetOrder gets order details by orderId or clientOrderId +func (e *Exchange) GetOrder(ctx context.Context, id, clientOrderID string) (*TradeOrder, error) { + path, err := orderPath(id, "/orders/", clientOrderID, "/orders/cid:") + if err != nil { + return nil, err + } + var resp TradeOrder + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetOpenOrderDetailEPL, http.MethodGet, path, nil, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrGetFailed, err) } - result := Response{} + return &resp, nil +} - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexTradableBalances, url.Values{}, &result.Data) +// CancelOrderByID cancels an active order +func (e *Exchange) CancelOrderByID(ctx context.Context, id, clientOrderID string) (*CancelOrderResponse, error) { + path, err := orderPath(id, "/orders/", clientOrderID, "/orders/cid:") if err != nil { return nil, err } - - balances := make(map[string]map[string]float64) - - for x, y := range result.Data { - balances[x] = make(map[string]float64) - for z, w := range y { - bal, ok := w.(string) - if !ok { - return nil, common.GetTypeAssertError("string", w, "balance") - } - balances[x][z], err = strconv.ParseFloat(bal, 64) - if err != nil { - return nil, err - } - } + var resp CancelOrderResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sCancelOrderByIDEPL, http.MethodDelete, path, nil, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } - - return balances, nil + return &resp, nil } -// TransferBalance transfers balances between your accounts -func (e *Exchange) TransferBalance(ctx context.Context, ccy, from, to string, amount float64) (bool, error) { - values := url.Values{} - result := GenericResponse{} - - values.Set("currency", ccy) - values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - values.Set("fromAccount", from) - values.Set("toAccount", to) - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexTransferBalance, values, &result) +// CancelOrdersByIDs cancels multiple orders +func (e *Exchange) CancelOrdersByIDs(ctx context.Context, orderIDs, clientOrderIDs []string) ([]*CancelOrderResponse, error) { + if len(orderIDs) == 0 && len(clientOrderIDs) == 0 { + return nil, order.ErrOrderIDNotSet + } + params := make(map[string]any) + if len(orderIDs) > 0 { + params["orderIds"] = orderIDs + } + if len(clientOrderIDs) > 0 { + params["clientOrderIds"] = clientOrderIDs + } + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*CancelOrderResponse](ctx, e, exchange.RestSpot, sCancelBatchOrdersEPL, http.MethodDelete, "/orders/cancelByIds", nil, params) if err != nil { - return false, err + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } + return resp, nil +} - if result.Error != "" && result.Success != 1 { - return false, errors.New(result.Error) +// CancelTradeOrders batch cancels all orders in an account +func (e *Exchange) CancelTradeOrders(ctx context.Context, symbols []string, accountTypes []AccountType) ([]*CancelOrderResponse, error) { + args := make(map[string]any) + if len(symbols) != 0 { + args["symbols"] = symbols + } + if len(accountTypes) > 0 { + args["accountTypes"] = accountTypes + } + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*CancelOrderResponse](ctx, e, exchange.RestSpot, sCancelAllOrdersEPL, http.MethodDelete, "/orders", nil, args) + if err != nil { + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } + return resp, nil +} - return true, nil +// KillSwitch sets a timer that cancels all regular and smart orders after the timeout has expired. +// Timeout can be reset by calling this command again with a new timeout value. +// timeout value in seconds; range is 10 seconds to 10 minutes or 600 seconds +func (e *Exchange) KillSwitch(ctx context.Context, timeout time.Duration) (*KillSwitchStatus, error) { + var timeoutString string + if timeout < time.Second*10 || timeout > time.Minute*10 { + return nil, fmt.Errorf("%w: must be between 10 seconds and 10 minutes", errInvalidTimeout) + } + timeoutString = strconv.FormatInt(int64(timeout.Seconds()), 10) + var resp *KillSwitchStatus + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sKillSwitchEPL, http.MethodPost, "/orders/killSwitch", nil, map[string]any{"timeout": timeoutString}, &resp) } -// GetMarginAccountSummary returns a summary on your margin accounts -func (e *Exchange) GetMarginAccountSummary(ctx context.Context) (Margin, error) { - result := Margin{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexMarginAccountSummary, url.Values{}, &result) +// DisableKillSwitch disables the timer to cancel all regular and smart orders +func (e *Exchange) DisableKillSwitch(ctx context.Context) (*KillSwitchStatus, error) { + var resp *KillSwitchStatus + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sKillSwitchEPL, http.MethodPost, "/orders/killSwitch", nil, map[string]any{"timeout": "-1"}, &resp) } -// PlaceMarginOrder places a margin order -func (e *Exchange) PlaceMarginOrder(ctx context.Context, currencyPair string, rate, amount, lendingRate float64, buy bool) (OrderResponse, error) { - result := OrderResponse{} - values := url.Values{} +// GetKillSwitchStatus gets status of the kill switch +func (e *Exchange) GetKillSwitchStatus(ctx context.Context) (*KillSwitchStatus, error) { + var resp *KillSwitchStatus + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetKillSwitchStatusEPL, http.MethodGet, "/orders/killSwitchStatus", nil, nil, &resp) +} - var orderType string - if buy { - orderType = poloniexMarginBuy - } else { - orderType = poloniexMarginSell +// CreateSmartOrder create a smart order for an account. Funds will only be frozen when the smart order triggers, not upon smart order creation +func (e *Exchange) CreateSmartOrder(ctx context.Context, arg *SmartOrderRequest) (*OrderIDResponse, error) { + if arg.Symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty } - - values.Set("currencyPair", currencyPair) - values.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64)) - values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - - if lendingRate != 0 { - values.Set("lendingRate", strconv.FormatFloat(lendingRate, 'f', -1, 64)) + if arg.Side != order.Buy && arg.Side != order.Sell { + return nil, order.ErrSideIsInvalid } - - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, orderType, values, &result) -} - -// GetMarginPosition returns a position on a margin order -func (e *Exchange) GetMarginPosition(ctx context.Context, currencyPair string) (any, error) { - values := url.Values{} - - if currencyPair != "" && currencyPair != "all" { - values.Set("currencyPair", currencyPair) - result := MarginPosition{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexMarginPosition, values, &result) + if arg.BaseAmount <= 0 { + return nil, fmt.Errorf("%w; base quantity is required", limits.ErrAmountBelowMin) } - values.Set("currencyPair", "all") - - type Response struct { - Data map[string]MarginPosition + if arg.Type == OrderType(order.StopLimit) && arg.Price <= 0 { + return nil, fmt.Errorf("%w: %w", order.ErrPriceMustBeSetIfLimitOrder, limits.ErrPriceBelowMin) } - result := Response{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexMarginPosition, values, &result.Data) + if oType := order.Type(arg.Type); oType.Is(order.TrailingStop) && arg.TrailingOffset == "" { + return nil, errInvalidTrailingOffset + } + if oType := order.Type(arg.Type); oType.Is(order.TrailingStopLimit) && arg.LimitOffset == "" { + return nil, errInvalidOffsetLimit + } + var resp *OrderIDResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sCreateSmartOrdersEPL, http.MethodPost, "/smartorders", nil, arg, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrPlaceFailed, err) + } + return resp, nil } -// CloseMarginPosition closes a current margin position -func (e *Exchange) CloseMarginPosition(ctx context.Context, currencyPair string) (bool, error) { - values := url.Values{} - values.Set("currencyPair", currencyPair) - result := GenericResponse{} +func orderPath(orderID, idPath, clientOrderID, clientIDPath string) (string, error) { + switch { + case orderID != "": + return idPath + orderID, nil + case clientOrderID != "": + return clientIDPath + clientOrderID, nil + default: + return "", order.ErrOrderIDNotSet + } +} - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexMarginPositionClose, values, &result) +// CancelReplaceSmartOrder cancels an existing untriggered smart order and places a new smart order on the same symbol with details from the existing smart order, unless amended by new parameters +func (e *Exchange) CancelReplaceSmartOrder(ctx context.Context, arg *CancelReplaceSmartOrderRequest) (*OrderIDResponse, error) { + path, err := orderPath(arg.OrderID, "/smartorders/", arg.OldClientOrderID, "/smartorders/cid:") if err != nil { - return false, err + return nil, err } - - if result.Success == 0 { - return false, errors.New(result.Error) + var resp *OrderIDResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sCreateReplaceSmartOrdersEPL, http.MethodPut, path, nil, arg, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } - - return true, nil + return resp, nil } -// CreateLoanOffer places a loan offer on the exchange -func (e *Exchange) CreateLoanOffer(ctx context.Context, ccy string, amount, rate float64, duration int, autoRenew bool) (int64, error) { - values := url.Values{} - values.Set("currency", ccy) - values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - values.Set("duration", strconv.Itoa(duration)) - - if autoRenew { - values.Set("autoRenew", "1") - } else { - values.Set("autoRenew", "0") +// GetSmartOpenOrders gets a list of pending smart orders for an account +func (e *Exchange) GetSmartOpenOrders(ctx context.Context, limit uint64, types []string) ([]*SmartOrder, error) { + params := url.Values{} + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) } - - values.Set("lendingRate", strconv.FormatFloat(rate, 'f', -1, 64)) - - type Response struct { - Success int `json:"success"` - Error string `json:"error"` - OrderID int64 `json:"orderID"` + if len(types) > 0 { + params.Set("types", strings.Join(types, ",")) } + var resp []*SmartOrder + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSmartOrdersEPL, http.MethodGet, "/smartorders", params, nil, &resp) +} - result := Response{} - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexCreateLoanOffer, values, &result) +// GetSmartOrderDetails retrieves a smart order's details +func (e *Exchange) GetSmartOrderDetails(ctx context.Context, orderID, clientOrderID string) ([]*SmartOrderDetails, error) { + path, err := orderPath(orderID, "/smartorders/", clientOrderID, "/smartorders/cid:") if err != nil { - return 0, err + return nil, err } - - if result.Success == 0 { - return 0, errors.New(result.Error) + var resp []*SmartOrderDetails + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sSmartOrderDetailEPL, http.MethodGet, path, nil, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrGetFailed, err) } - - return result.OrderID, nil + return resp, nil } -// CancelLoanOffer cancels a loan offer order -func (e *Exchange) CancelLoanOffer(ctx context.Context, orderNumber int64) (bool, error) { - result := GenericResponse{} - values := url.Values{} - values.Set("orderID", strconv.FormatInt(orderNumber, 10)) - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexCancelLoanOffer, values, &result) +// CancelSmartOrderByID cancels a smart order by its id. +func (e *Exchange) CancelSmartOrderByID(ctx context.Context, id, clientOrderID string) (*CancelOrderResponse, error) { + path, err := orderPath(id, "/smartorders/", clientOrderID, "/smartorders/cid:") if err != nil { - return false, err + return nil, err } - - if result.Success == 0 { - return false, errors.New(result.Error) + var resp *CancelOrderResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sCancelSmartOrderByIDEPL, http.MethodDelete, path, nil, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } - - return true, nil + return resp, nil } -// GetOpenLoanOffers returns all open loan offers -func (e *Exchange) GetOpenLoanOffers(ctx context.Context) (map[string][]LoanOffer, error) { - type Response struct { - Data map[string][]LoanOffer +// CancelMultipleSmartOrders performs a batch cancel of one or many smart orders in an account by their IDs. +func (e *Exchange) CancelMultipleSmartOrders(ctx context.Context, args *CancelOrdersRequest) ([]*CancelOrderResponse, error) { + if len(args.ClientOrderIDs) == 0 && len(args.OrderIDs) == 0 { + return nil, order.ErrOrderIDNotSet } - result := Response{} - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexOpenLoanOffers, url.Values{}, &result.Data) + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*CancelOrderResponse](ctx, e, exchange.RestSpot, sCancelSmartOrdersByIDEPL, http.MethodDelete, "/smartorders/cancelByIds", nil, args) if err != nil { - return nil, err + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) } - - if result.Data == nil { - return nil, errors.New("there are no open loan offers") - } - - return result.Data, nil + return resp, nil } -// GetActiveLoans returns active loans -func (e *Exchange) GetActiveLoans(ctx context.Context) (ActiveLoans, error) { - result := ActiveLoans{} - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexActiveLoans, url.Values{}, &result) +// CancelSmartOrders cancels all smart orders in an account. +func (e *Exchange) CancelSmartOrders(ctx context.Context, symbols []currency.Pair, accountTypes []AccountType, orderTypes []OrderType) ([]*CancelOrderResponse, error) { + args := make(map[string]any) + if len(symbols) != 0 { + args["symbols"] = symbols + } + if len(accountTypes) > 0 { + args["accountTypes"] = accountTypes + } + if len(orderTypes) > 0 { + args["orderTypes"] = orderTypes + } + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*CancelOrderResponse](ctx, e, exchange.RestSpot, sCancelAllSmartOrdersEPL, http.MethodDelete, "/smartorders", nil, args) + if err != nil { + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil } -// GetLendingHistory returns lending history for the account -func (e *Exchange) GetLendingHistory(ctx context.Context, start, end string) ([]LendingHistory, error) { - vals := url.Values{} - - if start != "" { - vals.Set("start", start) +func orderFillParams(arg *OrdersHistoryRequest) (url.Values, error) { + if !arg.StartTime.IsZero() && !arg.EndTime.IsZero() { + if err := common.StartEndTimeCheck(arg.StartTime, arg.EndTime); err != nil { + return nil, err + } } - - if end != "" { - vals.Set("end", end) + params := url.Values{} + if !arg.StartTime.IsZero() { + params.Set("startTime", strconv.FormatInt(arg.StartTime.UnixMilli(), 10)) } - - var resp []LendingHistory - return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, - poloniexLendingHistory, - vals, - &resp) + if !arg.EndTime.IsZero() { + params.Set("endTime", strconv.FormatInt(arg.EndTime.UnixMilli(), 10)) + } + if arg.AccountType != "" { + params.Set("accountType", arg.AccountType) + } + if arg.OrderType != "" { + params.Set("type", arg.OrderType) + } + if len(arg.OrderTypes) > 0 { + params.Set("types", strings.Join(arg.OrderTypes, ",")) + } + if arg.Side != order.UnknownSide && arg.Side != order.AnySide { + params.Set("side", arg.Side.String()) + } + if !arg.Symbol.IsEmpty() { + params.Set("symbol", arg.Symbol.String()) + } + if arg.From > 0 { + params.Set("from", strconv.FormatInt(arg.From, 10)) + } + if arg.Direction != "" { + params.Set("direction", arg.Direction) + } + if arg.States != "" { + params.Set("states", arg.States) + } + if arg.Limit > 0 { + params.Set("limit", strconv.FormatInt(arg.Limit, 10)) + } + if arg.HideCancel { + params.Set("hideCancel", "true") + } + return params, nil } -// ToggleAutoRenew allows for the autorenew of a contract -func (e *Exchange) ToggleAutoRenew(ctx context.Context, orderNumber int64) (bool, error) { - values := url.Values{} - values.Set("orderNumber", strconv.FormatInt(orderNumber, 10)) - result := GenericResponse{} - - err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, - poloniexAutoRenew, - values, - &result) +// GetOrdersHistory gets a list of historical orders in an account +func (e *Exchange) GetOrdersHistory(ctx context.Context, arg *OrdersHistoryRequest) ([]*OrderHistoryItem, error) { + params, err := orderFillParams(arg) if err != nil { - return false, err + return nil, err } - - if result.Success == 0 { - return false, errors.New(result.Error) + var resp []*OrderHistoryItem + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetOrderHistoryEPL, http.MethodGet, "/orders/history", params, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrGetFailed, err) } - - return true, nil + return resp, nil } -// WalletActivity returns the wallet activity between set start and end time -func (e *Exchange) WalletActivity(ctx context.Context, start, end time.Time, activityType string) (*WalletActivityResponse, error) { - values := url.Values{} - err := common.StartEndTimeCheck(start, end) +// GetSmartOrderHistory gets a list of historical smart orders in an account +func (e *Exchange) GetSmartOrderHistory(ctx context.Context, arg *OrdersHistoryRequest) ([]*SmartOrder, error) { + params, err := orderFillParams(arg) if err != nil { return nil, err } - values.Set("start", strconv.FormatInt(start.Unix(), 10)) - values.Set("end", strconv.FormatInt(end.Unix(), 10)) - if activityType != "" { - values.Set("activityType", activityType) + var resp []*SmartOrder + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetSmartOrderHistoryEPL, http.MethodGet, "/smartorders/history", params, nil, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrGetFailed, err) } - var resp WalletActivityResponse - return &resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, - poloniexWalletActivity, - values, - &resp) + return resp, nil } -// CancelMultipleOrdersByIDs Batch cancel one or many smart orders in an account by IDs. -func (e *Exchange) CancelMultipleOrdersByIDs(ctx context.Context, orderIDs, clientOrderIDs []string) ([]CancelOrdersResponse, error) { - values := url.Values{} - if len(orderIDs) > 0 { - values.Set("orderIds", strings.Join(orderIDs, ",")) +// GetTradeHistory gets a list of all trades for an account +func (e *Exchange) GetTradeHistory(ctx context.Context, symbols currency.Pairs, direction string, from, limit uint64, startTime, endTime time.Time) ([]*TradeHistory, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } } - if len(clientOrderIDs) > 0 { - values.Set("clientOrderIds", strings.Join(clientOrderIDs, ",")) + params := url.Values{} + if !startTime.IsZero() { + params.Set("startTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("endTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if len(symbols) != 0 { + params.Set("symbols", symbols.Join()) } - var result []CancelOrdersResponse - return result, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, - poloniexCancelByIDs, - values, - &result) + if from > 0 { + params.Set("from", strconv.FormatUint(from, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + if direction != "" { + params.Set("direction", direction) + } + var resp []*TradeHistory + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetTradesEPL, http.MethodGet, "/trades", params, nil, &resp) +} + +// GetTradesByOrderID gets trades for an order +func (e *Exchange) GetTradesByOrderID(ctx context.Context, orderID string) ([]*TradeHistory, error) { + if orderID == "" { + return nil, order.ErrOrderIDNotSet + } + var resp []*TradeHistory + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, sGetTradeDetailEPL, http.MethodGet, "/orders/"+orderID+"/trades", nil, nil, &resp) } // SendHTTPRequest sends an unauthenticated HTTP request -func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, result any) error { +func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, path string, result any) error { endpoint, err := e.API.Endpoints.GetURL(ep) if err != nil { return err } - - item := &request.Item{ - Method: http.MethodGet, - Path: endpoint + path, - Result: result, - Verbose: e.Verbose, - HTTPDebugging: e.HTTPDebugging, - HTTPRecording: e.HTTPRecording, - HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit, + resp := result + if strings.HasPrefix(path, v3Path) { + resp = &V3ResponseWrapper{ + Data: result, + } } - - return e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) { - return item, nil - }, request.UnauthenticatedRequest) + if err := e.SendPayload(ctx, epl, func() (*request.Item, error) { + return &request.Item{ + Method: http.MethodGet, + Path: endpoint + path, + Result: resp, + Verbose: e.Verbose, + HTTPDebugging: e.HTTPDebugging, + HTTPRecording: e.HTTPRecording, + HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit, + }, nil + }, request.UnauthenticatedRequest); err != nil { + return err + } + if resp == nil { + return common.ErrNoResponse + } + if errType, ok := resp.(hasError); ok && errType.Error() != nil { + return errType.Error() + } + return nil } // SendAuthenticatedHTTPRequest sends an authenticated HTTP request -func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, result any) error { +func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, epl request.EndpointLimit, method, path string, values url.Values, body, result any) error { creds, err := e.GetCredentials(ctx) if err != nil { return err } - ePoint, err := e.API.Endpoints.GetURL(ep) + endpoint, err := e.API.Endpoints.GetURL(ep) if err != nil { return err } - - return e.SendPayload(ctx, request.Auth, func() (*request.Item, error) { + var resp any + resp = result + if strings.HasPrefix(path, v3Path) { + resp = &V3ResponseWrapper{ + Data: result, + } + } + requestFunc := func() (*request.Item, error) { headers := make(map[string]string) - headers["Content-Type"] = "application/x-www-form-urlencoded" - headers["Key"] = creds.Key - values.Set("nonce", e.Requester.GetNonce(nonce.UnixNano).String()) - values.Set("command", endpoint) - - hmac, err := crypto.GetHMAC(crypto.HashSHA512, []byte(values.Encode()), []byte(creds.Secret)) + headers["Content-Type"] = "application/json" + headers["key"] = creds.Key + if values == nil { + values = url.Values{} + } + timestamp := time.Now() + signTimestamp := strconv.FormatInt(timestamp.UnixMilli(), 10) + values.Set("signTimestamp", signTimestamp) + var signatureStrings string + req := &request.Item{ + Method: method, + Result: resp, + Headers: headers, + Verbose: e.Verbose, + HTTPDebugging: e.HTTPDebugging, + HTTPRecording: e.HTTPRecording, + } + if body != nil { + bodyPayload, err := json.Marshal(body) + if err != nil { + return nil, err + } + signatureStrings = method + "\n" + path + "\n" + "requestBody=" + string(bodyPayload) + "&" + values.Encode() + req.Body = bytes.NewBuffer(bodyPayload) + } else { + signatureStrings = method + "\n" + path + "\n" + values.Encode() + } + var hmac []byte + hmac, err = crypto.GetHMAC(crypto.HashSHA256, + []byte(signatureStrings), + []byte(creds.Secret)) if err != nil { return nil, err } - headers["Sign"] = hex.EncodeToString(hmac) - path := fmt.Sprintf("%s/%s", ePoint, poloniexAPITradingEndpoint) - return &request.Item{ - Method: method, - Path: path, - Headers: headers, - Body: bytes.NewBufferString(values.Encode()), - Result: result, - NonceEnabled: true, - Verbose: e.Verbose, - HTTPDebugging: e.HTTPDebugging, - HTTPRecording: e.HTTPRecording, - HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit, - }, nil - }, request.AuthenticatedRequest) + headers["signatureMethod"] = "hmacSHA256" + headers["signature"] = base64.StdEncoding.EncodeToString(hmac) + headers["signTimestamp"] = signTimestamp + values.Del("signTimestamp") // The signature timestamp was removed from the query string because we now send the timestamp in the request header instead. + req.Path = common.EncodeURLValues(endpoint+path, values) + return req, nil + } + if err := e.SendPayload(ctx, epl, requestFunc, request.AuthenticatedRequest); err != nil { + return fmt.Errorf("%w: %w", request.ErrAuthRequestFailed, err) + } + if errType, ok := resp.(hasError); ok && errType.Error() != nil { + return fmt.Errorf("%w: %w", request.ErrAuthRequestFailed, errType.Error()) + } + return nil +} + +// SendBatchValidatedAuthenticatedHTTPRequest sends an authenticated V3 HTTP request and returns a slice response after validating errors on each batch item. +func SendBatchValidatedAuthenticatedHTTPRequest[T hasError](ctx context.Context, e *Exchange, ep exchange.URL, epl request.EndpointLimit, method, path string, values url.Values, body any) (result []T, err error) { + if err := e.SendAuthenticatedHTTPRequest(ctx, ep, epl, method, path, values, body, &result); err != nil { + return nil, err + } + // Return result, which contains the full response including both + // successful and failed cancellation attempts. + return result, checkForErrorInSliceResponse(result) +} + +func checkForErrorInSliceResponse[T hasError](slice []T) error { + var err error + for _, v := range slice { + if e := v.Error(); e != nil { + err = common.AppendError(err, e) + } + } + return err } // GetFee returns an estimate of fee based on type of transaction @@ -949,25 +1153,24 @@ func (e *Exchange) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) case exchange.CryptocurrencyWithdrawalFee: fee = getWithdrawalFee(feeBuilder.Pair.Base) case exchange.OfflineTradeFee: - fee = getOfflineTradeFee(feeBuilder.PurchasePrice, feeBuilder.Amount) - } - if fee < 0 { - fee = 0 + fee = getOfflineTradeFee(feeBuilder.IsMaker, feeBuilder.PurchasePrice, feeBuilder.Amount) } - return fee, nil } // getOfflineTradeFee calculates the worst case-scenario trading fee -func getOfflineTradeFee(price, amount float64) float64 { - return 0.002 * price * amount +func getOfflineTradeFee(isMaker bool, price, amount float64) float64 { + if isMaker { + return 0.00145 * price * amount + } + return 0.00155 * price * amount } -func calculateTradingFee(feeInfo Fee, purchasePrice, amount float64, isMaker bool) (fee float64) { +func calculateTradingFee(feeInfo *FeeInfo, purchasePrice, amount float64, isMaker bool) (fee float64) { if isMaker { - fee = feeInfo.MakerFee + fee = feeInfo.MakerRate.Float64() } else { - fee = feeInfo.TakerFee + fee = feeInfo.TakerRate.Float64() } return fee * amount * purchasePrice } diff --git a/exchanges/poloniex/poloniex_futures.go b/exchanges/poloniex/poloniex_futures.go new file mode 100644 index 00000000000..e608f8e08e4 --- /dev/null +++ b/exchanges/poloniex/poloniex_futures.go @@ -0,0 +1,788 @@ +package poloniex + +import ( + "context" + "errors" + "fmt" + "net/http" + "net/url" + "strconv" + "time" + + "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/exchange/order/limits" + exchange "github.com/thrasher-corp/gocryptotrader/exchanges" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/margin" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" + "github.com/thrasher-corp/gocryptotrader/exchanges/request" +) + +var ( + errInvalidPositionMode = errors.New("invalid position mode") + errInvalidMarginAdjustType = errors.New("invalid margin adjust type") +) + +const ( + tradePathV3 = v3Path + "trade/" + marketsPathV3 = v3Path + "market/" + accountPathV3 = v3Path + "account/" + positionPathV3 = v3Path + "position/" +) + +// GetAccountBalance gets information about your Futures account. +func (e *Exchange) GetAccountBalance(ctx context.Context) (*FuturesAccountBalance, error) { + var resp *FuturesAccountBalance + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetAccountBalanceEPL, http.MethodGet, accountPathV3+"balance", nil, nil, &resp) +} + +// GetAccountBills retrieves the account’s bills. +func (e *Exchange) GetAccountBills(ctx context.Context, startTime, endTime time.Time, offset, limit uint64, direction, billType string) ([]*BillDetails, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if offset > 0 { + params.Set("from", strconv.FormatUint(offset, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + if direction != "" { + params.Set("direct", direction) + } + if billType != "" { + params.Set("type", billType) + } + var resp []*BillDetails + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetBillsDetailsEPL, http.MethodGet, accountPathV3+"bills", params, nil, &resp) +} + +// PlaceFuturesOrder places an order in futures trading. +func (e *Exchange) PlaceFuturesOrder(ctx context.Context, arg *FuturesOrderRequest) (*FuturesOrderIDResponse, error) { + if err := arg.validate(); err != nil { + return nil, err + } + var resp *FuturesOrderIDResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fOrderEPL, http.MethodPost, tradePathV3+"order", nil, arg, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrPlaceFailed, err) + } + return resp, nil +} + +// PlaceFuturesMultipleOrders places orders in a batch. A maximum of 10 orders can be placed per request. +func (e *Exchange) PlaceFuturesMultipleOrders(ctx context.Context, args []FuturesOrderRequest) ([]*FuturesOrderIDResponse, error) { + if len(args) == 0 { + return nil, common.ErrEmptyParams + } + for i := range args { + if err := args[i].validate(); err != nil { + return nil, err + } + } + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*FuturesOrderIDResponse](ctx, e, exchange.RestSpot, fBatchOrdersEPL, http.MethodPost, tradePathV3+"orders", nil, args) + if err != nil { + return resp, fmt.Errorf("%w: %w", order.ErrPlaceFailed, err) + } + return resp, nil +} + +func (o *FuturesOrderRequest) validate() error { + if o.Symbol.IsEmpty() { + return currency.ErrSymbolStringEmpty + } + if o.Side == "" { + return order.ErrSideIsInvalid + } + if (o.MarginMode != MarginMode(margin.Unset) && o.PositionSide == order.UnknownSide) || + (o.MarginMode == MarginMode(margin.Unset) && o.PositionSide != order.UnknownSide) { + return fmt.Errorf("%w: %w: either both margin mode and position side fields are filled or left blank", order.ErrSideIsInvalid, margin.ErrInvalidMarginType) + } + if o.OrderType == OrderType(order.UnknownType) { + return order.ErrTypeIsInvalid + } + if o.Size <= 0 { + return limits.ErrAmountBelowMin + } + return nil +} + +// CancelFuturesOrder cancels an order in futures trading. +func (e *Exchange) CancelFuturesOrder(ctx context.Context, arg *CancelOrderRequest) (*FuturesOrderIDResponse, error) { + if arg.Symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + if arg.OrderID == "" && arg.ClientOrderID == "" { + return nil, order.ErrOrderIDNotSet + } + var resp *FuturesOrderIDResponse + if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fCancelOrderEPL, http.MethodDelete, tradePathV3+"order", nil, arg, &resp); err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil +} + +// CancelMultipleFuturesOrders cancels orders in a batch. A maximum of 10 orders can be cancelled per request. +func (e *Exchange) CancelMultipleFuturesOrders(ctx context.Context, args *CancelFuturesOrdersRequest) ([]*FuturesOrderIDResponse, error) { + if args.Symbol.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty + } + if len(args.OrderIDs) == 0 && len(args.ClientOrderIDs) == 0 { + return nil, order.ErrOrderIDNotSet + } + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*FuturesOrderIDResponse](ctx, e, exchange.RestSpot, fCancelBatchOrdersEPL, http.MethodDelete, tradePathV3+"batchOrders", nil, args) + if err != nil { + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil +} + +// CancelFuturesOrders cancels all current pending orders. +func (e *Exchange) CancelFuturesOrders(ctx context.Context, symbol currency.Pair, side string) ([]*FuturesOrderIDResponse, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + arg := &struct { + Symbol string `json:"symbol"` + Side string `json:"side,omitempty"` + }{ + Symbol: symbol.String(), + Side: side, + } + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*FuturesOrderIDResponse](ctx, e, exchange.RestSpot, fCancelAllLimitOrdersEPL, http.MethodDelete, tradePathV3+"allOrders", nil, arg) + if err != nil { + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil +} + +// CloseAtMarketPrice closes orders at market price. +func (e *Exchange) CloseAtMarketPrice(ctx context.Context, symbol currency.Pair, marginMode, positionSide, clientOrderID string) (*FuturesOrderIDResponse, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + if marginMode == "" { + return nil, margin.ErrInvalidMarginType + } + arg := &struct { + Symbol string `json:"symbol"` + MgnMode string `json:"mgnMode"` + ClOrdID string `json:"clOrdId,omitempty"` + PositionSide string `json:"posSide,omitempty"` + }{ + Symbol: symbol.String(), + MgnMode: marginMode, + ClOrdID: clientOrderID, + PositionSide: positionSide, + } + var resp *FuturesOrderIDResponse + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fCancelPositionAtMarketPriceEPL, http.MethodPost, tradePathV3+"position", nil, arg, &resp) +} + +// CloseAllPositionsAtMarketPrice closes all orders at market price. +func (e *Exchange) CloseAllPositionsAtMarketPrice(ctx context.Context) ([]*FuturesOrderIDResponse, error) { + resp, err := SendBatchValidatedAuthenticatedHTTPRequest[*FuturesOrderIDResponse](ctx, e, exchange.RestSpot, fCancelAllPositionsAtMarketPriceEPL, http.MethodPost, tradePathV3+"positionAll", nil, nil) + if err != nil { + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil +} + +// GetCurrentFuturesOrders gets unfilled futures orders. If no request parameters are specified, you will get all open orders sorted by creation time in chronological order. +func (e *Exchange) GetCurrentFuturesOrders(ctx context.Context, symbol currency.Pair, side, clientOrderID, direction string, orderID, offsetOrderID, limit uint64) ([]*FuturesOrderDetails, error) { + params := url.Values{} + if side != "" { + params.Set("side", side) + } + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + if orderID > 0 { + params.Set("ordId", strconv.FormatUint(orderID, 10)) + } + if clientOrderID != "" { + params.Set("clOrdId", clientOrderID) + } + if direction != "" { + params.Set("direct", direction) + } + if offsetOrderID > 0 { + params.Set("from", strconv.FormatUint(offsetOrderID, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesOrderDetails + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetOrdersEPL, http.MethodGet, tradePathV3+"order/opens", params, nil, &resp) +} + +// GetOrderExecutionDetails retrieves detailed information about your executed futures order +func (e *Exchange) GetOrderExecutionDetails(ctx context.Context, side order.Side, symbol currency.Pair, orderID, clientOrderID, direction string, startTime, endTime time.Time, offset, limit uint64) ([]*FuturesTradeFill, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + if side != order.UnknownSide { + params.Set("side", side.String()) + } + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + if orderID != "" { + params.Set("ordId", orderID) + } + if clientOrderID != "" { + params.Set("clOrdId", clientOrderID) + } + if direction != "" { + params.Set("direct", direction) + } + if offset > 0 { + params.Set("from", strconv.FormatUint(offset, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesTradeFill + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetFillsV2EPL, http.MethodGet, tradePathV3+"order/trades", params, nil, &resp) +} + +// GetFuturesOrderHistory retrieves previous futures orders. Orders initiated through the API that are completely canceled (no transaction has occurred) can only be queried for 4 hours. +func (e *Exchange) GetFuturesOrderHistory(ctx context.Context, symbol currency.Pair, side order.Side, orderType, orderState, orderID, clientOrderID, direction string, startTime, endTime time.Time, offset, limit uint64) ([]*FuturesOrderDetails, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if orderType != "" { + params.Set("type", orderType) + } + if side != order.UnknownSide { + params.Set("side", side.String()) + } + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + if orderState != "" { + params.Set("state", orderState) + } + if orderID != "" { + params.Set("ordId", orderID) + } + if clientOrderID != "" { + params.Set("clOrdId", clientOrderID) + } + if direction != "" { + params.Set("direct", direction) + } + if offset > 0 { + params.Set("from", strconv.FormatUint(offset, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesOrderDetails + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetOrderHistoryEPL, http.MethodGet, tradePathV3+"order/history", params, nil, &resp) +} + +// GetFuturesCurrentPosition retrieves information about your current position. +func (e *Exchange) GetFuturesCurrentPosition(ctx context.Context, symbol currency.Pair) ([]*OpenFuturesPosition, error) { + params := url.Values{} + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + var resp []*OpenFuturesPosition + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetPositionOpenEPL, http.MethodGet, tradePathV3+"position/opens", params, nil, &resp) +} + +// GetFuturesPositionHistory gets information about previous positions. +func (e *Exchange) GetFuturesPositionHistory(ctx context.Context, symbol currency.Pair, marginMode, positionSide, direction string, startTime, endTime time.Time, offset, limit uint64) ([]*FuturesPosition, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + if marginMode != "" { + params.Set("mgnMode", marginMode) + } + if positionSide != "" { + params.Set("posSide", positionSide) + } + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if direction != "" { + params.Set("direct", direction) + } + if offset > 0 { + params.Set("from", strconv.FormatUint(offset, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesPosition + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetPositionHistoryEPL, http.MethodGet, tradePathV3+"position/history", params, nil, &resp) +} + +// AdjustMarginForIsolatedMarginTradingPositions adds or reduces margin for positions in isolated margin mode. +func (e *Exchange) AdjustMarginForIsolatedMarginTradingPositions(ctx context.Context, symbol currency.Pair, positionSide, adjustType string, amount float64) (*AdjustFuturesMarginResponse, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + if amount <= 0 { + return nil, limits.ErrAmountBelowMin + } + if adjustType == "" { + return nil, errInvalidMarginAdjustType + } + arg := &struct { + Symbol currency.Pair `json:"symbol"` + PositionSide string `json:"posSide,omitempty"` + Amount float64 `json:"amt,string"` + Type string `json:"type"` + }{ + Symbol: symbol, + PositionSide: positionSide, + Amount: amount, + Type: adjustType, + } + var resp *AdjustFuturesMarginResponse + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fAdjustMarginEPL, http.MethodPost, tradePathV3+"position/margin", nil, arg, &resp) +} + +// GetFuturesLeverage retrieves the list of leverage. +func (e *Exchange) GetFuturesLeverage(ctx context.Context, symbol currency.Pair, marginMode string) ([]*FuturesLeverage, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + if marginMode != "" { + params.Set("mgnMode", marginMode) + } + var resp []*FuturesLeverage + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetPositionLeverageEPL, http.MethodGet, positionPathV3+"leverages", params, nil, &resp) +} + +// SetFuturesLeverage changes leverage +func (e *Exchange) SetFuturesLeverage(ctx context.Context, symbol currency.Pair, marginMode, positionSide string, leverage uint64) (*FuturesLeverage, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + if marginMode == "" { + return nil, margin.ErrInvalidMarginType + } + if positionSide == "" { + return nil, order.ErrSideIsInvalid + } + if leverage <= 0 { + return nil, order.ErrSubmitLeverageNotSupported + } + arg := &struct { + Symbol string `json:"symbol"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + Leverage uint64 `json:"lever,string"` + }{ + Symbol: symbol.String(), + MarginMode: marginMode, + PositionSide: positionSide, + Leverage: leverage, + } + var resp *FuturesLeverage + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fSetPositionLeverageEPL, http.MethodPost, positionPathV3+"leverage", nil, arg, &resp) +} + +// SwitchPositionMode switches the current position mode. Please ensure you do not have open positions and open orders under this mode before the switch. +// Position mode, HEDGE: LONG/SHORT, ONE_WAY: BOTH +func (e *Exchange) SwitchPositionMode(ctx context.Context, positionMode string) error { + if positionMode != "HEDGE" && positionMode != "ONE_WAY" { + return errInvalidPositionMode + } + return e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fSwitchPositionModeEPL, http.MethodPost, positionPathV3+"mode", nil, map[string]string{"posMode": positionMode}, nil) +} + +// GetPositionMode gets the current position mode. +func (e *Exchange) GetPositionMode(ctx context.Context) (string, error) { + resp := &struct { + PositionMode string `json:"posMode"` + }{} + return resp.PositionMode, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetPositionModeEPL, http.MethodGet, positionPathV3+"mode", nil, nil, &resp) +} + +// GetUserPositionRiskLimit retrieves the user's position risk limit. +func (e *Exchange) GetUserPositionRiskLimit(ctx context.Context, symbol currency.Pair, marginMode, positionSide string) ([]*UserPositionRiskLimit, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + if marginMode != "" { + params.Set("mgnMode", marginMode) + } + if positionSide != "" { + params.Set("posSide", positionSide) + } + var resp []*UserPositionRiskLimit + return resp, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, fGetPositionRiskLimitEPL, http.MethodGet, positionPathV3+"riskLimit", params, nil, &resp) +} + +// GetFuturesOrderBook gets market depth data for the designated trading pair +func (e *Exchange) GetFuturesOrderBook(ctx context.Context, symbol currency.Pair, depth, limit uint64) (*FuturesOrderbook, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + if depth > 0 { + params.Set("scale", strconv.FormatUint(depth, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp *FuturesOrderbook + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"orderBook", params), &resp) +} + +// GetFuturesKlineData retrieves K-line data for the designated trading pair +func (e *Exchange) GetFuturesKlineData(ctx context.Context, symbol currency.Pair, interval kline.Interval, startTime, endTime time.Time, limit uint64) ([]*FuturesCandle, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + intervalString, err := intervalToString(interval) + if err != nil { + return nil, err + } + params := url.Values{} + params.Set("symbol", symbol.String()) + params.Set("interval", intervalString) + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesCandle + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fCandlestickEPL, common.EncodeURLValues(marketsPathV3+"candles", params), &resp) +} + +// GetFuturesExecution gets the latest execution information. The default limit is 500, with a maximum of 1,000. +func (e *Exchange) GetFuturesExecution(ctx context.Context, symbol currency.Pair, limit uint64) ([]*FuturesExecutionInfo, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesExecutionInfo + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"trades", params), &resp) +} + +// GetLiquidationOrder gets details of previous liquidation events +func (e *Exchange) GetLiquidationOrder(ctx context.Context, symbol currency.Pair, direction string, startTime, endTime time.Time, offset, limit uint64) ([]*LiquidationPrice, error) { + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if direction != "" { + params.Set("direct", direction) + } + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + if offset > 0 { + params.Set("from", strconv.FormatUint(offset, 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*LiquidationPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"liquidationOrder", params), &resp) +} + +// GetFuturesMarket gets the market information of trading pairs in the past 24 hours. +func (e *Exchange) GetFuturesMarket(ctx context.Context, symbol currency.Pair) ([]*FuturesTickerDetails, error) { + params := url.Values{} + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + var resp []*FuturesTickerDetails + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"tickers", params), &resp) +} + +// GetFuturesIndexPrice gets the current index price. +func (e *Exchange) GetFuturesIndexPrice(ctx context.Context, symbol currency.Pair) (*InstrumentIndexPrice, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp *InstrumentIndexPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"indexPrice", params), &resp) +} + +// GetFuturesIndexPrices gets the current index price for all instruments +func (e *Exchange) GetFuturesIndexPrices(ctx context.Context) ([]*InstrumentIndexPrice, error) { + var resp []*InstrumentIndexPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, marketsPathV3+"indexPrice", &resp) +} + +// GetIndexPriceComponents gets the index price components for a trading pair. +func (e *Exchange) GetIndexPriceComponents(ctx context.Context, symbol currency.Pair) (*IndexPriceComponent, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp []*IndexPriceComponent + if err := e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"indexPriceComponents", params), &resp); err != nil { + return nil, fmt.Errorf("%w %w", order.ErrGetFailed, err) + } + if len(resp) != 1 { + return nil, fmt.Errorf("%w %w", order.ErrGetFailed, common.ErrInvalidResponse) + } + return resp[0], nil +} + +// GetAllIndexPriceComponents returns index price components for all pairs. +func (e *Exchange) GetAllIndexPriceComponents(ctx context.Context) ([]*IndexPriceComponent, error) { + var resp []*IndexPriceComponent + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, marketsPathV3+"indexPriceComponents", &resp) +} + +// GetIndexPriceKlineData obtains the K-line data for the index price. +func (e *Exchange) GetIndexPriceKlineData(ctx context.Context, symbol currency.Pair, interval kline.Interval, startTime, endTime time.Time, limit uint64) ([]*FuturesIndexPriceData, error) { + return e.getIndexPriceKlineData(ctx, symbol, interval, startTime, endTime, limit, "indexPriceCandlesticks", fCandlestickEPL) +} + +// GetPremiumIndexKlineData retrieves the K-line information of the premium index. +func (e *Exchange) GetPremiumIndexKlineData(ctx context.Context, symbol currency.Pair, interval kline.Interval, startTime, endTime time.Time, limit uint64) ([]*FuturesIndexPriceData, error) { + return e.getIndexPriceKlineData(ctx, symbol, interval, startTime, endTime, limit, "premiumIndexCandlesticks", fPremiumCandlestickEPL) +} + +func (e *Exchange) getIndexPriceKlineData(ctx context.Context, symbol currency.Pair, interval kline.Interval, startTime, endTime time.Time, limit uint64, path string, epl request.EndpointLimit) ([]*FuturesIndexPriceData, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + intervalString, err := intervalToString(interval) + if err != nil { + return nil, err + } + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + params.Set("symbol", symbol.String()) + params.Set("interval", intervalString) + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesIndexPriceData + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, epl, common.EncodeURLValues(marketsPathV3+path, params), &resp) +} + +// GetFuturesMarkPrice gets the current mark price. +func (e *Exchange) GetFuturesMarkPrice(ctx context.Context, symbol currency.Pair) (*FuturesMarkPrice, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp *FuturesMarkPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"markPrice", params), &resp) +} + +// GetFuturesMarkPrices gets the current mark price for all instruments +func (e *Exchange) GetFuturesMarkPrices(ctx context.Context) ([]*FuturesMarkPrice, error) { + var resp []*FuturesMarkPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, marketsPathV3+"markPrice", &resp) +} + +// GetMarkPriceKlineData obtains the K-line data for the mark price. +func (e *Exchange) GetMarkPriceKlineData(ctx context.Context, symbol currency.Pair, interval kline.Interval, startTime, endTime time.Time, limit uint64) ([]*FuturesMarkPriceCandle, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + intervalString, err := intervalToString(interval) + if err != nil { + return nil, err + } + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + params.Set("symbol", symbol.String()) + params.Set("interval", intervalString) + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesMarkPriceCandle + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fCandlestickEPL, common.EncodeURLValues(marketsPathV3+"markPriceCandlesticks", params), &resp) +} + +// GetFuturesAllProducts inquires about the basic information of all products. +func (e *Exchange) GetFuturesAllProducts(ctx context.Context, symbol currency.Pair) ([]*ProductDetail, error) { + params := url.Values{} + if !symbol.IsEmpty() { + params.Set("symbol", symbol.String()) + } + var resp []*ProductDetail + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"allInstruments", params), &resp) +} + +// GetFuturesProduct inquires about the basic information of one product. +func (e *Exchange) GetFuturesProduct(ctx context.Context, symbol currency.Pair) (*ProductDetail, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp *ProductDetail + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"instruments", params), &resp) +} + +// GetFuturesCurrentFundingRate retrieves the current funding rate of the contract. +func (e *Exchange) GetFuturesCurrentFundingRate(ctx context.Context, symbol currency.Pair) (*FuturesFundingRate, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp *FuturesFundingRate + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"fundingRate", params), &resp) +} + +// GetFuturesHistoricalFundingRates retrieves the previous funding rates of a contract. +func (e *Exchange) GetFuturesHistoricalFundingRates(ctx context.Context, symbol currency.Pair, startTime, endTime time.Time, limit uint64) ([]*FuturesFundingRate, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + if !startTime.IsZero() && !endTime.IsZero() { + if err := common.StartEndTimeCheck(startTime, endTime); err != nil { + return nil, err + } + } + params := url.Values{} + params.Set("symbol", symbol.String()) + if !startTime.IsZero() { + params.Set("sTime", strconv.FormatInt(startTime.UnixMilli(), 10)) + } + if !endTime.IsZero() { + params.Set("eTime", strconv.FormatInt(endTime.UnixMilli(), 10)) + } + if limit > 0 { + params.Set("limit", strconv.FormatUint(limit, 10)) + } + var resp []*FuturesFundingRate + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fCandlestickEPL, common.EncodeURLValues(marketsPathV3+"fundingRate/history", params), &resp) +} + +// GetContractOpenInterest retrieve all current open interest in the market. +func (e *Exchange) GetContractOpenInterest(ctx context.Context, symbol currency.Pair) (*OpenInterestData, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + var resp *OpenInterestData + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"openInterest", params), &resp) +} + +// GetInsuranceFund query insurance fund information +func (e *Exchange) GetInsuranceFund(ctx context.Context) ([]*InsuranceFundInfo, error) { + var resp []*InsuranceFundInfo + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, marketsPathV3+"insurance", &resp) +} + +// GetFuturesRiskLimit retrieve information from the Futures Risk Limit Table. +func (e *Exchange) GetFuturesRiskLimit(ctx context.Context, symbol currency.Pair, marginMode string, tier uint8) ([]*RiskLimit, error) { + if symbol.IsEmpty() { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbol.String()) + if marginMode != "" { + params.Set("mgnMode", marginMode) + } + if tier > 0 { + params.Set("tier", strconv.Itoa(int(tier))) + } + var resp []*RiskLimit + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"riskLimit", params), &resp) +} + +// GetContractLimitPrice query the highest buy price and the lowest sell price of the current contract trading pair. +func (e *Exchange) GetContractLimitPrice(ctx context.Context, symbols currency.Pairs) ([]ContractLimitPrice, error) { + if len(symbols) == 0 || (len(symbols) == 1 && symbols[0].IsEmpty()) { + return nil, currency.ErrSymbolStringEmpty + } + params := url.Values{} + params.Set("symbol", symbols.Join()) + var resp []ContractLimitPrice + return resp, e.SendHTTPRequest(ctx, exchange.RestSpot, fMarketEPL, common.EncodeURLValues(marketsPathV3+"limitPrice", params), &resp) +} diff --git a/exchanges/poloniex/poloniex_futures_types.go b/exchanges/poloniex/poloniex_futures_types.go new file mode 100644 index 00000000000..9a2a5332cc4 --- /dev/null +++ b/exchanges/poloniex/poloniex_futures_types.go @@ -0,0 +1,756 @@ +package poloniex + +import ( + "fmt" + + "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/encoding/json" + "github.com/thrasher-corp/gocryptotrader/exchanges/margin" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" + "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-corp/gocryptotrader/types" +) + +// MarginMode represents margin mode type for futures orders +type MarginMode margin.Type + +// MarshalText implements encoding.TextMarshaler and serializes MarginMode to a string +func (m MarginMode) MarshalText() ([]byte, error) { + switch margin.Type(m) { + case margin.Multi: + return []byte("CROSS"), nil + case margin.Isolated: + return []byte("ISOLATED"), nil + case margin.Unset: + return []byte(""), nil + } + return nil, fmt.Errorf("%w: %q", margin.ErrMarginTypeUnsupported, m) +} + +// FuturesAccountBalance represents a futures account balance detail +type FuturesAccountBalance struct { + State string `json:"state"` + Equity types.Number `json:"eq"` + IsolatedEquity types.Number `json:"isoEq"` + InitialMargin types.Number `json:"im"` + MaintenanceMargin types.Number `json:"mm"` + MaintenanceMarginRate types.Number `json:"mmr"` + UnrealizedProfitAndLoss types.Number `json:"upl"` + AvailableMargin types.Number `json:"availMgn"` + CreationTime types.Time `json:"cTime"` + UpdateTime types.Time `json:"uTime"` + Details []*FuturesCurrencyAccountBalance `json:"details"` +} + +// FuturesCurrencyAccountBalance holds a futures account currency balance detail +type FuturesCurrencyAccountBalance struct { + Currency currency.Code `json:"ccy"` + Equity types.Number `json:"eq"` + IsolatedEquity types.Number `json:"isoEq"` + Available types.Number `json:"avail"` + TradeHold types.Number `json:"trdHold"` + UnrealisedPNL types.Number `json:"upl"` + IsolatedAvailable types.Number `json:"isoAvail"` + IsolatedHold types.Number `json:"isoHold"` + IsolatedUPL types.Number `json:"isoUpl"` + InitialMargin types.Number `json:"im"` + MaintenanceMargin types.Number `json:"mm"` + MaintenanceMarginRate types.Number `json:"mmr"` + InitialMarginRate types.Number `json:"imr"` + CreationTime types.Time `json:"cTime"` + UpdateTime types.Time `json:"uTime"` +} + +// BillDetails represents a bill type detail information +type BillDetails struct { + ID string `json:"id"` + AccountType string `json:"actType"` + BillType string `json:"type"` + Currency currency.Code `json:"ccy"` + Symbol currency.Pair `json:"symbol"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + CreationTime types.Time `json:"cTime"` + Size types.Number `json:"sz"` +} + +// FuturesOrderRequest represents a futures order parameters +type FuturesOrderRequest struct { + Symbol currency.Pair `json:"symbol"` + Side string `json:"side"` + MarginMode MarginMode `json:"mgnMode"` + PositionSide order.Side `json:"posSide"` + OrderType OrderType `json:"type,omitempty"` + ClientOrderID string `json:"clOrdId,omitempty"` + Price float64 `json:"px,omitempty,string"` + Size float64 `json:"sz,omitempty,string"` + ReduceOnly bool `json:"reduceOnly,omitempty"` + TimeInForce TimeInForce `json:"timeInForce,omitempty"` + SelfTradePreventionMode string `json:"stpMode,omitempty"` +} + +// FuturesOrderIDResponse represents a futures order creation response +type FuturesOrderIDResponse struct { + ClientOrderID string `json:"clOrdId"` + OrderID string `json:"ordId"` + Code int64 `json:"code"` + Message string `json:"msg"` +} + +func (s *FuturesOrderIDResponse) Error() error { + if s == nil { + return common.ErrNoResponse + } + if s.Code != 0 && s.Code != 200 { + return fmt.Errorf("error code: %d; message: %s", s.Code, s.Message) + } + return nil +} + +// CancelOrderRequest represents a single order cancellation parameters +type CancelOrderRequest struct { + Symbol currency.Pair `json:"symbol"` + OrderID string `json:"ordId,omitempty"` + ClientOrderID string `json:"clOrdId,omitempty"` +} + +// CancelFuturesOrdersRequest represents cancel futures order request parameters +type CancelFuturesOrdersRequest struct { + Symbol currency.Pair `json:"symbol"` + OrderIDs []string `json:"ordIds,omitempty"` + ClientOrderIDs []string `json:"clOrdIds,omitempty"` +} + +// FuturesTradeFill represents a trade executions +type FuturesTradeFill struct { + ID string `json:"id"` + Symbol currency.Pair `json:"symbol"` + Side string `json:"side"` + OrderID string `json:"ordId"` + ClientOrderID string `json:"clOrdId"` + Role string `json:"role"` + TradeID string `json:"trdId"` + FeeCurrency currency.Code `json:"feeCcy"` + FeeAmount types.Number `json:"feeAmt"` + DeductCurrency currency.Code `json:"deductCcy"` + DeductAmount types.Number `json:"deductAmt"` + UpdateTime types.Time `json:"uTime"` + CreationTime types.Time `json:"cTime"` + FeeRate types.Number `json:"feeRate"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + OrderType string `json:"ordType"` + Price types.Number `json:"px"` + BaseAmount types.Number `json:"qty"` + Type string `json:"type"` + AccountType string `json:"actType"` + QuoteCurrency currency.Code `json:"qCcy"` + Value types.Number `json:"value"` +} + +// WSTradeFill represents a websocket streamed trade fill data +type WSTradeFill struct { + Symbol currency.Pair `json:"symbol"` + Side string `json:"side"` + OrderID string `json:"ordId"` + ClientOrderID string `json:"clOrdId"` + Role string `json:"role"` + TradeID string `json:"trdId"` + FeeCurrency currency.Code `json:"feeCcy"` + FeeAmount types.Number `json:"feeAmt"` + DeductCurrency currency.Code `json:"deductCcy"` + DeductAmount types.Number `json:"deductAmt"` + Type string `json:"type"` + FillPrice types.Number `json:"fpx"` + FillQuantity types.Number `json:"fqty"` + UpdateTime types.Time `json:"uTime"` + Timestamp types.Time `json:"ts"` +} + +// FuturesOrderDetails represents a futures v3 order detail +type FuturesOrderDetails struct { + Symbol currency.Pair `json:"symbol"` + Side order.Side `json:"side"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + AccountType string `json:"actType"` + QuoteCurrency currency.Code `json:"qCcy"` + OrderType string `json:"type"` + Price types.Number `json:"px"` + Size types.Number `json:"sz"` + TimeInForce order.TimeInForce `json:"timeInForce"` + OrderID string `json:"ordId"` + AveragePrice types.Number `json:"avgPx"` + CreationTime types.Time `json:"cTime"` + ClientOrderID string `json:"clOrdId"` + DeductAmount types.Number `json:"deductAmt"` + ExecutedAmount types.Number `json:"execAmt"` + DeductCurrency currency.Code `json:"deductCcy"` + ExecutedQuantity types.Number `json:"execQty"` + FeeAmount types.Number `json:"feeAmt"` + FeeCurrency currency.Code `json:"feeCcy"` + Leverage types.Number `json:"lever"` + ReduceOnly types.Boolean `json:"reduceOnly"` + StopLossPrice types.Number `json:"slPx"` + StopLossTriggerPrice string `json:"slTrgPx"` + StopLossTriggerPriceType string `json:"slTrgPxType"` + Source string `json:"source"` + State string `json:"state"` + SelfTradePreventionMode string `json:"stpMode"` + TakeProfitPrice types.Number `json:"tpPx"` + TakeProfitTriggerPrice types.Number `json:"tpTrgPx"` + TakeProfitTriggerPriceType string `json:"tpTrgPxType"` + UpdateTime types.Time `json:"uTime"` + CancelReason string `json:"cancelReason"` +} + +// FuturesWebsocketOrderDetails represents a futures websocket order detail +type FuturesWebsocketOrderDetails struct { + Symbol currency.Pair `json:"symbol"` + Side order.Side `json:"side"` + OrderType string `json:"type"` + MarginMode string `json:"mgnMode"` + TimeInForce order.TimeInForce `json:"timeInForce"` + ClientOrderID string `json:"clOrdId"` + Size types.Number `json:"sz"` + Price types.Number `json:"px"` + ReduceOnly bool `json:"reduceOnly"` + PositionSide string `json:"posSide"` + OrderID string `json:"ordId"` + State string `json:"state"` + CancelReason string `json:"cancelReason"` + Source string `json:"source"` + AveragePrice types.Number `json:"avgPx"` + ExecutedQuantity types.Number `json:"execQty"` + ExecutedAmount types.Number `json:"execAmt"` + FeeCurrency currency.Code `json:"feeCcy"` + FeeAmount types.Number `json:"feeAmt"` + DeductCurrency currency.Code `json:"deductCcy"` + DeductAmount types.Number `json:"deductAmt"` + FillSize types.Number `json:"fillSz"` + CreationTime types.Time `json:"cTime"` + UpdateTime types.Time `json:"uTime"` + Timestamp types.Time `json:"ts"` +} + +// FuturesPosition represents a v3 futures position detail +type FuturesPosition struct { + ID string `json:"id"` + Symbol currency.Pair `json:"symbol"` + Side string `json:"side"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + OpenAveragePrice types.Number `json:"openAvgPx"` + CloseAveragePrice string `json:"closeAvgPx"` + ClosedQuantity string `json:"closedQty"` + AvailableQuantity types.Number `json:"availQty"` + BaseAmount types.Number `json:"qty"` + ProfitAndLoss types.Number `json:"pnl"` + Fee string `json:"fee"` + FundingFee string `json:"fFee"` + State string `json:"state"` + CreationTime types.Time `json:"cTime"` + UpdateTime types.Time `json:"uTime"` +} + +// OpenFuturesPosition represents a v3 futures open position detail +type OpenFuturesPosition struct { + Symbol currency.Pair `json:"symbol"` + Side string `json:"side"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + OpenAveragePrice string `json:"openAvgPx"` + BaseAmount string `json:"qty"` + AvailableQuantity types.Number `json:"availQty"` + Leverage types.Number `json:"lever"` + AutoDeleveraging string `json:"adl"` + LiquidationPrice types.Number `json:"liqPx"` + InitialMargin types.Number `json:"im"` + MaintenanceMargin types.Number `json:"mm"` + IsolatedPositionMargin string `json:"mgn"` + MaxWithdrawalAmount types.Number `json:"maxWAmt"` + UnrealizedPNL types.Number `json:"upl"` + UnrealizedPNLRatio types.Number `json:"uplRatio"` + ProfitAndLoss types.Number `json:"pnl"` + MarkPrice types.Number `json:"markPx"` + LastPrice types.Number `json:"lastPx"` + IndexPrice types.Number `json:"indexPx"` + MarginRatio types.Number `json:"mgnRatio"` + State string `json:"state"` + AccountType string `json:"actType"` + TakeProfitTriggerPrice types.Number `json:"tpTrgPx"` + StopLossTriggerPrice types.Number `json:"slTrgPx"` + CreateTime types.Time `json:"cTime"` + UpdateTime types.Time `json:"uTime"` +} + +// WsFuturesPosition represents a futures websocket position +type WsFuturesPosition struct { + Symbol currency.Pair `json:"symbol"` + PositionSide string `json:"posSide"` + Side string `json:"side"` + MarginMode string `json:"mgnMode"` + OpenAveragePrice types.Number `json:"openAvgPx"` + BaseAmount types.Number `json:"qty"` + OldQuantity types.Number `json:"oldQty"` + AvailableQuantity types.Number `json:"availQty"` + Leverage uint16 `json:"lever"` + Fee types.Number `json:"fee"` + AutoDeleveraging string `json:"adl"` + LiquidationPrice types.Number `json:"liqPx"` + IsolatedPositionMargin types.Number `json:"mgn"` + InitialMargin types.Number `json:"im"` + MaintenanceMargin types.Number `json:"mm"` + UnrealizedPNL types.Number `json:"upl"` + UnrealizedPNLRatio types.Number `json:"uplRatio"` + LatestClosingProfitAndLoss types.Number `json:"fpnl"` + MarkPrice types.Number `json:"markPx"` + MarginRatio types.Number `json:"mgnRatio"` + State string `json:"state"` + CreateTime types.Time `json:"cTime"` + UpdateTime types.Time `json:"uTime"` + Timestamp types.Time `json:"ts"` + ProfitAndLoss types.Number `json:"pnl"` + FundingFee types.Number `json:"ffee"` +} + +// AdjustFuturesMarginResponse represents a response data after adjusting futures margin positions +type AdjustFuturesMarginResponse struct { + Amount types.Number `json:"amt"` + Leverage uint8 `json:"lever,string"` + Symbol currency.Pair `json:"symbol"` + PositionSide string `json:"posSide"` + OrderType string `json:"type"` +} + +// FuturesLeverage represents futures symbols leverage information +type FuturesLeverage struct { + Leverage uint8 `json:"lever,string"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + Symbol currency.Pair `json:"symbol"` +} + +// FuturesOpenInterest represents futures open interest value for symbol +type FuturesOpenInterest struct { + Symbol currency.Pair `json:"s"` + OpenInterest types.Number `json:"oInterest"` + Timestamp types.Time `json:"ts"` +} + +// FuturesLiquidationOrder represents a futures liquidation price detail +type FuturesLiquidationOrder struct { + Symbol currency.Pair `json:"s"` + Side string `json:"side"` + PositionSide string `json:"posSide"` + Size types.Number `json:"sz"` + BankruptcyPrice types.Number `json:"bkPx"` + UpdateTime types.Time `json:"uTime"` + Timestamp types.Time `json:"ts"` +} + +// FuturesLimitPrice represents a futures limit price info +type FuturesLimitPrice struct { + Timestamp types.Time `json:"ts"` + Symbol currency.Pair `json:"s"` + BuyLimit types.Number `json:"buyLmt"` + SellLimit types.Number `json:"sellLmt"` +} + +// UserPositionRiskLimit represents a user position risk limit detail +type UserPositionRiskLimit struct { + Symbol currency.Pair `json:"symbol"` + MarginMode string `json:"mgnMode"` + PositionSide string `json:"posSide"` + Tier string `json:"tier"` + MaxLeverage uint16 `json:"maxLever,string"` + MaintenanceMarginRatio types.Number `json:"mMRatio"` + MaxSize types.Number `json:"maxSize"` + MinSize types.Number `json:"minSize"` +} + +// FuturesOrderbook represents an orderbook data for v3 futures instruments +type FuturesOrderbook struct { + Asks orderbook.LevelsArrayPriceAmount `json:"asks"` + Bids orderbook.LevelsArrayPriceAmount `json:"bids"` + Scale types.Number `json:"s"` + Timestamp types.Time `json:"ts"` +} + +// WSFuturesOrderbook represents an orderbook data for v3 websocket futures instruments +type WSFuturesOrderbook struct { + ID int64 `json:"id"` + LastVersionID int64 `json:"lid"` + Symbol currency.Pair `json:"s"` + Asks orderbook.LevelsArrayPriceAmount `json:"asks"` + Bids orderbook.LevelsArrayPriceAmount `json:"bids"` + CreationTime types.Time `json:"cT"` + Timestamp types.Time `json:"ts"` +} + +// FuturesCandle represents a kline data for v3 futures instrument +type FuturesCandle struct { + LowestPrice types.Number + HighestPrice types.Number + OpeningPrice types.Number + ClosingPrice types.Number + QuoteAmount types.Number + BaseAmount types.Number + Trades types.Number + StartTime types.Time + EndTime types.Time +} + +// UnmarshalJSON deserializes JSON data into a kline.Candle instance +func (v *FuturesCandle) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &[9]any{&v.LowestPrice, &v.HighestPrice, &v.OpeningPrice, &v.ClosingPrice, &v.QuoteAmount, &v.BaseAmount, &v.Trades, &v.StartTime, &v.EndTime}) +} + +// FuturesExecutionInfo represents a V3 futures instruments execution information +type FuturesExecutionInfo struct { + ID int64 `json:"id"` + Price types.Number `json:"px"` + BaseAmount types.Number `json:"qty"` + QuoteAmount types.Number `json:"amt"` + Side string `json:"side"` + CreationTime types.Time `json:"cT"` +} + +// LiquidationPrice represents a liquidation price detail for an instrument +type LiquidationPrice struct { + Symbol currency.Pair `json:"symbol"` + PositionSide string `json:"posSide"` + Side string `json:"side"` + Size types.Number `json:"sz"` + PriceOfCommissionedTransaction types.Number `json:"bkPx"` + UpdateTime types.Time `json:"uTime"` +} + +// FuturesTickerDetails represents a v3 futures instrument ticker detail +type FuturesTickerDetails struct { + Symbol currency.Pair `json:"s"` + OpeningPrice types.Number `json:"o"` + LowPrice types.Number `json:"l"` + HighPrice types.Number `json:"h"` + ClosingPrice types.Number `json:"c"` + BaseAmount types.Number `json:"qty"` + QuoteAmount types.Number `json:"amt"` + TradeCount int64 `json:"tC"` + StartTime types.Time `json:"sT"` + EndTime types.Time `json:"cT"` + DailyPrice types.Number `json:"dC"` + DisplayName string `json:"dN"` + BestBidPrice types.Number `json:"bPx"` + BestBidSize types.Number `json:"bSz"` + BestAskPrice types.Number `json:"aPx"` + BestAskSize types.Number `json:"aSz"` + MarkPrice types.Number `json:"mPx"` + IndexPrice types.Number `json:"iPx"` + Timestamp types.Time `json:"ts"` +} + +// InstrumentIndexPrice represents a symbols index price +type InstrumentIndexPrice struct { + Symbol currency.Pair `json:"s"` + Timestamp types.Time `json:"ts"` +} + +// WSInstrumentIndexPrice represents a symbols index price of websocket response +type WSInstrumentIndexPrice struct { + Symbol currency.Pair `json:"s"` + Timestamp types.Time `json:"ts"` + IndexPrice types.Number `json:"iPx"` +} + +// IndexPriceComponent represents an index price component detail +type IndexPriceComponent struct { + Symbol currency.Pair `json:"s"` + Price types.Number `json:"px"` + Cs []SymbolPriceDetails `json:"cs"` +} + +// SymbolPriceDetails represents symbol's price from different exchanges and its weight factor. +type SymbolPriceDetails struct { + Exchange string `json:"e"` + WeightFactor types.Number `json:"w"` + TradingPairPrice types.Number `json:"sPx"` + TradingPairIndexPrice types.Number `json:"cPx"` +} + +// FuturesIndexPriceData represents a futures index price data detail +type FuturesIndexPriceData struct { + OpenPrice types.Number + HighPrice types.Number + LowestPrice types.Number + ClosingPrice types.Number + StartTime types.Time + EndTime types.Time +} + +// UnmarshalJSON deserializes candlestick data into a FuturesIndexPriceData instance +func (v *FuturesIndexPriceData) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &[6]any{&v.LowestPrice, &v.HighPrice, &v.OpenPrice, &v.ClosingPrice, &v.StartTime, &v.EndTime}) +} + +// FuturesMarkPrice represents a mark price instance +type FuturesMarkPrice struct { + MarkPrice types.Number `json:"mPx"` + Symbol currency.Pair `json:"s"` +} + +// FuturesWebsocketMarkPrice represents a mark price instance for websocket response +type FuturesWebsocketMarkPrice struct { + MarkPrice types.Number `json:"mPx"` + Symbol currency.Pair `json:"s"` + Timestamp types.Time `json:"ts"` +} + +// FuturesMarkPriceCandle represents a k-line data for mark price +type FuturesMarkPriceCandle struct { + OpeningPrice types.Number + HighestPrice types.Number + LowestPrice types.Number + ClosingPrice types.Number + StartTime types.Time + EndTime types.Time +} + +// UnmarshalJSON deserializes byte data into FuturesMarkPriceCandle instance +func (v *FuturesMarkPriceCandle) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &[6]any{&v.LowestPrice, &v.HighestPrice, &v.OpeningPrice, &v.ClosingPrice, &v.StartTime, &v.EndTime}) +} + +// WSProductDetail represents websocket response of basic information of all products +type WSProductDetail struct { + Symbol string `json:"s"` + VisibleStartTime types.Time `json:"visibleST"` + TradableStartTime types.Time `json:"tradableST"` + PriceScale string `json:"pxScale"` + LotSize float64 `json:"lotSz"` + MinSize float64 `json:"minSz"` + ContractFeeValue types.Number `json:"ctVal"` + Status string `json:"status"` + MaxPrice types.Number `json:"maxPx"` + MinPrice types.Number `json:"minPx"` + MaxQuantity types.Number `json:"maxQty"` + MinQuantity types.Number `json:"minQty"` + MaxLeverage uint16 `json:"maxLever,string"` + Leverage string `json:"lever"` + OrderPriceRange string `json:"ordPxRange"` + ContractType string `json:"ctType"` + Alias string `json:"alias"` + MarketMaxQuantity types.Number `json:"marketMaxQty"` + LimitMaxQuantity types.Number `json:"limitMaxQty"` + Timestamp types.Time `json:"ts"` + BaseCurrency currency.Code `json:"bCcy"` + UnderlyingAsset string `json:"bAsset"` + QuoteCurrency currency.Code `json:"qCcy"` + SettlementCurrency currency.Code `json:"sCcy"` + TickSize types.Number `json:"tSz"` + ListingDate types.Time `json:"oDate"` + InitialMarginRate types.Number `json:"iM"` + MaximumRiskLimit types.Number `json:"mR"` + MaintenanceMarginRate types.Number `json:"mM"` +} + +// ProductDetail represents basic information of all products +type ProductDetail struct { + Alias string `json:"alias"` + BaseAsset string `json:"bAsset"` + BaseCurrency string `json:"bCcy"` + ContractType string `json:"ctType"` + ContractValue types.Number `json:"ctVal"` + InitialMarginRate types.Number `json:"iM"` + Leverage uint16 `json:"lever,string"` + MaxLeverage uint16 `json:"maxLever,string"` + SizePrecision uint16 `json:"lotSz"` + MaintenanceMarginRate types.Number `json:"mM"` + MaximumRiskLimit types.Number `json:"mR"` + MaxPrice types.Number `json:"maxPx"` + MaxQuantity types.Number `json:"maxQty"` + MinPrice types.Number `json:"minPx"` + MinQuantity types.Number `json:"minQty"` + MinSize uint16 `json:"minSz"` + ListingDate types.Time `json:"oDate"` + PriceScale string `json:"pxScale"` + QuoteCurrency currency.Code `json:"qCcy"` + SettlementCurrency currency.Code `json:"sCcy"` + Status string `json:"status"` + Symbol currency.Pair `json:"symbol"` + TickSize types.Number `json:"tSz"` + TradableStartTime types.Time `json:"tradableStartTime"` + VisibleStartTime types.Time `json:"visibleStartTime"` + OrderPriceRange types.Number `json:"ordPxRange"` + MarketMaxQty types.Number `json:"marketMaxQty"` + LimitMaxQty types.Number `json:"limitMaxQty"` +} + +// FuturesFundingRate represents symbols funding rate information +type FuturesFundingRate struct { + Symbol currency.Pair `json:"s"` + FundingRate types.Number `json:"fR"` + FundingRateSettleTime types.Time `json:"fT"` + NextPredictedFundingRate types.Number `json:"nFR"` + NextFundingTime types.Time `json:"nFT"` +} + +// WSFuturesFundingRate represents symbols funding rate information pushed through websocket +type WSFuturesFundingRate struct { + Symbol currency.Pair `json:"s"` + FundingRate types.Number `json:"fR"` + FundingRateSettleTime types.Time `json:"fT"` + NextPredictedFundingRate types.Number `json:"nFR"` + NextFundingTime types.Time `json:"nFT"` + PushTime types.Time `json:"ts"` +} + +// OpenInterestData represents an open interest data +type OpenInterestData struct { + CurrentOpenInterest types.Number `json:"oInterest"` + Symbol currency.Pair `json:"s"` +} + +// InsuranceFundInfo represents an insurance fund information of a currency +type InsuranceFundInfo struct { + Amount types.Number `json:"amt"` + Currency currency.Code `json:"ccy"` + UpdateTime types.Time `json:"uTime"` +} + +// RiskLimit represents a risk limit of futures instrument +type RiskLimit struct { + Symbol currency.Pair `json:"symbol"` + MarginMode string `json:"mgnMode"` + Tier uint8 `json:"tier,string"` + MaxLeverage uint16 `json:"maxLever,string"` + MaintenanceMarginRatio types.Number `json:"mMRatio"` + MaxSize types.Number `json:"maxSize"` + MinSize types.Number `json:"minSize"` +} + +// WsFuturesCandlestick represents a kline data for futures instrument +type WsFuturesCandlestick struct { + Symbol currency.Pair + LowestPrice types.Number + HighestPrice types.Number + OpenPrice types.Number + ClosePrice types.Number + BaseAmount types.Number + QuoteAmount types.Number + Trades uint64 + StartTime types.Time + EndTime types.Time + PushTime types.Time +} + +// UnmarshalJSON deserialises byte data into futures candlesticks into *WsFuturesCandlestick +func (o *WsFuturesCandlestick) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &[11]any{&o.Symbol, &o.LowestPrice, &o.HighestPrice, &o.OpenPrice, &o.ClosePrice, &o.QuoteAmount, &o.BaseAmount, &o.Trades, &o.StartTime, &o.EndTime, &o.PushTime}) +} + +// FuturesTrades represents a futures trades detail +type FuturesTrades struct { + ID int64 `json:"id"` + Timestamp types.Time `json:"ts"` + Symbol currency.Pair `json:"s"` + Price types.Number `json:"px"` + BaseAmount types.Number `json:"qty"` + QuoteAmount types.Number `json:"amt"` + Side string `json:"side"` + CreationTime types.Time `json:"cT"` +} + +// WsFuturesMarkAndIndexPriceCandle represents a websocket k-line data for mark/index candlestick data +type WsFuturesMarkAndIndexPriceCandle struct { + OpeningPrice types.Number + HighestPrice types.Number + LowestPrice types.Number + ClosingPrice types.Number + StartTime types.Time + EndTime types.Time + Symbol currency.Pair + PushTimestamp types.Time +} + +// UnmarshalJSON deserializes byte data into WsFuturesMarkAndIndexPriceCandle instance +func (v *WsFuturesMarkAndIndexPriceCandle) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &[8]any{&v.Symbol, &v.LowestPrice, &v.HighestPrice, &v.OpeningPrice, &v.ClosingPrice, &v.StartTime, &v.EndTime, &v.PushTimestamp}) +} + +// MarginModeSwitchResponse represents a response detail after switching margin mode for a symbol +type MarginModeSwitchResponse struct { + MarginMode string `json:"mgnMode"` + Symbol currency.Pair `json:"symbol"` +} + +// ContractLimitPrice holds a contracts highest buy price and lowest sell price limits +type ContractLimitPrice struct { + Symbol currency.Pair `json:"symbol"` + BuyLimit float64 `json:"buyLmt"` + SellLimit float64 `json:"sellLmt"` +} + +// FuturesOrders represents a paginated list of Futures orders. +type FuturesOrders struct { + CurrentPage int64 `json:"currentPage"` + PageSize int64 `json:"pageSize"` + TotalNum int64 `json:"totalNum"` + TotalPage int64 `json:"totalPage"` + Items []FuturesOrder `json:"items"` +} + +// FuturesOrder represents a futures order detail. +type FuturesOrder struct { + OrderID string `json:"id"` + Symbol currency.Pair `json:"symbol"` + OrderType string `json:"type"` + Side string `json:"side"` + Price types.Number `json:"price"` + Size float64 `json:"size"` + Value types.Number `json:"value"` + FilledValue types.Number `json:"filledValue"` + FilledSize float64 `json:"filledSize"` + SelfTradePrevention string `json:"stp"` + Stop string `json:"stop"` + StopPriceType string `json:"stopPriceType"` + StopTriggered bool `json:"stopTriggered"` + StopPrice float64 `json:"stopPrice"` + TimeInForce order.TimeInForce `json:"timeInForce"` + PostOnly bool `json:"postOnly"` + Hidden bool `json:"hidden"` + Iceberg bool `json:"iceberg"` + VisibleSize float64 `json:"visibleSize"` + Leverage types.Number `json:"leverage"` + ForceHold bool `json:"forceHold"` + CloseOrder bool `json:"closeOrder"` + ReduceOnly bool `json:"reduceOnly"` + ClientOrderID string `json:"clientOid"` + Remark string `json:"remark"` + IsActive bool `json:"isActive"` + CancelExist bool `json:"cancelExist"` + CreatedAt types.Time `json:"createdAt"` + SettleCurrency currency.Code `json:"settleCurrency"` + Status string `json:"status"` + UpdatedAt types.Time `json:"updatedAt"` + OrderTime types.Time `json:"orderTime"` + + MarginType int64 `json:"marginType"` // Margin Mode, 0 (Isolated) or 1 (Cross) + Trades []TradeIDAndFee `json:"trades"` +} + +// TradeIDAndFee holds a trade ID and fee information +type TradeIDAndFee struct { + FeePay float64 `json:"feePay"` + TradeID string `json:"tradeId"` +} + +// AuthenticationResponse represents an authentication response for futures websocket connection +type AuthenticationResponse struct { + Data struct { + Success bool `json:"success"` + Message string `json:"message"` + Timestamp types.Time `json:"ts"` + } `json:"data"` + Channel string `json:"channel"` +} diff --git a/exchanges/poloniex/poloniex_futures_websocket.go b/exchanges/poloniex/poloniex_futures_websocket.go new file mode 100644 index 00000000000..2da07c38ef7 --- /dev/null +++ b/exchanges/poloniex/poloniex_futures_websocket.go @@ -0,0 +1,522 @@ +package poloniex + +import ( + "context" + "encoding/base64" + "fmt" + "strconv" + "strings" + "time" + + "github.com/thrasher-corp/gocryptotrader/common/crypto" + "github.com/thrasher-corp/gocryptotrader/encoding/json" + "github.com/thrasher-corp/gocryptotrader/exchange/accounts" + "github.com/thrasher-corp/gocryptotrader/exchange/websocket" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/fill" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/margin" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" + "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-corp/gocryptotrader/exchanges/subscription" + "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/trade" +) + +const ( + futuresWebsocketPrivateURL = "wss://ws.poloniex.com/ws/v3/private" + futuresWebsocketPublicURL = "wss://ws.poloniex.com/ws/v3/public" +) + +const ( + // Public channels + channelFuturesSymbol = "symbol" + channelFuturesOrderbookLvl2 = "book_lv2" + channelFuturesOrderbook = "book" + channelFuturesTickers = "tickers" + channelFuturesTrades = "trades" + channelFuturesIndexPrice = "index_price" + channelFuturesMarkPrice = "mark_price" + channelFuturesFundingRate = "funding_rate" + channelFuturesMarkPriceCandles = "mark_price_candles" + channelFuturesMarkCandles = "mark_candles" + channelFuturesCandles = "candles" + channelFuturesIndexCandles = "index_candles" + channelFuturesLimitPrice = "limit_price" + channelFuturesLiquidationPrice = "liquidation_orders" + channelFuturesOpenInterest = "open_interest" + + // Authenticated channels + channelFuturesPrivatePositions = "positions" + channelFuturesPrivateOrders = "orders" + channelFuturesPrivateTrades = "trade" + channelFuturesAccount = "account" +) + +var ( + futuresDefaultSubscriptions = subscription.List{ + {Enabled: true, Asset: asset.Futures, Channel: subscription.CandlesChannel, Interval: kline.FiveMin}, + {Enabled: true, Asset: asset.Futures, Channel: subscription.AllTradesChannel}, + {Enabled: true, Asset: asset.Futures, Channel: subscription.TickerChannel}, + {Enabled: true, Asset: asset.Futures, Channel: subscription.OrderbookChannel}, + } + + futuresPrivateDefaultSubscriptions = subscription.List{ + {Enabled: true, Asset: asset.Futures, Channel: subscription.MyAccountChannel, Authenticated: true}, + {Enabled: true, Asset: asset.Futures, Channel: subscription.MyOrdersChannel, Authenticated: true}, + {Enabled: true, Asset: asset.Futures, Channel: subscription.MyTradesChannel, Authenticated: true}, + } + + futuresSubscriptionNames = map[string]string{ + subscription.CandlesChannel: channelFuturesCandles, + subscription.AllTradesChannel: channelFuturesTrades, + subscription.TickerChannel: channelFuturesTickers, + subscription.OrderbookChannel: channelFuturesOrderbookLvl2, + subscription.MyOrdersChannel: channelFuturesPrivateOrders, + subscription.MyAccountChannel: channelFuturesAccount, + subscription.MyTradesChannel: channelFuturesPrivateTrades, + } +) + +// authenticateFuturesAuthConn authenticates a futures websocket connection +func (e *Exchange) authenticateFuturesAuthConn(ctx context.Context, conn websocket.Connection) error { + creds, err := e.GetCredentials(ctx) + if err != nil { + return err + } + + timestamp := time.Now().UnixMilli() + signatureStrings := "GET\n/ws\nsignTimestamp=" + strconv.FormatInt(timestamp, 10) + + var hmac []byte + hmac, err = crypto.GetHMAC(crypto.HashSHA256, + []byte(signatureStrings), + []byte(creds.Secret)) + if err != nil { + return err + } + e.futuresSubMtx.Lock() + data, err := conn.SendMessageReturnResponse(ctx, fWebsocketPrivateEPL, "auth", &SubscriptionPayload{ + Event: "subscribe", + Channel: []string{"auth"}, + Params: map[string]any{ + "key": creds.Key, + "signTimestamp": timestamp, + "signature": base64.StdEncoding.EncodeToString(hmac), + }, + }) + e.futuresSubMtx.Unlock() + if err != nil { + return err + } + var resp *AuthenticationResponse + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + if !resp.Data.Success { + return fmt.Errorf("authentication failed with status code: %s", resp.Data.Message) + } + return nil +} + +func (e *Exchange) generateFuturesSubscriptions() (subscription.List, error) { + return futuresDefaultSubscriptions.ExpandTemplates(e) +} + +func (e *Exchange) generateFuturesPrivateSubscriptions() (subscription.List, error) { + return futuresPrivateDefaultSubscriptions.ExpandTemplates(e) +} + +func (e *Exchange) wsFuturesHandleData(ctx context.Context, conn websocket.Connection, respRaw []byte) error { + var result *SubscriptionResponse + if err := json.Unmarshal(respRaw, &result); err != nil { + return err + } + if result.Event != "" { + switch result.Event { + case "pong": + return nil + case "subscribe", "unsubscribe", "error": + return conn.RequireMatchWithData("subscription", respRaw) + default: + return fmt.Errorf("%s %s %s", e.Name, websocket.UnhandledMessage, string(respRaw)) + } + } + switch result.Channel { + case channelAuth: + return conn.RequireMatchWithData(channelAuth, respRaw) + case channelFuturesSymbol: + var resp []*WSProductDetail + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + case channelFuturesOrderbookLvl2: + return e.processFuturesOrderbookLevel2(result.Data, result.Action) + case channelFuturesOrderbook: + return e.processFuturesOrderbook(result.Data) + case channelFuturesTickers: + return e.processFuturesTickers(ctx, result.Data) + case channelFuturesTrades: + return e.processFuturesTrades(ctx, result.Data) + case channelFuturesIndexPrice: + var resp []*WSInstrumentIndexPrice + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + case channelFuturesMarkPrice: + var resp []*FuturesWebsocketMarkPrice + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + case channelFuturesFundingRate: + return e.processFuturesFundingRate(ctx, result.Data) + case channelFuturesPrivatePositions: + var resp []*WsFuturesPosition + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + case channelFuturesPrivateOrders: + return e.processFuturesOrders(ctx, result.Data) + case channelFuturesPrivateTrades: + return e.processFuturesTradeFills(ctx, result.Data) + case channelFuturesAccount: + return e.processFuturesAccountData(ctx, result.Data) + case channelFuturesLimitPrice: + var resp []*FuturesLimitPrice + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + case channelFuturesLiquidationPrice: + var resp []*FuturesLiquidationOrder + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + case channelFuturesOpenInterest: + var resp []*FuturesOpenInterest + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + return e.Websocket.DataHandler.Send(ctx, resp) + default: + if strings.Contains(result.Channel, "_") { + channel, interval, err := channelToIntervalSplit(result.Channel) + if err != nil { + return err + } + switch channel { + case channelFuturesMarkPriceCandles, channelFuturesMarkCandles, channelFuturesIndexCandles: + return e.processFuturesMarkAndIndexPriceCandlesticks(ctx, result.Data, interval) + case channelFuturesCandles: + return e.processFuturesCandlesticks(ctx, result.Data, interval) + } + } + return fmt.Errorf("%s %s %s", e.Name, websocket.UnhandledMessage, string(respRaw)) + } +} + +func channelToIntervalSplit(intervalString string) (string, kline.Interval, error) { + splits := strings.Split(intervalString, "_") + length := len(splits) + if length < 3 { + return intervalString, kline.Interval(0), fmt.Errorf("%w %q", kline.ErrInvalidInterval, intervalString) + } + intervalValue, err := stringToInterval(strings.Join(splits[length-2:], "_")) + return strings.Join(splits[:length-2], "_"), intervalValue, err +} + +func (e *Exchange) processFuturesAccountData(ctx context.Context, data []byte) error { + var resp []*FuturesAccountBalance + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + var accChanges []accounts.Change + for _, r := range resp { + for _, detail := range r.Details { + accChanges = append(accChanges, accounts.Change{ + AssetType: asset.Futures, + Balance: accounts.Balance{ + Currency: detail.Currency, + Total: detail.Available.Float64(), + Hold: detail.TradeHold.Float64(), + Free: detail.Available.Float64() - detail.TradeHold.Float64(), + UpdatedAt: detail.UpdateTime.Time(), + }, + }) + } + } + return e.Websocket.DataHandler.Send(ctx, accChanges) +} + +func (e *Exchange) processFuturesTradeFills(ctx context.Context, data []byte) error { + var resp []*WSTradeFill + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + tFills := make([]fill.Data, len(resp)) + for i, r := range resp { + oSide, err := order.StringToOrderSide(r.Side) + if err != nil { + return err + } + tFills[i] = fill.Data{ + Side: oSide, + Exchange: e.Name, + AssetType: asset.Futures, + CurrencyPair: r.Symbol, + OrderID: r.OrderID, + ID: r.TradeID, + TradeID: r.TradeID, + ClientOrderID: r.ClientOrderID, + Timestamp: r.UpdateTime.Time(), + Amount: r.FillQuantity.Float64(), + Price: r.FillPrice.Float64(), + } + } + return e.Websocket.DataHandler.Send(ctx, tFills) +} + +func (e *Exchange) processFuturesOrders(ctx context.Context, data []byte) error { + var resp []*FuturesWebsocketOrderDetails + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + orders := make([]order.Detail, len(resp)) + for i, r := range resp { + oStatus, err := order.StringToOrderStatus(r.State) + if err != nil { + return err + } + oType, err := order.StringToOrderType(r.OrderType) + if err != nil { + return err + } + var marginMode margin.Type + if r.MarginMode != "" { + marginMode, err = margin.StringToMarginType(r.MarginMode) + if err != nil { + return err + } + } + orders[i] = order.Detail{ + ReduceOnly: r.ReduceOnly, + Price: r.Price.Float64(), + Amount: r.Size.Float64(), + AverageExecutedPrice: r.AveragePrice.Float64(), + ExecutedAmount: r.ExecutedQuantity.Float64(), + RemainingAmount: r.Size.Float64() - r.ExecutedQuantity.Float64(), + Fee: r.FeeAmount.Float64(), + FeeAsset: r.FeeCurrency, + Exchange: e.Name, + OrderID: r.OrderID, + ClientOrderID: r.ClientOrderID, + Type: oType, + Side: r.Side, + Status: oStatus, + AssetType: asset.Futures, + Date: r.CreationTime.Time(), + LastUpdated: r.UpdateTime.Time(), + TimeInForce: r.TimeInForce, + MarginType: marginMode, + Pair: r.Symbol, + } + } + return e.Websocket.DataHandler.Send(ctx, orders) +} + +func (e *Exchange) processFuturesFundingRate(ctx context.Context, data []byte) error { + var resp []*WSFuturesFundingRate + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + + for _, r := range resp { + if err := e.Websocket.DataHandler.Send(ctx, websocket.FundingData{ + CurrencyPair: r.Symbol, + Timestamp: r.PushTime.Time(), + AssetType: asset.Futures, + Exchange: e.Name, + Rate: r.FundingRate.Float64(), + }); err != nil { + return err + } + } + return nil +} + +func (e *Exchange) processFuturesMarkAndIndexPriceCandlesticks(ctx context.Context, data []byte, interval kline.Interval) error { + var resp []*WsFuturesMarkAndIndexPriceCandle + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + + candles := make([]websocket.KlineData, len(resp)) + for i, r := range resp { + candles[i] = websocket.KlineData{ + Timestamp: r.PushTimestamp.Time(), + Pair: r.Symbol, + AssetType: asset.Futures, + Exchange: e.Name, + StartTime: r.StartTime.Time(), + CloseTime: r.EndTime.Time(), + Interval: interval.String(), + OpenPrice: r.OpeningPrice.Float64(), + ClosePrice: r.ClosingPrice.Float64(), + HighPrice: r.HighestPrice.Float64(), + LowPrice: r.LowestPrice.Float64(), + } + } + return e.Websocket.DataHandler.Send(ctx, candles) +} + +func (e *Exchange) processFuturesOrderbook(data []byte) error { + var resp []*WSFuturesOrderbook + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + for _, r := range resp { + if err := e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{ + Bids: r.Bids.Levels(), + Asks: r.Asks.Levels(), + Exchange: e.Name, + LastUpdateID: r.ID, + Asset: asset.Futures, + Pair: r.Symbol, + LastUpdated: r.CreationTime.Time(), + }); err != nil { + return err + } + } + return nil +} + +func (e *Exchange) processFuturesOrderbookLevel2(data []byte, action string) error { + var resp []*WSFuturesOrderbook + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + for _, r := range resp { + if action == "snapshot" { + if err := e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{ + Bids: r.Bids.Levels(), + Asks: r.Asks.Levels(), + Exchange: e.Name, + Asset: asset.Futures, + Pair: r.Symbol, + LastUpdated: r.CreationTime.Time(), + LastUpdateID: r.LastVersionID, + }); err != nil { + return err + } + continue + } + if err := e.Websocket.Orderbook.Update(&orderbook.Update{ + UpdateID: r.ID, + UpdateTime: r.CreationTime.Time(), + LastPushed: r.Timestamp.Time(), + Action: orderbook.UpdateAction, + Asset: asset.Futures, + Pair: r.Symbol, + Asks: r.Asks.Levels(), + Bids: r.Bids.Levels(), + }); err != nil { + return err + } + } + return nil +} + +func (e *Exchange) processFuturesTickers(ctx context.Context, data []byte) error { + var resp []*FuturesTickerDetails + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + tickerPrices := make([]ticker.Price, len(resp)) + for i, r := range resp { + tickerPrices[i] = ticker.Price{ + High: r.HighPrice.Float64(), + Low: r.LowPrice.Float64(), + Bid: r.BestBidPrice.Float64(), + BidSize: r.BestBidSize.Float64(), + Ask: r.BestAskPrice.Float64(), + AskSize: r.BestAskSize.Float64(), + Volume: r.BaseAmount.Float64(), + QuoteVolume: r.QuoteAmount.Float64(), + Open: r.OpeningPrice.Float64(), + Close: r.ClosingPrice.Float64(), + MarkPrice: r.MarkPrice.Float64(), + Pair: r.Symbol, + ExchangeName: e.Name, + AssetType: asset.Futures, + LastUpdated: r.Timestamp.Time(), + } + } + return e.Websocket.DataHandler.Send(ctx, tickerPrices) +} + +// processFuturesTrades handles latest trading data for this product, including the latest price, trading volume, trading direction, etc. +func (e *Exchange) processFuturesTrades(ctx context.Context, data []byte) error { + var resp []*FuturesTrades + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + trades := make([]trade.Data, len(resp)) + for i, r := range resp { + oSide, err := order.StringToOrderSide(resp[i].Side) + if err != nil { + return err + } + trades[i] = trade.Data{ + TID: strconv.FormatInt(r.ID, 10), + Exchange: e.Name, + Side: oSide, + AssetType: asset.Futures, + CurrencyPair: r.Symbol, + Price: r.Price.Float64(), + Amount: r.BaseAmount.Float64(), + Timestamp: r.Timestamp.Time(), + } + } + return e.Websocket.DataHandler.Send(ctx, trades) +} + +func (e *Exchange) processFuturesCandlesticks(ctx context.Context, data []byte, interval kline.Interval) error { + var resp []*WsFuturesCandlestick + if err := json.Unmarshal(data, &resp); err != nil { + return err + } + + candles := make([]websocket.KlineData, len(resp)) + for i, r := range resp { + candles[i] = websocket.KlineData{ + Timestamp: r.PushTime.Time(), + Pair: r.Symbol, + AssetType: asset.Futures, + Exchange: e.Name, + StartTime: r.StartTime.Time(), + CloseTime: r.EndTime.Time(), + Interval: interval.String(), + OpenPrice: r.OpenPrice.Float64(), + ClosePrice: r.ClosePrice.Float64(), + HighPrice: r.HighestPrice.Float64(), + LowPrice: r.LowestPrice.Float64(), + Volume: r.QuoteAmount.Float64(), + } + } + return e.Websocket.DataHandler.Send(ctx, candles) +} + +// SubscribeFutures sends a websocket message to receive data from the channel +func (e *Exchange) SubscribeFutures(ctx context.Context, conn websocket.Connection, subs subscription.List) error { + return e.manageSubs(ctx, "subscribe", conn, subs, &e.futuresSubMtx) +} + +// UnsubscribeFutures sends a websocket message to stop receiving data from the channel +func (e *Exchange) UnsubscribeFutures(ctx context.Context, conn websocket.Connection, unsub subscription.List) error { + return e.manageSubs(ctx, "unsubscribe", conn, unsub, &e.futuresSubMtx) +} diff --git a/exchanges/poloniex/poloniex_live_test.go b/exchanges/poloniex/poloniex_live_test.go index f90bc89f267..2ffce59374d 100644 --- a/exchanges/poloniex/poloniex_live_test.go +++ b/exchanges/poloniex/poloniex_live_test.go @@ -5,11 +5,14 @@ package poloniex import ( + "context" "log" "os" "testing" + "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchange/stream" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange" ) @@ -19,14 +22,39 @@ var mockTests = false func TestMain(m *testing.M) { e = new(Exchange) if err := testexch.Setup(e); err != nil { - log.Fatalf("Poloniex Setup error: %s", err) + log.Fatal(err) } - if apiKey != "" && apiSecret != "" { - e.API.AuthenticatedSupport = true - e.SetCredentials(apiKey, apiSecret, "", "", "", "") + + e.setAPICredential(apiKey, apiSecret) + if err := e.populateTradablePairs(); err != nil { + log.Fatal(err) } log.Printf(sharedtestvalues.LiveTesting, e.Name) e.Websocket.DataHandler = stream.NewRelay(sharedtestvalues.WebsocketRelayBufferCapacity) e.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride() os.Exit(m.Run()) } + +func (e *Exchange) populateTradablePairs() error { + if err := e.UpdateTradablePairs(context.Background()); err != nil { + return err + } + tradablePairs, err := e.GetEnabledPairs(asset.Spot) + if err != nil { + return err + } else if len(tradablePairs) == 0 { + return currency.ErrCurrencyPairsEmpty + } + spotTradablePair, err = e.FormatExchangeCurrency(tradablePairs[0], asset.Spot) + if err != nil { + return err + } + tradablePairs, err = e.GetEnabledPairs(asset.Futures) + if err != nil { + return err + } else if len(tradablePairs) == 0 { + return currency.ErrCurrencyPairsEmpty + } + futuresTradablePair, err = e.FormatExchangeCurrency(tradablePairs[0], asset.Futures) + return err +} diff --git a/exchanges/poloniex/poloniex_mock_test.go b/exchanges/poloniex/poloniex_mock_test.go index e9ce8049890..54b34b0d171 100644 --- a/exchanges/poloniex/poloniex_mock_test.go +++ b/exchanges/poloniex/poloniex_mock_test.go @@ -9,6 +9,8 @@ import ( "os" "testing" + "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange" ) @@ -17,12 +19,36 @@ var mockTests = true func TestMain(m *testing.M) { e = new(Exchange) if err := testexch.Setup(e); err != nil { - log.Fatalf("Poloniex Setup error: %s", err) + log.Fatal(err) } - + e.setAPICredential(apiKey, apiSecret) if err := testexch.MockHTTPInstance(e); err != nil { log.Fatalf("Poloniex MockHTTPInstance error: %s", err) } - + var err error + spotTradablePair, err = e.FormatExchangeCurrency(currency.NewPairWithDelimiter("BTC", "USDT", "_"), asset.Spot) + if err != nil { + log.Fatal(err) + } + futuresTradablePair, err = e.FormatExchangeCurrency(currency.NewPairWithDelimiter("BTC", "USDT_PERP", ""), asset.Futures) + if err != nil { + log.Fatal(err) + } + if err := e.setEnabledPairs(spotTradablePair, futuresTradablePair); err != nil { + log.Fatal(err) + } os.Exit(m.Run()) } + +func (e *Exchange) setEnabledPairs(spotTradablePair, futuresTradablePair currency.Pair) error { + if err := e.CurrencyPairs.StorePairs(asset.Spot, []currency.Pair{spotTradablePair, currency.NewPairWithDelimiter("BTC", "ETH", "_")}, false); err != nil { + return err + } + if err := e.CurrencyPairs.StorePairs(asset.Spot, []currency.Pair{spotTradablePair, currency.NewPairWithDelimiter("BTC", "ETH", "_")}, true); err != nil { + return err + } + if err := e.CurrencyPairs.StorePairs(asset.Futures, []currency.Pair{futuresTradablePair}, false); err != nil { + return err + } + return e.CurrencyPairs.StorePairs(asset.Futures, []currency.Pair{futuresTradablePair}, true) +} diff --git a/exchanges/poloniex/poloniex_test.go b/exchanges/poloniex/poloniex_test.go index 8fdc874d55c..a3baa0c83dc 100644 --- a/exchanges/poloniex/poloniex_test.go +++ b/exchanges/poloniex/poloniex_test.go @@ -1,26 +1,32 @@ package poloniex import ( + "context" "net/http" - "strings" + "sync" "testing" "time" - gws "github.com/gorilla/websocket" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/thrasher-corp/gocryptotrader/common" - "github.com/thrasher-corp/gocryptotrader/core" "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/encoding/json" "github.com/thrasher-corp/gocryptotrader/exchange/accounts" - "github.com/thrasher-corp/gocryptotrader/exchange/websocket" + "github.com/thrasher-corp/gocryptotrader/exchange/order/limits" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate" + "github.com/thrasher-corp/gocryptotrader/exchanges/futures" "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/margin" "github.com/thrasher-corp/gocryptotrader/exchanges/order" + "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" + "github.com/thrasher-corp/gocryptotrader/exchanges/subscription" testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" + "github.com/thrasher-corp/gocryptotrader/types" ) // Please supply your own APIKEYS here for due diligence testing @@ -28,75 +34,21 @@ const ( apiKey = "" apiSecret = "" canManipulateRealOrders = false -) - -var testPair = currency.NewPair(currency.BTC, currency.LTC) - -var e *Exchange - -func TestTimestamp(t *testing.T) { - t.Parallel() - _, err := e.GetTimestamp(t.Context()) - if err != nil { - t.Error(err) - } -} - -func TestGetTicker(t *testing.T) { - t.Parallel() - _, err := e.GetTicker(t.Context()) - if err != nil { - t.Error("Poloniex GetTicker() error", err) - } -} - -func TestGetVolume(t *testing.T) { - t.Parallel() - _, err := e.GetVolume(t.Context()) - if err != nil { - t.Error("Test failed - Poloniex GetVolume() error") - } -} -func TestGetOrderbook(t *testing.T) { - t.Parallel() - _, err := e.GetOrderbook(t.Context(), "BTC_XMR", 50) - if err != nil { - t.Error("Test failed - Poloniex GetOrderbook() error", err) - } -} - -func TestGetTradeHistory(t *testing.T) { - t.Parallel() - _, err := e.GetTradeHistory(t.Context(), "BTC_XMR", 0, 0) - if err != nil { - t.Error("Test failed - Poloniex GetTradeHistory() error", err) - } -} - -func TestGetChartData(t *testing.T) { - t.Parallel() - _, err := e.GetChartData(t.Context(), - "BTC_XMR", - time.Unix(1405699200, 0), time.Unix(1405699400, 0), "300") - if err != nil { - t.Error("Test failed - Poloniex GetChartData() error", err) - } -} + websocketMockTestsSkipped = "skipped websocket test while mock testing is enabled" +) -func TestGetCurrencies(t *testing.T) { - t.Parallel() - _, err := e.GetCurrencies(t.Context()) - if err != nil { - t.Error("Test failed - Poloniex GetCurrencies() error", err) - } -} +var ( + e *Exchange + spotTradablePair, futuresTradablePair currency.Pair +) -func TestGetLoanOrders(t *testing.T) { - t.Parallel() - _, err := e.GetLoanOrders(t.Context(), "BTC") - if err != nil { - t.Error("Test failed - Poloniex GetLoanOrders() error", err) +func (e *Exchange) setAPICredential(apiKey, apiSecret string) { //nolint:unparam // Intentional suppress 'apiKey always receives apiKey ("")' error + if apiKey != "" && apiSecret != "" { + e.API.AuthenticatedSupport = true + e.API.AuthenticatedWebsocketSupport = true + e.SetCredentials(apiKey, apiSecret, "", "", "", "") + e.Websocket.SetCanUseAuthenticatedEndpoints(true) } } @@ -115,24 +67,15 @@ func setFeeBuilder() *exchange.FeeBuilder { func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { t.Parallel() - feeBuilder := setFeeBuilder() - _, err := e.GetFeeByType(t.Context(), feeBuilder) - if err != nil { - t.Fatal(err) - } - if !sharedtestvalues.AreAPICredentialsSet(e) { - if feeBuilder.FeeType != exchange.OfflineTradeFee { - t.Errorf("Expected %v, received %v", - exchange.OfflineTradeFee, - feeBuilder.FeeType) - } + result, err := e.GetFeeByType(t.Context(), feeBuilder) + require.NoError(t, err) + + if !sharedtestvalues.AreAPICredentialsSet(e) || e.SkipAuthCheck { + assert.Equal(t, exchange.OfflineTradeFee, feeBuilder.FeeType) } else { - if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee { - t.Errorf("Expected %v, received %v", - exchange.CryptocurrencyTradeFee, - feeBuilder.FeeType) - } + assert.Equal(t, exchange.CryptocurrencyTradeFee, feeBuilder.FeeType) + assert.NotNil(t, result) } } @@ -142,900 +85,3364 @@ func TestGetFee(t *testing.T) { if sharedtestvalues.AreAPICredentialsSet(e) || mockTests { // CryptocurrencyTradeFee Basic - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } + _, err := e.GetFee(generateContext(t), feeBuilder) + assert.NoError(t, err) // CryptocurrencyTradeFee High quantity feeBuilder = setFeeBuilder() feeBuilder.Amount = 1000 feeBuilder.PurchasePrice = 1000 - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } + _, err = e.GetFee(generateContext(t), feeBuilder) + assert.NoError(t, err) // CryptocurrencyTradeFee Negative purchase price feeBuilder = setFeeBuilder() feeBuilder.PurchasePrice = -1000 - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { + if _, err := e.GetFee(generateContext(t), feeBuilder); err != nil { t.Error(err) } } // CryptocurrencyWithdrawalFee Basic - feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } + result, err := e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) // CryptocurrencyWithdrawalFee Invalid currency feeBuilder = setFeeBuilder() feeBuilder.Pair.Base = currency.NewCode("hello") feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) // CryptocurrencyDepositFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.CryptocurrencyDepositFee - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) // InternationalBankDepositFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.InternationalBankDepositFee - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) // InternationalBankWithdrawalFee Basic feeBuilder = setFeeBuilder() feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee feeBuilder.FiatCurrency = currency.USD - if _, err := e.GetFee(t.Context(), feeBuilder); err != nil { - t.Error(err) - } -} + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) -func TestFormatWithdrawPermissions(t *testing.T) { - t.Parallel() - expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + - " & " + - exchange.NoFiatWithdrawalsText - withdrawPermissions := e.FormatWithdrawPermissions() - if withdrawPermissions != expectedResult { - t.Errorf("Expected: %s, Received: %s", - expectedResult, - withdrawPermissions) - } + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + // CryptocurrencyTradeFee Basic + feeBuilder = setFeeBuilder() + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) + + // CryptocurrencyTradeFee High quantity + feeBuilder = setFeeBuilder() + feeBuilder.Amount = 1000 + feeBuilder.PurchasePrice = 1000 + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) + + // CryptocurrencyTradeFee Negative purchase price + feeBuilder = setFeeBuilder() + feeBuilder.PurchasePrice = -1000 + result, err = e.GetFee(t.Context(), feeBuilder) + require.NoError(t, err) + assert.NotNil(t, result) } func TestGetActiveOrders(t *testing.T) { t.Parallel() - getOrdersRequest := order.MultiOrderRequest{ - Type: order.AnyType, - AssetType: asset.Spot, - Side: order.AnySide, - } + _, err := e.GetActiveOrders(t.Context(), &order.MultiOrderRequest{AssetType: asset.Options, Side: order.AnySide}) + require.ErrorIs(t, err, asset.ErrNotSupported) - _, err := e.GetActiveOrders(t.Context(), &getOrdersRequest) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Error("GetActiveOrders() error", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("Expecting an error when no keys are set") - case mockTests && err != nil: - t.Error("Mock GetActiveOrders() err", err) + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetActiveOrders(generateContext(t), &order.MultiOrderRequest{ + AssetType: asset.Spot, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetActiveOrders(generateContext(t), &order.MultiOrderRequest{ + AssetType: asset.Futures, + Side: order.Buy, + }) + assert.NoError(t, err) + assert.NotNil(t, result) } func TestGetOrderHistory(t *testing.T) { t.Parallel() - getOrdersRequest := order.MultiOrderRequest{ - Type: order.AnyType, + _, err := e.GetOrderHistory(t.Context(), &order.MultiOrderRequest{ + Type: order.Liquidation, AssetType: asset.Spot, - Side: order.AnySide, - } + Side: order.Buy, + }) + require.ErrorIs(t, err, order.ErrUnsupportedOrderType) - _, err := e.GetOrderHistory(t.Context(), &getOrdersRequest) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Errorf("Could not get order history: %s", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && err == nil && !mockTests: - t.Error("Expecting an error when no keys are set") - case mockTests && err != nil: - t.Errorf("Could not mock get order history: %s", err) + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetOrderHistory(generateContext(t), &order.MultiOrderRequest{ + Type: order.Limit, + AssetType: asset.Spot, + Side: order.Buy, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetOrderHistory(generateContext(t), &order.MultiOrderRequest{ + Type: order.StopLimit, + AssetType: asset.Spot, + Side: order.Sell, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetOrderHistory(generateContext(t), &order.MultiOrderRequest{ + Type: order.Limit, + AssetType: asset.Futures, + Side: order.Buy, + }) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetOrderStatus(t *testing.T) { +func TestSubmitOrder(t *testing.T) { t.Parallel() + _, err := e.SubmitOrder(t.Context(), nil) + require.ErrorIs(t, err, order.ErrSubmissionIsNil) + + _, err = e.SubmitOrder(t.Context(), &order.Submit{}) + require.ErrorIs(t, err, common.ErrExchangeNameNotSet) + + arg := &order.Submit{Exchange: e.Name} + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrPairIsEmpty) + + arg.Pair = spotTradablePair + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrAssetNotSet) + + arg.AssetType = asset.Spot + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.Side = order.Bid + arg.Type = order.Type(65537) + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrTypeIsInvalid) + + arg.Type = order.Limit + arg.TimeInForce = order.GoodTillCancel + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrAmountIsInvalid) + + arg.Amount = 1 + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrPriceMustBeSetIfLimitOrder) + + arg = &order.Submit{Exchange: e.Name, AssetType: asset.Options, Side: order.Long, Type: order.Market, Amount: 1, TimeInForce: order.GoodTillCrossing, Pair: futuresTradablePair} + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, asset.ErrNotSupported) + + // unit tests specific to spot + arg.AssetType = asset.Spot + arg.Type = order.Liquidation + arg.Pair = spotTradablePair + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrUnsupportedOrderType) + + // spot smart orders validation + arg.Type = order.TrailingStopLimit + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.Side = order.Sell + arg.Amount = 0 + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrAmountIsInvalid) + + // Futures place order + arg = &order.Submit{Exchange: e.Name, AssetType: asset.Futures, Type: order.Market, Amount: 1, TimeInForce: order.GoodTillCrossing, Pair: futuresTradablePair, MarginType: margin.Isolated} + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.Side = order.Sell + arg.Type = order.TrailingStopLimit + _, err = e.SubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrUnsupportedOrderType) - tests := []struct { - name string - mock bool - orderID string - errExpected bool - errMsgExpected string - }{ - { - name: "correct order ID", - mock: true, - orderID: "96238912841", - errExpected: false, - errMsgExpected: "", - }, - { - name: "wrong order ID", - mock: true, - orderID: "96238912842", - errExpected: true, - errMsgExpected: "Order not found", - }, - } + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Buy, + Type: order.Market, + Price: 10, + QuoteAmount: 10000000, + AssetType: asset.Spot, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Buy, + Type: order.StopLimit, + TriggerPrice: 11, + Price: 10, + Amount: 10000000, + ClientID: "hi", + AssetType: asset.Spot, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Buy, + Type: order.TrailingStop, + TrackingMode: order.Percentage, + TrackingValue: 5, + TriggerPrice: 11, + Price: 10, + Amount: 10000000, + ClientOrderID: "999999910", + AssetType: asset.Spot, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Buy, + Type: order.TrailingStopLimit, + TrackingMode: order.Percentage, + TrackingValue: 5, + LimitTrackingMode: order.Percentage, + LimitTrackingValue: 1, + TriggerPrice: 11, + Price: 10, + Amount: 10000000, + ClientOrderID: "999999910", + AssetType: asset.Spot, + StopDirection: order.StopUp, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Buy, + Type: order.Market, + TriggerPrice: 11, + Price: 10, + Amount: 10000000, + ClientID: "hi", + AssetType: asset.Futures, + }) + require.NoError(t, err) + assert.NotNil(t, result) - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if tt.mock != mockTests { - t.Skip("mock mismatch, skipping") - } + result, err = e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: futuresTradablePair, + Side: order.Sell, + Type: order.Market, + Price: 10, + Amount: 10000000, + AssetType: asset.Futures, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.SubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: futuresTradablePair, + Side: order.Buy, + MarginType: margin.Multi, + Type: order.Limit, + Price: 10, + Amount: 10000000, + AssetType: asset.Futures, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} - _, err := e.GetAuthenticatedOrderStatus(t.Context(), - tt.orderID) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Errorf("Could not get order status: %s", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && err == nil && !mockTests: - t.Error("Expecting an error when no keys are set") - case mockTests && err != nil: - if !tt.errExpected { - t.Errorf("Could not mock get order status: %s", err.Error()) - } else if !(strings.Contains(err.Error(), tt.errMsgExpected)) { - t.Errorf("Could not mock get order status: %s", err.Error()) - } - case mockTests: - if tt.errExpected { - t.Errorf("Mock get order status expect an error %q, get no error", tt.errMsgExpected) - } - } - }) +func TestWebsocketSubmitOrder(t *testing.T) { + t.Parallel() + + _, err := e.WebsocketSubmitOrder(t.Context(), nil) + require.ErrorIs(t, err, order.ErrSubmissionIsNil) + + _, err = e.WebsocketSubmitOrder(t.Context(), &order.Submit{}) + require.ErrorIs(t, err, common.ErrExchangeNameNotSet) + + arg := &order.Submit{Exchange: e.Name} + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrPairIsEmpty) + + arg.Pair = spotTradablePair + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrAssetNotSet) + + arg.AssetType = asset.Spot + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.Side = order.Sell + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrTypeIsInvalid) + + arg.Type = order.TrailingStop + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrAmountIsInvalid) + + arg.Amount = 1 + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrUnsupportedOrderType) + + arg.Type = order.Limit + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrPriceMustBeSetIfLimitOrder) + + arg.AssetType = asset.Futures + arg.Price = 10 + _, err = e.WebsocketSubmitOrder(t.Context(), arg) + require.ErrorIs(t, err, asset.ErrNotSupported) + + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") + + if mockTests { + t.Skip(websocketMockTestsSkipped) } + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") + + testexch.SetupWs(t, e) + result, err := e.WebsocketSubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Buy, + Type: order.Market, + Price: 10, + QuoteAmount: 1000000, + AssetType: asset.Spot, + }) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.WebsocketSubmitOrder(generateContext(t), &order.Submit{ + Exchange: e.Name, + Pair: spotTradablePair, + Side: order.Sell, + Type: order.Limit, + TriggerPrice: 11, + Price: 10, + Amount: 1, + ClientID: "hi", + AssetType: asset.Spot, + }) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetOrderTrades(t *testing.T) { +func TestWebsocketCancelOrder(t *testing.T) { t.Parallel() + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") - tests := []struct { - name string - mock bool - orderID string - errExpected bool - errMsgExpected string - }{ - { - name: "correct order ID", - mock: true, - orderID: "96238912841", - errExpected: false, - errMsgExpected: "", - }, - { - name: "wrong order ID", - mock: true, - orderID: "96238912842", - errExpected: true, - errMsgExpected: "Order not found", - }, + err := e.WebsocketCancelOrder(t.Context(), &order.Cancel{}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if mockTests { + t.Skip(websocketMockTestsSkipped) } + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if tt.mock != mockTests { - t.Skip("mock mismatch, skipping") - } + testexch.SetupWs(t, e) + err = e.WebsocketCancelOrder(t.Context(), &order.Cancel{OrderID: "2312", ClientOrderID: "23123121231"}) + assert.NoError(t, err) +} - _, err := e.GetAuthenticatedOrderTrades(t.Context(), tt.orderID) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Errorf("Could not get order trades: %s", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && err == nil && !mockTests: - t.Error("Expecting an error when no keys are set") - case mockTests && err != nil: - assert.ErrorContains(t, err, tt.errMsgExpected) - } - }) +func TestCancelExchangeOrder(t *testing.T) { + t.Parallel() + arg := &order.Cancel{ + AccountID: "1", } -} + err := e.CancelOrder(t.Context(), nil) + assert.ErrorIs(t, err, order.ErrCancelOrderIsNil) -// Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them -// ---------------------------------------------------------------------------------------------------------------------------- + err = e.CancelOrder(t.Context(), arg) + assert.ErrorIs(t, err, order.ErrOrderIDNotSet) + + arg.OrderID = "123" + err = e.CancelOrder(t.Context(), arg) + assert.ErrorIs(t, err, asset.ErrNotSupported) -func TestSubmitOrder(t *testing.T) { - t.Parallel() if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + arg.AssetType = asset.Spot + err = e.CancelOrder(generateContext(t), arg) + assert.NoError(t, err) - orderSubmission := &order.Submit{ - Exchange: e.Name, - Pair: currency.Pair{ - Delimiter: currency.UnderscoreDelimiter, - Base: currency.BTC, - Quote: currency.LTC, - }, - Side: order.Buy, - Type: order.Market, - Price: 10, - Amount: 10000000, - ClientID: "hi", - AssetType: asset.Spot, - } + arg.Type = order.StopLimit + err = e.CancelOrder(generateContext(t), arg) + assert.NoError(t, err) - response, err := e.SubmitOrder(t.Context(), orderSubmission) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && (err != nil || response.Status != order.Filled): - t.Errorf("Order failed to be placed: %v", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("Expecting an error when no keys are set") - case mockTests && err != nil: - t.Error("Mock SubmitOrder() err", err) - } + err = e.CancelOrder(generateContext(t), &order.Cancel{ + OrderID: "1", + AssetType: asset.Futures, + }) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + err = e.CancelOrder(generateContext(t), &order.Cancel{ + OrderID: "1", + AssetType: asset.Futures, + Pair: futuresTradablePair, + }) + assert.NoError(t, err) } -func TestCancelExchangeOrder(t *testing.T) { +func TestCancelAllOrders(t *testing.T) { t.Parallel() + _, err := e.CancelAllOrders(t.Context(), nil) + require.ErrorIs(t, err, common.ErrNilPointer) + + _, err = e.CancelAllOrders(t.Context(), &order.Cancel{AssetType: asset.Options}) + require.ErrorIs(t, err, asset.ErrNotSupported) + if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + testexch.SetupWs(t, e) } - orderCancellation := &order.Cancel{ + arg := &order.Cancel{ OrderID: "1", AccountID: "1", - Pair: currency.NewPair(currency.LTC, currency.BTC), + Pair: spotTradablePair, AssetType: asset.Spot, } + arg.Type = order.Stop + result, err := e.CancelAllOrders(generateContext(t), arg) + require.NoError(t, err) + assert.NotNil(t, result) + + arg.Type = order.Limit + result, err = e.CancelAllOrders(generateContext(t), arg) + require.NoError(t, err) + assert.NotNil(t, result) + + arg.AssetType = asset.Futures + arg.Pair = futuresTradablePair + result, err = e.CancelAllOrders(generateContext(t), arg) + require.NoError(t, err) + assert.NotNil(t, result) + + arg.Type = order.StopLimit + result, err = e.CancelAllOrders(generateContext(t), arg) + assert.NoError(t, err) + assert.NotNil(t, result) +} - err := e.CancelOrder(t.Context(), orderCancellation) - switch { - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("Expecting an error when no keys are set") - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Errorf("Could not cancel orders: %v", err) - case mockTests && err != nil: - t.Error("Mock CancelExchangeOrder() err", err) +func TestModifyOrder(t *testing.T) { + t.Parallel() + arg := &order.Modify{ + OrderID: "1337", + Price: 1337, } + _, err := e.ModifyOrder(t.Context(), arg) + assert.ErrorIs(t, err, order.ErrPairIsEmpty) + + arg.Pair = spotTradablePair + _, err = e.ModifyOrder(t.Context(), arg) + assert.ErrorIs(t, err, order.ErrAssetNotSet) + + arg.AssetType = asset.Futures + _, err = e.ModifyOrder(t.Context(), arg) + assert.ErrorIs(t, err, asset.ErrNotSupported) + + arg.AssetType = asset.Spot + _, err = e.ModifyOrder(t.Context(), arg) + assert.ErrorIs(t, err, order.ErrUnsupportedOrderType) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + // TimeInForce is defined in the type declaration, and its value conversion + // and validation occur during input payload marshalling. For authenticated + // endpoints, this happens after the credentials check. + arg.Type = order.Limit + arg.TimeInForce = order.GoodTillTime + _, err = e.ModifyOrder(t.Context(), arg) + assert.ErrorIs(t, err, order.ErrInvalidTimeInForce) + + arg.TimeInForce = order.GoodTillCancel + result, err := e.ModifyOrder(t.Context(), arg) + require.NoError(t, err) + assert.NotNil(t, result) + + arg.Type = order.StopLimit + result, err = e.ModifyOrder(t.Context(), arg) + assert.NoError(t, err) + assert.NotNil(t, result) + + arg.TimeInForce = order.GoodTillTime + arg.Type = order.StopLimit + _, err = e.ModifyOrder(t.Context(), arg) + assert.ErrorIs(t, err, order.ErrInvalidTimeInForce) } -func TestCancelAllExchangeOrders(t *testing.T) { +func TestWithdraw(t *testing.T) { t.Parallel() + _, err := e.WithdrawCryptocurrencyFunds(t.Context(), nil) + require.ErrorIs(t, err, withdraw.ErrRequestCannotBeNil) + + _, err = e.WithdrawCryptocurrencyFunds(t.Context(), &withdraw.Request{}) + require.ErrorIs(t, err, common.ErrExchangeNameNotSet) + + _, err = e.WithdrawCryptocurrencyFunds(t.Context(), &withdraw.Request{ + Exchange: e.Name, + }) + require.ErrorContains(t, err, withdraw.ErrStrAmountMustBeGreaterThanZero) + + _, err = e.WithdrawCryptocurrencyFunds(t.Context(), &withdraw.Request{ + Exchange: e.Name, + Amount: 1, + }) + require.ErrorContains(t, err, withdraw.ErrStrNoCurrencySet) + + _, err = e.WithdrawCryptocurrencyFunds(t.Context(), &withdraw.Request{ + Exchange: e.Name, + Amount: 1, + Type: withdraw.Crypto, + Currency: currency.USD, + }) + require.ErrorContains(t, err, withdraw.ErrStrCurrencyNotCrypto) + if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + result, err := e.WithdrawCryptocurrencyFunds(t.Context(), &withdraw.Request{ + Exchange: e.Name, + Crypto: withdraw.CryptoRequest{ + Address: "bc1qk0jareu4jytc0cfrhr5wgshsq8", + Chain: "ETH", + }, + Amount: 0.0000001, + Currency: currency.BTC, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} - currencyPair := currency.NewPair(currency.LTC, currency.BTC) - orderCancellation := &order.Cancel{ - OrderID: "1", - AccountID: "1", - Pair: currencyPair, - AssetType: asset.Spot, +func TestUpdateAccountBalances(t *testing.T) { + t.Parallel() + _, err := e.UpdateAccountBalances(t.Context(), asset.Options) + require.ErrorIs(t, err, asset.ErrNotSupported) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.UpdateAccountBalances(generateContext(t), asset.Spot) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.UpdateAccountBalances(generateContext(t), asset.Futures) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestWithdrawFiat(t *testing.T) { + t.Parallel() + var withdrawFiatRequest withdraw.Request + _, err := e.WithdrawFiatFunds(t.Context(), &withdrawFiatRequest) + require.ErrorIs(t, err, common.ErrFunctionNotSupported) +} + +func TestWithdrawInternationalBank(t *testing.T) { + t.Parallel() + _, err := e.WithdrawFiatFundsToInternationalBank(t.Context(), &withdraw.Request{}) + require.ErrorIs(t, err, common.ErrFunctionNotSupported) +} - resp, err := e.CancelAllOrders(t.Context(), orderCancellation) - switch { - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("Expecting an error when no keys are set") - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Errorf("Could not cancel orders: %v", err) - case mockTests && err != nil: - t.Error("Mock CancelAllExchangeOrders() err", err) +func TestGetHistoricCandles(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1744183959258), time.UnixMilli(1744191159258) + if !mockTests { + startTime, endTime = time.Now().Add(-time.Hour*2), time.Now() } - if len(resp.Status) > 0 { - t.Errorf("%v orders failed to cancel", len(resp.Status)) + result, err := e.GetHistoricCandles(t.Context(), spotTradablePair, asset.Spot, kline.FiveMin, startTime.UTC(), endTime.UTC()) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetHistoricCandles(t.Context(), futuresTradablePair, asset.Futures, kline.FiveMin, startTime.UTC(), endTime.UTC()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetHistoricCandlesExtended(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1744103854944), time.UnixMilli(1744190254944) + if !mockTests { + startTime, endTime = time.Now().Add(-time.Hour*24), time.Now() + } + result, err := e.GetHistoricCandlesExtended(t.Context(), spotTradablePair, asset.Spot, kline.OneHour, startTime, endTime) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetHistoricCandlesExtended(t.Context(), futuresTradablePair, asset.Futures, kline.FiveMin, startTime, endTime) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetRecentTrades(t *testing.T) { + t.Parallel() + _, err := e.GetRecentTrades(t.Context(), currency.EMPTYPAIR, asset.Spot) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.GetRecentTrades(t.Context(), spotTradablePair, asset.Spot) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetRecentTrades(t.Context(), futuresTradablePair, asset.Futures) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetHistoricTrades(t *testing.T) { + t.Parallel() + _, err := e.GetHistoricTrades(t.Context(), + spotTradablePair, asset.Spot, time.Time{}, time.Time{}) + require.ErrorIs(t, err, common.ErrFunctionNotSupported) +} + +func TestUpdateTickers(t *testing.T) { + t.Parallel() + err := e.UpdateTickers(t.Context(), asset.Options) + assert.ErrorIs(t, err, asset.ErrNotSupported) + + err = e.UpdateTickers(t.Context(), asset.Spot) + assert.NoError(t, err) + + err = e.UpdateTickers(t.Context(), asset.Futures) + assert.NoError(t, err) +} + +func TestUpdateTicker(t *testing.T) { + t.Parallel() + _, err := e.UpdateTicker(t.Context(), spotTradablePair, asset.Options) + require.ErrorIs(t, err, asset.ErrNotSupported) + + _, err = e.UpdateTicker(t.Context(), currency.EMPTYPAIR, asset.Spot) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.UpdateTicker(t.Context(), spotTradablePair, asset.Spot) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.UpdateTicker(t.Context(), futuresTradablePair, asset.Futures) + require.NoError(t, err) + assert.NotNil(t, result) + + if !mockTests { + t.Skip("skipped: downstream test data is intentionally malformed and only valid for mock tests") + } + _, err = e.UpdateTicker(t.Context(), currency.NewPairWithDelimiter("ABC", "DEF", currency.DashDelimiter), asset.Futures) + assert.ErrorIs(t, err, common.ErrInvalidResponse) +} + +func TestGetAvailableTransferChains(t *testing.T) { + t.Parallel() + _, err := e.GetAvailableTransferChains(t.Context(), currency.EMPTYCODE) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + + result, err := e.GetAvailableTransferChains(t.Context(), currency.BTC) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetAccountFundingHistory(t *testing.T) { + t.Parallel() + if mockTests { + t.Skip("skipped mock test because GetAccountFundingHistory uses dynamic timestamp data") + } + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + result, err := e.GetAccountFundingHistory(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetWithdrawalsHistory(t *testing.T) { + t.Parallel() + if mockTests { + t.Skip("skipped mock test because GetWithdrawalsHistory uses dynamic timestamp data") + } + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + result, err := e.GetWithdrawalsHistory(t.Context(), currency.BTC, asset.Spot) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelBatchOrders(t *testing.T) { + t.Parallel() + _, err := e.CancelBatchOrders(t.Context(), []order.Cancel{}) + require.ErrorIs(t, err, common.ErrEmptyParams) + + _, err = e.CancelBatchOrders(t.Context(), []order.Cancel{{AssetType: asset.Options}}) + require.ErrorIs(t, err, asset.ErrNotSupported) + + _, err = e.CancelBatchOrders(t.Context(), []order.Cancel{{AssetType: asset.Futures, OrderID: "1234"}}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + _, err = e.CancelBatchOrders(t.Context(), []order.Cancel{{AssetType: asset.Futures, Pair: futuresTradablePair}}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + _, err = e.CancelBatchOrders(t.Context(), []order.Cancel{{AssetType: asset.Futures, OrderID: "1233"}, {AssetType: asset.Futures}}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + _, err = e.CancelBatchOrders(generateContext(t), []order.Cancel{ + { + Pair: futuresTradablePair, + AssetType: asset.Futures, + OrderID: "1233", + }, + { + Pair: futuresTradablePair, + AssetType: asset.Spot, + OrderID: "123444", + }, + }) + require.ErrorIs(t, err, errAllMustBeEqual) + + _, err = e.CancelBatchOrders(generateContext(t), []order.Cancel{ + { + Pair: futuresTradablePair, + AssetType: asset.Futures, + OrderID: "1233", + }, + { + Pair: spotTradablePair, + AssetType: asset.Futures, + OrderID: "123444", + }, + }) + require.ErrorIs(t, err, errAllMustBeEqual) + + _, err = e.CancelBatchOrders(generateContext(t), []order.Cancel{ + { + Pair: spotTradablePair, + AssetType: asset.Spot, + OrderID: "1233", + Type: order.StopLimit, + }, + { + Pair: spotTradablePair, + AssetType: asset.Spot, + OrderID: "123444", + Type: order.Limit, + }, + }) + require.ErrorIs(t, err, errAllMustBeEqual) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + + resp, err := e.CancelBatchOrders(generateContext(t), []order.Cancel{ + { + Pair: futuresTradablePair, + AssetType: asset.Futures, + OrderID: "1233", + }, + { + Pair: futuresTradablePair, + AssetType: asset.Futures, + OrderID: "123444", + }, + }) + assert.NoError(t, err) + assert.NotNil(t, resp) + resp, err = e.CancelBatchOrders(generateContext(t), []order.Cancel{ + { + OrderID: "1234", + AssetType: asset.Spot, + Pair: spotTradablePair, + }, + { + OrderID: "134", + AssetType: asset.Spot, + Pair: currency.NewBTCUSD(), + }, + { + ClientOrderID: "234", + AssetType: asset.Spot, + }, + }) + assert.NoError(t, err) + assert.NotNil(t, resp) + resp, err = e.CancelBatchOrders(generateContext(t), []order.Cancel{ + { + OrderID: "134", + AssetType: asset.Spot, + Type: order.StopLimit, + }, + { + OrderID: "234", + AssetType: asset.Spot, + Type: order.TrailingStop, + }, + }) + assert.NoError(t, err) + assert.NotNil(t, resp) +} + +func TestGetServerTime(t *testing.T) { + t.Parallel() + st, err := e.GetServerTime(t.Context(), asset.Spot) + assert.NoError(t, err) + assert.NotZero(t, st) + + st, err = e.GetServerTime(t.Context(), asset.Futures) + assert.NoError(t, err) + assert.NotZero(t, st) +} + +func TestGetFuturesContractDetails(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesContractDetails(t.Context(), asset.Spot) + require.ErrorIs(t, err, futures.ErrNotFuturesAsset) + + _, err = e.GetFuturesContractDetails(t.Context(), asset.FutureCombo) + require.ErrorIs(t, err, asset.ErrNotSupported) + + result, err := e.GetFuturesContractDetails(t.Context(), asset.Futures) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetLatestFundingRates(t *testing.T) { + t.Parallel() + _, err := e.GetLatestFundingRates(t.Context(), &fundingrate.LatestRateRequest{}) + require.ErrorIs(t, err, common.ErrEmptyParams) + + _, err = e.GetLatestFundingRates(t.Context(), &fundingrate.LatestRateRequest{Pair: currency.NewPair(currency.BTC, currency.LTC)}) + require.ErrorIs(t, err, futures.ErrNotPerpetualFuture) + + _, err = e.GetLatestFundingRates(t.Context(), &fundingrate.LatestRateRequest{ + Asset: asset.Spot, + Pair: spotTradablePair, + IncludePredictedRate: false, + }) + require.ErrorIs(t, err, futures.ErrNotPerpetualFuture) + + result, err := e.GetLatestFundingRates(t.Context(), &fundingrate.LatestRateRequest{ + Asset: asset.Futures, + Pair: futuresTradablePair, + IncludePredictedRate: false, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestIsPerpetualFutureCurrency(t *testing.T) { + t.Parallel() + is, err := e.IsPerpetualFutureCurrency(asset.Spot, spotTradablePair) + assert.NoError(t, err) + require.False(t, is) + + is, err = e.IsPerpetualFutureCurrency(asset.Futures, futuresTradablePair) + assert.NoError(t, err) + assert.True(t, is) +} + +func TestFetchTradablePairs(t *testing.T) { + t.Parallel() + _, err := e.FetchTradablePairs(t.Context(), asset.Options) + require.ErrorIs(t, err, asset.ErrNotSupported) + + result, err := e.FetchTradablePairs(t.Context(), asset.Spot) + assert.NoError(t, err) + require.NotNil(t, result) + + result, err = e.FetchTradablePairs(t.Context(), asset.Futures) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetSymbol(t *testing.T) { + t.Parallel() + _, err := e.GetSymbol(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + result, err := e.GetSymbol(t.Context(), spotTradablePair) + require.NoError(t, err) + require.NotNil(t, result) + assert.Len(t, result, 1) +} + +func TestGetSymbols(t *testing.T) { + t.Parallel() + result, err := e.GetSymbols(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetCurrencies(t *testing.T) { + t.Parallel() + result, err := e.GetCurrencies(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetCurrency(t *testing.T) { + t.Parallel() + _, err := e.GetCurrency(t.Context(), currency.EMPTYCODE) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + + result, err := e.GetCurrency(t.Context(), currency.BTC) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetSystemTimestamp(t *testing.T) { + t.Parallel() + result, err := e.GetSystemTimestamp(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetMarketPrices(t *testing.T) { + t.Parallel() + result, err := e.GetMarketPrices(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetMarketPrice(t *testing.T) { + t.Parallel() + _, err := e.GetMarketPrice(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.GetMarketPrice(t.Context(), spotTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetMarkPrices(t *testing.T) { + t.Parallel() + result, err := e.GetMarkPrices(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetMarkPrice(t *testing.T) { + t.Parallel() + _, err := e.GetMarkPrice(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.GetMarkPrice(t.Context(), spotTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestMarkPriceComponents(t *testing.T) { + t.Parallel() + _, err := e.GetMarkPriceComponents(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.GetMarkPriceComponents(t.Context(), spotTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetOrderbook(t *testing.T) { + t.Parallel() + _, err := e.GetOrderbook(t.Context(), currency.EMPTYPAIR, 0, 0) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + spotPair, err := e.FormatExchangeCurrency(currency.NewPairWithDelimiter("BTC", "USDT", "_"), asset.Spot) + require.NoError(t, err) + + result, err := e.GetOrderbook(t.Context(), spotPair, 0, 0) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetOrderbook(t.Context(), spotPair, .01, 100) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestUpdateOrderbook(t *testing.T) { + t.Parallel() + _, err := e.UpdateOrderbook(t.Context(), currency.EMPTYPAIR, asset.Spot) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + _, err = e.UpdateOrderbook(t.Context(), spotTradablePair, asset.Options) + require.ErrorIs(t, err, asset.ErrNotSupported) + + result, err := e.UpdateOrderbook(t.Context(), spotTradablePair, asset.Spot) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.UpdateOrderbook(t.Context(), futuresTradablePair, asset.Futures) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetCandlesticks(t *testing.T) { + t.Parallel() + _, err := e.GetCandlesticks(t.Context(), currency.EMPTYPAIR, kline.FiveMin, time.Time{}, time.Time{}, 0) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + startTime, endTime := time.UnixMilli(1743615790295), time.UnixMilli(1743702190295) + _, err = e.GetCandlesticks(t.Context(), spotTradablePair, kline.HundredMilliseconds, startTime, time.Time{}, 0) + require.ErrorIs(t, err, kline.ErrUnsupportedInterval) + + _, err = e.GetCandlesticks(t.Context(), spotTradablePair, kline.FiveMin, endTime, startTime, 0) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() + } + result, err := e.GetCandlesticks(t.Context(), spotTradablePair, kline.FiveMin, startTime, endTime, 0) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetTrades(t *testing.T) { + t.Parallel() + _, err := e.GetTrades(t.Context(), currency.EMPTYPAIR, 10) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.GetTrades(t.Context(), spotTradablePair, 10) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetTickers(t *testing.T) { + t.Parallel() + result, err := e.GetTickers(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetTicker(t *testing.T) { + t.Parallel() + _, err := e.GetTicker(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + result, err := e.GetTicker(t.Context(), spotTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetCollateral(t *testing.T) { + t.Parallel() + _, err := e.GetCollateral(t.Context(), currency.EMPTYCODE) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + + result, err := e.GetCollateral(t.Context(), currency.BTC) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetCollaterals(t *testing.T) { + t.Parallel() + result, err := e.GetCollaterals(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetBorrowRate(t *testing.T) { + t.Parallel() + result, err := e.GetBorrowRate(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetAccount(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetAccount(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetBalances(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetBalances(generateContext(t), "") + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetBalances(generateContext(t), "SPOT") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetBalancesByID(t *testing.T) { + t.Parallel() + _, err := e.GetAccountBalances(t.Context(), "", "") + require.ErrorIs(t, err, errAccountIDRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetAccountBalances(generateContext(t), "329455537441832960", "") + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetAccountBalances(generateContext(t), "329455537441832960", "SPOT") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetAccountActivities(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764664401864), time.UnixMilli(1764668001864) + _, err := e.GetAccountActivities(generateContext(t), endTime, startTime, 0, 0, 0, "", currency.EMPTYCODE) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour), time.Now() + } + _, err = e.GetAccountActivities(generateContext(t), startTime, endTime, 0, 0, 0, "", currency.EMPTYCODE) + require.NoError(t, err) + + _, err = e.GetAccountActivities(generateContext(t), time.Time{}, time.Time{}, 200, 0, 0, "", currency.EMPTYCODE) + require.NoError(t, err) + + _, err = e.GetAccountActivities(generateContext(t), time.Time{}, time.Time{}, 0, 10, 100, "PRE", currency.EMPTYCODE) + require.NoError(t, err) + + _, err = e.GetAccountActivities(generateContext(t), time.Time{}, time.Time{}, 0, 0, 0, "NEXT", currency.BTC) + require.NoError(t, err) +} + +func TestAccountsTransfer(t *testing.T) { + t.Parallel() + _, err := e.AccountsTransfer(t.Context(), &AccountTransferRequest{Amount: 1232.221}) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + _, err = e.AccountsTransfer(t.Context(), &AccountTransferRequest{ + Currency: currency.BTC, + }) + require.ErrorIs(t, err, order.ErrAmountIsInvalid) + _, err = e.AccountsTransfer(t.Context(), &AccountTransferRequest{ + Amount: 1, + Currency: currency.BTC, + FromAccount: "219961623421431808", + }) + require.ErrorIs(t, err, errAddressRequired) + + _, err = e.AccountsTransfer(t.Context(), &AccountTransferRequest{ + Amount: 1, + Currency: currency.BTC, + ToAccount: "219961623421431808", + }) + require.ErrorIs(t, err, errAddressRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.AccountsTransfer(generateContext(t), &AccountTransferRequest{ + Amount: 1, + Currency: currency.BTC, + FromAccount: "329455537441832960", + ToAccount: "329455537441832960", + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetAccountsTransferRecords(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764664401864), time.UnixMilli(1764668001864) + _, err := e.GetAccountsTransferRecords(generateContext(t), endTime, startTime, "", currency.BTC, 0, 0) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour), time.Now() + } + _, err = e.GetAccountsTransferRecords(generateContext(t), startTime, endTime, "", currency.BTC, 0, 0) + require.NoError(t, err) + + _, err = e.GetAccountsTransferRecords(generateContext(t), time.Time{}, time.Time{}, "NEXT", currency.BTC, 1, 100) + require.NoError(t, err) + + _, err = e.GetAccountsTransferRecords(generateContext(t), startTime, endTime, "", currency.EMPTYCODE, 0, 0) + require.NoError(t, err) +} + +func TestGetAccountTransferRecord(t *testing.T) { + t.Parallel() + _, err := e.GetAccountsTransferRecordByTransferID(generateContext(t), "") + require.ErrorIs(t, err, errAccountIDRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err = e.GetAccountsTransferRecordByTransferID(generateContext(t), "329455537441832960") + require.NoError(t, err) +} + +func TestGetFeeInfo(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetFeeInfo(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetInterestHistory(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764664401864), time.UnixMilli(1764668001864) + _, err := e.GetInterestHistory(generateContext(t), endTime, startTime, "", 0, 0) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour), time.Now() + } + _, err = e.GetInterestHistory(generateContext(t), startTime, endTime, "", 0, 0) + require.NoError(t, err) + + _, err = e.GetInterestHistory(generateContext(t), time.Time{}, time.Time{}, "NEXT", 0, 0) + require.NoError(t, err) + + _, err = e.GetInterestHistory(generateContext(t), time.Time{}, time.Time{}, "NEXT", 1, 100) + require.NoError(t, err) + + _, err = e.GetInterestHistory(generateContext(t), time.Time{}, time.Time{}, "", 0, 0) + require.NoError(t, err) +} + +func TestGetSubAccount(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetSubAccount(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetSubAccountBalances(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetSubAccountBalances(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetSubAccountBalance(t *testing.T) { + t.Parallel() + _, err := e.GetSubAccountBalance(t.Context(), "") + require.ErrorIs(t, err, errAccountIDRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err = e.GetSubAccountBalance(generateContext(t), "2d45301d-5f08-4a2b-a763-f9199778d854") + require.NoError(t, err) +} + +func TestSubAccountTransfer(t *testing.T) { + t.Parallel() + _, err := e.SubAccountTransfer(t.Context(), &SubAccountTransferRequest{Amount: 12.34}) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + _, err = e.SubAccountTransfer(t.Context(), &SubAccountTransferRequest{ + Currency: currency.BTC, + }) + require.ErrorIs(t, err, order.ErrAmountIsInvalid) + _, err = e.SubAccountTransfer(t.Context(), &SubAccountTransferRequest{ + Currency: currency.BTC, + Amount: 1, + }) + require.ErrorIs(t, err, errAccountIDRequired) + + _, err = e.SubAccountTransfer(t.Context(), &SubAccountTransferRequest{ + Currency: currency.BTC, + Amount: 1, + FromAccountID: "1234568", + }) + require.ErrorIs(t, err, errAccountIDRequired) + _, err = e.SubAccountTransfer(t.Context(), &SubAccountTransferRequest{ + Currency: currency.BTC, + Amount: 1, + FromAccountID: "1234568", + ToAccountID: "1234567", + }) + require.ErrorIs(t, err, errAccountTypeRequired) + + _, err = e.SubAccountTransfer(t.Context(), &SubAccountTransferRequest{ + Currency: currency.BTC, + Amount: 1, + FromAccountID: "1234568", + ToAccountID: "1234567", + FromAccountType: "SPOT", + }) + require.ErrorIs(t, err, errAccountTypeRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.SubAccountTransfer(generateContext(t), &SubAccountTransferRequest{ + Currency: currency.BTC, + Amount: 1, + FromAccountID: "329455537441832960", + ToAccountID: "329455537441832961", + FromAccountType: "SPOT", + ToAccountType: "SPOT", + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetSubAccountTransferRecords(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764664401864), time.UnixMilli(1764668001864) + _, err := e.GetSubAccountTransferRecords(generateContext(t), &SubAccountTransferRecordRequest{Currency: currency.BTC, StartTime: endTime, EndTime: startTime}) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour), time.Now() + } + _, err = e.GetSubAccountTransferRecords(generateContext(t), &SubAccountTransferRecordRequest{ + Currency: currency.BTC, + FromAccountType: "SPOT", + ToAccountType: "FUTURES", + ToAccountID: "32b323201-e832-2270-78t4-e25ak408946", + FromAccountID: "32b323201-e832-2270-78t4-e25ak408941", + }) + require.NoError(t, err) + + _, err = e.GetSubAccountTransferRecords(generateContext(t), &SubAccountTransferRecordRequest{Currency: currency.BTC, StartTime: startTime, EndTime: endTime}) + require.NoError(t, err) + + _, err = e.GetSubAccountTransferRecords(generateContext(t), &SubAccountTransferRecordRequest{Currency: currency.BTC, StartTime: startTime, From: 1, Limit: 100}) + require.NoError(t, err) + + _, err = e.GetSubAccountTransferRecords(generateContext(t), &SubAccountTransferRecordRequest{Currency: currency.BTC, Direction: "NEXT"}) + require.NoError(t, err) +} + +func TestGetSubAccountTransferRecord(t *testing.T) { + t.Parallel() + _, err := e.GetSubAccountTransferRecord(t.Context(), "") + require.ErrorIs(t, err, errAccountIDRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err = e.GetSubAccountTransferRecord(generateContext(t), "329455537441832960") + require.NoError(t, err) +} + +func TestGetDepositAddresses(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err := e.GetDepositAddresses(generateContext(t), currency.LTC) + require.NoError(t, err) +} + +func TestGetOrderInfo(t *testing.T) { + t.Parallel() + _, err := e.GetOrderInfo(generateContext(t), "1234", spotTradablePair, asset.Options) + require.ErrorIs(t, err, asset.ErrNotSupported) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetOrderInfo(generateContext(t), "1234", spotTradablePair, asset.Spot) + require.NoError(t, err) + assert.NotNil(t, result) + + result, err = e.GetOrderInfo(generateContext(t), "12345", futuresTradablePair, asset.Futures) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetDepositAddress(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetDepositAddress(generateContext(t), currency.BTC, "", "TON") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestWalletActivity(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1743575750138), time.UnixMilli(1743582950138) + _, err := e.WalletActivity(generateContext(t), endTime, startTime, "") + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour*2), time.Now() + } + _, err = e.WalletActivity(generateContext(t), startTime, endTime, "deposits") + require.NoError(t, err) + + result, err := e.WalletActivity(generateContext(t), startTime, endTime, "") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestNewCurrencyDepositAddress(t *testing.T) { + t.Parallel() + _, err := e.NewCurrencyDepositAddress(t.Context(), currency.EMPTYCODE) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.NewCurrencyDepositAddress(generateContext(t), currency.BTC) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestWithdrawCurrency(t *testing.T) { + t.Parallel() + _, err := e.WithdrawCurrency(t.Context(), &WithdrawCurrencyRequest{Amount: 1}) + require.ErrorIs(t, err, currency.ErrCurrencyCodeEmpty) + + _, err = e.WithdrawCurrency(t.Context(), &WithdrawCurrencyRequest{Coin: currency.BTC}) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + _, err = e.WithdrawCurrency(t.Context(), &WithdrawCurrencyRequest{Coin: currency.BTC, Amount: 1}) + require.ErrorIs(t, err, errInvalidWithdrawalChain) + + _, err = e.WithdrawCurrency(t.Context(), &WithdrawCurrencyRequest{Coin: currency.BTC, Amount: 1, Network: "BTC"}) + require.ErrorIs(t, err, errAddressRequired) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.WithdrawCurrency(t.Context(), &WithdrawCurrencyRequest{Network: "ERP", Coin: currency.BTC, Amount: 1, Address: "bc1qk0jareu4jytc0cfrhr5wgshsq8"}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetAccountMargin(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err := e.GetAccountMargin(generateContext(t), "") + require.ErrorIs(t, err, errAccountTypeRequired) + + result, err := e.GetAccountMargin(generateContext(t), "SPOT") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetBorrowStatus(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err := e.GetBorrowStatus(generateContext(t), currency.USDT) + require.NoError(t, err) +} + +func TestMaximumBuySellAmount(t *testing.T) { + t.Parallel() + _, err := e.GetMarginBuySellAmounts(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetMarginBuySellAmounts(generateContext(t), spotTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestPlaceOrder(t *testing.T) { + t.Parallel() + _, err := e.PlaceOrder(t.Context(), &PlaceOrderRequest{QuoteAmount: 1}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + _, err = e.PlaceOrder(t.Context(), &PlaceOrderRequest{Symbol: spotTradablePair}) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + _, err = e.PlaceOrder(t.Context(), &PlaceOrderRequest{Symbol: spotTradablePair, Side: order.Sell, Type: OrderType(order.Limit)}) + require.ErrorIs(t, err, limits.ErrPriceBelowMin) + _, err = e.PlaceOrder(t.Context(), &PlaceOrderRequest{Symbol: spotTradablePair, Side: order.Sell}) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + _, err = e.PlaceOrder(t.Context(), &PlaceOrderRequest{ + Symbol: spotTradablePair, + Side: order.Buy, + Type: OrderType(order.Market), + BaseAmount: 1, + Price: 40000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abc", + }) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + _, err = e.PlaceOrder(t.Context(), &PlaceOrderRequest{ + Symbol: spotTradablePair, + Side: order.Sell, + Type: OrderType(order.Market), + QuoteAmount: 1, + Price: 40000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abc", + }) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.PlaceOrder(t.Context(), &PlaceOrderRequest{ + Symbol: spotTradablePair, + Side: order.Buy, + Type: OrderType(order.Market), + QuoteAmount: 100, + Price: 100000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abc", + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestPlaceBatchOrders(t *testing.T) { + t.Parallel() + _, err := e.PlaceBatchOrders(t.Context(), nil) + require.ErrorIs(t, err, common.ErrNilPointer) + _, err = e.PlaceBatchOrders(t.Context(), []PlaceOrderRequest{{}}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + _, err = e.PlaceBatchOrders(t.Context(), []PlaceOrderRequest{ + { + Symbol: spotTradablePair, + }, + }) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + _, err = e.PlaceBatchOrders(t.Context(), []PlaceOrderRequest{{ + Symbol: spotTradablePair, + Side: order.Buy, + Type: OrderType(order.Market), + BaseAmount: 1, + Price: 40000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abc", + }}) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + _, err = e.PlaceBatchOrders(t.Context(), []PlaceOrderRequest{{ + Symbol: spotTradablePair, + Side: order.Sell, + Type: OrderType(order.Market), + QuoteAmount: 1, + Price: 40000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abc", + }}) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + var pair currency.Pair + getPairFromString := func(pairString string) currency.Pair { + pair, err = currency.NewPairFromString(pairString) + if err != nil { + return currency.EMPTYPAIR + } + return pair + } + + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + result, err := e.PlaceBatchOrders(t.Context(), []PlaceOrderRequest{ + { + Symbol: pair, + Side: order.Buy, + Type: OrderType(order.Market), + QuoteAmount: 1, + Price: 40000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abc", + }, + { + Symbol: getPairFromString("BTC_USDT"), + QuoteAmount: 100, + Side: order.Buy, + }, + { + Symbol: getPairFromString("BTC_USDT"), + Type: OrderType(order.Limit), + BaseAmount: 100, + Side: order.Buy, + Price: 40000.50000, + TimeInForce: TimeInForce(order.ImmediateOrCancel), + ClientOrderID: "1234Abc", + }, + { + Symbol: getPairFromString("ETH_USDT"), + QuoteAmount: 1000, + Side: order.Buy, + }, + { + Symbol: getPairFromString("TRX_USDT"), + Type: OrderType(order.Limit), + BaseAmount: 15000, + Side: order.Sell, + Price: 0.0623423423, + TimeInForce: TimeInForce(order.ImmediateOrCancel), + ClientOrderID: "456Xyz", + }, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelReplaceOrder(t *testing.T) { + t.Parallel() + _, err := e.CancelReplaceOrder(t.Context(), &CancelReplaceOrderRequest{TimeInForce: TimeInForce(order.GoodTillCancel)}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelReplaceOrder(t.Context(), &CancelReplaceOrderRequest{ + OrderID: "29772698821328896", + ClientOrderID: "1234Abc", + Price: 18000, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetOpenOrders(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err := e.GetOpenOrders(generateContext(t), spotTradablePair, "", "NEXT", "", 10) + require.NoError(t, err) + + _, err = e.GetOpenOrders(generateContext(t), spotTradablePair, "SELL", "NEXT", "24993088082542592", 10) + require.NoError(t, err) +} + +func TestGetOrder(t *testing.T) { + t.Parallel() + _, err := e.GetOrder(t.Context(), "", "") + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + _, err = e.GetOrder(generateContext(t), "12345536545645", "") + require.ErrorIs(t, err, order.ErrGetFailed) + + _, err = e.GetOrder(generateContext(t), "", "12345") + require.ErrorIs(t, err, order.ErrGetFailed) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetOrder(generateContext(t), "12345", "") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelOrderByID(t *testing.T) { + t.Parallel() + _, err := e.CancelOrderByID(t.Context(), "", "") + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + _, err = e.CancelOrderByID(t.Context(), "", "12345536545645") + require.ErrorIs(t, err, order.ErrCancelFailed) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelOrderByID(t.Context(), "12345536545645", "") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelMultipleOrdersByIDs(t *testing.T) { + t.Parallel() + _, err := e.CancelOrdersByIDs(t.Context(), nil, nil) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelOrdersByIDs(t.Context(), []string{"1234"}, []string{"5678"}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelTradeOrders(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + _, err := e.CancelTradeOrders(t.Context(), []string{"BTC_USDT", "ETH_USDT"}, []AccountType{AccountType(asset.Spot)}) + require.NoError(t, err) +} + +func TestKillSwitch(t *testing.T) { + t.Parallel() + _, err := e.KillSwitch(t.Context(), 0) + require.ErrorIs(t, err, errInvalidTimeout) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.KillSwitch(generateContext(t), time.Second*30) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestDisableKillSwitch(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.DisableKillSwitch(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetKillSwitchStatus(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetKillSwitchStatus(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCreateSmartOrder(t *testing.T) { + t.Parallel() + _, err := e.CreateSmartOrder(t.Context(), &SmartOrderRequest{Side: order.Buy}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + _, err = e.CreateSmartOrder(t.Context(), &SmartOrderRequest{Symbol: spotTradablePair}) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + _, err = e.CreateSmartOrder(t.Context(), &SmartOrderRequest{Symbol: spotTradablePair, Side: order.Buy}) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + _, err = e.CreateSmartOrder(t.Context(), &SmartOrderRequest{Symbol: spotTradablePair, Side: order.Buy, BaseAmount: 10, Type: OrderType(order.StopLimit)}) + require.ErrorIs(t, err, order.ErrPriceMustBeSetIfLimitOrder) + + _, err = e.CreateSmartOrder(t.Context(), &SmartOrderRequest{Symbol: spotTradablePair, Side: order.Buy, BaseAmount: 10, Type: OrderType(order.TrailingStopLimit), Price: 1234, TrailingOffset: "1%"}) + require.ErrorIs(t, err, errInvalidOffsetLimit) + + _, err = e.CreateSmartOrder(t.Context(), &SmartOrderRequest{Symbol: spotTradablePair, Side: order.Buy, BaseAmount: 10, Type: OrderType(order.TrailingStopLimit), Price: 1234}) + require.ErrorIs(t, err, errInvalidTrailingOffset) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CreateSmartOrder(generateContext(t), &SmartOrderRequest{ + Symbol: spotTradablePair, + Type: OrderType(order.StopLimit), + Price: 100000.5, + ClientOrderID: "1234Abc", + Side: order.Buy, + TimeInForce: TimeInForce(order.GoodTillCancel), + BaseAmount: 100, + }) + require.NoError(t, err) + require.NotNil(t, result) + + result, err = e.CreateSmartOrder(generateContext(t), &SmartOrderRequest{ + Symbol: spotTradablePair, + Type: OrderType(order.TrailingStopLimit), + Price: 100000.5, + ClientOrderID: "55667798abcd", + Side: order.Buy, + TimeInForce: TimeInForce(order.GoodTillCancel), + BaseAmount: 100, + TrailingOffset: "2%", + LimitOffset: "1%", + }) + assert.NoError(t, err) + assert.NotNil(t, result) + assert.Equalf(t, int64(0), result.Code, "CreateSmartOrder error with code: %d message: %s", result.Code, result.Message) +} + +func TestCancelReplaceSmartOrder(t *testing.T) { + t.Parallel() + _, err := e.CancelReplaceSmartOrder(t.Context(), &CancelReplaceSmartOrderRequest{Price: 18000}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + _, err = e.CancelReplaceSmartOrder(t.Context(), &CancelReplaceSmartOrderRequest{NewClientOrderID: "1234Abc", Price: 18000}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelReplaceSmartOrder(t.Context(), &CancelReplaceSmartOrderRequest{ + OrderID: "29772698821328896", + NewClientOrderID: "1234Abc", + Price: 18000, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetSmartOpenOrders(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err := e.GetSmartOpenOrders(generateContext(t), 10, []string{"TRAILING_STOP", "TRAILING_STOP_LIMIT", "STOP", "STOP_LIMIT"}) + require.NoError(t, err) +} + +func TestGetSmartOrderDetails(t *testing.T) { + t.Parallel() + _, err := e.GetSmartOrderDetails(generateContext(t), "", "") + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + result, err := e.GetSmartOrderDetails(generateContext(t), "123313413", "") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelSmartOrderByID(t *testing.T) { + t.Parallel() + _, err := e.CancelSmartOrderByID(t.Context(), "", "") + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelSmartOrderByID(t.Context(), "123313413", "") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelMultipleSmartOrders(t *testing.T) { + t.Parallel() + _, err := e.CancelMultipleSmartOrders(t.Context(), &CancelOrdersRequest{}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelMultipleSmartOrders(t.Context(), &CancelOrdersRequest{OrderIDs: []string{"1234"}, ClientOrderIDs: []string{"5678"}}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelSmartOrders(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelSmartOrders(t.Context(), []currency.Pair{{Base: currency.BTC, Delimiter: "_", Quote: currency.USDT}, {Base: currency.ETH, Delimiter: "_", Quote: currency.USDT}}, []AccountType{AccountType(asset.Spot)}, []OrderType{}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestGetOrdersHistory(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764930174763), time.UnixMilli(1765290174763) + _, err := e.GetOrdersHistory(generateContext(t), &OrdersHistoryRequest{Symbol: spotTradablePair, AccountType: "SPOT", Limit: 10, StartTime: endTime, EndTime: startTime}) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour*100), time.Now() + } + _, err = e.GetOrdersHistory(generateContext(t), &OrdersHistoryRequest{Symbol: spotTradablePair, AccountType: "SPOT", Limit: 10, OrderTypes: []string{"LIMIT", "LIMIT_MAKER"}}) + require.NoError(t, err) + + _, err = e.GetOrdersHistory(generateContext(t), &OrdersHistoryRequest{ + Symbol: spotTradablePair, + AccountType: "SPOT", + From: 228530000, + Limit: 10, + Direction: "NEXT", + Side: order.Sell, + HideCancel: true, + StartTime: startTime, + EndTime: endTime, + OrderType: "LIMIT_MAKER", + States: "FAILED", + }) + require.NoError(t, err) +} + +func TestGetSmartOrderHistory(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764930174763), time.UnixMilli(1765290174763) + _, err := e.GetSmartOrderHistory(generateContext(t), &OrdersHistoryRequest{Limit: 10, StartTime: endTime, EndTime: startTime}) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour*100), time.Now() + } + _, err = e.GetSmartOrderHistory(generateContext(t), &OrdersHistoryRequest{ + Symbol: spotTradablePair, + AccountType: "SPOT", + OrderType: "LIMIT", + Side: order.Sell, + Direction: "PRE", + From: 12323123, + Limit: 100, + StartTime: startTime, + EndTime: endTime, + HideCancel: true, + }) + require.NoError(t, err) +} + +func TestGetTradeHistory(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764664401864), time.UnixMilli(1764668001864) + _, err := e.GetTradeHistory(generateContext(t), currency.Pairs{spotTradablePair}, "", 0, 0, endTime, startTime) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour), time.Now() + } + _, err = e.GetTradeHistory(generateContext(t), currency.Pairs{spotTradablePair}, "", 0, 0, startTime, endTime) + require.NoError(t, err) + + _, err = e.GetTradeHistory(generateContext(t), currency.Pairs{spotTradablePair}, "", 1, 100, startTime, endTime) + require.NoError(t, err) + + _, err = e.GetTradeHistory(generateContext(t), currency.Pairs{spotTradablePair}, "NEXT", 10, 100, startTime, endTime) + require.NoError(t, err) + + _, err = e.GetTradeHistory(generateContext(t), currency.Pairs{spotTradablePair}, "", 0, 0, time.Time{}, time.Time{}) + require.NoError(t, err) +} + +func TestGetTradeOrderID(t *testing.T) { + t.Parallel() + _, err := e.GetTradesByOrderID(t.Context(), "") + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err = e.GetTradesByOrderID(generateContext(t), "13123242323") + require.NoError(t, err) +} + +func TestGenerateSubscriptions(t *testing.T) { + t.Parallel() + var privateQualifiedChannels []string + if e.ValidateAPICredentials(t.Context(), asset.Spot) == nil { + privateQualifiedChannels = append(privateQualifiedChannels, "orders", "balances") + } + + for _, input := range []struct { + gen func() (subscription.List, error) + exp []string + }{ + { + gen: e.generateSubscriptions, + exp: []string{"candles_minute_5", "trades", "ticker", "book_lv2"}, + }, + { + gen: e.generatePrivateSubscriptions, + exp: privateQualifiedChannels, + }, + } { + got, err := input.gen() + require.NoError(t, err) + + var gotQualifiedChannels []string + for _, inp := range got { + gotQualifiedChannels = append(gotQualifiedChannels, inp.QualifiedChannel) + } + assert.Equal(t, input.exp, gotQualifiedChannels) + } +} + +func TestHandleSubscription(t *testing.T) { + t.Parallel() + subs, err := e.generateSubscriptions() + require.NoError(t, err) + require.NotEmpty(t, subs) + + for _, s := range subs { + if s.Authenticated { + continue // Skip authenticated channels + } + t.Run(s.QualifiedChannel, func(t *testing.T) { + t.Parallel() + payload, err := e.handleSubscription("subscribe", s) + require.NoError(t, err, "handleSubscription must not error") + assert.NotEmpty(t, payload.Channel, "Channel should not be empty") + }) + } +} + +var pushMessages = []*struct { + label string + payload string + auth bool + err error + errExplanation string +}{ + {label: "Symbols", payload: `{"channel":"symbols","data":[{"symbol":"BTC_USDC","baseCurrencyName":"BTC","quoteCurrencyName":"USDT","displayName":"BTC/USDT","state":"NORMAL","visibleStartTime":1659018819512,"tradableStartTime":1659018819512,"crossMargin":{"supportCrossMargin":true,"maxLeverage":"3"},"symbolTradeLimit":{"symbol":"BTC_USDT","priceScale":2,"quantityScale":6,"amountScale":2,"minQuantity":"0.000001","minAmount":"1","highestBid":"0","lowestAsk":"0"}}],"action":"snapshot"}`}, + {label: "Currencies", payload: `{"channel":"currencies","data":[{"currency":"BTC","id":28,"name":"Bitcoin","description":"BTC Clone","type":"address","withdrawalFee":"0.0008","minConf":2,"depositAddress":null,"blockchain":"BTC","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["BTCTRON"]},{"currency":"XRP","id":243,"name":"XRP","description":"Payment ID","type":"address-payment-id","withdrawalFee":"0.2","minConf":2,"depositAddress":"rwU8rAiE2eyEPz3sikfbHuqCuiAtdXqa2v","blockchain":"XRP","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":false,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":[]},{"currency":"ETH","id":267,"name":"Ethereum","description":"Sweep to Main Account","type":"address","withdrawalFee":"0.00197556","minConf":64,"depositAddress":null,"blockchain":"ETH","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["ETHTRON"]},{"currency":"USDT","id":214,"name":"Tether USD","description":"Sweep to Main Account","type":"address","withdrawalFee":"0","minConf":2,"depositAddress":null,"blockchain":"OMNI","delisted":false,"tradingState":"NORMAL","walletState":"DISABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["USDTETH","USDTTRON"]},{"currency":"DOGE","id":59,"name":"Dogecoin","description":"BTC Clone","type":"address","withdrawalFee":"20","minConf":6,"depositAddress":null,"blockchain":"DOGE","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["DOGETRON"]},{"currency":"LTC","id":125,"name":"Litecoin","description":"BTC Clone","type":"address","withdrawalFee":"0.001","minConf":4,"depositAddress":null,"blockchain":"LTC","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["LTCTRON"]},{"currency":"DASH","id":60,"name":"Dash","description":"BTC Clone","type":"address","withdrawalFee":"0.01","minConf":20,"depositAddress":null,"blockchain":"DASH","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":false,"isChildChain":false,"supportCollateral":false,"supportBorrow":false,"childChains":[]}],"action":"snapshot"}`}, + {label: "Currencies Malformed JSON", payload: `{"channel":"currencies","data":[{"currency":"BTC","id":28,"name":1235,"description":"BTC Clone","type":"address","withdrawalFee":"0.0008","minConf":2,"depositAddress":null,"blockchain":"BTC","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["BTCTRON"]},{"currency":"XRP","id":243,"name":"XRP","description":"Payment ID","type":"address-payment-id","withdrawalFee":"0.2","minConf":2,"depositAddress":"rwU8rAiE2eyEPz3sikfbHuqCuiAtdXqa2v","blockchain":"XRP","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":false,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":[]},{"currency":"ETH","id":267,"name":"Ethereum","description":"Sweep to Main Account","type":"address","withdrawalFee":"0.00197556","minConf":64,"depositAddress":null,"blockchain":"ETH","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["ETHTRON"]},{"currency":"USDT","id":214,"name":"Tether USD","description":"Sweep to Main Account","type":"address","withdrawalFee":"0","minConf":2,"depositAddress":null,"blockchain":"OMNI","delisted":false,"tradingState":"NORMAL","walletState":"DISABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["USDTETH","USDTTRON"]},{"currency":"DOGE","id":59,"name":"Dogecoin","description":"BTC Clone","type":"address","withdrawalFee":"20","minConf":6,"depositAddress":null,"blockchain":"DOGE","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["DOGETRON"]},{"currency":"LTC","id":125,"name":"Litecoin","description":"BTC Clone","type":"address","withdrawalFee":"0.001","minConf":4,"depositAddress":null,"blockchain":"LTC","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["LTCTRON"]},{"currency":"DASH","id":60,"name":"Dash","description":"BTC Clone","type":"address","withdrawalFee":"0.01","minConf":20,"depositAddress":null,"blockchain":"DASH","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":false,"isChildChain":false,"supportCollateral":false,"supportBorrow":false,"childChains":[]}],"action":"snapshot"}`, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Candles", payload: `{"channel":"candles_minute_5","data":[{"symbol":"BTC_USDT","open":"25143.19","high":"25148.58","low":"25138.76","close":"25144.55","quantity":"0.860454","amount":"21635.20983974","tradeCount":20,"startTime":1694469000000,"closeTime":1694469299999,"ts":1694469049867}]}`}, + {label: "Candles Malformed JSON", payload: `{"channel":"candles_minute_5","data":[{"symbol":"BTC_USDT","open":"25143.19","high":"25148.58","low":"25138.76","close":"25144.55","quantity":"0.860454","amount":"21635.20983974","tradeCount":"abc","startTime":1694469000000,"closeTime":1694469299999,"ts":1694469049867}]}`, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Error Candles", payload: `{"channel":"candles_minute5","data":[{"symbol":"BTC_USDT","open":"25143.19","high":"25148.58","low":"25138.76","close":"25144.55","quantity":"0.860454","amount":"21635.20983974","tradeCount":20,"startTime":1694469000000,"closeTime":1694469299999,"ts":1694469049867}]}`, err: kline.ErrInvalidInterval}, + {label: "Trades", payload: `{"channel":"trades","data":[{"symbol":"BTC_USDC","amount":"52.821342","quantity":"0.0021","takerSide":"sell","createTime":1694469183664,"price":"25153.02","id":"71076055","ts":1694469183673}]}`}, + {label: "Trades Malformed JSON", payload: `{"channel":"trades","data":[{"symbol":"BTC_USDC","amount":"52.821342","quantity":"0.0021","takerSide":123,"createTime":1694469183664,"price":"25153.02","id":"71076055","ts":1694469183673}]}`, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Tickers", payload: `{"channel":"ticker","data":[{"symbol":"BTC_USDC","startTime":1694382780000,"open":"25866.3","high":"26008.47","low":"24923.65","close":"25153.02","quantity":"1626.444884","amount":"41496808.63699303","tradeCount":37124,"dailyChange":"-0.0276","markPrice":"25154.9","closeTime":1694469183664,"ts":1694469187081}]}`}, + {label: "Tickers Malformed JSON", payload: `{"channel":"ticker","data":[{"symbol":1234,"startTime":1694382780000,"open":"25866.3","high":"26008.47","low":"24923.65","close":"25153.02","quantity":"1626.444884","amount":"41496808.63699303","tradeCount":37124,"dailyChange":"-0.0276","markPrice":"25154.9","closeTime":1694469183664,"ts":1694469187081}]}`, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Books", payload: `{"channel":"book","data":[{"symbol":"BTC_USDC","createTime":1694469187686,"asks":[["25157.24","0.444294"],["25157.25","0.024357"],["25157.26","0.003204"],["25163.39","0.039476"],["25163.4","0.110047"]],"bids":[["25148.8","0.00692"],["25148.61","0.021581"],["25148.6","0.034504"],["25148.59","0.065405"],["25145.52","0.79537"]],"id":598273384,"ts":1694469187733}]}`}, + {label: "Books Malformed JSON", payload: `{"channel":"book","data":[{"symbol": 12345,"createTime":1694469187686,"asks":[["25157.24","0.444294"],["25157.25","0.024357"],["25157.26","0.003204"],["25163.39","0.039476"],["25163.4","0.110047"]],"bids":[["25148.8","0.00692"],["25148.61","0.021581"],["25148.6","0.034504"],["25148.59","0.065405"],["25145.52","0.79537"]],"id":598273384,"ts":1694469187733}]}`, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Orders", payload: `{"channel": "orders", "data": [{"symbol": "BTC_USDC", "type": "LIMIT", "quantity": "1", "orderId": "32471407854219264", "tradeFee": "0", "clientOrderId": "", "accountType": "SPOT", "feeCurrency": "", "eventType": "place", "source": "API", "side": "BUY", "filledQuantity": "0", "filledAmount": "0", "matchRole": "MAKER", "state": "NEW", "tradeTime": 0, "tradeAmount": "0", "orderAmount": "0", "createTime": 1648708186922, "price": "47112.1", "tradeQty": "0", "tradePrice": "0", "tradeId": "0", "ts": 1648708187469}]}`, auth: true}, + {label: "Orders Malformed JSON", payload: `{"channel": "orders", "data": [{"symbol": "BTC_USDC", "type": 1234, "quantity": "1", "orderId": "32471407854219264", "tradeFee": "0", "clientOrderId": "", "accountType": "SPOT", "feeCurrency": "", "eventType": "place", "source": "API", "side": "BUY", "filledQuantity": "0", "filledAmount": "0", "matchRole": "MAKER", "state": "NEW", "tradeTime": 0, "tradeAmount": "0", "orderAmount": "0", "createTime": 1648708186922, "price": "47112.1", "tradeQty": "0", "tradePrice": "0", "tradeId": "0", "ts": 1648708187469}]}`, auth: true, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Account Balance", payload: `{ "channel": "balances", "data": [{ "changeTime": 1657312008411, "accountId": "1234", "accountType": "SPOT", "eventType": "place_order", "available": "9999999983.668", "currency": "BTC", "id": 60018450912695040, "userId": 12345, "hold": "16.332", "ts": 1657312008443 }] }`, auth: true}, + {label: "Account Balance Malformed JSON", payload: `{ "channel": "balances", "data": [{ "changeTime": 1657312008411, "accountId": 1234, "accountType": "SPOT", "eventType": "place_order", "available": "9999999983.668", "currency": "BTC", "id": 60018450912695040, "userId": 12345, "hold": "16.332", "ts": 1657312008443 }] }`, auth: true, errExplanation: "Unhandled JSON Unmarshaling Error"}, + {label: "Orderbook Level Error", payload: `{"channel":"book_lv2","data":[{"symbol":"BTC_USDC","createTime":1694469187745,"asks":[],"bids":[["25148.81","0.02158"],["25088.11","0"]],"lastId":598273385,"id":598273386,"ts":1694469187760}, {}],"action":"snapshot"}`, errExplanation: "expected 1 orderbook snapshot payload"}, + {label: "Exchange Channel", payload: `{"channel": "exchange", "action" : "snapshot", "data": [ { "MM" : "ON", "POM" : "OFF" } ] }`}, + {label: "Currencies Malformed JSON", payload: `{"channel":"currencies","data":[{"currency":124,"id":28,"name":"Bitcoin","description":"BTC Clone","type":"address","withdrawalFee":"0.0008","minConf":2,"depositAddress":null,"blockchain":"BTC","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["BTCTRON"]},{"currency":"XRP","id":243,"name":"XRP","description":"Payment ID","type":"address-payment-id","withdrawalFee":"0.2","minConf":2,"depositAddress":"rwU8rAiE2eyEPz3sikfbHuqCuiAtdXqa2v","blockchain":"XRP","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":false,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":[]},{"currency":"ETH","id":267,"name":"Ethereum","description":"Sweep to Main Account","type":"address","withdrawalFee":"0.00197556","minConf":64,"depositAddress":null,"blockchain":"ETH","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["ETHTRON"]},{"currency":"USDT","id":214,"name":"Tether USD","description":"Sweep to Main Account","type":"address","withdrawalFee":"0","minConf":2,"depositAddress":null,"blockchain":"OMNI","delisted":false,"tradingState":"NORMAL","walletState":"DISABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["USDTETH","USDTTRON"]},{"currency":"DOGE","id":59,"name":"Dogecoin","description":"BTC Clone","type":"address","withdrawalFee":"20","minConf":6,"depositAddress":null,"blockchain":"DOGE","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["DOGETRON"]},{"currency":"LTC","id":125,"name":"Litecoin","description":"BTC Clone","type":"address","withdrawalFee":"0.001","minConf":4,"depositAddress":null,"blockchain":"LTC","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":true,"isChildChain":false,"supportCollateral":true,"supportBorrow":true,"childChains":["LTCTRON"]},{"currency":"DASH","id":60,"name":"Dash","description":"BTC Clone","type":"address","withdrawalFee":"0.01","minConf":20,"depositAddress":null,"blockchain":"DASH","delisted":false,"tradingState":"NORMAL","walletState":"ENABLED","parentChain":null,"isMultiChain":false,"isChildChain":false,"supportCollateral":false,"supportBorrow":false,"childChains":[]}],"action":"snapshot"}`, errExplanation: "Unhandled JSON unmarshal error"}, + {label: "Unmarshal Error", payload: `{"channel":"abc","data":[]`, errExplanation: "Unexpected JSON input error"}, + {label: "Unhandled Channel", payload: `{"channel":"abc","data":[]}`, errExplanation: "Unhandled channel message"}, + {label: "Unhandled Event", payload: `{"event": "abc"}`, errExplanation: "Unhandled event message"}, + {label: "Pong Event", payload: `{"event": "pong"}`}, +} + +func TestWsHandleData(t *testing.T) { + t.Parallel() + for _, p := range pushMessages { + t.Run(p.label, func(t *testing.T) { + t.Parallel() + if p.auth { + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + } + + err := e.wsHandleData(generateContext(t), e.Websocket.Conn, []byte(p.payload)) + if p.errExplanation == "" { + assert.ErrorIs(t, err, p.err) + } else { + assert.Error(t, err, p.errExplanation) + } + }) + } + // Since running test in parallel shuffles the order of execution + // We run book_lv2 data handling, ensuring the snapshot is processed before the update as follows + err := e.wsHandleData(generateContext(t), e.Websocket.Conn, []byte(`{"channel":"book_lv2","data":[{"symbol":"BTC_USDC","createTime":1694469187745,"asks":[],"bids":[["25148.81","0.02158"],["25088.11","0"]],"lastId":598273385,"id":598273386,"ts":1694469187760}],"action":"snapshot"}`)) + require.NoError(t, err, "book_lv2 snapshot must not error") + err = e.wsHandleData(generateContext(t), e.Websocket.Conn, []byte(`{"channel":"book_lv2","data":[{"symbol":"BTC_USDC","createTime":1694469187745,"asks":[],"bids":[["25148.81","0.02158"],["25088.11","0"]],"lastId":598273385,"id":598273386,"ts":1694469187760}],"action":"update"}`)) + assert.NoError(t, err, "book_lv2 update should not error") +} + +var spotPrivatePushDataMap = []struct { + k string + v string + signature string +}{ + {k: "Error", v: `{ "event": "error", "message": "Error Message" }`, signature: "subscription"}, + {k: "Subscribe", v: `{"event": "subscribe", "channel": "exchange"}`, signature: "subscription"}, + {k: "Unsubscription Response", v: `{ "channel": "orders", "event": "unsubscribe", "symbols": ["all"] }`, signature: "subscription"}, + {k: "Auth Successful", v: `{ "data": { "success": true, "ts": 1645597033915 }, "channel": "auth" }`, signature: "auth"}, + {k: "Auth Failed", v: `{"data": { "success": false, "message": "Authentication failed!", "ts": 1646276295075 }, "channel": "auth"}`, signature: "auth"}, + {k: "Order Subscription", v: `{ "channel": "orders", "event": "subscribe" }`, signature: "subscription"}, + {k: "Create Order Successful", v: `{ "id": "1234567", "data": [{ "orderId": 205343650954092544, "clientOrderId": "", "message": "", "code": 200 }] }`, signature: "1234567"}, + {k: "Create Order Failure", v: `{ "id": "123457", "data": [{ "orderId": 0, "clientOrderId": null, "message": "Currency trade disabled", "code": 21352 }] }`, signature: "123457"}, + {k: "Cancel Multiple Order Successful", v: `{ "id": "1234567", "data": [{ "orderId": 170903943331844096, "clientOrderId": "45662xyz", "message": "", "code": 200 }, { "orderId": 170904091512410112, "clientOrderId": "xasd2343", "message": "", "code": 200 }] }`, signature: "1234567"}, + {k: "Cancel All Order Successful", v: `{ "id": "1234567", "data": [{ "orderId": 170903943331844096, "clientOrderId": "45662xyz", "message": "", "code": 200 }, { "orderId": 170904091512410112, "clientOrderId": "xasd2343", "message": "", "code": 200 }] }`, signature: "1234567"}, +} + +func TestWsSpotPrivateHandleData(t *testing.T) { + t.Parallel() + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") + if mockTests { + t.Skip(websocketMockTestsSkipped) + } + + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") + + testexch.SetupWs(t, e) + conn, err := e.Websocket.GetConnection(connSpotPrivate) + require.NoError(t, err) + require.NotNil(t, conn) + + for _, data := range spotPrivatePushDataMap { + buf, err := conn.MatchReturnResponses(t.Context(), data.signature, 1) + require.NoError(t, err) + + err = e.wsHandleData(t.Context(), conn, []byte(data.v)) + require.NoError(t, err) + + select { + case <-buf: + // success + case <-time.After(10 * time.Millisecond): + t.Fatalf("timeout waiting for websocket stream data with signature %s", data.signature) + } + } +} + +func TestWsCreateOrder(t *testing.T) { + t.Parallel() + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") + + _, err := e.WsCreateOrder(t.Context(), &PlaceOrderRequest{QuoteAmount: 1}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + + _, err = e.WsCreateOrder(t.Context(), &PlaceOrderRequest{ + Symbol: spotTradablePair, + }) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + _, err = e.WsCreateOrder(t.Context(), &PlaceOrderRequest{ + Symbol: spotTradablePair, + Side: order.Sell, + }) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + if mockTests { + t.Skip(websocketMockTestsSkipped) + } + + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") + + testexch.SetupWs(t, e) + result, err := e.WsCreateOrder(generateContext(t), &PlaceOrderRequest{ + Symbol: spotTradablePair, + Side: order.Buy, + Type: OrderType(order.Market), + QuoteAmount: 400050.0, + BaseAmount: 100, + Price: 40000.50000, + TimeInForce: TimeInForce(order.GoodTillCancel), + ClientOrderID: "1234Abcde", + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestWsCancelMultipleOrdersByIDs(t *testing.T) { + t.Parallel() + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") + + _, err := e.WsCancelMultipleOrdersByIDs(t.Context(), []string{}, []string{}) + assert.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if mockTests { + t.Skip(websocketMockTestsSkipped) + } + + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") + + testexch.SetupWs(t, e) + result, err := e.WsCancelMultipleOrdersByIDs(t.Context(), []string{"1234"}, []string{"5678"}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestWsCancelTradeOrders(t *testing.T) { + t.Parallel() + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") + + if mockTests { + t.Skip(websocketMockTestsSkipped) + } + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") + + testexch.SetupWs(t, e) + result, err := e.WsCancelTradeOrders(t.Context(), []string{"BTC_USDT", "ETH_USDT"}, []AccountType{AccountType(asset.Spot)}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestUpdateOrderExecutionLimits(t *testing.T) { + t.Parallel() + err := e.UpdateOrderExecutionLimits(t.Context(), asset.Options) + require.ErrorIs(t, err, asset.ErrNotSupported) + + err = e.UpdateOrderExecutionLimits(t.Context(), asset.Futures) + require.NoError(t, err) + + instrument, err := e.GetFuturesProduct(t.Context(), futuresTradablePair) + require.NoError(t, err) + require.NotNil(t, instrument) + + lms, err := e.GetOrderExecutionLimits(asset.Futures, futuresTradablePair) + require.NoError(t, err) + require.NotNil(t, lms) + assert.Equal(t, lms.PriceStepIncrementSize, instrument.TickSize.Float64()) + assert.Equal(t, lms.MinimumBaseAmount, instrument.MinQuantity.Float64()) + assert.Equal(t, lms.MinimumQuoteAmount, float64(instrument.MinSize)) + + // sample test for spot instrument order execution limit + + err = e.UpdateOrderExecutionLimits(t.Context(), asset.Spot) + require.NoError(t, err) + + spotInstruments, err := e.GetSymbol(t.Context(), spotTradablePair) + require.NoError(t, err) + require.NotNil(t, spotInstruments) + + lms, err = e.GetOrderExecutionLimits(asset.Spot, spotTradablePair) + require.NoError(t, err) + require.Len(t, spotInstruments, 1) + require.Equal(t, lms.PriceStepIncrementSize, priceScaleMultipliers[spotInstruments[0].SymbolTradeLimit.PriceScale]) + require.Equal(t, lms.MinimumBaseAmount, spotInstruments[0].SymbolTradeLimit.MinQuantity.Float64()) + assert.Equal(t, lms.MinimumQuoteAmount, spotInstruments[0].SymbolTradeLimit.MinAmount.Float64()) +} + +func TestGetCurrencyTradeURL(t *testing.T) { + t.Parallel() + testexch.UpdatePairsOnce(t, e) + for _, a := range e.GetAssetTypes(false) { + pairs, err := e.CurrencyPairs.GetPairs(a, false) + assert.NoError(t, err) + assert.NotEmpty(t, pairs) + + resp, err := e.GetCurrencyTradeURL(t.Context(), a, pairs[0]) + assert.NoError(t, err) + assert.NotEmpty(t, resp) + } +} + +var futuresPushDataMap = []struct { + label string + payload string + err error + errExplanation string +}{ + {label: "Symbols", payload: `{"channel": "symbol", "data": [ { "symbol": "BTC_USDT_PERP", "visibleStartTime": "1584721775000", "tradableStartTime": "1584721775000", "pxScale": "0.01,0.1,1,10,100", "lotSz": 1, "minSz": 1, "ctVal": "0.001", "status": "OPEN", "maxPx": "1000000", "minPx": "0.01", "marketMaxQty": 100000, "limitMaxQty": 100000, "maxQty": "1000000", "minQty": "1", "maxLever": "75", "lever": "20", "ctType": "LINEAR", "alias": "", "bAsset": ".PXBTUSDT", "bCcy": "BTC", "qCcy": "USDT", "sCcy": "USDT", "tSz": "0.01", "oDate": "1547435912000", "iM": "0.0133", "mR": "5000", "mM": "0.006" } ], "action": "snapshot" }`}, + {label: "Product Info", payload: `{"channel": "symbol", "data":[{"symbol": "BTC_USDT_PERP", "visibleStartTime": "1584721775000", "tradableStartTime": "1584721775000", "pxScale": "0.01,0.1,1,10,100", "lotSz": 1, "minSz": 1, "ctVal": "0.001", "status": "OPEN", "maxPx": "1000000", "minPx": "0.01", "marketMaxQty": 100000, "limitMaxQty": 100000, "maxQty": "1000000", "minQty": "1", "maxLever": "75", "lever": "20", "ctType": "LINEAR", "alias": "", "bAsset": ".PXBTUSDT", "bCcy": "BTC", "qCcy": "USDT", "sCcy": "USDT", "tSz": "0.01","oDate": "1547435912000", "iM": "0.0133", "mR": "5000", "mM": "0.006" } ], "action": "snapshot"}`}, + {label: "Orderbook", payload: `{"channel":"book","data":[{"asks":[["87854.92","9"],["87854.93","1"],["87861.31","1"],["87864.51","530"],["87866.84","21"]],"bids":[["87851.73","1"],["87851.72","1"],["87811.92","158"],["87810.84","9"],["87809.78","446"]],"id":3206990058,"ts":1765921966039,"s":"BTC_USDT_PERP","cT":1765921965951}]}`}, + {label: "K-Line Data", payload: `{"channel": "candles_minute_1", "data": [ ["BTC_USDT_PERP","91883.46","91958.73","91883.46","91958.73","367.68438","4",2,1741243200000,1741243259999,1741243218348]]}`}, + {label: "K-Line Five Min Data", payload: `{"channel": "candles_minute_5", "data": [ ["BTC_USDT_PERP","91883.46","91958.73","91883.46","91958.73","367.68438","4",2,1741243200000,1741243259999,1741243218348]]}`}, + {label: "Err K-Line Five Min Data", payload: `{"channel": "candles_minute5", "data": [ ["BTC_USDT_PERP","91883.46","91958.73","91883.46","91958.73","367.68438","4",2,1741243200000,1741243259999,1741243218348]]}`, err: kline.ErrInvalidInterval}, + {label: "Tickers", payload: `{"channel": "tickers", "data": [ { "s": "BTC_USDT_PERP", "o": "46000", "l": "26829.541", "h": "46100", "c": "46100", "qty": "18736", "amt": "8556118.81658", "tC": 44, "sT": 1718785800000, "cT": 1718872244268, "dC": "0.0022", "bPx": "46000", "bSz": "46000", "aPx": "46100", "aSz": "9279", "ts": 1718872247385}]}`}, + {label: "Trades", payload: `{"channel":"trades", "data": [ { "id": 291, "ts": 1718871802553, "s": "BTC_USDT_PERP", "px": "46100", "qty": "1", "amt": "461", "side": "buy", "cT": 1718871802534}]}`}, + {label: "Index Price", payload: `{"channel": "index_price", "data": [ { "ts": 1719226453000, "s": "BTC_USDT_PERP", "iPx": "34400"}]}`}, + {label: "Mark Price", payload: `{"channel":"mark_price", "data": [ { "ts": 1719226453000, "s": "BTC_USDT_PERP", "mPx": "34400"}]}`}, + {label: "Mark Price K-line Data", payload: `{"channel": "mark_price_candles_minute_1", "data": [["BTC_USDT_PERP","57800.17","57815.95","57809.65","57800.17",1725264900000,1725264959999,1725264919140]]}`}, + {label: "Index Price K-line Data", payload: `{"channel": "index_candles_minute_1", "data": [ ["BTC_USDT_PERP","57520.09","57614.9","57520.09","57609.89",1725248760000,1725248819999,1725248813187]]}`}, + {label: "Funding Rate", payload: `{"channel":"funding_rate", "data": [ { "ts": 1718874420000, "s": "BTC_USDT_PERP", "nFR": "0.000003", "fR": "0.000619", "fT": 1718874000000, "nFT": 1718874900000}]}`}, + {label: "Positions", payload: `{"channel":"positions", "data": [ { "symbol": "BTC_USDT_PERP", "posSide": "BOTH", "side": "buy", "mgnMode": "CROSS", "openAvgPx": "64999", "qty": "1", "oldQty": "0", "availQty": "1", "lever": 1, "fee": "-0.259996", "adl": "0", "liqPx": "-965678126.114070339063390145", "mgn": "604.99", "im": "604.99", "mm": "3.327445", "upl": "-45", "uplRatio": "-0.0743", "pnl": "0", "markPx": "60499", "mgnRatio": "0.000007195006959591", "state": "NORMAL", "ffee": "0", "fpnl": "0", "cTime": 1723459553457, "uTime": 1725330697439, "ts": 1725330697459}]}`}, + {label: "Orders", payload: `{"channel": "orders", "data": [ { "symbol": "BTC_USDT_PERP", "side": "BUY", "type": "LIMIT", "mgnMode": "CROSS", "timeInForce": "GTC", "clOrdId": "polo353849510130364416", "sz": "1", "px": "64999", "reduceOnly": false, "posSide": "BOTH", "ordId": "353849510130364416", "state": "NEW", "source": "WEB", "avgPx": "0", "execQty": "0", "execAmt": "0", "feeCcy": "", "feeAmt": "0", "deductCcy": "", "deductAmt": "0", "actType": "TRADING", "qCcy": "USDT", "cTime": 1725330697421, "uTime": 1725330697421, "ts": 1725330697451}]}`}, + {label: "Trade", payload: `{"channel": "trade", "data": [ { "symbol": "BTC_USDT_PERP", "side": "BUY", "ordId": "353849510130364416", "clOrdId": "polo353849510130364416", "role": "TAKER", "trdId": "48", "feeCcy": "USDT", "feeAmt": "0.259996", "deductCcy": "", "deductAmt": "0", "fpx": "64999", "fqty": "1", "uTime": 1725330697559, "ts": 1725330697579}]}`}, + {label: "Account Change", payload: `{"channel": "account", "data": [ { "state": "NORMAL", "eq": "9604385.495986629521985415", "isoEq": "0", "im": "281.27482", "mm": "65.7758462", "mmr": "0.000006848522086861", "upl": "702.005423182573616772", "availMgn": "9604104.221166629521985415", "details": [ { "ccy": "USDT", "eq": "9604385.495986629521985415", "isoEq": "0", "avail": "9603683.490563446948368643", "upl": "702.005423182573616772", "isoAvail": "0", "isoHold": "0", "isoUpl": "0", "im": "281.27482", "imr": "0.000029286081875569", "mm": "65.7758462", "mmr": "0.000006848522086861", "cTime": 1723431998599, "uTime": 1725329576649 } ], "cTime": 1689326308656, "uTime": 1725329576649, "ts": 1725329576659}]}`}, + {label: "Open Interest", payload: `{"channel": "open_interest", "data": [ { "s": "BTC_USDT_PERP", "oInterest": "19774.000000000000000000", "ts": 1747296831379 } ], "action": "snapshot"}`}, + {label: "Liquidation Price", payload: `{"channel": "liquidation_orders", "data": [ { "s": "BTC_USDT_PERP", "side": "BUY", "posSide": "BOTH", "sz": "1", "bkPx": "94120.8368032", "uTime": 1739367328421, "ts": 1739367328446}]}`}, + {label: "Limit Price", payload: `{"channel": "limit_price", "data": [ { "ts": 1739346571315, "s": "BTC_USDT_PERP", "buyLmt": "100790.67", "sellLmt": "91191.57" } ], "action": "update" }`}, + {label: "Unhandle Mark Price Unmarshal Error", payload: `{"channel":"mark_price", "data": [ { "ts": 1719226453000, "s": 123, "mPx": "34400"}]}`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Symbols Unmarshal Error", payload: `{"channel": "symbol", "data": [{"symbol": "BTC_USDT_PERP", "visibleStartTime": "1584721775000", "tradableStartTime": "1584721775000", "pxScale": "0.01,0.1,1,10,100", "lotSz": "1", "minSz": 1, "ctVal": "0.001", "status": "OPEN", "maxPx": "1000000", "minPx": "0.01", "marketMaxQty": 100000, "limitMaxQty": 100000, "maxQty": "1000000", "minQty": "1", "maxLever": "75", "lever": "20", "ctType": "LINEAR", "alias": "", "bAsset": ".PXBTUSDT", "bCcy": "BTC", "qCcy": "USDT", "sCcy": "USDT", "tSz": "0.01", "oDate": "1547435912000", "iM": "0.0133", "mR": "5000", "mM": "0.006" } ], "action": "snapshot" }`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Index Price Unmarshal Error", payload: `{"channel": "index_price", "data": [ { "ts": 1719226453000, "s": 123, "iPx": "34400"}]}`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Mark Price Unmarshal Error", payload: `{"channel":"mark_price", "data": [ { "ts": 1719226453000, "s": 123456, "mPx": "34400"}]}`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Positions Unmarshal Error", payload: `{"channel":"positions", "data": [ { "symbol": "BTC_USDT_PERP", "posSide": "BOTH", "side": 123, "mgnMode": "CROSS", "openAvgPx": "64999", "qty": "1", "oldQty": "0", "availQty": "1", "lever": 1, "fee": "-0.259996", "adl": "0", "liqPx": "-965678126.114070339063390145", "mgn": "604.99", "im": "604.99", "mm": "3.327445", "upl": "-45", "uplRatio": "-0.0743", "pnl": "0", "markPx": "60499", "mgnRatio": "0.000007195006959591", "state": 1, "ffee": "0", "fpnl": "0", "cTime": 1723459553457, "uTime": 1725330697439, "ts": 1725330697459}]}`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Limit Price Unmarshal Error", payload: `{"channel": "limit_price", "data": [ { "ts": 1739346571315, "s": 124, "buyLmt": "100790.67", "sellLmt": "91191.57" } ], "action": "update" }`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Open Interest Unmarshal Error", payload: `{"channel": "open_interest", "data": [ { "s": 123, "oInterest": "19774.000000000000000000", "ts": 1747296831379 } ], "action": "snapshot"}`, errExplanation: "Unhandled event message"}, + {label: "Unhandled Liquidation Price Unmarshal Error", payload: `{"channel": "liquidation_orders", "data": [ { "s": "BTC_USDT_PERP", "side": 123, "posSide": "BOTH", "sz": "1", "bkPx": "94120.8368032", "uTime": 1739367328421, "ts": 1739367328446}]}`, errExplanation: "Unhandled event message"}, + {label: "Unmarshal Error", payload: `{"channel":"abc","data":[]`, errExplanation: "Unexpected JSON input error"}, + {label: "Unhandled Channel", payload: `{"channel":"abc","data":[]}`, errExplanation: "Unhandled channel message"}, + {label: "Unhandled Event", payload: `{"event": "abc"}`, errExplanation: "Unhandled event message"}, + {label: "Pong", payload: `{"event": "pong"}`}, +} + +func TestWsFuturesHandleData(t *testing.T) { + t.Parallel() + for _, data := range futuresPushDataMap { + t.Run(data.label, func(t *testing.T) { + t.Parallel() + err := e.wsFuturesHandleData(t.Context(), e.Websocket.Conn, []byte(data.payload)) + if data.errExplanation == "" { + assert.ErrorIs(t, err, data.err) + } else { + assert.Error(t, err, data.errExplanation) + } + }) + } + // Since running test in parallel shuffles the order of execution + // We run book_lv2 data handling, ensuring the snapshot is processed before the update as follows + err := e.wsFuturesHandleData(generateContext(t), e.Websocket.Conn, []byte(`{"channel":"book_lv2","data":[{"asks":[["87845.63","1"],["87850.4","1"],["87859.98","9"],["87866.84","21"],["87888.32","33"],["87891.40","106"],["87894.48","705"],["87897.56","238"],["87900.64","762"],["87905.16","8"],["87911.17","34"],["87913.95","4040"],["87915.13","470"],["87919.09","199"],["87922.74","2141"],["87923.05","758"],["87931.52","1568"],["87937.09","10"],["87940.31","1392"],["87940.61","64"]],"bids":[["87842.42","1"],["87842.41","1"],["87835.72","1138"],["87834.64","226"],["87833.61","446"],["87833.56","26"],["87832.48","13"],["87831.40","130"],["87807.27","69"],["87798.48","935"],["87794.18","1932"],["87791.10","296"],["87789.69","1596"],["87788.02","320"],["87784.94","131"],["87781.86","242"],["87780.90","768"],["87772.11","1737"],["87771.33","910"],["87767.37","261"]],"lid":3206980818,"id":3206980819,"ts":1765921828543,"s":"BTC_USDT_PERP","cT":1765921827839}],"action":"snapshot"}`)) + require.NoError(t, err, "Futures Orderbook Level-2 Snapshot must not error") + err = e.wsFuturesHandleData(t.Context(), e.Websocket.Conn, []byte(`{"channel":"book_lv2","data":[{"asks":[],"bids":[["87807.27","4"]],"lid":3206980819,"id":3206980843,"ts":1765921828626,"s":"BTC_USDT_PERP","cT":1765921828619}],"action":"update"}`)) + assert.NoError(t, err, "Futures Orderbook Level-2 Update should not error") +} + +var futuresPrivatePushDataMap = []struct { + k string + v string + signature string +}{ + {k: "Error", v: `{ "event": "error", "message": "Error Message" }`, signature: "subscription"}, + {k: "Subscription Response", v: `{ "channel": "orders", "event": "subscribe", "symbols": ["all"] }`, signature: "subscription"}, + {k: "Unsubscription Response", v: `{ "channel": "orders", "event": "unsubscribe", "symbols": ["all"] }`, signature: "subscription"}, + {k: "Auth", v: `{"data": { "success": true, "ts": 1645597033915 }, "channel": "auth"}`, signature: "auth"}, +} + +func TestWsFuturesPrivateHandleData(t *testing.T) { + t.Parallel() + e := new(Exchange) + require.NoError(t, testexch.Setup(e), "Test instance Setup must not error") + if mockTests { + t.Skip(websocketMockTestsSkipped) + } + + e.setAPICredential(apiKey, apiSecret) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + require.True(t, e.Websocket.CanUseAuthenticatedEndpoints(), "CanUseAuthenticatedEndpoints must return true") + + testexch.SetupWs(t, e) + conn, err := e.Websocket.GetConnection(connFuturesPrivate) + require.NoError(t, err) + require.NotNil(t, conn) + + var wg sync.WaitGroup + defer func() { + wg.Wait() + }() + + for _, data := range futuresPrivatePushDataMap { + buf, err := conn.MatchReturnResponses(t.Context(), data.signature, 1) + require.NoError(t, err) + + wg.Go(func() { + dtimer := time.NewTimer(time.Millisecond * 10) + select { + case <-buf: + break + case <-dtimer.C: + t.Error("timeout waiting for websocket stream data with signature ", data.signature) + } + }) + err = e.wsFuturesHandleData(t.Context(), conn, []byte(data.v)) + assert.NoError(t, err) + } +} + +func TestGetAccountBalance(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + } + _, err := e.GetAccountBalance(generateContext(t)) + require.NoError(t, err) +} + +func TestGetAccountBills(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1764930174763), time.UnixMilli(1765290174763) + _, err := e.GetAccountBills(generateContext(t), endTime, startTime, 0, 0, "NEXT", "PNL") + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() + } + result, err := e.GetAccountBills(generateContext(t), startTime, endTime, 1, 100, "NEXT", "PNL") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestPlaceFuturesOrder(t *testing.T) { + t.Parallel() + arg := &FuturesOrderRequest{ + ReduceOnly: true, + } + _, err := e.PlaceFuturesOrder(t.Context(), arg) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + arg.Symbol = futuresTradablePair + _, err = e.PlaceFuturesOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.Side = "buy" + arg.MarginMode = MarginMode(margin.Multi) + _, err = e.PlaceFuturesOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.PositionSide = order.Long + _, err = e.PlaceFuturesOrder(t.Context(), arg) + require.ErrorIs(t, err, order.ErrTypeIsInvalid) + + arg.OrderType = OrderType(order.LimitMaker) + _, err = e.PlaceFuturesOrder(t.Context(), arg) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + _, err = e.PlaceFuturesOrder(t.Context(), &FuturesOrderRequest{ + ClientOrderID: "939a9d51-8f32-443a-9fb8-ff0852010487", + Symbol: futuresTradablePair, + Side: "buy", + MarginMode: MarginMode(margin.Multi), + PositionSide: order.Long, + OrderType: OrderType(order.LimitMaker), + Price: 46050, + Size: 10, + TimeInForce: TimeInForce(order.GoodTillCancel), + SelfTradePreventionMode: "EXPIRE_TAKER", + ReduceOnly: false, + }) + require.NoError(t, err) +} + +func TestPlaceMultipleOrders(t *testing.T) { + t.Parallel() + arg := FuturesOrderRequest{ + ReduceOnly: true, + } + _, err := e.PlaceFuturesMultipleOrders(t.Context(), nil) + require.ErrorIs(t, err, common.ErrEmptyParams) + + _, err = e.PlaceFuturesMultipleOrders(t.Context(), []FuturesOrderRequest{arg}) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + arg.Symbol = futuresTradablePair + _, err = e.PlaceFuturesMultipleOrders(t.Context(), []FuturesOrderRequest{arg}) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.Side = "buy" + arg.MarginMode = MarginMode(margin.Multi) + _, err = e.PlaceFuturesMultipleOrders(t.Context(), []FuturesOrderRequest{arg}) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + + arg.PositionSide = order.Long + _, err = e.PlaceFuturesMultipleOrders(t.Context(), []FuturesOrderRequest{arg}) + require.ErrorIs(t, err, order.ErrTypeIsInvalid) + + arg.OrderType = OrderType(order.LimitMaker) + _, err = e.PlaceFuturesMultipleOrders(t.Context(), []FuturesOrderRequest{arg}) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + result, err := e.PlaceFuturesMultipleOrders(t.Context(), []FuturesOrderRequest{ + { + ClientOrderID: "939a9d51", + Symbol: futuresTradablePair, + Side: "buy", + MarginMode: MarginMode(margin.Multi), + PositionSide: order.Long, + OrderType: OrderType(order.LimitMaker), + Price: 46050, + Size: 10, + TimeInForce: TimeInForce(order.GoodTillCancel), + SelfTradePreventionMode: "EXPIRE_TAKER", + ReduceOnly: false, + }, + }) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelFuturesOrder(t *testing.T) { + t.Parallel() + _, err := e.CancelFuturesOrder(t.Context(), &CancelOrderRequest{OrderID: "1234"}) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + _, err = e.CancelFuturesOrder(t.Context(), &CancelOrderRequest{Symbol: futuresTradablePair}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + _, err = e.CancelFuturesOrder(generateContext(t), &CancelOrderRequest{Symbol: futuresTradablePair, OrderID: "12345"}) + require.NoError(t, err) +} + +func TestCancelMultipleFuturesOrders(t *testing.T) { + t.Parallel() + _, err := e.CancelMultipleFuturesOrders(t.Context(), &CancelFuturesOrdersRequest{}) + require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty) + _, err = e.CancelMultipleFuturesOrders(t.Context(), &CancelFuturesOrdersRequest{Symbol: futuresTradablePair}) + require.ErrorIs(t, err, order.ErrOrderIDNotSet) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelMultipleFuturesOrders(generateContext(t), &CancelFuturesOrdersRequest{Symbol: futuresTradablePair, OrderIDs: []string{"331378951169769472", "331378951182352384", "331378951199129601"}}) + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCancelFuturesOrders(t *testing.T) { + t.Parallel() + _, err := e.CancelFuturesOrders(t.Context(), currency.EMPTYPAIR, "BUY") + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) + } + result, err := e.CancelFuturesOrders(generateContext(t), futuresTradablePair, "BUY") + assert.NoError(t, err) + assert.NotNil(t, result) +} + +func TestCloseAtMarketPrice(t *testing.T) { + t.Parallel() + _, err := e.CloseAtMarketPrice(t.Context(), currency.EMPTYPAIR, "", "", "") + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + _, err = e.CloseAtMarketPrice(t.Context(), futuresTradablePair, "", "", "") + require.ErrorIs(t, err, margin.ErrInvalidMarginType) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + _, err = e.CloseAtMarketPrice(generateContext(t), futuresTradablePair, "CROSS", "", "") + require.NoError(t, err) } -func TestModifyOrder(t *testing.T) { +func TestCloseAllPositionsAtMarketPrice(t *testing.T) { t.Parallel() if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) - } - - _, err := e.ModifyOrder(t.Context(), &order.Modify{ - OrderID: "1337", - Price: 1337, - AssetType: asset.Spot, - Pair: currency.NewBTCUSDT(), - }) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil && mockTests: - t.Error("ModifyOrder() error", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("ModifyOrder() error cannot be nil") - case mockTests && err != nil: - t.Error("Mock ModifyOrder() err", err) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + result, err := e.CloseAllPositionsAtMarketPrice(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestWithdraw(t *testing.T) { +func TestGetCurrentFuturesOrders(t *testing.T) { t.Parallel() - withdrawCryptoRequest := withdraw.Request{ - Exchange: e.Name, - Crypto: withdraw.CryptoRequest{ - Address: core.BitcoinDonationAddress, - FeeAmount: 0, - }, - Amount: -1, - Currency: currency.LTC, - Description: "WITHDRAW IT ALL", - TradePassword: "Password", - } if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetCurrentFuturesOrders(generateContext(t), futuresTradablePair, "SELL", "1234123", "NEXT", 331382472929705985, 0, 0) + assert.NoError(t, err) + assert.NotNil(t, result) - _, err := e.WithdrawCryptocurrencyFunds(t.Context(), - &withdrawCryptoRequest) - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Errorf("Withdraw failed to be placed: %v", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("Expecting an error when no keys are set") - case mockTests && err == nil: - t.Error("should error due to invalid amount") - } + result, err = e.GetCurrentFuturesOrders(generateContext(t), futuresTradablePair, "SELL", "client-given-order-id", "NEXT", 0, 331382472929705985, 100) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestWithdrawFiat(t *testing.T) { +func TestGetOrderExecutionDetails(t *testing.T) { t.Parallel() + startTime, endTime := time.UnixMilli(1743615790295), time.UnixMilli(1743702190295) + _, err := e.GetOrderExecutionDetails(generateContext(t), order.Sell, currency.EMPTYPAIR, "", "", "NEXT", endTime, startTime, 0, 100) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour*24), time.Now() } + result, err := e.GetOrderExecutionDetails(generateContext(t), order.Buy, futuresTradablePair, "331381604734197760", "polo331381602863284224", "NEXT", startTime, endTime, 1, 100) + assert.NoError(t, err) + assert.NotNil(t, result) +} - var withdrawFiatRequest withdraw.Request - _, err := e.WithdrawFiatFunds(t.Context(), &withdrawFiatRequest) - if err != common.ErrFunctionNotSupported { - t.Errorf("Expected '%v', received: '%v'", - common.ErrFunctionNotSupported, err) +func TestGetFuturesOrderHistory(t *testing.T) { + t.Parallel() + startTime, endTime := time.UnixMilli(1743615790295), time.UnixMilli(1743702190295) + _, err := e.GetFuturesOrderHistory(generateContext(t), currency.EMPTYPAIR, order.UnknownSide, "LIMIT", "PARTIALLY_CANCELED", "", "", "PREV", endTime, startTime, 0, 100) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour*24), time.Now() } + result, err := e.GetFuturesOrderHistory(generateContext(t), futuresTradablePair, order.Sell, "LIMIT", "PARTIALLY_CANCELED", "331381604734197760", "polo331381602863284224", "PREV", startTime, endTime, 1, 100) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestWithdrawInternationalBank(t *testing.T) { +func TestGetFuturesCurrentPosition(t *testing.T) { t.Parallel() if !mockTests { - sharedtestvalues.SkipTestIfCannotManipulateOrders(t, e, canManipulateRealOrders) + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetFuturesCurrentPosition(generateContext(t), currency.EMPTYPAIR) + require.NoError(t, err) + assert.NotNil(t, result) - var withdrawFiatRequest withdraw.Request - _, err := e.WithdrawFiatFundsToInternationalBank(t.Context(), - &withdrawFiatRequest) - if err != common.ErrFunctionNotSupported { - t.Errorf("Expected '%v', received: '%v'", - common.ErrFunctionNotSupported, err) - } + result, err = e.GetFuturesCurrentPosition(generateContext(t), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetDepositAddress(t *testing.T) { +func TestGetFuturesPositionHistory(t *testing.T) { t.Parallel() - _, err := e.GetDepositAddress(t.Context(), currency.USDT, "", "USDTETH") - switch { - case sharedtestvalues.AreAPICredentialsSet(e) && err != nil: - t.Error("GetDepositAddress()", err) - case !sharedtestvalues.AreAPICredentialsSet(e) && !mockTests && err == nil: - t.Error("GetDepositAddress() cannot be nil") - case mockTests && err != nil: - t.Error("Mock GetDepositAddress() err", err) + startTime, endTime := time.UnixMilli(1743615790295), time.UnixMilli(1743702190295) + _, err := e.GetFuturesPositionHistory(generateContext(t), currency.EMPTYPAIR, "ISOLATED", "LONG", "NEXT", endTime, startTime, 0, 100) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + startTime, endTime = time.Now().Add(-time.Hour*24), time.Now() } + result, err := e.GetFuturesPositionHistory(generateContext(t), futuresTradablePair, "ISOLATED", "LONG", "NEXT", startTime, endTime, 1, 100) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGenerateNewAddress(t *testing.T) { +func TestAdjustMarginForIsolatedMarginTradingPositions(t *testing.T) { t.Parallel() - sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + _, err := e.AdjustMarginForIsolatedMarginTradingPositions(t.Context(), currency.EMPTYPAIR, "", "ADD", 123) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + _, err = e.AdjustMarginForIsolatedMarginTradingPositions(t.Context(), futuresTradablePair, "", "ADD", 0) + require.ErrorIs(t, err, limits.ErrAmountBelowMin) + _, err = e.AdjustMarginForIsolatedMarginTradingPositions(t.Context(), futuresTradablePair, "", "", 123) + require.ErrorIs(t, err, errInvalidMarginAdjustType) - _, err := e.GenerateNewAddress(t.Context(), currency.XRP.String()) - if err != nil { - t.Fatal(err) + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + _, err = e.AdjustMarginForIsolatedMarginTradingPositions(generateContext(t), futuresTradablePair, "", "ADD", 123) + require.NoError(t, err) } -// TestWsAuth receives a message only on failure -func TestWsAuth(t *testing.T) { +func TestGetFuturesLeverage(t *testing.T) { t.Parallel() - if !e.Websocket.IsEnabled() && !e.API.AuthenticatedWebsocketSupport || !sharedtestvalues.AreAPICredentialsSet(e) { - t.Skip(websocket.ErrWebsocketNotEnabled.Error()) - } - var dialer gws.Dialer - err := e.Websocket.Conn.Dial(t.Context(), &dialer, http.Header{}) - if err != nil { - t.Fatal(err) - } - go e.wsReadData(t.Context()) - creds, err := e.GetCredentials(t.Context()) - if err != nil { - t.Fatal(err) - } - err = e.wsSendAuthorisedCommand(t.Context(), creds.Secret, creds.Key, "subscribe") - if err != nil { - t.Fatal(err) - } - timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout) - select { - case response := <-e.Websocket.DataHandler.C: - t.Error(response) - case <-timer.C: - } - timer.Stop() -} + _, err := e.GetFuturesLeverage(t.Context(), currency.EMPTYPAIR, "ISOLATED") + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) -func TestWsSubAck(t *testing.T) { - pressXToJSON := []byte(`[1002, 1]`) - err := e.wsHandleData(t.Context(), pressXToJSON) - if err != nil { - t.Error(err) + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetFuturesLeverage(generateContext(t), futuresTradablePair, "ISOLATED") + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestWsTicker(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } - pressXToJSON := []byte(`[1002, null, [ 50, "382.98901522", "381.99755898", "379.41296309", "-0.04312950", "14969820.94951828", "38859.58435407", 0, "412.25844455", "364.56122072" ] ]`) - err = e.wsHandleData(t.Context(), pressXToJSON) - if err != nil { - t.Error(err) +func TestSetFuturesLeverage(t *testing.T) { + t.Parallel() + _, err := e.SetFuturesLeverage(t.Context(), currency.EMPTYPAIR, "CROSS", "LONG", 10) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + _, err = e.SetFuturesLeverage(t.Context(), futuresTradablePair, "", "LONG", 10) + require.ErrorIs(t, err, margin.ErrInvalidMarginType) + _, err = e.SetFuturesLeverage(t.Context(), futuresTradablePair, "CROSS", "", 10) + require.ErrorIs(t, err, order.ErrSideIsInvalid) + _, err = e.SetFuturesLeverage(t.Context(), futuresTradablePair, "CROSS", "LONG", 0) + require.ErrorIs(t, err, order.ErrSubmitLeverageNotSupported) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + _, err = e.SetFuturesLeverage(generateContext(t), futuresTradablePair, "CROSS", "LONG", 10) + require.NoError(t, err) } -func TestWsExchangeVolume(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } - pressXToJSON := []byte(`[1003,null,["2018-11-07 16:26",5804,{"BTC":"3418.409","ETH":"2645.921","USDT":"10832502.689","USDC":"1578020.908"}]]`) - err = e.wsHandleData(t.Context(), pressXToJSON) - if err != nil { - t.Error(err) +func TestSwitchPositionMode(t *testing.T) { + t.Parallel() + err := e.SwitchPositionMode(t.Context(), "") + require.ErrorIs(t, err, errInvalidPositionMode) + + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) } + err = e.SwitchPositionMode(generateContext(t), "HEDGE") + require.NoError(t, err) } -func TestWsTrades(t *testing.T) { - e.SetSaveTradeDataStatus(true) - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } - pressXToJSON := []byte(`[14, 8768, [["t", "42706057", 1, "0.05567134", "0.00181421", 1522877119]]]`) - err = e.wsHandleData(t.Context(), pressXToJSON) - if err != nil { - t.Error(err) +func TestGetPositionMode(t *testing.T) { + t.Parallel() + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetPositionMode(generateContext(t)) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestWsPriceAggregateOrderbook(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } - pressXToJSON := []byte(`[50,141160924,[["i",{"currencyPair":"BTC_LTC","orderBook":[{"0.002784":"17.55","0.002786":"1.47","0.002792":"13.25","0.0028":"0.21","0.002804":"0.02","0.00281":"1.5","0.002811":"258.82","0.002812":"3.81","0.002817":"0.06","0.002824":"3","0.002825":"0.02","0.002836":"18.01","0.002837":"0.03","0.00284":"0.03","0.002842":"12.7","0.00285":"0.02","0.002852":"0.02","0.002855":"1.3","0.002857":"15.64","0.002864":"0.01"},{"0.002782":"45.93","0.002781":"1.46","0.002774":"13.34","0.002773":"0.04","0.002771":"0.05","0.002765":"6.21","0.002764":"3","0.00276":"10.77","0.002758":"3.11","0.002754":"0.02","0.002751":"288.94","0.00275":"24.06","0.002745":"187.27","0.002743":"0.04","0.002742":"0.96","0.002731":"0.06","0.00273":"12.13","0.002727":"0.02","0.002725":"0.03","0.002719":"1.09"}]}, "1692080077892"]]]`) - err = e.wsHandleData(t.Context(), pressXToJSON) - if err != nil { - t.Error(err) - } +func TestGetUserPositionRiskLimit(t *testing.T) { + t.Parallel() + _, err := e.GetUserPositionRiskLimit(t.Context(), currency.EMPTYPAIR, "CROSS", "LONG") + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - pressXToJSON = []byte(`[50,141160925,[["o",1,"0.002742","0", "1692080078806"],["o",1,"0.002718","0.02", "1692080078806"]]]`) - err = e.wsHandleData(t.Context(), pressXToJSON) - if err != nil { - t.Error(err) + if !mockTests { + sharedtestvalues.SkipTestIfCredentialsUnset(t, e) } + result, err := e.GetUserPositionRiskLimit(t.Context(), futuresTradablePair, "CROSS", "LONG") + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetHistoricCandles(t *testing.T) { +func TestGetFuturesOrderBook(t *testing.T) { t.Parallel() + _, err := e.GetFuturesOrderBook(t.Context(), currency.EMPTYPAIR, 100, 100) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - _, err := e.GetHistoricCandles(t.Context(), testPair, asset.Spot, kline.FiveMin, time.Unix(1588741402, 0), time.Unix(1588745003, 0)) + result, err := e.GetFuturesOrderBook(t.Context(), futuresTradablePair, 100, 10) assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetHistoricCandlesExtended(t *testing.T) { +func TestGetFuturesKlineData(t *testing.T) { t.Parallel() + _, err := e.GetFuturesKlineData(t.Context(), currency.EMPTYPAIR, kline.FiveMin, time.Time{}, time.Time{}, 100) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + startTime, endTime := time.UnixMilli(1743615790295), time.UnixMilli(1743702190295) + _, err = e.GetFuturesKlineData(t.Context(), futuresTradablePair, kline.FiveMin, endTime, startTime, 100) + require.ErrorIs(t, err, common.ErrStartAfterEnd) - _, err := e.GetHistoricCandlesExtended(t.Context(), testPair, asset.Spot, kline.FiveMin, time.Unix(1588741402, 0), time.Unix(1588745003, 0)) + _, err = e.GetFuturesKlineData(t.Context(), futuresTradablePair, kline.HundredMilliseconds, startTime, endTime, 100) + require.ErrorIs(t, err, kline.ErrUnsupportedInterval) + + _, err = e.GetFuturesKlineData(t.Context(), futuresTradablePair, kline.HundredMilliseconds, endTime, startTime, 100) + require.ErrorIs(t, err, common.ErrStartAfterEnd) + + if !mockTests { + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() + } + result, err := e.GetFuturesKlineData(t.Context(), futuresTradablePair, kline.FiveMin, startTime, endTime, 100) assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetRecentTrades(t *testing.T) { +func TestGetFuturesExecution(t *testing.T) { t.Parallel() - if mockTests { - t.Skip("relies on time.Now()") - } - _, err := e.GetRecentTrades(t.Context(), currency.NewPair(currency.BTC, currency.XMR), asset.Spot) + _, err := e.GetFuturesExecution(t.Context(), currency.EMPTYPAIR, 0) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) + + result, err := e.GetFuturesExecution(t.Context(), futuresTradablePair, 5) assert.NoError(t, err) + assert.NotNil(t, result) } -func TestGetHistoricTrades(t *testing.T) { +func TestGetLiquidationOrder(t *testing.T) { t.Parallel() + startTime, endTime := time.UnixMilli(1764664401864), time.UnixMilli(1764668001864) + _, err := e.GetLiquidationOrder(t.Context(), futuresTradablePair, "NEXT", endTime, startTime, 0, 0) + require.ErrorIs(t, err, common.ErrStartAfterEnd) - tStart := time.Date(2020, 6, 6, 0, 0, 0, 0, time.UTC) - tEnd := time.Date(2020, 6, 6, 1, 0, 0, 0, time.UTC) if !mockTests { - tmNow := time.Now() - tStart = time.Date(tmNow.Year(), tmNow.Month()-3, 6, 0, 0, 0, 0, time.UTC) - tEnd = time.Date(tmNow.Year(), tmNow.Month()-3, 7, 0, 0, 0, 0, time.UTC) + startTime, endTime = time.Now().Add(-time.Hour), time.Now() } - _, err := e.GetHistoricTrades(t.Context(), currency.NewPair(currency.BTC, currency.XMR), asset.Spot, tStart, tEnd) + result, err := e.GetLiquidationOrder(t.Context(), futuresTradablePair, "NEXT", startTime, endTime, 1, 100) assert.NoError(t, err) + assert.NotNil(t, result) } -func TestProcessAccountMarginPosition(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } +func TestGetFuturesMarket(t *testing.T) { + t.Parallel() + result, err := e.GetFuturesMarket(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - margin := []byte(`[1000,"",[["m", 23432933, 28, "-0.06000000"]]]`) - err = e.wsHandleData(t.Context(), margin) - require.ErrorIs(t, err, errNotEnoughData) +func TestGetFuturesIndexPrice(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesIndexPrice(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - margin = []byte(`[1000,"",[["m", "23432933", 28, "-0.06000000", null]]]`) - err = e.wsHandleData(t.Context(), margin) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetFuturesIndexPrice(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - margin = []byte(`[1000,"",[["m", 23432933, "28", "-0.06000000", null]]]`) - err = e.wsHandleData(t.Context(), margin) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetFuturesIndexPrices(t *testing.T) { + t.Parallel() + result, err := e.GetFuturesIndexPrices(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} - margin = []byte(`[1000,"",[["m", 23432933, 28, -0.06000000, null]]]`) - err = e.wsHandleData(t.Context(), margin) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetIndexPriceComponents(t *testing.T) { + t.Parallel() + _, err := e.GetIndexPriceComponents(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - margin = []byte(`[1000,"",[["m", 23432933, 28, "-0.06000000", null]]]`) - err = e.wsHandleData(t.Context(), margin) - if err != nil { - t.Fatal(err) - } + result, err := e.GetIndexPriceComponents(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestProcessAccountPendingOrder(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } +func TestGetInstrumentsIndexPriceComponents(t *testing.T) { + t.Parallel() + result, err := e.GetAllIndexPriceComponents(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} - pending := []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000","0"]]]`) - err = e.wsHandleData(t.Context(), pending) - require.ErrorIs(t, err, errNotEnoughData) +func TestGetIndexPriceKlineData(t *testing.T) { + t.Parallel() + _, err := e.GetIndexPriceKlineData(t.Context(), currency.EMPTYPAIR, kline.FiveMin, time.Time{}, time.Time{}, 10) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - pending = []byte(`[1000,"",[["p","431682155857",127,"1000.00000000","1.00000000","0",null]]]`) - err = e.wsHandleData(t.Context(), pending) - require.ErrorIs(t, err, errTypeAssertionFailure) + _, err = e.GetIndexPriceKlineData(t.Context(), futuresTradablePair, kline.HundredMilliseconds, time.Time{}, time.Time{}, 10) + require.ErrorIs(t, err, kline.ErrUnsupportedInterval) - pending = []byte(`[1000,"",[["p",431682155857,"127","1000.00000000","1.00000000","0",null]]]`) - err = e.wsHandleData(t.Context(), pending) - require.ErrorIs(t, err, errTypeAssertionFailure) + startTime, endTime := time.UnixMilli(1764930174763), time.UnixMilli(1765290174763) + _, err = e.GetIndexPriceKlineData(t.Context(), futuresTradablePair, kline.FourHour, endTime, startTime, 10) + require.ErrorIs(t, err, common.ErrStartAfterEnd) - pending = []byte(`[1000,"",[["p",431682155857,127,1000.00000000,"1.00000000","0",null]]]`) - err = e.wsHandleData(t.Context(), pending) - require.ErrorIs(t, err, errTypeAssertionFailure) + if !mockTests { + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() + } + result, err := e.GetIndexPriceKlineData(t.Context(), futuresTradablePair, kline.FourHour, startTime, endTime, 10) + assert.NoError(t, err) + assert.NotNil(t, result) +} - pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000",1.00000000,"0",null]]]`) - err = e.wsHandleData(t.Context(), pending) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetPremiumIndexKlineData(t *testing.T) { + t.Parallel() + _, err := e.GetPremiumIndexKlineData(t.Context(), currency.EMPTYPAIR, kline.FiveMin, time.Time{}, time.Time{}, 10) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000",0,null]]]`) - err = e.wsHandleData(t.Context(), pending) - require.ErrorIs(t, err, errTypeAssertionFailure) + _, err = e.GetPremiumIndexKlineData(t.Context(), futuresTradablePair, kline.HundredMilliseconds, time.Time{}, time.Time{}, 10) + require.ErrorIs(t, err, kline.ErrUnsupportedInterval) - pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000","0",null]]]`) - err = e.wsHandleData(t.Context(), pending) - if err != nil { - t.Fatal(err) - } + startTime, endTime := time.UnixMilli(1764930174763), time.UnixMilli(1765290174763) + _, err = e.GetPremiumIndexKlineData(t.Context(), futuresTradablePair, kline.FourHour, endTime, startTime, 10) + require.ErrorIs(t, err, common.ErrStartAfterEnd) - // Unmatched pair in system - pending = []byte(`[1000,"",[["p",431682155857,666,"1000.00000000","1.00000000","0",null]]]`) - err = e.wsHandleData(t.Context(), pending) - if err != nil { - t.Fatal(err) + if !mockTests { + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() } + result, err := e.GetPremiumIndexKlineData(t.Context(), futuresTradablePair, kline.FourHour, startTime, endTime, 10) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestProcessAccountOrderUpdate(t *testing.T) { - orderUpdate := []byte(`[1000,"",[["o",431682155857,"0.00000000","f"]]]`) - err := e.wsHandleData(t.Context(), orderUpdate) - require.ErrorIs(t, err, errNotEnoughData) - - orderUpdate = []byte(`[1000,"",[["o","431682155857","0.00000000","f",null]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - require.ErrorIs(t, err, errTypeAssertionFailure) - - orderUpdate = []byte(`[1000,"",[["o",431682155857,0.00000000,"f",null]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetFuturesMarkPrice(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesMarkPrice(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000",123,null]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetFuturesMarkPrice(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","c",null]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - require.ErrorIs(t, err, errNotEnoughData) +func TestGetFuturesMarkPrices(t *testing.T) { + t.Parallel() + result, err := e.GetFuturesMarkPrices(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) +} - orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.50000000","c",null,"0.50000000"]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - if err != nil { - t.Fatal(err) - } +func TestGetMarkPriceKlineData(t *testing.T) { + t.Parallel() + _, err := e.GetMarkPriceKlineData(t.Context(), currency.EMPTYPAIR, kline.FiveMin, time.Time{}, time.Time{}, 10) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","c",null,"1.00000000"]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - if err != nil { - t.Fatal(err) - } + _, err = e.GetMarkPriceKlineData(t.Context(), futuresTradablePair, kline.HundredMilliseconds, time.Time{}, time.Time{}, 10) + require.ErrorIs(t, err, kline.ErrUnsupportedInterval) - orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.50000000","f",null]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - if err != nil { - t.Fatal(err) - } + startTime, endTime := time.UnixMilli(1764930174763), time.UnixMilli(1765290174763) + _, err = e.GetMarkPriceKlineData(t.Context(), futuresTradablePair, kline.FourHour, endTime, startTime, 10) + require.ErrorIs(t, err, common.ErrStartAfterEnd) - orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","s",null]]]`) - err = e.wsHandleData(t.Context(), orderUpdate) - if err != nil { - t.Fatal(err) + if !mockTests { + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() } + result, err := e.GetMarkPriceKlineData(t.Context(), futuresTradablePair, kline.FourHour, startTime, endTime, 10) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestProcessAccountOrderLimit(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } - - accountTrade := []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000"]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errNotEnoughData) +func TestGetFuturesAllProducts(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesAllProducts(t.Context(), currency.EMPTYPAIR) + require.NoError(t, err) - accountTrade = []byte(`[1000,"",[["n","127",431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetFuturesAllProducts(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - accountTrade = []byte(`[1000,"",[["n",127,"431682155857","0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetFuturesProduct(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesProduct(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - accountTrade = []byte(`[1000,"",[["n",127,431682155857,0,"1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetFuturesProduct(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0",1000.00000000,"1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetFuturesCurrentFundingRate(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesCurrentFundingRate(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000",1.00000000,"2021-04-13 07:19:56","1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetFuturesCurrentFundingRate(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000",1234,"1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetFuturesHistoricalFundingRates(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesHistoricalFundingRates(t.Context(), currency.EMPTYPAIR, time.Time{}, time.Time{}, 100) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56",1.00000000,null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - require.ErrorIs(t, err, errTypeAssertionFailure) + startTime, endTime := time.UnixMilli(1743615790295), time.UnixMilli(1743702190295) + _, err = e.GetFuturesHistoricalFundingRates(t.Context(), futuresTradablePair, endTime, startTime, 100) + require.ErrorIs(t, err, common.ErrStartAfterEnd) - accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`) - err = e.wsHandleData(t.Context(), accountTrade) - if err != nil { - t.Fatal(err) + if !mockTests { + startTime, endTime = endTime.Add(-time.Hour*24), time.Now() } + result, err := e.GetFuturesHistoricalFundingRates(t.Context(), futuresTradablePair, startTime, endTime, 100) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestProcessAccountBalanceUpdate(t *testing.T) { - err := e.loadCurrencyDetails(t.Context()) - if err != nil { - t.Error(err) - } - - balance := []byte(`[1000,"",[["b",243,"e"]]]`) - err = e.wsHandleData(t.Context(), balance) - require.ErrorIs(t, err, errNotEnoughData) - - balance = []byte(`[1000,"",[["b","243","e","-1.00000000"]]]`) - err = e.wsHandleData(t.Context(), balance) - require.ErrorIs(t, err, errTypeAssertionFailure) - - balance = []byte(`[1000,"",[["b",243,1234,"-1.00000000"]]]`) - err = e.wsHandleData(t.Context(), balance) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetContractOpenInterest(t *testing.T) { + t.Parallel() + _, err := e.GetContractOpenInterest(t.Context(), currency.EMPTYPAIR) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - balance = []byte(`[1000,"",[["b",243,"e",-1.00000000]]]`) - err = e.wsHandleData(t.Context(), balance) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetContractOpenInterest(t.Context(), futuresTradablePair) + assert.NoError(t, err) + assert.NotNil(t, result) +} - ctx := accounts.DeployCredentialsToContext(t.Context(), &accounts.Credentials{Key: "test", Secret: "test"}) - balance = []byte(`[1000,"",[["b",243,"e","-1.00000000"]]]`) - err = e.wsHandleData(ctx, balance) - require.NoError(t, err, "wsHandleData must not error") +func TestGetInsuranceFund(t *testing.T) { + t.Parallel() + result, err := e.GetInsuranceFund(t.Context()) + assert.NoError(t, err) + assert.NotNil(t, result) } -func TestProcessAccountTrades(t *testing.T) { - accountTrades := []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345"]]]`) - err := e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errNotEnoughData) +func TestGetFuturesRiskLimit(t *testing.T) { + t.Parallel() + _, err := e.GetFuturesRiskLimit(t.Context(), currency.EMPTYPAIR, "", 1) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - accountTrades = []byte(`[1000,"",[["t", "12345", "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetFuturesRiskLimit(t.Context(), futuresTradablePair, "", 0) + require.NoError(t, err) + assert.NotNil(t, result) - accountTrades = []byte(`[1000,"",[["t", 12345, 0.03000000, "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err = e.GetFuturesRiskLimit(t.Context(), futuresTradablePair, "CROSS", 1) + assert.NoError(t, err) + assert.NotNil(t, result) +} - accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", 0.50000000, "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestGetContractLimitPrice(t *testing.T) { + t.Parallel() + _, err := e.GetContractLimitPrice(t.Context(), []currency.Pair{currency.EMPTYPAIR}) + require.ErrorIs(t, err, currency.ErrSymbolStringEmpty) - accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, 0.00000375, "2018-09-08 05:54:09", "12345", "0.015"]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errTypeAssertionFailure) + result, err := e.GetContractLimitPrice(t.Context(), []currency.Pair{currency.NewPairWithDelimiter("DOT", "USDT_PERP", "_"), currency.EMPTYPAIR, futuresTradablePair}) + assert.NoError(t, err) + assert.NotNil(t, result) +} - accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, 0.0000037, "2018-09-08 05:54:09", "12345", "0.015"]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestIntervalString(t *testing.T) { + t.Parallel() + params := map[kline.Interval]struct { + IntervalString string + Error error + }{ + kline.OneMin: {IntervalString: "MINUTE_1"}, + kline.FiveMin: {IntervalString: "MINUTE_5"}, + kline.TenMin: {IntervalString: "MINUTE_10"}, + kline.FifteenMin: {IntervalString: "MINUTE_15"}, + kline.ThirtyMin: {IntervalString: "MINUTE_30"}, + kline.OneHour: {IntervalString: "HOUR_1"}, + kline.TwoHour: {IntervalString: "HOUR_2"}, + kline.FourHour: {IntervalString: "HOUR_4"}, + kline.SixHour: {IntervalString: "HOUR_6"}, + kline.EightHour: {IntervalString: "HOUR_8"}, + kline.TwelveHour: {IntervalString: "HOUR_12"}, + kline.OneDay: {IntervalString: "DAY_1"}, + kline.ThreeDay: {IntervalString: "DAY_3"}, + kline.OneWeek: {IntervalString: "WEEK_1"}, + kline.OneMonth: {IntervalString: "MONTH_1"}, + kline.TwoWeek: {Error: kline.ErrUnsupportedInterval}, + } + for key, val := range params { + s, err := intervalToString(key) + require.Equal(t, val.IntervalString, s) + require.ErrorIs(t, err, val.Error, err) + } +} - accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", 12345, "12345", 0.015]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - require.ErrorIs(t, err, errTypeAssertionFailure) +func TestOrderStateString(t *testing.T) { + t.Parallel() + orderStatusToStringMap := map[string]order.Status{ + "NEW": order.New, + "FAILED": order.Rejected, + "FILLED": order.Filled, + "CANCELED": order.Cancelled, + "PENDING_Cancel": order.PendingCancel, + "abcd": order.UnknownStatus, + "PARTIALLY_FILLED": order.PartiallyFilled, + "PARTIALLY_CANCELED": order.PartiallyCancelled, + } + for k, v := range orderStatusToStringMap { + result := orderStateFromString(k) + assert.Equal(t, v, result) + } +} - accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`) - err = e.wsHandleData(t.Context(), accountTrades) - if err != nil { - t.Fatal(err) +func generateContext(tb testing.TB) context.Context { + tb.Helper() + if mockTests { + return accounts.DeployCredentialsToContext(tb.Context(), &accounts.Credentials{ + Key: "abcde", + Secret: "fghij", + }) } + return tb.Context() +} + +func TestUnmarshalToFuturesCandle(t *testing.T) { + t.Parallel() + data := []byte(`[ [ "58651", "58651", "58651", "58651", "0", "0", "0", "1719975420000", "1719975479999" ], [ "58651", "58651", "58651", "58651", "0", "0", "0", "1719975480000", "1719975539999" ]]`) + var resp []FuturesCandle + err := json.Unmarshal(data, &resp) + require.NoError(t, err) + require.Len(t, resp, 2) + assert.Equal(t, 58651.0, resp[0].LowestPrice.Float64()) + assert.Equal(t, 58651.0, resp[0].HighestPrice.Float64()) + assert.Equal(t, 58651.0, resp[0].OpeningPrice.Float64()) + assert.Equal(t, 58651.0, resp[0].ClosingPrice.Float64()) + assert.Equal(t, 0.0, resp[0].QuoteAmount.Float64()) + assert.Equal(t, 0.0, resp[0].BaseAmount.Float64()) + assert.Equal(t, 0.0, resp[0].Trades.Float64()) + assert.Equal(t, time.UnixMilli(1719975420000), resp[0].StartTime.Time()) + assert.Equal(t, time.UnixMilli(1719975479999), resp[0].EndTime.Time()) } -func TestProcessAccountKilledOrder(t *testing.T) { - kill := []byte(`[1000,"",[["k", 1337]]]`) - err := e.wsHandleData(t.Context(), kill) - require.ErrorIs(t, err, errNotEnoughData) +func TestHandleFuturesSubscriptions(t *testing.T) { + t.Parallel() + enabledPairs, err := e.GetEnabledPairs(asset.Futures) + require.NoError(t, err) - kill = []byte(`[1000,"",[["k", "1337", null]]]`) - err = e.wsHandleData(t.Context(), kill) - require.ErrorIs(t, err, errTypeAssertionFailure) + subscs, err := subscription.List{ + { + Asset: asset.Futures, + Channel: subscription.TickerChannel, + Pairs: enabledPairs, + }, + { + Asset: asset.Futures, + Channel: subscription.OrderbookChannel, + Pairs: enabledPairs, + }, + }.ExpandTemplates(e) + require.NoError(t, err) - kill = []byte(`[1000,"",[["k", 1337, null]]]`) - err = e.wsHandleData(t.Context(), kill) - if err != nil { - t.Fatal(err) + payloads := []*SubscriptionPayload{ + {Event: "subscribe", Channel: []string{"tickers"}, Symbols: enabledPairs.Strings()}, + {Event: "subscribe", Channel: []string{"book_lv2"}, Symbols: enabledPairs.Strings()}, + } + for i, s := range subscs { + result, err := e.handleSubscription("subscribe", s) + require.NoError(t, err) + require.Equal(t, payloads[i], result) } } -func TestGetCompleteBalances(t *testing.T) { +func TestWebsocketSubmitOrders(t *testing.T) { t.Parallel() - if !mockTests { - sharedtestvalues.SkipTestIfCredentialsUnset(t, e) - } - _, err := e.GetCompleteBalances(t.Context()) - if err != nil { - t.Fatal(err) - } + _, err := e.WebsocketSubmitOrders(t.Context(), nil) + require.ErrorIs(t, err, common.ErrFunctionNotSupported) } -func TestUpdateTicker(t *testing.T) { +func TestWebsocketModifyOrder(t *testing.T) { t.Parallel() - _, err := e.UpdateTicker(t.Context(), testPair, asset.Spot) - assert.NoError(t, err) + _, err := e.WebsocketModifyOrder(t.Context(), nil) + require.ErrorIs(t, err, common.ErrFunctionNotSupported) } -func TestUpdateTickers(t *testing.T) { +func TestOrderbookLevelFromSlice(t *testing.T) { t.Parallel() - err := e.UpdateTickers(t.Context(), asset.Spot) - if err != nil { - t.Error(err) + var obData []types.Number + data := []byte(`["88350.22","0.019937","88376.19","0.000203","88376.58","0.000696"]`) + err := json.Unmarshal(data, &obData) + require.NoError(t, err) + + target := []orderbook.Level{{Price: 88350.22, Amount: 0.019937}, {Price: 88376.19, Amount: 0.000203}, {Price: 88376.58, Amount: 0.000696}} + obLevels := orderbookLevelFromSlice(obData) + require.Len(t, obLevels, len(target)) + for x := range obLevels { + require.Equal(t, target[x].Price, obLevels[x].Price) + require.Equal(t, target[x].Amount, obLevels[x].Amount) } } -func TestGetAvailableTransferChains(t *testing.T) { +var channelIntervals = []*struct { + input string + channel string + interval kline.Interval + err error +}{ + {input: "mark_candles", channel: "mark_candles", err: kline.ErrInvalidInterval}, + {input: "mark_candles_hour_1", channel: "mark_candles", interval: kline.OneHour}, + {input: "mark_price_candles_minute_1", channel: "mark_price_candles", interval: kline.OneMin}, + {input: "mark_candles_minute_30", channel: "mark_candles", interval: kline.ThirtyMin}, + {input: "index_candles_hour_4", channel: "index_candles", interval: kline.FourHour}, + {input: "candles_minute_30", channel: "candles", interval: kline.ThirtyMin}, + {input: "candles_minute_15", channel: "candles", interval: kline.FifteenMin}, + {input: "candles_minute_10", channel: "candles", interval: kline.TenMin}, + {input: "candles_minute_5", channel: "candles", interval: kline.FiveMin}, + {input: "mark_candles_day_3", channel: "mark_candles", interval: kline.ThreeDay}, + {input: "mark_candles_week_1", channel: "mark_candles", interval: kline.OneWeek}, + {input: "mark_candles_hour_abc", channel: "mark_candles", interval: kline.Interval(0), err: kline.ErrUnsupportedInterval}, +} + +func TestChannelToIntervalSplit(t *testing.T) { t.Parallel() - _, err := e.GetAvailableTransferChains(t.Context(), currency.USDT) - if err != nil { - t.Fatal(err) + for _, chd := range channelIntervals { + t.Run(chd.input, func(t *testing.T) { + t.Parallel() + c, i, err := channelToIntervalSplit(chd.input) + require.ErrorIs(t, err, chd.err) + require.Equal(t, chd.channel, c) + assert.Equal(t, chd.interval, i) + }) } } -func TestWalletActivity(t *testing.T) { +func TestStatusResponseError(t *testing.T) { t.Parallel() - sharedtestvalues.SkipTestIfCredentialsUnset(t, e) - - _, err := e.WalletActivity(t.Context(), time.Now().Add(-time.Minute), time.Now(), "") - if err != nil { - t.Error(err) - } + var p *OrderIDResponse + require.NoError(t, json.Unmarshal([]byte(`{"id": "4"}`), &p)) + require.NoError(t, json.Unmarshal([]byte(`{"id": "4","code":200}`), &p)) + require.NoError(t, p.Error()) + require.NoError(t, json.Unmarshal([]byte(`{"id": "4","code":400,"message":"this works"}`), &p)) + err, ok := any(p).(interface{ Error() error }) + require.True(t, ok) + require.ErrorContains(t, err.Error(), "this works") } -func TestCancelMultipleOrdersByIDs(t *testing.T) { +func TestConnect(t *testing.T) { t.Parallel() - sharedtestvalues.SkipTestIfCredentialsUnset(t, e) - _, err := e.CancelMultipleOrdersByIDs(t.Context(), []string{"1234"}, []string{"5678"}) - if err != nil { - t.Error(err) + if mockTests { + t.Skip(websocketMockTestsSkipped) } + require.NoError(t, e.Websocket.Connect(t.Context())) + assert.True(t, e.Websocket.IsConnected(), "websocket should be connected") } -func TestGetAccountFundingHistory(t *testing.T) { +func TestWebsocketSliceErrorCheck(t *testing.T) { t.Parallel() - sharedtestvalues.SkipTestIfCredentialsUnset(t, e) - _, err := e.GetAccountFundingHistory(t.Context()) - if err != nil { - t.Error(err) + results := []struct { + in string + hasError bool + sliceLen int + }{ + {in: `{"data":[{ "orderId": 205343650954092544, "clientOrderId": "", "message": "", "code": 200 }]}`, sliceLen: 1}, + {in: `{ "id": "123457", "data": [{ "orderId": 0, "clientOrderId": null, "message": "Currency trade disabled", "code": 21352 }] }`, hasError: true, sliceLen: 1}, + {in: `{ "id": "123457", "data": [{ "orderId": 205343650954092544, "clientOrderId": "", "message": "", "code": 200 }, { "orderId": 0, "clientOrderId": null, "message": "Currency trade disabled", "code": 21352 }] }`, hasError: true, sliceLen: 2}, + } + + response := []*WsCancelOrderResponse{} + for _, elem := range results { + require.NoError(t, json.Unmarshal([]byte(elem.in), &WebsocketResponse{Data: &response})) + assert.NotNil(t, response) + assert.Len(t, response, elem.sliceLen) + if elem.hasError { + assert.Error(t, checkForErrorInSliceResponse(response)) + } else { + assert.NoError(t, checkForErrorInSliceResponse(response)) + } } } -func TestGetWithdrawalsHistory(t *testing.T) { +func TestSendBatchValidatedAuthenticatedHTTPRequest(t *testing.T) { t.Parallel() - sharedtestvalues.SkipTestIfCredentialsUnset(t, e) + result, err := SendBatchValidatedAuthenticatedHTTPRequest[*OrderIDResponse](t.Context(), e, exchange.RestSpot, sBatchOrderEPL, http.MethodGet, "path", nil, nil) + require.Error(t, err) + assert.IsType(t, []*OrderIDResponse{}, result) +} - _, err := e.GetWithdrawalsHistory(t.Context(), currency.BTC, asset.Spot) - if err != nil { - t.Error(err) +func TestV3ResponseWrapperUnmarshal(t *testing.T) { + t.Parallel() + validResponse := []byte(`{ "code": 200, "data": [ { "amt": "103.86838", "cT": 1734354688285, "id": 105091009, "px": "103868.38", "qty": "1", "side": "sell" }, { "amt": "103.88358", "cT": 1734354660249, "id": 105091008, "px": "103883.58", "qty": "1", "side": "buy" }], "msg": "Success" }`) + var data []FuturesExecutionInfo + in := &V3ResponseWrapper{ + Data: &data, } + err := json.Unmarshal(validResponse, &in) + require.NoError(t, err) + assert.NoError(t, in.Error()) + assert.Len(t, data, 2) + + errorResponse := []byte(`{"code":24101,"msg":"Invalid symbol!","data":""}`) + err = json.Unmarshal(errorResponse, &in) + require.NoError(t, err) + assert.Error(t, in.Error()) + + in = &V3ResponseWrapper{} + validWithNoPayloadResponse := []byte(`{ "code":200, "data":{ }, "msg":"Success" }`) + err = json.Unmarshal(validWithNoPayloadResponse, &in) + require.NoError(t, err) + assert.NoError(t, in.Error()) + + in = &V3ResponseWrapper{} + validWithNoPayloadResponse = []byte(`{"code":200,"msg":"it's Ok"}`) + err = json.Unmarshal(validWithNoPayloadResponse, &in) + require.NoError(t, err) + assert.ErrorIs(t, in.Error(), common.ErrNoResponse) } -func TestCancelBatchOrders(t *testing.T) { +func TestMarshalMarginMode(t *testing.T) { t.Parallel() - sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders) - _, err := e.CancelBatchOrders(t.Context(), []order.Cancel{ - { - OrderID: "1234", - AssetType: asset.Spot, - Pair: currency.NewBTCUSD(), - }, - }) - if err != nil { - t.Error(err) + marginModes := []MarginMode{MarginMode(margin.Multi), MarginMode(margin.Isolated), MarginMode(margin.Unset)} + data, err := json.Marshal(marginModes) + require.NoError(t, err) + assert.Equal(t, []byte(`["CROSS","ISOLATED",""]`), data) + + type sample struct { + Mode MarginMode `json:"mgnMode,omitempty"` + } + inputs := []struct { + in sample + data any + err error + }{ + {in: sample{}, data: []byte(`{}`)}, + {in: sample{Mode: MarginMode(margin.Unset)}, data: []byte(`{}`)}, + {in: sample{Mode: MarginMode(margin.Multi)}, data: []byte(`{"mgnMode":"CROSS"}`)}, + {in: sample{Mode: MarginMode(8)}, data: []byte(nil), err: margin.ErrMarginTypeUnsupported}, + } + for _, input := range inputs { + data, err = json.Marshal(&input.in) + require.ErrorIs(t, err, input.err) + assert.Equal(t, input.data, data) } } -func TestGetTimestamp(t *testing.T) { +func TestMarshalOrderType(t *testing.T) { t.Parallel() - st, err := e.GetTimestamp(t.Context()) + orderTypes := []OrderType{OrderType(order.Market), OrderType(order.Limit), OrderType(order.LimitMaker), OrderType(order.Stop), OrderType(order.StopLimit), OrderType(order.TrailingStop), OrderType(order.TrailingStopLimit), OrderType(order.AnyType), OrderType(order.UnknownType)} + data, err := json.Marshal(orderTypes) require.NoError(t, err) + assert.Equal(t, []byte(`["MARKET","LIMIT","LIMIT_MAKER","STOP","STOP_LIMIT","TRAILING_STOP","TRAILING_STOP_LIMIT","",""]`), data) - if st.IsZero() { - t.Error("expected a time") + type sample struct { + Type OrderType `json:"type,omitempty"` + } + inputs := []struct { + in sample + data any + err error + }{ + {in: sample{}, data: []byte(`{}`)}, + {in: sample{Type: OrderType(order.LimitMaker)}, data: []byte(`{"type":"LIMIT_MAKER"}`)}, + {in: sample{Type: OrderType(order.UnknownType)}, data: []byte(`{}`)}, + {in: sample{Type: OrderType(12345)}, data: []byte(nil), err: order.ErrUnsupportedOrderType}, + } + for _, input := range inputs { + data, err = json.Marshal(&input.in) + require.ErrorIs(t, err, input.err) + assert.Equal(t, input.data, data) } } -func TestGetServerTime(t *testing.T) { - t.Parallel() - st, err := e.GetServerTime(t.Context(), asset.Spot) +func TestMarshalTimeInForce(t *testing.T) { + timeInForceValues := []TimeInForce{TimeInForce(order.GoodTillCancel), TimeInForce(order.FillOrKill), TimeInForce(order.ImmediateOrCancel), TimeInForce(order.UnknownTIF)} + data, err := json.Marshal(timeInForceValues) require.NoError(t, err) + assert.Equal(t, []byte(`["GTC","FOK","IOC",""]`), data) - if st.IsZero() { - t.Error("expected a time") + type sample struct { + TIF TimeInForce `json:"tif,omitempty"` + } + inputs := []struct { + in sample + data any + err error + }{ + {in: sample{}, data: []byte(`{}`)}, + {in: sample{TIF: TimeInForce(order.FillOrKill)}, data: []byte(`{"tif":"FOK"}`)}, + {in: sample{TIF: TimeInForce(order.UnknownTIF)}, data: []byte(`{}`)}, + {in: sample{TIF: TimeInForce(1)}, data: []byte(nil), err: order.ErrInvalidTimeInForce}, + } + for _, input := range inputs { + data, err = json.Marshal(&input.in) + require.ErrorIs(t, err, input.err) + assert.Equal(t, input.data, data) } } -func TestFetchTradablePairs(t *testing.T) { +func TestUnmarshalStatusResponse(t *testing.T) { t.Parallel() - _, err := e.FetchTradablePairs(t.Context(), asset.Spot) - if err != nil { - t.Error(err) + var resp statusResponse + err := json.Unmarshal([]byte(`{"code":0 , "message": "congrats!"}`), &resp) + require.NoError(t, err) + assert.NoError(t, resp.Error()) + + err = json.Unmarshal([]byte(`{"code":4000 , "message": "something gone wrong"}`), &resp) + require.NoError(t, err) + assert.ErrorContains(t, resp.Error(), `error code: 4000; message: something gone wrong`) + + var sample *struct { + *statusResponse + Name string `json:"name"` } + err = json.Unmarshal([]byte(`{"name": "thrasher"}`), &sample) + require.NoError(t, err) + assert.NotNil(t, sample) + assert.ErrorIs(t, sample.Error(), common.ErrNoResponse) } -func TestGetCurrencyTradeURL(t *testing.T) { +func TestUnmarshalFuturesOrderIDResponse(t *testing.T) { t.Parallel() - testexch.UpdatePairsOnce(t, e) - for _, a := range e.GetAssetTypes(false) { - pairs, err := e.CurrencyPairs.GetPairs(a, false) - require.NoErrorf(t, err, "cannot get pairs for %s", a) - require.NotEmptyf(t, pairs, "no pairs for %s", a) - resp, err := e.GetCurrencyTradeURL(t.Context(), a, pairs[0]) - require.NoError(t, err) - assert.NotEmpty(t, resp) - } + var resp FuturesOrderIDResponse + err := json.Unmarshal([]byte(`{"code":0 , "msg": "congrats!"}`), &resp) + require.NoError(t, err) + assert.NoError(t, resp.Error()) + + err = json.Unmarshal([]byte(`{"code":4000 , "msg": "something gone wrong"}`), &resp) + require.NoError(t, err) + assert.ErrorContains(t, resp.Error(), `error code: 4000; message: something gone wrong`) + + var sample *FuturesOrderIDResponse + assert.ErrorIs(t, sample.Error(), common.ErrNoResponse) + + err = json.Unmarshal([]byte(`{"ordId": "1234567890"}`), &sample) + require.NoError(t, err) + assert.NotNil(t, sample) + assert.NoError(t, sample.Error()) } diff --git a/exchanges/poloniex/poloniex_types.go b/exchanges/poloniex/poloniex_types.go index e04eb7f08b9..cf23111a09d 100644 --- a/exchanges/poloniex/poloniex_types.go +++ b/exchanges/poloniex/poloniex_types.go @@ -1,385 +1,83 @@ package poloniex import ( + "fmt" "time" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/encoding/json" + "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/types" ) -// Ticker holds ticker data -type Ticker struct { - ID float64 `json:"id"` - Last float64 `json:"last,string"` - LowestAsk float64 `json:"lowestAsk,string"` - HighestBid float64 `json:"highestBid,string"` - PercentChange float64 `json:"percentChange,string"` - BaseVolume float64 `json:"baseVolume,string"` - QuoteVolume float64 `json:"quoteVolume,string"` - High24Hr float64 `json:"high24hr,string"` - Low24Hr float64 `json:"low24hr,string"` - IsFrozen uint8 `json:"isFrozen,string"` - PostOnly uint8 `json:"postOnly,string"` -} - -// OrderbookResponseAll holds the full response type orderbook -type OrderbookResponseAll struct { - Data map[string]OrderbookResponse -} +type ( + // TimeInForce wraps order.TimeInForce and implements a custom Text marshaler. + TimeInForce order.TimeInForce -// CompleteBalances holds the full balance data -type CompleteBalances map[string]CompleteBalance + // OrderType wraps order.Type and implements a custom Text marshaler. + OrderType order.Type -// OrderbookResponse is a sub-type for orderbooks -type OrderbookResponse struct { - Asks orderbook.LevelsArrayPriceAmount `json:"asks"` - Bids orderbook.LevelsArrayPriceAmount `json:"bids"` - IsFrozen string `json:"isFrozen"` - Error string `json:"error"` - Seq int64 `json:"seq"` -} + // AccountType wraps asset.Item and implements a custom Text marshaler. + AccountType asset.Item +) -// OrderbookAll contains the full range of orderbooks -type OrderbookAll struct { - Data map[string]Orderbook +// MarshalText implements the TextMarshaler interface for TimeInForce +func (t TimeInForce) MarshalText() ([]byte, error) { + tif := order.TimeInForce(t) + switch { + case tif.Is(order.GoodTillCancel): + return []byte("GTC"), nil + case tif.Is(order.FillOrKill): + return []byte("FOK"), nil + case tif.Is(order.ImmediateOrCancel): + return []byte("IOC"), nil + case tif == order.UnknownTIF: + return []byte(""), nil + } + return nil, fmt.Errorf("%w: %v", order.ErrInvalidTimeInForce, t) } -// Orderbook is a generic type golding orderbook information -type Orderbook struct { - Asks []orderbook.Level `json:"asks"` - Bids []orderbook.Level `json:"bids"` +// MarshalText implements the TextMarshaler interface for OrderType +func (o OrderType) MarshalText() ([]byte, error) { + t := order.Type(o) + switch t { + case order.Market: + return []byte("MARKET"), nil + case order.Limit: + return []byte("LIMIT"), nil + case order.LimitMaker: + return []byte("LIMIT_MAKER"), nil + case order.Stop: + return []byte("STOP"), nil + case order.StopLimit: + return []byte("STOP_LIMIT"), nil + case order.TrailingStop: + return []byte("TRAILING_STOP"), nil + case order.TrailingStopLimit: + return []byte("TRAILING_STOP_LIMIT"), nil + case order.AnyType, order.UnknownType: + return nil, nil + } + return nil, fmt.Errorf("%w: %v", order.ErrUnsupportedOrderType, o) } -// TradeHistory holds trade history data -type TradeHistory struct { - GlobalTradeID string `json:"globalTradeID"` - TradeID string `json:"tradeID"` - Date string `json:"date"` - Type string `json:"type"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Total float64 `json:"total,string"` -} - -// OrderStatus holds order status data -type OrderStatus struct { - Result json.RawMessage `json:"result"` - Success int64 `json:"success"` -} - -// OrderStatusData defines order status details -type OrderStatusData struct { - Pair string `json:"currencyPair"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Total float64 `json:"total,string"` - StartingAmount float64 `json:"startingAmount,string"` - Type string `json:"type"` - Status string `json:"status"` - Date string `json:"date"` - Fee float64 `json:"fee,string"` -} - -// OrderTrade holds order trade data -type OrderTrade struct { - Status string `json:"status"` - GlobalTradeID string `json:"globalTradeID"` - TradeID string `json:"tradeID"` - CurrencyPair string `json:"currencyPair"` - Type string `json:"type"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Total float64 `json:"total,string"` - Fee float64 `json:"fee,string"` - Date string `json:"date"` -} - -// ChartData holds kline data -type ChartData struct { - Date types.Time `json:"date"` - High types.Number `json:"high"` - Low types.Number `json:"low"` - Open types.Number `json:"open"` - Close types.Number `json:"close"` - Volume types.Number `json:"volume"` - QuoteVolume types.Number `json:"quoteVolume"` - WeightedAverage types.Number `json:"weightedAverage"` - Error string `json:"error"` -} - -// Currencies contains currency information -type Currencies struct { - ID float64 `json:"id"` - Name string `json:"name"` - HumanType string `json:"humanType"` - CurrencyType string `json:"currencyType"` - TxFee float64 `json:"txFee,string"` - MinConfirmations int64 `json:"minConf"` - DepositAddress string `json:"depositAddress"` - WithdrawalDepositDisabled uint8 `json:"disabled"` - Frozen uint8 `json:"frozen"` - HexColour string `json:"hexColor"` - Blockchain string `json:"blockchain"` - Delisted uint8 `json:"delisted"` - ParentChain string `json:"parentChain"` - IsMultiChain uint8 `json:"isMultiChain"` - IsChildChain uint8 `json:"isChildChain"` - ChildChains []string `json:"childChains"` - IsGeofenced uint8 `json:"isGeofenced"` -} - -// LoanOrder holds loan order information -type LoanOrder struct { - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - RangeMin int64 `json:"rangeMin"` - RangeMax int64 `json:"rangeMax"` -} - -// LoanOrders holds loan order information range -type LoanOrders struct { - Offers []LoanOrder `json:"offers"` - Demands []LoanOrder `json:"demands"` -} - -// CompleteBalance contains the complete balance with a btcvalue -type CompleteBalance struct { - Available float64 `json:"available,string"` - OnOrders float64 `json:"onOrders,string"` - BTCValue float64 `json:"btcValue,string"` +// MarshalText implements the TextMarshaler interface for AccountType +func (a AccountType) MarshalText() ([]byte, error) { + switch asset.Item(a) { + case asset.Spot: + return []byte("SPOT"), nil + case asset.Futures: + return []byte("FUTURES"), nil + default: + return nil, asset.ErrNotSupported + } } // DepositAddresses holds the full address per crypto-currency -type DepositAddresses struct { - Addresses map[string]string -} - -// DepositsWithdrawals holds withdrawal information -type DepositsWithdrawals struct { - Deposits []struct { - Currency string `json:"currency"` - Address string `json:"address"` - Amount float64 `json:"amount,string"` - Confirmations int64 `json:"confirmations"` - TransactionID string `json:"txid"` - Timestamp types.Time `json:"timestamp"` - Status string `json:"status"` - } `json:"deposits"` - Withdrawals []struct { - WithdrawalNumber int64 `json:"withdrawalNumber"` - Currency string `json:"currency"` - Address string `json:"address"` - Amount float64 `json:"amount,string"` - Confirmations int64 `json:"confirmations"` - TransactionID string `json:"txid"` - Timestamp types.Time `json:"timestamp"` - Status string `json:"status"` - IPAddress string `json:"ipAddress"` - } `json:"withdrawals"` -} - -// Order hold order information -type Order struct { - OrderNumber int64 `json:"orderNumber,string"` - Type string `json:"type"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Total float64 `json:"total,string"` - Date string `json:"date"` - Margin float64 `json:"margin"` -} - -// OpenOrdersResponseAll holds all open order responses -type OpenOrdersResponseAll struct { - Data map[string][]Order -} - -// OpenOrdersResponse holds open response orders -type OpenOrdersResponse struct { - Data []Order -} - -// AuthenticatedTradeHistory holds client trade history information -type AuthenticatedTradeHistory struct { - GlobalTradeID string `json:"globalTradeID"` - TradeID string `json:"tradeID"` - Date string `json:"date"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Total float64 `json:"total,string"` - Fee float64 `json:"fee,string"` - OrderNumber int64 `json:"orderNumber,string"` - Type string `json:"type"` - Category string `json:"category"` -} - -// AuthenticatedTradeHistoryAll holds the full client trade history -type AuthenticatedTradeHistoryAll struct { - Data map[string][]AuthenticatedTradeHistory -} - -// AuthenticatedTradeHistoryResponse is a response type for trade history -type AuthenticatedTradeHistoryResponse struct { - Data []AuthenticatedTradeHistory -} - -// ResultingTrades holds resultant trade information -type ResultingTrades struct { - Amount float64 `json:"amount,string"` - Date string `json:"date"` - Rate float64 `json:"rate,string"` - Total float64 `json:"total,string"` - TradeID int64 `json:"tradeID,string"` - Type string `json:"type"` -} - -// OrderResponse is a response type of trades -type OrderResponse struct { - OrderNumber int64 `json:"orderNumber,string"` - Trades []ResultingTrades `json:"resultingTrades"` -} - -// GenericResponse is a response type for exchange generic responses -type GenericResponse struct { - Success int64 `json:"success"` - Error string `json:"error"` -} - -// MoveOrderResponse is a response type for move order trades -type MoveOrderResponse struct { - Success int64 `json:"success"` - Error string `json:"error"` - OrderNumber int64 `json:"orderNumber,string"` - Trades map[string][]ResultingTrades `json:"resultingTrades"` -} - -// Withdraw holds withdraw information -type Withdraw struct { - Response string `json:"response"` - Error string `json:"error"` -} - -// Fee holds fees for specific trades -type Fee struct { - MakerFee float64 `json:"makerFee,string"` - TakerFee float64 `json:"takerFee,string"` - ThirtyDayVolume float64 `json:"thirtyDayVolume,string"` -} - -// Margin holds margin information -type Margin struct { - TotalValue float64 `json:"totalValue,string"` - ProfitLoss float64 `json:"pl,string"` - LendingFees float64 `json:"lendingFees,string"` - NetValue float64 `json:"netValue,string"` - BorrowedValue float64 `json:"totalBorrowedValue,string"` - CurrentMargin float64 `json:"currentMargin,string"` -} - -// MarginPosition holds margin positional information -type MarginPosition struct { - Amount float64 `json:"amount,string"` - Total float64 `json:"total,string"` - BasePrice float64 `json:"basePrice,string"` - LiquidationPrice float64 `json:"liquidationPrice"` - ProfitLoss float64 `json:"pl,string"` - LendingFees float64 `json:"lendingFees,string"` - Type string `json:"type"` -} - -// LoanOffer holds loan offer information -type LoanOffer struct { - ID int64 `json:"id"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Duration int64 `json:"duration"` - AutoRenew bool `json:"autoRenew"` - Date string `json:"date"` -} - -// ActiveLoans shows the full active loans on the exchange -type ActiveLoans struct { - Provided []LoanOffer `json:"provided"` - Used []LoanOffer `json:"used"` -} - -// LendingHistory holds the full lending history data -type LendingHistory struct { - ID int64 `json:"id"` - Currency string `json:"currency"` - Rate float64 `json:"rate,string"` - Amount float64 `json:"amount,string"` - Duration float64 `json:"duration,string"` - Interest float64 `json:"interest,string"` - Fee float64 `json:"fee,string"` - Earned float64 `json:"earned,string"` - Open string `json:"open"` - Close string `json:"close"` -} - -// WebsocketTicker holds ticker data for the websocket -type WebsocketTicker struct { - CurrencyPair string - Last float64 - LowestAsk float64 - HighestBid float64 - PercentChange float64 - BaseVolume float64 - QuoteVolume float64 - IsFrozen bool - High float64 - Low float64 -} - -// WebsocketTrollboxMessage holds trollbox messages and information for -// websocket -type WebsocketTrollboxMessage struct { - MessageNumber float64 - Username string - Message string - Reputation float64 -} - -type wsOp string - -const ( - wsSubscribeOp wsOp = "subscribe" - wsUnsubscribeOp wsOp = "unsubscribe" -) - -// wsCommand defines the request params after a websocket connection has been established -type wsCommand struct { - Command wsOp `json:"command"` - Channel any `json:"channel"` - APIKey string `json:"key,omitempty"` - Payload string `json:"payload,omitempty"` - Sign string `json:"sign,omitempty"` -} - -// WsTicker defines the websocket ticker response -type WsTicker struct { - LastPrice float64 - LowestAsk float64 - HighestBid float64 - PercentageChange float64 - BaseCurrencyVolume24H float64 - QuoteCurrencyVolume24H float64 - IsFrozen bool - HighestTradeIn24H float64 - LowestTradePrice24H float64 -} - -// WsTrade defines the websocket trade response -type WsTrade struct { - Symbol string - TradeID int64 - Side string - Volume float64 - Price float64 - Timestamp types.Time -} +type DepositAddresses map[string]string // WithdrawalFees the large list of predefined withdrawal fees // Prone to change, using highest value @@ -446,55 +144,364 @@ var WithdrawalFees = map[currency.Code]float64{ currency.ZEC: 0.001, } -// WsOrderUpdateResponse Authenticated Ws Account data -type WsOrderUpdateResponse struct { - OrderNumber float64 - NewAmount string +// SubscriptionResponse represents a subscription response detail +type SubscriptionResponse struct { + ID string `json:"id"` + Channel string `json:"channel"` + Data json.RawMessage `json:"data"` + Action string `json:"action"` + Event string `json:"event"` + Message string `json:"message"` } -// WsTradeNotificationResponse Authenticated Ws Account data -type WsTradeNotificationResponse struct { - TradeID float64 - Rate float64 - Amount float64 - FeeMultiplier float64 - FundingType float64 - OrderNumber float64 - TotalFee float64 - Date time.Time +// SymbolTradeLimit holds symbol's trade limit details +type SymbolTradeLimit struct { + Symbol currency.Pair `json:"symbol"` + PriceScale uint8 `json:"priceScale"` + QuantityScale uint8 `json:"quantityScale"` + QuoteAmountScale uint8 `json:"amountScale"` + MinQuantity types.Number `json:"minQuantity"` + MinAmount types.Number `json:"minAmount"` + MaxQuantity types.Number `json:"maxQuantity"` + MaxAmount types.Number `json:"maxAmount"` + HighestBid types.Number `json:"highestBid"` + LowestAsk types.Number `json:"lowestAsk"` } -// wsAuthorisationRequest Authenticated Ws Account data request -type wsAuthorisationRequest struct { - Command wsOp `json:"command"` - Channel int64 `json:"channel"` - Sign string `json:"sign"` - Key string `json:"key"` - Payload string `json:"payload"` +// WsSymbolTradeLimit holds a websocket symbol's trade limit details +type WsSymbolTradeLimit struct { + Symbol currency.Pair `json:"symbol"` + PriceScale uint8 `json:"priceScale"` + QuantityScale uint8 `json:"quantityScale"` + QuoteAmountScale uint8 `json:"amountScale"` + MinQuantity types.Number `json:"minQuantity"` + MinAmount types.Number `json:"minAmount"` + HighestBid types.Number `json:"highestBid"` + LowestAsk types.Number `json:"lowestAsk"` } -// CancelOrdersResponse holds cancelled order info -type CancelOrdersResponse struct { - OrderID string `json:"orderId"` - ClientOrderID string `json:"clientOrderId"` - State string `json:"state"` - Code int64 `json:"code"` - Message string `json:"message"` +// SymbolDetails represents a currency symbol +type SymbolDetails struct { + Symbol currency.Pair `json:"symbol"` + BaseCurrencyName currency.Code `json:"baseCurrencyName"` + QuoteCurrencyName currency.Code `json:"quoteCurrencyName"` + DisplayName string `json:"displayName"` + State string `json:"state"` + VisibleStartTime types.Time `json:"visibleStartTime"` + TradableStartTime types.Time `json:"tradableStartTime"` + SymbolTradeLimit *SymbolTradeLimit `json:"symbolTradeLimit"` + CrossMargin *CrossMarginSupportInfo `json:"crossMargin"` +} + +// Currency represents all supported currencies +type Currency struct { + ID uint64 `json:"id"` + Coin currency.Code `json:"coin"` + Delisted bool `json:"delisted"` + TradeEnable bool `json:"tradeEnable"` + Name string `json:"name"` + NetworkList []*CryptoNetworkDetail `json:"networkList"` + SupportCollateral bool `json:"supportCollateral"` + SupportBorrow bool `json:"supportBorrow"` +} + +// CryptoNetworkDetail holds a crypto network detail +type CryptoNetworkDetail struct { + ID uint64 `json:"id"` + Coin string `json:"coin"` + Name string `json:"name"` + CurrencyType string `json:"currencyType"` + Blockchain string `json:"blockchain"` + WithdrawalEnable bool `json:"withdrawalEnable"` + DepositEnable bool `json:"depositEnable"` + DepositAddress string `json:"depositAddress"` + Decimals float64 `json:"decimals"` + MinConfirm uint64 `json:"minConfirm"` + WithdrawMin types.Number `json:"withdrawMin"` + WithdrawFee types.Number `json:"withdrawFee"` + ContractAddress string `json:"contractAddress"` } -// WalletActivityResponse holds wallet activity info -type WalletActivityResponse struct { - Deposits []WalletDeposits `json:"deposits"` - Withdrawals []WalletWithdrawals `json:"withdrawals"` +// ServerSystemTime represents a server time. +type ServerSystemTime struct { + ServerTime types.Time `json:"serverTime"` +} + +// MarketPrice represents ticker information. +type MarketPrice struct { + Symbol currency.Pair `json:"symbol"` + DailyChange types.Number `json:"dailyChange"` + Price types.Number `json:"price"` + Timestamp types.Time `json:"time"` + PushTimestamp types.Time `json:"ts"` +} + +// MarkPrice represents latest mark price for all cross margin symbols. +type MarkPrice struct { + Symbol currency.Pair `json:"symbol"` + MarkPrice types.Number `json:"markPrice"` + RecordTimestamp types.Time `json:"time"` +} + +// MarkPriceComponents represents a mark price component instance. +type MarkPriceComponents struct { + Symbol currency.Pair `json:"symbol"` + Timestamp types.Time `json:"ts"` + MarkPrice types.Number `json:"markPrice"` + Components []*MarkPriceComponent `json:"components"` +} + +// MarkPriceComponent holds a mark price detail component +type MarkPriceComponent struct { + Symbol string `json:"symbol"` + Exchange string `json:"exchange"` + SymbolPrice types.Number `json:"symbolPrice"` + Weight types.Number `json:"weight"` + ConvertPrice types.Number `json:"convertPrice"` +} + +// OrderbookData represents an order book data for a specific symbol. +type OrderbookData struct { + CreationTime types.Time `json:"time"` + Scale types.Number `json:"scale"` + Asks []types.Number `json:"asks"` + Bids []types.Number `json:"bids"` + PushTimestamp types.Time `json:"ts"` +} + +// CandlestickData represents a candlestick data for a specific symbol. +type CandlestickData struct { + Low types.Number + High types.Number + Open types.Number + Close types.Number + BaseAmount types.Number + QuoteAmount types.Number + BuyTakerAmount types.Number + BuyTakerQuantity types.Number + TradeCount types.Number + PushTimestamp types.Time + WeightedAverage types.Number + Interval string + StartTime types.Time + EndTime types.Time +} + +// UnmarshalJSON deserializes byte data into CandlestickData structure +func (c *CandlestickData) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &[14]any{&c.Low, &c.High, &c.Open, &c.Close, &c.QuoteAmount, &c.BaseAmount, &c.BuyTakerAmount, &c.BuyTakerQuantity, &c.TradeCount, &c.PushTimestamp, &c.WeightedAverage, &c.Interval, &c.StartTime, &c.EndTime}) +} + +// Trade represents a trade instance. +type Trade struct { + ID string `json:"id"` + Price types.Number `json:"price"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + TakerSide string `json:"takerSide"` + Timestamp types.Time `json:"ts"` + CreateTime types.Time `json:"createTime"` +} + +// TickerData represents a price ticker information. +type TickerData struct { + Symbol currency.Pair `json:"symbol"` + Open types.Number `json:"open"` + Low types.Number `json:"low"` + High types.Number `json:"high"` + Close types.Number `json:"close"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + TradeCount uint64 `json:"tradeCount"` + StartTime types.Time `json:"startTime"` + CloseTime types.Time `json:"closeTime"` + DisplayName string `json:"displayName"` + DailyChange types.Number `json:"dailyChange"` + Bid types.Number `json:"bid"` + BidQuantity types.Number `json:"bidQuantity"` + Ask types.Number `json:"ask"` + AskQuantity types.Number `json:"askQuantity"` + Timestamp types.Time `json:"ts"` + MarkPrice types.Number `json:"markPrice"` +} + +// CollateralDetails represents collateral information. +type CollateralDetails struct { + Currency currency.Code `json:"currency"` + CollateralRate types.Number `json:"collateralRate"` + InitialMarginRate types.Number `json:"initialMarginRate"` + MaintenanceMarginRate types.Number `json:"maintenanceMarginRate"` +} + +// BorrowRateDetails represents borrow rates information +type BorrowRateDetails struct { + Tier string `json:"tier"` + Rates []*BorrowRate `json:"rates"` +} + +// BorrowRate holds currency borrow detail +type BorrowRate struct { + Currency currency.Code `json:"currency"` + DailyBorrowRate types.Number `json:"dailyBorrowRate"` + HourlyBorrowRate types.Number `json:"hourlyBorrowRate"` + BorrowLimit types.Number `json:"borrowLimit"` +} + +// AccountDetails represents a user account information. +type AccountDetails struct { + AccountID string `json:"accountId"` + AccountType string `json:"accountType"` + AccountState string `json:"accountState"` +} + +// AccountBalances represents each account’s id, type and balances (assets). +type AccountBalances struct { + AccountID string `json:"accountId"` + AccountType string `json:"accountType"` + Balances []*AccountBalance `json:"balances"` +} + +// AccountBalance holds an account balance of currency +type AccountBalance struct { + CurrencyID string `json:"currencyId"` + Currency currency.Code `json:"currency"` + Available types.Number `json:"available"` + Hold types.Number `json:"hold"` +} + +// AccountActivity represents activities such as airdrop, rebates, staking, +// credit/debit adjustments, and other (historical adjustments). +type AccountActivity struct { + ID string `json:"id"` + Currency currency.Code `json:"currency"` + Amount types.Number `json:"amount"` + State string `json:"state"` + CreateTime types.Time `json:"createTime"` + Description string `json:"description"` + ActivityType uint8 `json:"activityType"` // possible values: 'ALL': 200, 'AIRDROP': 201, 'COMMISSION_REBATE': 202, 'STAKING': 203, 'REFERRAL_REBATE': 204, 'SWAP': 205, 'CREDIT_ADJUSTMENT': 104, 'DEBIT_ADJUSTMENT': 105, 'OTHER': 199 +} + +// AccountTransferRequest request parameter for account fund transfer. +type AccountTransferRequest struct { + Currency currency.Code `json:"currency"` + Amount float64 `json:"amount,string"` + FromAccount string `json:"fromAccount"` + ToAccount string `json:"toAccount"` +} + +// AccountTransferResponse represents an account transfer response. +type AccountTransferResponse struct { + TransferID string `json:"transferId"` +} + +// AccountTransferRecord represents an account transfer record. +type AccountTransferRecord struct { + ID string `json:"id"` + FromAccount string `json:"fromAccount"` + ToAccount string `json:"toAccount"` + Currency currency.Code `json:"currency"` + State string `json:"state"` + CreateTime types.Time `json:"createTime"` + Amount types.Number `json:"amount"` +} + +// FeeInfo represents an account transfer information. +type FeeInfo struct { + TransactionDiscount bool `json:"trxDiscount"` + MakerRate types.Number `json:"makerRate"` + TakerRate types.Number `json:"takerRate"` + Volume30D types.Number `json:"volume30D"` + SpecialFeeRates []*SpecialFeeRate `json:"specialFeeRates"` +} + +// SpecialFeeRate holds special fee rate of a symbol +type SpecialFeeRate struct { + Symbol string `json:"symbol"` + MakerRate types.Number `json:"makerRate"` + TakerRate types.Number `json:"takerRate"` +} + +// InterestHistory represents an interest history. +type InterestHistory struct { + ID string `json:"id"` + Currency currency.Code `json:"currencyName"` + Principal types.Number `json:"principal"` + Interest types.Number `json:"interest"` + InterestRate types.Number `json:"interestRate"` + InterestAccuredTime types.Time `json:"interestAccuredTime"` +} + +// SubAccount represents a users account. +type SubAccount struct { + AccountID string `json:"accountId"` + AccountName string `json:"accountName"` + AccountState string `json:"accountState"` + IsPrimary bool `json:"isPrimary,string"` +} + +// SubAccountBalances represents a users account details and balances +type SubAccountBalances struct { + AccountID string `json:"accountId"` + AccountName string `json:"accountName"` + AccountType string `json:"accountType"` + IsPrimary bool `json:"isPrimary,string"` + Balances []*SubAccountBalance `json:"balances"` +} + +// SubAccountBalance holds a subaccount balance detail +type SubAccountBalance struct { + Currency currency.Code `json:"currency"` + Available types.Number `json:"available"` + Hold types.Number `json:"hold"` + MaxAvailable types.Number `json:"maxAvailable"` + AccountEquity types.Number `json:"accountEquity"` + UnrealisedPNL types.Number `json:"unrealisedPNL"` + MarginBalance types.Number `json:"marginBalance"` + PositionMargin types.Number `json:"positionMargin"` + OrderMargin types.Number `json:"orderMargin"` + FrozenFunds types.Number `json:"frozenFunds"` + AvailableBalance types.Number `json:"availableBalance"` + RealizedProfitAndLoss types.Number `json:"pnl"` +} + +// SubAccountTransferRequest represents a sub-account transfer request parameters. +type SubAccountTransferRequest struct { + Currency currency.Code `json:"currency"` + Amount float64 `json:"amount,string"` + FromAccountID string `json:"fromAccountId"` + FromAccountType string `json:"fromAccountType"` + ToAccountID string `json:"toAccountId"` + ToAccountType string `json:"toAccountType"` +} + +// SubAccountTransfer represents a sub-account transfer record. +type SubAccountTransfer struct { + ID string `json:"id"` + FromAccountID string `json:"fromAccountId"` + FromAccountName string `json:"fromAccountName"` + FromAccountType string `json:"fromAccountType"` + ToAccountID string `json:"toAccountId"` + ToAccountName string `json:"toAccountName"` + ToAccountType string `json:"toAccountType"` + Currency currency.Code `json:"currency"` + Amount types.Number `json:"amount"` + State string `json:"state"` + CreateTime types.Time `json:"createTime"` +} + +// WalletActivity holds wallet activity info +type WalletActivity struct { + Deposits []*WalletDeposits `json:"deposits"` + Withdrawals []*WalletWithdrawals `json:"withdrawals"` } // WalletDeposits holds wallet deposit info type WalletDeposits struct { - DepositNumber int64 `json:"depositNumber"` + DepositNumber uint64 `json:"depositNumber"` Currency currency.Code `json:"currency"` Address string `json:"address"` - Amount float64 `json:"amount,string"` - Confirmations int64 `json:"confirmations"` + Amount types.Number `json:"amount"` + Confirmations uint64 `json:"confirmations"` TransactionID string `json:"txid"` Timestamp types.Time `json:"timestamp"` Status string `json:"status"` @@ -502,19 +509,546 @@ type WalletDeposits struct { // WalletWithdrawals holds wallet withdrawal info type WalletWithdrawals struct { - WithdrawalRequestsID int64 `json:"withdrawalRequestsId"` + WithdrawalRequestsID uint64 `json:"withdrawalRequestsId"` Currency currency.Code `json:"currency"` Address string `json:"address"` - Amount float64 `json:"amount,string"` - Fee float64 `json:"fee,string"` - Timestamp types.Time `json:"timestamp"` Status string `json:"status"` TransactionID string `json:"txid"` IPAddress string `json:"ipAddress"` PaymentID string `json:"paymentID"` + Amount types.Number `json:"amount"` + Fee types.Number `json:"fee"` + Timestamp types.Time `json:"timestamp"` } -// TimeStampResponse returns the time -type TimeStampResponse struct { - ServerTime types.Time `json:"serverTime"` +// Withdraw holds withdraw information +type Withdraw struct { + WithdrawRequestID uint64 `json:"withdrawalRequestsId"` +} + +// WithdrawCurrencyRequest represents a V2 currency withdrawal parameter. +type WithdrawCurrencyRequest struct { + Coin currency.Code `json:"coin"` + Network string `json:"network"` + Amount float64 `json:"amount,string"` + Address string `json:"address"` + AddressTag string `json:"addressTag,omitempty"` + AllowBorrow bool `json:"allowBorrow,omitempty"` +} + +// AccountMargin represents an account margin response +type AccountMargin struct { + TotalAccountValue types.Number `json:"totalAccountValue"` + TotalMargin types.Number `json:"totalMargin"` + UsedMargin types.Number `json:"usedMargin"` + FreeMargin types.Number `json:"freeMargin"` + MaintenanceMargin types.Number `json:"maintenanceMargin"` + CreationTime types.Time `json:"time"` + MarginRatio string `json:"marginRatio"` +} + +// BorrowStatus represents currency borrow status. +type BorrowStatus struct { + Currency currency.Code `json:"currency"` + Available types.Number `json:"available"` + Borrowed types.Number `json:"borrowed"` + Hold types.Number `json:"hold"` + MaxAvailable types.Number `json:"maxAvailable"` + HourlyBorrowRate types.Number `json:"hourlyBorrowRate"` + Version string `json:"version"` +} + +// MarginBuySellAmount represents a maximum buy and sell amount. +type MarginBuySellAmount struct { + Symbol string `json:"symbol"` + MaxLeverage uint16 `json:"maxLeverage"` + AvailableBuy types.Number `json:"availableBuy"` + MaxAvailableBuy types.Number `json:"maxAvailableBuy"` + AvailableSell types.Number `json:"availableSell"` + MaxAvailableSell types.Number `json:"maxAvailableSell"` +} + +// PlaceOrderRequest represents place order parameters. +type PlaceOrderRequest struct { + Symbol currency.Pair `json:"symbol"` + Side order.Side `json:"side"` + Type OrderType `json:"type,omitempty"` + AccountType AccountType `json:"accountType,omitempty"` + + // BaseAmount Base units for the order. BaseAmount is required for MARKET SELL or any LIMIT orders + BaseAmount float64 `json:"quantity,omitempty,string"` + + // QuoteAmount Quote units for the order. QuoteAmount is required for MARKET BUY order + QuoteAmount float64 `json:"amount,omitempty,string"` + + // Price is required for non-market orders + Price float64 `json:"price,omitempty,string"` + + TimeInForce TimeInForce `json:"timeInForce,omitempty"` // GTC, IOC, FOK (Default: GTC) + ClientOrderID string `json:"clientOrderId,omitempty"` + + AllowBorrow bool `json:"allowBorrow,omitempty"` + SelfTradePreventionMode string `json:"stpMode,omitempty"` // self-trade prevention. Defaults to EXPIRE_TAKER. None: enable self-trade; EXPIRE_TAKER: Taker order will be canceled when self-trade happens + + SlippageTolerance string `json:"slippageTolerance,omitempty"` // Used to control the maximum slippage ratio, the value range is greater than 0 and less than 1 +} + +type statusResponse struct { + Message string `json:"message"` + Code int64 `json:"code"` +} + +func (s *statusResponse) Error() error { + if s == nil { + return common.ErrNoResponse + } + if s.Code != 0 && s.Code != 200 { + return fmt.Errorf("error code: %d; message: %s", s.Code, s.Message) + } + return nil +} + +// CancelReplaceOrderRequest represents a cancellation and order replacement request parameter. +type CancelReplaceOrderRequest struct { + OrderID string `json:"-"` // used in order path parameter. + ClientOrderID string `json:"clientOrderId"` + Price float64 `json:"price,omitempty,string"` + BaseAmount float64 `json:"quantity,omitempty,string"` + QuoteAmount float64 `json:"amount,omitempty,string"` + AmendedType string `json:"type,omitempty,string"` + TimeInForce TimeInForce `json:"timeInForce,omitempty"` + AllowBorrow bool `json:"allowBorrow,omitempty"` + ProceedOnFailure bool `json:"proceedOnFailure,omitempty,string"` + SlippageTolerance float64 `json:"slippageTolerance,omitempty,string"` +} + +// CancelReplaceOrderResponse represents a response parameter for order cancellation and replacement operation. +type CancelReplaceOrderResponse struct { + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId"` + Price types.Number `json:"price"` + Quantity types.Number `json:"quantity"` + Code uint64 `json:"code"` + Message string `json:"message"` +} + +// OrdersHistoryRequest holds a orders history request parameters +type OrdersHistoryRequest struct { + Symbol currency.Pair + AccountType string + OrderType string + OrderTypes []string + Side order.Side + Direction string + States string + From int64 + Limit int64 + StartTime time.Time + EndTime time.Time + HideCancel bool +} + +// OrderHistoryItem represents an order history item +type OrderHistoryItem struct { + TradeOrder + ID uint64 `json:"id"` +} + +// TradeOrder represents a trade order +type TradeOrder struct { + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId"` + Symbol currency.Pair `json:"symbol"` + State string `json:"state"` + AccountType string `json:"accountType"` + Side order.Side `json:"side"` + Type string `json:"type"` + TimeInForce order.TimeInForce `json:"timeInForce"` + Price types.Number `json:"price"` + AveragePrice types.Number `json:"avgPrice"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + FilledQuantity types.Number `json:"filledQuantity"` + FilledAmount types.Number `json:"filledAmount"` + CreateTime types.Time `json:"createTime"` + UpdateTime types.Time `json:"updateTime"` + OrderSource string `json:"orderSource"` + Loan bool `json:"loan"` + CancelReason uint64 `json:"cancelReason"` + + statusResponse +} + +// SmartOrder represents a smart order detail. +type SmartOrder struct { + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId"` + Symbol currency.Pair `json:"symbol"` + State string `json:"state"` + AccountType string `json:"accountType"` + Side order.Side `json:"side"` + Type string `json:"type"` + TimeInForce order.TimeInForce `json:"timeInForce"` + Price types.Number `json:"price"` + ActivationPrice types.Number `json:"activationPrice"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + StopPrice types.Number `json:"stopPrice"` + CreateTime types.Time `json:"createTime"` + UpdateTime types.Time `json:"updateTime"` + TrailingOffset string `json:"trailingOffset"` + LimitOffset string `json:"limitOffset"` + Operator string `json:"operator"` } + +// CancelOrderResponse represents a cancel order response instance. +type CancelOrderResponse struct { + OrderID string `json:"orderId"` + ClientOrderID string `json:"clientOrderId"` + State string `json:"state"` + statusResponse +} + +// WsCancelOrderResponse represents a websocket cancel orders instance. +type WsCancelOrderResponse struct { + OrderID uint64 `json:"orderId"` + ClientOrderID string `json:"clientOrderId"` + State string `json:"state"` + statusResponse +} + +// CancelOrdersRequest represents cancel spot order request parameters +type CancelOrdersRequest struct { + OrderIDs []string `json:"orderIds,omitempty"` + ClientOrderIDs []string `json:"clientOrderIds,omitempty"` +} + +// KillSwitchStatus represents a kill switch response +type KillSwitchStatus struct { + StartTime types.Time `json:"startTime"` + CancellationTime types.Time `json:"cancellationTime"` +} + +// SmartOrderRequest represents a smart trade order's parameters +type SmartOrderRequest struct { + Symbol currency.Pair `json:"symbol"` + Side order.Side `json:"side"` + TimeInForce TimeInForce `json:"timeInForce,omitempty"` + AccountType AccountType `json:"accountType,omitempty"` + Type OrderType `json:"type,omitempty"` + Price float64 `json:"price,omitempty,string"` + StopPrice float64 `json:"stopPrice,omitempty,string"` + BaseAmount float64 `json:"quantity,omitempty,string"` + QuoteAmount float64 `json:"amount,omitempty,string"` + ClientOrderID string `json:"clientOrderId,omitempty"` + TrailingOffset string `json:"trailingOffset,omitempty"` // trailing stop offset; Append % to trail by percentage + LimitOffset string `json:"limitOffset,omitempty"` // When trigger price is reached a limit order is placed. Append % for percentage + Operator string `json:"operator,omitempty"` // Direction for TRAILING_STOP orders; Allowed values: `GTE` for >= or `LTE` for <= +} + +// CancelReplaceSmartOrderRequest represents a cancellation and order replacement request parameter for smart orders. +type CancelReplaceSmartOrderRequest struct { + OrderID string `json:"-"` // will be used in request path + OldClientOrderID string `json:"-"` + NewClientOrderID string `json:"clientOrderId,omitempty"` + Price float64 `json:"price,omitempty,string"` + StopPrice float64 `json:"stopPrice,omitempty,string"` + BaseAmount float64 `json:"quantity,omitempty,string"` + QuoteAmount float64 `json:"amount,omitempty,string"` + AmendedType OrderType `json:"type,omitempty,string"` + TimeInForce TimeInForce `json:"timeInForce,omitempty"` + ProceedOnFailure bool `json:"proceedOnFailure,omitempty,string"` // proceedOnFailure flag is intended to specify whether to continue with new smart order placement in case cancellation of the existing smart order fails. +} + +// WsOrderIDResponse represents order's ID response for websocket create order +type WsOrderIDResponse struct { + OrderID int64 `json:"orderId"` + ClientOrderID string `json:"clientOrderId"` + statusResponse +} + +// OrderIDResponse represents order's ID response structure details +type OrderIDResponse struct { + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId"` + statusResponse +} + +// SmartOrderDetails represents a smart order information and trigger detailed information. +type SmartOrderDetails struct { + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId"` + Symbol currency.Pair `json:"symbol"` + State string `json:"state"` + AccountType string `json:"accountType"` + Side order.Side `json:"side"` + Type string `json:"type"` + TimeInForce order.TimeInForce `json:"timeInForce"` + Price types.Number `json:"price"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + StopPrice types.Number `json:"stopPrice"` + CreateTime types.Time `json:"createTime"` + UpdateTime types.Time `json:"updateTime"` + TriggeredOrder TradeOrder `json:"triggeredOrder"` + TrailingOffset string `json:"trailingOffset"` + LimitOffset string `json:"limitOffset"` + ActivationPrice types.Number `json:"activationPrice"` + Operator string `json:"operator"` +} + +// TradeHistory represents an order trade history instance. +type TradeHistory struct { + ID string `json:"id"` + ClientOrderID string `json:"clientOrderId"` + Symbol string `json:"symbol"` + AccountType string `json:"accountType"` + OrderID string `json:"orderId"` + Side order.Side `json:"side"` + Type string `json:"type"` + MatchRole string `json:"matchRole"` + Price types.Number `json:"price"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + FeeCurrency currency.Code `json:"feeCurrency"` + FeeAmount types.Number `json:"feeAmount"` + PageID string `json:"pageId"` + CreateTime types.Time `json:"createTime"` +} + +// SubscriptionPayload represents a subscriptions request instance structure. +type SubscriptionPayload struct { + Event string `json:"event"` + Channel []string `json:"channel"` + Symbols []string `json:"symbols,omitempty"` + Currencies []string `json:"currencies,omitempty"` + Depth int64 `json:"depth,omitempty"` + Params map[string]any `json:"params,omitempty"` +} + +// CrossMarginSupportInfo represents information on whether cross margin support is enabled or not, and leverage detail +type CrossMarginSupportInfo struct { + SupportCrossMargin bool `json:"supportCrossMargin"` + MaxLeverage uint64 `json:"maxLeverage"` +} + +// WsCrossMarginSupportInfo represents information returned through the websocket stream on whether cross margin support is enabled or not, and leverage detail +type WsCrossMarginSupportInfo struct { + SupportCrossMargin bool `json:"supportCrossMargin"` + MaxLeverage uint64 `json:"maxLeverage,string"` +} + +// WsSymbol represents a subscription +type WsSymbol struct { + Symbol currency.Pair `json:"symbol"` + BaseCurrencyName currency.Code `json:"baseCurrencyName"` + QuoteCurrencyName currency.Code `json:"quoteCurrencyName"` + DisplayName string `json:"displayName"` + State string `json:"state"` + VisibleStartTime types.Time `json:"visibleStartTime"` + TradableStartTime types.Time `json:"tradableStartTime"` + CrossMargin *WsCrossMarginSupportInfo `json:"crossMargin"` + SymbolTradeLimit *WsSymbolTradeLimit `json:"symbolTradeLimit"` +} + +// WsCurrency represents a currency instance from websocket stream. +type WsCurrency struct { + ID uint64 `json:"id"` + Name string `json:"name"` + Currency currency.Code `json:"currency"` + Description string `json:"description"` + Type string `json:"type"` + WithdrawalFee types.Number `json:"withdrawalFee"` + MinConf uint64 `json:"minConf"` + DepositAddress string `json:"depositAddress"` + Blockchain string `json:"blockchain"` + Delisted bool `json:"delisted"` + TradingState string `json:"tradingState"` + WalletState string `json:"walletState"` + ParentChain string `json:"parentChain"` + IsMultiChain bool `json:"isMultiChain"` + IsChildChain bool `json:"isChildChain"` + SupportCollateral bool `json:"supportCollateral"` + SupportBorrow bool `json:"supportBorrow"` + ChildChains []string `json:"childChains"` +} + +// WsExchangeStatus represents websocket exchange status. +// the values for MM and POM are ON and OFF +type WsExchangeStatus struct { + MaintenanceMode string `json:"MM"` + PostOnlyMode string `json:"POM"` +} + +// WsCandles represents a candlestick data instance. +type WsCandles struct { + Symbol currency.Pair `json:"symbol"` + Open types.Number `json:"open"` + High types.Number `json:"high"` + Low types.Number `json:"low"` + Close types.Number `json:"close"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + TradeCount uint64 `json:"tradeCount"` + StartTime types.Time `json:"startTime"` + CloseTime types.Time `json:"closeTime"` + Timestamp types.Time `json:"ts"` +} + +// WsTrade represents websocket trade data +type WsTrade struct { + ID uint64 `json:"id,string"` + Symbol currency.Pair `json:"symbol"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + TakerSide order.Side `json:"takerSide"` + Price types.Number `json:"price"` + CreateTime types.Time `json:"createTime"` + Timestamp types.Time `json:"ts"` +} + +// WsTicker represents a websocket ticker information. +type WsTicker struct { + TradeCount uint64 `json:"tradeCount"` + Symbol currency.Pair `json:"symbol"` + StartTime types.Time `json:"startTime"` + Open types.Number `json:"open"` + High types.Number `json:"high"` + Low types.Number `json:"low"` + Close types.Number `json:"close"` + BaseAmount types.Number `json:"quantity"` + QuoteAmount types.Number `json:"amount"` + DailyChange types.Number `json:"dailyChange"` + MarkPrice types.Number `json:"markPrice"` + CloseTime types.Time `json:"closeTime"` + Timestamp types.Time `json:"ts"` +} + +// WsBook represents an orderbook. +type WsBook struct { + Symbol currency.Pair `json:"symbol"` + Asks orderbook.LevelsArrayPriceAmount `json:"asks"` + Bids orderbook.LevelsArrayPriceAmount `json:"bids"` + ID int64 `json:"id"` + Timestamp types.Time `json:"ts"` + CreateTime types.Time `json:"createTime"` + LastID int64 `json:"lastId"` +} + +// AuthRequest represents websocket authentication parameters +type AuthRequest struct { + Key string `json:"key"` + SignTimestamp int64 `json:"signTimestamp"` + SignatureMethod string `json:"signatureMethod,omitempty"` + SignatureVersion string `json:"signatureVersion,omitempty"` + Signature string `json:"signature"` +} + +// WebsocketAuthenticationResponse represents websocket authentication response. +type WebsocketAuthenticationResponse struct { + Success bool `json:"success"` + Message string `json:"message"` + Timestamp types.Time `json:"ts"` +} + +// WebsocketTradeOrder represents a websocket trade order. +type WebsocketTradeOrder struct { + Symbol currency.Pair `json:"symbol"` + Type string `json:"type"` + BaseAmount types.Number `json:"quantity"` + OrderID string `json:"orderId"` + TradeFee types.Number `json:"tradeFee"` + ClientOrderID string `json:"clientOrderId"` + AccountType string `json:"accountType"` + FeeCurrency currency.Code `json:"feeCurrency"` + EventType string `json:"eventType"` + Source string `json:"source"` + Side order.Side `json:"side"` + FilledQuantity types.Number `json:"filledQuantity"` + FilledAmount types.Number `json:"filledAmount"` + MatchRole string `json:"matchRole"` + State string `json:"state"` + TradeTime types.Time `json:"tradeTime"` + TradeAmount types.Number `json:"tradeAmount"` + OrderAmount types.Number `json:"orderAmount"` + CreateTime types.Time `json:"createTime"` + Price types.Number `json:"price"` + TradeQty types.Number `json:"tradeQty"` + TradePrice types.Number `json:"tradePrice"` + TradeID string `json:"tradeId"` + Timestamp types.Time `json:"ts"` +} + +// WsTradeBalance represents a balance information through the websocket channel +type WsTradeBalance struct { + ID uint64 `json:"id"` + UserID uint64 `json:"userId"` + ChangeTime types.Time `json:"changeTime"` + AccountID string `json:"accountId"` + AccountType string `json:"accountType"` + EventType string `json:"eventType"` + Available types.Number `json:"available"` + Currency currency.Code `json:"currency"` + Hold types.Number `json:"hold"` + Version uint32 `json:"version"` + Timestamp types.Time `json:"ts"` +} + +// WebsocketResponse represents a websocket responses. +type WebsocketResponse struct { + ID string `json:"id"` + Data any `json:"data"` +} + +// SubAccountTransferRecordRequest represents a sub-account transfer record retrieval parameters +type SubAccountTransferRecordRequest struct { + Currency currency.Code + StartTime time.Time + EndTime time.Time + FromAccountID string + ToAccountID string + FromAccountType string + ToAccountType string + Direction string + From uint64 + Limit uint64 +} + +// V3ResponseWrapper holds a wrapper struct for V3 and smart-order endpoints +type V3ResponseWrapper struct { + Code int64 `json:"code"` + Message string `json:"msg"` + Data any `json:"data"` +} + +func (s *V3ResponseWrapper) Error() error { + if s.Code != 0 && s.Code != 200 { + return fmt.Errorf("error code: %d; message: %s", s.Code, s.Message) + } + if s.Data == nil { + return common.ErrNoResponse + } + return nil +} + +// UnmarshalJSON conforms type to the unmarshaler interface +func (s *V3ResponseWrapper) UnmarshalJSON(data []byte) error { + var aux struct { + Code int64 `json:"code"` + Message string `json:"message"` + Data json.RawMessage `json:"data"` + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + s.Code = aux.Code + s.Message = aux.Message + if (s.Code == 0 || s.Code == 200) && aux.Data != nil { + return json.Unmarshal(aux.Data, &s.Data) + } + + return nil +} + +type hasError interface{ Error() error } diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 4a8461770f9..c232daa547f 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -2,1149 +2,521 @@ package poloniex import ( "context" - "encoding/hex" - "errors" + "encoding/base64" "fmt" "net/http" + "slices" "strconv" "strings" + "sync" + "text/template" "time" + "github.com/Masterminds/sprig/v3" gws "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/crypto" - "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/encoding/json" "github.com/thrasher-corp/gocryptotrader/exchange/accounts" "github.com/thrasher-corp/gocryptotrader/exchange/websocket" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/subscription" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" "github.com/thrasher-corp/gocryptotrader/exchanges/trade" - "github.com/thrasher-corp/gocryptotrader/log" ) const ( - poloniexWebsocketAddress = "wss://api2.poloniex.com" - wsAccountNotificationID = 1000 - wsTickerDataID = 1002 - ws24HourExchangeVolumeID = 1003 - wsHeartbeat = 1010 - - accountNotificationBalanceUpdate = "b" - accountNotificationOrderUpdate = "o" - accountNotificationPendingOrder = "p" - accountNotificationOrderLimitCreated = "n" - accountNotificationTrades = "t" - accountNotificationKilledOrder = "k" - accountNotificationMarginPosition = "m" - - orderbookInitial = "i" - orderbookUpdate = "o" - tradeUpdate = "t" -) - -var ( - errNotEnoughData = errors.New("element length not adequate to process") - errTypeAssertionFailure = errors.New("type assertion failure") - errIDNotFoundInPairMap = errors.New("id not associated with currency pair map") - errIDNotFoundInCodeMap = errors.New("id not associated with currency code map") + websocketURL = "wss://ws.poloniex.com/ws/public" + privateWebsocketURL = "wss://ws.poloniex.com/ws/private" + + channelExchange = "exchange" + channelAuth = "auth" + + // Public channels + channelSymbols = "symbols" + channelCurrencies = "currencies" + channelCandles = "candles" + channelTrades = "trades" + channelTicker = "ticker" + channelBooks = "book" + channelBookLevel2 = "book_lv2" + + // Authenticated channels + channelOrders = "orders" + channelBalances = "balances" ) -// WsConnect initiates a websocket connection -func (e *Exchange) WsConnect() error { - ctx := context.TODO() - if !e.Websocket.IsEnabled() || !e.IsEnabled() { - return websocket.ErrWebsocketNotEnabled - } - var dialer gws.Dialer - err := e.Websocket.Conn.Dial(ctx, &dialer, http.Header{}) - if err != nil { - return err - } - - err = e.loadCurrencyDetails(ctx) - if err != nil { - return err - } - - e.Websocket.Wg.Add(1) - go e.wsReadData(ctx) - - return nil +var defaultSubscriptions = subscription.List{ + {Enabled: true, Asset: asset.Spot, Channel: subscription.CandlesChannel, Interval: kline.FiveMin}, + {Enabled: true, Asset: asset.Spot, Channel: subscription.AllTradesChannel}, + {Enabled: true, Asset: asset.Spot, Channel: subscription.TickerChannel}, + {Enabled: true, Asset: asset.Spot, Channel: subscription.OrderbookChannel}, } -// loadCurrencyDetails loads currency details for websocket usage -// TODO: Create routine to refresh list every day/week(?) for production -func (e *Exchange) loadCurrencyDetails(ctx context.Context) error { - if e.details.isInitial() { - ticks, err := e.GetTicker(ctx) - if err != nil { - return err - } - err = e.details.loadPairs(ticks) - if err != nil { - return err - } - - currs, err := e.GetCurrencies(ctx) - if err != nil { - return err - } +var defaultSpotPrivateSubscriptions = subscription.List{ + {Enabled: true, Asset: asset.Spot, Channel: subscription.MyOrdersChannel, Authenticated: true}, + {Enabled: true, Asset: asset.Spot, Channel: subscription.MyAccountChannel, Authenticated: true}, +} - err = e.details.loadCodes(currs) - if err != nil { - return err - } - } - return nil +var subscriptionNames = map[string]string{ + subscription.CandlesChannel: channelCandles, + subscription.AllTradesChannel: channelTrades, + subscription.TickerChannel: channelTicker, + subscription.OrderbookChannel: channelBookLevel2, + subscription.MyOrdersChannel: channelOrders, + subscription.MyAccountChannel: channelBalances, } -// wsReadData handles data from the websocket connection -func (e *Exchange) wsReadData(ctx context.Context) { - defer e.Websocket.Wg.Done() - for { - resp := e.Websocket.Conn.ReadMessage() - if resp.Raw == nil { - return - } - if err := e.wsHandleData(ctx, resp.Raw); err != nil { - if errSend := e.Websocket.DataHandler.Send(ctx, err); errSend != nil { - log.Errorf(log.WebsocketMgr, "%s %s: %s %s", e.Name, e.Websocket.Conn.GetURL(), errSend, err) - } - } - } +func setupPingHandler(conn websocket.Connection) { + conn.SetupPingHandler(request.Unset, websocket.PingHandler{ + MessageType: gws.TextMessage, + Message: []byte(`{"event": "ping"}`), + Delay: time.Second * 15, + }) } -func (e *Exchange) wsHandleData(ctx context.Context, respRaw []byte) error { - var result any - err := json.Unmarshal(respRaw, &result) - if err != nil { +// wsConnect checks if websocket is enabled and initiates a websocket connection +func (e *Exchange) wsConnect(ctx context.Context, conn websocket.Connection) error { + if err := conn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil { return err } - - data, ok := result.([]any) - if !ok { - return fmt.Errorf("%w data is not []any", - errTypeAssertionFailure) - } - - if len(data) == 0 { - return nil - } - if len(data) == 2 { - // subscription acknowledgement - // TODO: Add in subscriber ack - return nil - } - - channelID, ok := data[0].(float64) - if !ok { - return fmt.Errorf("%w channel id is not of type float64", - errTypeAssertionFailure) - } - switch channelID { - case ws24HourExchangeVolumeID, wsHeartbeat: - return nil - case wsAccountNotificationID: - var notificationsArray []any - notificationsArray, ok = data[2].([]any) - if !ok { - return fmt.Errorf("%w account notification is not a []any", - errTypeAssertionFailure) - } - for i := range notificationsArray { - var notification []any - notification, ok = (notificationsArray[i]).([]any) - if !ok { - return fmt.Errorf("%w notification array element is not a []any", - errTypeAssertionFailure) - } - var updateType string - updateType, ok = notification[0].(string) - if !ok { - return fmt.Errorf("%w update type is not a string", - errTypeAssertionFailure) - } - - switch updateType { - case accountNotificationPendingOrder: - err = e.processAccountPendingOrder(ctx, notification) - if err != nil { - return fmt.Errorf("account notification pending order: %w", err) - } - case accountNotificationOrderUpdate: - err = e.processAccountOrderUpdate(ctx, notification) - if err != nil { - return fmt.Errorf("account notification order update: %w", err) - } - case accountNotificationOrderLimitCreated: - err = e.processAccountOrderLimit(ctx, notification) - if err != nil { - return fmt.Errorf("account notification limit order creation: %w", err) - } - case accountNotificationBalanceUpdate: - err = e.processAccountBalanceUpdate(ctx, notification) - if err != nil { - return fmt.Errorf("account notification balance update: %w", err) - } - case accountNotificationTrades: - err = e.processAccountTrades(ctx, notification) - if err != nil { - return fmt.Errorf("account notification trades: %w", err) - } - case accountNotificationKilledOrder: - err = e.processAccountKilledOrder(ctx, notification) - if err != nil { - return fmt.Errorf("account notification killed order: %w", err) - } - case accountNotificationMarginPosition: - err = e.processAccountMarginPosition(ctx, notification) - if err != nil { - return fmt.Errorf("account notification margin position: %w", err) - } - default: - return fmt.Errorf("unhandled account update: %s", string(respRaw)) - } - } - return nil - case wsTickerDataID: - err = e.wsHandleTickerData(ctx, data) - if err != nil { - return fmt.Errorf("websocket ticker process: %w", err) - } - return nil - } - - priceAggBook, ok := data[2].([]any) - if !ok { - return fmt.Errorf("%w price aggregated book not []any", - errTypeAssertionFailure) - } - - for x := range priceAggBook { - subData, ok := priceAggBook[x].([]any) - if !ok { - return fmt.Errorf("%w price aggregated book element not []any", - errTypeAssertionFailure) - } - - updateIdent, ok := subData[0].(string) - if !ok { - return fmt.Errorf("%w update identifier not a string", - errTypeAssertionFailure) - } - - switch updateIdent { - case orderbookInitial: - err = e.WsProcessOrderbookSnapshot(subData) - if err != nil { - return fmt.Errorf("websocket process orderbook snapshot: %w", err) - } - case orderbookUpdate: - var pair currency.Pair - pair, err = e.details.GetPair(channelID) - if err != nil { - return err - } - var seqNo float64 - seqNo, ok = data[1].(float64) - if !ok { - return fmt.Errorf("%w sequence number is not a float64", - errTypeAssertionFailure) - } - err = e.WsProcessOrderbookUpdate(seqNo, subData, pair) - if err != nil { - return fmt.Errorf("websocket process orderbook update: %w", err) - } - case tradeUpdate: - err = e.processTrades(channelID, subData) - if err != nil { - return fmt.Errorf("websocket process trades update: %w", err) - } - default: - if err := e.Websocket.DataHandler.Send(ctx, websocket.UnhandledMessageWarning{ - Message: e.Name + websocket.UnhandledMessage + string(respRaw), - }); err != nil { - return err - } - } - } + setupPingHandler(conn) return nil } -func (e *Exchange) wsHandleTickerData(ctx context.Context, data []any) error { - tickerData, ok := data[2].([]any) - if !ok { - return fmt.Errorf("%w ticker data is not []any", - errTypeAssertionFailure) - } - - currencyID, ok := tickerData[0].(float64) - if !ok { - return fmt.Errorf("%w currency ID not float64", errTypeAssertionFailure) - } - - pair, err := e.details.GetPair(currencyID) +// authenticateSpotAuthConn authenticates a spot websocket connection +func (e *Exchange) authenticateSpotAuthConn(ctx context.Context, conn websocket.Connection) error { + creds, err := e.GetCredentials(ctx) if err != nil { return err } - - enabled, err := e.GetEnabledPairs(asset.Spot) + timestamp := time.Now() + hmac, err := crypto.GetHMAC(crypto.HashSHA256, + fmt.Appendf(nil, "GET\n/ws\nsignTimestamp=%d", timestamp.UnixMilli()), + []byte(creds.Secret)) if err != nil { return err } - - if !enabled.Contains(pair, true) { - return nil - } - - tlp, ok := tickerData[1].(string) - if !ok { - return fmt.Errorf("%w last price not string", errTypeAssertionFailure) + auth := &struct { + Event string `json:"event"` + Channel []string `json:"channel"` + Params AuthRequest `json:"params"` + }{ + Event: "subscribe", + Channel: []string{channelAuth}, + Params: AuthRequest{ + Key: creds.Key, + SignatureMethod: "hmacSHA256", + SignTimestamp: timestamp.UnixMilli(), + Signature: base64.StdEncoding.EncodeToString(hmac), + }, } - - lastPrice, err := strconv.ParseFloat(tlp, 64) + data, err := conn.SendMessageReturnResponse(ctx, fWebsocketPrivateEPL, channelAuth, auth) if err != nil { return err } - - la, ok := tickerData[2].(string) - if !ok { - return fmt.Errorf("%w lowest ask price not string", - errTypeAssertionFailure) - } - - lowestAsk, err := strconv.ParseFloat(la, 64) - if err != nil { + var resp *AuthenticationResponse + if err := json.Unmarshal(data, &resp); err != nil { return err } - - hb, ok := tickerData[3].(string) - if !ok { - return fmt.Errorf("%w highest bid price not string", - errTypeAssertionFailure) + if !resp.Data.Success { + return fmt.Errorf("authentication failed with status code: %s", resp.Data.Message) } + return nil +} - highestBid, err := strconv.ParseFloat(hb, 64) - if err != nil { +func (e *Exchange) wsHandleData(ctx context.Context, conn websocket.Connection, respRaw []byte) error { + var result SubscriptionResponse + if err := json.Unmarshal(respRaw, &result); err != nil { return err } - - bcv, ok := tickerData[5].(string) - if !ok { - return fmt.Errorf("%w base currency volume not string", - errTypeAssertionFailure) + if result.ID != "" { + return conn.RequireMatchWithData(result.ID, respRaw) + } else if result.Event != "" { + switch result.Event { + case "pong": + return nil + case "subscribe", "unsubscribe", "error": + return conn.RequireMatchWithData("subscription", respRaw) + default: + return fmt.Errorf("%s %s %s", e.Name, websocket.UnhandledMessage, string(respRaw)) + } } + switch result.Channel { + case channelAuth: + return conn.RequireMatchWithData(channelAuth, respRaw) + case channelSymbols: + var response []*WsSymbol + return e.processResponse(ctx, &result, &response) + case channelCurrencies: + var response []*WsCurrency + return e.processResponse(ctx, &result, &response) + case channelExchange: + var response []*WsExchangeStatus + return e.processResponse(ctx, &result, &response) + case channelTrades: + return e.processTrades(&result) + case channelTicker: + return e.processTicker(ctx, &result) + case channelBookLevel2: + return e.processBooksLevel2(&result) + case channelBooks: + return e.processBooks(&result) + case channelOrders: + return e.processOrders(ctx, &result) + case channelBalances: + return e.processBalance(ctx, &result) + default: + if strings.HasPrefix(result.Channel, channelCandles) { + splits := strings.Split(result.Channel, "_") + length := len(splits) + if length < 3 { + return fmt.Errorf("%w %q", kline.ErrInvalidInterval, result.Channel) + } + return e.processCandlestickData(ctx, &result, strings.Join(splits[length-2:], "_")) + } + return fmt.Errorf("%s %s %s", e.Name, websocket.UnhandledMessage, string(respRaw)) + } +} - baseCurrencyVolume24H, err := strconv.ParseFloat(bcv, 64) - if err != nil { +func (e *Exchange) processBalance(ctx context.Context, result *SubscriptionResponse) error { + var resp []*WsTradeBalance + if err := json.Unmarshal(result.Data, &resp); err != nil { return err } - - qcv, ok := tickerData[6].(string) - if !ok { - return fmt.Errorf("%w quote currency volume not string", - errTypeAssertionFailure) + subAccts := accounts.SubAccounts{} + for _, r := range resp { + subAcct := accounts.NewSubAccount(stringToAccountType(r.AccountType), r.AccountID) + subAcct.Balances.Set(r.Currency, accounts.Balance{ + Currency: r.Currency, + Hold: r.Hold.Float64(), + Total: r.Available.Float64(), + UpdatedAt: r.Timestamp.Time(), + Free: r.Available.Float64() - r.Hold.Float64(), + }) + subAccts = subAccts.Merge(subAcct) } - - quoteCurrencyVolume24H, err := strconv.ParseFloat(qcv, 64) - if err != nil { + if err := e.Accounts.Save(ctx, subAccts, true); err != nil { return err } - - // Unused variables below, can add later if needed: - // percentageChange, ok := tickerData[4].(string) - // Not integrating isFrozen with currency details as this will slow down - // the sync RW mutex (can use REST calls for now). - // isFrozen, ok := tickerData[7].(float64) // == 1 means it is frozen - // highestTradeIn24Hm, ok := tickerData[8].(string) - // lowestTradePrice24H, ok := tickerData[9].(string) - - return e.Websocket.DataHandler.Send(ctx, &ticker.Price{ - ExchangeName: e.Name, - Volume: baseCurrencyVolume24H, - QuoteVolume: quoteCurrencyVolume24H, - High: highestBid, - Low: lowestAsk, - Bid: highestBid, - Ask: lowestAsk, - Last: lastPrice, - AssetType: asset.Spot, - Pair: pair, - }) + return e.Websocket.DataHandler.Send(ctx, subAccts) } -// WsProcessOrderbookSnapshot processes a new orderbook snapshot into a local -// of orderbooks -func (e *Exchange) WsProcessOrderbookSnapshot(data []any) error { - subDataMap, ok := data[1].(map[string]any) - if !ok { - return fmt.Errorf("%w subData element is not map[string]any", - errTypeAssertionFailure) - } - - pMap, ok := subDataMap["currencyPair"] - if !ok { - return errors.New("could not find currency pair in map") - } - - pair, ok := pMap.(string) - if !ok { - return fmt.Errorf("%w subData element is not map[string]any", - errTypeAssertionFailure) - } - - if len(data) < 3 { - return fmt.Errorf("%w for pair %v", errNotEnoughData, pair) - } - - ts, ok := data[2].(string) - if !ok { - return common.GetTypeAssertError("string", data[2], "timestamp string") - } - - tsMilli, err := strconv.ParseInt(ts, 10, 64) - if err != nil { +func (e *Exchange) processOrders(ctx context.Context, result *SubscriptionResponse) error { + response := []*WebsocketTradeOrder{} + if err := json.Unmarshal(result.Data, &response); err != nil { return err } - - oMap, ok := subDataMap["orderBook"] - if !ok { - return errors.New("could not find orderbook data in map") - } - - ob, ok := oMap.([]any) - if !ok { - return fmt.Errorf("%w orderbook data is not []any", - errTypeAssertionFailure) - } - - if len(ob) != 2 { - return errNotEnoughData - } - - askData, ok := ob[0].(map[string]any) - if !ok { - return fmt.Errorf("%w ask data is not map[string]any", - errTypeAssertionFailure) - } - - bidData, ok := ob[1].(map[string]any) - if !ok { - return fmt.Errorf("%w bid data is not map[string]any", - errTypeAssertionFailure) - } - - var book orderbook.Book - book.Asks = make(orderbook.Levels, 0, len(askData)) - for price, volume := range askData { - var p float64 - p, err = strconv.ParseFloat(price, 64) + orderDetails := make([]order.Detail, len(response)) + for x, r := range response { + oStatus, err := order.StringToOrderStatus(r.State) if err != nil { return err } - v, ok := volume.(string) - if !ok { - return fmt.Errorf("%w ask volume data not string", - errTypeAssertionFailure) - } - var a float64 - a, err = strconv.ParseFloat(v, 64) + oType, err := order.StringToOrderType(r.Type) if err != nil { return err } - book.Asks = append(book.Asks, orderbook.Level{Price: p, Amount: a}) + orderDetails[x] = order.Detail{ + Price: r.Price.Float64(), + Amount: r.BaseAmount.Float64(), + QuoteAmount: r.OrderAmount.Float64(), + ExecutedAmount: r.FilledAmount.Float64(), + RemainingAmount: r.BaseAmount.Float64() - r.FilledQuantity.Float64(), + Fee: r.TradeFee.Float64(), + FeeAsset: r.FeeCurrency, + Exchange: e.Name, + OrderID: r.OrderID, + ClientOrderID: r.ClientOrderID, + Type: oType, + Side: r.Side, + Status: oStatus, + AssetType: stringToAccountType(r.AccountType), + Date: r.CreateTime.Time(), + LastUpdated: r.TradeTime.Time(), + Pair: r.Symbol, + Trades: []order.TradeHistory{ + { + Price: r.TradePrice.Float64(), + Amount: r.TradeQty.Float64(), + Fee: r.TradeFee.Float64(), + Exchange: e.Name, + TID: r.TradeID, + Type: oType, + Side: r.Side, + Timestamp: r.Timestamp.Time(), + FeeAsset: r.FeeCurrency.String(), + Total: r.BaseAmount.Float64(), + }, + }, + } } + return e.Websocket.DataHandler.Send(ctx, orderDetails) +} - book.Bids = make(orderbook.Levels, 0, len(bidData)) - for price, volume := range bidData { - var p float64 - p, err = strconv.ParseFloat(price, 64) - if err != nil { +func (e *Exchange) processBooks(result *SubscriptionResponse) error { + var resp []*WsBook + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + for _, r := range resp { + if err := e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{ + Pair: r.Symbol, + Exchange: e.Name, + LastUpdateID: r.ID, + Asset: asset.Spot, + LastUpdated: r.CreateTime.Time(), + LastPushed: r.Timestamp.Time(), + Asks: r.Asks.Levels(), + Bids: r.Bids.Levels(), + }); err != nil { return err } - v, ok := volume.(string) - if !ok { - return fmt.Errorf("%w bid volume data not string", - errTypeAssertionFailure) - } - var a float64 - a, err = strconv.ParseFloat(v, 64) - if err != nil { - return err - } - book.Bids = append(book.Bids, orderbook.Level{Price: p, Amount: a}) - } - - // Both sides are completely out of order - sort needs to be used - book.Asks.SortAsks() - book.Bids.SortBids() - book.Asset = asset.Spot - book.ValidateOrderbook = e.ValidateOrderbook - book.LastUpdated = time.UnixMilli(tsMilli) - book.Pair, err = currency.NewPairFromString(pair) - if err != nil { - return err } - book.Exchange = e.Name - - return e.Websocket.Orderbook.LoadSnapshot(&book) + return nil } -// WsProcessOrderbookUpdate processes new orderbook updates -func (e *Exchange) WsProcessOrderbookUpdate(sequenceNumber float64, data []any, pair currency.Pair) error { - if len(data) < 5 { - return errNotEnoughData - } - - ps, ok := data[2].(string) - if !ok { - return fmt.Errorf("%w price not string", errTypeAssertionFailure) - } - price, err := strconv.ParseFloat(ps, 64) - if err != nil { - return err - } - vs, ok := data[3].(string) - if !ok { - return fmt.Errorf("%w volume not string", errTypeAssertionFailure) - } - volume, err := strconv.ParseFloat(vs, 64) - if err != nil { +func (e *Exchange) processBooksLevel2(result *SubscriptionResponse) error { + var resp []WsBook + if err := json.Unmarshal(result.Data, &resp); err != nil { return err } - bs, ok := data[1].(float64) - if !ok { - return fmt.Errorf("%w buysell not float64", errTypeAssertionFailure) + if len(resp) != 1 { + return fmt.Errorf("expected 1 orderbook update, received %d", len(resp)) } - ts, ok := data[4].(string) - if !ok { - return common.GetTypeAssertError("string", data[2], "timestamp string") - } - - tsMilli, err := strconv.ParseInt(ts, 10, 64) - if err != nil { - return err + r := resp[0] + if result.Action == "snapshot" { + return e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{ + Exchange: e.Name, + Pair: r.Symbol, + Asset: asset.Spot, + Asks: r.Asks.Levels(), + Bids: r.Bids.Levels(), + LastUpdateID: r.LastID, + LastUpdated: r.Timestamp.Time(), + }) } - update := &orderbook.Update{ - Pair: pair, + return e.Websocket.Orderbook.Update(&orderbook.Update{ + Pair: r.Symbol, + UpdateTime: r.Timestamp.Time(), + UpdateID: r.ID, Asset: asset.Spot, - UpdateID: int64(sequenceNumber), - UpdateTime: time.UnixMilli(tsMilli), - } - if bs == 1 { - update.Bids = []orderbook.Level{{Price: price, Amount: volume}} - } else { - update.Asks = []orderbook.Level{{Price: price, Amount: volume}} - } - return e.Websocket.Orderbook.Update(update) -} - -// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions() -func (e *Exchange) GenerateDefaultSubscriptions() (subscription.List, error) { - enabledPairs, err := e.GetEnabledPairs(asset.Spot) - if err != nil { - return nil, err - } - - subscriptions := make(subscription.List, 0, len(enabledPairs)) - subscriptions = append(subscriptions, &subscription.Subscription{ - Channel: strconv.FormatInt(wsTickerDataID, 10), + Asks: r.Asks.Levels(), + Bids: r.Bids.Levels(), }) - - if e.IsWebsocketAuthenticationSupported() { - subscriptions = append(subscriptions, &subscription.Subscription{ - Channel: strconv.FormatInt(wsAccountNotificationID, 10), - }) - } - - for j := range enabledPairs { - enabledPairs[j].Delimiter = currency.UnderscoreDelimiter - subscriptions = append(subscriptions, &subscription.Subscription{ - Channel: "orderbook", - Pairs: currency.Pairs{enabledPairs[j]}, - Asset: asset.Spot, - }) - } - return subscriptions, nil -} - -// Subscribe sends a websocket message to receive data from the channel -func (e *Exchange) Subscribe(subs subscription.List) error { - ctx := context.TODO() - return e.manageSubs(ctx, subs, wsSubscribeOp) } -// Unsubscribe sends a websocket message to stop receiving data from the channel -func (e *Exchange) Unsubscribe(subs subscription.List) error { - ctx := context.TODO() - return e.manageSubs(ctx, subs, wsUnsubscribeOp) +func (e *Exchange) processTicker(ctx context.Context, result *SubscriptionResponse) error { + var resp []*WsTicker + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + tickerData := make([]ticker.Price, len(resp)) + for x, r := range resp { + tickerData[x] = ticker.Price{ + MarkPrice: r.MarkPrice.Float64(), + High: r.High.Float64(), + Low: r.Low.Float64(), + Volume: r.BaseAmount.Float64(), + QuoteVolume: r.QuoteAmount.Float64(), + Open: r.Open.Float64(), + Close: r.Close.Float64(), + Pair: r.Symbol, + AssetType: asset.Spot, + ExchangeName: e.Name, + LastUpdated: r.Timestamp.Time(), + } + } + return e.Websocket.DataHandler.Send(ctx, tickerData) } -func (e *Exchange) manageSubs(ctx context.Context, subs subscription.List, op wsOp) error { - var creds *accounts.Credentials - if e.IsWebsocketAuthenticationSupported() { - var err error - creds, err = e.GetCredentials(ctx) - if err != nil { - return err +func (e *Exchange) processTrades(result *SubscriptionResponse) error { + var resp []*WsTrade + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + trades := make([]trade.Data, len(resp)) + for x, r := range resp { + trades[x] = trade.Data{ + TID: strconv.FormatUint(r.ID, 10), + Exchange: e.Name, + CurrencyPair: r.Symbol, + Side: r.TakerSide, + Price: r.Price.Float64(), + Timestamp: r.Timestamp.Time(), + Amount: r.BaseAmount.Float64(), } } + return trade.AddTradesToBuffer(trades...) +} - var errs error - for _, s := range subs { - var err error - if creds != nil && strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), s.Channel) { - err = e.wsSendAuthorisedCommand(ctx, creds.Secret, creds.Key, op) - } else { - req := wsCommand{Command: op} - if strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10), s.Channel) { - req.Channel = wsTickerDataID - } else { - if len(s.Pairs) != 1 { - return subscription.ErrNotSinglePair - } - req.Channel = s.Pairs[0].String() - } - err = e.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) - } - if err == nil { - if op == wsSubscribeOp { - err = e.Websocket.AddSuccessfulSubscriptions(e.Websocket.Conn, s) - } else { - err = e.Websocket.RemoveSubscriptions(e.Websocket.Conn, s) - } - } - if err != nil { - errs = common.AppendError(errs, err) +func (e *Exchange) processCandlestickData(ctx context.Context, result *SubscriptionResponse, intervalString string) error { + var resp []*WsCandles + if err := json.Unmarshal(result.Data, &resp); err != nil { + return err + } + candles := make([]websocket.KlineData, len(resp)) + for x, r := range resp { + candles[x] = websocket.KlineData{ + Pair: r.Symbol, + Exchange: e.Name, + Timestamp: r.Timestamp.Time(), + StartTime: r.StartTime.Time(), + CloseTime: r.CloseTime.Time(), + OpenPrice: r.Open.Float64(), + ClosePrice: r.Close.Float64(), + HighPrice: r.High.Float64(), + LowPrice: r.Low.Float64(), + Volume: r.BaseAmount.Float64(), + Interval: intervalString, } } - return errs + return e.Websocket.DataHandler.Send(ctx, candles) } -func (e *Exchange) wsSendAuthorisedCommand(ctx context.Context, secret, key string, op wsOp) error { - nonce := fmt.Sprintf("nonce=%v", time.Now().UnixNano()) - hmac, err := crypto.GetHMAC(crypto.HashSHA512, []byte(nonce), []byte(secret)) - if err != nil { +func (e *Exchange) processResponse(ctx context.Context, result *SubscriptionResponse, instance any) error { + if err := json.Unmarshal(result.Data, instance); err != nil { return err } - req := wsAuthorisationRequest{ - Command: op, - Channel: 1000, - Sign: hex.EncodeToString(hmac), - Key: key, - Payload: nonce, - } - return e.Websocket.Conn.SendJSONMessage(ctx, request.Unset, req) + return e.Websocket.DataHandler.Send(ctx, instance) } -func (e *Exchange) processAccountMarginPosition(ctx context.Context, notification []any) error { - if len(notification) < 5 { - return errNotEnoughData - } - - orderID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w order id not float64", errTypeAssertionFailure) - } - - currencyID, ok := notification[2].(float64) - if !ok { - return fmt.Errorf("%w currency id not float64", errTypeAssertionFailure) - } - code, err := e.details.GetCode(currencyID) +func (e *Exchange) handleSubscription(operation string, s *subscription.Subscription) (*SubscriptionPayload, error) { + pairFormat, err := e.GetPairFormat(s.Asset, true) if err != nil { - return err + return nil, err } - - a, ok := notification[3].(string) - if !ok { - return fmt.Errorf("%w amount not string", errTypeAssertionFailure) + input := &SubscriptionPayload{ + Event: operation, + Channel: []string{strings.ToLower(s.QualifiedChannel)}, } - amount, err := strconv.ParseFloat(a, 64) - if err != nil { - return err + switch { + case s.Asset == asset.Futures && s.QualifiedChannel == channelFuturesAccount, + s.Asset == asset.Spot && (s.QualifiedChannel == channelBalances || s.QualifiedChannel == channelOrders): + case len(s.Pairs) != 0: + input.Symbols = s.Pairs.Format(pairFormat).Strings() } - // null returned so ok check is not needed - clientOrderID, _ := notification[4].(string) + switch s.Channel { + case subscription.OrderbookChannel, channelBooks: + input.Depth = int64(s.Levels) // supported orderbook levels are 5, 10 and 20 + case channelCurrencies: + for _, p := range s.Pairs { + if !slices.Contains(input.Currencies, p.Base.String()) { + input.Currencies = append(input.Currencies, p.Base.String()) + } + } + case subscription.MyOrdersChannel: + if s.Asset == asset.Spot && len(input.Symbols) == 0 { + input.Symbols = []string{"all"} + } + } + return input, nil +} - // Temp struct for margin position changes - return e.Websocket.DataHandler.Send(ctx, struct { - OrderID string - Code currency.Code - Amount float64 - ClientOrderID string - }{ - OrderID: strconv.FormatFloat(orderID, 'f', -1, 64), - Code: code, - Amount: amount, - ClientOrderID: clientOrderID, - }) +func (e *Exchange) generateSubscriptions() (subscription.List, error) { + return e.Features.Subscriptions.ExpandTemplates(e) } -func (e *Exchange) processAccountPendingOrder(ctx context.Context, notification []any) error { - if len(notification) < 7 { - return errNotEnoughData - } +func (e *Exchange) generatePrivateSubscriptions() (subscription.List, error) { + return defaultSpotPrivateSubscriptions.ExpandTemplates(e) +} - orderID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w order id not float64", errTypeAssertionFailure) - } +// GetSubscriptionTemplate returns a subscription channel template +func (e *Exchange) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) { + return template.New("master.tmpl").Funcs(sprig.FuncMap()).Funcs(template.FuncMap{ + "channelName": channelName, + "interval": intervalToString, + }).Parse(subTplText) +} - currencyID, ok := notification[2].(float64) - if !ok { - return fmt.Errorf("%w currency id not float64", errTypeAssertionFailure) - } - pair, err := e.details.GetPair(currencyID) - if err != nil { - if !errors.Is(err, errIDNotFoundInPairMap) { - return err +func channelName(s *subscription.Subscription) string { + switch s.Asset { + case asset.Futures: + if name, ok := futuresSubscriptionNames[s.Channel]; ok { + return name + } + case asset.Spot: + if name, ok := subscriptionNames[s.Channel]; ok { + return name } - log.Errorf(log.WebsocketMgr, - "%s - Unknown currency pair ID. Currency will appear as the pair ID: '%v'", - e.Name, - currencyID) } + return s.Channel +} - price, ok := notification[3].(string) - if !ok { - return fmt.Errorf("%w price not string", errTypeAssertionFailure) - } - orderPrice, err := strconv.ParseFloat(price, 64) - if err != nil { - return err - } - amount, ok := notification[4].(string) - if !ok { - return fmt.Errorf("%w amount not string", errTypeAssertionFailure) - } - orderAmount, err := strconv.ParseFloat(amount, 64) +// Subscribe sends a websocket message to receive data from the channel +func (e *Exchange) Subscribe(ctx context.Context, conn websocket.Connection, subs subscription.List) error { + subs, err := subs.ExpandTemplates(e) if err != nil { return err } - side, ok := notification[5].(string) - if !ok { - return fmt.Errorf("%w order type not string", errTypeAssertionFailure) - } - orderSide := order.Buy - if side == "0" { - orderSide = order.Sell - } - - // null returned so ok check is not needed - clientOrderID, _ := notification[6].(string) - - return e.Websocket.DataHandler.Send(ctx, &order.Detail{ - Exchange: e.Name, - OrderID: strconv.FormatFloat(orderID, 'f', -1, 64), - Pair: pair, - AssetType: asset.Spot, - Side: orderSide, - Price: orderPrice, - Amount: orderAmount, - RemainingAmount: orderAmount, - ClientOrderID: clientOrderID, - Status: order.Pending, - }) + return e.manageSubs(ctx, "subscribe", conn, subs, &e.spotSubMtx) } -func (e *Exchange) processAccountOrderUpdate(ctx context.Context, notification []any) error { - if len(notification) < 5 { - return errNotEnoughData - } - - orderID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w order id not float64", errTypeAssertionFailure) - } - - a, ok := notification[2].(string) - if !ok { - return fmt.Errorf("%w amount not string", errTypeAssertionFailure) - } - amount, err := strconv.ParseFloat(a, 64) +// Unsubscribe sends a websocket message to stop receiving data from the channel +func (e *Exchange) Unsubscribe(ctx context.Context, conn websocket.Connection, subs subscription.List) error { + subs, err := subs.ExpandTemplates(e) if err != nil { return err } + return e.manageSubs(ctx, "unsubscribe", conn, subs, &e.spotSubMtx) +} - oType, ok := notification[3].(string) - if !ok { - return fmt.Errorf("%w order type not string", errTypeAssertionFailure) - } - - var oStatus order.Status - var cancelledAmount float64 - if oType == "c" { - if len(notification) < 6 { - return errNotEnoughData +func (e *Exchange) manageSubs(ctx context.Context, operation string, conn websocket.Connection, subscs subscription.List, sendMsgLock *sync.Mutex) error { + var errs error + for _, s := range subscs { + payload, err := e.handleSubscription(operation, s) + if err != nil { + errs = common.AppendError(errs, err) + continue } - cancel, ok := notification[5].(string) - if !ok { - return fmt.Errorf("%w cancel amount not string", errTypeAssertionFailure) + epl := sWebsocketPublicEPL + switch { + case s.Asset == asset.Futures && s.Authenticated: + epl = fWebsocketPrivateEPL + case s.Asset == asset.Futures: + epl = fWebsocketPublicEPL + case s.Authenticated: + epl = sWebsocketPrivateEPL } - cancelledAmount, err = strconv.ParseFloat(cancel, 64) + sendMsgLock.Lock() + result, err := conn.SendMessageReturnResponse(ctx, epl, "subscription", &payload) + sendMsgLock.Unlock() if err != nil { - return err + errs = common.AppendError(errs, fmt.Errorf("%w %s channel %q: %w", websocket.ErrSubscriptionFailure, operation, payload.Channel[0], err)) + continue } - - if amount > 0 { - oStatus = order.PartiallyCancelled - } else { - oStatus = order.Cancelled + var subscriptionResponse *SubscriptionResponse + if err := json.Unmarshal(result, &subscriptionResponse); err != nil { + errs = common.AppendError(errs, err) + continue } - } else { - if amount > 0 { - oStatus = order.PartiallyFilled - } else { - oStatus = order.Filled + if subscriptionResponse.Event == "error" { + errs = common.AppendError(errs, fmt.Errorf("%w %s channel %q", websocket.ErrSubscriptionFailure, operation, payload.Channel[0])) + continue } - } - - // null returned so ok check is not needed - clientOrderID, _ := notification[4].(string) - - return e.Websocket.DataHandler.Send(ctx, &order.Detail{ - Exchange: e.Name, - RemainingAmount: cancelledAmount, - Amount: amount + cancelledAmount, - ExecutedAmount: amount, - OrderID: strconv.FormatFloat(orderID, 'f', -1, 64), - Type: order.Limit, - Status: oStatus, - AssetType: asset.Spot, - ClientOrderID: clientOrderID, - }) -} - -func (e *Exchange) processAccountOrderLimit(ctx context.Context, notification []any) error { - if len(notification) != 9 { - return errNotEnoughData - } - - currencyID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w currency ID not string", errTypeAssertionFailure) - } - pair, err := e.details.GetPair(currencyID) - if err != nil { - if !errors.Is(err, errIDNotFoundInPairMap) { - return err + if operation == "subscribe" { + err = e.Websocket.AddSuccessfulSubscriptions(conn, s) + } else { + err = e.Websocket.RemoveSubscriptions(conn, s) } - log.Errorf(log.WebsocketMgr, - "%s - Unknown currency pair ID. Currency will appear as the pair ID: '%v'", - e.Name, - currencyID) - } - - orderID, ok := notification[2].(float64) - if !ok { - return fmt.Errorf("%w order ID not float64", errTypeAssertionFailure) + errs = common.AppendError(errs, err) } - - side, ok := notification[3].(string) - if !ok { - return fmt.Errorf("%w order type not string", errTypeAssertionFailure) - } - orderSide := order.Buy - if side == "0" { - orderSide = order.Sell - } - - rate, ok := notification[4].(string) - if !ok { - return fmt.Errorf("%w rate not string", errTypeAssertionFailure) - } - orderPrice, err := strconv.ParseFloat(rate, 64) - if err != nil { - return err - } - amount, ok := notification[5].(string) - if !ok { - return fmt.Errorf("%w amount not string", errTypeAssertionFailure) - } - orderAmount, err := strconv.ParseFloat(amount, 64) - if err != nil { - return err - } - - ts, ok := notification[6].(string) - if !ok { - return fmt.Errorf("%w time not string", errTypeAssertionFailure) - } - - var timeParse time.Time - timeParse, err = time.Parse(time.DateTime, ts) - if err != nil { - return err - } - - origAmount, ok := notification[7].(string) - if !ok { - return fmt.Errorf("%w original amount not string", errTypeAssertionFailure) - } - origOrderAmount, err := strconv.ParseFloat(origAmount, 64) - if err != nil { - return err - } - - // null returned so ok check is not needed - clientOrderID, _ := notification[8].(string) - return e.Websocket.DataHandler.Send(ctx, &order.Detail{ - Exchange: e.Name, - Price: orderPrice, - RemainingAmount: orderAmount, - ExecutedAmount: origOrderAmount - orderAmount, - Amount: origOrderAmount, - OrderID: strconv.FormatFloat(orderID, 'f', -1, 64), - Type: order.Limit, - Side: orderSide, - Status: order.New, - AssetType: asset.Spot, - Date: timeParse, - Pair: pair, - ClientOrderID: clientOrderID, - }) -} - -func (e *Exchange) processAccountBalanceUpdate(ctx context.Context, notification []any) error { - if len(notification) < 4 { - return errNotEnoughData - } - - currencyID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w currency ID not float64", errTypeAssertionFailure) - } - curr, err := e.details.GetCode(currencyID) - if err != nil { - return err - } - - walletType, ok := notification[2].(string) - if !ok { - return fmt.Errorf("%w wallet addr not string", errTypeAssertionFailure) - } - - a, ok := notification[3].(string) - if !ok { - return fmt.Errorf("%w amount not string", errTypeAssertionFailure) - } - amount, err := strconv.ParseFloat(a, 64) - if err != nil { - return err - } - - bal := accounts.Balance{ - Currency: curr, - Total: amount, - Free: amount, - } - - id := deriveWalletType(walletType) - subAccts := accounts.SubAccounts{accounts.NewSubAccount(asset.Spot, id)} - subAccts[0].Balances.Set(curr, bal) - - if err := e.Accounts.Save(ctx, subAccts, true); err != nil { - return err - } - return e.Websocket.DataHandler.Send(ctx, subAccts) -} - -func deriveWalletType(s string) string { - switch s { - case "e": - return "exchange" - case "m": - return "margin" - case "l": - return "lending" - default: - return "unknown" - } -} - -func (e *Exchange) processAccountTrades(ctx context.Context, notification []any) error { - if len(notification) < 11 { - return errNotEnoughData - } - - tradeID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w tradeID not float64", errTypeAssertionFailure) - } - - r, ok := notification[2].(string) - if !ok { - return fmt.Errorf("%w rate not string", errTypeAssertionFailure) - } - rate, err := strconv.ParseFloat(r, 64) - if err != nil { - return err - } - - a, ok := notification[3].(string) - if !ok { - return fmt.Errorf("%w amount not string", errTypeAssertionFailure) - } - amount, err := strconv.ParseFloat(a, 64) - if err != nil { - return err - } - - // notification[4].(string) is the fee multiplier - // notification[5].(string) is the funding type 0 (exchange wallet), - // 1 (borrowed funds), 2 (margin funds), or 3 (lending funds) - - orderID, ok := notification[6].(float64) - if !ok { - return fmt.Errorf("%w orderID not float64", errTypeAssertionFailure) - } - - fee, ok := notification[7].(string) - if !ok { - return fmt.Errorf("%w fee not string", errTypeAssertionFailure) - } - totalFee, err := strconv.ParseFloat(fee, 64) - if err != nil { - return err - } - - t, ok := notification[8].(string) - if !ok { - return fmt.Errorf("%w time not string", errTypeAssertionFailure) - } - timeParse, err := time.Parse(time.DateTime, t) - if err != nil { - return err - } - - // null returned so ok check is not needed - clientOrderID, _ := notification[9].(string) - - tt, ok := notification[10].(string) - if !ok { - return fmt.Errorf("%w time not string", errTypeAssertionFailure) - } - tradeTotal, err := strconv.ParseFloat(tt, 64) - if err != nil { - return err - } - - return e.Websocket.DataHandler.Send(ctx, &order.Detail{ - Exchange: e.Name, - OrderID: strconv.FormatFloat(orderID, 'f', -1, 64), - Fee: totalFee, - Trades: []order.TradeHistory{{ - Price: rate, - Amount: amount, - Fee: totalFee, - Exchange: e.Name, - TID: strconv.FormatFloat(tradeID, 'f', -1, 64), - Timestamp: timeParse, - Total: tradeTotal, - }}, - AssetType: asset.Spot, - ClientOrderID: clientOrderID, - }) -} - -func (e *Exchange) processAccountKilledOrder(ctx context.Context, notification []any) error { - if len(notification) < 3 { - return errNotEnoughData - } - - orderID, ok := notification[1].(float64) - if !ok { - return fmt.Errorf("%w order ID not float64", errTypeAssertionFailure) - } - - // null returned so ok check is not needed - clientOrderID, _ := notification[2].(string) - - return e.Websocket.DataHandler.Send(ctx, &order.Detail{ - Exchange: e.Name, - OrderID: strconv.FormatFloat(orderID, 'f', -1, 64), - Status: order.Cancelled, - AssetType: asset.Spot, - ClientOrderID: clientOrderID, - }) + return errs } -func (e *Exchange) processTrades(currencyID float64, subData []any) error { - if !e.IsSaveTradeDataEnabled() { - return nil - } - pair, err := e.details.GetPair(currencyID) - if err != nil { - return err - } - - if len(subData) != 6 { - return errNotEnoughData - } - - var tradeID string - switch tradeIDData := subData[1].(type) { // tradeID type intermittently changes - case string: - tradeID = tradeIDData - case float64: - tradeID = strconv.FormatFloat(tradeIDData, 'f', -1, 64) - default: - return fmt.Errorf("unhandled type for websocket trade update: %v", - tradeIDData) - } - - orderSide, ok := subData[2].(float64) - if !ok { - return fmt.Errorf("%w order side not float64", - errTypeAssertionFailure) - } - - side := order.Buy - if orderSide != 1 { - side = order.Sell - } - - v, ok := subData[3].(string) - if !ok { - return fmt.Errorf("%w volume not string", - errTypeAssertionFailure) - } - volume, err := strconv.ParseFloat(v, 64) - if err != nil { - return err - } - rate, ok := subData[4].(string) - if !ok { - return fmt.Errorf("%w rate not string", errTypeAssertionFailure) - } - price, err := strconv.ParseFloat(rate, 64) - if err != nil { - return err - } - timestamp, ok := subData[5].(float64) - if !ok { - return fmt.Errorf("%w time not float64", errTypeAssertionFailure) - } - - return e.AddTradesToBuffer(trade.Data{ - TID: tradeID, - Exchange: e.Name, - CurrencyPair: pair, - AssetType: asset.Spot, - Side: side, - Price: price, - Amount: volume, - Timestamp: time.Unix(int64(timestamp), 0), - }) -} +const subTplText = ` +{{- range $asset, $pairs := $.AssetPairs -}} + {{- channelName $.S -}} + {{- if eq $.S.Channel "candles" -}}_{{- interval $.S.Interval | lower -}}{{- end -}} + {{ $.AssetSeparator }} +{{- end -}} +` diff --git a/exchanges/poloniex/poloniex_websocket_trade.go b/exchanges/poloniex/poloniex_websocket_trade.go new file mode 100644 index 00000000000..a2e79fd06ab --- /dev/null +++ b/exchanges/poloniex/poloniex_websocket_trade.go @@ -0,0 +1,103 @@ +package poloniex + +import ( + "context" + "fmt" + + "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/encoding/json" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" +) + +// WsCreateOrder create an order for an account. +func (e *Exchange) WsCreateOrder(ctx context.Context, arg *PlaceOrderRequest) (*WsOrderIDResponse, error) { + if err := validateOrderRequest(arg); err != nil { + return nil, err + } + resp, err := SendWebsocketRequest[*WsOrderIDResponse](ctx, e, "createOrder", arg) + if err != nil { + return nil, fmt.Errorf("%w: %w", order.ErrPlaceFailed, err) + } + if len(resp) != 1 || resp[0] == nil { + return nil, fmt.Errorf("%w: %w", order.ErrPlaceFailed, common.ErrInvalidResponse) + } + return resp[0], nil +} + +// WsCancelMultipleOrdersByIDs batch cancels one or many active orders in an account by their IDs through the websocket stream. +func (e *Exchange) WsCancelMultipleOrdersByIDs(ctx context.Context, orderIDs, clientOrderIDs []string) ([]*WsCancelOrderResponse, error) { + if len(clientOrderIDs) == 0 && len(orderIDs) == 0 { + return nil, order.ErrOrderIDNotSet + } + params := make(map[string][]string) + if len(clientOrderIDs) > 0 { + params["clientOrderIds"] = clientOrderIDs + } + if len(orderIDs) > 0 { + params["orderIds"] = orderIDs + } + resp, err := SendWebsocketRequest[*WsCancelOrderResponse](ctx, e, "cancelOrders", params) + if err != nil { + // Return resp, which contains the full response including both + // successful and failed cancellation attempts. + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil +} + +// WsCancelTradeOrders batch cancels all orders in an account. +func (e *Exchange) WsCancelTradeOrders(ctx context.Context, symbols []string, accountTypes []AccountType) ([]*WsCancelOrderResponse, error) { + args := make(map[string]any) + if len(symbols) > 0 { + args["symbols"] = symbols + } + if len(accountTypes) > 0 { + args["accountTypes"] = accountTypes + } + resp, err := SendWebsocketRequest[*WsCancelOrderResponse](ctx, e, "cancelAllOrders", args) + if err != nil { + // Return resp, which contains the full response including both + // successful and failed cancellation attempts. + return resp, fmt.Errorf("%w: %w", order.ErrCancelFailed, err) + } + return resp, nil +} + +// SendWebsocketRequest sends a websocket request through the private connection +func SendWebsocketRequest[T hasError](ctx context.Context, + e *Exchange, + event string, + arg any, +) (response []T, err error) { + conn, err := e.Websocket.GetConnection(connSpotPrivate) + if err != nil { + return nil, err + } + + input := &struct { + ID string `json:"id"` + Event string `json:"event"` + Params any `json:"params"` + }{ + ID: e.MessageID(), + Event: event, + Params: arg, + } + + // Locks due to the endpoint not returning identifying packets so outbound subs and inbound responses can be matched. + e.spotSubMtx.Lock() + result, err := conn.SendMessageReturnResponse(ctx, sWebsocketPrivateEPL, input.ID, input) + e.spotSubMtx.Unlock() + if err != nil { + return nil, err + } + + if err := json.Unmarshal(result, &WebsocketResponse{Data: &response}); err != nil { + return nil, err + } + if response == nil { + return nil, common.ErrNoResponse + } + + return response, checkForErrorInSliceResponse(response) +} diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index 708b1c389b1..75558eb3b80 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -10,10 +10,13 @@ import ( "strings" "time" + "github.com/shopspring/decimal" "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/common/key" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchange/accounts" + "github.com/thrasher-corp/gocryptotrader/exchange/order/limits" "github.com/thrasher-corp/gocryptotrader/exchange/websocket" "github.com/thrasher-corp/gocryptotrader/exchange/websocket/buffer" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" @@ -22,6 +25,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate" "github.com/thrasher-corp/gocryptotrader/exchanges/futures" "github.com/thrasher-corp/gocryptotrader/exchanges/kline" + "github.com/thrasher-corp/gocryptotrader/exchanges/margin" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" @@ -30,29 +34,45 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" + "github.com/thrasher-corp/gocryptotrader/types" +) + +var ( + errChainsNotFound = errors.New("chains not found") + errAllMustBeEqual = errors.New("all must be equal") +) + +var assetPairStores = map[asset.Item]currency.PairStore{ + asset.Futures: { + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + }, + asset.Spot: { + AssetEnabled: true, + RequestFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}, + }, +} + +const ( + connSpotPublic = "spot:public" + connSpotPrivate = "spot:private" + connFuturesPublic = "futures:public" + connFuturesPrivate = "futures:private" ) // SetDefaults sets default settings for poloniex func (e *Exchange) SetDefaults() { e.Name = "Poloniex" e.Enabled = true - e.Verbose = true e.API.CredentialsValidator.RequiresKey = true e.API.CredentialsValidator.RequiresSecret = true - requestFmt := ¤cy.PairFormat{ - Delimiter: currency.UnderscoreDelimiter, - Uppercase: true, - } - - configFmt := ¤cy.PairFormat{ - Delimiter: currency.UnderscoreDelimiter, - Uppercase: true, - } - - err := e.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot) - if err != nil { - log.Errorln(log.ExchangeSys, err) + for a, ps := range assetPairStores { + if err := e.SetAssetPairStore(a, ps); err != nil { + log.Errorf(log.ExchangeSys, "%s error storing %q default asset formats: %s", e.Name, a, err) + } } e.Features = exchange.Features{ @@ -63,10 +83,12 @@ func (e *Exchange) SetDefaults() { TickerBatching: true, TickerFetching: true, KlineFetching: true, + CandleHistory: true, TradeFetching: true, OrderbookFetching: true, AutoPairUpdates: true, AccountInfo: true, + AccountBalance: true, GetOrder: true, GetOrders: true, CancelOrder: true, @@ -83,14 +105,18 @@ func (e *Exchange) SetDefaults() { MultiChainWithdrawals: true, }, WebsocketCapabilities: protocol.Features{ + TickerBatching: true, TickerFetching: true, TradeFetching: true, + CandleHistory: true, OrderbookFetching: true, Subscribe: true, Unsubscribe: true, AuthenticatedEndpoints: true, GetOrders: true, GetOrder: true, + SubmitOrder: true, + CancelOrder: true, }, WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission | exchange.NoFiatWithdrawals, @@ -120,22 +146,26 @@ func (e *Exchange) SetDefaults() { GlobalResultLimit: 500, }, }, + Subscriptions: defaultSubscriptions.Clone(), } - + var err error e.Requester, err = request.New(e.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), - request.WithLimiter(GetRateLimit())) + request.WithLimiter(rateLimits)) if err != nil { log.Errorln(log.ExchangeSys, err) } - e.API.Endpoints = e.NewEndpoints() - err = e.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{ - exchange.RestSpot: poloniexAPIURL, - exchange.RestSpotSupplementary: poloniexAltAPIUrl, - exchange.WebsocketSpot: poloniexWebsocketAddress, - }) - if err != nil { - log.Errorln(log.ExchangeSys, err) + if e.API.Endpoints == nil { + e.API.Endpoints = e.NewEndpoints() + if err := e.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{ + exchange.RestSpot: apiURL, + exchange.WebsocketSpot: websocketURL, + exchange.WebsocketPrivate: privateWebsocketURL, + exchange.WebsocketFutures: futuresWebsocketPublicURL, + exchange.WebsocketFuturesPrivate: futuresWebsocketPrivateURL, + }); err != nil { + log.Errorln(log.ExchangeSys, err) + } } e.Websocket = websocket.NewManager() e.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit @@ -145,132 +175,272 @@ func (e *Exchange) SetDefaults() { // Setup sets user exchange configuration settings func (e *Exchange) Setup(exch *config.Exchange) error { - err := exch.Validate() - if err != nil { + if err := exch.Validate(); err != nil { return err } if !exch.Enabled { e.SetEnabled(false) return nil } - err = e.SetupDefaults(exch) - if err != nil { + if err := e.SetupDefaults(exch); err != nil { return err } - wsRunningURL, err := e.API.Endpoints.GetURL(exchange.WebsocketSpot) + if err := e.Websocket.Setup(&websocket.ManagerSetup{ + ExchangeConfig: exch, + FillsFeed: e.Features.Enabled.FillsFeed, + TradeFeed: e.Features.Enabled.TradeFeed, + Features: &e.Features.Supports.WebsocketCapabilities, + OrderbookBufferConfig: buffer.Config{ + SortBuffer: true, + SortBufferByUpdateIDs: true, + }, + UseMultiConnectionManagement: true, + }); err != nil { + return err + } + wsSpot, err := e.API.Endpoints.GetURL(exchange.WebsocketSpot) if err != nil { return err } - - err = e.Websocket.Setup(&websocket.ManagerSetup{ - ExchangeConfig: exch, - DefaultURL: poloniexWebsocketAddress, - RunningURL: wsRunningURL, - Connector: e.WsConnect, + if err := e.Websocket.SetupNewConnection(&websocket.ConnectionSetup{ + ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, + ResponseMaxLimit: exch.WebsocketResponseMaxLimit, + URL: wsSpot, + RateLimit: request.NewWeightedRateLimitByDuration(2 * time.Millisecond), Subscriber: e.Subscribe, Unsubscriber: e.Unsubscribe, - GenerateSubscriptions: e.GenerateDefaultSubscriptions, - Features: &e.Features.Supports.WebsocketCapabilities, - OrderbookBufferConfig: buffer.Config{ - SortBuffer: true, - SortBufferByUpdateIDs: true, - }, - }) + GenerateSubscriptions: e.generateSubscriptions, + Handler: e.wsHandleData, + Connector: e.wsConnect, + MessageFilter: connSpotPublic, + }); err != nil { + return err + } + wsSpotPrivate, err := e.API.Endpoints.GetURL(exchange.WebsocketPrivate) + if err != nil { + return err + } + if err := e.Websocket.SetupNewConnection(&websocket.ConnectionSetup{ + ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, + ResponseMaxLimit: exch.WebsocketResponseMaxLimit, + URL: wsSpotPrivate, + RateLimit: request.NewWeightedRateLimitByDuration(2 * time.Millisecond), + Subscriber: e.Subscribe, + Unsubscriber: e.Unsubscribe, + GenerateSubscriptions: e.generatePrivateSubscriptions, + Handler: e.wsHandleData, + Connector: e.wsConnect, + MessageFilter: connSpotPrivate, + Authenticate: e.authenticateSpotAuthConn, + }); err != nil { + return err + } + wsFutures, err := e.API.Endpoints.GetURL(exchange.WebsocketFutures) if err != nil { return err } + if err := e.Websocket.SetupNewConnection(&websocket.ConnectionSetup{ + URL: wsFutures, + ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, + RateLimit: request.NewWeightedRateLimitByDuration(2 * time.Millisecond), + ResponseMaxLimit: exch.WebsocketResponseMaxLimit, + Handler: e.wsFuturesHandleData, + Subscriber: e.SubscribeFutures, + Unsubscriber: e.UnsubscribeFutures, + GenerateSubscriptions: e.generateFuturesSubscriptions, + Connector: e.wsConnect, + MessageFilter: connFuturesPublic, + }); err != nil { + return err + } + wsFuturesPrivate, err := e.API.Endpoints.GetURL(exchange.WebsocketFuturesPrivate) + if err != nil { + return err + } return e.Websocket.SetupNewConnection(&websocket.ConnectionSetup{ - ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, - ResponseMaxLimit: exch.WebsocketResponseMaxLimit, + URL: wsFuturesPrivate, + ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, + ResponseMaxLimit: exch.WebsocketResponseMaxLimit, + RateLimit: request.NewWeightedRateLimitByDuration(2 * time.Millisecond), + Handler: e.wsFuturesHandleData, + Subscriber: e.SubscribeFutures, + Unsubscriber: e.UnsubscribeFutures, + GenerateSubscriptions: e.generateFuturesPrivateSubscriptions, + Connector: e.wsConnect, + MessageFilter: connFuturesPrivate, + Authenticate: e.authenticateFuturesAuthConn, }) } -// FetchTradablePairs returns a list of the exchanges tradable pairs -func (e *Exchange) FetchTradablePairs(ctx context.Context, _ asset.Item) (currency.Pairs, error) { - // TODO: Upgrade to new API version for fetching operational pairs. - resp, err := e.GetTicker(ctx) - if err != nil { - return nil, err - } - - pairs := make([]currency.Pair, 0, len(resp)) - for key, info := range resp { - // Poloniex returns 0 for highest bid and lowest ask if support has been - // dropped from the front end. We don't want to add these pairs. - if info.HighestBid == 0 || info.LowestAsk == 0 { - continue +// FetchTradablePairs returns a list of the exchange's tradable pairs +func (e *Exchange) FetchTradablePairs(ctx context.Context, assetType asset.Item) (currency.Pairs, error) { + switch assetType { + case asset.Spot: + resp, err := e.GetSymbols(ctx) + if err != nil { + return nil, err + } + pairs := make([]currency.Pair, 0, len(resp)) + for _, symbolDetail := range resp { + if !strings.EqualFold(symbolDetail.State, "NORMAL") { + continue + } + pairs = append(pairs, symbolDetail.Symbol) } - var pair currency.Pair - pair, err = currency.NewPairFromString(key) + return pairs, nil + case asset.Futures: + instruments, err := e.GetFuturesAllProducts(ctx, currency.EMPTYPAIR) if err != nil { return nil, err } - pairs = append(pairs, pair) + pairs := make(currency.Pairs, 0, len(instruments)) + for _, productInfo := range instruments { + if !strings.EqualFold(productInfo.Status, "Open") { + continue + } + pairs = append(pairs, productInfo.Symbol) + } + return pairs, nil } - return pairs, nil + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) } // UpdateTradablePairs updates the exchanges available pairs and stores // them in the exchanges config func (e *Exchange) UpdateTradablePairs(ctx context.Context) error { - pairs, err := e.FetchTradablePairs(ctx, asset.Spot) - if err != nil { - return err - } - if err := e.UpdatePairs(pairs, asset.Spot, false); err != nil { - return err + for _, assetType := range e.GetAssetTypes(false) { + pairs, err := e.FetchTradablePairs(ctx, assetType) + if err != nil { + return err + } + if err := e.UpdatePairs(pairs, assetType, false); err != nil { + return err + } } return e.EnsureOnePairEnabled() } // UpdateTickers updates the ticker for all currency pairs of a given asset type -func (e *Exchange) UpdateTickers(ctx context.Context, a asset.Item) error { - tick, err := e.GetTicker(ctx) - if err != nil { - return err - } - - enabledPairs, err := e.GetEnabledPairs(a) - if err != nil { - return err - } - for i := range enabledPairs { - fPair, err := e.FormatExchangeCurrency(enabledPairs[i], a) +func (e *Exchange) UpdateTickers(ctx context.Context, assetType asset.Item) error { + switch assetType { + case asset.Spot: + ticks, err := e.GetTickers(ctx) if err != nil { return err } - curr := fPair.String() - if _, ok := tick[curr]; !ok { - continue + for _, tick := range ticks { + if err := ticker.ProcessTicker(&ticker.Price{ + ExchangeName: e.Name, + AssetType: assetType, + Pair: tick.Symbol, + Last: tick.MarkPrice.Float64(), + Low: tick.Low.Float64(), + Ask: tick.Ask.Float64(), + Bid: tick.Bid.Float64(), + High: tick.High.Float64(), + QuoteVolume: tick.QuoteAmount.Float64(), + Volume: tick.BaseAmount.Float64(), + }); err != nil { + return err + } } - - err = ticker.ProcessTicker(&ticker.Price{ - Pair: enabledPairs[i], - Ask: tick[curr].LowestAsk, - Bid: tick[curr].HighestBid, - High: tick[curr].High24Hr, - Last: tick[curr].Last, - Low: tick[curr].Low24Hr, - Volume: tick[curr].BaseVolume, - QuoteVolume: tick[curr].QuoteVolume, - ExchangeName: e.Name, - AssetType: a, - }) + case asset.Futures: + ticks, err := e.GetFuturesMarket(ctx, currency.EMPTYPAIR) if err != nil { return err } + for _, tick := range ticks { + if err := ticker.ProcessTicker(&ticker.Price{ + ExchangeName: e.Name, + AssetType: assetType, + Pair: tick.Symbol, + LastUpdated: tick.EndTime.Time(), + Volume: tick.BaseAmount.Float64(), + QuoteVolume: tick.QuoteAmount.Float64(), + BidSize: tick.BestBidSize.Float64(), + Bid: tick.BestBidPrice.Float64(), + AskSize: tick.BestAskSize.Float64(), + Ask: tick.BestAskPrice.Float64(), + }); err != nil { + return err + } + } + default: + return fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) } return nil } // UpdateTicker updates and returns the ticker for a currency pair -func (e *Exchange) UpdateTicker(ctx context.Context, currencyPair currency.Pair, a asset.Item) (*ticker.Price, error) { - if err := e.UpdateTickers(ctx, a); err != nil { - return nil, err +func (e *Exchange) UpdateTicker(ctx context.Context, pair currency.Pair, assetType asset.Item) (*ticker.Price, error) { + switch assetType { + case asset.Spot: + tickerResult, err := e.GetTicker(ctx, pair) + if err != nil { + return nil, err + } + if err := ticker.ProcessTicker(&ticker.Price{ + High: tickerResult.High.Float64(), + Low: tickerResult.Low.Float64(), + Bid: tickerResult.Bid.Float64(), + BidSize: tickerResult.BidQuantity.Float64(), + Ask: tickerResult.Ask.Float64(), + AskSize: tickerResult.AskQuantity.Float64(), + QuoteVolume: tickerResult.QuoteAmount.Float64(), + Volume: tickerResult.BaseAmount.Float64(), + Open: tickerResult.Open.Float64(), + Close: tickerResult.Close.Float64(), + MarkPrice: tickerResult.MarkPrice.Float64(), + Pair: tickerResult.Symbol, + ExchangeName: e.Name, + AssetType: asset.Spot, + LastUpdated: tickerResult.Timestamp.Time(), + }); err != nil { + return nil, err + } + return ticker.GetTicker(e.Name, pair, assetType) + case asset.Futures: + tickerResult, err := e.GetFuturesMarket(ctx, pair) + if err != nil { + return nil, err + } + if len(tickerResult) != 1 { + return nil, common.ErrInvalidResponse + } + if err := ticker.ProcessTicker(&ticker.Price{ + High: tickerResult[0].HighPrice.Float64(), + Low: tickerResult[0].LowPrice.Float64(), + Bid: tickerResult[0].BestBidPrice.Float64(), + BidSize: tickerResult[0].BestBidSize.Float64(), + Ask: tickerResult[0].BestAskPrice.Float64(), + AskSize: tickerResult[0].BestAskSize.Float64(), + Volume: tickerResult[0].BaseAmount.Float64(), + QuoteVolume: tickerResult[0].QuoteAmount.Float64(), + Open: tickerResult[0].OpeningPrice.Float64(), + Close: tickerResult[0].ClosingPrice.Float64(), + MarkPrice: tickerResult[0].MarkPrice.Float64(), + Pair: tickerResult[0].Symbol, + ExchangeName: e.Name, + AssetType: asset.Futures, + LastUpdated: tickerResult[0].Timestamp.Time(), + }); err != nil { + return nil, err + } + return ticker.GetTicker(e.Name, pair, assetType) + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) + } +} + +func orderbookLevelFromSlice(data []types.Number) orderbook.Levels { + obs := make(orderbook.Levels, len(data)/2) + for i := range obs { + obs[i].Price = data[i*2].Float64() + obs[i].Amount = data[i*2+1].Float64() } - return ticker.GetTicker(e.Name, currencyPair, a) + return obs } // UpdateOrderbook updates and returns the orderbook for a currency pair @@ -281,106 +451,114 @@ func (e *Exchange) UpdateOrderbook(ctx context.Context, pair currency.Pair, asse if err := e.CurrencyPairs.IsAssetEnabled(assetType); err != nil { return nil, err } - callingBook := &orderbook.Book{ + fPair, err := e.FormatExchangeCurrency(pair, assetType) + if err != nil { + return nil, err + } + book := &orderbook.Book{ Exchange: e.Name, - Pair: pair, + Pair: fPair, Asset: assetType, ValidateOrderbook: e.ValidateOrderbook, } - orderbookNew, err := e.GetOrderbook(ctx, "", poloniexMaxOrderbookDepth) - if err != nil { - return callingBook, err - } - - enabledPairs, err := e.GetEnabledPairs(assetType) - if err != nil { - return callingBook, err - } - for i := range enabledPairs { - pFmt, err := e.GetPairFormat(assetType, true) + switch assetType { + case asset.Spot: + orderbookNew, err := e.GetOrderbook(ctx, fPair, 0, 150) if err != nil { return nil, err } - fP := enabledPairs[i].Format(pFmt) - data, ok := orderbookNew.Data[fP.Base.String()+fP.Delimiter+fP.Quote.String()] - if !ok { - data, ok = orderbookNew.Data[fP.Quote.String()+fP.Delimiter+fP.Base.String()] - if !ok { - continue - } - } - book := &orderbook.Book{ - Exchange: e.Name, - Pair: enabledPairs[i], - Asset: assetType, - ValidateOrderbook: e.ValidateOrderbook, - } - - book.Bids = make(orderbook.Levels, len(data.Bids)) - for y := range data.Bids { - book.Bids[y] = orderbook.Level{ - Amount: data.Bids[y].Amount, - Price: data.Bids[y].Price, - } - } - - book.Asks = make(orderbook.Levels, len(data.Asks)) - for y := range data.Asks { - book.Asks[y] = orderbook.Level{ - Amount: data.Asks[y].Amount, - Price: data.Asks[y].Price, - } - } - err = book.Process() + book.Bids = orderbookLevelFromSlice(orderbookNew.Bids) + book.Asks = orderbookLevelFromSlice(orderbookNew.Asks) + case asset.Futures: + orderbookNew, err := e.GetFuturesOrderBook(ctx, fPair, 0, 150) if err != nil { - return book, err + return nil, err } + book.Bids = orderbookNew.Bids.Levels() + book.Asks = orderbookNew.Asks.Levels() + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) + } + if err := book.Process(); err != nil { + return book, err } - return orderbook.Get(e.Name, pair, assetType) + return orderbook.Get(e.Name, fPair, assetType) } // UpdateAccountBalances retrieves currency balances func (e *Exchange) UpdateAccountBalances(ctx context.Context, assetType asset.Item) (accounts.SubAccounts, error) { - resp, err := e.GetBalances(ctx) - if err != nil { - return nil, err - } - subAccts := accounts.SubAccounts{accounts.NewSubAccount(assetType, "")} - for curr, bal := range resp { - subAccts[0].Balances.Set(curr, accounts.Balance{Total: bal}) + switch assetType { + case asset.Spot, asset.Futures: + accountBalance, err := e.GetSubAccountBalances(ctx) + if err != nil { + return nil, err + } + subAccts := accounts.SubAccounts{} + for _, subAccountBalances := range accountBalance { + a := accounts.NewSubAccount(stringToAccountType(subAccountBalances.AccountType), subAccountBalances.AccountID) + if subAccountBalances.AccountType == "FUTURES" { + for _, bal := range subAccountBalances.Balances { + a.Balances.Set(bal.Currency, accounts.Balance{ + Currency: bal.Currency, + Total: bal.AccountEquity.Float64(), + Hold: bal.FrozenFunds.Float64(), + Free: bal.AvailableBalance.Float64(), + }) + } + } else { + for _, bal := range subAccountBalances.Balances { + a.Balances.Set(bal.Currency, accounts.Balance{ + Currency: bal.Currency, + Total: bal.Available.Float64(), + Hold: bal.Hold.Float64(), + Free: bal.MaxAvailable.Float64(), + }) + } + } + subAccts = subAccts.Merge(a) + } + return subAccts, e.Accounts.Save(ctx, subAccts, true) + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) } - return subAccts, e.Accounts.Save(ctx, subAccts, true) } -// GetAccountFundingHistory returns funding history, deposits and withdrawals +// GetAccountFundingHistory returns funding history, deposits and +// withdrawals func (e *Exchange) GetAccountFundingHistory(ctx context.Context) ([]exchange.FundingHistory, error) { end := time.Now() walletActivity, err := e.WalletActivity(ctx, end.Add(-time.Hour*24*365), end, "") if err != nil { return nil, err } - resp := make([]exchange.FundingHistory, len(walletActivity.Deposits)) - for i := range walletActivity.Deposits { + depositsLen := len(walletActivity.Deposits) + resp := make([]exchange.FundingHistory, depositsLen+len(walletActivity.Withdrawals)) + for i, walletDeposit := range walletActivity.Deposits { resp[i] = exchange.FundingHistory{ ExchangeName: e.Name, - Status: walletActivity.Deposits[i].Status, - Timestamp: walletActivity.Deposits[i].Timestamp.Time(), - Currency: walletActivity.Deposits[i].Currency.String(), - Amount: walletActivity.Deposits[i].Amount, - CryptoToAddress: walletActivity.Deposits[i].Address, - CryptoTxID: walletActivity.Deposits[i].TransactionID, + Status: walletDeposit.Status, + Timestamp: walletDeposit.Timestamp.Time(), + Amount: walletDeposit.Amount.Float64(), + Currency: walletDeposit.Currency.String(), + CryptoToAddress: walletDeposit.Address, + CryptoTxID: walletDeposit.TransactionID, + TransferID: strconv.FormatUint(walletDeposit.DepositNumber, 10), + TransferType: "deposit", } } - for i := range walletActivity.Withdrawals { - resp[i] = exchange.FundingHistory{ + + for i, walletWithdrawal := range walletActivity.Withdrawals { + resp[depositsLen+i] = exchange.FundingHistory{ ExchangeName: e.Name, - Status: walletActivity.Withdrawals[i].Status, - Timestamp: walletActivity.Withdrawals[i].Timestamp.Time(), - Currency: walletActivity.Withdrawals[i].Currency.String(), - Amount: walletActivity.Withdrawals[i].Amount, - Fee: walletActivity.Withdrawals[i].Fee, - CryptoToAddress: walletActivity.Withdrawals[i].Address, - CryptoTxID: walletActivity.Withdrawals[i].TransactionID, + Status: walletWithdrawal.Status, + Timestamp: walletWithdrawal.Timestamp.Time(), + Currency: walletWithdrawal.Currency.String(), + Amount: walletWithdrawal.Amount.Float64(), + Fee: walletWithdrawal.Fee.Float64(), + CryptoToAddress: walletWithdrawal.Address, + CryptoTxID: walletWithdrawal.TransactionID, + TransferID: strconv.FormatUint(walletWithdrawal.WithdrawalRequestsID, 10), + TransferType: "withdrawal", } } return resp, nil @@ -394,119 +572,214 @@ func (e *Exchange) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ return nil, err } resp := make([]exchange.WithdrawalHistory, 0, len(withdrawals.Withdrawals)) - for i := range withdrawals.Withdrawals { - if !withdrawals.Withdrawals[i].Currency.Equal(c) { + for _, walletWithdrawal := range withdrawals.Withdrawals { + if !c.Equal(walletWithdrawal.Currency) { continue } - resp[i] = exchange.WithdrawalHistory{ - Status: withdrawals.Withdrawals[i].Status, - Timestamp: withdrawals.Withdrawals[i].Timestamp.Time(), - Currency: withdrawals.Withdrawals[i].Currency.String(), - Amount: withdrawals.Withdrawals[i].Amount, - Fee: withdrawals.Withdrawals[i].Fee, - CryptoToAddress: withdrawals.Withdrawals[i].Address, - CryptoTxID: withdrawals.Withdrawals[i].TransactionID, - } + resp = append(resp, exchange.WithdrawalHistory{ + Status: walletWithdrawal.Status, + Timestamp: walletWithdrawal.Timestamp.Time(), + Currency: walletWithdrawal.Currency.String(), + Amount: walletWithdrawal.Amount.Float64(), + Fee: walletWithdrawal.Fee.Float64(), + CryptoToAddress: walletWithdrawal.Address, + CryptoTxID: walletWithdrawal.TransactionID, + TransferID: strconv.FormatUint(walletWithdrawal.WithdrawalRequestsID, 10), + }) } return resp, nil } // GetRecentTrades returns the most recent trades for a currency and asset func (e *Exchange) GetRecentTrades(ctx context.Context, pair currency.Pair, assetType asset.Item) ([]trade.Data, error) { - return e.GetHistoricTrades(ctx, pair, assetType, time.Now().Add(-time.Minute*15), time.Now()) -} - -// GetHistoricTrades returns historic trade data within the timeframe provided -func (e *Exchange) GetHistoricTrades(ctx context.Context, pair currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) { - if err := common.StartEndTimeCheck(timestampStart, timestampEnd); err != nil { - return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v %w", timestampStart, timestampEnd, err) - } - var err error - pair, err = e.FormatExchangeCurrency(pair, assetType) + fPair, err := e.FormatExchangeCurrency(pair, assetType) if err != nil { return nil, err } var resp []trade.Data - ts := timestampStart -allTrades: - for { - var tradeData []TradeHistory - tradeData, err = e.GetTradeHistory(ctx, - pair.String(), - ts.Unix(), - timestampEnd.Unix()) + switch assetType { + case asset.Spot: + tradeData, err := e.GetTrades(ctx, fPair, 0) if err != nil { return nil, err } - for i := range tradeData { - var tt time.Time - tt, err = time.Parse(time.DateTime, tradeData[i].Date) + for _, td := range tradeData { + side, err := order.StringToOrderSide(td.TakerSide) if err != nil { return nil, err } - if (tt.Before(timestampStart) && !timestampStart.IsZero()) || (tt.After(timestampEnd) && !timestampEnd.IsZero()) { - break allTrades - } - var side order.Side - side, err = order.StringToOrderSide(tradeData[i].Type) + resp = append(resp, trade.Data{ + TID: td.ID, + Exchange: e.Name, + CurrencyPair: fPair, + AssetType: assetType, + Side: side, + Price: td.Price.Float64(), + Amount: td.BaseAmount.Float64(), + Timestamp: td.Timestamp.Time(), + }) + } + case asset.Futures: + futuresExecutions, err := e.GetFuturesExecution(ctx, fPair, 0) + if err != nil { + return nil, err + } + for _, fExec := range futuresExecutions { + side, err := order.StringToOrderSide(fExec.Side) if err != nil { return nil, err } resp = append(resp, trade.Data{ + TID: strconv.FormatInt(fExec.ID, 10), Exchange: e.Name, - TID: tradeData[i].TradeID, - CurrencyPair: pair, + CurrencyPair: fPair, AssetType: assetType, Side: side, - Price: tradeData[i].Rate, - Amount: tradeData[i].Amount, - Timestamp: tt, + Price: fExec.Price.Float64(), + Amount: fExec.BaseAmount.Float64(), + Timestamp: fExec.CreationTime.Time(), }) - if i == len(tradeData)-1 { - if ts.Equal(tt) { - // reached end of trades to crawl - break allTrades - } - if timestampStart.IsZero() { - break allTrades - } - ts = tt - } } + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) } - - err = e.AddTradesToBuffer(resp...) - if err != nil { + if err := e.AddTradesToBuffer(resp...); err != nil { return nil, err } - resp = trade.FilterTradesByTime(resp, timestampStart, timestampEnd) - sort.Sort(trade.ByDate(resp)) return resp, nil } +// GetHistoricTrades returns historic trade data within the timeframe provided +func (e *Exchange) GetHistoricTrades(_ context.Context, _ currency.Pair, _ asset.Item, _, _ time.Time) ([]trade.Data, error) { + return nil, common.ErrFunctionNotSupported +} + // SubmitOrder submits a new order func (e *Exchange) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) { if err := s.Validate(e.GetTradingRequirements()); err != nil { return nil, err } - - fPair, err := e.FormatExchangeCurrency(s.Pair, s.AssetType) + var err error + s.Pair, err = e.FormatExchangeCurrency(s.Pair, s.AssetType) if err != nil { return nil, err } - response, err := e.PlaceOrder(ctx, - fPair.String(), - s.Price, - s.Amount, - false, - s.Type == order.Market, - s.Side.IsLong()) - if err != nil { - return nil, err + switch s.AssetType { + case asset.Spot: + var stpMode string + switch s.TimeInForce { + case order.PostOnly: + stpMode = "EXPIRE_MAKER" + case order.GoodTillCancel: + stpMode = "EXPIRE_TAKER" + } + switch s.Type { + case order.Stop, order.StopLimit, order.TrailingStop, order.TrailingStopLimit: + var trackingDistance string + if s.Type.Is(order.TrailingStop) { + trackingDistance = strconv.FormatFloat(s.TrackingValue, 'f', -1, 64) + if s.TrackingMode == order.Percentage { + trackingDistance += "%" + } + } + var limitOffset string + if s.Type == order.TrailingStopLimit { + limitOffset = strconv.FormatFloat(s.LimitTrackingValue, 'f', -1, 64) + if s.LimitTrackingMode == order.Percentage { + limitOffset += "%" + } + } + stopDirection := "GTC" + if s.StopDirection == order.StopDown { + stopDirection = "LTE" + } + sOrder, err := e.CreateSmartOrder(ctx, &SmartOrderRequest{ + Symbol: s.Pair, + Type: OrderType(s.Type), + Side: s.Side, + AccountType: AccountType(s.AssetType), + Price: s.Price, + StopPrice: s.TriggerPrice, + BaseAmount: s.Amount, + QuoteAmount: s.QuoteAmount, + ClientOrderID: s.ClientOrderID, + TimeInForce: TimeInForce(s.TimeInForce), + TrailingOffset: trackingDistance, + LimitOffset: limitOffset, + Operator: stopDirection, + }) + if err != nil { + return nil, err + } + return s.DeriveSubmitResponse(sOrder.ID) + case order.Market, order.Limit, order.LimitMaker: + response, err := e.PlaceOrder(ctx, &PlaceOrderRequest{ + AccountType: AccountType(s.AssetType), + Symbol: s.Pair, + Price: s.Price, + BaseAmount: s.Amount, + QuoteAmount: s.QuoteAmount, + AllowBorrow: s.AutoBorrow, + Type: OrderType(s.Type), + Side: s.Side, + TimeInForce: TimeInForce(s.TimeInForce), + ClientOrderID: s.ClientOrderID, + SelfTradePreventionMode: stpMode, + SlippageTolerance: strconv.FormatFloat(s.SlippageTolerance, 'f', -1, 64), + }) + if err != nil { + return nil, err + } + return s.DeriveSubmitResponse(response.ID) + default: + return nil, fmt.Errorf("%w: %v", order.ErrUnsupportedOrderType, s.Type) + } + case asset.Futures: + switch s.Type { + case order.Market, order.Limit, order.LimitMaker: + default: + return nil, fmt.Errorf("%w: %v", order.ErrUnsupportedOrderType, s.Type) + } + var positionSide order.Side + if s.MarginType != margin.Unset { + positionSide, err = s.Side.Position() + if err != nil { + return nil, err + } + } + side := "BUY" + if s.Side.IsShort() { + side = "SELL" + } + var stpMode string + switch s.TimeInForce { + case order.PostOnly: + stpMode = "EXPIRE_MAKER" + case order.GoodTillCancel: + stpMode = "EXPIRE_TAKER" + } + response, err := e.PlaceFuturesOrder(ctx, &FuturesOrderRequest{ + ClientOrderID: s.ClientOrderID, + Side: side, + MarginMode: MarginMode(s.MarginType), + PositionSide: positionSide, + Symbol: s.Pair, + OrderType: OrderType(s.Type), + ReduceOnly: s.ReduceOnly, + TimeInForce: TimeInForce(s.TimeInForce), + Price: s.Price, + Size: s.Amount, + SelfTradePreventionMode: stpMode, + }) + if err != nil { + return nil, err + } + return s.DeriveSubmitResponse(response.OrderID) + default: + return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, s.AssetType) } - return s.DeriveSubmitResponse(strconv.FormatInt(response.OrderNumber, 10)) } // ModifyOrder modifies an existing order @@ -514,236 +787,442 @@ func (e *Exchange) ModifyOrder(ctx context.Context, action *order.Modify) (*orde if err := action.Validate(); err != nil { return nil, err } - - oID, err := strconv.ParseInt(action.OrderID, 10, 64) - if err != nil { - return nil, err - } - - resp, err := e.MoveOrder(ctx, - oID, - action.Price, - action.Amount, - action.TimeInForce.Is(order.PostOnly), - action.TimeInForce.Is(order.ImmediateOrCancel)) - if err != nil { - return nil, err - } - - modResp, err := action.DeriveModifyResponse() - if err != nil { - return nil, err + if action.AssetType != asset.Spot { + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, action.AssetType) + } + switch action.Type { + case order.Market, order.Limit, order.LimitMaker: + resp, err := e.CancelReplaceOrder(ctx, &CancelReplaceOrderRequest{ + OrderID: action.OrderID, + ClientOrderID: action.NewClientOrderID, + Price: action.Price, + BaseAmount: action.Amount, + AmendedType: action.Type.String(), + TimeInForce: TimeInForce(action.TimeInForce), + SlippageTolerance: action.SlippageTolerance, + }) + if err != nil { + return nil, err + } + modResp, err := action.DeriveModifyResponse() + if err != nil { + return nil, err + } + modResp.OrderID = resp.ID + return modResp, nil + case order.Stop, order.StopLimit: + oResp, err := e.CancelReplaceSmartOrder(ctx, &CancelReplaceSmartOrderRequest{ + OrderID: action.OrderID, + OldClientOrderID: action.ClientOrderID, + NewClientOrderID: action.NewClientOrderID, + Price: action.Price, + StopPrice: action.TriggerPrice, + QuoteAmount: action.Amount, + AmendedType: OrderType(action.Type), + ProceedOnFailure: !action.TimeInForce.Is(order.ImmediateOrCancel), + TimeInForce: TimeInForce(action.TimeInForce), + }) + if err != nil { + return nil, err + } + modResp, err := action.DeriveModifyResponse() + if err != nil { + return nil, err + } + modResp.OrderID = oResp.ID + return modResp, nil + default: + return nil, fmt.Errorf("%w: %q", order.ErrUnsupportedOrderType, action.Type) } - modResp.OrderID = strconv.FormatInt(resp.OrderNumber, 10) - return modResp, nil } // CancelOrder cancels an order by its corresponding ID number func (e *Exchange) CancelOrder(ctx context.Context, o *order.Cancel) error { - if err := o.Validate(o.StandardCancel()); err != nil { + if err := o.Validate(); err != nil { return err } - - orderIDInt, err := strconv.ParseInt(o.OrderID, 10, 64) - if err != nil { - return err + if o.OrderID == "" && o.ClientOrderID == "" { + return order.ErrOrderIDNotSet + } + var err error + switch o.AssetType { + case asset.Spot: + if IsSmartOrderType(o.Type) { + _, err = e.CancelSmartOrderByID(ctx, o.OrderID, o.ClientOrderID) + } else { + _, err = e.CancelOrderByID(ctx, o.OrderID, o.ClientOrderID) + } + case asset.Futures: + _, err = e.CancelFuturesOrder(ctx, &CancelOrderRequest{Symbol: o.Pair, OrderID: o.OrderID, ClientOrderID: o.ClientOrderID}) + default: + return fmt.Errorf("%w: %q", asset.ErrNotSupported, o.AssetType) } + return err +} - return e.CancelExistingOrder(ctx, orderIDInt) +// IsSmartOrderType returns whether an order type is a smart order type +func IsSmartOrderType(o order.Type) bool { + return o == order.Stop || o == order.StopLimit || o == order.TrailingStop || o == order.TrailingStopLimit } // CancelBatchOrders cancels an orders by their corresponding ID numbers func (e *Exchange) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.CancelBatchResponse, error) { if len(o) == 0 { - return nil, order.ErrCancelOrderIsNil + return nil, common.ErrEmptyParams } - orderIDs := make([]string, 0, len(o)) - clientOrderIDs := make([]string, 0, len(o)) + a := o[0].AssetType + p := o[0].Pair + isSmartOrder := IsSmartOrderType(o[0].Type) for i := range o { - switch { - case o[i].ClientOrderID != "": - clientOrderIDs = append(clientOrderIDs, o[i].ClientOrderID) - case o[i].OrderID != "": - orderIDs = append(orderIDs, o[i].OrderID) - default: + if o[i].AssetType != asset.Spot && o[i].AssetType != asset.Futures { + return nil, fmt.Errorf("%w: %v", asset.ErrNotSupported, o[i].AssetType) + } + if o[i].OrderID == "" && o[i].ClientOrderID == "" { return nil, order.ErrOrderIDNotSet } - } - cancelledOrders, err := e.CancelMultipleOrdersByIDs(ctx, orderIDs, clientOrderIDs) - if err != nil { - return nil, err + if o[i].AssetType != a { + return nil, fmt.Errorf("%w: %v vs %v", errAllMustBeEqual, o[i].AssetType, a) + } + switch a { + case asset.Futures: + if o[i].Pair.IsEmpty() { + return nil, currency.ErrCurrencyPairEmpty + } + if !o[i].Pair.Equal(p) { + return nil, fmt.Errorf("%w: %v vs %v", errAllMustBeEqual, o[i].Pair, p) + } + case asset.Spot: + if IsSmartOrderType(o[i].Type) != isSmartOrder { + return nil, fmt.Errorf("%w: smart orders vs standard orders", errAllMustBeEqual) + } + } + } + var orderIDs, clientOrderIDs []string + for i := range o { + if o[i].OrderID != "" { + orderIDs = append(orderIDs, o[i].OrderID) + } else { + clientOrderIDs = append(clientOrderIDs, o[i].ClientOrderID) + } } resp := &order.CancelBatchResponse{ - Status: make(map[string]string), + Status: make(map[string]string, len(o)), } - for i := range cancelledOrders { - if cancelledOrders[i].ClientOrderID != "" { - resp.Status[cancelledOrders[i].ClientOrderID] = cancelledOrders[i].State + " " + cancelledOrders[i].Message - continue + switch a { + case asset.Spot: + var ( + r []*CancelOrderResponse + err error + ) + if isSmartOrder { + r, err = e.CancelMultipleSmartOrders(ctx, &CancelOrdersRequest{ + OrderIDs: orderIDs, + ClientOrderIDs: clientOrderIDs, + }) + } else { + r, err = e.CancelOrdersByIDs(ctx, orderIDs, clientOrderIDs) + } + for _, co := range r { + if slices.Contains(orderIDs, co.OrderID) { + resp.Status[co.OrderID] = co.State + " " + co.Message + } else { + resp.Status[co.ClientOrderID] = co.State + " " + co.Message + } + } + if err != nil { + return resp, err + } + case asset.Futures: + cancelledOrders, err := e.CancelMultipleFuturesOrders(ctx, &CancelFuturesOrdersRequest{ + Symbol: p, + OrderIDs: orderIDs, + ClientOrderIDs: clientOrderIDs, + }) + for _, co := range cancelledOrders { + cancellationStatus := order.Cancelled.String() + if co.Code != 200 && co.Code != 0 { + cancellationStatus = "Failed" + } + if slices.Contains(orderIDs, co.OrderID) { + resp.Status[co.OrderID] = cancellationStatus + } else { + resp.Status[co.ClientOrderID] = cancellationStatus + } + } + if err != nil { + return resp, err } - resp.Status[cancelledOrders[i].OrderID] = cancelledOrders[i].State + " " + cancelledOrders[i].Message } return resp, nil } // CancelAllOrders cancels all orders associated with a currency pair -func (e *Exchange) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.CancelAllResponse, error) { +func (e *Exchange) CancelAllOrders(ctx context.Context, cancelOrd *order.Cancel) (order.CancelAllResponse, error) { + if cancelOrd == nil { + return order.CancelAllResponse{}, common.ErrNilPointer + } cancelAllOrdersResponse := order.CancelAllResponse{ Status: make(map[string]string), } - openOrders, err := e.GetOpenOrdersForAllCurrencies(ctx) - if err != nil { - return cancelAllOrdersResponse, err - } - - for key := range openOrders.Data { - for i := range openOrders.Data[key] { - err = e.CancelExistingOrder(ctx, openOrders.Data[key][i].OrderNumber) + switch cancelOrd.AssetType { + case asset.Spot: + var pairs currency.Pairs + if !cancelOrd.Pair.IsEmpty() { + var err error + cancelOrd.Pair, err = e.FormatExchangeCurrency(cancelOrd.Pair, cancelOrd.AssetType) + if err != nil { + return order.CancelAllResponse{}, err + } + pairs = append(pairs, cancelOrd.Pair) + } + switch { + case IsSmartOrderType(cancelOrd.Type): + var orderTypes []OrderType + if cancelOrd.Type != order.UnknownType { + orderTypes = append(orderTypes, OrderType(cancelOrd.Type)) + } + resp, err := e.CancelSmartOrders(ctx, pairs, nil, orderTypes) + for _, co := range resp { + cancelAllOrdersResponse.Status[co.OrderID] = co.State + } + if err != nil { + return cancelAllOrdersResponse, err + } + case e.Websocket.IsConnected() && e.Websocket.CanUseAuthenticatedEndpoints() && e.Websocket.CanUseAuthenticatedWebsocketForWrapper(): + wsResponse, err := e.WsCancelTradeOrders(ctx, pairs.Strings(), []AccountType{AccountType(cancelOrd.AssetType)}) + for _, wco := range wsResponse { + cancelAllOrdersResponse.Status[strconv.FormatUint(wco.OrderID, 10)] = wco.State + if wco.Code != 0 && wco.Code != 200 { + cancelAllOrdersResponse.Status[strconv.FormatUint(wco.OrderID, 10)] = "Failed" + } + } + if err != nil { + return cancelAllOrdersResponse, err + } + default: + resp, err := e.CancelTradeOrders(ctx, pairs.Strings(), []AccountType{AccountType(cancelOrd.AssetType)}) + for _, co := range resp { + cancelAllOrdersResponse.Status[co.OrderID] = co.State + if co.Code != 0 && co.Code != 200 { + cancelAllOrdersResponse.Status[co.OrderID] = "Failed" + } + } if err != nil { - id := strconv.FormatInt(openOrders.Data[key][i].OrderNumber, 10) - cancelAllOrdersResponse.Status[id] = err.Error() + return cancelAllOrdersResponse, err + } + } + case asset.Futures: + result, err := e.CancelFuturesOrders(ctx, cancelOrd.Pair, cancelOrd.Side.String()) + for _, co := range result { + cancelAllOrdersResponse.Status[co.OrderID] = order.Cancelled.String() + if co.Code != 0 && co.Code != 200 { + cancelAllOrdersResponse.Status[co.OrderID] = "Failed" } } + if err != nil { + return cancelAllOrdersResponse, err + } + default: + return order.CancelAllResponse{}, fmt.Errorf("%w: %q", asset.ErrNotSupported, cancelOrd.AssetType) } - return cancelAllOrdersResponse, nil } // GetOrderInfo returns order information based on order ID -func (e *Exchange) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, _ asset.Item) (*order.Detail, error) { - if pair.IsEmpty() { - return nil, currency.ErrCurrencyPairEmpty - } - - orderInfo := order.Detail{ - Exchange: e.Name, - Pair: pair, - } - - trades, err := e.GetAuthenticatedOrderTrades(ctx, orderID) - if err != nil && !strings.Contains(err.Error(), "Order not found") { - return nil, err - } - - for i := range trades { - var tradeHistory order.TradeHistory - tradeHistory.Exchange = e.Name - tradeHistory.Side, err = order.StringToOrderSide(trades[i].Type) +func (e *Exchange) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (*order.Detail, error) { + switch assetType { + case asset.Spot: + trades, err := e.GetTradesByOrderID(ctx, orderID) if err != nil { return nil, err } - tradeHistory.TID = trades[i].GlobalTradeID - tradeHistory.Timestamp, err = time.Parse(time.DateTime, trades[i].Date) + orderTrades := make([]order.TradeHistory, len(trades)) + for i, td := range trades { + oType, err := order.StringToOrderType(td.Type) + if err != nil { + return nil, err + } + orderTrades[i] = order.TradeHistory{ + Exchange: e.Name, + TID: td.ID, + FeeAsset: td.FeeCurrency.String(), + Price: td.Price.Float64(), + Total: td.QuoteAmount.Float64(), + Timestamp: td.CreateTime.Time(), + Amount: td.BaseAmount.Float64(), + Fee: td.FeeAmount.Float64(), + Side: td.Side, + Type: oType, + } + } + resp, err := e.GetOrder(ctx, orderID, "") + if err != nil { + smartOrders, err := e.GetSmartOrderDetails(ctx, orderID, "") + switch { + case err != nil: + return nil, err + case len(smartOrders) != 1: + return nil, fmt.Errorf("%w: expected smart order length must be 1", common.ErrInvalidResponse) + } + s := smartOrders[0] + oType, err := order.StringToOrderType(s.Type) + if err != nil { + return nil, err + } + return &order.Detail{ + Side: s.Side, + Pair: s.Symbol, + Exchange: e.Name, + Trades: orderTrades, + OrderID: s.ID, + TimeInForce: s.TimeInForce, + ClientOrderID: s.ClientOrderID, + Price: s.Price.Float64(), + QuoteAmount: s.QuoteAmount.Float64(), + Date: s.CreateTime.Time(), + LastUpdated: s.UpdateTime.Time(), + Amount: s.BaseAmount.Float64(), + Type: oType, + Status: orderStateFromString(s.State), + AssetType: stringToAccountType(s.AccountType), + TriggerPrice: s.ActivationPrice.Float64(), + }, nil + } + oType, err := order.StringToOrderType(resp.Type) if err != nil { return nil, err } - tradeHistory.Price = trades[i].Rate - tradeHistory.Amount = trades[i].Amount - tradeHistory.Total = trades[i].Total - tradeHistory.Fee = trades[i].Fee - orderInfo.Trades = append(orderInfo.Trades, tradeHistory) - } - - resp, err := e.GetAuthenticatedOrderStatus(ctx, orderID) - if err != nil { - if len(orderInfo.Trades) > 0 { // on closed orders return trades only - if strings.Contains(err.Error(), "Order not found") { - orderInfo.Status = order.Closed - } - return &orderInfo, nil + return &order.Detail{ + Price: resp.Price.Float64(), + Amount: resp.BaseAmount.Float64(), + AverageExecutedPrice: resp.AveragePrice.Float64(), + QuoteAmount: resp.QuoteAmount.Float64(), + ExecutedAmount: resp.FilledQuantity.Float64(), + RemainingAmount: resp.BaseAmount.Float64() - resp.FilledAmount.Float64(), + Cost: resp.FilledQuantity.Float64() * resp.AveragePrice.Float64(), + Side: resp.Side, + Exchange: e.Name, + OrderID: resp.ID, + ClientOrderID: resp.ClientOrderID, + Type: oType, + Status: orderStateFromString(resp.State), + AssetType: stringToAccountType(resp.AccountType), + Date: resp.CreateTime.Time(), + LastUpdated: resp.UpdateTime.Time(), + Pair: pair, + Trades: orderTrades, + TimeInForce: resp.TimeInForce, + }, nil + case asset.Futures: + fResults, err := e.GetFuturesOrderHistory(ctx, pair, order.UnknownSide, "", "", orderID, "", "", time.Time{}, time.Time{}, 0, 0) + if err != nil { + return nil, err } - return nil, err - } - - if orderInfo.Status, err = order.StringToOrderStatus(resp.Status); err != nil { - log.Errorf(log.ExchangeSys, "%s %v", e.Name, err) - } - orderInfo.Price = resp.Rate - orderInfo.Amount = resp.Amount - orderInfo.Cost = resp.Total - orderInfo.Fee = resp.Fee - orderInfo.QuoteAmount = resp.StartingAmount - - orderInfo.Side, err = order.StringToOrderSide(resp.Type) - if err != nil { - return nil, err + if len(fResults) != 1 { + return nil, order.ErrOrderNotFound + } + orderDetail := fResults[0] + oType, err := order.StringToOrderType(orderDetail.OrderType) + if err != nil { + return nil, err + } + return &order.Detail{ + Price: orderDetail.Price.Float64(), + Amount: orderDetail.Size.Float64(), + AverageExecutedPrice: orderDetail.AveragePrice.Float64(), + QuoteAmount: orderDetail.AveragePrice.Float64() * orderDetail.ExecutedQuantity.Float64(), + ExecutedAmount: orderDetail.ExecutedQuantity.Float64(), + RemainingAmount: orderDetail.Size.Float64() - orderDetail.ExecutedQuantity.Float64(), + OrderID: orderDetail.OrderID, + Exchange: e.Name, + ClientOrderID: orderDetail.ClientOrderID, + Type: oType, + Side: orderDetail.Side, + Status: orderStateFromString(orderDetail.State), + AssetType: asset.Futures, + Date: orderDetail.CreationTime.Time(), + LastUpdated: orderDetail.UpdateTime.Time(), + Pair: orderDetail.Symbol, + TimeInForce: orderDetail.TimeInForce, + }, nil + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) } +} - orderInfo.Date, err = time.Parse(time.DateTime, resp.Date) - if err != nil { - return nil, err +// orderStateFromString returns an order.Status instance from a string representation +func orderStateFromString(orderState string) order.Status { + switch strings.ToUpper(orderState) { + case "NEW": + return order.New + case "FAILED": + return order.Rejected + case "FILLED": + return order.Filled + case "CANCELED": + return order.Cancelled + case "PENDING_CANCEL": + return order.PendingCancel + case "PARTIALLY_CANCELED": + return order.PartiallyCancelled + case "PARTIALLY_FILLED": + return order.PartiallyFilled + default: + return order.UnknownStatus } - - return &orderInfo, nil } // GetDepositAddress returns a deposit address for a specified currency func (e *Exchange) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _, chain string) (*deposit.Address, error) { - depositAddrs, err := e.GetDepositAddresses(ctx) + depositAddrs, err := e.GetDepositAddresses(ctx, cryptocurrency) if err != nil { return nil, err } - // Some coins use a main address, so we must use this in conjunction with the returned - // deposit address to produce the full deposit address and tag - currencies, err := e.GetCurrencies(ctx) + // deposit address to produce the full deposit address and payment-id + currencyDetail, err := e.GetCurrency(ctx, cryptocurrency) if err != nil { return nil, err } - coinParams, ok := currencies[cryptocurrency.Upper().String()] - if !ok { - return nil, fmt.Errorf("unable to find currency %s in map", cryptocurrency) - } - - // Handle coins with payment ID's like XRP - var address, tag string - if coinParams.CurrencyType == "address-payment-id" && coinParams.DepositAddress != "" { - address = coinParams.DepositAddress - tag, ok = depositAddrs.Addresses[cryptocurrency.Upper().String()] - if !ok { - newAddr, err := e.GenerateNewAddress(ctx, cryptocurrency.Upper().String()) - if err != nil { - return nil, err + for _, networkDetail := range currencyDetail.NetworkList { + if networkDetail.CurrencyType == "address-payment-id" && networkDetail.DepositAddress != "" && (networkDetail.Blockchain == "" || networkDetail.Blockchain != chain) { + paymentID, ok := depositAddrs[cryptocurrency.Upper().String()] + if !ok { + newAddr, err := e.NewCurrencyDepositAddress(ctx, cryptocurrency) + if err != nil { + return nil, err + } + paymentID = newAddr } - tag = newAddr + return &deposit.Address{ + Address: networkDetail.DepositAddress, + Tag: paymentID, + Chain: networkDetail.Blockchain, + }, nil } - return &deposit.Address{ - Address: address, - Tag: tag, - }, nil - } - - // Handle coins like BTC or multichain coins - targetCurrency := cryptocurrency.String() - if chain != "" && !strings.EqualFold(chain, cryptocurrency.String()) { - targetCurrency = chain } - address, ok = depositAddrs.Addresses[strings.ToUpper(targetCurrency)] + var chainName string + address, ok := depositAddrs[cryptocurrency.Upper().String()] if !ok { - if len(coinParams.ChildChains) > 1 && chain != "" && !slices.Contains(coinParams.ChildChains, targetCurrency) { - // rather than assume, return an error - return nil, fmt.Errorf("currency %s has %v chains available, one of these must be specified", - cryptocurrency, - coinParams.ChildChains) - } - - coinParams, ok = currencies[strings.ToUpper(targetCurrency)] - if !ok { - return nil, fmt.Errorf("unable to find currency %s in map", cryptocurrency) - } - if coinParams.WithdrawalDepositDisabled == 1 { - return nil, fmt.Errorf("deposits and withdrawals for %v are currently disabled", targetCurrency) - } + for _, networkDetail := range currencyDetail.NetworkList { + if !networkDetail.DepositEnable { + return nil, fmt.Errorf("deposits and withdrawals for %v are currently disabled", cryptocurrency.Upper().String()) + } - newAddr, err := e.GenerateNewAddress(ctx, targetCurrency) - if err != nil { - return nil, err + newAddr, err := e.NewCurrencyDepositAddress(ctx, cryptocurrency) + if err != nil { + return nil, err + } + address = newAddr + chainName = networkDetail.Blockchain } - address = newAddr } - return &deposit.Address{Address: address}, nil + return &deposit.Address{ + Address: address, + Chain: chainName, + }, nil } // WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is @@ -752,29 +1231,31 @@ func (e *Exchange) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequ if err := withdrawRequest.Validate(); err != nil { return nil, err } - - targetCurrency := withdrawRequest.Currency.String() - if withdrawRequest.Crypto.Chain != "" { - targetCurrency = withdrawRequest.Crypto.Chain - } - v, err := e.Withdraw(ctx, targetCurrency, withdrawRequest.Crypto.Address, withdrawRequest.Amount) + v, err := e.WithdrawCurrency(ctx, &WithdrawCurrencyRequest{ + Coin: withdrawRequest.Currency, + Network: withdrawRequest.Crypto.Chain, + Address: withdrawRequest.Crypto.Address, + Amount: withdrawRequest.Amount, + AddressTag: withdrawRequest.Crypto.AddressTag, + }) if err != nil { return nil, err } return &withdraw.ExchangeResponse{ - Status: v.Response, - }, err + Name: e.Name, + ID: strconv.FormatUint(v.WithdrawRequestID, 10), + }, nil } // WithdrawFiatFunds returns a withdrawal ID when a // withdrawal is submitted -func (e *Exchange) WithdrawFiatFunds(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) { +func (e *Exchange) WithdrawFiatFunds(context.Context, *withdraw.Request) (*withdraw.ExchangeResponse, error) { return nil, common.ErrFunctionNotSupported } // WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a // withdrawal is submitted -func (e *Exchange) WithdrawFiatFundsToInternationalBank(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) { +func (e *Exchange) WithdrawFiatFundsToInternationalBank(context.Context, *withdraw.Request) (*withdraw.ExchangeResponse, error) { return nil, common.ErrFunctionNotSupported } @@ -792,124 +1273,284 @@ func (e *Exchange) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBui // GetActiveOrders retrieves any orders that are active/open func (e *Exchange) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) { - err := req.Validate() - if err != nil { - return nil, err - } - - resp, err := e.GetOpenOrdersForAllCurrencies(ctx) - if err != nil { - return nil, err + var samplePair currency.Pair + if len(req.Pairs) == 1 { + samplePair = req.Pairs[0] } - - format, err := e.GetPairFormat(asset.Spot, false) - if err != nil { - return nil, err + var sideString string + switch { + case req.Side.IsLong(): + sideString = order.Buy.String() + case req.Side.IsShort(): + sideString = order.Sell.String() } - var orders []order.Detail - for key := range resp.Data { - var symbol currency.Pair - symbol, err = currency.NewPairDelimiter(key, format.Delimiter) + switch req.AssetType { + case asset.Spot: + resp, err := e.GetOpenOrders(ctx, samplePair, sideString, "", req.FromOrderID, 0) if err != nil { return nil, err } - for i := range resp.Data[key] { - var orderSide order.Side - orderSide, err = order.StringToOrderSide(resp.Data[key][i].Type) + for _, td := range resp { + if len(req.Pairs) != 0 && !req.Pairs.Contains(td.Symbol, true) { + continue + } + oType, err := order.StringToOrderType(td.Type) if err != nil { return nil, err } - var orderDate time.Time - orderDate, err = time.Parse(time.DateTime, resp.Data[key][i].Date) + orders = append(orders, order.Detail{ + Type: oType, + OrderID: td.ID, + Side: td.Side, + Amount: td.BaseAmount.Float64(), + QuoteAmount: td.QuoteAmount.Float64(), + Date: td.CreateTime.Time(), + Price: td.Price.Float64(), + Pair: td.Symbol, + Exchange: e.Name, + TimeInForce: td.TimeInForce, + }) + } + case asset.Futures: + fOrders, err := e.GetCurrentFuturesOrders(ctx, samplePair, sideString, "", "", 0, 0, 0) + if err != nil { + return nil, err + } + for _, fOrder := range fOrders { + if len(req.Pairs) != 0 && !req.Pairs.Contains(fOrder.Symbol, true) { + continue + } + var oState order.Status + switch fOrder.State { + case "NEW": + oState = order.Active + case "PARTIALLY_FILLED": + oState = order.PartiallyFilled + default: + continue + } + var mType margin.Type + switch fOrder.MarginMode { + case "ISOLATED": + mType = margin.Isolated + case "CROSS": + mType = margin.Multi + } + oType, err := order.StringToOrderType(fOrder.OrderType) if err != nil { - log.Errorf(log.ExchangeSys, - "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", - e.Name, - "GetActiveOrders", - resp.Data[key][i].OrderNumber, - resp.Data[key][i].Date) + return nil, err } - orders = append(orders, order.Detail{ - OrderID: strconv.FormatInt(resp.Data[key][i].OrderNumber, 10), - Side: orderSide, - Amount: resp.Data[key][i].Amount, - Date: orderDate, - Price: resp.Data[key][i].Rate, - Pair: symbol, - Exchange: e.Name, + Type: oType, + OrderID: fOrder.OrderID, + Side: fOrder.Side, + Amount: fOrder.Size.Float64(), + Date: fOrder.CreationTime.Time(), + Price: fOrder.Price.Float64(), + Exchange: e.Name, + Pair: fOrder.Symbol, + ReduceOnly: fOrder.ReduceOnly.Bool(), + Leverage: fOrder.Leverage.Float64(), + ExecutedAmount: fOrder.ExecutedQuantity.Float64(), + RemainingAmount: fOrder.Size.Float64() - fOrder.ExecutedQuantity.Float64(), + ClientOrderID: fOrder.ClientOrderID, + Status: oState, + AssetType: req.AssetType, + LastUpdated: fOrder.UpdateTime.Time(), + MarginType: mType, + FeeAsset: fOrder.FeeCurrency, + Fee: fOrder.FeeAmount.Float64(), + TimeInForce: fOrder.TimeInForce, }) } + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, req.AssetType) } return req.Filter(e.Name, orders), nil } +func accountTypeString(assetType asset.Item) string { + switch assetType { + case asset.Spot: + return "SPOT" + case asset.Futures: + return "FUTURES" + default: + return "" + } +} + +func stringToAccountType(assetType string) asset.Item { + switch assetType { + case "SPOT": + return asset.Spot + case "FUTURES": + return asset.Futures + default: + return asset.Empty + } +} + // GetOrderHistory retrieves account order information -// Can Limit response to specific order status +// can Limit response to specific order status func (e *Exchange) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) { - err := req.Validate() - if err != nil { + if err := req.Validate(); err != nil { return nil, err } - - resp, err := e.GetAuthenticatedTradeHistory(ctx, - req.StartTime.Unix(), - req.EndTime.Unix(), - 10000) + if req.AssetType == asset.Spot { + switch req.Type { + case order.Market, order.Limit, order.UnknownType, order.AnyType: + oTypeString, err := orderTypeString(req.Type) + if err != nil { + return nil, err + } + resp, err := e.GetOrdersHistory(ctx, &OrdersHistoryRequest{ + AccountType: accountTypeString(req.AssetType), + OrderType: oTypeString, + Side: req.Side, + Limit: 100, + StartTime: req.StartTime, + EndTime: req.EndTime, + }) + if err != nil { + return nil, err + } + orders := make([]order.Detail, 0, len(resp)) + for _, tOrder := range resp { + if len(req.Pairs) != 0 && !req.Pairs.Contains(tOrder.Symbol, true) { + continue + } + oType, err := order.StringToOrderType(tOrder.Type) + if err != nil { + return nil, err + } + assetType, err := asset.New(tOrder.AccountType) + if err != nil { + return nil, err + } + detail := order.Detail{ + OrderID: strconv.FormatUint(tOrder.ID, 10), + Side: tOrder.Side, + Amount: tOrder.BaseAmount.Float64(), + ExecutedAmount: tOrder.FilledAmount.Float64(), + Price: tOrder.Price.Float64(), + AverageExecutedPrice: tOrder.AveragePrice.Float64(), + Pair: tOrder.Symbol, + Type: oType, + Exchange: e.Name, + QuoteAmount: tOrder.QuoteAmount.Float64(), + RemainingAmount: tOrder.BaseAmount.Float64() - tOrder.FilledQuantity.Float64(), + ClientOrderID: tOrder.ClientOrderID, + Status: orderStateFromString(tOrder.State), + AssetType: assetType, + Date: tOrder.CreateTime.Time(), + LastUpdated: tOrder.UpdateTime.Time(), + TimeInForce: tOrder.TimeInForce, + } + detail.InferCostsAndTimes() + orders = append(orders, detail) + } + return req.Filter(e.Name, orders), nil + case order.Stop, order.StopLimit, order.TrailingStop, order.TrailingStopLimit: + oTypeString, err := orderTypeString(req.Type) + if err != nil { + return nil, err + } + smartOrders, err := e.GetSmartOrderHistory(ctx, + &OrdersHistoryRequest{ + Symbol: currency.EMPTYPAIR, + AccountType: accountTypeString(req.AssetType), + OrderType: oTypeString, + Side: req.Side, + Limit: 100, + StartTime: req.StartTime, + EndTime: req.EndTime, + }, + ) + if err != nil { + return nil, err + } + orders := make([]order.Detail, 0, len(smartOrders)) + for _, smartOrder := range smartOrders { + if len(req.Pairs) != 0 && !req.Pairs.Contains(smartOrder.Symbol, true) { + continue + } + assetType, err := asset.New(smartOrder.AccountType) + if err != nil { + return nil, err + } + oType, err := order.StringToOrderType(smartOrder.Type) + if err != nil { + return nil, err + } + detail := order.Detail{ + Side: smartOrder.Side, + Amount: smartOrder.BaseAmount.Float64(), + QuoteAmount: smartOrder.QuoteAmount.Float64(), + Price: smartOrder.Price.Float64(), + TriggerPrice: smartOrder.StopPrice.Float64(), + Pair: smartOrder.Symbol, + Type: oType, + Exchange: e.Name, + OrderID: smartOrder.ID, + ClientOrderID: smartOrder.ClientOrderID, + Status: orderStateFromString(smartOrder.State), + AssetType: assetType, + Date: smartOrder.CreateTime.Time(), + LastUpdated: smartOrder.UpdateTime.Time(), + TimeInForce: smartOrder.TimeInForce, + } + detail.InferCostsAndTimes() + orders = append(orders, detail) + } + return orders, nil + default: + return nil, fmt.Errorf("%w: %q", order.ErrUnsupportedOrderType, req.Type) + } + } + oTypeString, err := orderTypeString(req.Type) if err != nil { return nil, err } - - format, err := e.GetPairFormat(asset.Spot, false) + orderHistory, err := e.GetFuturesOrderHistory(ctx, currency.EMPTYPAIR, req.Side, oTypeString, "", "", "", "", req.StartTime, req.EndTime, 0, 100) if err != nil { return nil, err } - - var orders []order.Detail - for key := range resp.Data { - var pair currency.Pair - pair, err = currency.NewPairDelimiter(key, format.Delimiter) + orders := make([]order.Detail, 0, len(orderHistory)) + for _, fOrder := range orderHistory { + if len(req.Pairs) != 0 && !req.Pairs.Contains(fOrder.Symbol, true) { + continue + } + oType, err := order.StringToOrderType(fOrder.OrderType) if err != nil { return nil, err } - - for i := range resp.Data[key] { - orderSide, err := order.StringToOrderSide(resp.Data[key][i].Type) - if err != nil { - return nil, err - } - orderDate, err := time.Parse(time.DateTime, - resp.Data[key][i].Date) - if err != nil { - log.Errorf(log.ExchangeSys, - "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", - e.Name, - "GetActiveOrders", - resp.Data[key][i].OrderNumber, - resp.Data[key][i].Date) - } - - detail := order.Detail{ - OrderID: resp.Data[key][i].GlobalTradeID, - Side: orderSide, - Amount: resp.Data[key][i].Amount, - ExecutedAmount: resp.Data[key][i].Amount, - Date: orderDate, - Price: resp.Data[key][i].Rate, - AverageExecutedPrice: resp.Data[key][i].Rate, - Pair: pair, - Status: order.Filled, - Exchange: e.Name, - } - detail.InferCostsAndTimes() - orders = append(orders, detail) + detail := order.Detail{ + Side: fOrder.Side, + Amount: fOrder.Size.Float64(), + ExecutedAmount: fOrder.ExecutedAmount.Float64(), + Price: fOrder.Price.Float64(), + Pair: fOrder.Symbol, + Type: oType, + Exchange: e.Name, + RemainingAmount: fOrder.Size.Float64() - fOrder.ExecutedAmount.Float64(), + OrderID: fOrder.OrderID, + ClientOrderID: fOrder.ClientOrderID, + Status: orderStateFromString(fOrder.State), + AssetType: asset.Futures, + Date: fOrder.CreationTime.Time(), + LastUpdated: fOrder.UpdateTime.Time(), + TimeInForce: fOrder.TimeInForce, } + detail.InferCostsAndTimes() + orders = append(orders, detail) } return req.Filter(e.Name, orders), nil } -// ValidateAPICredentials validates current credentials used for wrapper functionality +// ValidateAPICredentials validates current credentials used for wrapper +// functionality func (e *Exchange) ValidateAPICredentials(ctx context.Context, assetType asset.Item) error { _, err := e.UpdateAccountBalances(ctx, assetType) return e.CheckTransientError(err) @@ -921,28 +1562,46 @@ func (e *Exchange) GetHistoricCandles(ctx context.Context, pair currency.Pair, a if err != nil { return nil, err } - - resp, err := e.GetChartData(ctx, - req.RequestFormatted.String(), - req.Start, - req.End, - e.FormatExchangeKlineInterval(req.ExchangeInterval)) - if err != nil { - return nil, err - } - - timeSeries := make([]kline.Candle, len(resp)) - for x := range resp { - timeSeries[x] = kline.Candle{ - Time: resp[x].Date.Time(), - Open: resp[x].Open.Float64(), - High: resp[x].High.Float64(), - Low: resp[x].Low.Float64(), - Close: resp[x].Close.Float64(), - Volume: resp[x].Volume.Float64(), + switch a { + case asset.Spot: + resp, err := e.GetCandlesticks(ctx, req.RequestFormatted, req.ExchangeInterval, req.Start, req.End, req.RequestLimit) + if err != nil { + return nil, err } + timeSeries := make([]kline.Candle, len(resp)) + for i, candleData := range resp { + timeSeries[i] = kline.Candle{ + Time: candleData.StartTime.Time(), + Open: candleData.Open.Float64(), + High: candleData.High.Float64(), + Low: candleData.Low.Float64(), + Close: candleData.Close.Float64(), + Volume: candleData.BaseAmount.Float64(), + QuoteVolume: candleData.QuoteAmount.Float64(), + } + } + return req.ProcessResponse(timeSeries) + case asset.Futures: + resp, err := e.GetFuturesKlineData(ctx, req.RequestFormatted, req.ExchangeInterval, req.Start, req.End, req.RequestLimit) + if err != nil { + return nil, err + } + timeSeries := make([]kline.Candle, len(resp)) + for i, fCandle := range resp { + timeSeries[i] = kline.Candle{ + Time: fCandle.StartTime.Time(), + Open: fCandle.OpeningPrice.Float64(), + Close: fCandle.ClosingPrice.Float64(), + High: fCandle.HighestPrice.Float64(), + Low: fCandle.LowestPrice.Float64(), + Volume: fCandle.BaseAmount.Float64(), + QuoteVolume: fCandle.QuoteAmount.Float64(), + } + } + return req.ProcessResponse(timeSeries) } - return req.ProcessResponse(timeSeries) + + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, a) } // GetHistoricCandlesExtended returns candles between a time period for a set time interval @@ -951,67 +1610,222 @@ func (e *Exchange) GetHistoricCandlesExtended(ctx context.Context, pair currency if err != nil { return nil, err } - - timeSeries := make([]kline.Candle, 0, req.Size()) - for i := range req.RangeHolder.Ranges { - resp, err := e.GetChartData(ctx, - req.RequestFormatted.String(), - req.RangeHolder.Ranges[i].Start.Time, - req.RangeHolder.Ranges[i].End.Time, - e.FormatExchangeKlineInterval(req.ExchangeInterval)) - if err != nil { - return nil, err + var timeSeries []kline.Candle + switch a { + case asset.Spot: + for i := range req.RangeHolder.Ranges { + resp, err := e.GetCandlesticks(ctx, + req.RequestFormatted, + req.ExchangeInterval, + req.RangeHolder.Ranges[i].Start.Time, + req.RangeHolder.Ranges[i].End.Time, + req.RequestLimit, + ) + if err != nil { + return nil, err + } + for _, candleData := range resp { + timeSeries = append(timeSeries, kline.Candle{ + Time: candleData.StartTime.Time(), + Open: candleData.Open.Float64(), + High: candleData.High.Float64(), + Low: candleData.Low.Float64(), + Close: candleData.Close.Float64(), + Volume: candleData.BaseAmount.Float64(), + QuoteVolume: candleData.QuoteAmount.Float64(), + }) + } } - for x := range resp { - timeSeries = append(timeSeries, kline.Candle{ - Time: resp[x].Date.Time(), - Open: resp[x].Open.Float64(), - High: resp[x].High.Float64(), - Low: resp[x].Low.Float64(), - Close: resp[x].Close.Float64(), - Volume: resp[x].Volume.Float64(), - }) + case asset.Futures: + for i := range req.RangeHolder.Ranges { + resp, err := e.GetFuturesKlineData(ctx, + req.RequestFormatted, + interval, + req.RangeHolder.Ranges[i].Start.Time, + req.RangeHolder.Ranges[i].End.Time, + 500, + ) + if err != nil { + return nil, err + } + for _, fCandle := range resp { + timeSeries = append(timeSeries, kline.Candle{ + Time: fCandle.StartTime.Time().UTC(), + Open: fCandle.OpeningPrice.Float64(), + Close: fCandle.ClosingPrice.Float64(), + High: fCandle.HighestPrice.Float64(), + Low: fCandle.LowestPrice.Float64(), + Volume: fCandle.BaseAmount.Float64(), + QuoteVolume: fCandle.QuoteAmount.Float64(), + }) + } } + default: + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, a) } - return req.ProcessResponse(timeSeries) } -// GetAvailableTransferChains returns the available transfer blockchains for the specific cryptocurrency +// GetAvailableTransferChains returns the available transfer blockchains for the specific +// cryptocurrency func (e *Exchange) GetAvailableTransferChains(ctx context.Context, cryptocurrency currency.Code) ([]string, error) { - currencies, err := e.GetCurrencies(ctx) + if cryptocurrency.IsEmpty() { + return nil, currency.ErrCurrencyCodeEmpty + } + currencyDetail, err := e.GetCurrency(ctx, cryptocurrency) if err != nil { return nil, err } - - curr, ok := currencies[cryptocurrency.Upper().String()] - if !ok { - return nil, errors.New("unable to locate currency in map") + if len(currencyDetail.NetworkList) == 0 { + return nil, fmt.Errorf("%w for currency %v", errChainsNotFound, cryptocurrency) } - - return curr.ChildChains, nil + chains := make([]string, len(currencyDetail.NetworkList)) + for i, cryptoNetwork := range currencyDetail.NetworkList { + chains[i] = cryptoNetwork.Blockchain + } + return chains, nil } // GetServerTime returns the current exchange server time. func (e *Exchange) GetServerTime(ctx context.Context, _ asset.Item) (time.Time, error) { - return e.GetTimestamp(ctx) + return e.GetSystemTimestamp(ctx) } // GetFuturesContractDetails returns all contracts from the exchange by asset type -func (e *Exchange) GetFuturesContractDetails(context.Context, asset.Item) ([]futures.Contract, error) { - // TODO: implement with API upgrade - return nil, common.ErrNotYetImplemented +func (e *Exchange) GetFuturesContractDetails(ctx context.Context, assetType asset.Item) ([]futures.Contract, error) { + if !assetType.IsFutures() { + return nil, futures.ErrNotFuturesAsset + } + if assetType != asset.Futures { + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, assetType) + } + contracts, err := e.GetFuturesAllProducts(ctx, currency.EMPTYPAIR) + if err != nil { + return nil, err + } + resp := make([]futures.Contract, len(contracts)) + for i, productInfo := range contracts { + ct := futures.Quarterly + if strings.HasSuffix(productInfo.Symbol.Quote.String(), "PERP") { + ct = futures.Perpetual + } + resp[i] = futures.Contract{ + Type: ct, + Exchange: e.Name, + SettlementCurrency: productInfo.SettlementCurrency, + MarginCurrency: productInfo.SettlementCurrency, + Asset: assetType, + Name: productInfo.Symbol, + StartDate: productInfo.ListingDate.Time(), + IsActive: strings.EqualFold(productInfo.Status, "OPEN"), + Status: productInfo.Status, + MaxLeverage: float64(productInfo.Leverage), + SettlementType: futures.Linear, + } + } + return resp, nil } // GetLatestFundingRates returns the latest funding rates data -func (e *Exchange) GetLatestFundingRates(context.Context, *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) { - // TODO: implement with API upgrade - return nil, common.ErrNotYetImplemented +func (e *Exchange) GetLatestFundingRates(ctx context.Context, r *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) { + if r == nil || *r == (fundingrate.LatestRateRequest{}) { + return nil, fmt.Errorf("%w LatestRateRequest", common.ErrEmptyParams) + } + if !r.Pair.IsEmpty() { + is, err := e.IsPerpetualFutureCurrency(r.Asset, r.Pair) + if err != nil { + return nil, err + } else if !is { + return nil, fmt.Errorf("%w %s %v", futures.ErrNotPerpetualFuture, r.Asset, r.Pair) + } + } + contracts, err := e.GetFuturesHistoricalFundingRates(ctx, r.Pair, time.Time{}, time.Time{}, 0) + if err != nil { + return nil, err + } + timeChecked := time.Now() + resp := make([]fundingrate.LatestRateResponse, 0, len(contracts)) + for _, fFundingRate := range contracts { + var isPerp bool + isPerp, err = e.IsPerpetualFutureCurrency(r.Asset, fFundingRate.Symbol) + if err != nil { + return nil, err + } else if !isPerp { + continue + } + rate := fundingrate.LatestRateResponse{ + Exchange: e.Name, + Asset: r.Asset, + Pair: fFundingRate.Symbol, + LatestRate: fundingrate.Rate{ + Time: fFundingRate.FundingRateSettleTime.Time(), + Rate: decimal.NewFromFloat(fFundingRate.FundingRate.Float64()), + }, + TimeOfNextRate: fFundingRate.NextFundingTime.Time(), + TimeChecked: timeChecked, + } + rate.PredictedUpcomingRate = fundingrate.Rate{ + Time: fFundingRate.NextFundingTime.Time(), + Rate: decimal.NewFromFloat(fFundingRate.NextPredictedFundingRate.Float64()), + } + resp = append(resp, rate) + } + return resp, nil +} + +// IsPerpetualFutureCurrency ensures a given asset and currency is a perpetual future +func (e *Exchange) IsPerpetualFutureCurrency(a asset.Item, cp currency.Pair) (bool, error) { + return a == asset.Futures && strings.HasSuffix(cp.Quote.String(), "PERP"), nil } +var priceScaleMultipliers = []float64{1, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001, 0.0000000001, 0.00000000001, 0.000000000001, 0.0000000000001, 0.00000000000001, 0.000000000000001} + // UpdateOrderExecutionLimits updates order execution limits -func (e *Exchange) UpdateOrderExecutionLimits(_ context.Context, _ asset.Item) error { - return common.ErrNotYetImplemented +func (e *Exchange) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error { + if !e.SupportsAsset(a) { + return fmt.Errorf("%w: %q", asset.ErrNotSupported, a) + } + if a == asset.Spot { + instruments, err := e.GetSymbols(ctx) + if err != nil { + return err + } + l := make([]limits.MinMaxLevel, len(instruments)) + for i, symbolDetail := range instruments { + l[i] = limits.MinMaxLevel{ + Key: key.NewExchangeAssetPair(e.Name, a, symbolDetail.Symbol), + MinimumBaseAmount: symbolDetail.SymbolTradeLimit.MinQuantity.Float64(), + MinimumQuoteAmount: symbolDetail.SymbolTradeLimit.MinAmount.Float64(), + MaximumBaseAmount: symbolDetail.SymbolTradeLimit.MaxQuantity.Float64(), + MaximumQuoteAmount: symbolDetail.SymbolTradeLimit.MaxAmount.Float64(), + PriceStepIncrementSize: priceScaleMultipliers[symbolDetail.SymbolTradeLimit.PriceScale], + AmountStepIncrementSize: priceScaleMultipliers[symbolDetail.SymbolTradeLimit.QuantityScale], + QuoteStepIncrementSize: priceScaleMultipliers[symbolDetail.SymbolTradeLimit.QuoteAmountScale], + } + } + return limits.Load(l) + } + + instruments, err := e.GetFuturesAllProducts(ctx, currency.EMPTYPAIR) + if err != nil { + return err + } + l := make([]limits.MinMaxLevel, len(instruments)) + for i, productInfo := range instruments { + l[i] = limits.MinMaxLevel{ + Key: key.NewExchangeAssetPair(e.Name, a, productInfo.Symbol), + MinPrice: productInfo.MinPrice.Float64(), + MaxPrice: productInfo.MaxPrice.Float64(), + PriceStepIncrementSize: productInfo.TickSize.Float64(), + AmountStepIncrementSize: float64(productInfo.SizePrecision), + MinimumBaseAmount: productInfo.MinQuantity.Float64(), + MaximumBaseAmount: productInfo.MaxQuantity.Float64(), + MinimumQuoteAmount: float64(productInfo.MinSize), + MarketMinQty: productInfo.MinQuantity.Float64(), + MarketMaxQty: productInfo.MarketMaxQty.Float64(), + } + } + return limits.Load(l) } // GetCurrencyTradeURL returns the URL to the exchange's trade page for the given asset and currency pair @@ -1020,14 +1834,86 @@ func (e *Exchange) GetCurrencyTradeURL(_ context.Context, a asset.Item, cp curre if err != nil { return "", err } + pairFormat, err := e.GetPairFormat(a, true) + if err != nil { + return "", err + } switch a { case asset.Spot: - cp.Delimiter = currency.UnderscoreDelimiter - return poloniexAPIURL + tradeSpot + cp.Upper().String(), nil + return mainURL + tradeSpotPath + pairFormat.Format(cp), nil case asset.Futures: - cp.Delimiter = "" - return poloniexAPIURL + tradeFutures + cp.Upper().String(), nil + return mainURL + tradeFuturesPath + pairFormat.Format(cp), nil + default: + return "", fmt.Errorf("%w: %q", asset.ErrNotSupported, a) + } +} + +// WebsocketSubmitOrder submits an order to the exchange via a websocket connection +func (e *Exchange) WebsocketSubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) { + if err := s.Validate(e.GetTradingRequirements()); err != nil { + return nil, err + } + var err error + s.Pair, err = e.FormatExchangeCurrency(s.Pair, s.AssetType) + if err != nil { + return nil, err + } + if s.AssetType != asset.Spot { + return nil, fmt.Errorf("%w: %q", asset.ErrNotSupported, s.AssetType) + } + switch s.Type { + case order.Market, order.Limit, order.LimitMaker: default: - return "", fmt.Errorf("%w %q", asset.ErrNotSupported, a) + return nil, fmt.Errorf("%w: %q", order.ErrUnsupportedOrderType, s.Type) + } + var stpMode string + switch s.TimeInForce { + case order.PostOnly: + stpMode = "EXPIRE_MAKER" + case order.GoodTillCancel: + stpMode = "EXPIRE_TAKER" + } + response, err := e.WsCreateOrder(ctx, &PlaceOrderRequest{ + Symbol: s.Pair, + Price: s.Price, + BaseAmount: s.Amount, + QuoteAmount: s.QuoteAmount, + AllowBorrow: s.AutoBorrow, + Type: OrderType(s.Type), + Side: s.Side, + TimeInForce: TimeInForce(s.TimeInForce), + ClientOrderID: s.ClientOrderID, + SelfTradePreventionMode: stpMode, + }) + if err != nil { + return nil, err + } + return s.DeriveSubmitResponse(strconv.FormatInt(response.OrderID, 10)) +} + +// WebsocketCancelOrder cancels an order via the websocket connection +func (e *Exchange) WebsocketCancelOrder(ctx context.Context, req *order.Cancel) error { + if req.OrderID == "" && req.ClientOrderID == "" { + return order.ErrOrderIDNotSet } + if err := req.Validate(req.StandardCancel()); err != nil { + return err + } + _, err := e.WsCancelMultipleOrdersByIDs(ctx, []string{req.OrderID}, []string{req.ClientOrderID}) + return err +} + +// orderTypeString return a string representation of order type +func orderTypeString(oType order.Type) (string, error) { + switch oType { + case order.Market, order.Limit, order.LimitMaker: + return oType.String(), nil + case order.StopLimit: + return "STOP_LIMIT", nil + case order.TrailingStopLimit: + return "TRAILING_STOP_LIMIT", nil + case order.AnyType, order.UnknownType: + return "", nil + } + return "", fmt.Errorf("%w: %q", order.ErrUnsupportedOrderType, oType) } diff --git a/exchanges/poloniex/ratelimit.go b/exchanges/poloniex/ratelimit.go index 71c2ec66609..72240871e76 100644 --- a/exchanges/poloniex/ratelimit.go +++ b/exchanges/poloniex/ratelimit.go @@ -7,19 +7,144 @@ import ( ) const ( - poloniexRateInterval = time.Second - poloniexAuthRate = 6 - poloniexUnauthRate = 6 + publicEPL request.EndpointLimit = iota + sWebsocketPublicEPL + sWebsocketPrivateEPL + fWebsocketPublicEPL + fWebsocketPrivateEPL + referenceDataEPL + sCreateOrderEPL + sBatchOrderEPL + sCancelReplaceOrderEPL + sGetOpenOrdersEPL + sGetOpenOrderDetailEPL + sCancelOrderByIDEPL + sCancelBatchOrdersEPL + sCancelAllOrdersEPL + sKillSwitchEPL + sGetKillSwitchStatusEPL + sAccountInfoEPL + sAccountBalancesEPL + sAccountActivityEPL + sAccountsTransferEPL + sAccountsTransferRecordsEPL + sFeeInfoEPL + sInterestHistoryEPL + sGetSubAccountEPL + sGetSubAccountBalancesEPL + sGetSubAccountTransfersEPL + sGetDepositAddressesEPL + sGetWalletActivityRecordsEPL + sGetWalletAddressesEPL + sWithdrawCurrencyEPL + sAccountMarginEPL + sBorrowStatusEPL + sMaxMarginSizeEPL + sCreateSmartOrdersEPL + sCreateReplaceSmartOrdersEPL + sGetSmartOrdersEPL + sSmartOrderDetailEPL + sCancelSmartOrderByIDEPL + sCancelSmartOrdersByIDEPL + sCancelAllSmartOrdersEPL + sGetOrderHistoryEPL + sGetSmartOrderHistoryEPL + sGetTradesEPL + sGetTradeDetailEPL + fOrderEPL + fBatchOrdersEPL + fCancelOrderEPL + fCancelBatchOrdersEPL + fCancelAllLimitOrdersEPL + fCancelPositionAtMarketPriceEPL + fCancelAllPositionsAtMarketPriceEPL + fGetFillsV2EPL + fGetOrdersEPL + fGetOrderHistoryEPL + fGetPositionOpenEPL + fGetPositionHistoryEPL + fGetPositionModeEPL + fGetPositionRiskLimitEPL + fSwitchPositionModeEPL + fAdjustMarginEPL + fGetPositionLeverageEPL + fSetPositionLeverageEPL + fGetAccountBalanceEPL + fGetBillsDetailsEPL + fMarketEPL + fCandlestickEPL + fPremiumCandlestickEPL ) -// GetRateLimit returns the rate limit for the exchange -// If your account's volume is over $5 million in 30 day volume, -// you may be eligible for an API rate limit increase. -// Please email poloniex@circle.com. +// rateLimits returns the rate limit for the exchange // As per https://docs.poloniex.com/#http-api -func GetRateLimit() request.RateLimitDefinitions { - return request.RateLimitDefinitions{ - request.Auth: request.NewRateLimitWithWeight(poloniexRateInterval, poloniexAuthRate, 1), - request.UnAuth: request.NewRateLimitWithWeight(poloniexRateInterval, poloniexUnauthRate, 1), - } +var rateLimits = request.RateLimitDefinitions{ + referenceDataEPL: request.NewRateLimitWithWeight(time.Second, 30, 1), + publicEPL: request.NewRateLimitWithWeight(time.Second, 200, 1), + sWebsocketPublicEPL: request.NewRateLimitWithWeight(time.Second, 500, 1), + sWebsocketPrivateEPL: request.NewRateLimitWithWeight(time.Second, 500, 1), + fWebsocketPublicEPL: request.NewRateLimitWithWeight(time.Second, 500, 1), + fWebsocketPrivateEPL: request.NewRateLimitWithWeight(time.Second, 500, 1), + fOrderEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + fBatchOrdersEPL: request.NewRateLimitWithWeight(time.Second, 5, 1), + fCancelOrderEPL: request.NewRateLimitWithWeight(time.Second, 100, 1), + fCancelBatchOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fCancelAllLimitOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fCancelPositionAtMarketPriceEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fCancelAllPositionsAtMarketPriceEPL: request.NewRateLimitWithWeight(time.Second, 2, 1), + fGetOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetFillsV2EPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetOrderHistoryEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetPositionOpenEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetPositionHistoryEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetPositionModeEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetPositionRiskLimitEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fSwitchPositionModeEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fAdjustMarginEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetPositionLeverageEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fSetPositionLeverageEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fGetAccountBalanceEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + fGetBillsDetailsEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + fMarketEPL: request.NewRateLimitWithWeight(time.Second, 300, 1), + fCandlestickEPL: request.NewRateLimitWithWeight(time.Second, 20, 1), + fPremiumCandlestickEPL: request.NewRateLimitWithWeight(time.Second, 20, 1), + + sCreateOrderEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sBatchOrderEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sCancelReplaceOrderEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetOpenOrdersEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetOpenOrderDetailEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sCancelOrderByIDEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sCancelBatchOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sCancelAllOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sKillSwitchEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetKillSwitchStatusEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sAccountInfoEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sAccountBalancesEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sAccountActivityEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sAccountsTransferEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sAccountsTransferRecordsEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sFeeInfoEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sInterestHistoryEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetSubAccountEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sGetSubAccountBalancesEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetSubAccountTransfersEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetDepositAddressesEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetWalletActivityRecordsEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sGetWalletAddressesEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sWithdrawCurrencyEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sAccountMarginEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sBorrowStatusEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sMaxMarginSizeEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sCreateSmartOrdersEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sCreateReplaceSmartOrdersEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sGetSmartOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sSmartOrderDetailEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sCancelSmartOrderByIDEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), + sCancelSmartOrdersByIDEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sCancelAllSmartOrdersEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sGetOrderHistoryEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sGetSmartOrderHistoryEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sGetTradesEPL: request.NewRateLimitWithWeight(time.Second, 10, 1), + sGetTradeDetailEPL: request.NewRateLimitWithWeight(time.Second, 50, 1), } diff --git a/exchanges/poloniex/ratelimit_test.go b/exchanges/poloniex/ratelimit_test.go new file mode 100644 index 00000000000..c8145861107 --- /dev/null +++ b/exchanges/poloniex/ratelimit_test.go @@ -0,0 +1,92 @@ +package poloniex + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/require" + "github.com/thrasher-corp/gocryptotrader/exchanges/request" +) + +func TestRateLimit_LimitStatic(t *testing.T) { + t.Parallel() + testTable := map[string]request.EndpointLimit{ + "unauth": publicEPL, + "futuresWebsocketPublicEPL": fWebsocketPublicEPL, + "futuresWebsocketPrivateEPL": fWebsocketPrivateEPL, + "spotWebsocketPublicEPL": sWebsocketPublicEPL, + "spotWebsocketPrivateEPL": sWebsocketPrivateEPL, + "referenceData": referenceDataEPL, + "sCreateOrder": sCreateOrderEPL, + "sBatchOrder": sBatchOrderEPL, + "sCancelReplaceOrder": sCancelReplaceOrderEPL, + "sGetOpenOrders": sGetOpenOrdersEPL, + "sGetOpenOrderDetail": sGetOpenOrderDetailEPL, + "sCancelOrderByID": sCancelOrderByIDEPL, + "sCancelBatchOrders": sCancelBatchOrdersEPL, + "sCancelAllOrders": sCancelAllOrdersEPL, + "sKillSwitch": sKillSwitchEPL, + "sGetKillSwitchStatus": sGetKillSwitchStatusEPL, + "sAccountInfo": sAccountInfoEPL, + "sAccountBalances": sAccountBalancesEPL, + "sAccountActiviti": sAccountActivityEPL, + "sAccountsTransfer": sAccountsTransferEPL, + "sAccountsTransferRecords": sAccountsTransferRecordsEPL, + "sFeeInfo": sFeeInfoEPL, + "sInterestHistory": sInterestHistoryEPL, + "sGetSubAccount": sGetSubAccountEPL, + "sGetSubAccountBalances": sGetSubAccountBalancesEPL, + "sGetSubAccountTransfers": sGetSubAccountTransfersEPL, + "sGetDepositAddresses": sGetDepositAddressesEPL, + "sGetWalletActivityRecords": sGetWalletActivityRecordsEPL, + "sGetWalletAddresses": sGetWalletAddressesEPL, + "sWithdrawCurrency": sWithdrawCurrencyEPL, + "sAccountMargin": sAccountMarginEPL, + "sBorrowStatus": sBorrowStatusEPL, + "sMaxMarginSize": sMaxMarginSizeEPL, + "sCreateSmartOrders": sCreateSmartOrdersEPL, + "sCreateReplaceSmartOrders": sCreateReplaceSmartOrdersEPL, + "sGetSmartOrders": sGetSmartOrdersEPL, + "sSmartOrderDetail": sSmartOrderDetailEPL, + "sCancelSmartOrderByID": sCancelSmartOrderByIDEPL, + "sCancelSmartOrdersByID": sCancelSmartOrdersByIDEPL, + "sCancelAllSmartOrders": sCancelAllSmartOrdersEPL, + "sGetOrderHistory": sGetOrderHistoryEPL, + "sGetSmartOrderHistory": sGetSmartOrderHistoryEPL, + "sGetTrades": sGetTradesEPL, + "sGetTradeDetail": sGetTradeDetailEPL, + "fOrder": fOrderEPL, + "fBatchOrders": fBatchOrdersEPL, + "fCancelOrder": fCancelOrderEPL, + "fCancelBatchOrders": fCancelBatchOrdersEPL, + "fCancelAllLimitOrders": fCancelAllLimitOrdersEPL, + "fCancelPositionAtMarketPrice": fCancelPositionAtMarketPriceEPL, + "fCancelAllPositionsAtMarketPrice": fCancelAllPositionsAtMarketPriceEPL, + "fGetFillsV2": fGetFillsV2EPL, + "fGetOrders": fGetOrdersEPL, + "fGetOrderHistory": fGetOrderHistoryEPL, + "fGetPositionOpen": fGetPositionOpenEPL, + "fGetPositionHistory": fGetPositionHistoryEPL, + "fGetPositionMode": fGetPositionModeEPL, + "fGetPositionRiskLimit": fGetPositionRiskLimitEPL, + "fSwitchPositionMode": fSwitchPositionModeEPL, + "fAdjustMargin": fAdjustMarginEPL, + "fGetPositionLeverage": fGetPositionLeverageEPL, + "fSetPositionLeverage": fSetPositionLeverageEPL, + "fGetAccountBalance": fGetAccountBalanceEPL, + "fGetBillsDetails": fGetBillsDetailsEPL, + "fMarket": fMarketEPL, + "fCandlestick": fCandlestickEPL, + "fPremiumCandlestickEPL": fPremiumCandlestickEPL, + } + rl, err := request.New("rateLimitTest2", http.DefaultClient, request.WithLimiter(rateLimits)) + require.NoError(t, err, "request.New must not error") + + for name, tt := range testTable { + t.Run(name, func(t *testing.T) { + t.Parallel() + + require.NoError(t, rl.InitiateRateLimit(t.Context(), tt), "InitiateRateLimit must not error") + }) + } +} diff --git a/exchanges/poloniex/testdata/http.json b/exchanges/poloniex/testdata/http.json index b775fd484cd..9b32738ad00 100644 --- a/exchanges/poloniex/testdata/http.json +++ b/exchanges/poloniex/testdata/http.json @@ -1,19604 +1,14369 @@ { "routes": { - "/public": { + "/accounts": { "GET": [ { "data": [ { - "close": 0.00518763, - "date": 1588741402, - "high": 0.00518763, - "low": 0.00518763, - "open": 0.00518763, - "quoteVolume": 0, - "volume": 0, - "weightedAverage": 0.00518763 - }, - { - "close": 0.00518401, - "date": 1588741500, - "high": 0.00518818, - "low": 0.00518401, - "open": 0.00518818, - "quoteVolume": 65.00109374, - "volume": 0.33723736, - "weightedAverage": 0.00518817 - }, - { - "close": 0.0051839, - "date": 1588741800, - "high": 0.00518444, - "low": 0.0051839, - "open": 0.00518444, - "quoteVolume": 0.43601529, - "volume": 0.00226025, - "weightedAverage": 0.0051839 - }, - { - "close": 0.00518201, - "date": 1588742100, - "high": 0.00518614, - "low": 0.00518201, - "open": 0.00518401, - "quoteVolume": 90.59918563, - "volume": 0.46972322, - "weightedAverage": 0.00518462 - }, - { - "close": 0.00518373, - "date": 1588742400, - "high": 0.0051847, - "low": 0.00517971, - "open": 0.00517972, - "quoteVolume": 8.6152343, - "volume": 0.04465903, - "weightedAverage": 0.00518372 - }, - { - "close": 0.00519266, - "date": 1588742700, - "high": 0.00519266, - "low": 0.00518553, - "open": 0.00518553, - "quoteVolume": 81.37365353, - "volume": 0.42217513, - "weightedAverage": 0.0051881 - }, - { - "close": 0.00519104, - "date": 1588743000, - "high": 0.00519597, - "low": 0.00519104, - "open": 0.00519597, - "quoteVolume": 1.10021375, - "volume": 0.0057163, - "weightedAverage": 0.00519562 - }, - { - "close": 0.00518988, - "date": 1588743300, - "high": 0.00518988, - "low": 0.00518905, - "open": 0.00518905, - "quoteVolume": 0.00086904, - "volume": 0.0000045, - "weightedAverage": 0.00518961 - }, - { - "close": 0.00519395, - "date": 1588743600, - "high": 0.00519395, - "low": 0.00518901, - "open": 0.00518903, - "quoteVolume": 0.03395903, - "volume": 0.0001763, - "weightedAverage": 0.00519181 - }, - { - "close": 0.00519098, - "date": 1588743900, - "high": 0.00519526, - "low": 0.00519098, - "open": 0.00519126, - "quoteVolume": 209.14700529, - "volume": 1.08631528, - "weightedAverage": 0.00519402 - }, - { - "close": 0.00518534, - "date": 1588744200, - "high": 0.00519198, - "low": 0.00518534, - "open": 0.00519179, - "quoteVolume": 176.01313731, - "volume": 0.91303131, - "weightedAverage": 0.00518729 - }, - { - "close": 0.00518573, - "date": 1588744500, - "high": 0.00518752, - "low": 0.00518572, - "open": 0.00518752, - "quoteVolume": 97.1672869, - "volume": 0.50399966, - "weightedAverage": 0.00518692 - }, - { - "close": 0.00518864, - "date": 1588744800, - "high": 0.00519153, - "low": 0.00518657, - "open": 0.00518826, - "quoteVolume": 74.95742178, - "volume": 0.38903394, - "weightedAverage": 0.00519006 + "accountId": "329455537441832960", + "accountState": "NORMAL", + "accountType": "SPOT" } ], - "queryString": "command=returnChartData\u0026currencyPair=BTC_LTC\u0026end=1588745003\u0026period=300\u0026start=1588741402", + "queryString": "", "bodyParams": "", - "headers": {} - }, + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "njVNG1V+KCjqF7317T+QSC+sowQ5K5QBOXVaI4p7c3I=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742832814341" + ] + } + } + ] + }, + "/accounts/219961623421431808/balances": { + "GET": [ { "data": { - "1CR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 1, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "ABY": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 2, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "AC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 3, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "ACH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 4, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" - }, - "ADN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 5, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "AEON": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "WmrzAb4yy6i4otzaTZznsmaeBn8UKoBqS14XdW2DDzXr3DQnwz4o1XPJAJuo7QTqSoD9WVrdEQfn15udzhsJWmNR1jAEETQ2N", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 6, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "AERO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 7, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "AIR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 8, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "AMP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 275, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "5.00000000" - }, - "APH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 9, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "ARCH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 258, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "ARDR": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 285, - "isGeofenced": 0, - "minConf": 20, - "name": "", - "txFee": "2.00000000" - }, - "ATOM": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 313, - "isGeofenced": 0, - "minConf": 0, - "name": "", - "txFee": "0.00500000" - }, - "AUR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 10, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "AXIS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 11, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BALLS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 12, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "6.40000000" - }, - "BANK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 13, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BAT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 302, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "9.00000000" - }, - "BBL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 14, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BBR": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "1D9hJ1nEjwuhxZMk6fupoTjKLtS2KzkfCQ7kF25k5B6Sc4UJjt9FrvDNYomVd4ZVHv36FskVRJGZa1JZAnZ35GiuAHf7gBy", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 15, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00500000" - }, - "BCC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 16, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BCH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "humanType": "BTC Clone", - "id": 292, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.00010000" - }, - "BCHABC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 308, - "isGeofenced": 0, - "minConf": 11, - "name": "", - "txFee": "0.00100000" - }, - "BCHSV": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 309, - "isGeofenced": 0, - "minConf": 36, - "name": "", - "txFee": "0.00100000" - }, - "BCN": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "25cZNQYVAi3issDCoa6fWA2Aogd4FgPhYdpX3p8KLfhKC6sN8s6Q9WpcW4778TPwcUS5jEM25JrQvjD3XjsvXuNHSWhYUsu", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 17, - "isGeofenced": 0, - "minConf": 1000, - "name": "", - "txFee": "1.00000000" - }, - "BCY": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 269, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "4.00000000" - }, - "BDC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 18, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BDG": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 19, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BELA": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 20, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" - }, - "BITCNY": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniexwallet", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 273, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" - }, - "BITS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 21, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BITUSD": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniexwallet", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 272, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.15000000" - }, - "BLK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 22, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" - }, - "BLOCK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "humanType": "BTC Clone", - "id": 23, - "isGeofenced": 0, - "minConf": 100000, - "name": "", - "txFee": "0.01000000" - }, - "BLU": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 24, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BNS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 25, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BNT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 305, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "1.10000000" - }, - "BONES": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 26, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BOST": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 27, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BTC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 28, - "isGeofenced": 0, - "minConf": 1, - "name": "", - "txFee": "0.00050000" - }, - "BTCD": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 29, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" - }, - "BTCS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 30, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BTM": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 31, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" - }, - "BTS": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "poloniexwallet", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 32, - "isGeofenced": 0, - "minConf": 50, - "name": "", - "txFee": "5.00000000" - }, - "BURN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 33, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "BURST": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 34, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "1.00000000" - }, - "C2": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 35, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CACH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 36, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CAI": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 37, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 38, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CCN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 39, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CGA": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 40, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00100000" - }, - "CHA": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 41, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CINNI": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 42, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CLAM": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 43, - "isGeofenced": 0, - "minConf": 6, - "name": "", - "txFee": "0.00100000" - }, - "CNL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 44, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CNMT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 45, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" - }, - "CNOTE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 46, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "COMM": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 47, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CON": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 48, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.10000000" - }, - "CORG": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 49, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CRYPT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 50, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CURE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 51, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "CVC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 294, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "1.00000000" - }, - "CYC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 52, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DAO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 279, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DASH": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 60, - "isGeofenced": 0, - "minConf": 50, - "name": "", - "txFee": "0.01000000" - }, - "DCR": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 277, - "isGeofenced": 0, - "minConf": 4, - "name": "", - "txFee": "0.10000000" - }, - "DGB": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 53, - "isGeofenced": 0, - "minConf": 40, - "name": "", - "txFee": "0.10000000" - }, - "DICE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 54, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" - }, - "DIEM": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 55, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DIME": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 56, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DIS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 57, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DNS": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 58, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.50000000" - }, - "DOGE": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 59, - "isGeofenced": 0, - "minConf": 6, - "name": "", - "txFee": "100.00000000" - }, - "DRKC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 61, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DRM": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 62, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "DSH": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "D8PDwmpq4KMhTy6u8RvWt5PLTMwEayGN3jeYoS3pkJQJMULNt2CyYKXG7KhqSahe9DPppRKqzkWGoMjf8C4L2mzFAgsJZXs", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 63, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" - }, - "DVK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 64, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "EAC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 65, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "EBT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 66, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "ECC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 67, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "EFL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 68, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + "code": 21600, + "message": "Account not found" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "ZrLKbg6q+PCP1da2K65fp0y+koJ88Kdv82LYJDJPEM0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742833289521" + ] + } + } + ] + }, + "/accounts/329455537441832960/balances": { + "GET": [ + { + "data": [ + { + "accountId": "329455537441832960", + "accountType": "SPOT", + "balances": [] + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "ZGLktWcRel8bQuk0k8KKVy3JiH7quDt1o1huM3v2aRU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742833392576" + ] + } + }, + { + "data": [ + { + "accountId": "329455537441832960", + "accountType": "SPOT", + "balances": [] + } + ], + "queryString": "accountType=SPOT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "arYxCkxHRmV2yR82VgWaEx8oYN2XFmJ1ps6MZJhDmMo=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250968468" + ] + } + } + ] + }, + "/accounts/activity": { + "GET": [ + { + "data": [ + { + "id": "22774050", + "currency": "LINK", + "amount": "100000000", + "state": "SUCCESS", + "createTime": 1659781580499, + "description": "Your airdrop for 100000000 LINK", + "activityType": 200 + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "BPPZeUXRcLj0/a9Z7CHN+H4Qv0zVEC6PqHe3PvuQq4c=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250968214" + ] + } + }, + { + "data": [ + { + "id": "22774050", + "currency": "LINK", + "amount": "100000000", + "state": "SUCCESS", + "createTime": 1659781580499, + "description": "Your airdrop for 100000000 LINK", + "activityType": 200 + } + ], + "queryString": "direction=PRE\u0026from=100\u0026limit=10", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "BPPZeUXRcLj0/a9Z7CHN+H4Qv0zVEC6PqHe3PvuQq4c=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250968214" + ] + } + }, + { + "data": [ + { + "id": "22774050", + "currency": "LINK", + "amount": "100000000", + "state": "SUCCESS", + "createTime": 1659781580499, + "description": "Your airdrop for 100000000 LINK", + "activityType": 200 + } + ], + "queryString": "endTime=1764668001864\u0026startTime=1764664401864", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "BPPZeUXRcLj0/a9Z7CHN+H4Qv0zVEC6PqHe3PvuQq4c=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250968214" + ] + } + }, + { + "data": [], + "queryString": "activityType=200", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "BPPZeUXRcLj0/a9Z7CHN+H4Qv0zVEC6PqHe3PvuQq4c=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250968214" + ] + } + }, + { + "data": [], + "queryString": "currency=BTC\u0026direction=NEXT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "BPPZeUXRcLj0/a9Z7CHN+H4Qv0zVEC6PqHe3PvuQq4c=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250968214" + ] + } + } + ] + }, + "/accounts/balances": { + "GET": [ + { + "data": [ + { + "accountId": "329455537441832960", + "accountType": "SPOT", + "balances": [] + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "/247QvTB/K5iiDSeDehSVshhru4YZ2G+Oza95+7J1X0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250971372" + ] + } + }, + { + "data": [ + { + "accountId": "329455537441832960", + "accountType": "SPOT", + "balances": [] + } + ], + "queryString": "accountType=SPOT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "rhIjyyBpDGWMp99X6+hJAAunxrny5fPqdffa30n9Kos=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203664720" + ] + } + } + ] + }, + "/accounts/interest/history": { + "GET": [ + { + "data": null, + "queryString": "endTime=1764668001864\u0026startTime=1764664401864", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "f9uEeXpE4EXpU96UFCTm/kZCqiSnKzxQhdkhpeeRBdg=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668519603" + ] + } + }, + { + "data": null, + "queryString": "direction=NEXT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "QQ7qifkQlxYw7YFz2MmEpz/XbNzj3rJ2FnDqmZz4fJc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668521034" + ] + } + }, + { + "data": null, + "queryString": "direction=NEXT\u0026from=1\u0026limit=100", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "QvFHXtawAZxvNt74QhsjuEFxQ8silfWE/fDmIXFPgIU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668521405" + ] + } + }, + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "KoGE0xRjL0APhKf+acSGwm3aNoT2N3QDL7a4HQiBVdM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668522652" + ] + } + } + ] + }, + "/accounts/transfer": { + "GET": [ + { + "data": [ + { + "id": "23365", + "fromAccount": "SPOT", + "toAccount": "FUTURES", + "currency": "BTC", + "amount": "0.01", + "state": "SUCCESS", + "createTime": 1656000618690 + } + ], + "queryString": "currency=BTC\u0026endTime=1764668001864\u0026startTime=1764664401864", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "M9s2bI1n3Mjaq23My43zMociRO4ZYBgPk8JunEMvnWE=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668418513" + ] + } + }, + { + "data": [ + { + "id": "23365", + "fromAccount": "SPOT", + "toAccount": "FUTURES", + "currency": "USDT", + "amount": "0.01", + "state": "SUCCESS", + "createTime": 1656000618690 + }, + { + "id": "532", + "fromAccount": "SPOT", + "toAccount": "FUTURES", + "currency": "USDT", + "amount": "1.2", + "state": "SUCCESS", + "createTime": 1650843791635 + } + ], + "queryString": "currency=BTC\u0026direction=NEXT\u0026from=1\u0026limit=100", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "3E5ncgrqlHXmDh11LpA/oU3JgvBWq1Hx7KztuFYZ0GM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668418876" + ] + } + }, + { + "data": [ + { + "id": "23365", + "fromAccount": "SPOT", + "toAccount": "FUTURES", + "currency": "USDT", + "amount": "0.01", + "state": "SUCCESS", + "createTime": 1656000618690 + }, + { + "id": "532", + "fromAccount": "SPOT", + "toAccount": "FUTURES", + "currency": "USDT", + "amount": "1.2", + "state": "SUCCESS", + "createTime": 1650843791635 + }, + { + "id": "147", + "fromAccount": "FUTURES", + "toAccount": "SPOT", + "currency": "ETH", + "amount": "2.05", + "state": "SUCCESS", + "createTime": 1650465162165 + } + ], + "queryString": "endTime=1764668001864\u0026startTime=1764664401864", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "N9wpTpwFXt0DIwrk7mYTAYdeDLYFS4J5qNVtfaVfwFs=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668419229" + ] + } + } + ], + "POST": [ + { + "data": { + "code": 601, + "message": "Invalid toAccount: 329455537441832960" + }, + "queryString": "", + "bodyParams": "{\"currency\":\"BTC\",\"amount\":\"1\",\"fromAccount\":\"329455537441832960\",\"toAccount\":\"329455537441832960\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "LpGKOjtzIiTEKqKMUtcgxOux/s6kguGePittrayoJHw=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742833670716" + ] + } + } + ] + }, + "/accounts/transfer/329455537441832960": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "vUN4cMbdeDcZF0oXL0nTnwi+Y/xlbzTY8l/y9AniIXw=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250973079" + ] + } + } + ] + }, + "/currencies/BTC": { + "GET": [ + { + "data": { + "BTC": { + "blockchain": "BTC", + "delisted": false, + "depositAddress": null, + "description": "BTC Clone", + "id": 28, + "minConf": 2, + "name": "", + "supportBorrow": true, + "supportCollateral": true, + "tradingState": "NORMAL", + "type": "address", + "walletDepositState": "ENABLED", + "walletState": "ENABLED", + "walletWithdrawalState": "ENABLED", + "withdrawalFee": "0.00100000" + } + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/currencies/ETH": { + "GET": [ + { + "data": { + "ETH": { + "blockchain": "ETH", + "delisted": false, + "depositAddress": null, + "description": "Sweep to Main Account", + "id": 267, + "minConf": 64, + "name": "", + "supportBorrow": true, + "supportCollateral": true, + "tradingState": "NORMAL", + "type": "address", + "walletDepositState": "ENABLED", + "walletState": "ENABLED", + "walletWithdrawalState": "ENABLED", + "withdrawalFee": "0.00070248" + } + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/feeinfo": { + "GET": [ + { + "data": { + "makerRate": "0.002", + "specialFeeRates": [ + { + "makerRate": "0", + "symbol": "WSTUSDT_USDT", + "takerRate": "0" + } + ], + "takerRate": "0.002", + "trxDiscount": false, + "volume30D": "0" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "QIh4LO7+yrOPnHwA4GY+k1lVBLkVs3SoC26z81R+Hng=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754251161785" + ] + } + } + ] + }, + "/margin/accountMargin": { + "GET": [ + { + "data": { + "freeMargin": "0", + "maintenanceMargin": "0", + "marginRatio": "999", + "time": 1760168102315, + "totalAccountValue": "0", + "totalMargin": "0", + "usedMargin": "0" + }, + "queryString": "accountType=SPOT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "H6TceK/CFBrZjfWaNx34D2w4IFSvMocsjDwY4yL5XU4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760168101566" + ] + } + } + ] + }, + "/margin/borrowStatus": { + "GET": [ + { + "data": null, + "queryString": "currency=USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "SFIp5wZhEfBapMtRUe9RtCqW1T82CFR6MdJtIa7idZs=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760168101547" + ] + } + } + ] + }, + "/margin/maxSize": { + "GET": [ + { + "data": { + "availableBuy": "0", + "availableSell": "0", + "maxAvailableBuy": "0", + "maxAvailableSell": "0", + "maxLeverage": 3, + "symbol": "BTC_USDT" + }, + "queryString": "symbol=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "5y/5asew5jLnqxUyd3DsQfV8S7FlcPxDY4kYGFY/dog=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760168101525" + ] + } + } + ] + }, + "/markets": { + "GET": [ + { + "data": [ + { + "baseCurrencyName": "BTC", + "crossMargin": { + "maxLeverage": 3, + "supportCrossMargin": true + }, + "displayName": "BTC/USDT", + "quoteCurrencyName": "USDT", + "state": "NORMAL", + "symbol": "BTC_USDT", + "symbolTradeLimit": { + "amountScale": 2, + "highestBid": "0", + "lowestAsk": "0", + "maxAmount": "2000000", + "maxQuantity": "20", + "minAmount": "1", + "minQuantity": "0.000001", + "priceScale": 2, + "quantityScale": 6, + "symbol": "BTC_USDT" + }, + "tradableStartTime": 1659018819512, + "visibleStartTime": 1659018819512 + }, + { + "baseCurrencyName": "DOGE", + "crossMargin": { + "maxLeverage": 3, + "supportCrossMargin": true + }, + "displayName": "DOGE/BTC", + "quoteCurrencyName": "BTC", + "state": "NORMAL", + "symbol": "DOGE_BTC", + "symbolTradeLimit": { + "amountScale": 8, + "highestBid": "0", + "lowestAsk": "0", + "maxAmount": "0", + "maxQuantity": "0", + "minAmount": "0.00001", + "minQuantity": "10", + "priceScale": 9, + "quantityScale": 0, + "symbol": "DOGE_BTC" + }, + "tradableStartTime": 1659018817873, + "visibleStartTime": 1659018817873 + }, + { + "baseCurrencyName": "LTC", + "crossMargin": { + "maxLeverage": 3, + "supportCrossMargin": true + }, + "displayName": "LTC/BTC", + "quoteCurrencyName": "BTC", + "state": "NORMAL", + "symbol": "LTC_BTC", + "symbolTradeLimit": { + "amountScale": 6, + "highestBid": "0", + "lowestAsk": "0", + "maxAmount": "0", + "maxQuantity": "0", + "minAmount": "0.00001", + "minQuantity": "0.01", + "priceScale": 6, + "quantityScale": 2, + "symbol": "LTC_BTC" + }, + "tradableStartTime": 1659018817950, + "visibleStartTime": 1659018817950 + }, + { + "baseCurrencyName": "XLM", + "crossMargin": { + "maxLeverage": 1, + "supportCrossMargin": false + }, + "displayName": "XLM/BTC", + "quoteCurrencyName": "BTC", + "state": "NORMAL", + "symbol": "XLM_BTC", + "symbolTradeLimit": { + "amountScale": 8, + "highestBid": "0", + "lowestAsk": "0", + "maxAmount": "0", + "maxQuantity": "0", + "minAmount": "0.00001", + "minQuantity": "10", + "priceScale": 9, + "quantityScale": 0, + "symbol": "XLM_BTC" + }, + "tradableStartTime": 1659018818660, + "visibleStartTime": 1659018818660 + }, + { + "baseCurrencyName": "XEM", + "crossMargin": { + "maxLeverage": 1, + "supportCrossMargin": false + }, + "displayName": "XEM/BTC", + "quoteCurrencyName": "BTC", + "state": "NORMAL", + "symbol": "XEM_BTC", + "symbolTradeLimit": { + "amountScale": 8, + "highestBid": "0", + "lowestAsk": "0", + "maxAmount": "0", + "maxQuantity": "0", + "minAmount": "0.00001", + "minQuantity": "10", + "priceScale": 9, + "quantityScale": 0, + "symbol": "XEM_BTC" + }, + "tradableStartTime": 1659018819284, + "visibleStartTime": 1659018819284 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC/collateralInfo": { + "GET": [ + { + "data": { + "collateralRate": "0.95", + "currency": "BTC", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTCUSDT_PERP": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDC/orderBook": { + "GET": [ + { + "data": { + "asks": [ + "57612.42", + "0.001981", + "57612.43", + "0.01", + "58608.95", + "0.003569", + "58611.59", + "0.001523", + "58611.6", + "0.000023", + "58612.58", + "0.00138", + "58905.51", + "0.001374", + "59099.5", + "0.07", + "59099.51", + "0.049958", + "59199.92", + "0.001366" + ], + "bids": [ + "56876.82", + "0.04799", + "56876.81", + "0.07", + "56876.65", + "0.000234", + "56400", + "0.003546", + "56000", + "0.012593", + "55988", + "0.000089", + "55486.06", + "0.001371", + "55486.05", + "0.01235", + "55175.63", + "0.003987", + "54800", + "0.05" + ], + "scale": "0.01", + "time": 1720103007642, + "ts": 1720103007712 + }, + "queryString": "limit=150", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT": { + "GET": [ + { + "data": [ + { + "baseCurrencyName": "BTC", + "crossMargin": { + "maxLeverage": 3, + "supportCrossMargin": true + }, + "displayName": "BTC/USDT", + "quoteCurrencyName": "USDT", + "state": "NORMAL", + "symbol": "BTC_USDT", + "symbolTradeLimit": { + "amountScale": 2, + "highestBid": "0", + "lowestAsk": "0", + "maxAmount": "2000000", + "maxQuantity": "20", + "minAmount": "1", + "minQuantity": "0.000001", + "priceScale": 2, + "quantityScale": 6, + "symbol": "BTC_USDT" + }, + "tradableStartTime": 1659018819512, + "visibleStartTime": 1659018819512 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/candles": { + "GET": [ + { + "data": [ + [ + "0.000004964", + "0.000005001", + "0.000004964", + "0.000004997", + "225.870214421", + "45238739", + "183.254931443", + "36708858.5", + 14, + 1720121097116, + "0.000004992", + "MINUTE_5", + 1720120800000, + 1720121099999 + ], + [ + "0.000004997", + "0.000005006", + "0.000004997", + "0.000005004", + "651.035635433", + "130213219.5", + "374.70650677", + "74942523.8", + 27, + 1720121397116, + "0.000004999", + "MINUTE_5", + 1720121100000, + 1720121399999 + ], + [ + "0.000004911", + "0.000005004", + "0.000005004", + "0.000004911", + "537.171531629", + "108789460", + "165.655217487", + "33569527.1", + 25, + 1720121655118, + "0.000004937", + "MINUTE_5", + 1720121400000, + 1720121699999 + ], + [ + "0.000004903", + "0.000004911", + "0.000004911", + "0.000004903", + "570.142046682", + "116193562.3", + "228.720909988", + "46606967", + 31, + 1720121997116, + "0.000004906", + "MINUTE_5", + 1720121700000, + 1720121999999 + ], + [ + "0.000004903", + "0.000004927", + "0.000004903", + "0.000004916", + "474.600363518", + "96491726.7", + "223.221459386", + "45398738.5", + 26, + 1720122297118, + "0.000004918", + "MINUTE_5", + 1720122000000, + 1720122299999 + ], + [ + "0.000004916", + "0.000004928", + "0.000004916", + "0.000004928", + "42.418180418", + "8618244.1", + "42.418180418", + "8618244.1", + 2, + 1720122597121, + "0.000004921", + "MINUTE_5", + 1720122300000, + 1720122599999 + ], + [ + "0.000004928", + "0.000004953", + "0.000004928", + "0.000004953", + "39.636106383", + "8022011.1", + "39.636106383", + "8022011.1", + 2, + 1720122897119, + "0.00000494", + "MINUTE_5", + 1720122600000, + 1720122899999 + ], + [ + "0.000004953", + "0.000004996", + "0.000004953", + "0.000004996", + "41.850779538", + "8414865.4", + "41.850779538", + "8414865.4", + 2, + 1720123197118, + "0.000004973", + "MINUTE_5", + 1720122900000, + 1720123199999 + ], + [ + "0.000004955", + "0.000004996", + "0.000004996", + "0.000004955", + "35.376870986", + "7110777.9", + "35.376870986", + "7110777.9", + 2, + 1720123498117, + "0.000004975", + "MINUTE_5", + 1720123200000, + 1720123499999 + ], + [ + "0.000004955", + "0.000004996", + "0.000004955", + "0.000004996", + "42.591409834", + "8559632.1", + "42.591409834", + "8559632.1", + 2, + 1720123797125, + "0.000004975", + "MINUTE_5", + 1720123500000, + 1720123799999 + ], + [ + "0.000004961", + "0.000004996", + "0.000004996", + "0.000004961", + "28.439702665", + "5712637", + "28.439702665", + "5712637", + 2, + 1720124097116, + "0.000004978", + "MINUTE_5", + 1720123800000, + 1720124099999 + ], + [ + "0.000004961", + "0.000004987", + "0.000004961", + "0.000004987", + "32.423020701", + "6515867.6", + "32.423020701", + "6515867.6", + 2, + 1720124397119, + "0.000004976", + "MINUTE_5", + 1720124100000, + 1720124399999 + ], + [ + "0.000004987", + "0.000004994", + "0.000004987", + "0.000004994", + "40.344695745", + "8084174.4", + "20.630936132", + "4131144.6", + 2, + 1720124697116, + "0.00000499", + "MINUTE_5", + 1720124400000, + 1720124699999 + ], + [ + "0.000004914", + "0.000004994", + "0.000004994", + "0.000004914", + "28.255441834", + "5706663.6", + "28.255441834", + "5706663.6", + 2, + 1720124997116, + "0.000004951", + "MINUTE_5", + 1720124700000, + 1720124999999 + ], + [ + "0.000004914", + "0.000004976", + "0.000004914", + "0.000004976", + "36.645269661", + "7416274.8", + "36.645269661", + "7416274.8", + 2, + 1720125297116, + "0.000004941", + "MINUTE_5", + 1720125000000, + 1720125299999 + ], + [ + "0.000004908", + "0.000004976", + "0.000004976", + "0.000004908", + "34.062341778", + "6888646.3", + "34.062341778", + "6888646.3", + 2, + 1720125597117, + "0.000004944", + "MINUTE_5", + 1720125300000, + 1720125599999 + ], + [ + "0.000004908", + "0.000004916", + "0.000004908", + "0.000004916", + "30.19029106", + "6145938.4", + "30.19029106", + "6145938.4", + 2, + 1720125897116, + "0.000004912", + "MINUTE_5", + 1720125600000, + 1720125899999 + ], + [ + "0.000004916", + "0.00000495", + "0.000004916", + "0.00000495", + "36.015671566", + "7306348.1", + "36.015671566", + "7306348.1", + 2, + 1720126197117, + "0.000004929", + "MINUTE_5", + 1720125900000, + 1720126199999 + ], + [ + "0.00000495", + "0.000004978", + "0.00000495", + "0.000004978", + "35.062075431", + "7061700.3", + "35.062075431", + "7061700.3", + 2, + 1720126497117, + "0.000004965", + "MINUTE_5", + 1720126200000, + 1720126499999 + ], + [ + "0.000004978", + "0.000005005", + "0.000004978", + "0.000005005", + "35.162714066", + "7046929", + "35.162714066", + "7046929", + 2, + 1720126797117, + "0.000004989", + "MINUTE_5", + 1720126500000, + 1720126799999 + ], + [ + "0.000004947", + "0.000005005", + "0.000005005", + "0.000004947", + "32.455647474", + "6518447.6", + "32.455647474", + "6518447.6", + 2, + 1720127097117, + "0.000004979", + "MINUTE_5", + 1720126800000, + 1720127099999 + ], + [ + "0.000004903", + "0.000004947", + "0.000004947", + "0.000004903", + "36.738251708", + "7455417.9", + "36.738251708", + "7455417.9", + 2, + 1720127397116, + "0.000004927", + "MINUTE_5", + 1720127100000, + 1720127399999 + ], + [ + "0.000004903", + "0.000004911", + "0.000004903", + "0.000004911", + "35.062066755", + "7144792", + "35.062066755", + "7144792", + 2, + 1720127697117, + "0.000004907", + "MINUTE_5", + 1720127400000, + 1720127699999 + ], + [ + "0.000004911", + "0.000004931", + "0.000004911", + "0.000004931", + "35.614046235", + "7238467.6", + "35.614046235", + "7238467.6", + 2, + 1720127997116, + "0.00000492", + "MINUTE_5", + 1720127700000, + 1720127999999 + ], + [ + "0.000004931", + "0.000004931", + "0.000004931", + "0.000004931", + "21.705499667", + "4401845.4", + "21.705499667", + "4401845.4", + 1, + 1720128001117, + "0.000004931", + "MINUTE_5", + 1720128000000, + 1720128299999 + ] + ], + "queryString": "endTime=1720128300000\u0026interval=MINUTE_5\u0026limit=500\u0026startTime=1720120800000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "0.000004964", + "0.000005001", + "0.000004964", + "0.000004997", + "225.870214421", + "45238739", + "183.254931443", + "36708858.5", + 14, + 1720121097116, + "0.000004992", + "MINUTE_5", + 1720120800000, + 1720121099999 + ], + [ + "0.000004997", + "0.000005006", + "0.000004997", + "0.000005004", + "651.035635433", + "130213219.5", + "374.70650677", + "74942523.8", + 27, + 1720121397116, + "0.000004999", + "MINUTE_5", + 1720121100000, + 1720121399999 + ] + ], + "queryString": "endTime=1720128300000\u0026interval=MINUTE_5\u0026limit=500\u0026startTime=1720120800000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "66642.46", + "66715.87", + "66705.42", + "66679.58", + "156469.69", + "2.346582", + "89783.65", + "1.346412", + 132, + 0, + "66679.83", + "MINUTE_5", + 1718546400000, + 1718546699999 + ], + [ + "66692.46", + "66731.8", + "66702.41", + "66730.83", + "32327.88", + "0.484569", + "17264.82", + "0.258785", + 40, + 0, + "66714.71", + "MINUTE_5", + 1718546700000, + 1718546999999 + ], + [ + "66699.88", + "66767.26", + "66730.86", + "66750.03", + "121557.06", + "1.821445", + "72431.78", + "1.08538", + 90, + 0, + "66736.61", + "MINUTE_5", + 1718547000000, + 1718547299999 + ], + [ + "66668.02", + "66768.99", + "66768.38", + "66724.38", + "114150.22", + "1.710548", + "57909.95", + "0.867792", + 96, + 0, + "66733.14", + "MINUTE_5", + 1718547300000, + 1718547599999 + ], + [ + "66624.65", + "66720.8", + "66720.8", + "66626.48", + "128385.4", + "1.925551", + "61466.96", + "0.921937", + 90, + 0, + "66674.64", + "MINUTE_5", + 1718547600000, + 1718547899999 + ], + [ + "66548.4", + "66664.38", + "66626.38", + "66579.59", + "126850.06", + "1.904152", + "66024.58", + "0.99114", + 87, + 0, + "66617.63", + "MINUTE_5", + 1718547900000, + 1718548199999 + ], + [ + "66531.66", + "66574.52", + "66574.52", + "66556", + "40571.54", + "0.609527", + "27096.15", + "0.407066", + 38, + 0, + "66562.34", + "MINUTE_5", + 1718548200000, + 1718548499999 + ], + [ + "66542.85", + "66573.38", + "66565.35", + "66573.38", + "66207.89", + "0.994716", + "33222.75", + "0.499156", + 44, + 0, + "66559.59", + "MINUTE_5", + 1718548500000, + 1718548799999 + ], + [ + "66574.52", + "66612.1", + "66574.52", + "66591.4", + "19729.1", + "0.296253", + "4857.44", + "0.072937", + 24, + 0, + "66595.45", + "MINUTE_5", + 1718548800000, + 1718549099999 + ], + [ + "66571.33", + "66614.62", + "66601.87", + "66597.96", + "101726.02", + "1.527478", + "51740.51", + "0.776922", + 91, + 0, + "66597.37", + "MINUTE_5", + 1718549100000, + 1718549399999 + ], + [ + "66514.36", + "66600.37", + "66597.56", + "66514.36", + "98412.98", + "1.478409", + "55573.74", + "0.834875", + 76, + 0, + "66566.82", + "MINUTE_5", + 1718549400000, + 1718549699999 + ], + [ + "66505.93", + "66566.6", + "66527.24", + "66516.37", + "153103.4", + "2.301245", + "70330.02", + "1.05708", + 122, + 0, + "66530.68", + "MINUTE_5", + 1718549700000, + 1718549999999 + ], + [ + "66508.89", + "66585.48", + "66513.1", + "66585.3", + "160119.36", + "2.405449", + "93207.32", + "1.40022", + 128, + 0, + "66565.27", + "MINUTE_5", + 1718550000000, + 1718550299999 + ], + [ + "66581.74", + "66585.66", + "66585.66", + "66582.1", + "25279.2", + "0.379666", + "17272.61", + "0.259416", + 23, + 0, + "66582.75", + "MINUTE_5", + 1718550300000, + 1718550599999 + ] + ], + "queryString": "endTime=1718550300000\u0026interval=MINUTE_5\u0026limit=500\u0026startTime=1718546400000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "84140.45", + "84264", + "84190.25", + "84166.85", + "117810.85", + "1.398574", + "73617.51", + "0.873654", + 74, + 1743580181248, + "84236.42", + "MINUTE_5", + 1743579900000, + 1743580199999 + ], + [ + "84186", + "84333.17", + "84244.81", + "84333.16", + "180194.3", + "2.138449", + "179980.53", + "2.135913", + 121, + 1743580463247, + "84264.01", + "MINUTE_5", + 1743580200000, + 1743580499999 + ], + [ + "84300.84", + "84364.62", + "84352.27", + "84364.62", + "13774.82", + "0.163279", + "13606.27", + "0.16128", + 22, + 1743580746248, + "84363.73", + "MINUTE_5", + 1743580500000, + 1743580799999 + ], + [ + "84296.61", + "84364.62", + "84364.6", + "84342.05", + "14128.62", + "0.167475", + "13602.3", + "0.161233", + 26, + 1743581088248, + "84362.61", + "MINUTE_5", + 1743580800000, + 1743581099999 + ], + [ + "84304.01", + "84310.63", + "84310.63", + "84304.01", + "26.13", + "0.00031", + "11.04", + "0.000131", + 2, + 1743581326247, + "84307.83", + "MINUTE_5", + 1743581100000, + 1743581399999 + ], + [ + "84281.76", + "84310.63", + "84307.54", + "84310.63", + "81.43", + "0.000966", + "66.68", + "0.000791", + 7, + 1743581540248, + "84304.05", + "MINUTE_5", + 1743581400000, + 1743581699999 + ], + [ + "84203.2", + "84296.61", + "84296.61", + "84254.73", + "174.74", + "0.002074", + "129.99", + "0.001543", + 8, + 1743581861248, + "84253.87", + "MINUTE_5", + 1743581700000, + 1743581999999 + ], + [ + "84286.27", + "84364.61", + "84320.32", + "84364.61", + "4425.16", + "0.052481", + "2.36", + "0.000028", + 9, + 1743582250248, + "84319.37", + "MINUTE_5", + 1743582000000, + 1743582299999 + ], + [ + "84355.71", + "84523", + "84355.71", + "84517.46", + "129436.66", + "1.534016", + "129436.66", + "1.534016", + 79, + 1743582577247, + "84377.67", + "MINUTE_5", + 1743582300000, + 1743582599999 + ], + [ + "84469.07", + "84591.33", + "84490.76", + "84591.33", + "118732.89", + "1.404308", + "118623.88", + "1.403018", + 76, + 1743582882248, + "84549.05", + "MINUTE_5", + 1743582600000, + 1743582899999 + ], + [ + "84542.6", + "84615.1", + "84590.69", + "84601.34", + "51410.75", + "0.607771", + "19564.88", + "0.231348", + 36, + 1743583195248, + "84589.03", + "MINUTE_5", + 1743582900000, + 1743583199999 + ], + [ + "84549.68", + "84585.71", + "84585.71", + "84580", + "36396.49", + "0.430391", + "36322.48", + "0.429516", + 27, + 1743583480248, + "84566.11", + "MINUTE_5", + 1743583200000, + 1743583499999 + ], + [ + "84617.49", + "84622.68", + "84617.49", + "84622.68", + "7309.87", + "0.086382", + "7309.87", + "0.086382", + 2, + 1743583508247, + "84622.66", + "MINUTE_5", + 1743583500000, + 1743583799999 + ] + ], + "queryString": "endTime=1743583800000\u0026interval=MINUTE_5\u0026limit=500\u0026startTime=1743579900000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "78584.13", + "78950.96", + "78800", + "78891.46", + "812760.13", + "10.316073", + "521966.45", + "6.625324", + 905, + 1744047898287, + "78785.9", + "MINUTE_5", + 1744047600000, + 1744047899999 + ], + [ + "78544.96", + "79168.37", + "78891.81", + "78961.53", + "905347.53", + "11.470807", + "446722.95", + "5.658924", + 1083, + 1744048200057, + "78926.49", + "MINUTE_5", + 1744047900000, + 1744048199999 + ], + [ + "78744.97", + "79102.12", + "78941.21", + "78948.06", + "857467.83", + "10.862937", + "518510.14", + "6.568679", + 1011, + 1744048500237, + "78935.31", + "MINUTE_5", + 1744048200000, + 1744048499999 + ], + [ + "78769.2", + "79108.75", + "78958.33", + "79031.23", + "693255.01", + "8.77967", + "403591.78", + "5.11116", + 802, + 1744048800238, + "78961.51", + "MINUTE_5", + 1744048500000, + 1744048799999 + ], + [ + "78848.37", + "79157.5", + "79041.94", + "79000.96", + "691592.05", + "8.755314", + "369703.29", + "4.680333", + 889, + 1744049094287, + "78991.17", + "MINUTE_5", + 1744048800000, + 1744049099999 + ], + [ + "78655.39", + "79049.07", + "79000.94", + "78919.91", + "926984.6", + "11.75327", + "547044.72", + "6.935461", + 1016, + 1744049400108, + "78870.47", + "MINUTE_5", + 1744049100000, + 1744049399999 + ], + [ + "78716.08", + "79153.8", + "78916", + "78783.32", + "879527.64", + "11.151059", + "529640.51", + "6.714542", + 1014, + 1744049700228, + "78874.07", + "MINUTE_5", + 1744049400000, + 1744049699999 + ], + [ + "78731.28", + "79322.08", + "78783.4", + "79197.88", + "656978.55", + "8.312678", + "391077.76", + "4.947915", + 798, + 1744050000074, + "79033.61", + "MINUTE_5", + 1744049700000, + 1744049999999 + ], + [ + "78943.38", + "79327.37", + "79219.74", + "79073.01", + "727153.17", + "9.190999", + "417392.68", + "5.275804", + 853, + 1744050297287, + "79115.91", + "MINUTE_5", + 1744050000000, + 1744050299999 + ], + [ + "78559.74", + "79105.98", + "79081.07", + "78574.94", + "998609.82", + "12.684508", + "490766.3", + "6.233135", + 1048, + 1744050600014, + "78726.92", + "MINUTE_5", + 1744050300000, + 1744050599999 + ], + [ + "78504.48", + "78675.75", + "78574.94", + "78675.75", + "870168.67", + "11.073482", + "502269.88", + "6.391821", + 1006, + 1744050895287, + "78581.32", + "MINUTE_5", + 1744050600000, + 1744050899999 + ], + [ + "78615.94", + "78954.16", + "78668", + "78863.69", + "646222.61", + "8.197912", + "369172.02", + "4.68332", + 831, + 1744051197287, + "78827.77", + "MINUTE_5", + 1744050900000, + 1744051199999 + ], + [ + "78762.14", + "79094.85", + "78862.95", + "79028.13", + "243295.96", + "3.082274", + "142990.86", + "1.811844", + 321, + 1744051318287, + "78934.07", + "MINUTE_5", + 1744051200000, + 1744051499999 + ] + ], + "queryString": "endTime=1744051500000\u0026interval=MINUTE_5\u0026limit=500\u0026startTime=1744047600000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "0.000004964", + "0.000005001", + "0.000004964", + "0.000004997", + "225.870214421", + "45238739", + "183.254931443", + "36708858.5", + 14, + 1720121097116, + "0.000004992", + "MINUTE_5", + 1720120800000, + 1720121099999 + ], + [ + "0.000004997", + "0.000005006", + "0.000004997", + "0.000005004", + "651.035635433", + "130213219.5", + "374.70650677", + "74942523.8", + 27, + 1720121397116, + "0.000004999", + "MINUTE_5", + 1720121100000, + 1720121399999 + ], + [ + "0.000004911", + "0.000005004", + "0.000005004", + "0.000004911", + "537.171531629", + "108789460", + "165.655217487", + "33569527.1", + 25, + 1720121655118, + "0.000004937", + "MINUTE_5", + 1720121400000, + 1720121699999 + ], + [ + "0.000004903", + "0.000004911", + "0.000004911", + "0.000004903", + "570.142046682", + "116193562.3", + "228.720909988", + "46606967", + 31, + 1720121997116, + "0.000004906", + "MINUTE_5", + 1720121700000, + 1720121999999 + ], + [ + "0.000004903", + "0.000004927", + "0.000004903", + "0.000004916", + "474.600363518", + "96491726.7", + "223.221459386", + "45398738.5", + 26, + 1720122297118, + "0.000004918", + "MINUTE_5", + 1720122000000, + 1720122299999 + ] + ], + "queryString": "endTime=1743702190295\u0026interval=MINUTE_5\u0026startTime=1743615790295", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "77631.89", + "77886.25", + "77685.78", + "77833.81", + "612340.63", + "7.872139", + "349344.21", + "4.491398", + 808, + 1744183800000, + "77785.87", + "MINUTE_5", + 1744183800000, + 1744184099999 + ], + [ + "77731.29", + "77854.06", + "77843.25", + "77747.94", + "622751.95", + "8.006937", + "361735.8", + "4.651004", + 731, + 1744184100000, + "77776.56", + "MINUTE_5", + 1744184100000, + 1744184399999 + ], + [ + "77732.96", + "77930.24", + "77777.81", + "77906.67", + "558923.35", + "7.18053", + "292028.34", + "3.751683", + 642, + 1744184400000, + "77838.77", + "MINUTE_5", + 1744184400000, + 1744184699999 + ], + [ + "77625.37", + "77901.53", + "77901.53", + "77728.29", + "656212.52", + "8.440868", + "389549.76", + "5.0107", + 795, + 1744184700000, + "77742.37", + "MINUTE_5", + 1744184700000, + 1744184999999 + ], + [ + "77585.08", + "77755.08", + "77729.31", + "77671.59", + "565843.04", + "7.285365", + "303819.54", + "3.911745", + 618, + 1744185000000, + "77668.47", + "MINUTE_5", + 1744185000000, + 1744185299999 + ] + ], + "queryString": "endTime=1744191300000\u0026interval=MINUTE_5\u0026limit=500\u0026startTime=1744183800000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + [ + "78860.99", + "79226.16", + "79148.93", + "78890.96", + "5311655.72", + "67.223912", + "2966582.59", + "37.543301", + 6392, + 1744102800000, + "79014.48", + "HOUR_1", + 1744102800000, + 1744106399999 + ], + [ + "78796.26", + "79161.56", + "78875.92", + "78964.62", + "6343101.23", + "80.318496", + "3440357.97", + "43.563319", + 6535, + 1744106400000, + "78974.41", + "HOUR_1", + 1744106400000, + 1744109999999 + ], + [ + "78952.78", + "80018.92", + "78964.63", + "79951.46", + "5437651.39", + "68.487417", + "3071683.13", + "38.685485", + 5868, + 1744110000000, + "79397.34", + "HOUR_1", + 1744110000000, + 1744113599999 + ], + [ + "79544.43", + "80067.86", + "79961.16", + "79792.77", + "4741037.22", + "59.421898", + "2573939.07", + "32.260785", + 4939, + 1744113600000, + "79786.19", + "HOUR_1", + 1744113600000, + 1744117199999 + ], + [ + "79398.18", + "80322.78", + "79721.02", + "79880", + "4057342.44", + "50.767962", + "2255424.33", + "28.220086", + 4780, + 1744117200000, + "79919.78", + "HOUR_1", + 1744117200000, + 1744120799999 + ] + ], + "queryString": "endTime=1744192800000\u0026interval=HOUR_1\u0026limit=500\u0026startTime=1744102800000", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/markPrice": { + "GET": [ + { + "data": { + "markPrice": "57992.58", + "symbol": "BTC_USDT", + "time": "1720110293905" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/markPriceComponents": { + "GET": [ + { + "data": { + "components": [ + { + "convertPrice": "58035.99", + "exchange": "BINANCE", + "symbol": "BTC_USDT", + "symbolPrice": "58035.99", + "weight": "0.52" + }, + { + "convertPrice": "58034.8", + "exchange": "OKX", + "symbol": "BTC_USDT", + "symbolPrice": "58034.8", + "weight": "0.12" + }, + { + "convertPrice": "58034.21", + "exchange": "HUOBI", + "symbol": "BTC_USDT", + "symbolPrice": "58034.21", + "weight": "0.02" + }, + { + "convertPrice": "58023.29", + "exchange": "POLONIEX", + "symbol": "BTC_USDT", + "symbolPrice": "58023.29", + "weight": "0.02" + }, + { + "convertPrice": "58036.8", + "exchange": "GATEIO", + "symbol": "BTC_USDT", + "symbolPrice": "58036.8", + "weight": "0.01" + } + ], + "markPrice": "58031.85", + "symbol": "BTC_USDT", + "ts": 1720110330525 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/orderBook": { + "GET": [ + { + "data": { + "asks": [ + "88350.22", + "0.019937", + "88376.19", + "0.000203", + "88376.58", + "0.000696", + "88416.98", + "0.09048", + "88450.09", + "0.000237", + "88475.29", + "0.003267", + "88475.3", + "0.051213", + "88480.39", + "0.000200", + "88489.33", + "0.000200", + "88489.93", + "0.000312" + ], + "bids": [ + "88350.21", + "0.140201", + "88350.2", + "0.07", + "88345.01", + "0.607222", + "88345", + "0.724152", + "88344.99", + "0.644995", + "88344.97", + "1.419373", + "88324.8", + "0.041414", + "88248.5", + "0.49", + "88223", + "0.090549", + "88195.2", + "0.006480" + ], + "scale": "0.01", + "time": 1742832730542, + "ts": 1742832730577 + }, + "queryString": "limit=150", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "asks": [ + "88350.22", + "0.019937", + "88376.19", + "0.000203", + "88376.58", + "0.000696", + "88416.98", + "0.09048", + "88450.09", + "0.000237", + "88475.29", + "0.003267", + "88475.3", + "0.051213", + "88480.39", + "0.000200", + "88489.33", + "0.000200", + "88489.93", + "0.000312" + ], + "bids": [ + "88350.21", + "0.140201", + "88350.2", + "0.07", + "88345.01", + "0.607222", + "88345", + "0.724152", + "88344.99", + "0.644995", + "88344.97", + "1.419373", + "88324.8", + "0.041414", + "88248.5", + "0.49", + "88223", + "0.090549", + "88195.2", + "0.006480" + ], + "scale": "0.01", + "time": 1742832730542, + "ts": 1742832730577 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "asks": [ + "106181", + "0.000222", + "106200", + "0.000060", + "106209", + "0.003933", + "106216", + "0.000040", + "106217", + "0.000285", + "106222", + "0.002831", + "106234", + "0.000040", + "106244", + "0.002140", + "106252", + "0.000160", + "106258", + "0.000380", + "106264", + "0.001080", + "106292", + "0.183303", + "106295", + "0.068600", + "106297", + "0.015", + "106303", + "0.340415", + "106313", + "0.193932", + "106325", + "0.000963", + "106331", + "0.000022", + "106345", + "0.007485", + "106351", + "0.031688", + "106352", + "0.000388", + "106355", + "0.013899", + "106356", + "0.06948", + "106357", + "0.010458", + "106361", + "0.000080", + "106366", + "0.09529", + "106368", + "0.019419", + "106376", + "0.000040", + "106377", + "0.147713", + "106378", + "0.036062", + "106382", + "0.006986", + "106387", + "0.903228", + "106389", + "0.309238", + "106393", + "0.012975", + "106397", + "0.0001", + "106403", + "0.024091", + "106414", + "0.053871", + "106416", + "0.00002", + "106417", + "0.00122", + "106444", + "0.0002", + "106446", + "0.000042", + "106448", + "0.00052", + "106473", + "0.00012", + "106474", + "0.064632", + "106485", + "0.000076", + "106500", + "0.00006", + "106520", + "0.094682", + "106524", + "0.00012", + "106531", + "0.000066", + "106540", + "0.002486", + "106542", + "0.000292", + "106547", + "0.192425", + "106556", + "0.0002", + "106572", + "0.00002", + "106573", + "0.093383", + "106596", + "0.654467", + "106607", + "1.449125", + "106612", + "0.000180", + "106618", + "4.015499", + "106625", + "0.000760", + "106628", + "18.730926", + "106649", + "0.000340", + "106653", + "0.00236", + "106654", + "0.002388", + "106659", + "0.000168", + "106667", + "0.000120", + "106669", + "0.003933", + "106674", + "0.000040", + "106686", + "0.002831", + "106698", + "0.002527", + "106700", + "0.099", + "106712", + "0.000042", + "106718", + "0.068580", + "106726", + "0.000475", + "106738", + "0.000040", + "106791", + "0.001016", + "106792", + "0.000214", + "106799", + "0.00004", + "106800", + "0.000081", + "106801", + "0.000138", + "106820", + "0.00008", + "106821", + "0.00054", + "106822", + "0.000100", + "106830", + "0.319995", + "106843", + "0.000022", + "106871", + "0.000063", + "106879", + "0.000076", + "106886", + "0.00002", + "106887", + "0.00016", + "106888", + "0.000285", + "106897", + "0.000044", + "106927", + "0.00002", + "106928", + "0.00108", + "106953", + "0.00012", + "106967", + "0.000276", + "106974", + "0.00002", + "106976", + "0.000286", + "106978", + "0.000042", + "106980", + "0.00034", + "106984", + "0.00038" + ], + "bids": [ + "106128", + "0.00018", + "106096", + "0.030854", + "106045", + "0.197714", + "106039", + "0.009515", + "106028", + "0.019248", + "106010", + "0.197714", + "105999", + "0.002011", + "105996", + "0.001886", + "105989", + "0.006037", + "105986", + "0.001887", + "105978", + "0.002678", + "105975", + "0.003707", + "105965", + "0.009487", + "105936", + "0.001415", + "105925", + "0.001464", + "105919", + "0.019463", + "105915", + "0.008029", + "105894", + "0.025", + "105876", + "0.000944", + "105867", + "0.040", + "105864", + "0.031996", + "105863", + "0.015105", + "105855", + "0.006985", + "105851", + "0.099797", + "105850", + "0.223812", + "105844", + "0.012973", + "105841", + "0.18534", + "105839", + "0.223813", + "105834", + "0.024094", + "105828", + "0.223812", + "105823", + "0.046512", + "105819", + "1.141424", + "105818", + "0.212195", + "105807", + "0.013897", + "105796", + "0.02581", + "105786", + "0.094234", + "105779", + "0.063761", + "105775", + "0.09344", + "105755", + "0.006241", + "105723", + "0.096475", + "105703", + "0.000340", + "105696", + "0.000076", + "105648", + "0.000042", + "105642", + "0.660399", + "105638", + "0.00004", + "105631", + "1.461254", + "105621", + "4.044297", + "105615", + "0.00002", + "105610", + "14.975124", + "105607", + "0.001561", + "105602", + "0.00076", + "105600", + "0.00006", + "105573", + "0.001525", + "105568", + "0.00004", + "105546", + "0.0001", + "105544", + "0.000391", + "105513", + "0.00012", + "105500", + "0.049160", + "105499", + "0.000399", + "105487", + "0.000077", + "105475", + "0.000475", + "105471", + "0.192303", + "105467", + "0.000515", + "105466", + "0.000084", + "105455", + "0.000069", + "105452", + "0.068580", + "105447", + "0.000080", + "105442", + "0.000047", + "105420", + "0.000063", + "105418", + "0.000120", + "105409", + "0.000779", + "105400", + "0.026377", + "105391", + "0.000023", + "105383", + "0.000380", + "105382", + "0.000042", + "105358", + "0.000273", + "105353", + "0.00012", + "105336", + "0.00214", + "105335", + "0.0002", + "105333", + "0.000011", + "105332", + "0.00054", + "105324", + "0.000214", + "105317", + "0.000187", + "105309", + "0.00002", + "105305", + "0.000022", + "105303", + "0.000076", + "105300", + "0.000154", + "105293", + "0.003933", + "105289", + "0.000970", + "105286", + "0.010200", + "105283", + "0.005883", + "105275", + "0.000047", + "105256", + "0.000084", + "105254", + "0.000011", + "105249", + "0.00122", + "105239", + "0.000981", + "105231", + "0.00034", + "105229", + "0.000011", + "105227", + "0.000044", + "105225", + "0.00004" + ], + "scale": "1", + "time": 1762186692324, + "ts": 1762186692370 + }, + "queryString": "limit=100\u0026scale=0.01", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/price": { + "GET": [ + { + "data": { + "dailyChange": "0.4566", + "price": "0.02501", + "symbol": "BTC_USDT", + "time": 1720108122072, + "ts": 1720108122089 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/ticker24h": { + "GET": [ + { + "data": { + "amount": "72573705.68779424", + "ask": "58050.37", + "askQuantity": "0.285757", + "bid": "58018.4", + "bidQuantity": "0.026527", + "close": "58017.58", + "closeTime": 1720116658453, + "dailyChange": "-0.0392", + "displayName": "BTC/USDT", + "high": "60491.7", + "low": "56777.77", + "markPrice": "58051.16", + "open": "60381.99", + "quantity": "1236.582993", + "startTime": 1720030200000, + "symbol": "BTC_USDT", + "tradeCount": 62498, + "ts": 1720116658703 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT/trades": { + "GET": [ + { + "data": [ + { + "amount": "4.3263322", + "createTime": 1720071844418, + "id": "7830", + "price": "0.0092", + "quantity": "470.2535", + "takerSide": "SELL", + "ts": 1720071844431 + }, + { + "amount": "1.01999997", + "createTime": 1719986507522, + "id": "7829", + "price": "0.0099", + "quantity": "103.0303", + "takerSide": "BUY", + "ts": 1719986507540 + }, + { + "amount": "6.6476348", + "createTime": 1719900635808, + "id": "7828", + "price": "0.0092", + "quantity": "722.569", + "takerSide": "SELL", + "ts": 1719900635817 + }, + { + "amount": "0.22580679", + "createTime": 1719900601221, + "id": "7827", + "price": "0.0093", + "quantity": "24.2803", + "takerSide": "SELL", + "ts": 1719900601235 + }, + { + "amount": "29.77419273", + "createTime": 1719900601221, + "id": "7826", + "price": "0.0093", + "quantity": "3201.5261", + "takerSide": "SELL", + "ts": 1719900601235 + }, + { + "amount": "0.185628", + "createTime": 1719819940268, + "id": "7825", + "price": "0.0093", + "quantity": "19.96", + "takerSide": "SELL", + "ts": 1719819940274 + }, + { + "amount": "7.69999932", + "createTime": 1719670968771, + "id": "7824", + "price": "0.0108", + "quantity": "712.9629", + "takerSide": "BUY", + "ts": 1719670968787 + }, + { + "amount": "0.00000108", + "createTime": 1719670968771, + "id": "7823", + "price": "0.0108", + "quantity": "0.0001", + "takerSide": "BUY", + "ts": 1719670968787 + }, + { + "amount": "6.89999796", + "createTime": 1719670663866, + "id": "7822", + "price": "0.0108", + "quantity": "638.8887", + "takerSide": "BUY", + "ts": 1719670663875 + }, + { + "amount": "2.69999928", + "createTime": 1719670663866, + "id": "7821", + "price": "0.0099", + "quantity": "272.7272", + "takerSide": "BUY", + "ts": 1719670663875 + }, + { + "amount": "0.17", + "createTime": 1719668253388, + "id": "7820", + "price": "0.0085", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719668253399 + }, + { + "amount": "23.15999972", + "createTime": 1719666369642, + "id": "7819", + "price": "0.0116", + "quantity": "1996.5517", + "takerSide": "BUY", + "ts": 1719666369657 + }, + { + "amount": "3.99999924", + "createTime": 1719665689322, + "id": "7818", + "price": "0.0108", + "quantity": "370.3703", + "takerSide": "BUY", + "ts": 1719665689328 + }, + { + "amount": "0.00340704", + "createTime": 1719582875661, + "id": "7817", + "price": "0.0048", + "quantity": "0.7098", + "takerSide": "SELL", + "ts": 1719582875673 + }, + { + "amount": "17.47058742", + "createTime": 1719553581761, + "id": "7816", + "price": "0.0099", + "quantity": "1764.7058", + "takerSide": "BUY", + "ts": 1719553581767 + }, + { + "amount": "0.00000099", + "createTime": 1719553581761, + "id": "7815", + "price": "0.0099", + "quantity": "0.0001", + "takerSide": "BUY", + "ts": 1719553581767 + }, + { + "amount": "28.3055507", + "createTime": 1719553581761, + "id": "7814", + "price": "0.0098", + "quantity": "2888.3215", + "takerSide": "BUY", + "ts": 1719553581767 + }, + { + "amount": "2.99999898", + "createTime": 1719552186103, + "id": "7813", + "price": "0.0099", + "quantity": "303.0302", + "takerSide": "BUY", + "ts": 1719552186116 + }, + { + "amount": "28.4058047", + "createTime": 1719552155758, + "id": "7812", + "price": "0.0098", + "quantity": "2898.5515", + "takerSide": "BUY", + "ts": 1719552155767 + }, + { + "amount": "1.212164", + "createTime": 1719552042132, + "id": "7811", + "price": "0.01", + "quantity": "121.2164", + "takerSide": "BUY", + "ts": 1719552042144 + }, + { + "amount": "4.79999916", + "createTime": 1719552042132, + "id": "7810", + "price": "0.0099", + "quantity": "484.8484", + "takerSide": "BUY", + "ts": 1719552042144 + }, + { + "amount": "4.8", + "createTime": 1719551975631, + "id": "7809", + "price": "0.01", + "quantity": "480", + "takerSide": "SELL", + "ts": 1719551975644 + }, + { + "amount": "10.4936139", + "createTime": 1719551975631, + "id": "7808", + "price": "0.0105", + "quantity": "999.3918", + "takerSide": "SELL", + "ts": 1719551975644 + }, + { + "amount": "10.4936139", + "createTime": 1719551975631, + "id": "7807", + "price": "0.0105", + "quantity": "999.3918", + "takerSide": "SELL", + "ts": 1719551975644 + }, + { + "amount": "19.9999998", + "createTime": 1719551957623, + "id": "7806", + "price": "0.011", + "quantity": "1818.1818", + "takerSide": "SELL", + "ts": 1719551957634 + }, + { + "amount": "36.4471941", + "createTime": 1719551957623, + "id": "7805", + "price": "0.0111", + "quantity": "3283.531", + "takerSide": "SELL", + "ts": 1719551957634 + }, + { + "amount": "2.29635105", + "createTime": 1719528331520, + "id": "7804", + "price": "0.0115", + "quantity": "199.6827", + "takerSide": "SELL", + "ts": 1719528331535 + }, + { + "amount": "31.10379125", + "createTime": 1719528331520, + "id": "7803", + "price": "0.0115", + "quantity": "2704.6775", + "takerSide": "SELL", + "ts": 1719528331535 + }, + { + "amount": "18.99999985", + "createTime": 1719528331520, + "id": "7802", + "price": "0.0115", + "quantity": "1652.1739", + "takerSide": "SELL", + "ts": 1719528331535 + }, + { + "amount": "7.01998682", + "createTime": 1719069579456, + "id": "7801", + "price": "0.0121", + "quantity": "580.1642", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "2.84409996", + "createTime": 1719069579456, + "id": "7800", + "price": "0.0124", + "quantity": "229.3629", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "2.99999996", + "createTime": 1719069513325, + "id": "7799", + "price": "0.0148", + "quantity": "202.7027", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "11.98001277", + "createTime": 1719036072662, + "id": "7798", + "price": "0.0121", + "quantity": "990.0837", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "9.99999962", + "createTime": 1719036072662, + "id": "7797", + "price": "0.0122", + "quantity": "819.6721", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "2.28023124", + "createTime": 1719036072662, + "id": "7796", + "price": "0.0122", + "quantity": "186.9042", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "9.9", + "createTime": 1719036072662, + "id": "7795", + "price": "0.0125", + "quantity": "792", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "4.2197714", + "createTime": 1718626301699, + "id": "7794", + "price": "0.013", + "quantity": "324.5978", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.68963027", + "createTime": 1718626301699, + "id": "7793", + "price": "0.0133", + "quantity": "51.8519", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.97036973", + "createTime": 1718601527813, + "id": "7792", + "price": "0.0133", + "quantity": "148.1481", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.99999935", + "createTime": 1718591717093, + "id": "7791", + "price": "0.0135", + "quantity": "148.1481", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "5.6802278", + "createTime": 1718461172672, + "id": "7790", + "price": "0.013", + "quantity": "436.9406", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.34049888", + "createTime": 1718457286296, + "id": "7789", + "price": "0.0196", + "quantity": "68.3928", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "1.29999906", + "createTime": 1718457217660, + "id": "7788", + "price": "0.0122", + "quantity": "106.5573", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.12989884", + "createTime": 1718457117713, + "id": "7787", + "price": "0.0196", + "quantity": "57.6479", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "6.8999996", + "createTime": 1718457045569, + "id": "7786", + "price": "0.0169", + "quantity": "408.284", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.00385728", + "createTime": 1718457021257, + "id": "7785", + "price": "0.0147", + "quantity": "0.2624", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.142", + "createTime": 1718456823226, + "id": "7784", + "price": "0.0142", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "11.47999881", + "createTime": 1718406670010, + "id": "7783", + "price": "0.0147", + "quantity": "780.9523", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "6.31976958", + "createTime": 1718406294864, + "id": "7782", + "price": "0.0122", + "quantity": "518.0139", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "4.00000059", + "createTime": 1718405563733, + "id": "7781", + "price": "0.0123", + "quantity": "325.2033", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "19.99999971", + "createTime": 1718405551491, + "id": "7780", + "price": "0.0139", + "quantity": "1438.8489", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "10.85888433", + "createTime": 1718405551491, + "id": "7779", + "price": "0.0139", + "quantity": "781.2147", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "10.49299812", + "createTime": 1718390197253, + "id": "7778", + "price": "0.0198", + "quantity": "529.9494", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "1.02787552", + "createTime": 1718389801065, + "id": "7777", + "price": "0.0142", + "quantity": "72.3856", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "8.22669833", + "createTime": 1718384646592, + "id": "7776", + "price": "0.0197", + "quantity": "417.5989", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "9.38939824", + "createTime": 1718384645219, + "id": "7775", + "price": "0.0197", + "quantity": "476.6192", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "9.98879832", + "createTime": 1718384643993, + "id": "7774", + "price": "0.0197", + "quantity": "507.0456", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "9.98879832", + "createTime": 1718384642452, + "id": "7773", + "price": "0.0197", + "quantity": "507.0456", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "3.81832551", + "createTime": 1718384471582, + "id": "7772", + "price": "0.0193", + "quantity": "197.8407", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "2.09579832", + "createTime": 1718384459026, + "id": "7771", + "price": "0.0189", + "quantity": "110.8888", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "4.8999987", + "createTime": 1718384452597, + "id": "7770", + "price": "0.0158", + "quantity": "310.1265", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.129", + "createTime": 1718384447487, + "id": "7769", + "price": "0.0129", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "9.89999881", + "createTime": 1718328048060, + "id": "7768", + "price": "0.0167", + "quantity": "592.8143", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "29.5677694", + "createTime": 1718328030526, + "id": "7767", + "price": "0.013", + "quantity": "2274.4438", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.13", + "createTime": 1718328030526, + "id": "7766", + "price": "0.013", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "18.9552156", + "createTime": 1718284693762, + "id": "7765", + "price": "0.012", + "quantity": "1579.6013", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "9.9999996", + "createTime": 1718284693762, + "id": "7764", + "price": "0.012", + "quantity": "833.3333", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "12.41288571", + "createTime": 1718284562528, + "id": "7763", + "price": "0.0123", + "quantity": "1009.1777", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.00999974", + "createTime": 1718284562528, + "id": "7762", + "price": "0.0123", + "quantity": "82.1138", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "10.18147544", + "createTime": 1718284470783, + "id": "7761", + "price": "0.0134", + "quantity": "759.8116", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "10.18147544", + "createTime": 1718284470783, + "id": "7760", + "price": "0.0134", + "quantity": "759.8116", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "10.11221352", + "createTime": 1718284470783, + "id": "7759", + "price": "0.0134", + "quantity": "754.6428", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.47316848", + "createTime": 1718284454501, + "id": "7758", + "price": "0.0146", + "quantity": "32.4088", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "50.218899", + "createTime": 1718284454501, + "id": "7757", + "price": "0.015", + "quantity": "3347.9266", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "36.70149375", + "createTime": 1718284450744, + "id": "7756", + "price": "0.0151", + "quantity": "2430.5625", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "25.2915362", + "createTime": 1718270468530, + "id": "7755", + "price": "0.0146", + "quantity": "1732.297", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.99999954", + "createTime": 1718270468530, + "id": "7754", + "price": "0.0154", + "quantity": "129.8701", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.1520293", + "createTime": 1718270468530, + "id": "7753", + "price": "0.017", + "quantity": "8.9429", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.9479693", + "createTime": 1718120093996, + "id": "7752", + "price": "0.017", + "quantity": "55.7629", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.99999922", + "createTime": 1718120093996, + "id": "7751", + "price": "0.0179", + "quantity": "111.7318", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "1.9999998", + "createTime": 1718120093996, + "id": "7750", + "price": "0.018", + "quantity": "111.1111", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.2245815", + "createTime": 1718035633503, + "id": "7749", + "price": "0.0198", + "quantity": "11.3425", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.08568532", + "createTime": 1718035633503, + "id": "7748", + "price": "0.0196", + "quantity": "4.3717", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "8.46732605", + "createTime": 1716541371328, + "id": "7747", + "price": "0.0185", + "quantity": "457.6933", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.184", + "createTime": 1716541357435, + "id": "7746", + "price": "0.0184", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.18032639", + "createTime": 1716530169448, + "id": "7745", + "price": "0.0179", + "quantity": "10.0741", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "53.99999868", + "createTime": 1716461632835, + "id": "7744", + "price": "0.0183", + "quantity": "2950.8196", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "8.41784262", + "createTime": 1716316137764, + "id": "7743", + "price": "0.0183", + "quantity": "459.9914", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.00325374", + "createTime": 1716316137764, + "id": "7742", + "price": "0.0183", + "quantity": "0.1778", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "78.60584774", + "createTime": 1716291793591, + "id": "7741", + "price": "0.0199", + "quantity": "3950.0426", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "11.49415244", + "createTime": 1716291610502, + "id": "7740", + "price": "0.0199", + "quantity": "577.5956", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "9.89999926", + "createTime": 1716291610502, + "id": "7739", + "price": "0.0199", + "quantity": "497.4874", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "10.56999948", + "createTime": 1716287013747, + "id": "7738", + "price": "0.0183", + "quantity": "577.5956", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "0.00127458", + "createTime": 1716270572197, + "id": "7737", + "price": "0.0194", + "quantity": "0.0657", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "28.36999934", + "createTime": 1716212393600, + "id": "7736", + "price": "0.0194", + "quantity": "1462.3711", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "55.8388357", + "createTime": 1716212384321, + "id": "7735", + "price": "0.0194", + "quantity": "2878.2905", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "48.50570184", + "createTime": 1716212384321, + "id": "7734", + "price": "0.0193", + "quantity": "2513.2488", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "45.17009442", + "createTime": 1716212384321, + "id": "7733", + "price": "0.0193", + "quantity": "2340.4194", + "takerSide": "BUY", + "ts": 1719393673042 + }, + { + "amount": "0.4532545", + "createTime": 1716212290421, + "id": "7732", + "price": "0.019", + "quantity": "23.8555", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "4.00000031", + "createTime": 1716212286448, + "id": "7731", + "price": "0.0191", + "quantity": "209.4241", + "takerSide": "SELL", + "ts": 1719393673042 + }, + { + "amount": "42.74787648", + "createTime": 1716212286448, + "id": "7730", + "price": "0.0192", + "quantity": "2226.4519", + "takerSide": "SELL", + "ts": 1719393673042 }, - "EMC2": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 69, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "43.32364605", + "createTime": 1716212286448, + "id": "7729", + "price": "0.0193", + "quantity": "2244.7485", + "takerSide": "SELL", + "ts": 1719393673042 }, - "EMO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 70, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.85601546", + "createTime": 1716146224374, + "id": "7728", + "price": "0.0194", + "quantity": "95.6709", + "takerSide": "BUY", + "ts": 1719393673042 }, - "ENC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 71, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "EOS": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "poloniexeos1", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 298, - "isGeofenced": 0, - "minConf": 600, - "name": "", - "txFee": "0.00000000" + { + "amount": "32.7579993", + "createTime": 1716145188885, + "id": "7727", + "price": "0.0195", + "quantity": "1679.8974", + "takerSide": "BUY", + "ts": 1719393673042 }, - "ETC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 283, - "isGeofenced": 0, - "minConf": 600, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.193", + "createTime": 1716145188885, + "id": "7726", + "price": "0.0193", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673042 }, - "ETH": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 267, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.01000000" + { + "amount": "2.09203836", + "createTime": 1715808062754, + "id": "7725", + "price": "0.0204", + "quantity": "102.5509", + "takerSide": "BUY", + "ts": 1719393673042 }, - "EXE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 73, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "45.17966173", + "createTime": 1715808062754, + "id": "7724", + "price": "0.0203", + "quantity": "2225.5991", + "takerSide": "BUY", + "ts": 1719393673042 }, - "EXP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 270, - "isGeofenced": 0, - "minConf": 8000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.71487827", + "createTime": 1715577971976, + "id": "7723", + "price": "0.0189", + "quantity": "90.7343", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FAC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 74, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "FCN": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "6mkbrPdSAjeaQKCCx8Nus1JiKb4HdeTDXC4bEWunDzTMXMPESd7aFNYPAG1U4MUpnhHfJfzVyTqnRFRW2REKN6efBVRMoSY", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 75, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "6.742348", + "createTime": 1715577971976, + "id": "7722", + "price": "0.02", + "quantity": "337.1174", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FCT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 271, - "isGeofenced": 0, - "minConf": 3, - "name": "", - "txFee": "0.01000000" + { + "amount": "35.166966", + "createTime": 1715577971976, + "id": "7721", + "price": "0.02", + "quantity": "1758.3483", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FIBRE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 76, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.06017", + "createTime": 1715576748762, + "id": "7720", + "price": "0.02", + "quantity": "453.0085", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FLAP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 77, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "5.772864", + "createTime": 1715518018095, + "id": "7719", + "price": "0.02", + "quantity": "288.6432", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FLDC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 78, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "750.00000000" + { + "amount": "44.21658903", + "createTime": 1715517971667, + "id": "7718", + "price": "0.0201", + "quantity": "2199.8303", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FLO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 254, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.8999985", + "createTime": 1715517966408, + "id": "7717", + "price": "0.021", + "quantity": "471.4285", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FLT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 79, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "13.5889704", + "createTime": 1715488242197, + "id": "7716", + "price": "0.024", + "quantity": "566.2071", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FOAM": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 307, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "1.00000000" + { + "amount": "15.86531438", + "createTime": 1715488030446, + "id": "7715", + "price": "0.0241", + "quantity": "658.3118", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FOX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 80, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "26.41116268", + "createTime": 1715487840036, + "id": "7714", + "price": "0.0244", + "quantity": "1082.4247", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FRAC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 81, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "41.26353387", + "createTime": 1715477468140, + "id": "7713", + "price": "0.0299", + "quantity": "1380.0513", + "takerSide": "SELL", + "ts": 1719393673042 }, - "FRK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 82, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "7.99999915", + "createTime": 1715477455850, + "id": "7712", + "price": "0.0299", + "quantity": "267.5585", + "takerSide": "BUY", + "ts": 1719393673042 }, - "FRQ": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 83, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.90425075", + "createTime": 1715477455850, + "id": "7711", + "price": "0.0299", + "quantity": "30.2425", + "takerSide": "BUY", + "ts": 1719393673042 }, - "FVZ": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 84, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "74.414325", + "createTime": 1715477408605, + "id": "7710", + "price": "0.0298", + "quantity": "2497.125", + "takerSide": "BUY", + "ts": 1719393673042 }, - "FZ": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 85, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "0.11422224", + "createTime": 1715457038470, + "id": "7709", + "price": "0.0198", + "quantity": "5.7688", + "takerSide": "BUY", + "ts": 1719393673042 }, - "FZN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 86, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "0.392", + "createTime": 1715457031272, + "id": "7708", + "price": "0.0196", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GAME": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 93, - "isGeofenced": 0, - "minConf": 80, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.03338756", + "createTime": 1715357587076, + "id": "7707", + "price": "0.0194", + "quantity": "53.2674", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GAP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 87, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "46.38821971", + "createTime": 1715357587076, + "id": "7706", + "price": "0.0193", + "quantity": "2403.5347", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GAS": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 296, - "isGeofenced": 0, - "minConf": 18, - "name": "", - "txFee": "0.00000000" + { + "amount": "44.72281152", + "createTime": 1715357587076, + "id": "7705", + "price": "0.0192", + "quantity": "2329.3131", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GDN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 88, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "57.192424", + "createTime": 1715355669162, + "id": "7704", + "price": "0.02", + "quantity": "2859.6212", + "takerSide": "SELL", + "ts": 1719393673042 }, - "GEMZ": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 89, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "500.00000000" + { + "amount": "47.807576", + "createTime": 1715354408480, + "id": "7703", + "price": "0.02", + "quantity": "2390.3788", + "takerSide": "SELL", + "ts": 1719393673042 }, - "GEO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 90, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "50.25", + "createTime": 1715354408480, + "id": "7702", + "price": "0.0201", + "quantity": "2500", + "takerSide": "SELL", + "ts": 1719393673042 }, - "GIAR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 91, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "48.40786314", + "createTime": 1715208277757, + "id": "7701", + "price": "0.0201", + "quantity": "2408.3514", + "takerSide": "SELL", + "ts": 1719393673042 }, - "GLB": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 92, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "44.17252372", + "createTime": 1715208277757, + "id": "7700", + "price": "0.0202", + "quantity": "2186.7586", + "takerSide": "SELL", + "ts": 1719393673042 }, - "GML": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "humanType": "BTC Clone", - "id": 94, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "2.4651759", + "createTime": 1715200085506, + "id": "7699", + "price": "0.019", + "quantity": "129.7461", + "takerSide": "SELL", + "ts": 1719393673042 }, - "GNO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 291, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01500000" + { + "amount": "95.656999", + "createTime": 1715193797037, + "id": "7698", + "price": "0.0202", + "quantity": "4735.495", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GNS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 95, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.198", + "createTime": 1715193797037, + "id": "7697", + "price": "0.0198", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GNT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 290, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "1.00000000" + { + "amount": "8.55845076", + "createTime": 1715075369311, + "id": "7696", + "price": "0.0213", + "quantity": "401.8052", + "takerSide": "BUY", + "ts": 1719393673042 }, - "GOLD": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 96, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "11.04116776", + "createTime": 1715075347826, + "id": "7695", + "price": "0.0212", + "quantity": "520.8098", + "takerSide": "BUY", + "ts": 1719393673041 }, - "GPC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 97, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "10.9370058", + "createTime": 1715075347826, + "id": "7694", + "price": "0.021", + "quantity": "520.8098", + "takerSide": "BUY", + "ts": 1719393673041 }, - "GPUC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 98, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.9384302", + "createTime": 1715075347826, + "id": "7693", + "price": "0.021", + "quantity": "92.3062", + "takerSide": "BUY", + "ts": 1719393673041 }, - "GRC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 261, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.224147", + "createTime": 1715054241685, + "id": "7692", + "price": "0.0175", + "quantity": "12.8084", + "takerSide": "SELL", + "ts": 1719393673041 }, - "GRCX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 99, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "11.09324904", + "createTime": 1715054228386, + "id": "7691", + "price": "0.0211", + "quantity": "525.7464", + "takerSide": "SELL", + "ts": 1719393673041 }, - "GRIN": { - "currencyType": "mimblewimble", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "MimbleWimble", - "id": 314, - "isGeofenced": 0, - "minConf": 15, - "name": "", - "txFee": "0.10000000" + { + "amount": "11.09324874", + "createTime": 1714999690346, + "id": "7690", + "price": "0.0213", + "quantity": "520.8098", + "takerSide": "SELL", + "ts": 1719393673041 }, - "GRS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 100, - "isGeofenced": 0, - "minConf": 100000, - "name": "", - "txFee": "0.01000000" + { + "amount": "12.57935562", + "createTime": 1714987810139, + "id": "7689", + "price": "0.0219", + "quantity": "574.3998", + "takerSide": "BUY", + "ts": 1719393673041 }, - "GUE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 101, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.03291239", + "createTime": 1714987611772, + "id": "7688", + "price": "0.0217", + "quantity": "1.5167", + "takerSide": "BUY", + "ts": 1719393673041 }, - "H2O": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 102, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.62282112", + "createTime": 1714689167827, + "id": "7687", + "price": "0.0199", + "quantity": "81.5488", + "takerSide": "BUY", + "ts": 1719393673041 }, - "HIRO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 103, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.198", + "createTime": 1714689167827, + "id": "7686", + "price": "0.0198", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "HOT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 104, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.09789812", + "createTime": 1714634444218, + "id": "7685", + "price": "0.0198", + "quantity": "55.4494", + "takerSide": "BUY", + "ts": 1719393673041 }, - "HUC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 105, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.74616269", + "createTime": 1714634274303, + "id": "7684", + "price": "0.0197", + "quantity": "88.6377", + "takerSide": "SELL", + "ts": 1719393673041 }, - "HUGE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "humanType": "BTC Clone", - "id": 260, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.61808958", + "createTime": 1714546982344, + "id": "7683", + "price": "0.0198", + "quantity": "485.7621", + "takerSide": "SELL", + "ts": 1719393673041 }, - "HVC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 106, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "18.08926559", + "createTime": 1714540184158, + "id": "7682", + "price": "0.0209", + "quantity": "865.5151", + "takerSide": "SELL", + "ts": 1719393673041 }, - "HYP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 107, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.79020204", + "createTime": 1714540175717, + "id": "7681", + "price": "0.0209", + "quantity": "85.6556", + "takerSide": "BUY", + "ts": 1719393673041 }, - "HZ": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 108, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" + { + "amount": "11.04042291", + "createTime": 1714540175717, + "id": "7680", + "price": "0.0209", + "quantity": "528.2499", + "takerSide": "BUY", + "ts": 1719393673041 }, - "IFC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 109, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "2000.00000000" + { + "amount": "0.206", + "createTime": 1714540175717, + "id": "7679", + "price": "0.0206", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "INDEX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 265, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "15.4233222", + "createTime": 1714538385220, + "id": "7678", + "price": "0.019", + "quantity": "811.7538", + "takerSide": "SELL", + "ts": 1719393673041 }, - "IOC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 263, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.94897818", + "createTime": 1714509432661, + "id": "7677", + "price": "0.0171", + "quantity": "55.4958", + "takerSide": "SELL", + "ts": 1719393673041 }, - "ITC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 110, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "10.51217301", + "createTime": 1714495052659, + "id": "7676", + "price": "0.0199", + "quantity": "528.2499", + "takerSide": "SELL", + "ts": 1719393673041 }, - "IXC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 111, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "43.91285415", + "createTime": 1714489294848, + "id": "7675", + "price": "0.0209", + "quantity": "2101.0935", + "takerSide": "BUY", + "ts": 1719393673041 }, - "JLH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 112, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "46.86184672", + "createTime": 1714489294848, + "id": "7674", + "price": "0.0208", + "quantity": "2252.9734", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "9.3585765", + "createTime": 1714487859907, + "id": "7673", + "price": "0.021", + "quantity": "445.6465", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "0.541422", + "createTime": 1714480666208, + "id": "7672", + "price": "0.021", + "quantity": "25.782", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "12.98999814", + "createTime": 1714480131843, + "id": "7671", + "price": "0.0219", + "quantity": "593.1506", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "3.0199994", + "createTime": 1714480131843, + "id": "7670", + "price": "0.022", + "quantity": "137.2727", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "48.42400173", + "createTime": 1714437184409, + "id": "7669", + "price": "0.0221", + "quantity": "2191.1313", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "9.98999781", + "createTime": 1714437184409, + "id": "7668", + "price": "0.0221", + "quantity": "452.0361", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "49.79378304", + "createTime": 1714437184409, + "id": "7667", + "price": "0.0222", + "quantity": "2242.9632", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "0.224", + "createTime": 1714436016700, + "id": "7666", + "price": "0.0224", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "4.11589945", + "createTime": 1714429053484, + "id": "7665", + "price": "0.0299", + "quantity": "137.6555", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "6.91959853", + "createTime": 1714429039615, + "id": "7664", + "price": "0.0299", + "quantity": "231.4247", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "2.06025053", + "createTime": 1714429033981, + "id": "7663", + "price": "0.0299", + "quantity": "68.9047", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.00008835", + "createTime": 1714429033981, + "id": "7662", + "price": "0.0285", + "quantity": "0.0031", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "2.2506006", + "createTime": 1714429033981, + "id": "7661", + "price": "0.0276", + "quantity": "81.5435", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "32.568759", + "createTime": 1714429033981, + "id": "7660", + "price": "0.0276", + "quantity": "1180.0275", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "1.52629187", + "createTime": 1714198486116, + "id": "7659", + "price": "0.0229", + "quantity": "66.6503", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "1.01889828", + "createTime": 1714198472031, + "id": "7658", + "price": "0.0284", + "quantity": "35.8767", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.00021624", + "createTime": 1714057236834, + "id": "7657", + "price": "0.0212", + "quantity": "0.0102", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.206", + "createTime": 1714057174869, + "id": "7656", + "price": "0.0206", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "13.1435018", + "createTime": 1714050783625, + "id": "7655", + "price": "0.0212", + "quantity": "619.9765", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.212", + "createTime": 1714050783625, + "id": "7654", + "price": "0.0212", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "19.99999872", + "createTime": 1714047370950, + "id": "7653", + "price": "0.0208", + "quantity": "961.5384", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "11.040172", + "createTime": 1714047370950, + "id": "7652", + "price": "0.0208", + "quantity": "530.7775", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "0.70559844", + "createTime": 1714040940449, + "id": "7651", + "price": "0.0228", + "quantity": "30.9473", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.436", + "createTime": 1714040940449, + "id": "7650", + "price": "0.0218", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.0052546", + "createTime": 1713540734448, + "id": "7649", + "price": "0.0188", + "quantity": "0.2795", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "9.6080992", + "createTime": 1713466412986, + "id": "7648", + "price": "0.0224", + "quantity": "428.933", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.198", + "createTime": 1713466410113, + "id": "7647", + "price": "0.0198", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "5.30849488", + "createTime": 1713452655017, + "id": "7646", + "price": "0.0208", + "quantity": "255.2161", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "11.14683856", + "createTime": 1713452655017, + "id": "7645", + "price": "0.0208", + "quantity": "535.9057", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "20.363148", + "createTime": 1713450943247, + "id": "7644", + "price": "0.026", + "quantity": "783.198", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "2.8278146", + "createTime": 1713450943247, + "id": "7643", + "price": "0.026", + "quantity": "108.7621", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.31167162", + "createTime": 1713436952053, + "id": "7642", + "price": "0.0207", + "quantity": "15.0566", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "16.4801196", + "createTime": 1713350707628, + "id": "7641", + "price": "0.021", + "quantity": "784.7676", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "0.212", + "createTime": 1713333016383, + "id": "7640", + "price": "0.0212", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "2.08841259", + "createTime": 1713333016383, + "id": "7639", + "price": "0.0211", + "quantity": "98.9769", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "1.35729377", + "createTime": 1713310976554, + "id": "7638", + "price": "0.0217", + "quantity": "62.5481", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "48.99272472", + "createTime": 1713310976554, + "id": "7637", + "price": "0.0216", + "quantity": "2268.1817", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.26763114", + "createTime": 1713242966130, + "id": "7636", + "price": "0.0203", + "quantity": "13.1838", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "63.67204916", + "createTime": 1713242966130, + "id": "7635", + "price": "0.0218", + "quantity": "2920.7362", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "3.19165298", + "createTime": 1713240791520, + "id": "7634", + "price": "0.0218", + "quantity": "146.4061", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "24.89402386", + "createTime": 1713240785350, + "id": "7633", + "price": "0.0218", + "quantity": "1141.9277", + "takerSide": "SELL", + "ts": 1719393673041 + }, + { + "amount": "49.9999962", + "createTime": 1713240785350, + "id": "7632", + "price": "0.022", + "quantity": "2272.7271", + "takerSide": "SELL", + "ts": 1719393673041 }, - "JPC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 113, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "2.1799998", + "createTime": 1713240785350, + "id": "7631", + "price": "0.022", + "quantity": "99.0909", + "takerSide": "SELL", + "ts": 1719393673041 }, - "JUG": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 114, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "8.08805506", + "createTime": 1713229706818, + "id": "7630", + "price": "0.0218", + "quantity": "371.0117", + "takerSide": "BUY", + "ts": 1719393673041 }, - "KDC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 115, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.15421756", + "createTime": 1713229706818, + "id": "7629", + "price": "0.0218", + "quantity": "7.0742", + "takerSide": "BUY", + "ts": 1719393673041 }, - "KEY": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 116, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.201", + "createTime": 1713163018089, + "id": "7628", + "price": "0.0201", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "KNC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 301, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "1.50000000" + { + "amount": "8.99999905", + "createTime": 1713126347314, + "id": "7627", + "price": "0.0217", + "quantity": "414.7465", + "takerSide": "BUY", + "ts": 1719393673041 }, - "LBC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 280, - "isGeofenced": 0, - "minConf": 11, - "name": "", - "txFee": "0.05000000" + { + "amount": "48.55134816", + "createTime": 1713126347314, + "id": "7626", + "price": "0.0216", + "quantity": "2247.7476", + "takerSide": "BUY", + "ts": 1719393673041 }, - "LC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 117, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "8.4308158", + "createTime": 1713115260370, + "id": "7625", + "price": "0.022", + "quantity": "383.2189", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LCL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 118, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.0082904", + "createTime": 1713115260370, + "id": "7624", + "price": "0.0221", + "quantity": "45.624", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LEAF": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 119, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.10000000" + { + "amount": "49.99999662", + "createTime": 1713115260370, + "id": "7623", + "price": "0.0222", + "quantity": "2252.2521", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LGC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 120, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "17.99999976", + "createTime": 1713115260370, + "id": "7622", + "price": "0.0222", + "quantity": "810.8108", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LOL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 121, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "40.641471", + "createTime": 1713073928221, + "id": "7621", + "price": "0.0237", + "quantity": "1714.83", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LOOM": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 303, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "19.00000000" + { + "amount": "59.35852704", + "createTime": 1713073503158, + "id": "7620", + "price": "0.0237", + "quantity": "2504.5792", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LOVE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 122, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.237", + "createTime": 1713032646349, + "id": "7619", + "price": "0.0237", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "LPT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 312, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.05000000" + { + "amount": "198.91355198", + "createTime": 1712939193900, + "id": "7618", + "price": "0.0286", + "quantity": "6955.0193", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LQD": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 123, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "1.08644536", + "createTime": 1712844139710, + "id": "7617", + "price": "0.0286", + "quantity": "37.9876", + "takerSide": "SELL", + "ts": 1719393673041 }, - "LSK": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 278, - "isGeofenced": 0, - "minConf": 303, - "name": "", - "txFee": "0.10000000" + { + "amount": "0.00009152", + "createTime": 1712825573527, + "id": "7616", + "price": "0.0286", + "quantity": "0.0032", + "takerSide": "BUY", + "ts": 1719393673041 }, - "LTBC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 124, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "15000.00000000" + { + "amount": "19.18172828", + "createTime": 1712825565285, + "id": "7615", + "price": "0.0286", + "quantity": "670.6898", + "takerSide": "BUY", + "ts": 1719393673041 }, - "LTC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 125, - "isGeofenced": 0, - "minConf": 4, - "name": "", - "txFee": "0.00100000" + { + "amount": "0.286", + "createTime": 1712825565285, + "id": "7614", + "price": "0.0286", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "LTCX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 126, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "6.35172307", + "createTime": 1712823140628, + "id": "7613", + "price": "0.0301", + "quantity": "211.0207", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MAID": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 127, - "isGeofenced": 0, - "minConf": 1, - "name": "", - "txFee": "80.00000000" + { + "amount": "25.91241584", + "createTime": 1712736925423, + "id": "7612", + "price": "0.0304", + "quantity": "852.3821", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MANA": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 306, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "22.00000000" + { + "amount": "4.8157291", + "createTime": 1712734928057, + "id": "7611", + "price": "0.0301", + "quantity": "159.991", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MAST": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 128, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "31.4540768", + "createTime": 1712683047958, + "id": "7610", + "price": "0.032", + "quantity": "982.9399", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MAX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 129, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "MCN": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "VdttvavdPJNGD4NzPQf8Hn4tWUGyy9mQ58ScwXxKbx9ve4Kp8xXZ1kD1KmXUMp5qtX8GmRgMk16aNVBhENEHNQAb3488Ha7Vv", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 130, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" + { + "amount": "15.0068896", + "createTime": 1712683047958, + "id": "7609", + "price": "0.032", + "quantity": "468.9653", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MEC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 131, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.2", + "createTime": 1712683047958, + "id": "7608", + "price": "0.032", + "quantity": "100", + "takerSide": "SELL", + "ts": 1719393673041 }, - "METH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 132, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.2", + "createTime": 1712683047958, + "id": "7607", + "price": "0.032", + "quantity": "100", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MIL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 133, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.5579648", + "createTime": 1712683047958, + "id": "7606", + "price": "0.032", + "quantity": "48.6864", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MIN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 134, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "2.2180352", + "createTime": 1712599039093, + "id": "7605", + "price": "0.032", + "quantity": "69.3136", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MINT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 135, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.10000000" + { + "amount": "3.2", + "createTime": 1712599031061, + "id": "7604", + "price": "0.032", + "quantity": "100", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MMC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 136, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.2", + "createTime": 1712599024256, + "id": "7603", + "price": "0.032", + "quantity": "100", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MMNXT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 137, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "2.8701184", + "createTime": 1712599014981, + "id": "7602", + "price": "0.032", + "quantity": "89.6912", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MMXIV": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 138, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00100000" + { + "amount": "0.3298816", + "createTime": 1712599014981, + "id": "7601", + "price": "0.032", + "quantity": "10.3088", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MNTA": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 139, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.44086661", + "createTime": 1712598882712, + "id": "7600", + "price": "0.0291", + "quantity": "152.6071", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MON": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 140, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "5.760468", + "createTime": 1712598882712, + "id": "7599", + "price": "0.03", + "quantity": "192.0156", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MRC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 141, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "11.1291488", + "createTime": 1712598882712, + "id": "7598", + "price": "0.031", + "quantity": "359.0048", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MRS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 142, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.438294", + "createTime": 1712482247138, + "id": "7597", + "price": "0.03", + "quantity": "114.6098", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MTS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 144, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.29170512", + "createTime": 1712469585634, + "id": "7596", + "price": "0.0301", + "quantity": "9.6912", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MUN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 145, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "96.68829457", + "createTime": 1712469585634, + "id": "7595", + "price": "0.0301", + "quantity": "3212.2357", + "takerSide": "BUY", + "ts": 1719393673041 }, - "MYR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 146, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.701238", + "createTime": 1712409400913, + "id": "7594", + "price": "0.03", + "quantity": "23.3746", + "takerSide": "SELL", + "ts": 1719393673041 }, - "MZC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 147, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "21.413115", + "createTime": 1712239833343, + "id": "7593", + "price": "0.0306", + "quantity": "699.775", + "takerSide": "SELL", + "ts": 1719393673041 }, - "N5X": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 148, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.4079849", + "createTime": 1712210808690, + "id": "7592", + "price": "0.033", + "quantity": "133.5753", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NAS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 149, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" + { + "amount": "11.1662307", + "createTime": 1712210808690, + "id": "7591", + "price": "0.0306", + "quantity": "364.9095", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NAUT": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 150, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "0.28114612", + "createTime": 1712049433973, + "id": "7590", + "price": "0.0281", + "quantity": "10.0052", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NAV": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 151, - "isGeofenced": 0, - "minConf": 480, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.59784452", + "createTime": 1712023647637, + "id": "7589", + "price": "0.0299", + "quantity": "19.9948", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NBT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 152, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "44.89482912", + "createTime": 1712023647637, + "id": "7588", + "price": "0.0296", + "quantity": "1516.7172", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NEOS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 153, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.00010000" + { + "amount": "52.27262235", + "createTime": 1712023647637, + "id": "7587", + "price": "0.0295", + "quantity": "1771.9533", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 154, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.99999797", + "createTime": 1712023636227, + "id": "7586", + "price": "0.0297", + "quantity": "168.3501", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NMC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 155, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.00009933", + "createTime": 1712018989685, + "id": "7585", + "price": "0.0301", + "quantity": "0.0033", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NMR": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 310, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.05000000" + { + "amount": "4.99989896", + "createTime": 1711989421851, + "id": "7584", + "price": "0.0301", + "quantity": "166.1096", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NOBL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 156, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "11.05675785", + "createTime": 1711988661182, + "id": "7583", + "price": "0.0303", + "quantity": "364.9095", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NOTE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 157, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "6.34238388", + "createTime": 1711988661182, + "id": "7582", + "price": "0.0303", + "quantity": "209.3196", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NOXT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 158, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "61.7923614", + "createTime": 1711896737577, + "id": "7581", + "price": "0.033", + "quantity": "1872.4958", + "takerSide": "BUY", + "ts": 1719393673041 }, - "NRS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 159, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "60.419568", + "createTime": 1711813102803, + "id": "7580", + "price": "0.0328", + "quantity": "1842.06", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NSR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 160, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "2.00000000" + { + "amount": "22.12976312", + "createTime": 1711801543247, + "id": "7579", + "price": "0.0328", + "quantity": "674.6879", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NTX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 161, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" + { + "amount": "49.99999214", + "createTime": 1711801511553, + "id": "7578", + "price": "0.0329", + "quantity": "1519.7566", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NXC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 288, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "10.00000000" + { + "amount": "118.3890015", + "createTime": 1711801511553, + "id": "7577", + "price": "0.033", + "quantity": "3587.5455", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NXT": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 162, - "isGeofenced": 0, - "minConf": 24, - "name": "", - "txFee": "1.00000000" + { + "amount": "7.07441462", + "createTime": 1711796647278, + "id": "7576", + "price": "0.0329", + "quantity": "215.0278", + "takerSide": "SELL", + "ts": 1719393673041 }, - "NXTI": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 163, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "6.03819136", + "createTime": 1711796617630, + "id": "7575", + "price": "0.0328", + "quantity": "184.0912", + "takerSide": "BUY", + "ts": 1719393673041 }, - "OMG": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 295, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.30000000" + { + "amount": "11.90518422", + "createTime": 1711796568764, + "id": "7573", + "price": "0.0326", + "quantity": "365.1897", + "takerSide": "BUY", + "ts": 1719393673041 }, - "OMNI": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 143, - "isGeofenced": 0, - "minConf": 1, - "name": "", - "txFee": "4.00000000" + { + "amount": "6.34951596", + "createTime": 1711632232665, + "id": "7572", + "price": "0.0327", + "quantity": "194.1748", + "takerSide": "BUY", + "ts": 1719393673041 }, - "OPAL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 164, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.321", + "createTime": 1711632232665, + "id": "7571", + "price": "0.0321", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "PAND": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 165, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "PASC": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "86646-64", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 289, - "isGeofenced": 0, - "minConf": 300, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.31096768", + "createTime": 1711600852551, + "id": "7570", + "price": "0.0304", + "quantity": "10.2292", + "takerSide": "SELL", + "ts": 1719393673041 }, - "PAWN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 166, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "181.27807938", + "createTime": 1711561134808, + "id": "7569", + "price": "0.0317", + "quantity": "5718.5514", + "takerSide": "BUY", + "ts": 1719393673041 }, - "PIGGY": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 167, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "125.7743832", + "createTime": 1711561134808, + "id": "7568", + "price": "0.0316", + "quantity": "3980.202", + "takerSide": "BUY", + "ts": 1719393673041 }, - "PINK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 168, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.43828509", + "createTime": 1711550404526, + "id": "7567", + "price": "0.0317", + "quantity": "297.7377", + "takerSide": "BUY", + "ts": 1719393673041 }, - "PLX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 169, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.317", + "createTime": 1711550404526, + "id": "7566", + "price": "0.0317", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "PMC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 170, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "8.76749072", + "createTime": 1711550168917, + "id": "7565", + "price": "0.0304", + "quantity": "288.4043", + "takerSide": "SELL", + "ts": 1719393673041 }, - "POLY": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 311, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.25000000" + { + "amount": "6.0000024", + "createTime": 1711550168917, + "id": "7564", + "price": "0.0304", + "quantity": "197.3685", + "takerSide": "SELL", + "ts": 1719393673041 }, - "POT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 171, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.5968059", + "createTime": 1711543026973, + "id": "7563", + "price": "0.033", + "quantity": "290.8123", + "takerSide": "SELL", + "ts": 1719393673041 }, - "PPC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 172, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "89.4031941", + "createTime": 1711531630408, + "id": "7562", + "price": "0.033", + "quantity": "2709.1877", + "takerSide": "SELL", + "ts": 1719393673041 }, - "PRC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 173, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "130.51304513", + "createTime": 1711531630408, + "id": "7561", + "price": "0.0331", + "quantity": "3942.9923", + "takerSide": "SELL", + "ts": 1719393673041 }, - "PRT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 174, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "PTS": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniexwallet", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 175, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "25.00000000" + { + "amount": "5.04344188", + "createTime": 1711525238346, + "id": "7560", + "price": "0.0332", + "quantity": "151.9109", + "takerSide": "BUY", + "ts": 1719393673041 }, - "Q2C": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 176, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.23164107", + "createTime": 1711522814783, + "id": "7559", + "price": "0.0331", + "quantity": "37.2097", + "takerSide": "SELL", + "ts": 1719393673041 }, - "QBK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 177, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "QCN": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "1VQpANF1pcKHPRAsZpeyG4jLDd1kbPn32YMeXkr9n8jNFvf8aaJdecB3FyAvo7X1DWJDQt3nii9eUTP5kJSfRpL5AwT72FM", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 178, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.9565578", + "createTime": 1711395562282, + "id": "7558", + "price": "0.033", + "quantity": "28.9866", + "takerSide": "BUY", + "ts": 1719393673041 }, - "QORA": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 179, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" + { + "amount": "1.00999692", + "createTime": 1711395547867, + "id": "7557", + "price": "0.0348", + "quantity": "29.0229", + "takerSide": "BUY", + "ts": 1719393673041 }, - "QTL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 180, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.05307651", + "createTime": 1711312489536, + "id": "7556", + "price": "0.0303", + "quantity": "1.7517", + "takerSide": "SELL", + "ts": 1719393673041 }, - "QTUM": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 304, - "isGeofenced": 0, - "minConf": 6, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.04832241", + "createTime": 1711129673903, + "id": "7555", + "price": "0.0303", + "quantity": "100.6047", + "takerSide": "SELL", + "ts": 1719393673041 }, - "RADS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 274, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.342", + "createTime": 1711039070389, + "id": "7554", + "price": "0.0342", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "RBY": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 181, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.45621498", + "createTime": 1710988373234, + "id": "7553", + "price": "0.0303", + "quantity": "15.0566", + "takerSide": "SELL", + "ts": 1719393673041 }, - "RDD": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 182, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "20.0784", + "createTime": 1710980155111, + "id": "7552", + "price": "0.0356", + "quantity": "564", + "takerSide": "BUY", + "ts": 1719393673041 }, - "REP": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 284, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.10000000" + { + "amount": "0.668", + "createTime": 1710980155111, + "id": "7551", + "price": "0.0334", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719393673041 }, - "RIC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 183, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.1846931", + "createTime": 1710956471015, + "id": "7550", + "price": "0.0318", + "quantity": "37.2545", + "takerSide": "BUY", + "ts": 1719393673041 }, - "RZR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 184, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "SBD": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniex", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 282, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "32.343998", + "createTime": 1710868857263, + "id": "7549", + "price": "0.0328", + "quantity": "986.0975", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 268, - "isGeofenced": 0, - "minConf": 6, - "name": "", - "txFee": "10.00000000" + { + "amount": "0.656", + "createTime": 1710868857263, + "id": "7548", + "price": "0.0328", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719393673041 + }, + { + "amount": "0.9999966", + "createTime": 1710865427466, + "id": "7547", + "price": "0.038", + "quantity": "26.3157", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SDC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 185, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.00714336", + "createTime": 1710865279901, + "id": "7546", + "price": "0.0336", + "quantity": "0.2126", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SHIBE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 186, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "13.2384", + "createTime": 1710865199682, + "id": "7545", + "price": "0.0336", + "quantity": "394", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SHOPX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 187, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "7.98668563", + "createTime": 1710865186865, + "id": "7544", + "price": "0.0497", + "quantity": "160.6979", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SILK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 188, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "23.70691116", + "createTime": 1710865180811, + "id": "7543", + "price": "0.0499", + "quantity": "475.0884", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SJCX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 189, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "3.00000000" + { + "amount": "57.25478595", + "createTime": 1710865173884, + "id": "7542", + "price": "0.0499", + "quantity": "1147.3905", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SLR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 190, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "49.99999539", + "createTime": 1710865173884, + "id": "7541", + "price": "0.0501", + "quantity": "998.0039", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SMC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 191, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "7.79999874", + "createTime": 1710865165216, + "id": "7540", + "price": "0.0499", + "quantity": "156.3126", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SNT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 300, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "200.00000000" + { + "amount": "14.57295945", + "createTime": 1710864912911, + "id": "7539", + "price": "0.0497", + "quantity": "293.2185", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SOC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 192, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "163.14344523", + "createTime": 1710864794882, + "id": "7538", + "price": "0.0387", + "quantity": "4215.5929", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SPA": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 193, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.378", + "createTime": 1710864770858, + "id": "7537", + "price": "0.0378", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SQL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 194, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.89999888", + "createTime": 1710864770858, + "id": "7536", + "price": "0.0378", + "quantity": "129.6296", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SRCC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 195, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "12.60508548", + "createTime": 1710864482177, + "id": "7535", + "price": "0.0377", + "quantity": "334.3524", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SRG": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 196, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "48.54175846", + "createTime": 1710864482177, + "id": "7534", + "price": "0.0377", + "quantity": "1287.5798", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SSD": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 197, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" - }, - "STEEM": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "poloniex", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 281, - "isGeofenced": 0, - "minConf": 50, - "name": "", - "txFee": "0.01000000" + { + "amount": "39.22086704", + "createTime": 1710849748569, + "id": "7533", + "price": "0.0304", + "quantity": "1290.1601", + "takerSide": "SELL", + "ts": 1719393673041 }, - "STORJ": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 297, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "1.00000000" - }, - "STR": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "GCF7F72LNF3ODSJIIWPJWEVWX33VT2SVZSUQ5NMDKDLK3N2NFCUAUHPT", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 198, - "isGeofenced": 0, - "minConf": 2, - "name": "", - "txFee": "0.00001000" + { + "amount": "49.7707056", + "createTime": 1710849630986, + "id": "7532", + "price": "0.0385", + "quantity": "1292.7456", + "takerSide": "BUY", + "ts": 1719393673041 }, - "STRAT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 287, - "isGeofenced": 0, - "minConf": 24, - "name": "", - "txFee": "0.01000000" + { + "amount": "149.98807328", + "createTime": 1710849573663, + "id": "7531", + "price": "0.0304", + "quantity": "4933.8182", + "takerSide": "BUY", + "ts": 1719393673041 }, - "SUM": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 199, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "11.28047632", + "createTime": 1710849390878, + "id": "7530", + "price": "0.0304", + "quantity": "371.0683", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SUN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 200, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "6.71952176", + "createTime": 1710849347235, + "id": "7529", + "price": "0.0304", + "quantity": "221.0369", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SWARM": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 201, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1000.00000000" + { + "amount": "11.10049968", + "createTime": 1710849238249, + "id": "7528", + "price": "0.0332", + "quantity": "334.3524", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SXC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 202, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.5145744", + "createTime": 1710849238248, + "id": "7527", + "price": "0.0354", + "quantity": "14.536", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SYNC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 203, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00010000" + { + "amount": "6.31123944", + "createTime": 1710838444003, + "id": "7526", + "price": "0.0354", + "quantity": "178.2836", + "takerSide": "SELL", + "ts": 1719393673041 }, - "SYS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 204, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "51.86745304", + "createTime": 1710838444003, + "id": "7525", + "price": "0.0386", + "quantity": "1343.7164", + "takerSide": "SELL", + "ts": 1719393673041 }, - "TAC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 205, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "52.8217454", + "createTime": 1710838124786, + "id": "7524", + "price": "0.0386", + "quantity": "1368.439", + "takerSide": "BUY", + "ts": 1719393673041 }, - "TOR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 206, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.2367552", + "createTime": 1710819382046, + "id": "7523", + "price": "0.0384", + "quantity": "6.1655", + "takerSide": "BUY", + "ts": 1719393673041 }, - "TRUST": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 207, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.013568", + "createTime": 1710819382046, + "id": "7522", + "price": "0.0384", + "quantity": "26.395", + "takerSide": "BUY", + "ts": 1719393673041 }, - "TWE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 208, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.17744843", + "createTime": 1710818034328, + "id": "7521", + "price": "0.0383", + "quantity": "82.9621", + "takerSide": "SELL", + "ts": 1719393673041 }, - "UIS": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 209, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "8.39686656", + "createTime": 1710818004682, + "id": "7520", + "price": "0.0384", + "quantity": "218.6684", + "takerSide": "SELL", + "ts": 1719393673041 }, - "ULTC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 210, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "53.0597337", + "createTime": 1710814748553, + "id": "7519", + "price": "0.0386", + "quantity": "1374.6045", + "takerSide": "SELL", + "ts": 1719393673041 }, - "UNITY": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 211, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "49.9999503", + "createTime": 1710814748553, + "id": "7518", + "price": "0.0386", + "quantity": "1295.3355", + "takerSide": "SELL", + "ts": 1719393673041 }, - "URO": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 212, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00100000" + { + "amount": "7.30644174", + "createTime": 1710794908191, + "id": "7517", + "price": "0.0598", + "quantity": "122.1813", + "takerSide": "BUY", + "ts": 1719393673041 }, - "USDC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 299, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "0.02000000" + { + "amount": "16.99999687", + "createTime": 1710794153771, + "id": "7516", + "price": "0.0499", + "quantity": "340.6813", + "takerSide": "BUY", + "ts": 1719393673041 }, - "USDE": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 213, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.94340615", + "createTime": 1710793680412, + "id": "7515", + "price": "0.0395", + "quantity": "23.8837", + "takerSide": "BUY", + "ts": 1719393673041 }, - "USDT": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 214, - "isGeofenced": 0, - "minConf": 2, - "name": "", - "txFee": "10.00000000" + { + "amount": "48.99999885", + "createTime": 1710787910443, + "id": "7514", + "price": "0.0395", + "quantity": "1240.5063", + "takerSide": "BUY", + "ts": 1719393673041 }, - "UTC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 215, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "40.35971996", + "createTime": 1710787904510, + "id": "7513", + "price": "0.0386", + "quantity": "1045.5886", + "takerSide": "BUY", + "ts": 1719393673041 }, - "UTIL": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 216, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.00000674", + "createTime": 1710787904510, + "id": "7512", + "price": "0.0337", + "quantity": "0.0002", + "takerSide": "BUY", + "ts": 1719393673041 }, - "UVC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 217, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.324", + "createTime": 1710787904510, + "id": "7511", + "price": "0.0324", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "VIA": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 218, - "isGeofenced": 0, - "minConf": 60, - "name": "", - "txFee": "0.01000000" + { + "amount": "3.9390245", + "createTime": 1710783194154, + "id": "7510", + "price": "0.0337", + "quantity": "116.885", + "takerSide": "BUY", + "ts": 1719393673040 }, - "VOOT": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 219, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "2.99999759", + "createTime": 1710783146084, + "id": "7509", + "price": "0.0337", + "quantity": "89.0207", + "takerSide": "SELL", + "ts": 1719393673040 }, - "VOX": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 276, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.4439925", + "createTime": 1710783146084, + "id": "7508", + "price": "0.035", + "quantity": "12.6855", + "takerSide": "SELL", + "ts": 1719393673040 }, - "VRC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 220, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "10.73636021", + "createTime": 1710783078035, + "id": "7507", + "price": "0.0361", + "quantity": "297.4061", + "takerSide": "SELL", + "ts": 1719393673040 }, - "VTC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 221, - "isGeofenced": 0, - "minConf": 600, - "name": "", - "txFee": "0.00100000" + { + "amount": "10.39468068", + "createTime": 1710783078035, + "id": "7506", + "price": "0.0372", + "quantity": "279.4269", + "takerSide": "SELL", + "ts": 1719393673040 }, - "WC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 222, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "11.12298814", + "createTime": 1710783032912, + "id": "7505", + "price": "0.0374", + "quantity": "297.4061", + "takerSide": "SELL", + "ts": 1719393673040 }, - "WDC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 223, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "6.42560625", + "createTime": 1710783032912, + "id": "7504", + "price": "0.0375", + "quantity": "171.3495", + "takerSide": "SELL", + "ts": 1719393673040 }, - "WIKI": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 224, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.10000000" + { + "amount": "8.86850712", + "createTime": 1710782593739, + "id": "7503", + "price": "0.0708", + "quantity": "125.2614", + "takerSide": "BUY", + "ts": 1719393673040 }, - "WOLF": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 225, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.02000000" + { + "amount": "1.79554464", + "createTime": 1710782593739, + "id": "7502", + "price": "0.0708", + "quantity": "25.3608", + "takerSide": "BUY", + "ts": 1719393673040 }, - "X13": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 226, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.6973025", + "createTime": 1710780306537, + "id": "7501", + "price": "0.0375", + "quantity": "125.2614", + "takerSide": "SELL", + "ts": 1719393673040 }, - "XAI": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 227, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.6651975", + "createTime": 1710780306537, + "id": "7500", + "price": "0.0375", + "quantity": "257.7386", + "takerSide": "SELL", + "ts": 1719393673040 }, - "XAP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 228, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "100.00000000" + { + "amount": "0.95547992", + "createTime": 1710779892561, + "id": "7499", + "price": "0.0376", + "quantity": "25.4117", + "takerSide": "SELL", + "ts": 1719393673040 }, - "XBC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 229, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.00010000" + { + "amount": "16.62849642", + "createTime": 1710779249074, + "id": "7498", + "price": "0.0797", + "quantity": "208.6386", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 230, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "5.89360452", + "createTime": 1710779214927, + "id": "7497", + "price": "0.0699", + "quantity": "84.3148", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XCH": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 231, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "4.00639539", + "createTime": 1710779078983, + "id": "7496", + "price": "0.0699", + "quantity": "57.3161", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XCN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 232, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.02000000" + { + "amount": "8.89999933", + "createTime": 1710779049778, + "id": "7495", + "price": "0.0499", + "quantity": "178.3567", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XCP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 233, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "16.00000000" + { + "amount": "5.42965284", + "createTime": 1710779010734, + "id": "7494", + "price": "0.0477", + "quantity": "113.8292", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XCR": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 234, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00017818" - }, - "XDN": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "ddddecTXF5B9PDwqZXP4Bs1FwttZbhF2YTRstruKctMoFJTE3VgD5uKd4RzmTHdzkv52wWWK2NYmfJeaiTuut2Pe2RVimGCvZ", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 235, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "1.00000000" + { + "amount": "6.84892124", + "createTime": 1710778893578, + "id": "7493", + "price": "0.0476", + "quantity": "143.8849", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XDP": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 236, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" - }, - "XEM": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "NBZMQO7ZPBYNBDUR7F75MAKA2S3DHDCIFG775N3D", - "disabled": 0, - "frozen": 0, - "humanType": "Payment ID", - "id": 256, - "isGeofenced": 0, - "minConf": 18, - "name": "", - "txFee": "15.00000000" + { + "amount": "21.881052", + "createTime": 1710778551895, + "id": "7492", + "price": "0.0397", + "quantity": "551.16", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XHC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 237, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "7.7487091", + "createTime": 1710777570493, + "id": "7491", + "price": "0.0365", + "quantity": "212.2934", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XLB": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 238, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.365", + "createTime": 1710777570493, + "id": "7490", + "price": "0.0365", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XMG": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 239, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "15.90309548", + "createTime": 1710720801362, + "id": "7489", + "price": "0.0382", + "quantity": "416.3114", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XMR": { - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 240, - "isGeofenced": 0, - "minConf": 8, - "name": "", - "txFee": "0.00010000" - }, - "XPB": { - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "PByFtxkMuoFRwrhXU19PBXLgHssTtcvTDSGzNf7Rvt5uKEf5PnRL4ccK4pWN4dpwvGhggGq12gH4bMqbxLyQGhkf3RLfzurMdK", - "disabled": 1, - "frozen": 0, - "humanType": "Payment ID", - "id": 241, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.10000000" + { + "amount": "2.96516422", + "createTime": 1710720801362, + "id": "7488", + "price": "0.0382", + "quantity": "77.6221", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XPM": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 242, - "isGeofenced": 0, - "minConf": 2880, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.377", + "createTime": 1710720801362, + "id": "7487", + "price": "0.0377", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XRP": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 243, - "isGeofenced": 0, - "minConf": 12, - "name": "", - "txFee": "0.15000000" + { + "amount": "5.67625696", + "createTime": 1710700805559, + "id": "7486", + "price": "0.0352", + "quantity": "161.2573", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XSI": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 244, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "29.64018816", + "createTime": 1710700775690, + "id": "7485", + "price": "0.0352", + "quantity": "842.0508", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XST": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 245, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "27.26385831", + "createTime": 1710700775690, + "id": "7484", + "price": "0.0351", + "quantity": "776.7481", + "takerSide": "BUY", + "ts": 1719393673040 }, - "XSV": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 246, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "2.72999727", + "createTime": 1710700680979, + "id": "7483", + "price": "0.0351", + "quantity": "77.7777", + "takerSide": "SELL", + "ts": 1719393673040 }, - "XUSD": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 247, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00000000" + { + "amount": "14.68355328", + "createTime": 1710700678758, + "id": "7482", + "price": "0.0352", + "quantity": "417.1464", + "takerSide": "SELL", + "ts": 1719393673040 }, - "XVC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 253, - "isGeofenced": 0, - "minConf": 1000000, - "name": "", - "txFee": "0.01000000" + { + "amount": "1.5560055", + "createTime": 1710517186787, + "id": "7481", + "price": "0.035", + "quantity": "44.4573", + "takerSide": "SELL", + "ts": 1719393673040 }, - "XXC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 248, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "9.8999985", + "createTime": 1710517186787, + "id": "7480", + "price": "0.035", + "quantity": "282.8571", + "takerSide": "SELL", + "ts": 1719393673040 }, - "YACC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 249, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.00000302", + "createTime": 1710517186787, + "id": "7479", + "price": "0.0351", + "quantity": "113.9602", + "takerSide": "SELL", + "ts": 1719393673040 }, - "YANG": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 250, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "6.00000033", + "createTime": 1710447754777, + "id": "7478", + "price": "0.0417", + "quantity": "143.8849", + "takerSide": "SELL", + "ts": 1719393673040 }, - "YC": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 251, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "0.46812976", + "createTime": 1710434780823, + "id": "7477", + "price": "0.0496", + "quantity": "9.4381", + "takerSide": "BUY", + "ts": 1719393673040 }, - "YIN": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 252, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.01000000" + { + "amount": "4.53186768", + "createTime": 1710434780823, + "id": "7476", + "price": "0.0496", + "quantity": "91.3683", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ZEC": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "BTC Clone", - "id": 286, - "isGeofenced": 0, - "minConf": 8, - "name": "", - "txFee": "0.00100000" + { + "amount": "6.204226", + "createTime": 1710367912371, + "id": "7475", + "price": "0.035", + "quantity": "177.2636", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ZRX": { - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "humanType": "Sweep to Main Account", - "id": 293, - "isGeofenced": 0, - "minConf": 30, - "name": "", - "txFee": "5.00000000" + { + "amount": "1.404396", + "createTime": 1710358289123, + "id": "7474", + "price": "0.035", + "quantity": "40.1256", + "takerSide": "SELL", + "ts": 1719393673040 }, - "eTOK": { - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "humanType": "BTC Clone", - "id": 72, - "isGeofenced": 0, - "minConf": 10000, - "name": "", - "txFee": "0.00100000" - } - }, - "queryString": "command=returnCurrencies", - "bodyParams": "", - "headers": {} - }, - { - "data": { - "error": "Invalid currency pair." - }, - "queryString": "command=returnChartData\u0026currencyPair=BTC_LTCC\u0026end=1588745003\u0026period=300\u0026start=1588741200", - "bodyParams": "", - "headers": {} - }, - { - "data": [ { - "close": "0.005187", - "date": "1588741200000", - "high": "0.005187", - "low": "0.005187", - "open": "0.005187", - "quoteVolume": "0.134607560000000000", - "volume": "25.950919030000000000", - "weightedAverage": "0.005187000000000000" - }, - { - "close": "0.005184", - "date": "1588741500000", - "high": "0.005188", - "low": "0.005184", - "open": "0.005188", - "quoteVolume": "0.337237360000000000", - "volume": "65.001093740000000000", - "weightedAverage": "0.005188170000000000" - }, - { - "close": "0.005183", - "date": "1588741800000", - "high": "0.005184", - "low": "0.005183", - "open": "0.005184", - "quoteVolume": "0.002260250000000000", - "volume": "0.436015290000000000", - "weightedAverage": "0.005183900000000000" - }, - { - "close": "0.005182", - "date": "1588742100000", - "high": "0.005186", - "low": "0.005182", - "open": "0.005184", - "quoteVolume": "0.469723220000000000", - "volume": "90.599185630000000000", - "weightedAverage": "0.005184620000000000" - }, - { - "close": "0.005183", - "date": "1588742400000", - "high": "0.005184", - "low": "0.005179", - "open": "0.005179", - "quoteVolume": "0.044659030000000000", - "volume": "8.615234300000000000", - "weightedAverage": "0.005183720000000000" - }, - { - "close": "0.005192", - "date": "1588742700000", - "high": "0.005192", - "low": "0.005185", - "open": "0.005185", - "quoteVolume": "0.422175130000000000", - "volume": "81.373653530000000000", - "weightedAverage": "0.005188100000000000" - }, - { - "close": "0.005191", - "date": "1588743000000", - "high": "0.005195", - "low": "0.005191", - "open": "0.005195", - "quoteVolume": "0.005716300000000000", - "volume": "1.100213750000000000", - "weightedAverage": "0.005195620000000000" - }, - { - "close": "0.005189", - "date": "1588743300000", - "high": "0.005189", - "low": "0.005189", - "open": "0.005189", - "quoteVolume": "0.000004500000000000", - "volume": "0.000869040000000000", - "weightedAverage": "0.005189610000000000" - }, - { - "close": "0.005193", - "date": "1588743600000", - "high": "0.005193", - "low": "0.005189", - "open": "0.005189", - "quoteVolume": "0.000176300000000000", - "volume": "0.033959030000000000", - "weightedAverage": "0.005191810000000000" - }, - { - "close": "0.005190", - "date": "1588743900000", - "high": "0.005195", - "low": "0.005190", - "open": "0.005191", - "quoteVolume": "1.086315280000000000", - "volume": "209.147005290000000000", - "weightedAverage": "0.005194020000000000" - }, - { - "close": "0.005185", - "date": "1588744200000", - "high": "0.005191", - "low": "0.005185", - "open": "0.005191", - "quoteVolume": "0.913031310000000000", - "volume": "176.013137310000000000", - "weightedAverage": "0.005187290000000000" - }, - { - "close": "0.005185", - "date": "1588744500000", - "high": "0.005187", - "low": "0.005185", - "open": "0.005187", - "quoteVolume": "0.503999660000000000", - "volume": "97.167286900000000000", - "weightedAverage": "0.005186920000000000" - }, - { - "close": "0.005188", - "date": "1588744800000", - "high": "0.005191", - "low": "0.005186", - "open": "0.005188", - "quoteVolume": "0.389033940000000000", - "volume": "74.957421780000000000", - "weightedAverage": "0.005190060000000000" - } - ], - "queryString": "command=returnChartData\u0026currencyPair=BTC_LTC\u0026end=1588745003\u0026period=300\u0026start=1588741200", - "bodyParams": "", - "headers": {} - }, - { - "data": [ + "amount": "2.2913765", + "createTime": 1710358281502, + "id": "7473", + "price": "0.035", + "quantity": "65.4679", + "takerSide": "SELL", + "ts": 1719393673040 + }, { - "close": "0.005192", - "date": "1588741200000", - "high": "0.005192", - "low": "0.005179", - "open": "0.005187", - "quoteVolume": "1.410662590000000000", - "volume": "271.976101520000000000", - "weightedAverage": "0.005186710000000000" - }, - { - "close": "0.005185", - "date": "1588743000000", - "high": "0.005195", - "low": "0.005185", - "open": "0.005195", - "quoteVolume": "2.509243380000000000", - "volume": "483.462471320000000000", - "weightedAverage": "0.005190150000000000" - }, - { - "close": "0.005190", - "date": "1588744800000", - "high": "0.005192", - "low": "0.005185", - "open": "0.005188", - "quoteVolume": "1.503792520000000000", - "volume": "289.807027890000000000", - "weightedAverage": "0.005188940000000000" - } - ], - "queryString": "command=returnChartData\u0026currencyPair=BTC_LTC\u0026end=1588745003\u0026period=1800\u0026start=1588741200", - "bodyParams": "", - "headers": {} - }, - { - "data": [ + "amount": "3.79896714", + "createTime": 1710358229837, + "id": "7472", + "price": "0.0478", + "quantity": "79.4763", + "takerSide": "SELL", + "ts": 1719393673040 + }, { - "amount": "3.21720471", - "date": "2020-06-06 00:59:21", - "globalTradeID": "469013857", - "orderNumber": 475804187646, - "rate": "0.00702980", - "total": "0.02261630", - "tradeID": "20409261", - "type": "sell" - }, - { - "amount": "0.00002285", - "date": "2020-06-06 00:00:43", - "globalTradeID": "469004013", - "orderNumber": 475797933906, - "rate": "0.00700206", - "total": "0.00000015", - "tradeID": "20409224", - "type": "sell" - } - ], - "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR\u0026end=1591405200\u0026start=1591401600", - "bodyParams": "", - "headers": {} - }, - { - "data": [ + "amount": "0.86014188", + "createTime": 1710358229837, + "id": "7471", + "price": "0.0478", + "quantity": "17.9946", + "takerSide": "SELL", + "ts": 1719393673040 + }, { - "amount": "3.21720471", - "date": "2020-06-06 00:59:21", - "globalTradeID": "469013857", - "orderNumber": 475804187646, - "rate": "0.00702980", - "total": "0.02261630", - "tradeID": "20409261", - "type": "sell" - }, - { - "amount": "0.00002285", - "date": "2020-06-06 00:00:43", - "globalTradeID": "469004013", - "orderNumber": 475797933906, - "rate": "0.00700206", - "total": "0.00000015", - "tradeID": "20409224", - "type": "sell" - } - ], - "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR\u0026end=1591405200\u0026start=1591401643", - "bodyParams": "", - "headers": {} - }, - { - "data": [ + "amount": "0.56757242", + "createTime": 1710357600513, + "id": "7470", + "price": "0.0478", + "quantity": "11.8739", + "takerSide": "SELL", + "ts": 1719393673040 + }, { - "close": "0.005187", - "date": "1588741200000", - "high": "0.005187", - "low": "0.005187", - "open": "0.005187", - "quoteVolume": "0.134607560000000000", - "volume": "25.950919030000000000", - "weightedAverage": "0.005187000000000000" - }, - { - "close": "0.005184", - "date": "1588741500000", - "high": "0.005188", - "low": "0.005184", - "open": "0.005188", - "quoteVolume": "0.337237360000000000", - "volume": "65.001093740000000000", - "weightedAverage": "0.005188170000000000" - }, - { - "close": "0.005183", - "date": "1588741800000", - "high": "0.005184", - "low": "0.005183", - "open": "0.005184", - "quoteVolume": "0.002260250000000000", - "volume": "0.436015290000000000", - "weightedAverage": "0.005183900000000000" - }, - { - "close": "0.005182", - "date": "1588742100000", - "high": "0.005186", - "low": "0.005182", - "open": "0.005184", - "quoteVolume": "0.469723220000000000", - "volume": "90.599185630000000000", - "weightedAverage": "0.005184620000000000" - }, - { - "close": "0.005183", - "date": "1588742400000", - "high": "0.005184", - "low": "0.005179", - "open": "0.005179", - "quoteVolume": "0.044659030000000000", - "volume": "8.615234300000000000", - "weightedAverage": "0.005183720000000000" - } - ], - "queryString": "command=returnChartData\u0026currencyPair=BTC_LTC\u0026end=1588745100\u0026period=300\u0026start=1588741200", - "bodyParams": "", - "headers": {} - }, - { - "data": { - "demands": [ - { - "amount": "0.07730000", - "rangeMax": 2, - "rangeMin": 2, - "rate": "0.00000100" - } - ], - "offers": [ - { - "amount": "0.01106802", - "rangeMax": 2, - "rangeMin": 2, - "rate": "0.00001000" - }, - { - "amount": "0.01421371", - "rangeMax": 2, - "rangeMin": 2, - "rate": "0.00005000" - }, - { - "amount": "0.01194792", - "rangeMax": 2, - "rangeMin": 2, - "rate": "0.00051121" - }, - { - "amount": "0.20407105", - "rangeMax": 10, - "rangeMin": 10, - "rate": "0.00051180" - }, - { - "amount": "1.39196698", - "rangeMax": 2, - "rangeMin": 2, - "rate": "0.00051200" - } - ] - }, - "queryString": "command=returnLoanOrders\u0026currency=BTC", - "bodyParams": "", - "headers": {} - }, - { - "data": [ + "amount": "1.69385056", + "createTime": 1710342077215, + "id": "7469", + "price": "0.0698", + "quantity": "24.2672", + "takerSide": "BUY", + "ts": 1719393673040 + }, { - "amount": "1.01999999", - "date": "2020-09-14 04:24:31", - "globalTradeID": "487261525", - "orderNumber": "494135055429", - "rate": "0.00822633", - "total": "0.00839085", - "tradeID": "20587658", - "type": "sell" - }, - { - "amount": "1.19452554", - "date": "2020-09-14 02:23:48", - "globalTradeID": "487248328", - "orderNumber": 494120664834, - "rate": "0.00822000", - "total": "0.00981899", - "tradeID": "20587459", - "type": "buy" - } - ], - "queryString": "command=returnTradeHistory\u0026currencyPair=BTC_XMR", - "bodyParams": "", - "headers": {} - }, - { - "data": { - "1CR": { - "blockchain": "1CR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 1, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + "amount": "0.41144308", + "createTime": 1710342077215, + "id": "7468", + "price": "0.0698", + "quantity": "5.8946", + "takerSide": "BUY", + "ts": 1719393673040 }, - "AAVE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "8179a9", - "humanType": "Sweep to Main Account", - "id": 446, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.21564059" - }, - "ABY": { - "blockchain": "ABY", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 2, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "AC": { - "blockchain": "AC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 3, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "ACH": { - "blockchain": "ACH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 4, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" + { + "amount": "10.33102356", + "createTime": 1710340196109, + "id": "7467", + "price": "0.0478", + "quantity": "216.1302", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ACH1": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "01033E", - "humanType": "Sweep to Main Account", - "id": 560, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "173.83602719" + { + "amount": "41.18814356", + "createTime": 1710337563580, + "id": "7466", + "price": "0.0482", + "quantity": "854.5258", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ADABEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 488, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1230972137.50000000" + { + "amount": "3.32350606", + "createTime": 1710337283959, + "id": "7465", + "price": "0.0698", + "quantity": "47.6147", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ADABULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 489, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00382974" + { + "amount": "8.94211752", + "createTime": 1710337283959, + "id": "7464", + "price": "0.0696", + "quantity": "128.4787", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ADD": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3ca6f4", - "humanType": "Sweep to Main Account", - "id": 503, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "130.74635607" + { + "amount": "47.3334756", + "createTime": 1710337283959, + "id": "7463", + "price": "0.069", + "quantity": "685.9924", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ADEL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3d30d6", - "humanType": "Sweep to Main Account", - "id": 430, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "418.19144667" - }, - "ADN": { - "blockchain": "ADN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 5, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "AEON": { - "blockchain": "AEON", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "WmrzAb4yy6i4otzaTZznsmaeBn8UKoBqS14XdW2DDzXr3DQnwz4o1XPJAJuo7QTqSoD9WVrdEQfn15udzhsJWmNR1jAEETQ2N", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 6, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "AERO": { - "blockchain": "AERO", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 7, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "AIR": { - "blockchain": "AIR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 8, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "13.6008145", + "createTime": 1710337260185, + "id": "7462", + "price": "0.065", + "quantity": "209.2433", + "takerSide": "BUY", + "ts": 1719393673040 }, - "AKITA": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F8A628", - "humanType": "Sweep to Main Account", - "id": 510, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "16232599.61538462" + { + "amount": "17.89999905", + "createTime": 1710337260185, + "id": "7461", + "price": "0.0647", + "quantity": "276.6615", + "takerSide": "BUY", + "ts": 1719393673040 }, - "AKRO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "c764fd", - "humanType": "Sweep to Main Account", - "id": 429, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "850.05919505" + { + "amount": "8.89999591", + "createTime": 1710337260185, + "id": "7460", + "price": "0.0599", + "quantity": "148.5809", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ALICE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EA8397", - "humanType": "Sweep to Main Account", - "id": 565, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.97960252" - }, - "ALPACA": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "64C385", - "humanType": "Sweep to Main Account", - "id": 556, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "2.08000000" + { + "amount": "0.00000458", + "createTime": 1710337004625, + "id": "7459", + "price": "0.0458", + "quantity": "0.0001", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ALPHA": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "57B3F9", - "humanType": "Sweep to Main Account", - "id": 463, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "18.25722519" + { + "amount": "0.00000916", + "createTime": 1710335889135, + "id": "7458", + "price": "0.0458", + "quantity": "0.0002", + "takerSide": "BUY", + "ts": 1719393673040 }, - "AMP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "C53F79", - "humanType": "Sweep to Main Account", - "id": 275, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "886.44951612" - }, - "APH": { - "blockchain": "APH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 9, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.435", + "createTime": 1710335889135, + "id": "7457", + "price": "0.0435", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "API3": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "BDBDBD", - "humanType": "Sweep to Main Account", - "id": 464, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.58250285" - }, - "ARCH": { - "blockchain": "ARCH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 258, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "ARDR": { - "blockchain": "ARDR", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3A86C7", - "humanType": "Sweep to Main Account", - "id": 285, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 20, - "name": "", - "parentChain": null, - "txFee": "2.00000000" - }, - "ATOM": { - "blockchain": "ATOM", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "707390", - "humanType": "Sweep to Main Account", - "id": 313, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.35000000" + { + "amount": "50.00002028", + "createTime": 1710335889135, + "id": "7456", + "price": "0.0434", + "quantity": "1152.0742", + "takerSide": "BUY", + "ts": 1719393673040 }, - "AUDIO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5C0EBA", - "humanType": "Sweep to Main Account", - "id": 567, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "12.32480950" - }, - "AUR": { - "blockchain": "AUR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 10, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "AUTO": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3A41BA", - "humanType": "Sweep to Main Account", - "id": 548, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "0.00200000" - }, - "AVA": { - "blockchain": "BNB", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1E2E5E", - "humanType": "Sweep to Main Account", - "id": 344, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.09666653" - }, - "AXIS": { - "blockchain": "AXIS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 11, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "6.89998526", + "createTime": 1710334041975, + "id": "7455", + "price": "0.0458", + "quantity": "150.6547", + "takerSide": "BUY", + "ts": 1719393673040 }, - "AXS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "0051DD", - "humanType": "Sweep to Main Account", - "id": 553, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.28008359" + { + "amount": "0.4828152", + "createTime": 1710278606909, + "id": "7454", + "price": "0.0406", + "quantity": "11.892", + "takerSide": "SELL", + "ts": 1719393673040 }, - "B20": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "262725", - "humanType": "Sweep to Main Account", - "id": 506, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "15.24378214" - }, - "BABYDOGE": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E9AC5A", - "humanType": "Sweep to Main Account", - "id": 555, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "1000000000.00000000" + { + "amount": "13.89327467", + "createTime": 1710277369749, + "id": "7453", + "price": "0.0407", + "quantity": "341.3581", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BAC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5855AF", - "humanType": "Sweep to Main Account", - "id": 477, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "311.74014706" + { + "amount": "33.09011343", + "createTime": 1710277359749, + "id": "7452", + "price": "0.0407", + "quantity": "813.0249", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BADGER": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E8A847", - "humanType": "Sweep to Main Account", - "id": 468, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2.15734027" + { + "amount": "7.98056815", + "createTime": 1710277359749, + "id": "7451", + "price": "0.0457", + "quantity": "174.6295", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BAL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "919191", - "humanType": "Sweep to Main Account", - "id": 369, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.69292827" - }, - "BALLS": { - "blockchain": "BALLS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 12, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "6.40000000" + { + "amount": "4.73429607", + "createTime": 1710277248050, + "id": "7450", + "price": "0.0457", + "quantity": "103.5951", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BAND": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "556DF6", - "humanType": "Sweep to Main Account", - "id": 390, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.60815861" - }, - "BANK": { - "blockchain": "BANK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 13, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "5.44843626", + "createTime": 1710277248050, + "id": "7449", + "price": "0.0457", + "quantity": "119.2218", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BAS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "E28F7C", - "humanType": "Sweep to Main Account", - "id": 476, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.30000000" + { + "amount": "1.03869612", + "createTime": 1710160450266, + "id": "7448", + "price": "0.0462", + "quantity": "22.4826", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BAT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "9E1F63", - "humanType": "Sweep to Main Account", - "id": 302, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "23.95365871" - }, - "BBL": { - "blockchain": "BBL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 14, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BBR": { - "blockchain": "BBR", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "1D9hJ1nEjwuhxZMk6fupoTjKLtS2KzkfCQ7kF25k5B6Sc4UJjt9FrvDNYomVd4ZVHv36FskVRJGZa1JZAnZ35GiuAHf7gBy", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 15, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00500000" - }, - "BCC": { - "blockchain": "BCC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 16, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BCH": { - "blockchain": "BCH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "32C939", - "humanType": "BTC Clone", - "id": 292, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 11, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - }, - "BCHA": { - "blockchain": "BCHA", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "32C939", - "humanType": "BTC Clone", - "id": 447, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 99999999, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - }, - "BCHABC": { - "blockchain": "BCHABC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "32C939", - "humanType": "BTC Clone", - "id": 308, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 11, - "name": "", - "parentChain": null, - "txFee": "0.00100000" + { + "amount": "4.7969772", + "createTime": 1710108855145, + "id": "7447", + "price": "0.0465", + "quantity": "103.1608", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BCHBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 339, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "133895.91967151" + { + "amount": "0.43", + "createTime": 1710108855145, + "id": "7446", + "price": "0.043", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BCHBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 340, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "351.37768647" + { + "amount": "3.22896288", + "createTime": 1710108855145, + "id": "7445", + "price": "0.0429", + "quantity": "75.2672", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BCHC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B72B2D", - "humanType": "Sweep to Main Account", - "id": 360, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2637.79743750" - }, - "BCHSV": { - "blockchain": "BCHSV", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "C8102E", - "humanType": "BTC Clone", - "id": 309, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1008, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - }, - "BCN": { - "blockchain": "BCN", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "25cZNQYVAi3issDCoa6fWA2Aogd4FgPhYdpX3p8KLfhKC6sN8s6Q9WpcW4778TPwcUS5jEM25JrQvjD3XjsvXuNHSWhYUsu", - "disabled": 0, - "frozen": 0, - "hexColor": "F04086", - "humanType": "Payment ID", - "id": 17, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "BCY": { - "blockchain": "BCY", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 269, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "4.00000000" - }, - "BDC": { - "blockchain": "BDC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 18, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BDG": { - "blockchain": "BDG", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 19, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "2.95799985", + "createTime": 1710098905559, + "id": "7444", + "price": "0.0351", + "quantity": "84.2735", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BDP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2596be", - "humanType": "Sweep to Main Account", - "id": 502, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "99.79892784" + { + "amount": "3.0329112", + "createTime": 1710098830815, + "id": "7443", + "price": "0.044", + "quantity": "68.9298", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 322, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "96843.06014476" - }, - "BELA": { - "blockchain": "BELA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 20, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "6.0643484", + "createTime": 1710074627625, + "id": "7442", + "price": "0.044", + "quantity": "137.8261", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BID": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5BC3EC", - "humanType": "Sweep to Main Account", - "id": 449, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1164.97237505" - }, - "BITCNY": { - "blockchain": "BITCNY", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniexwallet", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 273, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "BITS": { - "blockchain": "BITS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 21, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BITUSD": { - "blockchain": "BITUSD", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniexwallet", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 272, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.15000000" - }, - "BLK": { - "blockchain": "BLK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 22, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BLOCK": { - "blockchain": "BLOCK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 23, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 100000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BLU": { - "blockchain": "BLU", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 24, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.0000036", + "createTime": 1710074627625, + "id": "7441", + "price": "0.044", + "quantity": "68.1819", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BLY": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "50B2AB", - "humanType": "Sweep to Main Account", - "id": 406, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "584.91363241" + { + "amount": "3.0000033", + "createTime": 1710074114529, + "id": "7440", + "price": "0.0465", + "quantity": "64.5162", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BNB": { - "blockchain": "BNB", - "childChains": [ - "BSC" - ], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F0B90B", - "humanType": "Sweep to Main Account", - "id": 343, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.05000000" - }, - "BNS": { - "blockchain": "BNS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 25, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.20302314", + "createTime": 1710064544377, + "id": "7439", + "price": "0.0499", + "quantity": "4.0686", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BNT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "102644", - "humanType": "Sweep to Main Account", - "id": 305, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.75229433" + { + "amount": "1.023372", + "createTime": 1710064544377, + "id": "7438", + "price": "0.0496", + "quantity": "20.6325", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BOND": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EC5443", - "humanType": "Sweep to Main Account", - "id": 481, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.74069426" - }, - "BONES": { - "blockchain": "BONES", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 26, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BOST": { - "blockchain": "BOST", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 27, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.6394", + "createTime": 1710064467055, + "id": "7437", + "price": "0.0496", + "quantity": "73.375", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BREE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "6CAECD", - "humanType": "Sweep to Main Account", - "id": 441, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2.33100000" - }, - "BRG": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "EDBB47", - "humanType": "Sweep to Main Account", - "id": 500, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "BSC": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "f8d12f", - "humanType": "Sweep to Main Account", - "id": 538, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 15, - "name": "", - "parentChain": "BNB", - "txFee": "0.00050000" + { + "amount": "5.83626336", + "createTime": 1710060958943, + "id": "7436", + "price": "0.0496", + "quantity": "117.6666", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BSVBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 341, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "668824.85058408" + { + "amount": "3.27753328", + "createTime": 1710060958943, + "id": "7435", + "price": "0.0496", + "quantity": "66.0793", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BSVBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 342, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "173181.22362127" + { + "amount": "9.6099996", + "createTime": 1710059933452, + "id": "7434", + "price": "0.0454", + "quantity": "211.674", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BTC": { - "blockchain": "BTC", - "childChains": [ - "BTCTRON" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F59C3D", - "humanType": "BTC Clone", - "id": 28, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 2, - "name": "", - "parentChain": null, - "txFee": "0.00050000" - }, - "BTCD": { - "blockchain": "BTCD", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 29, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BTCS": { - "blockchain": "BTCS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 30, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BTCST": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 505, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "BTCTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F59C3D", - "humanType": "Sweep to Main Account", - "id": 445, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "BTC", - "txFee": "0.00000000" - }, - "BTM": { - "blockchain": "BTM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 31, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BTS": { - "blockchain": "BTS", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "poloniexwallet", - "disabled": 0, - "frozen": 0, - "hexColor": "00A9E0", - "humanType": "Payment ID", - "id": 32, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 50, - "name": "", - "parentChain": null, - "txFee": "5.00000000" + { + "amount": "3.00000022", + "createTime": 1710059933452, + "id": "7433", + "price": "0.0454", + "quantity": "66.0793", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BTT": { - "blockchain": "TRX", - "childChains": [ - "BTTETH" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "603893", - "humanType": "Sweep to Main Account", - "id": 320, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "250.00000000" + { + "amount": "9.89999533", + "createTime": 1710042622049, + "id": "7432", + "price": "0.0499", + "quantity": "198.3967", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BTTETH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3D3E44", - "humanType": "Sweep to Main Account", - "id": 535, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": "BTT", - "txFee": "4620.00000000" + { + "amount": "3.53267754", + "createTime": 1710042622049, + "id": "7431", + "price": "0.0498", + "quantity": "70.9373", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 323, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00202970" - }, - "BURGER": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EEBA5A", - "humanType": "Sweep to Main Account", - "id": 547, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "0.50000000" - }, - "BURN": { - "blockchain": "BURN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 33, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "BURST": { - "blockchain": "BURST", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "262626", - "humanType": "Sweep to Main Account", - "id": 34, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" + { + "amount": "2.99230623", + "createTime": 1710006102600, + "id": "7430", + "price": "0.0423", + "quantity": "70.7401", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BUSD": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E8B941", - "humanType": "Sweep to Main Account", - "id": 324, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "24.61944275" + { + "amount": "9.56899735", + "createTime": 1710006102600, + "id": "7429", + "price": "0.0431", + "quantity": "222.0185", + "takerSide": "SELL", + "ts": 1719393673040 }, - "BVOL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 346, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.03056392" + { + "amount": "0.431", + "createTime": 1710005747101, + "id": "7428", + "price": "0.0431", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "BZRX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "0C41D1", - "humanType": "Sweep to Main Account", - "id": 372, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "124.76536112" - }, - "C2": { - "blockchain": "C2", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 35, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "C98": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "D4B460", - "humanType": "Sweep to Main Account", - "id": 557, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "2.53000000" - }, - "CACH": { - "blockchain": "CACH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 36, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CAI": { - "blockchain": "CAI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 37, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CAKE": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5fc4d3", - "humanType": "Sweep to Main Account", - "id": 544, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "0.03800000" - }, - "CC": { - "blockchain": "CC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 38, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CCN": { - "blockchain": "CCN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 39, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CGA": { - "blockchain": "CGA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 40, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - }, - "CHA": { - "blockchain": "CHA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 41, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.16877554", + "createTime": 1709999799102, + "id": "7427", + "price": "0.0413", + "quantity": "76.7258", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CHR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F4B4C3", - "humanType": "Sweep to Main Account", - "id": 358, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "50.88006192" - }, - "CINNI": { - "blockchain": "CINNI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 42, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CLAM": { - "blockchain": "CLAM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "1A9193", - "humanType": "BTC Clone", - "id": 43, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 6, - "name": "", - "parentChain": null, - "txFee": "0.00100000" + { + "amount": "11.24096834", + "createTime": 1709999799102, + "id": "7426", + "price": "0.0401", + "quantity": "280.3234", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CLV": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "53AA81", - "humanType": "Sweep to Main Account", - "id": 561, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "13.92379961" - }, - "CNL": { - "blockchain": "CNL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 44, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CNMT": { - "blockchain": "CNMT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 45, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "CNOTE": { - "blockchain": "CNOTE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 46, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "10.39999814", + "createTime": 1709998709603, + "id": "7425", + "price": "0.0371", + "quantity": "280.3234", + "takerSide": "SELL", + "ts": 1719393673040 }, - "COMBO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B0B0B0", - "humanType": "Sweep to Main Account", - "id": 483, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "31.49614851" - }, - "COMM": { - "blockchain": "COMM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 47, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "9.83600835", + "createTime": 1709987722977, + "id": "7424", + "price": "0.0399", + "quantity": "246.5165", + "takerSide": "BUY", + "ts": 1719393673040 }, - "COMP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5FCF99", - "humanType": "Sweep to Main Account", - "id": 361, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.07483315" - }, - "CON": { - "blockchain": "CON", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 48, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "CORG": { - "blockchain": "CORG", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 49, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "CORN": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F7DD14", - "humanType": "Sweep to Main Account", - "id": 424, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.03468000" + { + "amount": "8.88403824", + "createTime": 1709987722976, + "id": "7423", + "price": "0.0399", + "quantity": "222.6576", + "takerSide": "BUY", + "ts": 1719393673040 }, - "COVER": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "BDBDBD", - "humanType": "Sweep to Main Account", - "id": 465, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.02760000" + { + "amount": "1.01596173", + "createTime": 1709964057732, + "id": "7422", + "price": "0.0399", + "quantity": "25.4627", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CREAM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "69e2db", - "humanType": "Sweep to Main Account", - "id": 427, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.11527827" - }, - "CRT": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "ff790a", - "humanType": "Sweep to Main Account", - "id": 422, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.17880000" + { + "amount": "2.999997", + "createTime": 1709925924658, + "id": "7421", + "price": "0.039", + "quantity": "76.923", + "takerSide": "SELL", + "ts": 1719393673040 }, - "CRV": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B2FB76", - "humanType": "Sweep to Main Account", - "id": 401, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "8.83143748" - }, - "CRYPT": { - "blockchain": "CRYPT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 50, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "9.6141474", + "createTime": 1709925924658, + "id": "7420", + "price": "0.039", + "quantity": "246.5166", + "takerSide": "SELL", + "ts": 1719393673040 }, - "CTSI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 530, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "27.33085826" + { + "amount": "9.58651854", + "createTime": 1709909493230, + "id": "7419", + "price": "0.0398", + "quantity": "240.8673", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CUDOS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "70B5F2", - "humanType": "Sweep to Main Account", - "id": 480, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "529.14692828" - }, - "CURE": { - "blockchain": "CURE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 51, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.18645698", + "createTime": 1709909493230, + "id": "7418", + "price": "0.0397", + "quantity": "80.2634", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CUSDT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5FCF99", - "humanType": "Sweep to Main Account", - "id": 364, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "3460.94971809" + { + "amount": "4.88915728", + "createTime": 1709908612932, + "id": "7417", + "price": "0.0392", + "quantity": "124.7234", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CVC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3AB03E", - "humanType": "Sweep to Main Account", - "id": 294, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "56.83803512" + { + "amount": "6.01869744", + "createTime": 1709908612932, + "id": "7416", + "price": "0.0392", + "quantity": "153.5382", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CVP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1836CC", - "humanType": "Sweep to Main Account", - "id": 435, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "20.09750428" + { + "amount": "3.21910254", + "createTime": 1709908612932, + "id": "7415", + "price": "0.0382", + "quantity": "84.2697", + "takerSide": "BUY", + "ts": 1719393673040 }, - "CVT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4150F5", - "humanType": "Sweep to Main Account", - "id": 451, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1371.64979814" - }, - "CYC": { - "blockchain": "CYC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 52, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "1.59616363", + "createTime": 1709847874566, + "id": "7414", + "price": "0.0353", + "quantity": "45.2171", + "takerSide": "SELL", + "ts": 1719393673040 }, - "DAI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F0B246", - "humanType": "Sweep to Main Account", - "id": 325, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "21.10237950" + { + "amount": "3.00000132", + "createTime": 1709847874566, + "id": "7413", + "price": "0.0354", + "quantity": "84.7458", + "takerSide": "SELL", + "ts": 1719393673040 }, - "DAO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 279, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00875000" - }, - "DASH": { - "blockchain": "DASH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "008DE4", - "humanType": "BTC Clone", - "id": 60, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 50, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "DCR": { - "blockchain": "DCR", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2970FF", - "humanType": "BTC Clone", - "id": 277, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 4, - "name": "", - "parentChain": null, - "txFee": "0.10000000" + { + "amount": "3.00000248", + "createTime": 1709847584591, + "id": "7412", + "price": "0.0376", + "quantity": "79.7873", + "takerSide": "SELL", + "ts": 1719393673040 }, - "DEC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "80BAED", - "humanType": "Sweep to Main Account", - "id": 379, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "192.88900709" + { + "amount": "3.06513722", + "createTime": 1709847189670, + "id": "7411", + "price": "0.0386", + "quantity": "79.4077", + "takerSide": "BUY", + "ts": 1719393673040 }, - "DEGO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2D6B6A", - "humanType": "Sweep to Main Account", - "id": 518, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "3.19685193" + { + "amount": "1.189215", + "createTime": 1709847108954, + "id": "7410", + "price": "0.0375", + "quantity": "31.7124", + "takerSide": "BUY", + "ts": 1719393673040 }, - "DEXT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "4298B7", - "humanType": "Sweep to Main Account", - "id": 397, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "516.45513631" - }, - "DGB": { - "blockchain": "DGB", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "012351", - "humanType": "BTC Clone", - "id": 53, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 40, - "name": "", - "parentChain": null, - "txFee": "0.10000000" + { + "amount": "3.5856281", + "createTime": 1709846812520, + "id": "7409", + "price": "0.0362", + "quantity": "99.0505", + "takerSide": "BUY", + "ts": 1719393673040 }, - "DHT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2C67CD", - "humanType": "Sweep to Main Account", - "id": 432, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "16.68908208" + { + "amount": "5.5937728", + "createTime": 1709826672750, + "id": "7408", + "price": "0.0352", + "quantity": "158.914", + "takerSide": "SELL", + "ts": 1719393673040 }, - "DIA": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "ADCFC3", - "humanType": "Sweep to Main Account", - "id": 391, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "9.53675717" - }, - "DICE": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "9FDC87", - "humanType": "Sweep to Main Account", - "id": 54, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "7.00000000" - }, - "DIEM": { - "blockchain": "DIEM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 55, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "DIME": { - "blockchain": "DIME", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 56, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "DIS": { - "blockchain": "DIS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 57, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "1.0999959", + "createTime": 1709826672750, + "id": "7407", + "price": "0.0355", + "quantity": "30.9858", + "takerSide": "SELL", + "ts": 1719393673040 }, - "DMG": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "447CC5", - "humanType": "Sweep to Main Account", - "id": 404, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "208.00000000" - }, - "DNS": { - "blockchain": "DNS", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 58, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.50000000" + { + "amount": "2.64982192", + "createTime": 1709822110044, + "id": "7406", + "price": "0.0356", + "quantity": "74.4332", + "takerSide": "BUY", + "ts": 1719393673040 }, - "DOGE": { - "blockchain": "DOGE", - "childChains": [ - "DOGETRON" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B88D3F", - "humanType": "BTC Clone", - "id": 59, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 6, - "name": "", - "parentChain": null, - "txFee": "20.00000000" - }, - "DOGETRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B88D34", - "humanType": "Sweep to Main Account", - "id": 524, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "DOGE", - "txFee": "20.00000000" + { + "amount": "0.00000355", + "createTime": 1709810528964, + "id": "7405", + "price": "0.0355", + "quantity": "0.0001", + "takerSide": "BUY", + "ts": 1719393673040 }, - "DOS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "A3A7A8", - "humanType": "Sweep to Main Account", - "id": 392, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "639.58665322" - }, - "DOT": { - "blockchain": "DOT", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E6007A", - "humanType": "Sweep to Main Account", - "id": 400, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "DRKC": { - "blockchain": "DRKC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 61, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "DRM": { - "blockchain": "DRM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 62, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "DSH": { - "blockchain": "DSH", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "D8PDwmpq4KMhTy6u8RvWt5PLTMwEayGN3jeYoS3pkJQJMULNt2CyYKXG7KhqSahe9DPppRKqzkWGoMjf8C4L2mzFAgsJZXs", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 63, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "DVK": { - "blockchain": "DVK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 64, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "EAC": { - "blockchain": "EAC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 65, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "EBT": { - "blockchain": "EBT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 66, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "ECC": { - "blockchain": "ECC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 67, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "EFL": { - "blockchain": "EFL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 68, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "15.9506825", + "createTime": 1709706732451, + "id": "7404", + "price": "0.0355", + "quantity": "449.315", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ELON": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FFCB83", - "humanType": "Sweep to Main Account", - "id": 520, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "301462564.28571429" - }, - "EMC2": { - "blockchain": "EMC2", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 69, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "EMO": { - "blockchain": "EMO", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 70, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "ENC": { - "blockchain": "ENC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 71, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "EOS": { - "blockchain": "EOS", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "poloniexeos1", - "disabled": 0, - "frozen": 0, - "hexColor": "717F99", - "humanType": "Payment ID", - "id": 298, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 350, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.652", + "createTime": 1709706732451, + "id": "7403", + "price": "0.0326", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719393673040 }, - "EOSBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 355, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "923459.96811703" + { + "amount": "9.3515", + "createTime": 1709705149722, + "id": "7402", + "price": "0.0295", + "quantity": "317", + "takerSide": "SELL", + "ts": 1719393673040 }, - "EOSBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 354, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "9393.22037940" - }, - "EPS": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "313131", - "humanType": "Sweep to Main Account", - "id": 546, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "4.50000000" + { + "amount": "1.61795556", + "createTime": 1709705130064, + "id": "7401", + "price": "0.0324", + "quantity": "49.9369", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ESD": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "8C8C89", - "humanType": "Sweep to Main Account", - "id": 472, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "458.74498698" - }, - "ETC": { - "blockchain": "ETC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "698F74", - "humanType": "Sweep to Main Account", - "id": 283, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 7000, - "name": "", - "parentChain": null, - "txFee": "0.04375000" + { + "amount": "10.40244444", + "createTime": 1709705130064, + "id": "7400", + "price": "0.0324", + "quantity": "321.0631", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ETH": { - "blockchain": "ETH", - "childChains": [ - "ETHTRON" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1C1CE1", - "humanType": "Sweep to Main Account", - "id": 267, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00739257" + { + "amount": "3.24", + "createTime": 1709705120731, + "id": "7399", + "price": "0.0324", + "quantity": "100", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ETHBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 333, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "68387340.97222222" + { + "amount": "0.648", + "createTime": 1709705104430, + "id": "7398", + "price": "0.0324", + "quantity": "20", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ETHBNT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "102644", - "humanType": "Sweep to Main Account", - "id": 319, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "6.30596246" + { + "amount": "1.36876716", + "createTime": 1709693855739, + "id": "7397", + "price": "0.0324", + "quantity": "42.2459", + "takerSide": "SELL", + "ts": 1719393673040 }, - "ETHBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 334, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.01440226" - }, - "ETHTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1C1CE1", - "humanType": "Sweep to Main Account", - "id": 458, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "ETH", - "txFee": "0.00000000" + { + "amount": "9.73777672", + "createTime": 1709665622199, + "id": "7396", + "price": "0.0373", + "quantity": "261.0664", + "takerSide": "BUY", + "ts": 1719393673040 }, - "EXE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "9F61F6", - "humanType": "Sweep to Main Account", - "id": 73, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "5242.37134659" - }, - "EXP": { - "blockchain": "EXP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 270, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 8000, - "name": "", - "parentChain": null, - "txFee": "0.00875000" - }, - "FAC": { - "blockchain": "FAC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 74, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.326", + "createTime": 1709665622199, + "id": "7395", + "price": "0.0326", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "FARM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E9B544", - "humanType": "Sweep to Main Account", - "id": 469, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.07665968" - }, - "FCN": { - "blockchain": "FCN", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "6mkbrPdSAjeaQKCCx8Nus1JiKb4HdeTDXC4bEWunDzTMXMPESd7aFNYPAG1U4MUpnhHfJfzVyTqnRFRW2REKN6efBVRMoSY", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 75, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FCT": { - "blockchain": "FCT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "417CA5", - "humanType": "BTC Clone", - "id": 271, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 3, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "5844.169008", + "createTime": 1709662558867, + "id": "7394", + "price": "0.036", + "quantity": "162338.028", + "takerSide": "BUY", + "ts": 1719393673040 }, - "FCT2": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "646665", - "humanType": "Sweep to Main Account", - "id": 413, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "139.28377731" - }, - "FIBRE": { - "blockchain": "FIBRE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 76, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FIL": { - "blockchain": "FIL", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "67BEC8", - "humanType": "Sweep to Main Account", - "id": 362, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 120, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FLAP": { - "blockchain": "FLAP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 77, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FLDC": { - "blockchain": "FLDC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 78, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "750.00000000" - }, - "FLO": { - "blockchain": "FLO", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 254, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FLT": { - "blockchain": "FLT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 79, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "38.83815293", + "createTime": 1709662558867, + "id": "7393", + "price": "0.0359", + "quantity": "1081.8427", + "takerSide": "BUY", + "ts": 1719393673040 }, - "FOAM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "CB8271", - "humanType": "Sweep to Main Account", - "id": 307, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "580.26445173" + { + "amount": "704.9526156", + "createTime": 1709662550936, + "id": "7392", + "price": "0.036", + "quantity": "19582.0171", + "takerSide": "BUY", + "ts": 1719393673040 }, - "FORTH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 519, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.21216642" - }, - "FOX": { - "blockchain": "FOX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 80, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FRAC": { - "blockchain": "FRAC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 81, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "FRK": { - "blockchain": "FRK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 82, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "9.6954624", + "createTime": 1709662546107, + "id": "7391", + "price": "0.036", + "quantity": "269.3184", + "takerSide": "SELL", + "ts": 1719393673040 }, - "FRONT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "372521", - "humanType": "Sweep to Main Account", - "id": 462, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "15.03739164" - }, - "FRQ": { - "blockchain": "FRQ", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 83, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "39.99999483", + "createTime": 1709662494050, + "id": "7390", + "price": "0.0369", + "quantity": "1084.0107", + "takerSide": "SELL", + "ts": 1719393673040 }, - "FSW": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2a6def", - "humanType": "Sweep to Main Account", - "id": 426, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "334.95840476" + { + "amount": "3.00000321", + "createTime": 1709662494050, + "id": "7389", + "price": "0.0369", + "quantity": "81.3009", + "takerSide": "SELL", + "ts": 1719393673040 }, - "FTT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7ECEE2", - "humanType": "Sweep to Main Account", - "id": 484, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.41970240" - }, - "FUND": { - "blockchain": "FUND", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "921D43", - "humanType": "Sweep to Main Account", - "id": 410, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "5.00000000" - }, - "FVZ": { - "blockchain": "FVZ", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 84, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.368", + "createTime": 1709650820411, + "id": "7388", + "price": "0.0368", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "FXC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "842CF6", - "humanType": "Sweep to Main Account", - "id": 351, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "705.32600000" - }, - "FZ": { - "blockchain": "FZ", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 85, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "FZN": { - "blockchain": "FZN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 86, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "GAME": { - "blockchain": "GAME", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "28546D", - "humanType": "BTC Clone", - "id": 93, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 80, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GAP": { - "blockchain": "GAP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 87, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GAS": { - "blockchain": "GAS", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3E8700", - "humanType": "BTC Clone", - "id": 296, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 18, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "GDN": { - "blockchain": "GDN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 88, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "6.0702302", + "createTime": 1709642204214, + "id": "7387", + "price": "0.038", + "quantity": "159.7429", + "takerSide": "BUY", + "ts": 1719393673040 }, - "GEEQ": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "30416F", - "humanType": "Sweep to Main Account", - "id": 388, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "28.28738260" - }, - "GEMZ": { - "blockchain": "GEMZ", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 89, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "500.00000000" - }, - "GEO": { - "blockchain": "GEO", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 90, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.35", + "createTime": 1709642204214, + "id": "7386", + "price": "0.035", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "GHST": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E641EC", - "humanType": "Sweep to Main Account", - "id": 436, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "25.63205006" - }, - "GIAR": { - "blockchain": "GIAR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 91, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GLB": { - "blockchain": "GLB", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 92, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "6.37467516", + "createTime": 1709637628120, + "id": "7385", + "price": "0.0378", + "quantity": "168.6422", + "takerSide": "BUY", + "ts": 1719393673040 }, - "GLM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "181EA9", - "humanType": "Sweep to Main Account", - "id": 457, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "42.28018939" - }, - "GML": { - "blockchain": "GML", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 94, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.19372445", + "createTime": 1709637628120, + "id": "7384", + "price": "0.0365", + "quantity": "87.4993", + "takerSide": "BUY", + "ts": 1719393673040 }, - "GNO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 291, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01312500" - }, - "GNS": { - "blockchain": "GNS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 95, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.0293", + "createTime": 1709570265033, + "id": "7383", + "price": "0.0293", + "quantity": "1", + "takerSide": "SELL", + "ts": 1719393673040 }, - "GNT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "181EA9", - "humanType": "Sweep to Main Account", - "id": 290, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "58.27591860" - }, - "GOLD": { - "blockchain": "GOLD", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 96, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GPC": { - "blockchain": "GPC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 97, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GPUC": { - "blockchain": "GPUC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 98, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GRC": { - "blockchain": "GRC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 261, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GRCX": { - "blockchain": "GRCX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 99, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "GRIN": { - "blockchain": "GRIN", - "childChains": [], - "currencyType": "mimblewimble", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "FEDC00", - "humanType": "MimbleWimble", - "id": 314, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15000, - "name": "", - "parentChain": null, - "txFee": "0.25000000" - }, - "GRS": { - "blockchain": "GRS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 100, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 100000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "1.465", + "createTime": 1709570250882, + "id": "7382", + "price": "0.0293", + "quantity": "50", + "takerSide": "SELL", + "ts": 1719393673040 }, - "GRT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4C37B3", - "humanType": "Sweep to Main Account", - "id": 470, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "20.39985698" + { + "amount": "1.99484362", + "createTime": 1709570188687, + "id": "7381", + "price": "0.0293", + "quantity": "68.0834", + "takerSide": "SELL", + "ts": 1719393673040 }, - "GTC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "02E4AE", - "humanType": "Sweep to Main Account", - "id": 537, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.30080101" - }, - "GUE": { - "blockchain": "GUE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 101, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "H2O": { - "blockchain": "H2O", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 102, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "2.66734293", + "createTime": 1709570176492, + "id": "7380", + "price": "0.0343", + "quantity": "77.7651", + "takerSide": "SELL", + "ts": 1719393673040 }, - "HEGIC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "A8F1F8", - "humanType": "Sweep to Main Account", - "id": 459, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "120.14178491" + { + "amount": "0.32455003", + "createTime": 1709563812771, + "id": "7379", + "price": "0.0343", + "quantity": "9.4621", + "takerSide": "SELL", + "ts": 1719393673040 }, - "HGET": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "fccc4c", - "humanType": "Sweep to Main Account", - "id": 428, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.69273778" - }, - "HIRO": { - "blockchain": "HIRO", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 103, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "HOT": { - "blockchain": "HOT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 104, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "4.99999838", + "createTime": 1709511825694, + "id": "7378", + "price": "0.0398", + "quantity": "125.6281", + "takerSide": "BUY", + "ts": 1719393673040 }, - "HT": { - "blockchain": "ETH", - "childChains": [ - "HTTRON" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "53A7DB", - "humanType": "Sweep to Main Account", - "id": 326, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.49958886" - }, - "HTTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2a3165", - "humanType": "Sweep to Main Account", - "id": 528, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "HT", - "txFee": "0.10000000" - }, - "HUC": { - "blockchain": "HUC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "8D4B1D", - "humanType": "BTC Clone", - "id": 105, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "HUGE": { - "blockchain": "HUGE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 260, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "HVC": { - "blockchain": "HVC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 106, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "HYP": { - "blockchain": "HYP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 107, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "HZ": { - "blockchain": "HZ", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 108, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" + { + "amount": "0.00002208", + "createTime": 1709450803469, + "id": "7377", + "price": "0.0368", + "quantity": "0.0006", + "takerSide": "BUY", + "ts": 1719393673040 }, - "IBVOL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 347, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00776931" - }, - "IFC": { - "blockchain": "IFC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 109, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "2000.00000000" - }, - "INDEX": { - "blockchain": "INDEX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 265, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" + { + "amount": "0.332", + "createTime": 1709450763434, + "id": "7376", + "price": "0.0332", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "INJ": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "61CEE7", - "humanType": "Sweep to Main Account", - "id": 452, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.65390189" - }, - "IOC": { - "blockchain": "IOC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 263, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "ITC": { - "blockchain": "ITC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 110, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "IXC": { - "blockchain": "IXC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 111, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "JFI": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "808080", - "humanType": "Sweep to Main Account", - "id": 421, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00840000" - }, - "JLH": { - "blockchain": "JLH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 112, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "JPC": { - "blockchain": "JPC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 113, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "JST": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "A52A21", - "humanType": "Sweep to Main Account", - "id": 345, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "15.00000000" - }, - "JUG": { - "blockchain": "JUG", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 114, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "13.48700496", + "createTime": 1709429706269, + "id": "7375", + "price": "0.0368", + "quantity": "366.4947", + "takerSide": "BUY", + "ts": 1719393673040 }, - "KCS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "23AF91", - "humanType": "Sweep to Main Account", - "id": 504, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.74460715" - }, - "KDC": { - "blockchain": "KDC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 115, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "KEY": { - "blockchain": "KEY", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 116, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.0004455", + "createTime": 1709429706269, + "id": "7374", + "price": "0.033", + "quantity": "0.0135", + "takerSide": "BUY", + "ts": 1719393673040 }, - "KISHU": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F5EEDC", - "humanType": "Sweep to Main Account", - "id": 529, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "318403655.00000000" - }, - "KLV": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E943C6", - "humanType": "Sweep to Main Account", - "id": 511, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "100.00000000" + { + "amount": "0.305", + "createTime": 1709351099335, + "id": "7373", + "price": "0.0305", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "KNC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "23A781", - "humanType": "Sweep to Main Account", - "id": 301, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "9.70565966" + { + "amount": "215.8628637", + "createTime": 1709345847983, + "id": "7372", + "price": "0.033", + "quantity": "6541.2989", + "takerSide": "BUY", + "ts": 1719393673040 }, - "KP3R": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "467FC1", - "humanType": "Sweep to Main Account", - "id": 455, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.13690394" + { + "amount": "0.314", + "createTime": 1709345847983, + "id": "7371", + "price": "0.0314", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "KTON": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5A9D51", - "humanType": "Sweep to Main Account", - "id": 382, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.25276858" - }, - "LBC": { - "blockchain": "LBC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "2F9176", - "humanType": "BTC Clone", - "id": 280, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 30, - "name": "", - "parentChain": null, - "txFee": "0.05000000" - }, - "LC": { - "blockchain": "LC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 117, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "LCL": { - "blockchain": "LCL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 118, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "LEAF": { - "blockchain": "LEAF", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 119, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.10000000" + { + "amount": "3.0347692", + "createTime": 1709332800311, + "id": "7370", + "price": "0.0316", + "quantity": "96.037", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LEND": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "4390C3", - "humanType": "Sweep to Main Account", - "id": 366, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "11.63200000" - }, - "LGC": { - "blockchain": "LGC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 120, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.302", + "createTime": 1709332800311, + "id": "7369", + "price": "0.0302", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LINK": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3663D4", - "humanType": "Sweep to Main Account", - "id": 327, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.74299275" + { + "amount": "2.85382132", + "createTime": 1709317745478, + "id": "7368", + "price": "0.0313", + "quantity": "91.1764", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LINKBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 357, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "820648091.66666667" + { + "amount": "0.301", + "createTime": 1709317745478, + "id": "7367", + "price": "0.0301", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LINKBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 356, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "7.81857250" - }, - "LIVE": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B64A45", - "humanType": "Sweep to Main Account", - "id": 508, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "10.00000000" - }, - "LOL": { - "blockchain": "LOL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 121, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "6.34437228", + "createTime": 1709317321722, + "id": "7366", + "price": "0.0313", + "quantity": "202.6956", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LON": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "706896", - "humanType": "Sweep to Main Account", - "id": 478, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "8.23638548" + { + "amount": "0.305", + "createTime": 1709317321722, + "id": "7365", + "price": "0.0305", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LOOM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5756E6", - "humanType": "Sweep to Main Account", - "id": 303, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "209.37540339" - }, - "LOVE": { - "blockchain": "LOVE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 122, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "6.13229955", + "createTime": 1709317287697, + "id": "7364", + "price": "0.0293", + "quantity": "209.2935", + "takerSide": "SELL", + "ts": 1719393673040 }, - "LPT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "283845", - "humanType": "Sweep to Main Account", - "id": 312, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.95170497" - }, - "LQD": { - "blockchain": "LQD", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 123, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" + { + "amount": "6.1796923", + "createTime": 1709317287697, + "id": "7363", + "price": "0.0293", + "quantity": "210.911", + "takerSide": "SELL", + "ts": 1719393673040 }, - "LQTY": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3925C2", - "humanType": "Sweep to Main Account", - "id": 512, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "3.24303079" + { + "amount": "2.36622666", + "createTime": 1709311469023, + "id": "7362", + "price": "0.0343", + "quantity": "68.9862", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LRC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2862F6", - "humanType": "Sweep to Main Account", - "id": 368, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "35.85297436" - }, - "LSK": { - "blockchain": "LSK", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "003075", - "humanType": "Sweep to Main Account", - "id": 278, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 303, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "LTBC": { - "blockchain": "LTBC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 124, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "15000.00000000" + { + "amount": "22.1666162", + "createTime": 1709311469023, + "id": "7361", + "price": "0.034", + "quantity": "651.9593", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LTC": { - "blockchain": "LTC", - "childChains": [ - "LTCTRON" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "509BCA", - "humanType": "BTC Clone", - "id": 125, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 4, - "name": "", - "parentChain": null, - "txFee": "0.00100000" + { + "amount": "3.0832254", + "createTime": 1709311469023, + "id": "7360", + "price": "0.034", + "quantity": "90.6831", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LTCBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 490, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "7272.34783700" + { + "amount": "3.4", + "createTime": 1709311469023, + "id": "7359", + "price": "0.034", + "quantity": "100", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LTCBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 491, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "110.04588709" - }, - "LTCTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "509BCA", - "humanType": "Sweep to Main Account", - "id": 494, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "LTC", - "txFee": "0.00010000" - }, - "LTCX": { - "blockchain": "LTCX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 126, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.4", + "createTime": 1709311469023, + "id": "7358", + "price": "0.034", + "quantity": "100", + "takerSide": "BUY", + "ts": 1719393673040 }, - "LUSD": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "6F62D7", - "humanType": "Sweep to Main Account", - "id": 513, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "20.95280622" - }, - "MAID": { - "blockchain": "MAID", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "5592D7", - "humanType": "Sweep to Main Account", - "id": 127, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1, - "name": "", - "parentChain": null, - "txFee": "80.00000000" + { + "amount": "142.94020767", + "createTime": 1709311469023, + "id": "7357", + "price": "0.0339", + "quantity": "4216.5253", + "takerSide": "BUY", + "ts": 1719393673040 }, - "MANA": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "DB6C27", - "humanType": "Sweep to Main Account", - "id": 306, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "23.30030984" - }, - "MAST": { - "blockchain": "MAST", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 128, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.999999", + "createTime": 1709177143806, + "id": "7356", + "price": "0.0276", + "quantity": "144.9275", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MATIC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4791F2", - "humanType": "Sweep to Main Account", - "id": 338, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "12.78704412" - }, - "MAX": { - "blockchain": "MAX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 129, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "1.43264187", + "createTime": 1709177116713, + "id": "7355", + "price": "0.0297", + "quantity": "48.2371", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MCB": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "DA7F43", - "humanType": "Sweep to Main Account", - "id": 398, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.87926581" - }, - "MCN": { - "blockchain": "MCN", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "VdttvavdPJNGD4NzPQf8Hn4tWUGyy9mQ58ScwXxKbx9ve4Kp8xXZ1kD1KmXUMp5qtX8GmRgMk16aNVBhENEHNQAb3488Ha7Vv", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 130, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" + { + "amount": "1.25104512", + "createTime": 1709177116713, + "id": "7354", + "price": "0.0312", + "quantity": "40.0976", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MDT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "6B9CE6", - "humanType": "Sweep to Main Account", - "id": 359, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "505.99778345" - }, - "MEC": { - "blockchain": "MEC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 131, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "2.20000242", + "createTime": 1709045838302, + "id": "7353", + "price": "0.0341", + "quantity": "64.5162", + "takerSide": "BUY", + "ts": 1719393673040 }, - "MEME": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "ECB754", - "humanType": "Sweep to Main Account", - "id": 433, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.03030478" - }, - "METH": { - "blockchain": "METH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 132, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "22.033791", + "createTime": 1708713616812, + "id": "7352", + "price": "0.03", + "quantity": "734.4597", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MEXP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "B1D968", - "humanType": "Sweep to Main Account", - "id": 439, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2.26300000" - }, - "MIL": { - "blockchain": "MIL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 133, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MIN": { - "blockchain": "MIN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 134, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MINT": { - "blockchain": "MINT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 135, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.10000000" + { + "amount": "1.269918", + "createTime": 1708713616812, + "id": "7351", + "price": "0.03", + "quantity": "42.3306", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MIR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "232C45", - "humanType": "Sweep to Main Account", - "id": 516, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.91011129" + { + "amount": "126.91741153", + "createTime": 1708713616811, + "id": "7350", + "price": "0.0301", + "quantity": "4216.5253", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MIST": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "8A1FE3", - "humanType": "Sweep to Main Account", - "id": 521, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.30922828" + { + "amount": "17.56506871", + "createTime": 1708713616811, + "id": "7349", + "price": "0.0301", + "quantity": "583.5571", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MKR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7EC5B6", - "humanType": "Sweep to Main Account", - "id": 328, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00540104" - }, - "MMC": { - "blockchain": "MMC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 136, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MMNXT": { - "blockchain": "MMNXT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 137, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "MMXIV": { - "blockchain": "MMXIV", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 138, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - }, - "MNTA": { - "blockchain": "MNTA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 139, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MON": { - "blockchain": "MON", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 140, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "2.13999876", + "createTime": 1708685632740, + "id": "7348", + "price": "0.0307", + "quantity": "69.7068", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MPH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "AD45AB", - "humanType": "Sweep to Main Account", - "id": 456, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.44898680" - }, - "MRC": { - "blockchain": "MRC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 141, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MRS": { - "blockchain": "MRS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 142, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "4.00000124", + "createTime": 1708685632740, + "id": "7347", + "price": "0.0307", + "quantity": "130.2932", + "takerSide": "SELL", + "ts": 1719393673040 }, - "MTA": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "95989C", - "humanType": "Sweep to Main Account", - "id": 374, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "20.07023896" - }, - "MTS": { - "blockchain": "MTS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 144, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MUN": { - "blockchain": "MUN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 145, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0.67699995", + "createTime": 1708634262077, + "id": "7346", + "price": "0.0339", + "quantity": "19.9705", + "takerSide": "BUY", + "ts": 1719393673040 }, - "MVL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 525, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1409.64378205" - }, - "MYR": { - "blockchain": "MYR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 146, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "MZC": { - "blockchain": "MZC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 147, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "N5X": { - "blockchain": "N5X", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 148, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NAS": { - "blockchain": "NAS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 149, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "NAUT": { - "blockchain": "NAUT", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 150, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "NAV": { - "blockchain": "NAV", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "7243BF", - "humanType": "BTC Clone", - "id": 151, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 480, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NBT": { - "blockchain": "NBT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 152, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NEO": { - "blockchain": "NEO", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3E8700", - "humanType": "BTC Clone", - "id": 348, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 18, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "NEOS": { - "blockchain": "NEOS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 153, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.00010000" + { + "amount": "0.323", + "createTime": 1708634262077, + "id": "7345", + "price": "0.0323", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "NFT": { - "blockchain": "TRX", - "childChains": [ - "NFTETH" - ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 526, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "1587301.58730159" + { + "amount": "2.00000169", + "createTime": 1708539218919, + "id": "7344", + "price": "0.0339", + "quantity": "58.9971", + "takerSide": "SELL", + "ts": 1719393673040 }, - "NFTETH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 527, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": "NFT", - "txFee": "7500000.00000000" + { + "amount": "0.73480842", + "createTime": 1708435800699, + "id": "7343", + "price": "0.0354", + "quantity": "20.7573", + "takerSide": "SELL", + "ts": 1719393673040 }, - "NFTX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EB34D2", - "humanType": "Sweep to Main Account", - "id": 515, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.32440509" - }, - "NL": { - "blockchain": "NL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 154, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NMC": { - "blockchain": "NMC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "6687B7", - "humanType": "BTC Clone", - "id": 155, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 24, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "138.84016014", + "createTime": 1708428298569, + "id": "7342", + "price": "0.0363", + "quantity": "3824.7978", + "takerSide": "BUY", + "ts": 1719393673040 }, - "NMR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "171717", - "humanType": "Sweep to Main Account", - "id": 310, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.46258847" - }, - "NOBL": { - "blockchain": "NOBL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 156, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NOTE": { - "blockchain": "NOTE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 157, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NOXT": { - "blockchain": "NOXT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 158, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "NRS": { - "blockchain": "NRS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 159, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "NRV": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "161A2D", - "humanType": "Sweep to Main Account", - "id": 549, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "2.89000000" - }, - "NSR": { - "blockchain": "NSR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 160, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "2.00000000" - }, - "NTX": { - "blockchain": "NTX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 161, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" + { + "amount": "2.0000032", + "createTime": 1708427903377, + "id": "7341", + "price": "0.0367", + "quantity": "54.496", + "takerSide": "SELL", + "ts": 1719393673040 }, - "NU": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3665CA", - "humanType": "Sweep to Main Account", - "id": 461, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "66.40527181" + { + "amount": "0.366", + "createTime": 1708415426554, + "id": "7340", + "price": "0.0366", + "quantity": "10", + "takerSide": "BUY", + "ts": 1719393673040 }, - "NXC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 288, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "8.75000000" - }, - "NXT": { - "blockchain": "NXT", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "008FBB", - "humanType": "Sweep to Main Account", - "id": 162, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 24, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "NXTI": { - "blockchain": "NXTI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 163, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" + { + "amount": "3.39692978", + "createTime": 1708373019448, + "id": "7339", + "price": "0.0326", + "quantity": "104.2003", + "takerSide": "SELL", + "ts": 1719393673040 }, - "OCEAN": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B7BDB9", - "humanType": "Sweep to Main Account", - "id": 403, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "39.79558738" + { + "amount": "2.8699128", + "createTime": 1708361738087, + "id": "7338", + "price": "0.034", + "quantity": "84.4092", + "takerSide": "BUY", + "ts": 1719393673040 }, - "OKB": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "005CEE", - "humanType": "Sweep to Main Account", - "id": 539, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.21160048" + { + "amount": "0.608", + "createTime": 1708361738087, + "id": "7337", + "price": "0.0304", + "quantity": "20", + "takerSide": "BUY", + "ts": 1719393673040 }, - "OM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "DA386E", - "humanType": "Sweep to Main Account", - "id": 405, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "131.72388327" + { + "amount": "0.00584695", + "createTime": 1708360544449, + "id": "7336", + "price": "0.0347", + "quantity": "0.1685", + "takerSide": "BUY", + "ts": 1719393673040 }, - "OMG": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1A53F0", - "humanType": "Sweep to Main Account", - "id": 295, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "3.33345257" - }, - "OMNI": { - "blockchain": "OMNI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "1C347A", - "humanType": "Sweep to Main Account", - "id": 143, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1, - "name": "", - "parentChain": null, - "txFee": "4.00000000" + { + "amount": "11.69415272", + "createTime": 1708360544449, + "id": "7335", + "price": "0.0344", + "quantity": "339.9463", + "takerSide": "BUY", + "ts": 1719393673040 }, - "ONEINCH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "23344F", - "humanType": "Sweep to Main Account", - "id": 473, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "6.42542030" - }, - "OPAL": { - "blockchain": "OPAL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 164, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "7.8418926", + "createTime": 1708359896164, + "id": "7334", + "price": "0.034", + "quantity": "230.6439", + "takerSide": "BUY", + "ts": 1719393673040 + }, + { + "amount": "20.947278", + "createTime": 1708359418864, + "id": "7333", + "price": "0.033", + "quantity": "634.766", + "takerSide": "BUY", + "ts": 1719393673040 + }, + { + "amount": "13.7500011", + "createTime": 1708359418864, + "id": "7332", + "price": "0.033", + "quantity": "416.6667", + "takerSide": "BUY", + "ts": 1719393673040 + }, + { + "amount": "17.936328", + "createTime": 1708354733906, + "id": "7331", + "price": "0.0282", + "quantity": "636.04", + "takerSide": "SELL", + "ts": 1719393673040 + }, + { + "amount": "1.13642052", + "createTime": 1708354733906, + "id": "7330", + "price": "0.0282", + "quantity": "40.2986", + "takerSide": "SELL", + "ts": 1719393673040 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "16.14360545", + "createTime": 1743970367435, + "id": "128015795", + "price": "79525.15", + "quantity": "0.000203", + "takerSide": "BUY", + "ts": 1743970367446 }, - "OPT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "202D47", - "humanType": "Sweep to Main Account", - "id": 407, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "10.04723372" - }, - "PAND": { - "blockchain": "PAND", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 165, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PASC": { - "blockchain": "PASC", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "86646-64", - "disabled": 1, - "frozen": 0, - "hexColor": "D48200", - "humanType": "Payment ID", - "id": 289, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 300, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PAWN": { - "blockchain": "PAWN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 166, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "3.1860672", + "createTime": 1743970266560, + "id": "128015794", + "price": "79651.68", + "quantity": "0.00004", + "takerSide": "SELL", + "ts": 1743970266572 }, - "PAX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "87B360", - "humanType": "Sweep to Main Account", - "id": 329, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "24.61944275" + { + "amount": "1.99129225", + "createTime": 1743970263798, + "id": "128015793", + "price": "79651.69", + "quantity": "0.000025", + "takerSide": "BUY", + "ts": 1743970263811 }, - "PBTC35A": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4D70EE", - "humanType": "Sweep to Main Account", - "id": 482, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.48273417" - }, - "PEARL": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "8a66ac", - "humanType": "Sweep to Main Account", - "id": 419, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00390000" + { + "amount": "11.1512352", + "createTime": 1743970261795, + "id": "128015792", + "price": "79651.68", + "quantity": "0.00014", + "takerSide": "SELL", + "ts": 1743970261815 }, - "PERP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1F2840", - "humanType": "Sweep to Main Account", - "id": 558, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.19781713" + { + "amount": "16.24894272", + "createTime": 1743970261795, + "id": "128015791", + "price": "79651.68", + "quantity": "0.000204", + "takerSide": "SELL", + "ts": 1743970261815 + } + ], + "queryString": "limit=1000", + "bodyParams": "", + "headers": {} + }, + { + "data": [ + { + "amount": "1830.93874332", + "createTime": 1720111018763, + "id": "97220622", + "price": "57845.91", + "quantity": "0.031652", + "takerSide": "BUY", + "ts": 1720111018774 }, - "PERX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EBCED2", - "humanType": "Sweep to Main Account", - "id": 399, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "11260.12736916" - }, - "PIGGY": { - "blockchain": "PIGGY", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 167, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PINK": { - "blockchain": "PINK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 168, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "1955.17582285", + "createTime": 1720111018124, + "id": "97220621", + "price": "57847.15", + "quantity": "0.033799", + "takerSide": "BUY", + "ts": 1720111018139 }, - "PLT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "578FCB", - "humanType": "Sweep to Main Account", - "id": 380, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "525.70578630" - }, - "PLX": { - "blockchain": "PLX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 169, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PMC": { - "blockchain": "PMC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 170, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "POL": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "00E2DF", - "humanType": "Sweep to Main Account", - "id": 540, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "10.00000000" + { + "amount": "1277.82015519", + "createTime": 1720111014770, + "id": "97220620", + "price": "57848.71", + "quantity": "0.022089", + "takerSide": "BUY", + "ts": 1720111014783 }, - "POLS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "D84D8C", - "humanType": "Sweep to Main Account", - "id": 444, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "10.58164685" + { + "amount": "1848.61337676", + "createTime": 1720111014769, + "id": "97220619", + "price": "57848.71", + "quantity": "0.031956", + "takerSide": "BUY", + "ts": 1720111014776 }, - "POLY": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3F4B80", - "humanType": "Sweep to Main Account", - "id": 311, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "63.57608696" - }, - "POT": { - "blockchain": "POT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 171, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PPC": { - "blockchain": "PPC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "34AA4C", - "humanType": "BTC Clone", - "id": 172, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PRC": { - "blockchain": "PRC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 173, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "1972.48473696", + "createTime": 1720111011966, + "id": "97220618", + "price": "57847.52", + "quantity": "0.034098", + "takerSide": "BUY", + "ts": 1720111011979 + } + ], + "queryString": "limit=10", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/BTC_USDT_PERP": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/ETHF_USDT/price": { + "GET": [ + { + "data": { + "dailyChange": "0.00", + "price": "1", + "symbol": "ETHF_USDT", + "time": 1719908857160, + "ts": 1719908857175 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/ETH_USDTPERP": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/FTT_USDT/orderBook": { + "GET": [ + { + "data": { + "asks": [ + "2.628", + "5.091604", + "2.66", + "50.462539", + "2.661", + "6.773860", + "2.685", + "4.240538", + "2.753", + "209.781858", + "2.754", + "2.098209", + "2.862", + "4.428045", + "3.497", + "23.813887", + "3.892", + "1.132473", + "3.999", + "0.250063" + ], + "bids": [ + "2.586", + "4.291392", + "2.504", + "93.493306", + "2.503", + "4.925275", + "2.502", + "4.98559", + "2.501", + "0.839674", + "2.302", + "3.475238", + "2.301", + "0.434784", + "2.2", + "5.454545", + "2.12", + "9.433962", + "2.115", + "0.472814" + ], + "scale": "0.001", + "time": 1734350610104, + "ts": 1734350610437 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/MSN_USDT": { + "GET": [ + { + "data": [ + { + "baseCurrencyName": "MSN", + "crossMargin": { + "maxLeverage": 1, + "supportCrossMargin": false + }, + "displayName": "MSN/USDT", + "quoteCurrencyName": "USDT", + "state": "NORMAL", + "symbol": "MSN_USDT", + "symbolTradeLimit": { + "amountScale": 2, + "highestBid": "0", + "lowestAsk": "0", + "minAmount": "1", + "minQuantity": "0.000001", + "priceScale": 2, + "quantityScale": 6, + "symbol": "MSN_USDT" + }, + "tradableStartTime": 1714383900000, + "visibleStartTime": 1714050000000 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/RDEX_USDT/orderBook": { + "GET": [ + { + "data": { + "asks": [ + "0.0608", + "102.3922", + "0.0609", + "326.1437", + "0.061", + "667.0518", + "0.0622", + "15462.4071", + "0.0623", + "335.6839", + "0.064", + "124.594", + "0.1041", + "81.1991", + "0.3495", + "809.2564", + "0.3497", + "613.168", + "0.418", + "191.9223" + ], + "bids": [ + "0.0185", + "721.2761", + "0.0184", + "71.7391", + "0.018", + "222.222", + "0.0168", + "297.619", + "0.0029", + "1728.0191", + "0.0028", + "506.7143", + "0.0007", + "14286", + "0.0001", + "10760.1319" + ], + "scale": "0.0001", + "time": 1734350596658, + "ts": 1734350597104 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/borrowRatesInfo": { + "GET": [ + { + "data": [ + { + "rates": [ + { + "borrowLimit": "160", + "currency": "BCH", + "dailyBorrowRate": "0.000685", + "hourlyBorrowRate": "0.000028541666666666" + }, + { + "borrowLimit": "60", + "currency": "BNB", + "dailyBorrowRate": "0.000822", + "hourlyBorrowRate": "0.00003425" + }, + { + "borrowLimit": "20", + "currency": "BTC", + "dailyBorrowRate": "0.0001", + "hourlyBorrowRate": "0.000004166666666666" + }, + { + "borrowLimit": "6000000", + "currency": "DOGE", + "dailyBorrowRate": "0.000219", + "hourlyBorrowRate": "0.000009125" + }, + { + "borrowLimit": "900", + "currency": "ETC", + "dailyBorrowRate": "0.000411", + "hourlyBorrowRate": "0.000017125" + } + ], + "tier": "TIER0" }, - "PRQ": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "225FC0", - "humanType": "Sweep to Main Account", - "id": 408, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "22.93311667" - }, - "PRT": { - "blockchain": "PRT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 174, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "PTS": { - "blockchain": "PTS", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniexwallet", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 175, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "25.00000000" - }, - "Q2C": { - "blockchain": "Q2C", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 176, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "QBK": { - "blockchain": "QBK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 177, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "QCN": { - "blockchain": "QCN", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "1VQpANF1pcKHPRAsZpeyG4jLDd1kbPn32YMeXkr9n8jNFvf8aaJdecB3FyAvo7X1DWJDQt3nii9eUTP5kJSfRpL5AwT72FM", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 178, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "QORA": { - "blockchain": "QORA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 179, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "QTL": { - "blockchain": "QTL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 180, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "QTUM": { - "blockchain": "QTUM", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1297D7", - "humanType": "BTC Clone", - "id": 304, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 6, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "rates": [ + { + "borrowLimit": "160", + "currency": "BCH", + "dailyBorrowRate": "0.000685", + "hourlyBorrowRate": "0.000028541666666666" + }, + { + "borrowLimit": "60", + "currency": "BNB", + "dailyBorrowRate": "0.000822", + "hourlyBorrowRate": "0.00003425" + }, + { + "borrowLimit": "20", + "currency": "BTC", + "dailyBorrowRate": "0.0001", + "hourlyBorrowRate": "0.000004166666666666" + }, + { + "borrowLimit": "6000000", + "currency": "DOGE", + "dailyBorrowRate": "0.000219", + "hourlyBorrowRate": "0.000009125" + }, + { + "borrowLimit": "900", + "currency": "ETC", + "dailyBorrowRate": "0.000411", + "hourlyBorrowRate": "0.000017125" + } + ], + "tier": "TIER1" }, - "QUICK": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5278C0", - "humanType": "Sweep to Main Account", - "id": 523, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.02848646" - }, - "RADS": { - "blockchain": "RADS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 274, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "rates": [ + { + "borrowLimit": "176", + "currency": "BCH", + "dailyBorrowRate": "0.0006165", + "hourlyBorrowRate": "0.0000256875" + }, + { + "borrowLimit": "66", + "currency": "BNB", + "dailyBorrowRate": "0.0007398", + "hourlyBorrowRate": "0.000030825" + }, + { + "borrowLimit": "22", + "currency": "BTC", + "dailyBorrowRate": "0.00009", + "hourlyBorrowRate": "0.00000375" + }, + { + "borrowLimit": "6600000", + "currency": "DOGE", + "dailyBorrowRate": "0.0001971", + "hourlyBorrowRate": "0.0000082125" + }, + { + "borrowLimit": "990", + "currency": "ETC", + "dailyBorrowRate": "0.0003699", + "hourlyBorrowRate": "0.0000154125" + } + ], + "tier": "TIER2" }, - "RARI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "6F9AF7", - "humanType": "Sweep to Main Account", - "id": 438, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.82292333" - }, - "RBY": { - "blockchain": "RBY", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 181, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "RD": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E46260", - "humanType": "Sweep to Main Account", - "id": 566, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.50000000" - }, - "RDD": { - "blockchain": "RDD", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 182, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "rates": [ + { + "borrowLimit": "192", + "currency": "BCH", + "dailyBorrowRate": "0.000548", + "hourlyBorrowRate": "0.000022833333333333" + }, + { + "borrowLimit": "72", + "currency": "BNB", + "dailyBorrowRate": "0.0006576", + "hourlyBorrowRate": "0.0000274" + }, + { + "borrowLimit": "24", + "currency": "BTC", + "dailyBorrowRate": "0.00008", + "hourlyBorrowRate": "0.000003333333333333" + }, + { + "borrowLimit": "7200000", + "currency": "DOGE", + "dailyBorrowRate": "0.0001752", + "hourlyBorrowRate": "0.0000073" + }, + { + "borrowLimit": "1080", + "currency": "ETC", + "dailyBorrowRate": "0.0003288", + "hourlyBorrowRate": "0.0000137" + } + ], + "tier": "TIER3" }, - "REEF": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4F37A4", - "humanType": "Sweep to Main Account", - "id": 475, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "806.48399252" + { + "rates": [ + { + "borrowLimit": "240", + "currency": "BCH", + "dailyBorrowRate": "0.0004795", + "hourlyBorrowRate": "0.000019979166666666" + }, + { + "borrowLimit": "90", + "currency": "BNB", + "dailyBorrowRate": "0.0005754", + "hourlyBorrowRate": "0.000023975" + }, + { + "borrowLimit": "30", + "currency": "BTC", + "dailyBorrowRate": "0.00007", + "hourlyBorrowRate": "0.000002916666666666" + }, + { + "borrowLimit": "9000000", + "currency": "DOGE", + "dailyBorrowRate": "0.0001533", + "hourlyBorrowRate": "0.0000063875" + }, + { + "borrowLimit": "1350", + "currency": "ETC", + "dailyBorrowRate": "0.0002877", + "hourlyBorrowRate": "0.0000119875" + } + ], + "tier": "TIER4" + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/collateralInfo": { + "GET": [ + { + "data": [ + { + "collateralRate": "0.95", + "currency": "BTC", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "REN": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "C2C2C5", - "humanType": "Sweep to Main Account", - "id": 367, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "33.49173907" + { + "collateralRate": "0.9", + "currency": "DOGE", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "REPV2": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "553580", - "humanType": "Sweep to Main Account", - "id": 437, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.94270579" + { + "collateralRate": "0.9", + "currency": "LTC", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "RFUEL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5786EB", - "humanType": "Sweep to Main Account", - "id": 440, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "382.11635453" - }, - "RIC": { - "blockchain": "RIC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 183, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "collateralRate": "1", + "currency": "USDT", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "RING": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "9D40B2", - "humanType": "Sweep to Main Account", - "id": 383, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "292.47729181" + { + "collateralRate": "0.85", + "currency": "XRP", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "RLC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F0D04A", - "humanType": "Sweep to Main Account", - "id": 531, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.15124960" + { + "collateralRate": "0.95", + "currency": "ETH", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "ROOK": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "BDBDBD", - "humanType": "Sweep to Main Account", - "id": 466, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.10400690" + { + "collateralRate": "0.8", + "currency": "ETC", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "RSR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "646665", - "humanType": "Sweep to Main Account", - "id": 411, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "413.46942258" + { + "collateralRate": "0.85", + "currency": "BCH", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "RUNE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 1, - "hexColor": "66DCD8", - "humanType": "Sweep to Main Account", - "id": 534, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.95771795" - }, - "RZR": { - "blockchain": "RZR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 184, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SAL": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "EB4034", - "humanType": "Sweep to Main Account", - "id": 423, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.06573000" + { + "collateralRate": "0.85", + "currency": "TRX", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "SAND": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4BAFF2", - "humanType": "Sweep to Main Account", - "id": 434, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "30.27667841" - }, - "SBD": { - "blockchain": "SBD", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "poloniex", - "disabled": 1, - "frozen": 0, - "hexColor": "171FC9", - "humanType": "Payment ID", - "id": 282, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "collateralRate": "0.8", + "currency": "MATIC", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.15" }, - "SBREE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "57AEC9", - "humanType": "Sweep to Main Account", - "id": 396, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.58300000" - }, - "SC": { - "blockchain": "SC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1ED660", - "humanType": "BTC Clone", - "id": 268, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 8, - "name": "", - "parentChain": null, - "txFee": "10.00000000" - }, - "SDC": { - "blockchain": "SDC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 185, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "collateralRate": "0.9", + "currency": "BNB", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.1" }, - "SENSO": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "848484", - "humanType": "Sweep to Main Account", - "id": 454, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "35.54201037" + { + "collateralRate": "0.8", + "currency": "SOL", + "initialMarginRate": "0.5", + "maintenanceMarginRate": "0.15" + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/markPrice": { + "GET": [ + { + "data": [ + { + "markPrice": "0.000015217", + "symbol": "SHIB_USDT", + "time": "1720110225903" }, - "SFI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B54F3D", - "humanType": "Sweep to Main Account", - "id": 467, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.02473439" + { + "markPrice": "5.837", + "symbol": "DOT_USDT", + "time": "1720110225909" }, - "SHIB": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FA931E", - "humanType": "Sweep to Main Account", - "id": 509, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2586075.91911765" - }, - "SHIBE": { - "blockchain": "SHIBE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 186, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SHOPX": { - "blockchain": "SHOPX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 187, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SILK": { - "blockchain": "SILK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 188, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SJCX": { - "blockchain": "SJCX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 189, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "3.00000000" - }, - "SLR": { - "blockchain": "SLR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 190, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SMC": { - "blockchain": "SMC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 191, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "markPrice": "0.0002412", + "symbol": "OMNI_BTC", + "time": "1720110225906" }, - "SNT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "4360DF", - "humanType": "Sweep to Main Account", - "id": 300, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "420.98027860" + { + "markPrice": "0.0463", + "symbol": "CLV_USDT", + "time": "1720110225905" }, - "SNX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1D1B30", - "humanType": "Sweep to Main Account", - "id": 335, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "3.33191724" - }, - "SOC": { - "blockchain": "SOC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 192, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SPA": { - "blockchain": "SPA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 193, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SQL": { - "blockchain": "SQL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 194, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SRCC": { - "blockchain": "SRCC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 195, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SRG": { - "blockchain": "SRG", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 196, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "markPrice": "3.207", + "symbol": "ZRO_USDT", + "time": "1720110225908" + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/price": { + "GET": [ + { + "data": [ + { + "dailyChange": "0.00", + "price": "0.0000000365", + "symbol": "BTS_BTC", + "time": 1719677307066, + "ts": 1719677307081 }, - "SRM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "AFE4EF", - "humanType": "Sweep to Main Account", - "id": 487, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2.82173789" - }, - "SSD": { - "blockchain": "SSD", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 197, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "dailyChange": "-0.0588", + "price": "0.000384", + "symbol": "DASH_BTC", + "time": 1719858347840, + "ts": 1719858347847 }, - "STAKE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "61A8A7", - "humanType": "Sweep to Main Account", - "id": 371, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.95571916" - }, - "STEEM": { - "blockchain": "STEEM", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "poloniex", - "disabled": 0, - "frozen": 0, - "hexColor": "5F00DE", - "humanType": "Payment ID", - "id": 281, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 50, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "dailyChange": "-0.0199", + "price": "0.00000197", + "symbol": "DOGE_BTC", + "time": 1719869746438, + "ts": 1719869746447 }, - "STORJ": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2683FF", - "humanType": "Sweep to Main Account", - "id": 297, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "15.55983875" + { + "dailyChange": "-0.0207", + "price": "0.00118", + "symbol": "LTC_BTC", + "time": 1719865802397, + "ts": 1719865802407 }, - "STPT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "75A7D9", - "humanType": "Sweep to Main Account", - "id": 350, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "323.72702948" - }, - "STR": { - "blockchain": "STR", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "GCF7F72LNF3ODSJIIWPJWEVWX33VT2SVZSUQ5NMDKDLK3N2NFCUAUHPT", - "disabled": 0, - "frozen": 0, - "hexColor": "404040", - "humanType": "Payment ID", - "id": 198, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 2, - "name": "", - "parentChain": null, - "txFee": "0.00001000" - }, - "STRAT": { - "blockchain": "STRAT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "199FC5", - "humanType": "BTC Clone", - "id": 287, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 24, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SUM": { - "blockchain": "SUM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 199, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "SUN": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "ffd60a", - "humanType": "Sweep to Main Account", - "id": 200, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "SUNX": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FFD60A", - "humanType": "Sweep to Main Account", - "id": 542, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "1.00000000" + { + "dailyChange": "-0.0444", + "price": "0.000001443", + "symbol": "XLM_BTC", + "time": 1719863292533, + "ts": 1719863292543 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/markets/ticker24h": { + "GET": [ + { + "data": [ + { + "amount": "0.05958902", + "ask": "0.000192", + "askQuantity": "16.30", + "bid": "0.000189", + "bidQuantity": "19.75", + "close": "0.000191", + "closeTime": 1759092211836, + "dailyChange": "-0.0052", + "displayName": "BTC/USDT", + "high": "0.000192", + "low": "0.000188", + "markPrice": "0.000189", + "open": "0.000192", + "quantity": "313.44", + "startTime": 1759005780000, + "symbol": "BTC_USDT", + "tradeCount": 195, + "ts": 1759092211843 }, - "SUSHI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FF485A", - "humanType": "Sweep to Main Account", - "id": 414, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.55013125" + { + "amount": "0.066806043", + "ask": "0.000002108", + "askQuantity": "3677", + "bid": "0.000002105", + "bidQuantity": "7139", + "close": "0.000002078", + "closeTime": 1759067177981, + "dailyChange": "-0.0142", + "displayName": "DOGE/BTC", + "high": "0.000002108", + "low": "0.000002065", + "markPrice": "0.000002102", + "open": "0.000002108", + "quantity": "32123", + "startTime": 1758980760000, + "symbol": "DOGE_BTC", + "tradeCount": 31, + "ts": 1759067178857 }, - "SWAP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "479CF7", - "humanType": "Sweep to Main Account", - "id": 384, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "13.75062849" - }, - "SWARM": { - "blockchain": "SWARM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 201, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1000.00000000" + { + "amount": "0.03332093", + "ask": "0.000958", + "askQuantity": "19.56", + "bid": "0.000941", + "bidQuantity": "0.06", + "close": "0.000958", + "closeTime": 1759091023416, + "dailyChange": "0.001", + "displayName": "LTC/BTC", + "high": "0.000958", + "low": "0.000941", + "markPrice": "0.000955", + "open": "0.000957", + "quantity": "35.32", + "startTime": 1759004580000, + "symbol": "LTC_BTC", + "tradeCount": 24, + "ts": 1759091023859 }, - "SWFTC": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "BA8934", - "humanType": "Sweep to Main Account", - "id": 349, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "8341.19115380" - }, - "SWINGBY": { - "blockchain": "BNB", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2A358B", - "humanType": "Sweep to Main Account", - "id": 409, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "2.55059336" + { + "amount": "0", + "ask": "0.000003337", + "askQuantity": "82", + "bid": "0.000003221", + "bidQuantity": "42", + "close": "0.0000033", + "closeTime": 1758998016659, + "dailyChange": "0.00", + "displayName": "XLM/BTC", + "high": "0.0000033", + "low": "0.0000033", + "markPrice": "0.000003289", + "open": "0.0000033", + "quantity": "0", + "startTime": 1758911580000, + "symbol": "XLM_BTC", + "tradeCount": 0, + "ts": 1758998016849 }, - "SWRV": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "202427", - "humanType": "Sweep to Main Account", - "id": 425, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "28.13568631" - }, - "SXC": { - "blockchain": "SXC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 202, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "amount": "0", + "ask": "0.000000018", + "askQuantity": "1010", + "bid": "0.000000015", + "bidQuantity": "1199", + "close": "0.000000017", + "closeTime": 1758889805140, + "dailyChange": "0.00", + "displayName": "XEM/BTC", + "high": "0.000000017", + "low": "0.000000017", + "markPrice": "0.000000017", + "open": "0.000000017", + "quantity": "0", + "startTime": 1758803400000, + "symbol": "XEM_BTC", + "tradeCount": 0, + "ts": 1758889805843 + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/orders": { + "DELETE": [ + { + "data": [], + "queryString": "", + "bodyParams": "{\"accountTypes\":[\"SPOT\"],\"symbols\":[\"BTC_USDT\",\"ETH_USDT\"]}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "2d6WzlNaKhiNRfBkTYsNWN6vV/rfO6aJdbCWYJaz6co=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743967897456" + ] + } + } + ], + "GET": [ + { + "data": [ + { + "id": "24993088082542592", + "clientOrderId": "", + "symbol": "ELON_USDC", + "state": "NEW", + "accountType": "SPOT", + "side": "SELL", + "type": "MARKET", + "timeInForce": "GTC", + "quantity": "1.00", + "price": "0.00", + "avgPrice": "0.00", + "amount": "0.00", + "filledQuantity": "0.00", + "filledAmount": "0.00", + "createTime": 1646925216548, + "updateTime": 1646925216548, + "orderSource": "API", + "loan": false + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "5XGZgY574VQR5PIBAy7ASNlv1Ec279Q3tbqWtmZVr8o=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203663135" + ] + } + }, + { + "data": [ + { + "id": "24993088082542592", + "clientOrderId": "", + "symbol": "ELON_USDC", + "state": "NEW", + "accountType": "SPOT", + "side": "SELL", + "type": "MARKET", + "timeInForce": "GTC", + "quantity": "1.00", + "price": "0.00", + "avgPrice": "0.00", + "amount": "0.00", + "filledQuantity": "0.00", + "filledAmount": "0.00", + "createTime": 1646925216548, + "updateTime": 1646925216548, + "orderSource": "API", + "loan": false + } + ], + "queryString": "direction=NEXT\u0026from=24993088082542592\u0026limit=10\u0026side=SELL\u0026symbol=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "5XGZgY574VQR5PIBAy7ASNlv1Ec279Q3tbqWtmZVr8o=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203663135" + ] + } + }, + { + "data": null, + "queryString": "direction=NEXT\u0026limit=10\u0026symbol=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "S8CMKEXIdLq6wh4MSNGGWZdt9zM5KdnuoOcZi9Vly+A=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760168101625" + ] + } + } + ], + "POST": [ + { + "data": { + "id": "29772698821328896", + "clientOrderId": "1234Abc" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"type\":\"MARKET\",\"amount\":\"100\",\"price\":\"100000.5\",\"timeInForce\":\"GTC\",\"clientOrderId\":\"1234Abc\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "5ZAw+roGshoL3o91+XBQoNayuX+ZxUBkMu9e/Srdt9M=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759182889740" + ] + } + }, + { + "data": { + "id": "29772698821328896", + "clientOrderId": "1234Abc" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"type\":\"MARKET\",\"accountType\":\"SPOT\",\"amount\":\"10000000\",\"price\":\"10\",\"slippageTolerance\":\"0\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "5ZAw+roGshoL3o91+XBQoNayuX+ZxUBkMu9e/Srdt9M=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759182889740" + ] + } + } + ] + }, + "/orders/123": { + "DELETE": [ + { + "data": { + "code": 200, + "message": "" + }, + "queryString": "", + "bodyParams": "{}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "LLn0WtbDmJt3dP29NCPJ/kjeFwMHePHleJ2kor7pzfc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760126739143" + ] + } + } + ] + }, + "/orders/1234": { + "GET": [ + { + "data": { + "code": 21301, + "message": "Order not exists" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "x9aooUcMzP5XQyNx/uoUmBdKFxGntThqsp9XN+VXHd0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760129149324" + ] + } + } + ], + "PUT": [ + { + "data": { + "id": "29772698821328896", + "clientOrderId": "1234Abc" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "8m4n2/KOedAaH396EE1OZzrsLe+EICrdGomdFAGLGmU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759183330720" + ] + } + } + ] + }, + "/orders/1234/trades": { + "GET": [ + { + "data": [ + { + "id": "68561226", + "symbol": "LINK_USDT", + "accountType": "SPOT", + "orderId": "30249408733945856", + "side": "BUY", + "type": "LIMIT", + "matchRole": "MAKER", + "createTime": 1648200366864, + "price": "3.1", + "quantity": "1", + "amount": "3.1", + "feeCurrency": "LINK", + "feeAmount": "0.00145", + "pageId": "30341456333942784", + "clientOrderId": "" + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "9+wMmOjFhQzfkHctFoS+wbRa0Qu45dC9Nsxi0uX5yyY=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760129148958" + ] + } + } + ] + }, + "/orders/12345": { + "GET": [ + { + "data": { + "id": "21934611974062080", + "clientOrderId": "123", + "symbol": "BTC_USDC", + "state": "NEW", + "accountType": "SPOT", + "side": "SELL", + "type": "LIMIT", + "timeInForce": "GTC", + "quantity": "1.00", + "price": "10.00", + "avgPrice": "0.00", + "amount": "0.00", + "filledQuantity": "0.00", + "filledAmount": "0.00", + "createTime": 1646196019020, + "updateTime": 1646196019020, + "orderSource": "API", + "loan": false, + "cancelReason": 0 + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "/npcIvDx41e86fhkszrX5JEZhYeCh11c1qNPW1ShFM4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970774" + ] + } + } + ] + }, + "/orders/12345536545645": { + "DELETE": [ + { + "data": { + "id": "21934611974062080", + "clientOrderId": "123", + "symbol": "TRX_USDC", + "state": "NEW", + "accountType": "SPOT", + "side": "SELL", + "type": "LIMIT", + "timeInForce": "GTC", + "quantity": "1.00", + "price": "10.00", + "avgPrice": "0.00", + "amount": "0.00", + "filledQuantity": "0.00", + "filledAmount": "0.00", + "createTime": 1646196019020, + "updateTime": 1646196019020, + "orderSource": "API", + "loan": false, + "cancelReason": 0 + }, + "queryString": "", + "bodyParams": "{}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "+Ri/71SAvgnGCA/WARlt1o+pRxKj7hO5m5lhKvW+j18=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759091754121" + ] + } + } + ], + "GET": [ + { + "data": { + "code": 21301, + "message": "Order not exists" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "/npcIvDx41e86fhkszrX5JEZhYeCh11c1qNPW1ShFM4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970774" + ] + } + } + ] + }, + "/orders/13123242323/trades": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "qMUuyj+ZNACbKo49qArvFAQLRlJgrmF3jhRbY6Y3q8A=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970356" + ] + } + } + ] + }, + "/orders/1337": { + "PUT": [ + { + "data": { + "id": "21934611974062080", + "clientOrderId": "123", + "symbol": "TRX_USDC", + "state": "NEW", + "accountType": "SPOT", + "side": "SELL", + "type": "LIMIT", + "timeInForce": "GTC", + "quantity": "1.00", + "price": "10.00", + "avgPrice": "0.00", + "amount": "0.00", + "filledQuantity": "0.00", + "filledAmount": "0.00", + "createTime": 1646196019020, + "updateTime": 1646196019020, + "orderSource": "API", + "loan": false, + "cancelReason": 0 + }, + "queryString": "", + "bodyParams": "{\"clientOrderId\":\"\",\"price\":\"1337\",\"type\":\"\\\"LIMIT\\\"\",\"timeInForce\":\"GTC\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "rW9SgCnJrXRT9f8fhe567t7qQxzTqcmlTIcgRJbxsic=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760099967774" + ] + } + } + ] + }, + "/orders/29772698821328896": { + "PUT": [ + { + "data": { + "id": "29772698821328896", + "clientOrderId": "1234Abc" + }, + "queryString": "", + "bodyParams": "{\"clientOrderId\":\"1234Abc\",\"price\":\"18000\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "hXNGjb9Tur4SdNMAnGiByWoXeCmummmEQXgyzxVFMCE=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760090250716" + ] + } + } + ] + }, + "/orders/batch": { + "POST": [ + { + "data": [ + { + "id": "2977269882132774", + "clientOrderId": "" + }, + { + "id": "29772698821328896", + "clientOrderId": "1234Abc" + }, + { + "code": 21709, + "message": "Low available balance", + "clientOrderId": "" + }, + { + "code": 21312, + "message": "Client order id repeat", + "clientOrderId": "456Xyz" + } + ], + "queryString": "", + "bodyParams": "[{\"symbol\":\"TRX_USDT\",\"side\":\"BUY\",\"type\":\"MARKET\",\"amount\":\"1\",\"price\":\"40000.5\",\"timeInForce\":\"GTC\",\"clientOrderId\":\"1234Abc\"},{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"amount\":\"100\"},{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"type\":\"LIMIT\",\"quantity\":\"100\",\"price\":\"40000.5\",\"timeInForce\":\"IOC\",\"clientOrderId\":\"1234Abc\"},{\"symbol\":\"ETH_USDT\",\"side\":\"BUY\",\"amount\":\"1000\"},{\"symbol\":\"TRX_USDT\",\"side\":\"SELL\",\"type\":\"LIMIT\",\"quantity\":\"15000\",\"price\":\"0.0623423423\",\"timeInForce\":\"IOC\",\"clientOrderId\":\"456Xyz\"}]", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "lV6g0s8iNYyvAeJ6r13ZjFxBRTz7PTvje9YB7FJfsGA=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1768935429072" + ] + } + } + ] + }, + "/orders/cancelByIds": { + "DELETE": [ + { + "data": [ + { + "orderId": "12345", + "clientOrderId": "33344", + "state": "PENDING_CANCEL", + "code": 200, + "message": "" }, - "SXP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EC6B47", - "humanType": "Sweep to Main Account", - "id": 373, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "5.63971216" - }, - "SYNC": { - "blockchain": "SYNC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 203, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00010000" - }, - "SYS": { - "blockchain": "SYS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "2A448C", - "humanType": "BTC Clone", - "id": 204, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "TAC": { - "blockchain": "TAC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 205, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "TAI": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "1062F7", - "humanType": "Sweep to Main Account", - "id": 418, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "orderId": "67890", + "clientOrderId": "myId-1", + "state": "PENDING_CANCEL", + "code": 200, + "message": "" + } + ], + "queryString": "", + "bodyParams": "{\"clientOrderIds\":[\"5678\"],\"orderIds\":[\"1234\"]}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "pR/0/oW7M+M5WPsCygE7YphaA934SX0OGxhKBPhcKeM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759177951020" + ] + } + } + ] + }, + "/orders/history": { + "GET": [ + { + "data": null, + "queryString": "accountType=SPOT\u0026limit=100\u0026side=BUY\u0026type=LIMIT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "FWE2Qh0xO3OU61pa8rEFWVcImHm3l3fsXRPCJ6WFmN4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742738478103" + ] + } + }, + { + "data": null, + "queryString": "accountType=SPOT\u0026limit=100\u0026side=SELL\u0026type=LIMIT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "+s7FWBnavPvFpYU+VBHU8PCTpdzcRQW7O/AAovNzu2w=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743973442485" + ] + } + }, + { + "data": [ + { + "id": 35490370041151490, + "clientOrderId": "Try1", + "symbol": "TRX_USDC", + "accountType": "SPOT", + "side": "SELL", + "type": "LIMIT_MAKER", + "timeInForce": "GTC", + "price": "3333", + "avgPrice": "0", + "quantity": "5", + "amount": "0", + "filledQuantity": "0", + "filledAmount": "0", + "state": "CANCELED", + "orderSource": "API", + "createTime": 1649427963597, + "updateTime": 1649427963597, + "loan": false, + "cancelReason": 1 + } + ], + "queryString": "accountType=SPOT\u0026limit=10\u0026symbol=BTC_USDT\u0026types=LIMIT%2CLIMIT_MAKER", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "+s7FWBnavPvFpYU+VBHU8PCTpdzcRQW7O/AAovNzu2w=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743973442485" + ] + } + }, + { + "data": [ + { + "id": 35490370041151490, + "clientOrderId": "Try1", + "symbol": "BTC_USDT", + "accountType": "SPOT", + "side": "SELL", + "type": "LIMIT_MAKER", + "timeInForce": "GTC", + "price": "3333", + "avgPrice": "0", + "quantity": "5", + "amount": "0", + "filledQuantity": "0", + "filledAmount": "0", + "state": "FAILED", + "orderSource": "API", + "createTime": 1649427963597, + "updateTime": 1649427963597, + "loan": false, + "cancelReason": 1 + } + ], + "queryString": "accountType=SPOT\u0026direction=NEXT\u0026endTime=1765290174763\u0026from=228530000\u0026hideCancel=true\u0026limit=10\u0026side=SELL\u0026startTime=1764930174763\u0026states=FAILED\u0026symbol=BTC_USDT\u0026type=LIMIT_MAKER", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "+s7FWBnavPvFpYU+VBHU8PCTpdzcRQW7O/AAovNzu2w=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743973442485" + ] + } + } + ] + }, + "/orders/killSwitch": { + "POST": [ + { + "data": { + "cancellationTime": "1743968899041", + "startTime": "1743968869041" + }, + "queryString": "", + "bodyParams": "{\"timeout\":\"30\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "hG0dZC5WEYPqHwZfFa8KPV7Ca876xuliC/02eH0Shb0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968868231" + ] + } + }, + { + "data": { + "startTime": "1665456160", + "cancellationTime": "0" + }, + "queryString": "", + "bodyParams": "{\"timeout\":\"-1\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "hG0dZC5WEYPqHwZfFa8KPV7Ca876xuliC/02eH0Shb0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968868231" + ] + } + } + ] + }, + "/orders/killSwitchStatus": { + "GET": [ + { + "data": { + "cancellationTime": "1743968899041", + "startTime": "1743968869041" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "YLwvEcYFFbmx0kJpclZiK8MxQ6vQgLFZC8RM7RmbjNw=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968880346" + ] + } + } + ] + }, + "/smartorders": { + "DELETE": [ + { + "data": [ + { + "orderId": "1111111111", + "clientOrderId": "aaaaa", + "state": "CANCELED", + "code": 200, + "message": "SUCCESS" }, - "TEND": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FF9E03", - "humanType": "Sweep to Main Account", - "id": 385, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "306.38343236" - }, - "TOR": { - "blockchain": "TOR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 206, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + { + "orderId": "222222222", + "clientOrderId": "", + "state": "CANCELED", + "code": 200, + "message": "SUCCESS" + } + ], + "queryString": "", + "bodyParams": "{\"orderTypes\":[\"STOP_LIMIT\"],\"symbols\":[\"BTC_USDT\"]}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "dV4tXkbzo4ZvFnpDkMca2Z8patXhvwUEcmn/YEsqqjs=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968911176" + ] + } + } + ], + "GET": [ + { + "data": null, + "queryString": "limit=10\u0026types=TRAILING_STOP%2CTRAILING_STOP_LIMIT%2CSTOP%2CSTOP_LIMIT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "myAnjmC+YpfaGjzLwsuzyhhSgEd/5wT0OOXZIjssT0g=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743582151201" + ] + } + } + ], + "POST": [ + { + "data": { + "id": "10000009", + "clientOrderId": "999999910" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"accountType\":\"SPOT\",\"type\":\"TRAILING_STOP_LIMIT\",\"price\":\"10\",\"stopPrice\":\"11\",\"quantity\":\"10000000\",\"clientOrderId\":\"999999910\",\"trailingOffset\":\"5%\",\"limitOffset\":\"1%\",\"operator\":\"GTC\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "dV4tXkbzo4ZvFnpDkMca2Z8patXhvwUEcmn/YEsqqjs=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968911176" + ] + } + }, + { + "data": { + "id": "10000009", + "clientOrderId": "999999910" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"timeInForce\":\"GTC\",\"type\":\"STOP_LIMIT\",\"price\":\"100000.5\",\"quantity\":\"100\",\"clientOrderId\":\"1234Abc\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "dV4tXkbzo4ZvFnpDkMca2Z8patXhvwUEcmn/YEsqqjs=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968911176" + ] + } + }, + { + "data": { + "id": "10000009", + "clientOrderId": "999999910" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"accountType\":\"SPOT\",\"type\":\"TRAILING_STOP\",\"price\":\"10\",\"stopPrice\":\"11\",\"quantity\":\"10000000\",\"clientOrderId\":\"999999910\",\"trailingOffset\":\"5%\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "dV4tXkbzo4ZvFnpDkMca2Z8patXhvwUEcmn/YEsqqjs=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968911176" + ] + } + }, + { + "data": { + "clientOrderId": "55667798abcd", + "id": "502143097648869376" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"timeInForce\":\"GTC\",\"type\":\"TRAILING_STOP_LIMIT\",\"price\":\"100000.5\",\"quantity\":\"100\",\"clientOrderId\":\"55667798abcd\",\"trailingOffset\":\"2%\",\"limitOffset\":\"1%\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "t9ziufRKQlrLUISTEUV5gAzRrwEFAxIJoy7zRCaHnb0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760686643056" + ] + } + }, + { + "data": { + "clientOrderId": "55667798abcd", + "id": "502143097648869376" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"accountType\":\"SPOT\",\"type\":\"STOP_LIMIT\",\"price\":\"10\",\"stopPrice\":\"11\",\"quantity\":\"10000000\",\"operator\":\"LTE\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "t9ziufRKQlrLUISTEUV5gAzRrwEFAxIJoy7zRCaHnb0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760686643056" + ] + } + }, + { + "data": { + "clientOrderId": "55667798abcd", + "id": "502143097648869376" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"accountType\":\"SPOT\",\"type\":\"TRAILING_STOP\",\"price\":\"10\",\"stopPrice\":\"11\",\"quantity\":\"10000000\",\"clientOrderId\":\"999999910\",\"trailingOffset\":\"5%\",\"operator\":\"LTE\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "t9ziufRKQlrLUISTEUV5gAzRrwEFAxIJoy7zRCaHnb0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760686643056" + ] + } + } + ] + }, + "/smartorders/123": { + "DELETE": [ + { + "data": { + "code": 200, + "message": "", + "data": { + "clientOrderId": "this-is-the-client-order-id", + "code": 200, + "message": "", + "orderId": "123", + "state": "" + } + }, + "queryString": "", + "bodyParams": "{}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "V5UN7wqorXtSAJN6Wvku8ju1CUW94iMgpoBjW3DHbBc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742815285115" + ] + } + } + ] + }, + "/smartorders/123313413": { + "DELETE": [ + { + "data": { + "code": 200, + "message": "", + "data": { + "orderId": "123313413", + "clientOrderId": "88888", + "state": "CANCELED", + "code": 200, + "message": "" + } + }, + "queryString": "", + "bodyParams": "{}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "QbX0FbmOYK2HwQFq/Xcc+QQ0eUeJxFVVqkAE4LYglEQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760094893731" + ] + } + } + ], + "GET": [ + { + "data": [ + { + "id": "14368195657859072", + "clientOrderId": "18113", + "symbol": "BTC_USDT", + "state": "TRIGGERED", + "accountType": "SPOT", + "side": "BUY", + "type": "STOP", + "timeInForce": "GTC", + "quantity": "0.2", + "price": "41920", + "amount": "10", + "stopPrice": "41946", + "createTime": 1644392044793, + "updateTime": 0, + "triggeredOrder": { + "id": "24106600339865600", + "clientOrderId": "18113", + "symbol": "BTC_USDT", + "state": "PARTIALLY_FILLED", + "accountType": "SPOT", + "side": "BUY", + "type": "MARKET", + "timeInForce": "GTC", + "quantity": "0.00", + "price": "0.00", + "avgPrice": "39991.10", + "amount": "10.00", + "filledQuantity": "0.00025005", + "filledAmount": "9.999774555", + "createTime": 1646713861400, + "updateTime": 1646713861400 + } + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "z/wSNMNFy3CkKtmQxFt+t2pOFzeHKvge5g4jxvgWF8E=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970545" + ] + } + } + ] + }, + "/smartorders/1234": { + "GET": [ + { + "data": [ + { + "id": "1234", + "clientOrderId": "", + "symbol": "BTC_USDT", + "state": "PENDING_NEW", + "accountType": "SPOT", + "side": "BUY", + "type": "STOP_LIMIT", + "timeInForce": "GTC", + "quantity": "0.036", + "price": "1", + "amount": "0.00", + "stopPrice": "3750.00", + "createTime": 1630832295888, + "updateTime": 1630832295888 + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "UOcfNpq3xKYOEC1EseDYiXBKYHOovCj6W1gmI0I84Hc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760129149846" + ] + } + } + ] + }, + "/smartorders/1337": { + "PUT": [ + { + "data": { + "code": 200, + "message": "", + "data": { + "id": "1337", + "clientOrderId": "1234Abc" + } + }, + "queryString": "", + "bodyParams": "{\"price\":\"1337\",\"type\":\"STOP_LIMIT\",\"timeInForce\":\"GTC\",\"proceedOnFailure\":\"true\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "Ihm+6Hy71J0aRF51RjA8aPmxDnN5aDDsid0nzGOizEQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968951008" + ] + } + } + ] + }, + "/smartorders/29772698821328896": { + "PUT": [ + { + "data": { + "code": 200, + "message": "", + "data": { + "id": "29772698821328896", + "clientOrderId": "1234Abc" + } + }, + "queryString": "", + "bodyParams": "{\"clientOrderId\":\"1234Abc\",\"price\":\"18000\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "Ihm+6Hy71J0aRF51RjA8aPmxDnN5aDDsid0nzGOizEQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743968951008" + ] + } + } + ] + }, + "/smartorders/cancelByIds": { + "DELETE": [ + { + "data": [ + { + "orderId": "9876543", + "clientOrderId": "88888", + "state": "CANCELED", + "code": 200, + "message": "" }, - "TORN": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "ADFAC4", - "humanType": "Sweep to Main Account", - "id": 496, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.40568519" + { + "orderId": "111222333", + "clientOrderId": "myId-2", + "state": "CANCELED", + "code": 200, + "message": "" + } + ], + "queryString": "", + "bodyParams": "{\"symbol\":\"\",\"ordIds\":[\"1234\"],\"clOrdIds\":[\"5678\"]}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "nslIRCTPjh8nNSMxPMtj9QxrBPGOLpj4EVfSKsBQe7I=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759175937783" + ] + } + } + ] + }, + "/smartorders/history": { + "GET": [ + { + "data": [ + { + "id": "25444163851911168", + "clientOrderId": "", + "symbol": "BTC_USDT", + "state": "CANCELED", + "accountType": "SPOT", + "side": "BUY", + "type": "STOP_LIMIT", + "timeInForce": "GTC", + "quantity": "2", + "price": "100", + "amount": "200", + "stopPrice": "125", + "createTime": 1647032761392, + "updateTime": 1647032874275 + } + ], + "queryString": "accountType=SPOT\u0026direction=PRE\u0026endTime=1765290174763\u0026from=12323123\u0026hideCancel=true\u0026limit=100\u0026side=SELL\u0026startTime=1764930174763\u0026symbol=BTC_USDT\u0026type=LIMIT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "wqrMHpazrPftzGuQaTR/0/37FNqBGJDqryHNBWZigxM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754251060127" + ] + } + }, + { + "data": [ + { + "id": "25444163851911168", + "clientOrderId": "", + "symbol": "BTC_USDT", + "state": "CANCELED", + "accountType": "SPOT", + "side": "BUY", + "type": "STOP_LIMIT", + "timeInForce": "GTC", + "quantity": "2", + "price": "100", + "amount": "200", + "stopPrice": "125", + "createTime": 1647032761392, + "updateTime": 1647032874275 + } + ], + "queryString": "accountType=SPOT\u0026limit=100\u0026side=SELL\u0026type=STOP_LIMIT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "wqrMHpazrPftzGuQaTR/0/37FNqBGJDqryHNBWZigxM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754251060127" + ] + } + } + ] + }, + "/subaccounts": { + "GET": [ + { + "data": [ + { + "accountId": "f406e865-c5cd-4757-91ea-45fb041c87ad", + "accountName": "Primary Account", + "accountState": "ACTIVE", + "isPrimary": "true" + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "vZ16bKCYVk1BmxvDFx/4OjHmUX2E4DI4+oOMA5VkV3M=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203663530" + ] + } + } + ] + }, + "/subaccounts/2d45301d-5f08-4a2b-a763-f9199778d854/balances": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "T6bZ6yQTAqCLdU1dCSb5nBsoaycU/AWYP0171aYwjQU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742834680509" + ] + } + } + ] + }, + "/subaccounts/balances": { + "GET": [ + { + "data": [ + { + "accountId": "32b323201-e832-2270-78t4-e25ak408945", + "accountName": "primary Acct", + "accountType": "SPOT", + "isPrimary": "true", + "balances": [ + { + "currency": "USDT", + "available": "100000233", + "hold": "0", + "maxAvailable": "100000233" + }, + { + "currency": "LTC", + "available": "999899455.8625", + "hold": "0", + "maxAvailable": "999899455.8625" + } + ] + }, + { + "accountId": "23422vdd1-e832-2270-78t4-2342cl2292", + "accountName": "sub1", + "accountType": "SPOT", + "isPrimary": "false", + "balances": [ + { + "currency": "USDT", + "available": "500", + "hold": "0", + "maxAvailable": "500" + }, + { + "currency": "TRX", + "available": "9991.234", + "hold": "0", + "maxAvailable": "9991.234" + } + ] + }, + { + "accountId": "56322vdd1-e832-2270-jh45-2342cl6789", + "accountName": "sub2", + "accountType": "SPOT", + "isPrimary": "false", + "balances": [ + { + "currency": "BTC", + "available": "20000.234", + "hold": "0", + "maxAvailable": "20000.234" + }, + { + "currency": "TRX", + "available": "12991.234", + "hold": "0", + "maxAvailable": "129991.234" + } + ] + }, + { + "accountId": "32b323201-e832-2270-78t4-e25ak408945", + "accountName": "string", + "accountType": "FUTURES", + "isPrimary": "true", + "balances": [ + { + "currency": "USDT", + "accountEquity": "200017", + "unrealisedPNL": "0", + "marginBalance": "200017", + "positionMargin": "0", + "orderMargin": "0", + "frozenFunds": "0", + "availableBalance": "200017", + "pnl": "0.0" + } + ] + }, + { + "accountId": "23422vdd1-e832-2270-78t4-2342cl2292", + "accountName": "sub1", + "accountType": "FUTURES", + "isPrimary": "false", + "balances": [ + { + "currency": "USDT", + "accountEquity": "100", + "unrealisedPNL": "0", + "marginBalance": "100", + "positionMargin": "0", + "orderMargin": "0", + "frozenFunds": "0", + "availableBalance": "100", + "pnl": "0.0" + } + ] + } + ], + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "bjP3Rchqye90vAjV2Q+VS26jgr0Ynnou0WPdIvZT/8o=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250972735" + ] + } + } + ] + }, + "/subaccounts/transfer": { + "GET": [ + { + "data": [ + { + "id": "228535117", + "fromAccountId": "32b323201-e832-2270-78t4-e25ak408945", + "fromAccountName": "primary Acct", + "fromAccountType": "SPOT", + "toAccountId": "23422vdd1-e832-2270-78t4-2342cl2292", + "toAccountName": "sub1", + "toAccountType": "SPOT", + "currency": "USDT", + "amount": "111", + "state": "SUCCESS", + "createTime": 1670980921113 }, - "TRADE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "B6E6FC", - "humanType": "Sweep to Main Account", - "id": 386, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, + { + "id": "1328535117", + "fromAccountId": "32b323201-e832-2270-78t4-e25ak408945", + "fromAccountName": "primary Acct", + "fromAccountType": "SPOT", + "toAccountId": "23422vdd1-e832-2270-78t4-2342cl2292", + "toAccountName": "sub2", + "toAccountType": "FUTURES", + "currency": "USDT", + "amount": "111", + "state": "SUCCESS", + "createTime": 1670980921113 + } + ], + "queryString": "currency=BTC\u0026fromAccountID=32b323201-e832-2270-78t4-e25ak408941\u0026fromAccountType=SPOT\u0026toAccountID=32b323201-e832-2270-78t4-e25ak408946\u0026toAccountType=FUTURES", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "2PkHzshF+6t9yhDKv9Tk5iBAQPKew30RLYSV+WqOkMg=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668975237" + ] + } + }, + { + "data": null, + "queryString": "currency=BTC\u0026endTime=1764668001864\u0026startTime=1764664401864", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "ZtsG//mn5FehAfpvhTGU9QKPj8cXIoMeIahXtFHpn94=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668975636" + ] + } + }, + { + "data": null, + "queryString": "currency=BTC\u0026from=1\u0026limit=100\u0026startTime=1764664401864", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "y292OO1nhjgO9MAfOcYYOzx5YGEdV3BTR7/NOWSHccQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668976024" + ] + } + }, + { + "data": null, + "queryString": "currency=BTC\u0026direction=NEXT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "5DgOGJ3sdP2xyS8aQc2ffYyxB00IF7LNvximjQkpwgc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764668976368" + ] + } + } + ], + "POST": [ + { + "data": { + "code": 250020, + "message": "No permission" + }, + "queryString": "", + "bodyParams": "{\"currency\":\"BTC\",\"amount\":\"1\",\"fromAccountId\":\"329455537441832960\",\"fromAccountType\":\"SPOT\",\"toAccountId\":\"329455537441832961\",\"toAccountType\":\"SPOT\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "cSSQ63OfTti2OkUx4a3qBNKTEh1BPXq3upGVJJJ31GU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742834853631" + ] + } + } + ] + }, + "/subaccounts/transfer/329455537441832960": { + "GET": [ + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "2bnywGyNeoyYHvmNm97e2Ef5aQRQCA2City7XiNkJV4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203665228" + ] + } + } + ] + }, + "/timestamp": { + "GET": [ + { + "data": { + "serverTime": 1720099170739 + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/trades": { + "GET": [ + { + "data": null, + "queryString": "endTime=1736208000000\u0026startTime=1736121600000", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "yDc8qD2tIqHcT0v/f4tsfl7bpudBRw+ST1GFWDVWrAQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743672729803" + ] + } + }, + { + "data": null, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "xiqPXIVCz69M8Qd0c773xTGHtoWTjU/najY4irUqnnQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743935595122" + ] + } + }, + { + "data": null, + "queryString": "symbols=DYDX_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "gGeQpNlXfMoNwvUQ6q2dyQGhDgUWbCunu3jqQkMv3mA=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743937017073" + ] + } + }, + { + "data": null, + "queryString": "symbols=GROKCOIN_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "X96gWyEFCyj1W6YhmC2Xe+rlzJkxv/dyd083+uxOgoM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743937061848" + ] + } + }, + { + "data": null, + "queryString": "endTime=1764668001864\u0026startTime=1764664401864\u0026symbols=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "VEJr5yCfJrU9MRYWtDAmkxJEGG73OgydTDXBboA6+iY=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764669365720" + ] + } + }, + { + "data": null, + "queryString": "endTime=1764668001864\u0026from=1\u0026limit=100\u0026startTime=1764664401864\u0026symbols=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "w377IcDAXcJ0Vbyq1Hk0+xRhl4X1j1+9xrplqNTHqKc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764669366793" + ] + } + }, + { + "data": null, + "queryString": "direction=NEXT\u0026endTime=1764668001864\u0026from=10\u0026limit=100\u0026startTime=1764664401864\u0026symbols=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "4WqemjKNqzQVjnNbFiiaIxPSo0Ahre6zX7W9MMXZGR0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764669367276" + ] + } + }, + { + "data": null, + "queryString": "symbols=BTC_USDT", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "248sxZtaGo2HmRGik/9R+cdijxWEWDP2Uif6jECSGNo=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764669367714" + ] + } + } + ] + }, + "/v2/currencies": { + "GET": [ + { + "data": [ + { + "coin": "1CR", + "delisted": true, + "id": 1, "name": "", - "parentChain": null, - "txFee": "105.72327003" + "networkList": [ + { + "blockchain": "1CR", + "coin": "1CR", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": false, + "id": 1, + "minConfirm": 10000, + "name": "", + "withdrawFee": "0.01000000", + "withdrawMin": "-1", + "withdrawalEnable": false + } + ], + "tradeEnable": false }, - "TRB": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "82F8B1", - "humanType": "Sweep to Main Account", - "id": 394, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, + { + "coin": "AAVE", + "delisted": false, + "id": 446, "name": "", - "parentChain": null, - "txFee": "0.69955220" + "networkList": [ + { + "blockchain": "ETH", + "coin": "AAVE", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": true, + "id": 446, + "minConfirm": 64, + "name": "", + "withdrawFee": "0.36837766", + "withdrawMin": "-1", + "withdrawalEnable": true + } + ], + "supportBorrow": false, + "supportCollateral": false, + "tradeEnable": true }, - "TRU": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3166F6", - "humanType": "Sweep to Main Account", - "id": 479, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "38.41619571" + { + "coin": "ABI", + "delisted": false, + "id": 1598, + "name": "", + "networkList": [ + { + "blockchain": "SOL", + "coin": "ABI", + "currencyType": "address", + "decimals": 5, + "depositAddress": null, + "depositEnable": true, + "id": 1598, + "minConfirm": 300, + "name": "", + "withdrawFee": "0.00240000", + "withdrawMin": "0.00360000", + "withdrawalEnable": true + } + ], + "supportBorrow": false, + "supportCollateral": false, + "tradeEnable": true }, - "TRUMPWIN": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "D7352C", - "humanType": "Sweep to Main Account", - "id": 377, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "TRUST": { - "blockchain": "TRUST", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 207, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, + { + "coin": "ABY", + "delisted": true, + "id": 2, "name": "", - "parentChain": null, - "txFee": "0.01000000" + "networkList": [ + { + "blockchain": "ABY", + "coin": "ABY", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": false, + "id": 2, + "minConfirm": 10000, + "name": "", + "withdrawFee": "0.01000000", + "withdrawMin": "-1", + "withdrawalEnable": false + } + ], + "tradeEnable": false }, - "TRX": { - "blockchain": "TRX", - "childChains": [ - "TRXETH" + { + "coin": "AC", + "delisted": false, + "id": 1289, + "name": "", + "networkList": [ + { + "blockchain": "ETH", + "coin": "AC", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": true, + "id": 1289, + "minConfirm": 64, + "name": "", + "withdrawFee": "2056.81760345", + "withdrawMin": "-1", + "withdrawalEnable": true + } + ], + "supportBorrow": false, + "supportCollateral": false, + "tradeEnable": true + } + ], + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v2/currencies/BTC": { + "GET": [ + { + "data": { + "coin": "BTC", + "delisted": false, + "id": 28, + "name": "", + "networkList": [ + { + "blockchain": "BSC", + "coin": "BTCB", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": false, + "id": 581, + "minConfirm": 15, + "name": "", + "withdrawFee": "0.00003000", + "withdrawMin": "-1", + "withdrawalEnable": false + }, + { + "blockchain": "BTCMERLIN", + "coin": "BTCMERLIN", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": false, + "id": 1372, + "minConfirm": 64, + "name": "", + "withdrawFee": "0.00003000", + "withdrawMin": "-1", + "withdrawalEnable": false + }, + { + "blockchain": "TRX", + "coin": "BTCTRON", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": true, + "id": 445, + "minConfirm": 0, + "name": "", + "withdrawFee": "0.00004000", + "withdrawMin": "-1", + "withdrawalEnable": true + }, + { + "blockchain": "BTC", + "coin": "BTC", + "currencyType": "address", + "decimals": 8, + "depositAddress": null, + "depositEnable": true, + "id": 28, + "minConfirm": 2, + "name": "", + "withdrawFee": "0.00350000", + "withdrawMin": "-1", + "withdrawalEnable": true + } + ], + "supportBorrow": false, + "supportCollateral": true, + "tradeEnable": true + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v2/wallets/withdraw": { + "POST": [ + { + "data": { + "currency": "ETH", + "amount": "1.50", + "address": "0xbb8d0d7c346daecc2380dabaa91f3ccf8ae232fb4" + }, + "queryString": "", + "bodyParams": "{\"coin\":\"BTC\",\"network\":\"ERP\",\"amount\":\"1\",\"address\":\"bc1qk0jareu4jytc0cfrhr5wgshsq8\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "P/vq7oFw/yOSVG1zZHfK7ymz1sJNBkXK8whPu31IJ5M=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759093194968" + ] + } + }, + { + "data": { + "currency": "BTC", + "amount": "1.50", + "address": "0xbb8d0d7c346daecc2380dabaa91f3ccf8ae232fb4" + }, + "queryString": "", + "bodyParams": "{\"coin\":\"BTC\",\"network\":\"ETH\",\"amount\":\"1e-7\",\"address\":\"bc1qk0jareu4jytc0cfrhr5wgshsq8\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "P/vq7oFw/yOSVG1zZHfK7ymz1sJNBkXK8whPu31IJ5M=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759093194968" + ] + } + } + ] + }, + "/v3/account/balance": { + "GET": [ + { + "data": { + "code": 200, + "msg": "", + "data": { + "state": "NORMAL", + "eq": "959.581928139999996061", + "isoEq": "0", + "im": "5.28", + "mm": "1.32", + "mmr": "0.001375599061727448", + "upl": "-2.4", + "availMgn": "954.301928139999996061", + "cTime": "1690196536233", + "uTime": "1721902285120", + "details": [ + { + "ccy": "USDT", + "eq": "959.581928139999996061", + "isoEq": "0", + "avail": "961.981928139999996061", + "trdHold": "0", + "upl": "-2.4", + "isoAvail": "0", + "isoHold": "0", + "isoUpl": "0", + "im": "5.28", + "mm": "1.32", + "mmr": "0.001375599061727448", + "imr": "0.005502396246909794", + "cTime": "1717396712353", + "uTime": "1721902285120" + } + ] + } + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "CoKxd3OS4t7vOiffEcgz1KCM8MV1u48SKYY4gMOLsMM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1734008690771" + ] + } + } + ] + }, + "/v3/account/bills": { + "GET": [ + { + "data": { + "code": 200, + "data": [], + "msg": "" + }, + "queryString": "direct=NEXT\u0026eTime=1765290174763\u0026from=1\u0026limit=100\u0026sTime=1764930174763\u0026type=PNL", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "gSnuTBIfwwC5i/e/cWS9H/d8lfkgy/Ohbuw73I2D1zg=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754251050148" + ] + } + } + ] + }, + "/v3/market/allInstruments": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "alias": "", + "bAsset": ".PBNBUSDT", + "bCcy": "BTC", + "ctType": "LINEAR", + "ctVal": "0.1", + "iM": "0.02", + "lever": "10", + "limitMaxQty": "1000000", + "lotSz": 1, + "mM": "0.0115", + "mR": "2000", + "marketMaxQty": "2800", + "maxLever": "50", + "maxPx": "1000000", + "maxQty": "1000000", + "minPx": "0.001", + "minQty": "1", + "minSz": 1, + "oDate": "1620287590000", + "ordPxRange": "0.05", + "pxScale": "0.001,0.01,0.1,1,10", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "BTC_USDT_PERP", + "tSz": "0.001", + "tradableStartTime": "1620390600000", + "visibleStartTime": "1620390600000" + }, + { + "alias": "", + "bAsset": ".PTRXUSDT", + "bCcy": "TRX", + "ctType": "LINEAR", + "ctVal": "100", + "iM": "0.02", + "lever": "10", + "limitMaxQty": "1000000", + "lotSz": 1, + "mM": "0.0115", + "mR": "10000", + "marketMaxQty": "7500", + "maxLever": "50", + "maxPx": "1000000", + "maxQty": "1000000", + "minPx": "0.00001", + "minQty": "1", + "minSz": 1, + "oDate": "1607328129000", + "ordPxRange": "0.05", + "pxScale": "0.00001,0.0001,0.001,0.01,0.1", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "TRX_USDT_PERP", + "tSz": "0.00001", + "tradableStartTime": "1607430600000", + "visibleStartTime": "1607430600000" + }, + { + "alias": "", + "bAsset": ".PLTCUSDT", + "bCcy": "LTC", + "ctType": "LINEAR", + "ctVal": "0.01", + "iM": "0.02", + "lever": "10", + "limitMaxQty": "1000000", + "lotSz": 1, + "mM": "0.0115", + "mR": "30000", + "marketMaxQty": "100000", + "maxLever": "50", + "maxPx": "1000000", + "maxQty": "1000000", + "minPx": "0.01", + "minQty": "1", + "minSz": 1, + "oDate": "1614781681000", + "ordPxRange": "0.05", + "pxScale": "0.01,0.1,1,10,100", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "LTC_USDT_PERP", + "tSz": "0.01", + "tradableStartTime": "1614861000000", + "visibleStartTime": "1614861000000" + }, + { + "alias": "", + "bAsset": ".PAPTUSDT", + "bCcy": "APT", + "ctType": "LINEAR", + "ctVal": "1", + "iM": "0.05", + "lever": "10", + "limitMaxQty": "1000000", + "lotSz": 1, + "mM": "0.027", + "mR": "20000", + "marketMaxQty": "4000", + "maxLever": "20", + "maxPx": "1000000", + "maxQty": "1000000", + "minPx": "0.001", + "minQty": "1", + "minSz": 1, + "oDate": "1666681959000", + "ordPxRange": "0.05", + "pxScale": "0.001,0.01,0.1,1,10", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "APT_USDT_PERP", + "tSz": "0.001", + "tradableStartTime": "1666701000000", + "visibleStartTime": "1666701000000" + }, + { + "alias": "", + "bAsset": ".P1000PEPEUSDT", + "bCcy": "1000PEPE", + "ctType": "LINEAR", + "ctVal": "1000", + "iM": "0.05", + "lever": "10", + "limitMaxQty": "100000000", + "lotSz": 1, + "mM": "0.027", + "mR": "50000", + "marketMaxQty": "10000", + "maxLever": "20", + "maxPx": "100000000", + "maxQty": "100000000", + "minPx": "0.0000001", + "minQty": "1", + "minSz": 1, + "oDate": "1683536085000", + "ordPxRange": "0.05", + "pxScale": "0.0000001,0.000001,0.00001,0.0001,0.001", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "1000PEPE_USDT_PERP", + "tSz": "0.0000001", + "tradableStartTime": "1683549000000", + "visibleStartTime": "1683549000000" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "alias": "", + "bAsset": ".PBNBUSDT", + "bCcy": "BTC", + "ctType": "LINEAR", + "ctVal": "0.1", + "iM": "0.02", + "lever": "10", + "limitMaxQty": "1000000", + "lotSz": 1, + "mM": "0.0115", + "mR": "2000", + "marketMaxQty": "2800", + "maxLever": "50", + "maxPx": "1000000", + "maxQty": "1000000", + "minPx": "0.001", + "minQty": "1", + "minSz": 1, + "oDate": "1620287590000", + "ordPxRange": "0.05", + "pxScale": "0.001,0.01,0.1,1,10", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "BTC_USDT_PERP", + "tSz": "0.001", + "tradableStartTime": "1620390600000", + "visibleStartTime": "1620390600000" + } + ], + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/candles": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + [ + "110605.38", + "111749.99", + "111175.92", + "110663.42", + "666126.22428", + "5998", + "1799", + "1756857600000", + "1756879199999" ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "DC062B", - "humanType": "Sweep to Main Account", - "id": 315, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "TRXBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 330, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "28298210.05747126" - }, - "TRXBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 331, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "46.86556725" - }, - "TRXETH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EB332A", - "humanType": "Sweep to Main Account", - "id": 536, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": "TRX", - "txFee": "235.00000000" - }, - "TUSD": { - "blockchain": "ETH", - "childChains": [ - "TUSDTRON" + [ + "110504.3", + "111677.93", + "110665.78", + "111443.94", + "947722.36948", + "8530", + "1494", + "1756879200000", + "1756900799999" ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "0A2A64", - "humanType": "Sweep to Main Account", - "id": 332, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "28.13650599" - }, - "TUSDTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "0A2A64", - "humanType": "Sweep to Main Account", - "id": 507, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "TUSD", - "txFee": "0.01000000" - }, - "TWE": { - "blockchain": "TWE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 208, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "UIS": { - "blockchain": "UIS", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 209, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "ULTC": { - "blockchain": "ULTC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 210, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "UMA": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "ED5A52", - "humanType": "Sweep to Main Account", - "id": 381, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.76676704" - }, - "UNI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "ff007a", - "humanType": "Sweep to Main Account", - "id": 431, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.12338181" - }, - "UNITY": { - "blockchain": "UNITY", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 211, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "URO": { - "blockchain": "URO", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 212, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - }, - "USDC": { - "blockchain": "ETH", - "childChains": [ - "USDCTRON" + [ + "110998.54", + "112558.14", + "111445.14", + "112271.32", + "3777407.4864", + "33824", + "2420", + "1756900800000", + "1756922399999" ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2775CA", - "humanType": "Sweep to Main Account", - "id": 299, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "24.61944275" - }, - "USDCTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2876C9", - "humanType": "Sweep to Main Account", - "id": 543, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "USDC", - "txFee": "0.01000000" - }, - "USDE": { - "blockchain": "USDE", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 213, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "USDJ": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "A52A21", - "humanType": "Sweep to Main Account", - "id": 337, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.05000000" - }, - "USDT": { - "blockchain": "OMNI", - "childChains": [ - "USDTTRON", - "USDTETH" + [ + "111568.05", + "112488.11", + "112273.86", + "111673.43", + "959561.0592", + "8570", + "1386", + "1756922400000", + "1756943999999" ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "44A58B", - "humanType": "Sweep to Main Account", - "id": 214, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 2, - "name": "", - "parentChain": null, - "txFee": "100.00000000" - }, - "USDTETH": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 318, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": "USDT", - "txFee": "24.61944275" - }, - "USDTTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 316, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "USDT", - "txFee": "0.00000000" - }, - "UST": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5493F7", - "humanType": "Sweep to Main Account", - "id": 517, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "21.13065781" - }, - "UTC": { - "blockchain": "UTC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 215, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "UTIL": { - "blockchain": "UTIL", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 216, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "UVC": { - "blockchain": "UVC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 217, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "VALUE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3A71BD", - "humanType": "Sweep to Main Account", - "id": 442, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "10.08172751" - }, - "VIA": { - "blockchain": "VIA", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "231F20", - "humanType": "BTC Clone", - "id": 218, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 60, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "VOOT": { - "blockchain": "VOOT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 219, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "VOX": { - "blockchain": "VOX", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 276, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "VRC": { - "blockchain": "VRC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 220, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "VSP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3C3EA4", - "humanType": "Sweep to Main Account", - "id": 499, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "2.74111095" - }, - "VTC": { - "blockchain": "VTC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "048652", - "humanType": "BTC Clone", - "id": 221, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1200, - "name": "", - "parentChain": null, - "txFee": "0.00100000" + [ + "110575.1", + "112139.08", + "111681.8", + "110646.86", + "892657.67648", + "8016", + "1314", + "1756944000000", + "1756965599999" + ] + ], + "msg": "Success" + }, + "queryString": "interval=HOUR_6\u0026limit=100\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + [ + "109422.04", + "109428.57", + "109423.06", + "109422.59", + "3720.43346", + "34", + "12", + "1758970500000", + "1758970799999" + ], + [ + "109427.54", + "109433.27", + "109433.27", + "109429.78", + "2407.45368", + "22", + "11", + "1758970800000", + "1758971099999" + ], + [ + "109318.23", + "109430.18", + "109429.98", + "109328.55", + "3937.85906", + "36", + "18", + "1758971100000", + "1758971399999" + ], + [ + "109312.29", + "109359.27", + "109331.01", + "109317.02", + "2842.98512", + "26", + "13", + "1758971400000", + "1758971699999" + ], + [ + "109308.73", + "109319.39", + "109314.38", + "109317.91", + "3060.73974", + "28", + "13", + "1758971700000", + "1758971999999" + ] + ], + "msg": "Success" + }, + "queryString": "eTime=1743702190295\u0026interval=MINUTE_5\u0026limit=100\u0026sTime=1743615790295\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + [ + "77631.97", + "77864.86", + "77697.45", + "77804.35", + "7464.83606", + "96", + "48", + "1744183800000", + "1744184099999" + ], + [ + "77721.51", + "77825.44", + "77825.44", + "77730.97", + "14771.44954", + "190", + "33", + "1744184100000", + "1744184399999" + ], + [ + "77718.22", + "77898.92", + "77770.86", + "77898.92", + "62906.96122", + "808", + "52", + "1744184400000", + "1744184699999" + ], + [ + "77618.97", + "77860.9", + "77860.9", + "77714.91", + "6995.28338", + "90", + "45", + "1744184700000", + "1744184999999" + ], + [ + "77600.23", + "77723.12", + "77693.45", + "77667.49", + "5590.98198", + "72", + "36", + "1744185000000", + "1744185299999" + ] + ], + "msg": "Success" + }, + "queryString": "eTime=1744191300000\u0026interval=MINUTE_5\u0026limit=500\u0026sTime=1744183800000\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + [ + "78975.25", + "79045.82", + "79045.82", + "78977.61", + "3002.09196", + "38", + "19", + "1744103700000", + "1744103999999" + ], + [ + "78975.23", + "79078.56", + "79020.37", + "79050.12", + "35575.35072", + "450", + "27", + "1744104000000", + "1744104299999" + ], + [ + "78842.01", + "78999.42", + "78999.42", + "78846.17", + "13089.95804", + "166", + "30", + "1744104300000", + "1744104599999" + ], + [ + "78835.81", + "78866.11", + "78846.18", + "78842.37", + "2365.3686", + "30", + "15", + "1744104600000", + "1744104899999" + ], + [ + "78840.42", + "79029.85", + "78850.3", + "78973.35", + "8369.5373", + "106", + "27", + "1744104900000", + "1744105199999" + ] + ], + "msg": "Success" + }, + "queryString": "eTime=1744190400000\u0026interval=MINUTE_5\u0026limit=500\u0026sTime=1744103700000\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/fundingRate": { + "GET": [ + { + "data": { + "code": 200, + "data": { + "fR": "0.0001", + "fT": "1734552000000", + "nFR": "0.0001", + "nFT": "1734580800000", + "s": "BTC_USDT_PERP" + }, + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/fundingRate/history": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "fR": "0.0001", + "fT": "1744171200000", + "s": "BTC_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "fR": "0.0001", + "fT": "1761537600000", + "s": "BTC_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "eTime=1743702190295\u0026limit=100\u0026sTime=1743615790295\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "fR": "0.0001", + "fT": "1761537600000", + "s": "BTC_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "limit=100\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/indexPrice": { + "GET": [ + { + "data": { + "code": 200, + "data": { + "iPx": "104413.36", + "s": "BTC_USDT_PERP" }, - "WBTC": { - "blockchain": "ETH", - "childChains": [ - "WBTCTRON" + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "iPx": "2.6514", + "s": "XRP_USDT_PERP" + }, + { + "iPx": "0.30138", + "s": "TRX_USDT_PERP" + }, + { + "iPx": "4228.08", + "s": "ETH_USDT_PERP" + }, + { + "iPx": "115707.34", + "s": "BTC_USDT_PERP" + }, + { + "iPx": "562.05", + "s": "BCH_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/indexPriceCandlesticks": { + "GET": [ + { + "data": { + "code": 24102, + "data": "", + "msg": "Invalid K-line type!" + }, + "queryString": "interval=HOUR_6\u0026limit=10\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + [ + "101583.66", + "102688.38", + "101731.3", + "102668.12", + "1734249600000", + "1734263999999" ], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F59C3D", - "humanType": "Sweep to Main Account", - "id": 453, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00030000" - }, - "WBTCTRON": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "F59C3D", - "humanType": "Sweep to Main Account", - "id": 474, - "isChildChain": 1, - "isGeofenced": 0, - "isMultiChain": 1, - "minConf": 0, - "name": "", - "parentChain": "WBTC", - "txFee": "0.00000000" - }, - "WC": { - "blockchain": "WC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 222, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "WDC": { - "blockchain": "WDC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 223, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "WETH": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 495, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.00370000" - }, - "WHALE": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "000000", - "humanType": "Sweep to Main Account", - "id": 514, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "1.45292053" - }, - "WIKI": { - "blockchain": "WIKI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 224, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "WIN": { - "blockchain": "TRX", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FAC50A", - "humanType": "Sweep to Main Account", - "id": 321, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "3500.00000000" - }, - "WNXM": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "646665", - "humanType": "Sweep to Main Account", - "id": 412, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.29304018" - }, - "WOLF": { - "blockchain": "WOLF", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 225, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.02000000" - }, - "WRX": { - "blockchain": "BNB", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "3B69E8", - "humanType": "Sweep to Main Account", - "id": 363, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "0.19855175" - }, - "X13": { - "blockchain": "X13", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 226, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XAI": { - "blockchain": "XAI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 227, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XAP": { - "blockchain": "XAP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 228, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "100.00000000" - }, - "XBC": { - "blockchain": "XBC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 229, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.00010000" - }, - "XC": { - "blockchain": "XC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 230, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XCH": { - "blockchain": "XCH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 231, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "XCN": { - "blockchain": "XCN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 232, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.02000000" - }, - "XCP": { - "blockchain": "XCP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "ED1650", - "humanType": "Sweep to Main Account", - "id": 233, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "16.00000000" - }, - "XCR": { - "blockchain": "XCR", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 234, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00017818" - }, - "XDN": { - "blockchain": "XDN", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "ddddecTXF5B9PDwqZXP4Bs1FwttZbhF2YTRstruKctMoFJTE3VgD5uKd4RzmTHdzkv52wWWK2NYmfJeaiTuut2Pe2RVimGCvZ", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 235, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "XDOT": { - "blockchain": "XDOT", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "D84D8C", - "humanType": "Sweep to Main Account", - "id": 402, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "XDP": { - "blockchain": "XDP", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 236, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "XEM": { - "blockchain": "XEM", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "NBZMQO7ZPBYNBDUR7F75MAKA2S3DHDCIFG775N3D", - "disabled": 0, - "frozen": 0, - "hexColor": "2CBAAD", - "humanType": "Payment ID", - "id": 256, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 18, - "name": "", - "parentChain": null, - "txFee": "15.00000000" - }, - "XFLR": { - "blockchain": null, - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "D78F9B", - "humanType": "Sweep to Main Account", - "id": 471, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 0, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "XHC": { - "blockchain": "XHC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 237, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XLB": { - "blockchain": "XLB", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 238, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XLMBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 492, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "247.76089576" - }, - "XLMBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 493, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "5.15891748" - }, - "XMG": { - "blockchain": "XMG", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 239, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XMR": { - "blockchain": "XMR", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EB5E00", - "humanType": "BTC Clone", - "id": 240, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 8, - "name": "", - "parentChain": null, - "txFee": "0.00010000" - }, - "XOR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "CD352D", - "humanType": "Sweep to Main Account", - "id": 522, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.08747702" - }, - "XPB": { - "blockchain": "XPB", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 1, - "depositAddress": "PByFtxkMuoFRwrhXU19PBXLgHssTtcvTDSGzNf7Rvt5uKEf5PnRL4ccK4pWN4dpwvGhggGq12gH4bMqbxLyQGhkf3RLfzurMdK", - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Payment ID", - "id": 241, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "XPM": { - "blockchain": "XPM", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "AC771B", - "humanType": "BTC Clone", - "id": 242, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 2880, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XRP": { - "blockchain": "XRP", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "rwU8rAiE2eyEPz3sikfbHuqCuiAtdXqa2v", - "disabled": 0, - "frozen": 0, - "hexColor": "0085C0", - "humanType": "Payment ID", - "id": 243, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 2, - "name": "", - "parentChain": null, - "txFee": "0.05000000" - }, - "XRPBEAR": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 353, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "87926581.25000000" + [ + "102471.6", + "103319.9", + "102668.13", + "102704.93", + "1734264000000", + "1734278399999" + ], + [ + "102584.34", + "103482.19", + "102704.94", + "103253.49", + "1734278400000", + "1734292799999" + ], + [ + "102624.48", + "105216.38", + "103253.49", + "104460.57", + "1734292800000", + "1734307199999" + ], + [ + "104283.98", + "106623.84", + "104463.68", + "104582.66", + "1734307200000", + "1734321599999" + ] + ], + "msg": "Success" + }, + "queryString": "eTime=1765290174763\u0026interval=HOUR_4\u0026limit=10\u0026sTime=1764930174763\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/indexPriceComponents": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "cs": [ + { + "cPx": "79490.8260397968", + "e": "Binance", + "sPx": "106578.52", + "w": "0.74584284" + }, + { + "cPx": "0.00", + "e": "Kucoin", + "sPx": "106584.1", + "w": "0.0" + }, + { + "cPx": "0.000", + "e": "huobi", + "sPx": "106561.29", + "w": "0.0" + }, + { + "cPx": "24238.676665800", + "e": "Okx", + "sPx": "106582.5", + "w": "0.22741704" + }, + { + "cPx": "2849.69458840", + "e": "Poloniex", + "sPx": "106570", + "w": "0.02674012" + } + ], + "px": "106579.2000000000", + "s": "BTC_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "cs": [ + { + "cPx": "0.0065087343054", + "e": "Binance", + "sPx": "0.01062", + "w": "0.61287517" + }, + { + "cPx": "0.0000000", + "e": "Kucoin", + "sPx": "0.010613", + "w": "0.0" + }, + { + "cPx": "0.000000", + "e": "huobi", + "sPx": "0.01061", + "w": "0.0" + }, + { + "cPx": "0.00179304493225", + "e": "Okx", + "sPx": "0.010615", + "w": "0.16891615" + }, + { + "cPx": "0.00231388484272", + "e": "Poloniex", + "sPx": "0.010604", + "w": "0.21820868" + } + ], + "px": "0.0106160000", + "s": "1000SHIB_USDT_PERP" + }, + { + "cs": [ + { + "cPx": "0.123524897984", + "e": "Binance", + "sPx": "0.2078", + "w": "0.59444128" + }, + { + "cPx": "0.00000", + "e": "Kucoin", + "sPx": "0.2078", + "w": "0.0" + }, + { + "cPx": "0.0000000", + "e": "huobi", + "sPx": "0.207779", + "w": "0.0" + }, + { + "cPx": "0.070009755600", + "e": "Okx", + "sPx": "0.20775", + "w": "0.3369904" + }, + { + "cPx": "0.01424451993344", + "e": "Poloniex", + "sPx": "0.207742", + "w": "0.06856832" + } + ], + "px": "0.2077800000", + "s": "DOGE_USDT_PERP" + }, + { + "cs": [ + { + "cPx": "78435.103820640", + "e": "Binance", + "sPx": "115898.56", + "w": "0.6767565" + }, + { + "cPx": "0.00", + "e": "Kucoin", + "sPx": "115880.8", + "w": "0.0" + }, + { + "cPx": "0.000", + "e": "huobi", + "sPx": "115870.89", + "w": "0.0" + }, + { + "cPx": "27132.685451879", + "e": "Okx", + "sPx": "115868.9", + "w": "0.23416711" + }, + { + "cPx": "10310.8121611833", + "e": "Poloniex", + "sPx": "115752.47", + "w": "0.08907639" + } + ], + "px": "115878.6000000000", + "s": "BTC_USDT_PERP" + }, + { + "cs": [ + { + "cPx": "62.020998290", + "e": "Binance", + "sPx": "101.0", + "w": "0.61406929" + }, + { + "cPx": "0.000", + "e": "Kucoin", + "sPx": "101.01", + "w": "0.0" + }, + { + "cPx": "0.00", + "e": "huobi", + "sPx": "101.0", + "w": "0.0" + }, + { + "cPx": "27.7202058134", + "e": "Okx", + "sPx": "100.99", + "w": "0.27448466" + }, + { + "cPx": "11.25259622245", + "e": "Poloniex", + "sPx": "100.969", + "w": "0.11144605" + } + ], + "px": "100.9900000000", + "s": "LTC_USDT_PERP" + }, + { + "cs": [ + { + "cPx": "730.8696585564", + "e": "Binance", + "sPx": "1149.99", + "w": "0.63554436" + }, + { + "cPx": "0.0000", + "e": "Kucoin", + "sPx": "1150.443", + "w": "0.0" + }, + { + "cPx": "42.651838033", + "e": "huobi", + "sPx": "1150.1", + "w": "0.03708533" + }, + { + "cPx": "298.71861311", + "e": "Okx", + "sPx": "1150.7", + "w": "0.2595973" + }, + { + "cPx": "77.9681038943", + "e": "Poloniex", + "sPx": "1150.43", + "w": "0.06777301" + } + ], + "px": "1150.2080000000", + "s": "BNB_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/instruments": { + "GET": [ + { + "data": { + "code": 200, + "data": { + "alias": "", + "bAsset": ".PBNBUSDT", + "bCcy": "BTC", + "ctType": "LINEAR", + "ctVal": "0.1", + "iM": "0.02", + "lever": "10", + "limitMaxQty": "1000000", + "lotSz": 1, + "mM": "0.0115", + "mR": "2000", + "marketMaxQty": "2800", + "maxLever": "50", + "maxPx": "1000000", + "maxQty": "1000000", + "minPx": "0.001", + "minQty": "1", + "minSz": 1, + "oDate": "1620287590000", + "ordPxRange": "0.05", + "pxScale": "0.001,0.01,0.1,1,10", + "qCcy": "USDT", + "sCcy": "USDT", + "status": "OPEN", + "symbol": "BTC_USDT_PERP", + "tSz": "0.001", + "tradableStartTime": "1620390600000", + "visibleStartTime": "1620390600000" + }, + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/insurance": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "amt": "4004044.982470137850115523", + "ccy": "USDT", + "uTime": "1734552540132" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/limitPrice": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "buyLmt": 112735.37, + "sellLmt": 101998.67, + "symbol": "BTC_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "symbol=DOT_USDT_PERP%2C%2CBTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/liquidationOrder": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "symbol": "BTC_USDT_PERP", + "posSide": "BOTH", + "side": "SELL", + "sz": "2", + "bkPx": "2974.9661346666666666", + "uTime": "1765917388122" + }, + { + "symbol": "BTC_USDT_PERP", + "posSide": "BOTH", + "side": "BUY", + "sz": "2", + "bkPx": "2903.9638973333333334", + "uTime": "1765912527011" + } + ], + "msg": "success" + }, + "queryString": "direct=NEXT\u0026eTime=1764668001864\u0026from=1\u0026limit=100\u0026sTime=1764664401864\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/markPrice": { + "GET": [ + { + "data": { + "code": 200, + "data": { + "mPx": "105817.02", + "s": "BTC_USDT_PERP" }, - "XRPBULL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "7BC8DB", - "humanType": "Sweep to Main Account", - "id": 352, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "834.54832863" - }, - "XSI": { - "blockchain": "XSI", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 244, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XST": { - "blockchain": "XST", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 245, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XSV": { - "blockchain": "XSV", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 246, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XTZ": { - "blockchain": "XTZ", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "4180EE", - "humanType": "Sweep to Main Account", - "id": 336, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 30, - "name": "", - "parentChain": null, - "txFee": "0.25000000" - }, - "XUSD": { - "blockchain": "XUSD", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "Sweep to Main Account", - "id": 247, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00000000" - }, - "XVC": { - "blockchain": "XVC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 253, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 1000000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XVS": { - "blockchain": "BSC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "EEC271", - "humanType": "Sweep to Main Account", - "id": 545, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 15, - "name": "", - "parentChain": null, - "txFee": "0.10000000" - }, - "XXC": { - "blockchain": "XXC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 248, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "XYM": { - "blockchain": "XYM", - "childChains": [], - "currencyType": "address-payment-id", - "delisted": 0, - "depositAddress": "ND4D3TWGBR6WEMLBIYZ3O2Q4V7BCEUMZMLTTPEQ", - "disabled": 0, - "frozen": 0, - "hexColor": "440074", - "humanType": "Payment ID", - "id": 501, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 41, - "name": "", - "parentChain": null, - "txFee": "1.00000000" - }, - "YACC": { - "blockchain": "YACC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 249, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "YANG": { - "blockchain": "YANG", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 250, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" - }, - "YC": { - "blockchain": "YC", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 251, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "mPx": "2.65", + "s": "XRP_USDT_PERP" + }, + { + "mPx": "0.30191", + "s": "TRX_USDT_PERP" + }, + { + "mPx": "4232.26", + "s": "ETH_USDT_PERP" + }, + { + "mPx": "115908.33", + "s": "BTC_USDT_PERP" + }, + { + "mPx": "561.06", + "s": "BCH_USDT_PERP" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/markPriceCandlesticks": { + "GET": [ + { + "data": { + "code": 24102, + "data": "", + "msg": "Invalid K-line type!" + }, + "queryString": "interval=HOUR_6\u0026limit=10\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + [ + "106289.42", + "107102.34", + "106791.24", + "106733.69", + "1734408000000", + "1734422399999" + ], + [ + "106666.92", + "107431.6", + "106733.69", + "106801.33", + "1734422400000", + "1734436799999" + ], + [ + "104942.01", + "108216.99", + "106801.33", + "105548.82", + "1734436800000", + "1734451199999" + ], + [ + "105537.07", + "107578.57", + "105548.82", + "106230", + "1734451200000", + "1734465599999" + ], + [ + "105268.08", + "106866.84", + "106230", + "106040.62", + "1734465600000", + "1734479999999" + ] + ], + "msg": "Success" + }, + "queryString": "eTime=1765290174763\u0026interval=HOUR_4\u0026limit=10\u0026sTime=1764930174763\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/openInterest": { + "GET": [ + { + "data": { + "code": 200, + "data": { + "oInterest": "43907.000000000000000000", + "s": "BTC_USDT_PERP" }, - "YFI": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "95989C", - "humanType": "Sweep to Main Account", - "id": 375, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00053784" + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/orderBook": { + "GET": [ + { + "data": { + "code": 24101, + "data": "", + "msg": "Invalid symbol!" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "62TTPDnAQYje2BkaVYmy5kWcSpRlAR9sW3gMpZyaJxM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1734349971244" + ] + } + }, + { + "data": { + "code": 200, + "data": { + "asks": [ + [ + "88380.46", + "1" + ], + [ + "88380.70", + "115" + ], + [ + "88395.66", + "115" + ], + [ + "88400", + "20" + ], + [ + "88411.39", + "1469" + ], + [ + "88412.7", + "50" + ], + [ + "88414.38", + "3961" + ], + [ + "88418.47", + "599" + ], + [ + "88421.46", + "1789" + ], + [ + "88425.55", + "1494" + ] + ], + "bids": [ + [ + "88373.21", + "1" + ], + [ + "88373.2", + "1" + ], + [ + "88354.17", + "195" + ], + [ + "88352.92", + "39" + ], + [ + "88347.22", + "50" + ], + [ + "88343.53", + "4" + ], + [ + "88341.76", + "85" + ], + [ + "88339.99", + "4" + ], + [ + "88338.22", + "172" + ], + [ + "88336.45", + "15" + ] + ], + "s": "0.01", + "ts": 1742832731114 }, - "YFII": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "E81F63", - "humanType": "Sweep to Main Account", - "id": 415, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.00511966" + "msg": "Success" + }, + "queryString": "limit=150\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": { + "asks": [ + [ + "103600", + "11" + ], + [ + "103700", + "9247" + ], + [ + "103800", + "9255" + ], + [ + "104200", + "240" + ], + [ + "104300", + "120" + ] + ], + "bids": [ + [ + "103500", + "2382" + ], + [ + "103400", + "803" + ], + [ + "103000", + "478" + ], + [ + "102900", + "1" + ], + [ + "102500", + "6" + ] + ], + "s": "100", + "ts": 1734350273895 }, - "YFL": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "2B5ADB", - "humanType": "Sweep to Main Account", - "id": 417, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.12867659" + "msg": "Success" + }, + "queryString": "limit=100\u0026scale=100\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": { + "asks": [ + [ + "109500", + "25924" + ], + [ + "109600", + "752" + ], + [ + "109800", + "15" + ], + [ + "109900", + "258" + ], + [ + "110000", + "1629" + ] + ], + "bids": [ + [ + "109300", + "30139" + ], + [ + "109200", + "4202" + ], + [ + "109000", + "1" + ], + [ + "108900", + "1" + ], + [ + "108800", + "2452" + ] + ], + "s": "100", + "ts": 1758998943425 }, - "YFV": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 1, - "hexColor": "2f81e4", - "humanType": "Sweep to Main Account", - "id": 416, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.53492856" + "msg": "Success" + }, + "queryString": "limit=10\u0026scale=100\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/premiumIndexCandlesticks": { + "GET": [ + { + "data": { + "code": 24102, + "data": "", + "msg": "Invalid K-line type!" + }, + "queryString": "interval=HOUR_6\u0026limit=10\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + [ + "101583.66", + "102688.38", + "101731.3", + "102668.12", + "1734249600000", + "1734263999999" + ], + [ + "102471.6", + "103319.9", + "102668.13", + "102704.93", + "1734264000000", + "1734278399999" + ], + [ + "102584.34", + "103482.19", + "102704.94", + "103253.49", + "1734278400000", + "1734292799999" + ], + [ + "102624.48", + "105216.38", + "103253.49", + "104460.57", + "1734292800000", + "1734307199999" + ], + [ + "104283.98", + "106623.84", + "104463.68", + "104582.66", + "1734307200000", + "1734321599999" + ] + ], + "msg": "Success" + }, + "queryString": "eTime=1765290174763\u0026interval=HOUR_4\u0026limit=10\u0026sTime=1764930174763\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/riskLimit": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "mMRatio": "0.027", + "maxLever": "20", + "maxSize": "1000", + "mgnMode": "ISOLATED", + "minSize": "1", + "symbol": "APT_USDT_PERP", + "tier": "1" + }, + { + "mMRatio": "0.05", + "maxLever": "10", + "maxSize": "1500", + "mgnMode": "ISOLATED", + "minSize": "1001", + "symbol": "APT_USDT_PERP", + "tier": "2" + }, + { + "mMRatio": "0.1", + "maxLever": "5", + "maxSize": "2000", + "mgnMode": "ISOLATED", + "minSize": "1501", + "symbol": "APT_USDT_PERP", + "tier": "3" + }, + { + "mMRatio": "0.167", + "maxLever": "3", + "maxSize": "4000", + "mgnMode": "ISOLATED", + "minSize": "2001", + "symbol": "APT_USDT_PERP", + "tier": "4" + }, + { + "mMRatio": "0.5", + "maxLever": "2", + "maxSize": "6000", + "mgnMode": "ISOLATED", + "minSize": "4001", + "symbol": "APT_USDT_PERP", + "tier": "5" + } + ], + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "mMRatio": "0.006", + "maxLever": "75", + "maxSize": "250", + "mgnMode": "CROSS", + "minSize": "1", + "symbol": "BTC_USDT_PERP", + "tier": "1" + } + ], + "msg": "Success" + }, + "queryString": "mgnMode=CROSS\u0026symbol=BTC_USDT_PERP\u0026tier=1", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/tickers": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "aPx": "104273.75", + "aSz": "1", + "amt": "16713942.42384", + "bPx": "104238.98", + "bSz": "14", + "c": "104271.54", + "cT": 1734359250814, + "dC": "0.0138", + "dN": "BTC/USDT/PERP", + "h": "106656.08", + "l": "102555.18", + "mPx": "104271.54", + "o": "102850.98", + "qty": "161306", + "s": "BTC_USDT_PERP", + "sT": 1734272820000, + "tC": 8527 + } + ], + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "aPx": "104273.75", + "aSz": "1", + "amt": "16713942.42384", + "bPx": "104238.98", + "bSz": "14", + "c": "104271.54", + "cT": 1734359250814, + "dC": "0.0138", + "dN": "ABC/DEF/PERP", + "h": "106656.08", + "l": "102555.18", + "mPx": "104271.54", + "o": "102850.98", + "qty": "161306", + "s": "ABC-DEF", + "sT": 1734272820000, + "tC": 8527 + }, + { + "aPx": "104273.75", + "aSz": "1", + "amt": "16713942.42384", + "bPx": "104238.98", + "bSz": "14", + "c": "104271.54", + "cT": 1734359250814, + "dC": "0.0138", + "dN": "ABC/DEF/PERP", + "h": "106656.08", + "l": "102555.18", + "mPx": "104271.54", + "o": "102850.98", + "qty": "161306", + "s": "ABC-DEF", + "sT": 1734272820000, + "tC": 8527 + } + ], + "msg": "Success" + }, + "queryString": "symbol=ABC-DEF", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "aPx": "2.4684", + "aSz": "71", + "amt": "430836.152", + "bPx": "2.4492", + "bSz": "21", + "c": "2.4556", + "cT": 1742831481621, + "dC": "0.0191", + "dN": "XRP/USDT/PERP", + "h": "2.4949", + "iPx": "2.468", + "l": "2.3753", + "mPx": "2.4582", + "o": "2.4096", + "qty": "17722", + "s": "XRP_USDT_PERP", + "sT": 1742745060000, + "tC": 3245 + }, + { + "aPx": "0.22979", + "aSz": "47", + "amt": "406203.694", + "bPx": "0.22941", + "bSz": "51", + "c": "0.22942", + "cT": 1742831456759, + "dC": "-0.0127", + "dN": "TRX/USDT/PERP", + "h": "0.23243", + "iPx": "0.22969", + "l": "0.22495", + "mPx": "0.22966", + "o": "0.23237", + "qty": "17740", + "s": "TRX_USDT_PERP", + "sT": 1742745060000, + "tC": 3239 + }, + { + "aPx": "2084.39", + "aSz": "1", + "amt": "2247076.4294", + "bPx": "2083.43", + "bSz": "635", + "c": "2083.04", + "cT": 1742831458063, + "dC": "0.0381", + "dN": "ETH/USDT/PERP", + "h": "2104.89", + "iPx": "2084.81", + "l": "1978.01", + "mPx": "2084.03", + "o": "2006.5", + "qty": "108794", + "s": "ETH_USDT_PERP", + "sT": 1742745060000, + "tC": 6330 + }, + { + "aPx": "88079.64", + "aSz": "122", + "amt": "10200071.42858", + "bPx": "88058.64", + "bSz": "2", + "c": "88065.79", + "cT": 1742831474592, + "dC": "0.0342", + "dN": "BTC/USDT/PERP", + "h": "88697.84", + "iPx": "88092.71", + "l": "84773.98", + "mPx": "88067.41", + "o": "85152.62", + "qty": "118002", + "s": "BTC_USDT_PERP", + "sT": 1742745060000, + "tC": 7314 + }, + { + "aPx": "331.87", + "aSz": "148", + "amt": "359730.6364", + "bPx": "331.21", + "bSz": "102", + "c": "331.35", + "cT": 1742831478342, + "dC": "0.0211", + "dN": "BCH/USDT/PERP", + "h": "333.61", + "iPx": "331.47", + "l": "320.81", + "mPx": "331.46", + "o": "324.5", + "qty": "110134", + "s": "BCH_USDT_PERP", + "sT": 1742745060000, + "tC": 3217 + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/market/trades": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "amt": "103.86838", + "cT": 1734354688285, + "id": 105091009, + "px": "103868.38", + "qty": "1", + "side": "sell" + }, + { + "amt": "103.88358", + "cT": 1734354660249, + "id": 105091008, + "px": "103883.58", + "qty": "1", + "side": "buy" + }, + { + "amt": "103.87036", + "cT": 1734354656195, + "id": 105091007, + "px": "103870.36", + "qty": "1", + "side": "buy" + }, + { + "amt": "2285.84576", + "cT": 1734354649944, + "id": 105091006, + "px": "103902.08", + "qty": "22", + "side": "buy" + }, + { + "amt": "103.84963", + "cT": 1734354649943, + "id": 105091005, + "px": "103849.63", + "qty": "1", + "side": "buy" + } + ], + "msg": "Success" + }, + "queryString": "limit=5\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + }, + { + "data": { + "code": 200, + "data": [ + { + "amt": "103.86838", + "cT": 1734354688285, + "id": 105091009, + "px": "103868.38", + "qty": "1", + "side": "sell" + }, + { + "amt": "103.88358", + "cT": 1734354660249, + "id": 105091008, + "px": "103883.58", + "qty": "1", + "side": "buy" + }, + { + "amt": "103.87036", + "cT": 1734354656195, + "id": 105091007, + "px": "103870.36", + "qty": "1", + "side": "buy" + }, + { + "amt": "2285.84576", + "cT": 1734354649944, + "id": 105091006, + "px": "103902.08", + "qty": "22", + "side": "buy" + }, + { + "amt": "103.84963", + "cT": 1734354649943, + "id": 105091005, + "px": "103849.63", + "qty": "1", + "side": "buy" + } + ], + "msg": "Success" + }, + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": {} + } + ] + }, + "/v3/position/leverage": { + "POST": [ + { + "data": { + "code": 200, + "data": { + "lever": "7", + "symbol": "DOGE_USDT_PERP", + "mgnMode": "CROSS", + "posSide": "BOTH" + }, + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"lever\":\"10\",\"mgnMode\":\"CROSS\",\"posSide\":\"LONG\",\"symbol\":\"BTC_USDT_PERP\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "OEJpZ38WprBxgpdY+Xn8AR/ULtHH1U0KcAl1P6tO1DE=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743967714615" + ] + } + } + ] + }, + "/v3/position/leverages": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "lever": "20", + "mgnMode": "ISOLATED", + "posSide": "BOTH", + "symbol": "BTC_USDT_PERP" + } + ], + "msg": "" + }, + "queryString": "mgnMode=ISOLATED\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "2N8qHz+lJ9gc7LAG4I5npZXv4PKJGqQfrC/g32GQuRA=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1734090134658" + ] + } + } + ] + }, + "/v3/position/mode": { + "GET": [ + { + "data": { + "code": 200, + "data": { + "posMode": "ONE_WAY" }, - "YFX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "FFB219", - "humanType": "Sweep to Main Account", - "id": 554, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "89.55628549" + "msg": "Success" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "NYsZ2jGdHesQyv3/U7tgBCB56LCqzPJTgZqr0sGcI08=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203644629" + ] + } + } + ], + "POST": [ + { + "data": { + "code": 200, + "data": {}, + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"posMode\":\"HEDGE\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "wJMakiE/uPwlnVRveQ+8SRSFCpOTNr2HUjTupjKLtLY=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203663001" + ] + } + } + ] + }, + "/v3/position/riskLimit": { + "GET": [ + { + "data": { + "code": 200, + "msg": "Success", + "data": [ + { + "symbol": "BTC_USDT_PERP", + "mgnMode": "CROSS", + "posSide": "BOTH", + "tier": "1", + "maxLever": "100", + "mMRatio": "0.025", + "maxSize": "1000", + "minSize": "1" + } + ] + }, + "queryString": "mgnMode=CROSS\u0026posSide=LONG\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Signature": [ + "TP8TqSKMsCUfydpTcaucN3X7FdU8aIR9BIfFgw91vrM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1767067253548" + ] + } + } + ] + }, + "/v3/trade/allOrders": { + "DELETE": [ + { + "data": { + "code": 200, + "data": [ + { + "clOrdId": "b93fe6bd-30eb-4d0e-8c99-0288a9156837", + "code": 200, + "msg": "Success", + "ordId": "331378951169769472" + }, + { + "clOrdId": "225c8607-d98f-4a2e-a27b-faea04fe718f", + "code": 200, + "msg": "Success", + "ordId": "331378951182352384" + }, + { + "clOrdId": "9e36e89c-6cab-45c6-9c8a-245b7547601a", + "code": 200, + "msg": "Success", + "ordId": "331378951199129601" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTCUSDT_PERP\",\"side\":\"BUY\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "pJ8w5yt5Pr0LOx1MqEtBPxWDb2VUm5yDL1lD0dZqOW8=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742835867992" + ] + } + } + ] + }, + "/v3/trade/batchOrders": { + "DELETE": [ + { + "data": { + "code": 200, + "data": [ + { + "clOrdId": "b93fe6bd-30eb-4d0e-8c99-0288a9156837", + "code": 200, + "msg": "Success", + "ordId": "331378951169769472" + }, + { + "clOrdId": "225c8607-d98f-4a2e-a27b-faea04fe718f", + "code": 200, + "msg": "Success", + "ordId": "331378951182352384" + }, + { + "clOrdId": "9e36e89c-6cab-45c6-9c8a-245b7547601a", + "code": 200, + "msg": "Success", + "ordId": "331378951199129601" + } + ], + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"1000SHIB_USDT_PERP\",\"ordIds\":[\"331378951169769472\",\"331378951182352384\",\"331378951199129601\"]}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "N2XIBQSSglIsiGblbobjOaSzhW//5mV4mYwmLjeYRJU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742835908350" + ] + } + } + ] + }, + "/v3/trade/order": { + "DELETE": [ + { + "data": { + "code": 200, + "data": { + "clOrdId": "1e073485-dfdc-44b9-9523-3daa871984f3", + "ordId": "331378951194935296" }, - "YGG": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "AA8B55", - "humanType": "Sweep to Main Account", - "id": 564, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "4.60044706" - }, - "YIN": { - "blockchain": "YIN", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 252, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.01000000" + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"ordId\":\"12345\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "0DfkTBk8ZuY94aaU7Bbph4uIvkJR6sb4AebI2OcCqVA=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742836395699" + ] + } + } + ], + "POST": [ + { + "data": { + "code": 200, + "data": { + "clOrdId": "939a9d51-8f32-443a-9fb8-ff0852010487", + "ordId": "331375826421678080" }, - "ZAP": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "46A2F8", - "humanType": "Sweep to Main Account", - "id": 393, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "399.83833005" - }, - "ZEC": { - "blockchain": "ZEC", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "D99F00", - "humanType": "BTC Clone", - "id": 286, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 8, - "name": "", - "parentChain": null, - "txFee": "0.00100000" + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"side\":\"buy\",\"mgnMode\":\"CROSS\",\"posSide\":\"LONG\",\"type\":\"LIMIT_MAKER\",\"clOrdId\":\"939a9d51-8f32-443a-9fb8-ff0852010487\",\"px\":\"46050\",\"sz\":\"10\",\"timeInForce\":\"GTC\",\"stpMode\":\"EXPIRE_TAKER\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "MK72Vc1EZ4H5RapViCE7qIs7bD/vuVehj2rbMCcuwpM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759075010078" + ] + } + }, + { + "data": { + "code": 200, + "data": { + "clOrdId": "939a9d51-8f32-443a-9fb8-ff0852010487", + "ordId": "331375826421678080" }, - "ZKS": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "5A22A3", - "humanType": "Sweep to Main Account", - "id": 497, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "24.45693247" + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT\",\"side\":\"BUY\",\"mgnMode\":\"\",\"posSide\":\"UNKNOWN\",\"type\":\"MARKET\",\"px\":\"10\",\"sz\":\"10000000\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "MK72Vc1EZ4H5RapViCE7qIs7bD/vuVehj2rbMCcuwpM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759075010078" + ] + } + }, + { + "data": { + "code": 200, + "data": { + "clOrdId": "939a9d51-8f32-443a-9fb8-ff0852010487", + "ordId": "331375826421678080" }, - "ZLOT": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "DAE2E3", - "humanType": "Sweep to Main Account", - "id": 460, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "0.26454333" + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"side\":\"SELL\",\"mgnMode\":\"\",\"posSide\":\"UNKNOWN\",\"type\":\"MARKET\",\"px\":\"10\",\"sz\":\"10000000\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "MK72Vc1EZ4H5RapViCE7qIs7bD/vuVehj2rbMCcuwpM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759075010078" + ] + } + }, + { + "data": { + "code": 200, + "data": { + "clOrdId": "939a9d51-8f32-443a-9fb8-ff0852010487", + "ordId": "331375826421678080" }, - "ZRX": { - "blockchain": "ETH", - "childChains": [], - "currencyType": "address", - "delisted": 0, - "depositAddress": null, - "disabled": 0, - "frozen": 0, - "hexColor": "003831", - "humanType": "Sweep to Main Account", - "id": 293, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 12, - "name": "", - "parentChain": null, - "txFee": "18.83724034" - }, - "eTOK": { - "blockchain": "eTOK", - "childChains": [], - "currencyType": "address", - "delisted": 1, - "depositAddress": null, - "disabled": 1, - "frozen": 0, - "hexColor": "068485", - "humanType": "BTC Clone", - "id": 72, - "isChildChain": 0, - "isGeofenced": 0, - "isMultiChain": 0, - "minConf": 10000, - "name": "", - "parentChain": null, - "txFee": "0.00100000" - } + "msg": "Success" + }, + "queryString": "", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"side\":\"BUY\",\"mgnMode\":\"CROSS\",\"posSide\":\"LONG\",\"type\":\"LIMIT\",\"px\":\"10\",\"sz\":\"10000000\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "MK72Vc1EZ4H5RapViCE7qIs7bD/vuVehj2rbMCcuwpM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1759075010078" + ] + } + } + ] + }, + "/v3/trade/order/history": { + "GET": [ + { + "data": { + "code": 200, + "data": [], + "msg": "" + }, + "queryString": "limit=100\u0026side=BUY", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "0PTi5rDNckq3rQFKkj5aWIeGrKa2cycguQ265zhwG+0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742738479200" + ] + } + }, + { + "data": { + "code": 200, + "data": [], + "msg": "" + }, + "queryString": "direct=PREV\u0026limit=100\u0026state=PARTIALLY_CANCELED", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "Gy54S0cBLkIVvWHdX9SCm3vpuMNLaS3Dwo9RjiQRSMo=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743701890362" + ] + } + }, + { + "data": { + "code": 200, + "data": [ + { + "cTime": "1719973930900", + "clOrdId": "polo331381602863284224", + "deductAmt": "0", + "deductCcy": "", + "feeAmt": "0.00009405", + "feeCcy": "USDT", + "feeRate": "0.0005", + "id": "331381604734197760", + "mgnMode": "CROSS", + "posSide": "BOTH", + "ordType": "MARKET", + "px": "60000", + "qty": "3", + "role": "TAKER", + "side": "SELL", + "symbol": "BTC_USDT_PERP", + "ordId": "356743696043233280", + "trdId": "100000010", + "type": "TRADE", + "actType": "TRADING", + "qCcy": "USDT", + "value": "1000", + "uTime": "1719973930924" + } + ], + "msg": "" }, - "queryString": "command=returnCurrencies\u0026includeMultiChainCurrencies=true", + "queryString": "clOrdId=polo331381602863284224\u0026direct=PREV\u0026eTime=1743702190295\u0026from=1\u0026limit=100\u0026ordId=331381604734197760\u0026sTime=1743615790295\u0026side=SELL\u0026state=PARTIALLY_CANCELED\u0026symbol=BTC_USDT_PERP\u0026type=LIMIT", "bodyParams": "", - "headers": {} + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "q+fj3lPyXJOi/zuAEUrQb4ANIpx9dAwevwiIYtMLtlk=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1744053335462" + ] + } }, { - "data": [ - { - "close": 0.00403997, - "date": 1405699200, - "high": 0.00413615, - "low": 0.00403986, - "open": 0.00404545, - "quoteVolume": 1205.10503896, - "volume": 4.95713239, - "weightedAverage": 0.00411344 - } - ], - "queryString": "command=returnChartData\u0026currencyPair=BTC_XMR\u0026end=1405699400\u0026period=300\u0026start=1405699200", + "data": { + "code": 200, + "data": [ + { + "avgPx": "0.6272", + "cTime": "1719973768748", + "cancelReason": "", + "clOrdId": "polo331380922769473536", + "deductAmt": "0", + "deductCcy": "0", + "execAmt": "1.8816", + "execQty": "3", + "feeAmt": "0.00009408", + "feeCcy": "USDT", + "lever": "20", + "mgnMode": "CROSS", + "posSide": "BOTH", + "ordId": "331380922769473536", + "px": "60000", + "reduceOnly": "false", + "side": "BUY", + "slPx": "", + "slTrgPx": "", + "slTrgPxType": "", + "source": "WEB", + "state": "FILLED", + "stpMode": "NONE", + "symbol": "BTC_USDT_PERP", + "sz": "3", + "timeInForce": "GTC", + "tpPx": "", + "tpTrgPx": "", + "tpTrgPxType": "", + "actType": "TRADING", + "qCcy": "USDT", + "type": "LIMIT", + "uTime": "1719973768764" + } + ], + "msg": "" + }, + "queryString": "ordId=12345\u0026symbol=BTC_USDT_PERP", "bodyParams": "", - "headers": {} + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "q+fj3lPyXJOi/zuAEUrQb4ANIpx9dAwevwiIYtMLtlk=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1744053335462" + ] + } }, { "data": { - "BTC_ARDR": { - "ARDR": "238083.87187020", - "BTC": "3.03108905" - }, - "BTC_ATOM": { - "ATOM": "52381.46699854", - "BTC": "39.67100725" - }, - "BTC_BAT": { - "BAT": "51122.24173657", - "BTC": "2.13275613" - }, - "BTC_BCHABC": { - "BCHABC": "733.46224700", - "BTC": "36.20758372" - }, - "BTC_BCHSV": { - "BCHSV": "4528.05891976", - "BTC": "107.87823714" - }, - "BTC_BCN": { - "BCN": "18580513.78451419", - "BTC": "2.10597417" - }, - "BTC_BNT": { - "BNT": "708.36829451", - "BTC": "0.06242819" - }, - "BTC_BTS": { - "BTC": "11.31814868", - "BTS": "1422525.76536768" - }, - "BTC_CLAM": { - "BTC": "2.91928382", - "CLAM": "5008.88307610" - }, - "BTC_CVC": { - "BTC": "0.75331703", - "CVC": "68777.88900435" - }, - "BTC_DASH": { - "BTC": "121.56922496", - "DASH": "6476.07273599" - }, - "BTC_DCR": { - "BTC": "2.34160137", - "DCR": "684.41654989" - }, - "BTC_DGB": { - "BTC": "16.15966014", - "DGB": "9761759.50030071" - }, - "BTC_DOGE": { - "BTC": "19.98598120", - "DOGE": "52317925.99866673" - }, - "BTC_EOS": { - "BTC": "18.59593565", - "EOS": "23099.92132301" - }, - "BTC_ETC": { - "BTC": "10.91386394", - "ETC": "10520.96374951" - }, - "BTC_ETH": { - "BTC": "155.94348625", - "ETH": "5059.54434879" - }, - "BTC_FCT": { - "BTC": "10.36741741", - "FCT": "13773.13207446" - }, - "BTC_FOAM": { - "BTC": "0.89731724", - "FOAM": "166155.79008468" - }, - "BTC_GAME": { - "BTC": "3.82370347", - "GAME": "300446.22176630" - }, - "BTC_GAS": { - "BTC": "0.77232780", - "GAS": "1916.80182489" - }, - "BTC_GNT": { - "BTC": "4.93328876", - "GNT": "404745.01492216" - }, - "BTC_GRIN": { - "BTC": "24.37429922", - "GRIN": "62838.47716938" - }, - "BTC_KNC": { - "BTC": "1.07605151", - "KNC": "31066.52899332" - }, - "BTC_LBC": { - "BTC": "3.00058286", - "LBC": "699495.42159049" - }, - "BTC_LOOM": { - "BTC": "5.48711026", - "LOOM": "522861.14578247" - }, - "BTC_LPT": { - "BTC": "2.49829681", - "LPT": "4080.23729692" - }, - "BTC_LSK": { - "BTC": "5.21884194", - "LSK": "20377.01855963" - }, - "BTC_LTC": { - "BTC": "666.94447027", - "LTC": "42339.40507638" - }, - "BTC_MAID": { - "BTC": "2.56267002", - "MAID": "107646.79242367" - }, - "BTC_MANA": { - "BTC": "2.70084416", - "MANA": "362727.87722537" - }, - "BTC_NAV": { - "BTC": "0.85599154", - "NAV": "30239.29066641" - }, - "BTC_NMR": { - "BTC": "1.64609151", - "NMR": "1912.03148904" - }, - "BTC_NXT": { - "BTC": "1.64399713", - "NXT": "360674.76672284" - }, - "BTC_OMG": { - "BTC": "1.25616463", - "OMG": "4963.85040878" - }, - "BTC_OMNI": { - "BTC": "0.20882002", - "OMNI": "732.64551893" - }, - "BTC_PASC": { - "BTC": "1.25124963", - "PASC": "45122.06215166" - }, - "BTC_POLY": { - "BTC": "1.91462892", - "POLY": "152996.00496795" - }, - "BTC_QTUM": { - "BTC": "9.94417285", - "QTUM": "23898.37003779" - }, - "BTC_REP": { - "BTC": "3.58890958", - "REP": "1490.86836755" - }, - "BTC_SC": { - "BTC": "1.87511642", - "SC": "4769865.10799687" - }, - "BTC_SNT": { - "BTC": "1.74882337", - "SNT": "463292.11309769" - }, - "BTC_STEEM": { - "BTC": "4.42639165", - "STEEM": "85043.49213557" - }, - "BTC_STORJ": { - "BTC": "0.59303686", - "STORJ": "16796.76970761" - }, - "BTC_STR": { - "BTC": "29.15587511", - "STR": "1887833.72135812" - }, - "BTC_STRAT": { - "BTC": "3.69185582", - "STRAT": "30477.03971572" - }, - "BTC_VIA": { - "BTC": "6.00937608", - "VIA": "82838.51366051" - }, - "BTC_VTC": { - "BTC": "8.10964192", - "VTC": "118741.18466855" - }, - "BTC_XEM": { - "BTC": "11.47584618", - "XEM": "1080591.66263058" - }, - "BTC_XMR": { - "BTC": "42.01213244", - "XMR": "3857.26226555" - }, - "BTC_XPM": { - "BTC": "0.71263628", - "XPM": "24729.03795341" - }, - "BTC_XRP": { - "BTC": "201.36631863", - "XRP": "4023790.64131056" - }, - "BTC_ZEC": { - "BTC": "6.83567402", - "ZEC": "679.67342401" - }, - "BTC_ZRX": { - "BTC": "2.07845804", - "ZRX": "49776.28138902" - }, - "ETH_BAT": { - "BAT": "11202.68186565", - "ETH": "15.19774324" - }, - "ETH_BNT": { - "BNT": "5013.99102334", - "ETH": "14.29896888" - }, - "ETH_CVC": { - "CVC": "22217.14581100", - "ETH": "7.76889158" - }, - "ETH_EOS": { - "EOS": "2204.63200411", - "ETH": "57.85287084" - }, - "ETH_ETC": { - "ETC": "1477.91871918", - "ETH": "50.23223183" - }, - "ETH_GAS": { - "ETH": "3.04307877", - "GAS": "227.12349806" - }, - "ETH_GNT": { - "ETH": "33.26795789", - "GNT": "85767.44098332" - }, - "ETH_KNC": { - "ETH": "3.97445644", - "KNC": "3526.69313018" - }, - "ETH_LOOM": { - "ETH": "65.66658897", - "LOOM": "193088.49239467" - }, - "ETH_LSK": { - "ETH": "0.76656131", - "LSK": "93.01338152" - }, - "ETH_MANA": { - "ETH": "22.07735950", - "MANA": "90624.84430328" - }, - "ETH_OMG": { - "ETH": "8.05512623", - "OMG": "971.21438737" - }, - "ETH_QTUM": { - "ETH": "19.21848012", - "QTUM": "1428.71665478" - }, - "ETH_REP": { - "ETH": "43.83047186", - "REP": "566.61066154" - }, - "ETH_SNT": { - "ETH": "11.98247233", - "SNT": "97344.62846475" - }, - "ETH_STEEM": { - "ETH": "6.47349009", - "STEEM": "3859.75860945" - }, - "ETH_ZEC": { - "ETH": "20.70785072", - "ZEC": "63.08405800" - }, - "ETH_ZRX": { - "ETH": "22.37346857", - "ZRX": "16548.11602204" - }, - "USDC_ATOM": { - "ATOM": "1435.15971856", - "USDC": "8589.72151742" - }, - "USDC_BCHABC": { - "BCHABC": "345.71602989", - "USDC": "135429.66946378" - }, - "USDC_BCHSV": { - "BCHSV": "1158.73869926", - "USDC": "219303.91833302" - }, - "USDC_BTC": { - "BTC": "441.87385476", - "USDC": "3482664.85806597" - }, - "USDC_DOGE": { - "DOGE": "907350.09402904", - "USDC": "2750.23843586" - }, - "USDC_ETH": { - "ETH": "2047.00238213", - "USDC": "501153.45720283" - }, - "USDC_FOAM": { - "FOAM": "16885.98552482", - "USDC": "722.65429834" - }, - "USDC_GRIN": { - "GRIN": "7937.02292983", - "USDC": "23814.63241472" - }, - "USDC_LTC": { - "LTC": "4496.10093795", - "USDC": "566449.26199652" - }, - "USDC_STR": { - "STR": "178840.89704069", - "USDC": "21935.95722630" - }, - "USDC_USDT": { - "USDC": "57933.50068393", - "USDT": "57719.93500183" - }, - "USDC_XMR": { - "USDC": "99062.18940901", - "XMR": "1147.67641269" - }, - "USDC_XRP": { - "USDC": "199920.97825116", - "XRP": "501260.01445723" - }, - "USDC_ZEC": { - "USDC": "18301.41164199", - "ZEC": "229.40589669" - }, - "USDT_ATOM": { - "ATOM": "21087.06757208", - "USDT": "125149.60868108" - }, - "USDT_BAT": { - "BAT": "58700.42769184", - "USDT": "19328.23384182" - }, - "USDT_BNT": { - "BNT": "514.58745683", - "USDT": "363.53451604" - }, - "USDT_BTC": { - "BTC": "561.77921782", - "USDT": "4421897.17330826" - }, - "USDT_DASH": { - "DASH": "1097.22131727", - "USDT": "163148.07688044" - }, - "USDT_DOGE": { - "DOGE": "10052886.96556405", - "USDT": "30256.35268923" - }, - "USDT_EOS": { - "EOS": "43736.05905905", - "USDT": "278043.19290915" - }, - "USDT_ETC": { - "ETC": "17511.35515526", - "USDT": "143484.54569522" - }, - "USDT_ETH": { - "ETH": "3668.33116661", - "USDT": "883511.34773111" - }, - "USDT_GNT": { - "GNT": "136510.36772013", - "USDT": "13022.42294546" - }, - "USDT_KNC": { - "KNC": "12879.73674180", - "USDT": "3460.19386639" - }, - "USDT_LOOM": { - "LOOM": "94061.17501115", - "USDT": "7884.22722657" - }, - "USDT_LSK": { - "LSK": "6568.77436503", - "USDT": "13223.12589230" - }, - "USDT_LTC": { - "LTC": "10573.16167640", - "USDT": "1316866.42418109" - }, - "USDT_MANA": { - "MANA": "59699.03615938", - "USDT": "3529.09794786" - }, - "USDT_NXT": { - "NXT": "287419.90703917", - "USDT": "10352.62135341" - }, - "USDT_QTUM": { - "QTUM": "12370.15246589", - "USDT": "39682.13887751" - }, - "USDT_REP": { - "REP": "1157.81116881", - "USDT": "21917.80239715" - }, - "USDT_SC": { - "SC": "8307626.97734275", - "USDT": "25558.80796699" - }, - "USDT_SNT": { - "SNT": "111527.99375151", - "USDT": "3314.06637263" - }, - "USDT_STR": { - "STR": "975973.89241271", - "USDT": "119159.96377689" - }, - "USDT_XMR": { - "USDT": "44311.82773756", - "XMR": "513.51239329" - }, - "USDT_XRP": { - "USDT": "628653.50566678", - "XRP": "1590094.01666263" - }, - "USDT_ZEC": { - "USDT": "22621.88453883", - "ZEC": "285.13456697" - }, - "USDT_ZRX": { - "USDT": "25505.45281006", - "ZRX": "78505.36961414" - }, - "XMR_BCN": { - "BCN": "15121.34000573", - "XMR": "0.16285090" - }, - "XMR_DASH": { - "DASH": "116.70250730", - "XMR": "199.20221390" - }, - "XMR_LTC": { - "LTC": "118.22421521", - "XMR": "170.93153487" - }, - "XMR_MAID": { - "MAID": "5131.12258542", - "XMR": "11.27396401" - }, - "XMR_NXT": { - "NXT": "4664.12738280", - "XMR": "1.90717544" - }, - "XMR_ZEC": { - "XMR": "18.27667017", - "ZEC": "19.92803337" - }, - "totalBTC": "1628.64800905", - "totalETH": "406.78806917", - "totalUSDC": "5338032.44894085", - "totalUSDT": "8364245.62980983", - "totalXMR": "401.75440929", - "totalXUSD": "0.00000000" + "code": 200, + "data": [], + "msg": "" }, - "queryString": "command=return24hVolume", + "queryString": "limit=100\u0026side=BUY\u0026type=LIMIT", "bodyParams": "", - "headers": {} + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "gWk0KG8LyLoZsOolOsX8Mmy1DCywRtCfS6Q5/raNQXU=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250969923" + ] + } + }, + { + "data": { + "code": 200, + "data": [ + { + "actType": "TRADING", + "avgPx": "0", + "cTime": "1719973298689", + "cancelReason": "ORDER_SOURCE_API", + "clOrdId": "9e36e89c-6cab-45c6-9c8a-245b7547601a", + "deductAmt": "0", + "deductCcy": "0", + "execAmt": "0", + "execQty": "0", + "feeAmt": "0", + "feeCcy": "", + "lever": "20", + "mgnMode": "CROSS", + "ordId": "331378951199129601", + "posSide": "BOTH", + "px": "60000", + "qCcy": "USDT", + "reduceOnly": false, + "side": "SELL", + "slPx": "", + "slTrgPx": "", + "slTrgPxType": "", + "source": "API", + "state": "CANCELED", + "stpMode": "EXPIRE_TAKER", + "symbol": "BTC_USDT_PERP", + "sz": "2", + "timeInForce": "GTC", + "tpPx": "", + "tpTrgPx": "", + "tpTrgPxType": "", + "type": "LIMIT", + "uTime": "1719973454788" + } + ], + "msg": "" + }, + "queryString": "ordId=12345", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "Be2gWGcKey+1yxsEAMiLy10fZeoEIAGJL2vjseCR/ZM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203665465" + ] + } + } + ] + }, + "/v3/trade/order/opens": { + "GET": [ + { + "data": { + "code": 200, + "data": [ + { + "avgPx": "0", + "cTime": "1719974138337", + "clOrdId": "11c033ce-8d86-49e2-9503-f21c61de51ee", + "deductAmt": "0", + "deductCcy": "0", + "execAmt": "0", + "execQty": "0", + "feeAmt": "0", + "feeCcy": "", + "posSide": "BOTH", + "lever": "20", + "mgnMode": "CROSS", + "ordId": "331382472938094592", + "px": "60000", + "reduceOnly": false, + "side": "SELL", + "slPx": "0", + "slTrgPx": "", + "slTrgPxType": "", + "source": "API", + "state": "NEW", + "stpMode": "EXPIRE_TAKER", + "symbol": "BTC_USDT_PERP", + "sz": "2", + "timeInForce": "GTC", + "tpPx": "", + "tpTrgPx": "", + "tpTrgPxType": "", + "actType": "TRADING", + "qCcy": "USDT", + "type": "LIMIT", + "uTime": "1719974161941" + } + ], + "msg": "" + }, + "queryString": "clOrdId=client-given-order-id\u0026direct=NEXT\u0026from=331382472929705985\u0026limit=100\u0026side=SELL\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "INhUHS0L8ZbA4eOplgPBA5NAfu8TPOVgXy/ru/X9ZrM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742815597964" + ] + } + }, + { + "data": { + "code": 200, + "data": [ + { + "avgPx": "0", + "cTime": "1719974138337", + "clOrdId": "11c033ce-8d86-49e2-9503-f21c61de51ee", + "deductAmt": "0", + "deductCcy": "0", + "execAmt": "0", + "execQty": "0", + "feeAmt": "0", + "feeCcy": "", + "posSide": "BOTH", + "lever": "20", + "mgnMode": "CROSS", + "ordId": "331382472938094592", + "px": "60000", + "reduceOnly": false, + "side": "SELL", + "slPx": "0", + "slTrgPx": "", + "slTrgPxType": "", + "source": "API", + "state": "NEW", + "stpMode": "EXPIRE_TAKER", + "symbol": "BTC_USDT_PERP", + "sz": "2", + "timeInForce": "GTC", + "tpPx": "", + "tpTrgPx": "", + "tpTrgPxType": "", + "actType": "TRADING", + "qCcy": "USDT", + "type": "LIMIT", + "uTime": "1719974161941" + } + ], + "msg": "" + }, + "queryString": "clOrdId=1234123\u0026direct=NEXT\u0026ordId=331382472929705985\u0026side=SELL\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "INhUHS0L8ZbA4eOplgPBA5NAfu8TPOVgXy/ru/X9ZrM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1742815597964" + ] + } + }, + { + "data": { + "code": 200, + "data": [], + "msg": "" + }, + "queryString": "", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "qcHHb2Oy3I2fSF5UYx3zSLcfP90Is9PnK5WUYaabuT0=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1744210640941" + ] + } + }, + { + "data": { + "code": 200, + "data": [], + "msg": "" + }, + "queryString": "side=BUY", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "V4OeA0QkQfKSjUSA4mZAvcbNaiD/O38K29HRdhSx9k8=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250969662" + ] + } }, { "data": { - "asks": [ - [ - "0.01087421", - 7.14432824 - ], - [ - "0.01087422", - 0.22865644 - ], - [ - "0.01087442", - 1.9545156 - ], - [ - "0.01090127", - 115.93784476 - ], - [ - "0.01090131", - 61.893 - ] - ], - "bids": [ - [ - "0.01086991", - 4.52422513 - ], - [ - "0.01086990", - 0.08398054 - ], - [ - "0.01085138", - 0.1145743 - ], - [ - "0.01085028", - 7.125 - ], - [ - "0.01085000", - 72.53101291 - ] - ], - "isFrozen": "0", - "seq": 445571843 + "code": 200, + "data": [], + "msg": "" }, - "queryString": "command=returnOrderBook\u0026currencyPair=BTC_XMR\u0026depth=50", + "queryString": "direct=NEXT\u0026limit=100\u0026side=SELL\u0026symbol=BTC_USDT_PERP", "bodyParams": "", - "headers": {} + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "DWowdCyL90qQ3Hc28fCe1HnScNKAmqeR6HE/OVueJjI=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754251004985" + ] + } }, { "data": { - "BTC_ARDR": { - "baseVolume": "3.03108905", - "high24hr": "0.00001333", - "highestBid": "0.00001248", - "id": 177, - "isFrozen": "0", - "last": "0.00001248", - "low24hr": "0.00001220", - "lowestAsk": "0.00001252", - "percentChange": "-0.01732283", - "quoteVolume": "238083.87187020" - }, - "BTC_ATOM": { - "baseVolume": "39.67100725", - "high24hr": "0.00077303", - "highestBid": "0.00074800", - "id": 253, - "isFrozen": "0", - "last": "0.00074800", - "low24hr": "0.00074568", - "lowestAsk": "0.00074909", - "percentChange": "-0.02023708", - "quoteVolume": "52381.46699854" - }, - "BTC_BAT": { - "baseVolume": "2.13275613", - "high24hr": "0.00004245", - "highestBid": "0.00004088", - "id": 210, - "isFrozen": "0", - "last": "0.00004095", - "low24hr": "0.00004087", - "lowestAsk": "0.00004095", - "percentChange": "-0.02777777", - "quoteVolume": "51122.24173657" - }, - "BTC_BCHABC": { - "baseVolume": "36.20758372", - "high24hr": "0.05032733", - "highestBid": "0.04900933", - "id": 236, - "isFrozen": "0", - "last": "0.04900933", - "low24hr": "0.04900932", - "lowestAsk": "0.04904416", - "percentChange": "-0.00782334", - "quoteVolume": "733.46224700" - }, - "BTC_BCHSV": { - "baseVolume": "107.87823714", - "high24hr": "0.02449024", - "highestBid": "0.02375483", - "id": 238, - "isFrozen": "0", - "last": "0.02387932", - "low24hr": "0.02353105", - "lowestAsk": "0.02389139", - "percentChange": "0.00192628", - "quoteVolume": "4528.05891976" - }, - "BTC_BCN": { - "baseVolume": "2.10597417", - "high24hr": "0.00000012", - "highestBid": "0.00000011", - "id": 7, - "isFrozen": "0", - "last": "0.00000012", - "low24hr": "0.00000011", - "lowestAsk": "0.00000012", - "percentChange": "0.00000000", - "quoteVolume": "18580513.78451419" - }, - "BTC_BNT": { - "baseVolume": "0.06242819", - "high24hr": "0.00009088", - "highestBid": "0.00008793", - "id": 232, - "isFrozen": "0", - "last": "0.00008844", - "low24hr": "0.00008666", - "lowestAsk": "0.00008843", - "percentChange": "-0.02609844", - "quoteVolume": "708.36829451" - }, - "BTC_BTS": { - "baseVolume": "11.31814868", - "high24hr": "0.00000804", - "highestBid": "0.00000770", - "id": 14, - "isFrozen": "0", - "last": "0.00000770", - "low24hr": "0.00000764", - "lowestAsk": "0.00000771", - "percentChange": "-0.00900900", - "quoteVolume": "1422525.76536768" - }, - "BTC_CLAM": { - "baseVolume": "2.91928382", - "high24hr": "0.00060427", - "highestBid": "0.00058663", - "id": 20, - "isFrozen": "0", - "last": "0.00058833", - "low24hr": "0.00056130", - "lowestAsk": "0.00059410", - "percentChange": "0.00896930", - "quoteVolume": "5008.88307610" - }, - "BTC_CVC": { - "baseVolume": "0.75331703", - "high24hr": "0.00001123", - "highestBid": "0.00001074", - "id": 194, - "isFrozen": "0", - "last": "0.00001081", - "low24hr": "0.00001070", - "lowestAsk": "0.00001081", - "percentChange": "0.01217228", - "quoteVolume": "68777.88900435" - }, - "BTC_DASH": { - "baseVolume": "121.56922496", - "high24hr": "0.01901934", - "highestBid": "0.01880000", - "id": 24, - "isFrozen": "0", - "last": "0.01880000", - "low24hr": "0.01830550", - "lowestAsk": "0.01880610", - "percentChange": "-0.00407587", - "quoteVolume": "6476.07273599" - }, - "BTC_DCR": { - "baseVolume": "2.34160137", - "high24hr": "0.00350651", - "highestBid": "0.00343891", - "id": 162, - "isFrozen": "0", - "last": "0.00346266", - "low24hr": "0.00336074", - "lowestAsk": "0.00346266", - "percentChange": "0.00119414", - "quoteVolume": "684.41654989" - }, - "BTC_DGB": { - "baseVolume": "16.15966014", - "high24hr": "0.00000172", - "highestBid": "0.00000162", - "id": 25, - "isFrozen": "0", - "last": "0.00000162", - "low24hr": "0.00000160", - "lowestAsk": "0.00000164", - "percentChange": "-0.04142011", - "quoteVolume": "9761759.50030071" - }, - "BTC_DOGE": { - "baseVolume": "19.98598120", - "high24hr": "0.00000039", - "highestBid": "0.00000038", - "id": 27, - "isFrozen": "0", - "last": "0.00000039", - "low24hr": "0.00000038", - "lowestAsk": "0.00000039", - "percentChange": "0.02631578", - "quoteVolume": "52317925.99866673" - }, - "BTC_EOS": { - "baseVolume": "18.59593565", - "high24hr": "0.00081224", - "highestBid": "0.00080063", - "id": 201, - "isFrozen": "0", - "last": "0.00080185", - "low24hr": "0.00079800", - "lowestAsk": "0.00080171", - "percentChange": "-0.00661554", - "quoteVolume": "23099.92132301" - }, - "BTC_ETC": { - "baseVolume": "10.91386394", - "high24hr": "0.00106777", - "highestBid": "0.00102764", - "id": 171, - "isFrozen": "0", - "last": "0.00102820", - "low24hr": "0.00102551", - "lowestAsk": "0.00103251", - "percentChange": "-0.02908404", - "quoteVolume": "10520.96374951" - }, - "BTC_ETH": { - "baseVolume": "155.94348625", - "high24hr": "0.03119996", - "highestBid": "0.03079004", - "id": 148, - "isFrozen": "0", - "last": "0.03079500", - "low24hr": "0.03042230", - "lowestAsk": "0.03081459", - "percentChange": "0.00818332", - "quoteVolume": "5059.54434879" - }, - "BTC_FCT": { - "baseVolume": "10.36741741", - "high24hr": "0.00078617", - "highestBid": "0.00073982", - "id": 155, - "isFrozen": "0", - "last": "0.00073952", - "low24hr": "0.00072961", - "lowestAsk": "0.00074498", - "percentChange": "-0.02689615", - "quoteVolume": "13773.13207446" - }, - "BTC_FOAM": { - "baseVolume": "0.89731724", - "high24hr": "0.00000555", - "highestBid": "0.00000545", - "id": 246, - "isFrozen": "0", - "last": "0.00000550", - "low24hr": "0.00000515", - "lowestAsk": "0.00000550", - "percentChange": "0.05769230", - "quoteVolume": "166155.79008468" - }, - "BTC_GAME": { - "baseVolume": "3.82370347", - "high24hr": "0.00001391", - "highestBid": "0.00001154", - "id": 38, - "isFrozen": "0", - "last": "0.00001153", - "low24hr": "0.00001128", - "lowestAsk": "0.00001176", - "percentChange": "-0.00945017", - "quoteVolume": "300446.22176630" - }, - "BTC_GAS": { - "baseVolume": "0.77232780", - "high24hr": "0.00041046", - "highestBid": "0.00038985", - "id": 198, - "isFrozen": "0", - "last": "0.00039654", - "low24hr": "0.00038985", - "lowestAsk": "0.00039595", - "percentChange": "-0.00284155", - "quoteVolume": "1916.80182489" - }, - "BTC_GNT": { - "baseVolume": "4.93328876", - "high24hr": "0.00001291", - "highestBid": "0.00001260", - "id": 185, - "isFrozen": "0", - "last": "0.00001257", - "low24hr": "0.00001152", - "lowestAsk": "0.00001266", - "percentChange": "0.06887755", - "quoteVolume": "404745.01492216" - }, - "BTC_GRIN": { - "baseVolume": "24.37429922", - "high24hr": "0.00041400", - "highestBid": "0.00038600", - "id": 251, - "isFrozen": "0", - "last": "0.00038601", - "low24hr": "0.00036639", - "lowestAsk": "0.00038831", - "percentChange": "-0.01686065", - "quoteVolume": "62838.47716938" - }, - "BTC_KNC": { - "baseVolume": "1.07605151", - "high24hr": "0.00003550", - "highestBid": "0.00003333", - "id": 207, - "isFrozen": "0", - "last": "0.00003377", - "low24hr": "0.00003371", - "lowestAsk": "0.00003373", - "percentChange": "-0.00295246", - "quoteVolume": "31066.52899332" - }, - "BTC_LBC": { - "baseVolume": "3.00058286", - "high24hr": "0.00000459", - "highestBid": "0.00000438", - "id": 167, - "isFrozen": "0", - "last": "0.00000437", - "low24hr": "0.00000411", - "lowestAsk": "0.00000445", - "percentChange": "0.01627906", - "quoteVolume": "699495.42159049" - }, - "BTC_LOOM": { - "baseVolume": "5.48711026", - "high24hr": "0.00001100", - "highestBid": "0.00001042", - "id": 213, - "isFrozen": "0", - "last": "0.00001042", - "low24hr": "0.00000982", - "lowestAsk": "0.00001048", - "percentChange": "0.03066271", - "quoteVolume": "522861.14578247" - }, - "BTC_LPT": { - "baseVolume": "2.49829681", - "high24hr": "0.00063805", - "highestBid": "0.00062300", - "id": 250, - "isFrozen": "0", - "last": "0.00062300", - "low24hr": "0.00057190", - "lowestAsk": "0.00062500", - "percentChange": "-0.01954612", - "quoteVolume": "4080.23729692" - }, - "BTC_LSK": { - "baseVolume": "5.21884194", - "high24hr": "0.00026000", - "highestBid": "0.00025678", - "id": 163, - "isFrozen": "0", - "last": "0.00025799", - "low24hr": "0.00024928", - "lowestAsk": "0.00025836", - "percentChange": "0.02907857", - "quoteVolume": "20377.01855963" - }, - "BTC_LTC": { - "baseVolume": "666.94447027", - "high24hr": "0.01630000", - "highestBid": "0.01613601", - "id": 50, - "isFrozen": "0", - "last": "0.01617495", - "low24hr": "0.01497000", - "lowestAsk": "0.01617366", - "percentChange": "0.06261463", - "quoteVolume": "42339.40507638" - }, - "BTC_MAID": { - "baseVolume": "2.56267002", - "high24hr": "0.00002442", - "highestBid": "0.00002362", - "id": 51, - "isFrozen": "0", - "last": "0.00002364", - "low24hr": "0.00002351", - "lowestAsk": "0.00002364", - "percentChange": "-0.03194103", - "quoteVolume": "107646.79242367" - }, - "BTC_MANA": { - "baseVolume": "2.70084416", - "high24hr": "0.00000765", - "highestBid": "0.00000740", - "id": 229, - "isFrozen": "0", - "last": "0.00000745", - "low24hr": "0.00000734", - "lowestAsk": "0.00000743", - "percentChange": "-0.00534045", - "quoteVolume": "362727.87722537" - }, - "BTC_NAV": { - "baseVolume": "0.85599154", - "high24hr": "0.00002880", - "highestBid": "0.00002824", - "id": 61, - "isFrozen": "0", - "last": "0.00002838", - "low24hr": "0.00002736", - "lowestAsk": "0.00002850", - "percentChange": "0.03728070", - "quoteVolume": "30239.29066641" - }, - "BTC_NMR": { - "baseVolume": "1.64609151", - "high24hr": "0.00090549", - "highestBid": "0.00086212", - "id": 248, - "isFrozen": "0", - "last": "0.00086057", - "low24hr": "0.00079044", - "lowestAsk": "0.00089787", - "percentChange": "0.06548385", - "quoteVolume": "1912.03148904" - }, - "BTC_NXT": { - "baseVolume": "1.64399713", - "high24hr": "0.00000466", - "highestBid": "0.00000453", - "id": 69, - "isFrozen": "0", - "last": "0.00000454", - "low24hr": "0.00000450", - "lowestAsk": "0.00000455", - "percentChange": "-0.01731601", - "quoteVolume": "360674.76672284" - }, - "BTC_OMG": { - "baseVolume": "1.25616463", - "high24hr": "0.00026071", - "highestBid": "0.00025135", - "id": 196, - "isFrozen": "0", - "last": "0.00025135", - "low24hr": "0.00024544", - "lowestAsk": "0.00025240", - "percentChange": "0.00741482", - "quoteVolume": "4963.85040878" - }, - "BTC_OMNI": { - "baseVolume": "0.20882002", - "high24hr": "0.00029480", - "highestBid": "0.00027236", - "id": 58, - "isFrozen": "0", - "last": "0.00028837", - "low24hr": "0.00027000", - "lowestAsk": "0.00028798", - "percentChange": "0.00215464", - "quoteVolume": "732.64551893" - }, - "BTC_PASC": { - "baseVolume": "1.25124963", - "high24hr": "0.00002870", - "highestBid": "0.00002814", - "id": 184, - "isFrozen": "0", - "last": "0.00002812", - "low24hr": "0.00002670", - "lowestAsk": "0.00002815", - "percentChange": "-0.01678321", - "quoteVolume": "45122.06215166" - }, - "BTC_POLY": { - "baseVolume": "1.91462892", - "high24hr": "0.00001311", - "highestBid": "0.00001306", - "id": 249, - "isFrozen": "0", - "last": "0.00001306", - "low24hr": "0.00001178", - "lowestAsk": "0.00001311", - "percentChange": "0.08471760", - "quoteVolume": "152996.00496795" - }, - "BTC_QTUM": { - "baseVolume": "9.94417285", - "high24hr": "0.00044164", - "highestBid": "0.00039745", - "id": 221, - "isFrozen": "0", - "last": "0.00039711", - "low24hr": "0.00039430", - "lowestAsk": "0.00039946", - "percentChange": "0.01102398", - "quoteVolume": "23898.37003779" - }, - "BTC_REP": { - "baseVolume": "3.58890958", - "high24hr": "0.00249520", - "highestBid": "0.00236841", - "id": 174, - "isFrozen": "0", - "last": "0.00238110", - "low24hr": "0.00233000", - "lowestAsk": "0.00238013", - "percentChange": "0.00882953", - "quoteVolume": "1490.86836755" - }, - "BTC_SC": { - "baseVolume": "1.87511642", - "high24hr": "0.00000040", - "highestBid": "0.00000039", - "id": 150, - "isFrozen": "0", - "last": "0.00000039", - "low24hr": "0.00000039", - "lowestAsk": "0.00000040", - "percentChange": "0.00000000", - "quoteVolume": "4769865.10799687" - }, - "BTC_SNT": { - "baseVolume": "1.74882337", - "high24hr": "0.00000391", - "highestBid": "0.00000377", - "id": 204, - "isFrozen": "0", - "last": "0.00000380", - "low24hr": "0.00000365", - "lowestAsk": "0.00000381", - "percentChange": "0.01063829", - "quoteVolume": "463292.11309769" - }, - "BTC_STEEM": { - "baseVolume": "4.42639165", - "high24hr": "0.00005363", - "highestBid": "0.00005127", - "id": 168, - "isFrozen": "0", - "last": "0.00005167", - "low24hr": "0.00005040", - "lowestAsk": "0.00005160", - "percentChange": "-0.01449551", - "quoteVolume": "85043.49213557" - }, - "BTC_STORJ": { - "baseVolume": "0.59303686", - "high24hr": "0.00003583", - "highestBid": "0.00003506", - "id": 200, - "isFrozen": "0", - "last": "0.00003506", - "low24hr": "0.00003460", - "lowestAsk": "0.00003515", - "percentChange": "0.00228702", - "quoteVolume": "16796.76970761" - }, - "BTC_STR": { - "baseVolume": "29.15587511", - "high24hr": "0.00001571", - "highestBid": "0.00001533", - "id": 89, - "isFrozen": "0", - "last": "0.00001537", - "low24hr": "0.00001532", - "lowestAsk": "0.00001537", - "percentChange": "-0.00646412", - "quoteVolume": "1887833.72135812" - }, - "BTC_STRAT": { - "baseVolume": "3.69185582", - "high24hr": "0.00012497", - "highestBid": "0.00011869", - "id": 182, - "isFrozen": "0", - "last": "0.00011859", - "low24hr": "0.00011892", - "lowestAsk": "0.00011955", - "percentChange": "-0.04006799", - "quoteVolume": "30477.03971572" - }, - "BTC_VIA": { - "baseVolume": "6.00937608", - "high24hr": "0.00007528", - "highestBid": "0.00007216", - "id": 97, - "isFrozen": "0", - "last": "0.00007259", - "low24hr": "0.00007013", - "lowestAsk": "0.00007261", - "percentChange": "0.02862406", - "quoteVolume": "82838.51366051" - }, - "BTC_VTC": { - "baseVolume": "8.10964192", - "high24hr": "0.00006995", - "highestBid": "0.00006727", - "id": 100, - "isFrozen": "0", - "last": "0.00006767", - "low24hr": "0.00006620", - "lowestAsk": "0.00006769", - "percentChange": "-0.00907892", - "quoteVolume": "118741.18466855" - }, - "BTC_XEM": { - "baseVolume": "11.47584618", - "high24hr": "0.00001091", - "highestBid": "0.00001058", - "id": 112, - "isFrozen": "0", - "last": "0.00001060", - "low24hr": "0.00001049", - "lowestAsk": "0.00001063", - "percentChange": "-0.01303538", - "quoteVolume": "1080591.66263058" - }, - "BTC_XMR": { - "baseVolume": "42.01213244", - "high24hr": "0.01102244", - "highestBid": "0.01088305", - "id": 114, - "isFrozen": "0", - "last": "0.01087441", - "low24hr": "0.01079251", - "lowestAsk": "0.01089415", - "percentChange": "-0.00620981", - "quoteVolume": "3857.26226555" - }, - "BTC_XPM": { - "baseVolume": "0.71263628", - "high24hr": "0.00002962", - "highestBid": "0.00002756", - "id": 116, - "isFrozen": "0", - "last": "0.00002756", - "low24hr": "0.00002756", - "lowestAsk": "0.00002860", - "percentChange": "-0.04735568", - "quoteVolume": "24729.03795341" - }, - "BTC_XRP": { - "baseVolume": "201.36631863", - "high24hr": "0.00005090", - "highestBid": "0.00004960", - "id": 117, - "isFrozen": "0", - "last": "0.00004960", - "low24hr": "0.00004933", - "lowestAsk": "0.00004961", - "percentChange": "-0.02131018", - "quoteVolume": "4023790.64131056" - }, - "BTC_ZEC": { - "baseVolume": "6.83567402", - "high24hr": "0.01024922", - "highestBid": "0.00990500", - "id": 178, - "isFrozen": "0", - "last": "0.00990515", - "low24hr": "0.00990501", - "lowestAsk": "0.00993296", - "percentChange": "-0.02472465", - "quoteVolume": "679.67342401" - }, - "BTC_ZRX": { - "baseVolume": "2.07845804", - "high24hr": "0.00004218", - "highestBid": "0.00004080", - "id": 192, - "isFrozen": "0", - "last": "0.00004091", - "low24hr": "0.00004081", - "lowestAsk": "0.00004091", - "percentChange": "-0.00559066", - "quoteVolume": "49776.28138902" - }, - "ETH_BAT": { - "baseVolume": "15.19774324", - "high24hr": "0.00138539", - "highestBid": "0.00132716", - "id": 211, - "isFrozen": "0", - "last": "0.00133065", - "low24hr": "0.00133065", - "lowestAsk": "0.00133346", - "percentChange": "-0.03673809", - "quoteVolume": "11202.68186565" - }, - "ETH_BNT": { - "baseVolume": "14.29896888", - "high24hr": "0.00288000", - "highestBid": "0.00285346", - "id": 233, - "isFrozen": "0", - "last": "0.00287809", - "low24hr": "0.00284999", - "lowestAsk": "0.00288685", - "percentChange": "0.00985614", - "quoteVolume": "5013.99102334" - }, - "ETH_CVC": { - "baseVolume": "7.76889158", - "high24hr": "0.00036357", - "highestBid": "0.00034931", - "id": 195, - "isFrozen": "0", - "last": "0.00034931", - "low24hr": "0.00034633", - "lowestAsk": "0.00035104", - "percentChange": "-0.00498490", - "quoteVolume": "22217.14581100" - }, - "ETH_EOS": { - "baseVolume": "57.85287084", - "high24hr": "0.02644714", - "highestBid": "0.02596530", - "id": 202, - "isFrozen": "0", - "last": "0.02596528", - "low24hr": "0.02596528", - "lowestAsk": "0.02603759", - "percentChange": "-0.01068667", - "quoteVolume": "2204.63200411" - }, - "ETH_ETC": { - "baseVolume": "50.23223183", - "high24hr": "0.03469387", - "highestBid": "0.03340000", - "id": 172, - "isFrozen": "0", - "last": "0.03342225", - "low24hr": "0.03342225", - "lowestAsk": "0.03345178", - "percentChange": "-0.03665230", - "quoteVolume": "1477.91871918" - }, - "ETH_GAS": { - "baseVolume": "3.04307877", - "high24hr": "0.01390000", - "highestBid": "0.01262073", - "id": 199, - "isFrozen": "0", - "last": "0.01300000", - "low24hr": "0.01271658", - "lowestAsk": "0.01309755", - "percentChange": "-0.01555871", - "quoteVolume": "227.12349806" - }, - "ETH_GNT": { - "baseVolume": "33.26795789", - "high24hr": "0.00041473", - "highestBid": "0.00040681", - "id": 186, - "isFrozen": "0", - "last": "0.00040752", - "low24hr": "0.00037826", - "lowestAsk": "0.00041263", - "percentChange": "0.05777916", - "quoteVolume": "85767.44098332" - }, - "ETH_KNC": { - "baseVolume": "3.97445644", - "high24hr": "0.00115000", - "highestBid": "0.00108615", - "id": 208, - "isFrozen": "0", - "last": "0.00109269", - "low24hr": "0.00108891", - "lowestAsk": "0.00114156", - "percentChange": "-0.02501070", - "quoteVolume": "3526.69313018" - }, - "ETH_LOOM": { - "baseVolume": "65.66658897", - "high24hr": "0.00035769", - "highestBid": "0.00033766", - "id": 214, - "isFrozen": "0", - "last": "0.00033930", - "low24hr": "0.00032567", - "lowestAsk": "0.00034802", - "percentChange": "0.02818181", - "quoteVolume": "193088.49239467" - }, - "ETH_LSK": { - "baseVolume": "0.76656131", - "high24hr": "0.00849344", - "highestBid": "0.00828726", - "id": 166, - "isFrozen": "0", - "last": "0.00836598", - "low24hr": "0.00815000", - "lowestAsk": "0.00841578", - "percentChange": "0.02650061", - "quoteVolume": "93.01338152" - }, - "ETH_MANA": { - "baseVolume": "22.07735950", - "high24hr": "0.00025004", - "highestBid": "0.00024084", - "id": 230, - "isFrozen": "0", - "last": "0.00024138", - "low24hr": "0.00024027", - "lowestAsk": "0.00024135", - "percentChange": "-0.00829909", - "quoteVolume": "90624.84430328" - }, - "ETH_OMG": { - "baseVolume": "8.05512623", - "high24hr": "0.00850000", - "highestBid": "0.00816185", - "id": 197, - "isFrozen": "0", - "last": "0.00823187", - "low24hr": "0.00812951", - "lowestAsk": "0.00820725", - "percentChange": "0.01803604", - "quoteVolume": "971.21438737" - }, - "ETH_QTUM": { - "baseVolume": "19.21848012", - "high24hr": "0.01445578", - "highestBid": "0.01286128", - "id": 222, - "isFrozen": "0", - "last": "0.01279123", - "low24hr": "0.01279123", - "lowestAsk": "0.01292445", - "percentChange": "0.01196680", - "quoteVolume": "1428.71665478" - }, - "ETH_REP": { - "baseVolume": "43.83047186", - "high24hr": "0.08044678", - "highestBid": "0.07691404", - "id": 176, - "isFrozen": "0", - "last": "0.07729862", - "low24hr": "0.07610657", - "lowestAsk": "0.07729862", - "percentChange": "0.00550880", - "quoteVolume": "566.61066154" - }, - "ETH_SNT": { - "baseVolume": "11.98247233", - "high24hr": "0.00012595", - "highestBid": "0.00012281", - "id": 205, - "isFrozen": "0", - "last": "0.00012341", - "low24hr": "0.00011976", - "lowestAsk": "0.00012330", - "percentChange": "-0.00684049", - "quoteVolume": "97344.62846475" - }, - "ETH_STEEM": { - "baseVolume": "6.47349009", - "high24hr": "0.00175423", - "highestBid": "0.00166580", - "id": 169, - "isFrozen": "0", - "last": "0.00167610", - "low24hr": "0.00165255", - "lowestAsk": "0.00168151", - "percentChange": "-0.03115606", - "quoteVolume": "3859.75860945" - }, - "ETH_ZEC": { - "baseVolume": "20.70785072", - "high24hr": "0.33600013", - "highestBid": "0.32237743", - "id": 179, - "isFrozen": "0", - "last": "0.32250027", - "low24hr": "0.32250027", - "lowestAsk": "0.32473808", - "percentChange": "-0.03832020", - "quoteVolume": "63.08405800" - }, - "ETH_ZRX": { - "baseVolume": "22.37346857", - "high24hr": "0.00137937", - "highestBid": "0.00132743", - "id": 193, - "isFrozen": "0", - "last": "0.00132759", - "low24hr": "0.00132759", - "lowestAsk": "0.00132744", - "percentChange": "-0.01595125", - "quoteVolume": "16548.11602204" - }, - "USDC_ATOM": { - "baseVolume": "8589.72151742", - "high24hr": "6.13222707", - "highestBid": "5.91425840", - "id": 254, - "isFrozen": "0", - "last": "5.94846938", - "low24hr": "5.77734693", - "lowestAsk": "5.98266834", - "percentChange": "0.00578678", - "quoteVolume": "1435.15971856" - }, - "USDC_BCHABC": { - "baseVolume": "135429.66946378", - "high24hr": "401.17968999", - "highestBid": "389.35541111", - "id": 237, - "isFrozen": "0", - "last": "389.35423311", - "low24hr": "376.01059082", - "lowestAsk": "393.59958829", - "percentChange": "0.03548741", - "quoteVolume": "345.71602989" - }, - "USDC_BCHSV": { - "baseVolume": "219303.91833302", - "high24hr": "194.44671873", - "highestBid": "188.54624615", - "id": 239, - "isFrozen": "0", - "last": "188.54622778", - "low24hr": "180.49999776", - "lowestAsk": "190.89997204", - "percentChange": "0.03030725", - "quoteVolume": "1158.73869926" - }, - "USDC_BTC": { - "baseVolume": "3482664.85806597", - "high24hr": "8077.47999788", - "highestBid": "7961.71516578", - "id": 224, - "isFrozen": "0", - "last": "7962.50000000", - "low24hr": "7608.58328444", - "lowestAsk": "7977.13341202", - "percentChange": "0.04403385", - "quoteVolume": "441.87385476" - }, - "USDC_DOGE": { - "baseVolume": "2750.23843586", - "high24hr": "0.00310197", - "highestBid": "0.00303215", - "id": 243, - "isFrozen": "0", - "last": "0.00303215", - "low24hr": "0.00297500", - "lowestAsk": "0.00306000", - "percentChange": "0.01921008", - "quoteVolume": "907350.09402904" - }, - "USDC_ETH": { - "baseVolume": "501153.45720283", - "high24hr": "248.44047988", - "highestBid": "245.35955433", - "id": 225, - "isFrozen": "0", - "last": "245.36055774", - "low24hr": "233.31933799", - "lowestAsk": "246.00046378", - "percentChange": "0.05094127", - "quoteVolume": "2047.00238213" - }, - "USDC_FOAM": { - "baseVolume": "722.65429834", - "high24hr": "0.04381000", - "highestBid": "0.04380999", - "id": 247, - "isFrozen": "0", - "last": "0.04380999", - "low24hr": "0.03968067", - "lowestAsk": "0.04381000", - "percentChange": "0.08844695", - "quoteVolume": "16885.98552482" - }, - "USDC_GRIN": { - "baseVolume": "23814.63241472", - "high24hr": "3.16500000", - "highestBid": "3.04000004", - "id": 252, - "isFrozen": "0", - "last": "3.11998999", - "low24hr": "2.89999999", - "lowestAsk": "3.10999999", - "percentChange": "0.02294753", - "quoteVolume": "7937.02292983" - }, - "USDC_LTC": { - "baseVolume": "566449.26199652", - "high24hr": "129.99999999", - "highestBid": "128.27905224", - "id": 244, - "isFrozen": "0", - "last": "128.93961490", - "low24hr": "114.11407952", - "lowestAsk": "128.93961440", - "percentChange": "0.10369106", - "quoteVolume": "4496.10093795" - }, - "USDC_STR": { - "baseVolume": "21935.95722630", - "high24hr": "0.12485687", - "highestBid": "0.12186123", - "id": 242, - "isFrozen": "0", - "last": "0.12152532", - "low24hr": "0.11824094", - "lowestAsk": "0.12344054", - "percentChange": "0.02557729", - "quoteVolume": "178840.89704069" - }, - "USDC_USDT": { - "baseVolume": "57933.50068393", - "high24hr": "1.00849999", - "highestBid": "1.00420002", - "id": 226, - "isFrozen": "0", - "last": "1.00420002", - "low24hr": "1.00048874", - "lowestAsk": "1.00519997", - "percentChange": "0.00170380", - "quoteVolume": "57719.93500183" - }, - "USDC_XMR": { - "baseVolume": "99062.18940901", - "high24hr": "87.99994711", - "highestBid": "86.23864800", - "id": 241, - "isFrozen": "0", - "last": "87.18629626", - "low24hr": "83.40045078", - "lowestAsk": "87.13843846", - "percentChange": "0.04513660", - "quoteVolume": "1147.67641269" - }, - "USDC_XRP": { - "baseVolume": "199920.97825116", - "high24hr": "0.40499909", - "highestBid": "0.39407291", - "id": 240, - "isFrozen": "0", - "last": "0.39275049", - "low24hr": "0.38130058", - "lowestAsk": "0.39644645", - "percentChange": "0.00705997", - "quoteVolume": "501260.01445723" - }, - "USDC_ZEC": { - "baseVolume": "18301.41164199", - "high24hr": "81.51460533", - "highestBid": "78.78616778", - "id": 245, - "isFrozen": "0", - "last": "79.00000000", - "low24hr": "77.79410548", - "lowestAsk": "79.66042211", - "percentChange": "0.00697317", - "quoteVolume": "229.40589669" - }, - "USDT_ATOM": { - "baseVolume": "125149.60868108", - "high24hr": "6.09972825", - "highestBid": "5.91263924", - "id": 255, - "isFrozen": "0", - "last": "5.93000005", - "low24hr": "5.74700000", - "lowestAsk": "5.96804558", - "percentChange": "0.02241380", - "quoteVolume": "21087.06757208" - }, - "USDT_BAT": { - "baseVolume": "19328.23384182", - "high24hr": "0.33689089", - "highestBid": "0.32445561", - "id": 212, - "isFrozen": "0", - "last": "0.32726271", - "low24hr": "0.32026548", - "lowestAsk": "0.32705989", - "percentChange": "0.01806377", - "quoteVolume": "58700.42769184" - }, - "USDT_BNT": { - "baseVolume": "363.53451604", - "high24hr": "0.70982964", - "highestBid": "0.69821937", - "id": 234, - "isFrozen": "0", - "last": "0.69821937", - "low24hr": "0.68340485", - "lowestAsk": "0.70982400", - "percentChange": "0.00089890", - "quoteVolume": "514.58745683" - }, - "USDT_BTC": { - "baseVolume": "4421897.17330826", - "high24hr": "8010.00000000", - "highestBid": "7934.30612610", - "id": 121, - "isFrozen": "0", - "last": "7938.84630781", - "low24hr": "7594.72485562", - "lowestAsk": "7939.11267940", - "percentChange": "0.04175843", - "quoteVolume": "561.77921782" - }, - "USDT_DASH": { - "baseVolume": "163148.07688044", - "high24hr": "151.49790691", - "highestBid": "148.18792540", - "id": 122, - "isFrozen": "0", - "last": "149.00000000", - "low24hr": "141.36289327", - "lowestAsk": "149.49998944", - "percentChange": "0.03081761", - "quoteVolume": "1097.22131727" - }, - "USDT_DOGE": { - "baseVolume": "30256.35268923", - "high24hr": "0.00305492", - "highestBid": "0.00303372", - "id": 216, - "isFrozen": "0", - "last": "0.00303376", - "low24hr": "0.00294256", - "lowestAsk": "0.00304854", - "percentChange": "0.02803427", - "quoteVolume": "10052886.96556405" - }, - "USDT_EOS": { - "baseVolume": "278043.19290915", - "high24hr": "6.49451490", - "highestBid": "6.33676472", - "id": 203, - "isFrozen": "0", - "last": "6.33455816", - "low24hr": "6.06318315", - "lowestAsk": "6.38358433", - "percentChange": "0.01939777", - "quoteVolume": "43736.05905905" - }, - "USDT_ETC": { - "baseVolume": "143484.54569522", - "high24hr": "8.38997233", - "highestBid": "8.15001491", - "id": 173, - "isFrozen": "0", - "last": "8.15001414", - "low24hr": "7.88066582", - "lowestAsk": "8.17000000", - "percentChange": "0.01628235", - "quoteVolume": "17511.35515526" - }, - "USDT_ETH": { - "baseVolume": "883511.34773111", - "high24hr": "247.86593850", - "highestBid": "243.60640010", - "id": 149, - "isFrozen": "0", - "last": "243.56443038", - "low24hr": "232.63838377", - "lowestAsk": "244.56399997", - "percentChange": "0.04452331", - "quoteVolume": "3668.33116661" - }, - "USDT_GNT": { - "baseVolume": "13022.42294546", - "high24hr": "0.10259935", - "highestBid": "0.09879707", - "id": 217, - "isFrozen": "0", - "last": "0.09841380", - "low24hr": "0.08921015", - "lowestAsk": "0.10132826", - "percentChange": "0.09122782", - "quoteVolume": "136510.36772013" - }, - "USDT_KNC": { - "baseVolume": "3460.19386639", - "high24hr": "0.27487268", - "highestBid": "0.26681722", - "id": 209, - "isFrozen": "0", - "last": "0.26815800", - "low24hr": "0.24150034", - "lowestAsk": "0.27081578", - "percentChange": "0.04138446", - "quoteVolume": "12879.73674180" - }, - "USDT_LOOM": { - "baseVolume": "7884.22722657", - "high24hr": "0.08800000", - "highestBid": "0.08138381", - "id": 215, - "isFrozen": "0", - "last": "0.08366370", - "low24hr": "0.07699900", - "lowestAsk": "0.08582526", - "percentChange": "0.10209527", - "quoteVolume": "94061.17501115" - }, - "USDT_LSK": { - "baseVolume": "13223.12589230", - "high24hr": "2.07878065", - "highestBid": "2.02319825", - "id": 218, - "isFrozen": "0", - "last": "2.04000000", - "low24hr": "1.90125984", - "lowestAsk": "2.04000000", - "percentChange": "0.05997011", - "quoteVolume": "6568.77436503" - }, - "USDT_LTC": { - "baseVolume": "1316866.42418109", - "high24hr": "129.80000000", - "highestBid": "127.31927721", - "id": 123, - "isFrozen": "0", - "last": "128.29999999", - "low24hr": "114.19423572", - "lowestAsk": "128.29999899", - "percentChange": "0.10600510", - "quoteVolume": "10573.16167640" - }, - "USDT_MANA": { - "baseVolume": "3529.09794786", - "high24hr": "0.06000000", - "highestBid": "0.05875324", - "id": 231, - "isFrozen": "0", - "last": "0.05874674", - "low24hr": "0.05685000", - "lowestAsk": "0.06023530", - "percentChange": "0.02910433", - "quoteVolume": "59699.03615938" - }, - "USDT_NXT": { - "baseVolume": "10352.62135341", - "high24hr": "0.03725000", - "highestBid": "0.03565562", - "id": 124, - "isFrozen": "0", - "last": "0.03564433", - "low24hr": "0.03465000", - "lowestAsk": "0.03661779", - "percentChange": "0.01783769", - "quoteVolume": "287419.90703917" - }, - "USDT_QTUM": { - "baseVolume": "39682.13887751", - "high24hr": "3.38228600", - "highestBid": "3.15135845", - "id": 223, - "isFrozen": "0", - "last": "3.15643449", - "low24hr": "3.01724000", - "lowestAsk": "3.19643113", - "percentChange": "0.04613305", - "quoteVolume": "12370.15246589" - }, - "USDT_REP": { - "baseVolume": "21917.80239715", - "high24hr": "19.50000000", - "highestBid": "18.73413490", - "id": 175, - "isFrozen": "0", - "last": "18.81359647", - "low24hr": "18.07435000", - "lowestAsk": "18.81359647", - "percentChange": "0.04529910", - "quoteVolume": "1157.81116881" - }, - "USDT_SC": { - "baseVolume": "25558.80796699", - "high24hr": "0.00315902", - "highestBid": "0.00310953", - "id": 219, - "isFrozen": "0", - "last": "0.00310875", - "low24hr": "0.00301287", - "lowestAsk": "0.00315390", - "percentChange": "0.02377361", - "quoteVolume": "8307626.97734275" - }, - "USDT_SNT": { - "baseVolume": "3314.06637263", - "high24hr": "0.03099999", - "highestBid": "0.02965894", - "id": 206, - "isFrozen": "0", - "last": "0.03002016", - "low24hr": "0.02852000", - "lowestAsk": "0.03099489", - "percentChange": "0.05260397", - "quoteVolume": "111527.99375151" - }, - "USDT_STR": { - "baseVolume": "119159.96377689", - "high24hr": "0.12367652", - "highestBid": "0.12155670", - "id": 125, - "isFrozen": "0", - "last": "0.12153229", - "low24hr": "0.11783976", - "lowestAsk": "0.12192981", - "percentChange": "0.02869133", - "quoteVolume": "975973.89241271" - }, - "USDT_XMR": { - "baseVolume": "44311.82773756", - "high24hr": "87.30000000", - "highestBid": "86.01288637", - "id": 126, - "isFrozen": "0", - "last": "86.80322950", - "low24hr": "83.20226300", - "lowestAsk": "86.63121390", - "percentChange": "0.03842924", - "quoteVolume": "513.51239329" - }, - "USDT_XRP": { - "baseVolume": "628653.50566678", - "high24hr": "0.40300000", - "highestBid": "0.39152696", - "id": 127, - "isFrozen": "0", - "last": "0.39377688", - "low24hr": "0.38130000", - "lowestAsk": "0.39377649", - "percentChange": "0.01987867", - "quoteVolume": "1590094.01666263" - }, - "USDT_ZEC": { - "baseVolume": "22621.88453883", - "high24hr": "81.19999999", - "highestBid": "78.59493102", - "id": 180, - "isFrozen": "0", - "last": "78.59493101", - "low24hr": "77.53260899", - "lowestAsk": "79.24350590", - "percentChange": "0.01370161", - "quoteVolume": "285.13456697" - }, - "USDT_ZRX": { - "baseVolume": "25505.45281006", - "high24hr": "0.33012685", - "highestBid": "0.32372112", - "id": 220, - "isFrozen": "0", - "last": "0.32372110", - "low24hr": "0.31581054", - "lowestAsk": "0.32556376", - "percentChange": "0.02641624", - "quoteVolume": "78505.36961414" - }, - "XMR_BCN": { - "baseVolume": "0.16285090", - "high24hr": "0.00001086", - "highestBid": "0.00001077", - "id": 129, - "isFrozen": "0", - "last": "0.00001085", - "low24hr": "0.00001076", - "lowestAsk": "0.00001085", - "percentChange": "0.00370027", - "quoteVolume": "15121.34000573" - }, - "XMR_DASH": { - "baseVolume": "199.20221390", - "high24hr": "1.74792000", - "highestBid": "1.70985983", - "id": 132, - "isFrozen": "0", - "last": "1.71734933", - "low24hr": "1.69000000", - "lowestAsk": "1.72597923", - "percentChange": "-0.00135971", - "quoteVolume": "116.70250730" - }, - "XMR_LTC": { - "baseVolume": "170.93153487", - "high24hr": "1.49999000", - "highestBid": "1.47456588", - "id": 137, - "isFrozen": "0", - "last": "1.47455980", - "low24hr": "1.37511020", - "lowestAsk": "1.48934226", - "percentChange": "0.06048168", - "quoteVolume": "118.22421521" - }, - "XMR_MAID": { - "baseVolume": "11.27396401", - "high24hr": "0.00219909", - "highestBid": "0.00215074", - "id": 138, - "isFrozen": "0", - "last": "0.00215539", - "low24hr": "0.00215539", - "lowestAsk": "0.00218535", - "percentChange": "-0.01503907", - "quoteVolume": "5131.12258542" - }, - "XMR_NXT": { - "baseVolume": "1.90717544", - "high24hr": "0.00042734", - "highestBid": "0.00040892", - "id": 140, - "isFrozen": "0", - "last": "0.00040927", - "low24hr": "0.00040123", - "lowestAsk": "0.00041471", - "percentChange": "-0.02296545", - "quoteVolume": "4664.12738280" - }, - "XMR_ZEC": { - "baseVolume": "18.27667017", - "high24hr": "0.93682194", - "highestBid": "0.90478668", - "id": 181, - "isFrozen": "0", - "last": "0.91217810", - "low24hr": "0.90298672", - "lowestAsk": "0.91363635", - "percentChange": "-0.01510586", - "quoteVolume": "19.92803337" - } + "code": 200, + "data": [ + { + "avgPx": "0", + "cTime": "1719974138337", + "clOrdId": "11c033ce-8d86-49e2-9503-f21c61de51ee", + "deductAmt": "0", + "deductCcy": "0", + "execAmt": "0", + "execQty": "0", + "feeAmt": "0", + "feeCcy": "", + "posSide": "BOTH", + "lever": "20", + "mgnMode": "CROSS", + "ordId": "331382472938094592", + "px": "60000", + "reduceOnly": false, + "side": "SELL", + "slPx": "0", + "slTrgPx": "", + "slTrgPxType": "", + "source": "API", + "state": "NEW", + "stpMode": "EXPIRE_TAKER", + "symbol": "BTC_USDT_PERP", + "sz": "2", + "timeInForce": "GTC", + "tpPx": "", + "tpTrgPx": "", + "tpTrgPxType": "", + "actType": "TRADING", + "qCcy": "USDT", + "type": "LIMIT", + "uTime": "1719974161941" + } + ], + "msg": "" }, - "queryString": "command=returnTicker", + "queryString": "clOrdId=NEXT\u0026limit=100\u0026side=SELL\u0026symbol=BTC_USDT_PERP", "bodyParams": "", - "headers": {} + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "DWowdCyL90qQ3Hc28fCe1HnScNKAmqeR6HE/OVueJjI=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754251004985" + ] + } } ] }, - "/timestamp": { + "/v3/trade/order/trades": { "GET": [ { "data": { - "serverTime": 1679366387677 + "code": 200, + "data": [ + { + "cTime": "1719973930900", + "clOrdId": "polo331381602863284224", + "deductAmt": "0", + "deductCcy": "", + "feeAmt": "0.00009405", + "feeCcy": "USDT", + "feeRate": "0.0005", + "id": "331381604734197760", + "mgnMode": "CROSS", + "posSide": "BOTH", + "ordType": "MARKET", + "px": "60000", + "qty": "3", + "role": "TAKER", + "side": "SELL", + "symbol": "BTC_USDT_PERP", + "ordId": "356743696043233280", + "trdId": "100000010", + "type": "TRADE", + "actType": "TRADING", + "qCcy": "USDT", + "value": "1000", + "uTime": "1719973930924" + } + ], + "msg": "" }, - "queryString": "", + "queryString": "clOrdId=polo331381602863284224\u0026direct=NEXT\u0026eTime=1743702190295\u0026from=1\u0026limit=100\u0026ordId=331381604734197760\u0026sTime=1743615790295\u0026side=BUY\u0026symbol=BTC_USDT_PERP", "bodyParams": "", - "headers": {} + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "CcCe2ANc2+wp4WrH+qnzznf26Z5uJHv8VUqFJsV8wR4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1758203663412" + ] + } } ] }, - "/tradingApi": { + "/v3/trade/position": { "POST": [ { "data": { - "response": "Withdrew 0.0 LTC." + "code": 200, + "data": { + "clOrdId": "12345", + "ordId": "331380687661957120" + }, + "msg": "Success" }, "queryString": "", - "bodyParams": "address=bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc\u0026amount=0.00001337\u0026command=withdraw\u0026currency=LTC\u0026nonce=1594157624217368003", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"mgnMode\":\"CROSS\"}", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "46c514cbdf18540b2a649effcda84c149db8f0934462113a4ac12959f2b437f64aa1f7056aeafce823705daa83200a41bc7a7cfbe9cfaef52fe482b71b14aea4" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "MMBoIOMeGmJGXWpi8QHGKiQg/H5gwz20AVJnuGtdsos=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970262" ] } }, { "data": { - "response": "Please use the following previously generated deposit address: LeFFAYmkSaU7ZhR3Ucq4Fvg4z1QTd9mmMN", - "success": 0 + "code": 200, + "data": { + "clOrdId": "12345", + "ordId": "331380687661957120" + }, + "msg": "Success" }, "queryString": "", - "bodyParams": "command=generateNewAddress\u0026currency=LTC\u0026nonce=1629687075227014300", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"mgnMode\":\"CROSS\",\"clOrdId\":\"123123\"}", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "ac25fc0b6c0b5d8c4784776a1ebb4a4ce97f6201fab8bdfae47589cdb1b4ab5e18875b14d4cac2412109e36ded103f9dc05a888f482e2d47132955099410f216" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "MMBoIOMeGmJGXWpi8QHGKiQg/H5gwz20AVJnuGtdsos=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970262" ] } - }, + } + ] + }, + "/v3/trade/position/history": { + "GET": [ { "data": { - "response": "Please use the following previously generated deposit address: 1083644748", - "success": 0 + "code": 200, + "data": [ + { + "availQty": "0", + "cTime": "1719910544000", + "closeAvgPx": "0.6271", + "closedQty": "-2", + "fFee": "0.0000025", + "fee": "-0.00012541", + "id": "101000367", + "mgnMode": "CROSS", + "openAvgPx": "0.627", + "pnl": "-0.00002", + "posSide": "BOTH", + "qty": "0", + "side": "SELL", + "state": "NORMAL", + "symbol": "BTC_USDT_PERP", + "uTime": "1719916971000" + } + ], + "msg": "" }, - "queryString": "", - "bodyParams": "command=generateNewAddress\u0026currency=XRP\u0026nonce=1629687130881488000", + "queryString": "direct=NEXT\u0026eTime=1743702190295\u0026from=1\u0026limit=100\u0026mgnMode=ISOLATED\u0026posSide=LONG\u0026sTime=1743615790295\u0026symbol=BTC_USDT_PERP", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "0d30720d6cf1cc5db3742c89001d562e097c6aa8df0f0c1395a97c1105a4006e96d503b99b337e76e4ac86f93d2c3e89a74d0c48a60fd99dd11a4c5b4110f094" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "suaDDlqcTZzkqrXSppIlCrC6earE3cgElcddbyJAn0c=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250970112" ] } - }, + } + ] + }, + "/v3/trade/position/margin": { + "POST": [ { "data": { - "1CR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AAVE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ABY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ACH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ADABEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ADABULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ADD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ADEL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ADN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AEON": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AERO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AIR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AKITA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AKRO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ALPHA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AMP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "APH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "API3": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ARCH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ARDR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ATOM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AUR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AVA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "AXIS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BAC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BADGER": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BAL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BALLS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BAND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BANK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BAS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BAT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BBL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BBR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCH": { - "available": "0.00000005", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCHA": { - "available": "0.00000005", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCHABC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCHBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCHBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCHC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCHSV": { - "available": "0.00000005", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BCY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BDC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BDG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BDP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BELA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BID": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BITCNY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BITS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BITUSD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BLK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BLOCK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BLU": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BLY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BNB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BNS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BNT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BOND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BONES": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BOST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BREE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BRG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BSVBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BSVBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTCD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTCS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTCST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BTT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BURN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BURST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BUSD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BVOL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "BZRX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "C2": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CACH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CAI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CCN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CGA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CHA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CHR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CINNI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CLAM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CNL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CNMT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CNOTE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "COMBO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "COMM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "COMP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CON": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CORG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CORN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "COVER": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CREAM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CRT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CRV": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CRYPT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CUDOS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CURE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CUSDT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CVC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CVP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CVT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "CYC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DAI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DAO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DASH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DCR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DEC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DEXT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DGB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DHT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DIA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DICE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DIEM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DIME": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DIS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DMG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DNS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DOGE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DOS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DOT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DRKC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DRM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DSH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "DVK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EAC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EBT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ECC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EFL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EMC2": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EMO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ENC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EOS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EOSBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EOSBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ESD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ETC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ETH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ETHBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ETHBNT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ETHBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EXE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "EXP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FAC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FARM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FCN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FCT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FCT2": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FIBRE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FIL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FLAP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FLDC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FLO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FLT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FOAM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FOX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FRAC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FRK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FRONT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FRQ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FSW": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FTT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FUND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FVZ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FXC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FZ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "FZN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GAME": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GAP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GAS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GDN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GEEQ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GEMZ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GEO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GHST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GIAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GLB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GLM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GML": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GNO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GNS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GNT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GOLD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GPC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GPUC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GRC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GRCX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GRIN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GRS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GRT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "GUE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "H2O": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HEGIC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HGET": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HIRO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HOT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HUC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HUGE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HVC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HYP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "HZ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "IBVOL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "IFC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "INDEX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "INJ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "IOC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ITC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "IXC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "JFI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "JLH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "JPC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "JST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "JUG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "KDC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "KEY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "KNC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "KP3R": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "KTON": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LBC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LCL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LEAF": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LEND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LGC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LINK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LINKBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LINKBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LIVE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LOL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LON": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LOOM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LOVE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LPT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LQD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LRC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LSK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LTBC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LTCBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LTCBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "LTCX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MAID": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MANA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MAST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MATIC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MAX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MCB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MCN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MDT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MEC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MEME": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "METH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MEXP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MIL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MIN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MINT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MKR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MMC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MMNXT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MMXIV": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MNTA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MON": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MPH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MRC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MRS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MTA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MTS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MUN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MYR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "MZC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "N5X": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NAS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NAUT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NAV": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NBT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NEO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NEOS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NMC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NMR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NOBL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NOTE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NOXT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NRS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NSR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NTX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NU": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NXC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NXT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "NXTI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "OCEAN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "OM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "OMG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "OMNI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ONEINCH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "OPAL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "OPT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PAND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PASC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PAWN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PAX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PBTC35A": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PEARL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PERX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PIGGY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PINK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PLT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PLX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PMC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "POLS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "POLY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "POT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PPC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PRC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PRQ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PRT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "PTS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "Q2C": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "QBK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "QCN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "QORA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "QTL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "QTUM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RADS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RARI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RBY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RDD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "REEF": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "REN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "REPV2": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RFUEL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RIC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RING": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ROOK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RSR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "RZR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SAL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SAND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SBD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SBREE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SDC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SENSO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SFI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SHIB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SHIBE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SHOPX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SILK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SJCX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SLR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SMC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SNT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SNX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SOC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SPA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SQL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SRCC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SRG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SRM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SSD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "STAKE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "STEEM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "STORJ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "STPT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "STR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "STRAT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SUM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SUN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SUSHI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SWAP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SWARM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SWFTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SWINGBY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SWRV": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SXC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SXP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SYNC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "SYS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TAC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TAI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TEND": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TOR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TORN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRADE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRU": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRUMPWIN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRUST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRXBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TRXBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TUSD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "TWE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "UIS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ULTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "UMA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "UNI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "UNITY": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "URO": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "USDC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "USDE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "USDJ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "USDT": { - "available": "5.81871750", - "btcValue": "0.00010159", - "onOrders": "0.00000000" - }, - "UTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "UTIL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "UVC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VALUE": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VIA": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VOOT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VOX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VRC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VSP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "VTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WBTC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WDC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WETH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WIKI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WIN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WNXM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WOLF": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "WRX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "X13": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XAI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XAP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XBC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XCH": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XCN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XCP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XCR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XDN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XDOT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XDP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XEM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XFLR": { - "available": "40.14000000", - "btcValue": "0.00022787", - "onOrders": "0.00000000" - }, - "XHC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XLB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XLMBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XLMBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XMG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XMR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XPB": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XPM": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XRP": { - "available": "40.14000000", - "btcValue": "0.00100470", - "onOrders": "0.00000000" - }, - "XRPBEAR": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XRPBULL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XSI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XST": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XSV": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XTZ": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XUSD": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XVC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "XXC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YACC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YANG": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YFI": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YFII": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YFL": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YFV": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "YIN": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ZAP": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ZEC": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ZKS": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ZLOT": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "ZRX": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - }, - "eTOK": { - "available": "0.00000000", - "btcValue": "0.00000000", - "onOrders": "0.00000000" - } + "code": 400, + "msg": "Param error symbol" }, "queryString": "", - "bodyParams": "account=all\u0026command=returnCompleteBalances\u0026nonce=1755565288536153000", + "bodyParams": "{\"symbol\":\"DOT_USDT_PERP\",\"amt\":\"123\",\"type\":\"ADD\"}", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "19170bbc1f7f8101aa50a857daa0702f8f40d6487621ec4defccd81ffa001a561fb172b796c274b739cc9a978683b13c326f266b8d511d9b9b83dbc50c78d06b" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "YohCDmE0F1fX8uppWnznMC8GscF8/8PsrlmtO8qVkpw=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1734076349302" ] } }, { "data": { - "BCH": "1FNVZjj3cJLpBtSmrBmun5KzC8XVmKH6LF", - "BCHABC": "1FNVZjj3cJLpBtSmrBmun5KzC8XVmKH6LF", - "BCHSV": "1FNVZjj3cJLpBtSmrBmun5KzC8XVmKH6LF", - "BNB": "bnb1fp33lzp8m0vqk75x6ny658qfwd9s5nwjlqkqdj", - "BSC": "0x3d20500b96e03e338e24991f5e623cb4fcf839be", - "BTC": "1KX2MNB1u2K1TU5md5BT2kn3rpHCNibpta", - "ETH": "0x7d28c2eee6ff17c50be3846d82bf179cb0edf69b", - "LTC": "LeFFAYmkSaU7ZhR3Ucq4Fvg4z1QTd9mmMN", - "USDTETH": "0x7d28c2eee6ff17c50be3846d82bf179cb0edf69b", - "USDTTRON": "TAULWokojh69qPmfEyf85L9iCsc8X8F4sE", - "XRP": "1083644748" + "code": 200, + "data": { + "amt": "50", + "lever": "20", + "symbol": "DOT_USDT_PERP", + "posSide": "BOTH", + "type": "ADD" + }, + "msg": "Success" }, "queryString": "", - "bodyParams": "command=returnDepositAddresses\u0026nonce=1755565288536153001", + "bodyParams": "{\"symbol\":\"BTC_USDT_PERP\",\"amt\":\"123\",\"type\":\"ADD\"}", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "23c29f815b29e8116ee36857606c83633f3938d0ee149c565b9bdc58353f0fb7b7e53abe505346b92c32941013d5bca68edf4af88789f36cbf8f9dd3e62607da" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "0peAv1nbJ2B1m2b3HVz53saag3XbRyOGPaNwxHbXo6A=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743949699366" ] } - }, + } + ] + }, + "/v3/trade/position/opens": { + "GET": [ { "data": { - "orderNumber": "514851232549", - "resultingTrades": { - "BTC_ETH": [] - }, - "success": 1 + "code": 200, + "data": [ + { + "adl": "0.1666", + "availQty": "1", + "cTime": "1719894977164", + "im": "1.955006333333333333", + "lever": "30", + "liqPx": "0", + "markPx": "58650.19", + "lastPx": "58650.19", + "indexPx": "58650.19", + "mgn": "1.955006333333333333", + "maxWAmt": "100000", + "mgnMode": "CROSS", + "posSide": "BOTH", + "mgnRatio": "0", + "mm": "0.322576045", + "openAvgPx": "58651", + "pnl": "0", + "qty": "1", + "side": "BUY", + "state": "NORMAL", + "actType": "TRADING", + "tpTrgPx": "58670", + "slTrgPx": "61003", + "symbol": "BTC_USDT_PERP", + "uTime": "1719974554434", + "upl": "-0.00081", + "uplRatio": "-0.0004" + } + ], + "msg": "Success" }, - "queryString": "", - "bodyParams": "command=moveOrder\u0026nonce=1755565288536153002\u0026orderNumber=1337\u0026rate=1337", + "queryString": "symbol=BTC_USDT_PERP", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "83c9fd8c4cfcf63e76d44b824ad381261b17b572e5eab1f1ead8de7206cfaaf153f2e25c8f12ce2ba88b2641e8bc51e500ca762fa562ed482a1063b7ddfb77cf" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "00//ytmPEfmTaKZ6UgQd6jfHsAIUuLlQCYgfp8N5D2A=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743701838034" ] } }, { "data": { - "amount": "50.00000000", - "message": "Order #1 canceled.", - "success": 1 + "code": 200, + "data": [], + "msg": "" }, "queryString": "", - "bodyParams": "command=cancelOrder\u0026nonce=1755565288536153004\u0026orderNumber=1", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "8f408258738ba7d66d3003bd920fd0d6dad78cfcb7c013b5344d61b029af52e45b82f540e1f588cde725e371ec7d0e58e85a9159c520f3c748969a8344a6a16e" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "00//ytmPEfmTaKZ6UgQd6jfHsAIUuLlQCYgfp8N5D2A=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743701838034" ] } - }, + } + ] + }, + "/v3/trade/positionAll": { + "POST": [ { "data": { - "currencyPair": "BTC_LTC", - "fee": "0.01000000", - "orderNumber": "514845991795", - "resultingTrades": [ + "code": 200, + "data": [ + { + "clOrdId": "polo331381602829729792", + "code": 200, + "msg": "", + "ordId": "331381602829729792" + }, + { + "clOrdId": "polo331381602854895616", + "code": 200, + "msg": "", + "ordId": "331381602854895616" + }, + { + "clOrdId": "polo331381602863284224", + "code": 200, + "msg": "", + "ordId": "331381602863284224" + }, { - "amount": "3.0", - "date": "2018-10-25 23:03:21", - "rate": "0.0002", - "total": "0.0006", - "tradeID": "251834", - "type": "buy" + "clOrdId": "polo331381602871672832", + "code": 200, + "msg": "", + "ordId": "331381602871672832" } - ] + ], + "msg": "Success" }, "queryString": "", - "bodyParams": "amount=10000000\u0026command=buy\u0026currencyPair=BTC_LTC\u0026fillOrKill=1\u0026nonce=1755565288536153005\u0026rate=10", + "bodyParams": "{}", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "867fc355a1ae6aadba12539a804d90dc4a334609a0d001740bf251df21020a4acdb789e4c45090639e9923258977ab03cfcef3f35dbbd348fe0c0828798f736c" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "eQVK9Nphl52py3igwF1sNZeCElFM9Cq1DH3DL4RKFLc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760131004377" ] } - }, + } + ] + }, + "/wallets/activity": { + "GET": [ { "data": { - "BTC_BCH": [ - { - "amount": "1.40308443", - "category": "exchange", - "date": "2018-10-16 18:05:17", - "fee": "0.00100000", - "globalTradeID": "394131412", - "orderNumber": "104768235081", - "rate": "0.06935244", - "total": "0.09730732", - "tradeID": "5455033", - "type": "sell" - }, - { - "amount": "0.00155709", - "category": "exchange", - "date": "2018-10-16 16:55:34", - "fee": "0.00200000", - "globalTradeID": "394126818", - "orderNumber": "104768179137", - "rate": "0.06935244", - "total": "0.00010798", - "tradeID": "5455007", - "type": "sell" - } + "withdrawals": [] + }, + "queryString": "activityType=withdrawals\u0026end=1743583374\u0026start=1712047374", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" ], - "BTC_STR": [ - { - "amount": "3696.05342780", - "category": "exchange", - "date": "2018-10-16 17:03:43", - "fee": "0.00200000", - "globalTradeID": "394127362", - "orderNumber": "96238912841", - "rate": "0.00003432", - "total": "0.12684855", - "tradeID": "13536351", - "type": "buy" - }, - { - "amount": "3600.53748129", - "category": "exchange", - "date": "2018-10-16 17:03:43", - "fee": "0.00200000", - "globalTradeID": "394127361", - "orderNumber": "96238912841", - "rate": "0.00003432", - "total": "0.12357044", - "tradeID": "13536350", - "type": "buy" - } + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "CtW9aJWMQgujt+GB/ALkiPD8v4reolJJwVV1Y/cu7Sg=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743583374230" ] + } + }, + { + "data": { + "withdrawals": [] }, - "queryString": "", - "bodyParams": "command=returnTradeHistory\u0026currencyPair=all\u0026limit=10000\u0026nonce=1755565288536153006", + "queryString": "activityType=withdrawals\u0026end=1743583403\u0026start=1712047403", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "42a72ed6889765e4312900d30fb5ae3a0b696d986950289cc7e6334fd26f880955f8e4874a687595d226af697ef4f3f4626982e55ad43f1ba3a34f0659f06a6c" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "1O0vbWWscAXvh7C7Q+3Shh+TPcQrebnNdXHp8ppMOSA=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743583403052" ] } }, { "data": { - "BTC_ARDR": [], - "BTC_ATOM": [], - "BTC_BAT": [], - "BTC_BCHABC": [], - "BTC_BCHSV": [], - "BTC_BCN": [], - "BTC_BNT": [], - "BTC_BTS": [], - "BTC_CLAM": [], - "BTC_CVC": [], - "BTC_DASH": [], - "BTC_DCR": [], - "BTC_DGB": [], - "BTC_DOGE": [], - "BTC_EOS": [], - "BTC_ETC": [], - "BTC_ETH": [], - "BTC_FCT": [], - "BTC_FOAM": [], - "BTC_GAME": [], - "BTC_GAS": [], - "BTC_GNT": [], - "BTC_GRIN": [], - "BTC_KNC": [], - "BTC_LBC": [], - "BTC_LOOM": [], - "BTC_LPT": [], - "BTC_LSK": [], - "BTC_LTC": [], - "BTC_MAID": [], - "BTC_MANA": [], - "BTC_NAV": [], - "BTC_NMR": [], - "BTC_NXT": [], - "BTC_OMG": [], - "BTC_OMNI": [], - "BTC_PASC": [], - "BTC_POLY": [], - "BTC_QTUM": [], - "BTC_REP": [], - "BTC_SC": [], - "BTC_SNT": [], - "BTC_STEEM": [], - "BTC_STORJ": [], - "BTC_STR": [], - "BTC_STRAT": [], - "BTC_VIA": [], - "BTC_VTC": [], - "BTC_XEM": [], - "BTC_XMR": [], - "BTC_XPM": [], - "BTC_XRP": [], - "BTC_ZEC": [], - "BTC_ZRX": [], - "ETH_BAT": [], - "ETH_BNT": [], - "ETH_CVC": [], - "ETH_EOS": [], - "ETH_ETC": [], - "ETH_GAS": [], - "ETH_GNT": [], - "ETH_KNC": [], - "ETH_LOOM": [], - "ETH_LSK": [], - "ETH_MANA": [], - "ETH_OMG": [], - "ETH_QTUM": [], - "ETH_REP": [], - "ETH_SNT": [], - "ETH_STEEM": [], - "ETH_ZEC": [], - "ETH_ZRX": [], - "USDC_ATOM": [], - "USDC_BCHABC": [], - "USDC_BCHSV": [], - "USDC_BTC": [], - "USDC_DOGE": [], - "USDC_ETH": [], - "USDC_FOAM": [], - "USDC_GRIN": [], - "USDC_LTC": [], - "USDC_STR": [], - "USDC_USDT": [], - "USDC_XMR": [], - "USDC_XRP": [], - "USDC_ZEC": [], - "USDT_ATOM": [], - "USDT_BAT": [], - "USDT_BNT": [], - "USDT_BTC": [], - "USDT_DASH": [], - "USDT_DOGE": [], - "USDT_EOS": [], - "USDT_ETC": [], - "USDT_ETH": [], - "USDT_GNT": [], - "USDT_KNC": [], - "USDT_LOOM": [], - "USDT_LSK": [], - "USDT_LTC": [], - "USDT_MANA": [], - "USDT_NXT": [], - "USDT_QTUM": [], - "USDT_REP": [], - "USDT_SC": [], - "USDT_SNT": [], - "USDT_STR": [], - "USDT_XMR": [], - "USDT_XRP": [], - "USDT_ZEC": [], - "USDT_ZRX": [], - "XMR_BCN": [], - "XMR_DASH": [], - "XMR_LTC": [], - "XMR_MAID": [], - "XMR_NXT": [], - "XMR_ZEC": [] + "deposits": [], + "withdrawals": [] }, - "queryString": "", - "bodyParams": "command=returnOpenOrders\u0026currencyPair=all\u0026nonce=1755565288536153007", + "queryString": "end=1760167247\u0026start=1728631247", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "742cb0956a106fe1ca603f3bb39a7bc9aefcda08e88e080f2f2fdfd747083937b5abfae98f9aa19ee48842f185fe33bef0c9034355d8a5e6ab1b56fcb92628f5" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "tEQWzkCTFmiIGE3qSLeOatQEsF4ixOifrGPBlV4K7Qk=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760167247974" ] } }, { "data": { - "makerFee": "0.00150000", - "nextTier": 25000, - "takerFee": "0.00250000", - "thirtyDayVolume": "0.00000000" + "deposits": [], + "withdrawals": [] }, - "queryString": "", - "bodyParams": "command=returnFeeInfo\u0026nonce=1755565288536153010", + "queryString": "end=1760168101\u0026start=1760160901", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "986e6d790642778cf26b2db7adeb1d6baedafd168c4b44c81295622473ab0a9c730e53673a68637461f7b90c398de9577ca8c052d8e93ae2c311f5e728ecabef" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "A69xFaS6ert+dutd57tvVOYVNYdUjMJ/od/1pv/Rfsg=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1760168101825" ] } }, { - "data": [ - { - "amount": "3696.05342780", - "currencyPair": "BTC_STR", - "date": "2018-10-16 17:03:43", - "fee": "0.00200000", - "globalTradeID": "394127362", - "rate": "0.00003432", - "total": "0.12684855", - "tradeID": "13536351", - "type": "buy" - }, - { - "amount": "3600.53748129", - "currencyPair": "BTC_STR", - "date": "2018-10-16 17:03:43", - "fee": "0.00200000", - "globalTradeID": "394127361", - "rate": "0.00003432", - "total": "0.12357044", - "tradeID": "13536350", - "type": "buy" - } - ], - "queryString": "", - "bodyParams": "command=returnOrderTrades\u0026nonce=1755565288536153011\u0026orderNumber=96238912841", + "data": { + "deposits": [] + }, + "queryString": "activityType=deposits\u0026end=1743582950\u0026start=1743575750", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "b58dd7f5192a71ca093bb05c0865e95d80234e18401df98ce7e9454acfd579cf91185b4bbcb6f1338676e8c727c410212c5cf53d54da96fc40bbb877047d181f" + "Signature": [ + "UqyE7jT23r0ixVew4iaMY98gVC438Ylrejp75YlKqEQ=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764669921345" ] } }, { "data": { - "error": "Order not found, or you are not the person who placed it." + "deposits": [], + "withdrawals": [] }, - "queryString": "", - "bodyParams": "command=returnOrderTrades\u0026nonce=1755565288536153012\u0026orderNumber=96238912842", + "queryString": "end=1743582950\u0026start=1743575750", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "39461ee3dd630b4ac93c9c447954a10ea77f80620715ca83cb204ccb899c2db7c2a714a96d80026772203bbc4335a3bea80c67f89fbcf7f0f9458eb8d5101645" + "Signature": [ + "/A9qyJS/3m9aYzN044HC8U1Q3x28zXFAtQeKaY5E8JY=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1764669921805" ] } - }, + } + ] + }, + "/wallets/address": { + "POST": [ { "data": { - "result": { - "6071071": { - "amount": "1.00000000", - "currencyPair": "BTC_ETH", - "date": "2018-10-17 17:04:50", - "rate": "0.40000000", - "startingAmount": "1.00000", - "status": "Open", - "total": "0.40000000", - "type": "buy" - } - }, - "success": 1 + "address": "14Lu2iKmxENf9w8busaaU9GHPZhDSeZ9y6" }, "queryString": "", - "bodyParams": "command=returnOrderStatus\u0026nonce=1755565288536153013\u0026orderNumber=96238912841", + "bodyParams": "{\"currency\":\"BTC\"}", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "CzztpxlAJv9MdgA6NmDbYtrRurCE9wyEJtoLUizjHjc=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1744227236306" + ] + } + } + ] + }, + "/wallets/addresses": { + "GET": [ + { + "data": null, + "queryString": "currency=LTC", + "bodyParams": "", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "644f9473efac53493f2e840b7e1517ab8dd70306da17000baedc0d553febd6a0f7cba4510a5f48767860d63f63ae3a86f5110f88a88fb221b3090931e20ad8cf" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "PSWPdPX0maKV4D0UXfE/4e99hL9NResj3mQYJdS2g4o=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1743705726197" ] } }, { "data": { - "result": { - "error": "Order not found, or you are not the person who placed it." - } + "BTC": "14Lu2iKmxENf9w8busaaU9GHPZhDSeZ9y6" + }, + "queryString": "currency=BTC", + "bodyParams": "", + "headers": { + "Content-Type": [ + "application/json" + ], + "Key": [ + "" + ], + "Recvwindow": [ + "1500" + ], + "Signature": [ + "CrNPP5PfYO6iUYr0ErbI5NUdmvJ7D8nX63+56VMEyxM=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1744186266583" + ] + } + } + ] + }, + "/wallets/withdraw": { + "POST": [ + { + "data": { + "code": 403, + "message": "Permission to withdraw denied." }, "queryString": "", - "bodyParams": "command=returnOrderStatus\u0026nonce=1755565288536153014\u0026orderNumber=96238912842", + "bodyParams": "{\"currency\":\"BTC\",\"amount\":\"1\",\"address\":\"0xbb8d0d7c346daecc2380dabaa91f3ccf8ae232fb4\"}", "headers": { "Content-Type": [ - "application/x-www-form-urlencoded" + "application/json" ], "Key": [ "" ], - "Sign": [ - "05b05626d86d031433502df8bd3bb5447ecdd86ce37a2ca986b107a06a657f8bdd8e0f945702e97515c562dd0a14590190318fbd12e32c8a05d221e6c42f33ff" + "Recvwindow": [ + "1500" + ], + "Signature": [ + "ybvsjI4makMHK3Se+s/N2IVEiIoDNrcbtVVqUnYfus4=" + ], + "Signaturemethod": [ + "hmacSHA256" + ], + "Signtimestamp": [ + "1754250971330" ] } } diff --git a/internal/testing/exchange/exchange.go b/internal/testing/exchange/exchange.go index ced9fdc2332..620dbacbedf 100644 --- a/internal/testing/exchange/exchange.go +++ b/internal/testing/exchange/exchange.go @@ -19,6 +19,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchange/accounts" + "github.com/thrasher-corp/gocryptotrader/exchange/stream" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/mock" "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" @@ -205,7 +206,7 @@ func SetupWs(tb testing.TB, e exchange.IBotExchange) { err = w.Connect(context.TODO()) require.NoError(tb, err, "Connect must not error") - + w.DataHandler = stream.NewRelay(100000) setupWsOnce[e] = true } diff --git a/testdata/configtest.json b/testdata/configtest.json index 7cc663ee005..46552d647c0 100644 --- a/testdata/configtest.json +++ b/testdata/configtest.json @@ -2351,31 +2351,36 @@ "delimiter": "_" }, "useGlobalFormat": true, - "assetTypes": [ - "spot" - ], "pairs": { "spot": { - "enabled": "BTC_LTC,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", + "assetEnabled": true, + "enabled": "BTC_USDT,BTC_ETH,BTC_DOGE,BTC_DASH,BTC_XRP", "available": "USDC_GRIN,BTC_BCN,BTC_DGB,BTC_XMR,USDT_STR,BTC_SC,BTC_ZRX,USDC_XMR,BTC_TRX,BTC_STR,BTC_SNT,USDT_QTUM,USDC_BTC,BTC_NMR,BTC_DASH,BTC_NXT,USDT_LTC,BTC_DCR,USDT_ZRX,USDC_ZEC,USDT_REP,USDT_BAT,BTC_MANA,USDC_BCHABC,USDC_STR,BTC_XRP,USDT_ETH,BTC_REP,USDT_EOS,USDC_ATOM,USDT_XRP,BTC_ETH,USDT_LSK,USDT_SC,USDT_MANA,USDC_ETC,USDC_ETH,BTC_BTS,BTC_LTC,BTC_ETC,BTC_OMG,BTC_STORJ,USDC_XRP,USDT_GRIN,BTC_QTUM,BTC_MAID,BTC_XEM,USDT_BTC,USDT_DASH,ETH_REP,BTC_ZEC,BTC_STRAT,USDC_LTC,BTC_FOAM,USDC_TRX,BTC_DOGE,BTC_VIA,BTC_VTC,ETH_ETC,USDT_ETC,ETH_EOS,USDC_BCHSV,USDT_NXT,USDT_XMR,BTC_ARDR,BTC_CVC,ETH_BAT,USDC_DOGE,BTC_XPM,BTC_LOOM,BTC_LPT,USDC_EOS,USDT_DGB,USDT_BCHSV,BTC_OMNI,ETH_ZEC,BTC_EOS,BTC_KNC,BTC_BCHSV,BTC_POLY,USDC_DASH,USDT_GNT,BTC_BCHABC,BTC_GRIN,BTC_ATOM,USDT_ATOM,USDT_BCHABC,BTC_LSK,ETH_ZRX,BTC_GAS,BTC_BAT,BTC_BNT,USDT_TRX,BTC_FCT,USDT_ZEC,BTC_GNT,USDT_DOGE,USDC_USDT" + }, + "futures": { + "assetEnabled": true, + "enabled": "XBT_USDT_PERP,ETH_USDT_PERP,BCH_USDT_PERP", + "available": "BNB_USDT_PERP,TRX_USDT_PERP,LTC_USDT_PERP,APT_USDT_PERP,1000PEPE_USDT_PERP,1000SHIB_USDT_PERP,BTC_USDT_PERP,DOGE_USDT_PERP,AVAX_USDT_PERP,XRP_USDT_PERP,SOL_USDT_PERP,ETH_USDT_PERP,BCH_USDT_PERP" } } }, "api": { "authenticatedSupport": false, "authenticatedWebsocketApiSupport": false, - "endpoints": { - "url": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API", - "urlSecondary": "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API", - "websocketURL": "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API" - }, "credentials": { - "key": "Key", - "secret": "Secret" + "key": "", + "secret": "" }, "credentialsValidator": { "requiresKey": true, "requiresSecret": true + }, + "urlEndpoints": { + "RestSpotURL": "https://api.poloniex.com", + "WebsocketPrivateURL": "wss://ws.poloniex.com/ws/private", + "WebsocketSpotURL": "wss://ws.poloniex.com/ws/public", + "WebsocketFuturesURL": "wss://ws.poloniex.com/ws/v3/public", + "WebsocketFuturesPrivateURL": "wss://ws.poloniex.com/ws/v3/private" } }, "features": { @@ -2390,7 +2395,7 @@ }, "enabled": { "autoPairUpdates": true, - "websocketAPI": false + "websocketAPI": true } }, "bankAccounts": [ diff --git a/types/boolean.go b/types/boolean.go new file mode 100644 index 00000000000..2053efdae7c --- /dev/null +++ b/types/boolean.go @@ -0,0 +1,26 @@ +package types + +import "errors" + +var errInvalidBooleanValue = errors.New("invalid value for Boolean type") + +// Boolean represents a boolean value and implements json.UnmarshalJSON +type Boolean bool + +// UnmarshalJSON implements json.Unmarshaler and converts the JSON boolean representation into a Boolean type +func (b *Boolean) UnmarshalJSON(data []byte) error { + switch string(data) { + case "1", `"1"`, "true", `"true"`: + *b = Boolean(true) + case "0", `"0"`, "false", `"false"`: + *b = Boolean(false) + default: + return errInvalidBooleanValue + } + return nil +} + +// Bool returns the underlying bool +func (b Boolean) Bool() bool { + return bool(b) +} diff --git a/types/boolean_test.go b/types/boolean_test.go new file mode 100644 index 00000000000..91052b3912e --- /dev/null +++ b/types/boolean_test.go @@ -0,0 +1,28 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/thrasher-corp/gocryptotrader/encoding/json" +) + +func TestBooleanUnmarshal(t *testing.T) { + t.Parallel() + data := []byte(`{"value": true, "another_value": "true", "third_value": "false", "fourth_value": 1, "fifth_value": 0, "sixth_value": "1", "seventh_value": "0"}`) + var result map[string]Boolean + err := json.Unmarshal(data, &result) + require.NoError(t, err) + assert.True(t, result["value"].Bool()) + assert.True(t, result["another_value"].Bool()) + assert.False(t, result["third_value"].Bool()) + assert.True(t, result["fourth_value"].Bool()) + assert.False(t, result["fifth_value"].Bool()) + assert.True(t, result["sixth_value"].Bool()) + assert.False(t, result["seventh_value"].Bool()) + + data = []byte(`{"value": "3"}`) + err = json.Unmarshal(data, &result) + require.ErrorIs(t, err, errInvalidBooleanValue) +}