Passed
Pull Request — master (#8)
by Vladislav
10:08 queued 02:40
created

MarketDataTest::testInstrumentInfoEndpoint()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 23
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 27
rs 9.552
1
<?php
2
namespace Carpenstar\ByBitAPI\Tests\Spot;
3
4
use Carpenstar\ByBitAPI\Core\Builders\ResponseDtoBuilder;
5
use Carpenstar\ByBitAPI\Core\Builders\ResponseHandlerBuilder;
6
use Carpenstar\ByBitAPI\Core\Builders\RestBuilder;
7
use Carpenstar\ByBitAPI\Core\Enums\EnumIntervals;
8
use Carpenstar\ByBitAPI\Core\Enums\EnumOutputMode;
9
use Carpenstar\ByBitAPI\Core\Objects\Collection\EntityCollection;
10
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestBidAskPrice;
11
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestKline;
12
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestLastTradedPrice;
13
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestMergedOrderBook;
14
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestOrderBook;
15
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestPublicTradingRecords;
16
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestSpotInstrumentInfo;
17
use Carpenstar\ByBitAPI\Core\Overrides\Spot\TestTickers;
18
use Carpenstar\ByBitAPI\Core\Response\CurlResponseDto;
19
use Carpenstar\ByBitAPI\Core\Response\CurlResponseHandler;
20
use Carpenstar\ByBitAPI\Spot\MarketData\BestBidAskPrice\Request\BestBidAskPriceRequest;
21
use Carpenstar\ByBitAPI\Spot\MarketData\BestBidAskPrice\Response\BestBidAskPriceResponse;
22
use Carpenstar\ByBitAPI\Spot\MarketData\InstrumentInfo\Response\InstrumentInfoResponse;
23
use Carpenstar\ByBitAPI\Spot\MarketData\Kline\Request\KlineRequest;
24
use Carpenstar\ByBitAPI\Spot\MarketData\Kline\Response\KlineResponse;
25
use Carpenstar\ByBitAPI\Spot\MarketData\LastTradedPrice\Request\LastTradedPriceRequest;
26
use Carpenstar\ByBitAPI\Spot\MarketData\LastTradedPrice\Response\LastTradedPriceResponse;
27
use Carpenstar\ByBitAPI\Spot\MarketData\MergedOrderBook\Request\MergedOrderBookRequest;
28
use Carpenstar\ByBitAPI\Spot\MarketData\MergedOrderBook\Response\MergedOrderBookPriceItemResponse;
29
use Carpenstar\ByBitAPI\Spot\MarketData\MergedOrderBook\Response\MergedOrderBookResponse;
30
use Carpenstar\ByBitAPI\Spot\MarketData\OrderBook\Request\OrderBookRequest;
31
use Carpenstar\ByBitAPI\Spot\MarketData\OrderBook\Response\OrderBookPriceItemResponse;
32
use Carpenstar\ByBitAPI\Spot\MarketData\OrderBook\Response\OrderBookResponse;
33
use Carpenstar\ByBitAPI\Spot\MarketData\PublicTradingRecords\Request\PublicTradingRecordsRequest;
34
use Carpenstar\ByBitAPI\Spot\MarketData\PublicTradingRecords\Response\PublicTradingRecordsResponse;
35
use Carpenstar\ByBitAPI\Spot\MarketData\Tickers\Request\TickersRequest;
36
use Carpenstar\ByBitAPI\Spot\MarketData\Tickers\Response\TickersResponse;
37
use PHPUnit\Framework\TestCase;
38
39
40
class MarketDataTest extends TestCase
41
{
42
    /**
43
     * SPOT - MARKET DATA
44
     * Best Bid Ask Price
45
     */
46
    private static string $bestBidAskApiResponse = '{"retCode":0,"retMsg":"OK","result":{"symbol":"BTCUSDT","bidPrice":"26298.69","bidQty":"0.106418","askPrice":"26298.7","askQty":"0.008773","time":1683979447464},"retExtInfo":{},"time":1683979447820}';
47
48
    public function testBestBidAskPriceDTOBuilder()
49
    {
50
        $dto = ResponseDtoBuilder::make(BestBidAskPriceResponse::class, json_decode(self::$bestBidAskApiResponse, true)['result']);
51
52
        $this->assertInstanceOf(BestBidAskPriceResponse::class, $dto);
53
        $this->assertIsString($dto->getSymbol());
54
        $this->assertIsFloat($dto->getAskPrice());
55
        $this->assertIsFloat($dto->getBidPrice());
56
        $this->assertIsFloat($dto->getAskQty());
57
        $this->assertIsFloat($dto->getBidQty());
58
        $this->assertInstanceOf(\DateTime::class, $dto->getTime());
59
    }
60
61
    public function testBestBidAskPriceResponseHandlerBuilder()
62
    {
63
        $handler = ResponseHandlerBuilder::make(self::$bestBidAskApiResponse, CurlResponseHandler::class, BestBidAskPriceResponse::class);
64
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
65
        $this->assertGreaterThan(0, $handler->getBody()->count());
66
    }
67
68
    public function testBestBidAskPriceEndpoint()
69
    {
70
        $endpoint = RestBuilder::make(TestBidAskPrice::class, (new BestBidAskPriceRequest())->setSymbol("BTCUSDT"));
71
72
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$bestBidAskApiResponse);
73
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
74
        $body = $entityResponse->getBody();
75
        $this->assertInstanceOf(EntityCollection::class, $body);
76
        $body = $body->fetch();
77
78
        $this->assertIsString($body->getSymbol());
79
        $this->assertIsFloat($body->getAskPrice());
80
        $this->assertIsFloat($body->getBidPrice());
81
        $this->assertIsFloat($body->getAskQty());
82
        $this->assertIsFloat($body->getBidQty());
83
        $this->assertInstanceOf(\DateTime::class, $body->getTime());
84
    }
85
86
    /**
87
     * SPOT - MARKET DATA
88
     * InstrumentInfo
89
     */
90
    private static string $instrumentInfoApiResponse = '{"retCode":0,"retMsg":"OK","result":{"list":[{"name":"BTCUSDT","alias":"BTCUSDT","baseCoin":"BTC","quoteCoin":"USDT","basePrecision":"0.000001","quotePrecision":"0.00000001","minTradeQty":"0.00004","minTradeAmt":"1","maxTradeQty":"500","maxTradeAmt":"1200000","minPricePrecision":"0.01","category":"1","showStatus":"1","innovation":"0"},{"name":"ETHUSDT","alias":"ETHUSDT","baseCoin":"ETH","quoteCoin":"USDT","basePrecision":"0.00001","quotePrecision":"0.0000001","minTradeQty":"0.0005","minTradeAmt":"1","maxTradeQty":"100000000","maxTradeAmt":"1200000","minPricePrecision":"0.01","category":"1","showStatus":"1","innovation":"0"},{"name":"EOSUSDT","alias":"EOSUSDT","baseCoin":"EOS","quoteCoin":"USDT","basePrecision":"0.01","quotePrecision":"0.000001","minTradeQty":"0.01","minTradeAmt":"0.01","maxTradeQty":"90909.090909","maxTradeAmt":"10000","minPricePrecision":"0.0001","category":"1","showStatus":"1","innovation":"0"}]},"retExtInfo":{},"time":1683980087416}';
91
92
    public function testInstrumentInfoDTOBuilder()
93
    {
94
        foreach (json_decode(self::$instrumentInfoApiResponse, true)['result']['list'] as $dataItem) {
95
            $dto = ResponseDtoBuilder::make(InstrumentInfoResponse::class, $dataItem);
96
            $this->assertInstanceOf(InstrumentInfoResponse::class, $dto);
97
            $this->assertIsString($dto->getName());
98
            $this->assertIsString($dto->getAlias());
99
            $this->assertIsString($dto->getQuoteCoin());
100
            $this->assertIsString($dto->getBaseCoin());
101
            $this->assertIsFloat($dto->getBasePrecision());
102
            $this->assertIsFloat($dto->getQuotePrecision());
103
            $this->assertIsInt($dto->getInnovation());
104
            $this->assertIsInt($dto->getMaxTradeAmt());
105
            $this->assertIsFloat($dto->getMaxTradeQty());
106
            $this->assertIsFloat($dto->getMinTradeAmt());
107
            $this->assertIsFloat($dto->getMinTradeQty());
108
            $this->assertIsFloat($dto->getMinPricePrecision());
109
            $this->assertIsInt($dto->getCategory());
110
            $this->assertIsInt($dto->getShowStatus());
111
            $this->assertIsInt($dto->getInnovation());
112
        }
113
    }
114
115
    public function testInstrumentInfoResponseHandlerBuilder()
116
    {
117
        $handler = ResponseHandlerBuilder::make(self::$instrumentInfoApiResponse, CurlResponseHandler::class, InstrumentInfoResponse::class);
118
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
119
        $this->assertGreaterThan(0, $handler->getBody()->count());
120
    }
121
122
    public function testInstrumentInfoEndpoint()
123
    {
124
        $endpoint = RestBuilder::make(TestSpotInstrumentInfo::class);
125
126
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$instrumentInfoApiResponse);
127
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
128
        $body = $entityResponse->getBody();
129
        $this->assertInstanceOf(EntityCollection::class, $body);
130
131
        foreach ($body->fetch() as $dataItem) {
132
            $dto = ResponseDtoBuilder::make(InstrumentInfoResponse::class, $dataItem);
133
            $this->assertInstanceOf(InstrumentInfoResponse::class, $dto);
134
            $this->assertIsString($dto->getName());
135
            $this->assertIsString($dto->getAlias());
136
            $this->assertIsString($dto->getQuoteCoin());
137
            $this->assertIsString($dto->getBaseCoin());
138
            $this->assertIsFloat($dto->getBasePrecision());
139
            $this->assertIsFloat($dto->getQuotePrecision());
140
            $this->assertIsInt($dto->getInnovation());
141
            $this->assertIsInt($dto->getMaxTradeAmt());
142
            $this->assertIsFloat($dto->getMaxTradeQty());
143
            $this->assertIsFloat($dto->getMinTradeAmt());
144
            $this->assertIsFloat($dto->getMinTradeQty());
145
            $this->assertIsFloat($dto->getMinPricePrecision());
146
            $this->assertIsInt($dto->getCategory());
147
            $this->assertIsInt($dto->getShowStatus());
148
            $this->assertIsInt($dto->getInnovation());
149
        }
150
    }
151
152
    /**
153
     * SPOT - Market Data
154
     * Kline
155
     */
156
    private static string $klineApiResponse = '{"retCode":0,"retMsg":"OK","result":{"list":[{"t":1683922260000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26413.58","h":"26444.15","l":"26413.58","o":"26440","v":"0.038419"},{"t":1683922320000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26405.44","h":"26420.02","l":"26402.16","o":"26413.58","v":"0.024527"},{"t":1683922380000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26390.96","h":"26406.3","l":"26390.95","o":"26405.44","v":"0.030255"},{"t":1683922440000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26397.07","h":"26399.92","l":"26390.95","o":"26390.96","v":"0.028976"},{"t":1683922500000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26390.98","h":"26397.07","l":"26390.95","o":"26397.07","v":"0.03669"},{"t":1683922560000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26409.24","h":"26409.24","l":"26389.68","o":"26390.98","v":"0.024756"},{"t":1683922620000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26443.27","h":"26453.24","l":"26390.95","o":"26409.24","v":"0.025462"},{"t":1683922680000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26451.86","h":"26451.89","l":"26440.91","o":"26443.27","v":"0.026304"},{"t":1683922740000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26426.59","h":"26451.86","l":"26424.63","o":"26451.86","v":"0.02513"},{"t":1683922800000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26429.66","h":"26435.5","l":"26419.97","o":"26426.59","v":"0.021732"},{"t":1683922860000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26426.6","h":"26435.01","l":"26421.77","o":"26429.66","v":"0.024761"},{"t":1683922920000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26404.56","h":"26434.34","l":"26401.55","o":"26426.6","v":"0.020718"},{"t":1683922980000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26403.24","h":"26414.24","l":"26386.61","o":"26404.56","v":"0.02995"},{"t":1683923040000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26391.6","h":"26403.24","l":"26391.57","o":"26403.24","v":"0.016944"},{"t":1683923100000,"s":"BTCUSDT","sn":"BTCUSDT","c":"26386.62","h":"26391.6","l":"26386.61","o":"26391.6","v":"0.03116"}]},"retExtInfo":{},"time":1683982237622}';
157
158
    public function testKlineInfoDTOBuilder()
159
    {
160
        foreach (json_decode(self::$klineApiResponse, true)['result']['list'] as $dataItem) {
161
            $dto = ResponseDtoBuilder::make(KlineResponse::class, $dataItem);
162
            $this->assertInstanceOf(KlineResponse::class, $dto);
163
            $this->assertInstanceOf(\DateTime::class, $dto->getTime());
164
            $this->assertIsString($dto->getSymbol());
165
            $this->assertIsString($dto->getAlias());
166
            $this->assertIsFloat($dto->getClosePrice());
167
            $this->assertIsFloat($dto->getHighPrice());
168
            $this->assertIsFloat($dto->getLowPrice());
169
            $this->assertIsFloat($dto->getOpenPrice());
170
            $this->assertIsFloat($dto->getTradingVolume());
171
        }
172
    }
173
174
    public function testKlineResponseHandlerBuilder()
175
    {
176
        $handler = ResponseHandlerBuilder::make(self::$klineApiResponse, CurlResponseHandler::class, KlineResponse::class);
177
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
178
        $this->assertGreaterThan(0, $handler->getBody()->count());
179
    }
180
181
    public function testKlineEndpoint()
182
    {
183
        $endpoint = RestBuilder::make(TestKline::class, (new KlineRequest())
184
            ->setSymbol("BTCUSDT")->setInterval(EnumIntervals::HOUR_1));
185
186
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$klineApiResponse);
187
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
188
        $body = $entityResponse->getBody();
189
        $this->assertInstanceOf(EntityCollection::class, $body);
190
191
        foreach ($body->fetch() as $dataItem) {
192
            $dto = ResponseDtoBuilder::make(KlineResponse::class, $dataItem);
193
            $this->assertInstanceOf(KlineResponse::class, $dto);
194
            $this->assertInstanceOf(\DateTime::class, $dto->getTime());
195
            $this->assertIsString($dto->getSymbol());
196
            $this->assertIsString($dto->getAlias());
197
            $this->assertIsFloat($dto->getClosePrice());
198
            $this->assertIsFloat($dto->getHighPrice());
199
            $this->assertIsFloat($dto->getLowPrice());
200
            $this->assertIsFloat($dto->getOpenPrice());
201
            $this->assertIsFloat($dto->getTradingVolume());
202
        }
203
    }
204
205
    /**
206
     * SPOT - MARKET DATA
207
     * Last Traded Price
208
     */
209
    private static string $lastTradedPriceApiResponse = '{"retCode":0,"retMsg":"OK","result":{"symbol":"BTCUSDT","price":"26386.61"},"retExtInfo":{},"time":1683982585451}';
210
211
    public function testLastTradedPriceDTOBuilder()
212
    {
213
        $dto = ResponseDtoBuilder::make(LastTradedPriceResponse::class, json_decode(self::$lastTradedPriceApiResponse, true)['result']);
214
        $this->assertInstanceOf(LastTradedPriceResponse::class, $dto);
215
        $this->assertIsString($dto->getSymbol());
216
        $this->assertIsFloat($dto->getPrice());
217
    }
218
219
    public function testLastTradedPriceResponseHandlerBuilder()
220
    {
221
        $handler = ResponseHandlerBuilder::make(self::$lastTradedPriceApiResponse, CurlResponseHandler::class, LastTradedPriceResponse::class);
222
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
223
        $this->assertGreaterThan(0, $handler->getBody()->count());
224
    }
225
226
    public function testLastTradedPriceEndpoint()
227
    {
228
        $endpoint = RestBuilder::make(TestLastTradedPrice::class, (new LastTradedPriceRequest())
229
            ->setSymbol("BTCUSDT"));
230
231
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$lastTradedPriceApiResponse);
232
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
233
        $body = $entityResponse->getBody();
234
        $this->assertInstanceOf(EntityCollection::class, $body);
235
236
        $dto = $body->fetch();
237
        $this->assertInstanceOf(LastTradedPriceResponse::class, $dto);
238
        $this->assertIsString($dto->getSymbol());
239
        $this->assertIsFloat($dto->getPrice());
240
    }
241
242
    /**
243
     * SPOT - Market Data
244
     * Merged Order Book
245
     */
246
    private static string $mergedOrderBookApiResponse = '{"retCode":0,"retMsg":"OK","result":{"asks":[["26796.1","0.011429"],["26796.9","0.000958"],["26800","0.026581"],["26807.7","0.000135"],["26810.2","0.000592"]],"bids":[["26796","0.077068"],["26795.9","0.115983"],["26711","0.002177"],["26693.1","0.001057"],["26683.9","0.001006"]],"time":1683983945762},"retExtInfo":{},"time":1683983945762}';
247
248
    public function testMergedOrderBookDTOBuilder()
249
    {
250
        $dto = ResponseDtoBuilder::make(MergedOrderBookResponse::class, json_decode(self::$mergedOrderBookApiResponse, true)['result']);
251
        $this->assertInstanceOf(MergedOrderBookResponse::class, $dto);
252
        $this->assertInstanceOf(\DateTime::class, $dto->getTime());
253
254
        /** @var MergedOrderBookPriceItemResponse $bid */
255
        while(!empty($bid = $dto->getBids()->fetch())) {
256
            $this->assertIsFloat($bid->getPrice());
0 ignored issues
show
Bug introduced by
The method getPrice() does not exist on Carpenstar\ByBitAPI\Core...\IResponseDataInterface. It seems like you code against a sub-type of Carpenstar\ByBitAPI\Core...\IResponseDataInterface such as Carpenstar\ByBitAPI\Spot...LastTradedPriceResponse or Carpenstar\ByBitAPI\Spot...erBookPriceItemResponse or Carpenstar\ByBitAPI\Spot...erBookPriceItemResponse or Carpenstar\ByBitAPI\Spot...cTradingRecordsResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

256
            $this->assertIsFloat($bid->/** @scrutinizer ignore-call */ getPrice());
Loading history...
257
            $this->assertIsFloat($bid->getQuantity());
0 ignored issues
show
Bug introduced by
The method getQuantity() does not exist on Carpenstar\ByBitAPI\Core...\IResponseDataInterface. It seems like you code against a sub-type of Carpenstar\ByBitAPI\Core...\IResponseDataInterface such as Carpenstar\ByBitAPI\Spot...erBookPriceItemResponse or Carpenstar\ByBitAPI\Spot...erBookPriceItemResponse or Carpenstar\ByBitAPI\Spot...cTradingRecordsResponse. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

257
            $this->assertIsFloat($bid->/** @scrutinizer ignore-call */ getQuantity());
Loading history...
258
        }
259
260
        /** @var MergedOrderBookPriceItemResponse $ask */
261
        while(!empty($ask = $dto->getAsks()->fetch())) {
262
            $this->assertIsFloat($ask->getPrice());
263
            $this->assertIsFloat($ask->getQuantity());
264
        }
265
    }
266
267
    public function testMergedOrderBookResponseHandlerBuilder()
268
    {
269
        $handler = ResponseHandlerBuilder::make(self::$mergedOrderBookApiResponse, CurlResponseHandler::class, MergedOrderBookResponse::class);
270
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
271
        $this->assertGreaterThan(0, $handler->getBody()->count());
272
    }
273
274
    public function testMergedOrderBookEndpoint()
275
    {
276
        $endpoint = RestBuilder::make(TestMergedOrderBook::class, (new MergedOrderBookRequest())
277
            ->setSymbol("BTCUSDT"));
278
279
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$mergedOrderBookApiResponse);
280
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
281
        $body = $entityResponse->getBody();
282
        $this->assertInstanceOf(EntityCollection::class, $body);
283
284
        $dto = $body->fetch();
285
286
        $this->assertInstanceOf(MergedOrderBookResponse::class, $dto);
287
        $this->assertInstanceOf(\DateTime::class, $dto->getTime());
288
289
        /** @var MergedOrderBookPriceItemResponse $bid */
290
        while(!empty($bid = $dto->getBids()->fetch())) {
291
            $this->assertIsFloat($bid->getPrice());
292
            $this->assertIsFloat($bid->getQuantity());
293
        }
294
295
        /** @var MergedOrderBookPriceItemResponse $ask */
296
        while(!empty($ask = $dto->getAsks()->fetch())) {
297
            $this->assertIsFloat($ask->getPrice());
298
            $this->assertIsFloat($ask->getQuantity());
299
        }
300
    }
301
302
    /**
303
     * SPOT - Market Data
304
     * Order Book
305
     */
306
307
    private static string $orderBookApiResult = '{"retCode":0,"retMsg":"OK","result":{"asks":[["26847.07","0.026755"],["26847.09","0.018993"],["26847.11","0.023623"],["26847.13","0.054235"],["26847.15","0.02979"]],"bids":[["26844.02","0.017595"],["26844","0.020731"],["26843.98","0.039244"],["26843.96","0.035931"],["26843.94","0.053928"]],"time":1683984334496},"retExtInfo":{},"time":1683984334496}';
308
309
    public function testOrderBookDTOBuilder()
310
    {
311
        $dto = ResponseDtoBuilder::make(OrderBookResponse::class, json_decode(self::$orderBookApiResult, true)['result']);
312
        $this->assertInstanceOf(OrderBookResponse::class, $dto);
313
314
        /** @var OrderBookPriceItemResponse $bid */
315
        while(!empty($bid = $dto->getBids()->fetch())) {
316
            $this->assertIsFloat($bid->getPrice());
317
            $this->assertIsFloat($bid->getQuantity());
318
        }
319
320
        /** @var OrderBookPriceItemResponse $ask */
321
        while(!empty($ask = $dto->getAsks()->fetch())) {
322
            $this->assertIsFloat($ask->getPrice());
323
            $this->assertIsFloat($ask->getQuantity());
324
        }
325
    }
326
327
    public function testOrderBookResponseHandlerBuilder()
328
    {
329
        $handler = ResponseHandlerBuilder::make(self::$orderBookApiResult, CurlResponseHandler::class, OrderBookResponse::class);
330
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
331
        $this->assertGreaterThan(0, $handler->getBody()->count());
332
    }
333
334
    public function testOrderBookEndpoint()
335
    {
336
        $endpoint = RestBuilder::make(TestOrderBook::class, (new OrderBookRequest())
337
            ->setSymbol("BTCUSDT"));
338
339
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$orderBookApiResult);
340
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
341
        $body = $entityResponse->getBody();
342
        $this->assertInstanceOf(EntityCollection::class, $body);
343
344
        $dto = $body->fetch();
345
346
        $this->assertInstanceOf(OrderBookResponse::class, $dto);
347
        $this->assertInstanceOf(\DateTime::class, $dto->getTime());
348
349
        /** @var MergedOrderBookPriceItemResponse $bid */
350
        while(!empty($bid = $dto->getBids()->fetch())) {
351
            $this->assertIsFloat($bid->getPrice());
352
            $this->assertIsFloat($bid->getQuantity());
353
        }
354
355
        /** @var MergedOrderBookPriceItemResponse $ask */
356
        while(!empty($ask = $dto->getAsks()->fetch())) {
357
            $this->assertIsFloat($ask->getPrice());
358
            $this->assertIsFloat($ask->getQuantity());
359
        }
360
    }
361
362
    /**
363
     * SPOT - Market Data
364
     * Public Trading Records
365
     */
366
    private static string $publicTradingRecordsApiResponse = '{"retCode":0,"retMsg":"OK","result":{"list":[{"price":"26822.93","time":1683984799441,"qty":"0.000336","isBuyerMaker":1,"type":"0"},{"price":"26822.93","time":1683984799749,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.93","time":1683984800267,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.93","time":1683984801045,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984801819,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984802595,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984803370,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984803430,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984804148,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984804430,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984804923,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984805427,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.45","time":1683984805496,"qty":"0.000242","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984805698,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984806472,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984807250,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984807427,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984808031,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984808434,"qty":"0.000261","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984808807,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984809582,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984809845,"qty":"0.001","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984810358,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984810874,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984811387,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984811433,"qty":"0.000298","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984811516,"qty":"0.000242","isBuyerMaker":0,"type":"0"},{"price":"26822.72","time":1683984811901,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984812415,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984812932,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26822.72","time":1683984813447,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.45","time":1683984813455,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984813961,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984814440,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984814475,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984814990,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984815440,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984815507,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984816023,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984816430,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984816539,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984816841,"qty":"0.000354","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984817056,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984817430,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984817568,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984818348,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984819136,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984819916,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984820698,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984821432,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26820.46","time":1683984821470,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984822251,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26820.46","time":1683984823027,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.31","time":1683984823434,"qty":"0.000373","isBuyerMaker":0,"type":"0"},{"price":"26819.32","time":1683984823799,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.32","time":1683984824571,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.32","time":1683984825349,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.32","time":1683984826123,"qty":"0.000037","isBuyerMaker":1,"type":"0"},{"price":"26819.32","time":1683984826445,"qty":"0.000205","isBuyerMaker":1,"type":"0"},{"price":"26817.46","time":1683984826525,"qty":"0.000298","isBuyerMaker":0,"type":"0"}]},"retExtInfo":{},"time":1683984826883}';
367
368
    public function testPublicTradingRecordsDTOBuilder()
369
    {
370
        foreach (json_decode(self::$publicTradingRecordsApiResponse, true)['result']['list'] as $record) {
371
            $dto = ResponseDtoBuilder::make(PublicTradingRecordsResponse::class, $record);
372
            $this->assertInstanceOf(PublicTradingRecordsResponse::class, $dto);
373
            $this->assertIsFloat($dto->getPrice());
374
            $this->assertInstanceOf(\DateTime::class, $dto->getTime());
375
            $this->assertIsFloat($dto->getQuantity());
376
            $this->assertIsBool($dto->getIsBuyerMaker());
377
            $this->assertIsInt($dto->getType());
378
        }
379
    }
380
381
    public function testPublicTradingRecordsResponseHandlerBuilder()
382
    {
383
        $handler = ResponseHandlerBuilder::make(self::$publicTradingRecordsApiResponse, CurlResponseHandler::class, PublicTradingRecordsResponse::class);
384
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
385
        $this->assertGreaterThan(0, $handler->getBody()->count());
386
    }
387
388
    public function testPublicTradingRecordsEndpoint()
389
    {
390
        $endpoint = RestBuilder::make(TestPublicTradingRecords::class, (new PublicTradingRecordsRequest())
391
            ->setSymbol("BTCUSDT"));
392
393
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$publicTradingRecordsApiResponse);
394
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
395
        $body = $entityResponse->getBody();
396
        $this->assertInstanceOf(EntityCollection::class, $body);
397
398
        $dto = $body->fetch();
399
400
        $this->assertInstanceOf(PublicTradingRecordsResponse::class, $dto);
401
        $this->assertInstanceOf(\DateTime::class, $dto->getTime());
402
        $this->assertIsFloat($dto->getPrice());
403
        $this->assertIsFloat($dto->getQuantity());
404
        $this->assertIsBool($dto->getIsBuyerMaker());
405
        $this->assertIsInt($dto->getType());
406
    }
407
408
    /**
409
     * SPOT - Market Data
410
     * Tickers
411
     */
412
    private static string $tickersApiResponse = '{"retCode":0,"retMsg":"OK","result":{"t":1683986136017,"s":"BTCUSDT","bp":"26799.99","ap":"26810.3","lp":"26810.3","o":"26875.03","h":"28073.41","l":"25992.06","v":"2389.959483","qv":"65100545.90244497"},"retExtInfo":{},"time":1683986136450}';
413
414
    public function testTickersDTOBuilder()
415
    {
416
        $dto = ResponseDtoBuilder::make(TickersResponse::class, json_decode(self::$tickersApiResponse, true)['result']);
417
        $this->assertInstanceOf(TickersResponse::class, $dto);
418
        $this->assertInstanceOf(\DateTime::class, $dto->getTime());
419
        $this->assertIsFloat($dto->getHighPrice());
420
        $this->assertIsFloat($dto->getTradingVolume());
421
        $this->assertIsFloat($dto->getOpenPrice());
422
        $this->assertIsFloat($dto->getLowPrice());
423
        $this->assertIsFloat($dto->getBestAskPrice());
424
        $this->assertIsFloat($dto->getBestBidPrice());
425
        $this->assertIsFloat($dto->getLastTradedPrice());
426
        $this->assertIsFloat($dto->getTradingQuoteVolume());
427
        $this->assertIsString($dto->getSymbol());
428
    }
429
430
    public function testTickersResponseHandlerBuilder()
431
    {
432
        $handler = ResponseHandlerBuilder::make(self::$tickersApiResponse, CurlResponseHandler::class, TickersResponse::class);
433
        $this->assertInstanceOf(EntityCollection::class, $handler->getBody());
434
        $this->assertGreaterThan(0, $handler->getBody()->count());
435
    }
436
437
    public function testTickersEndpoint()
438
    {
439
        $endpoint = RestBuilder::make(TestTickers::class, (new TickersRequest())
440
            ->setSymbol("BTCUSDT"));
441
442
        $entityResponse = $endpoint->execute(EnumOutputMode::MODE_ENTITY, self::$tickersApiResponse);
443
        $this->assertInstanceOf(CurlResponseDto::class, $entityResponse);
444
        $body = $entityResponse->getBody();
445
        $this->assertInstanceOf(EntityCollection::class, $body);
446
447
        $body = $body->fetch();
448
449
        $this->assertInstanceOf(TickersResponse::class, $body);
450
        $this->assertInstanceOf(\DateTime::class, $body->getTime());
451
        $this->assertIsFloat($body->getHighPrice());
452
        $this->assertIsFloat($body->getTradingVolume());
453
        $this->assertIsFloat($body->getOpenPrice());
454
        $this->assertIsFloat($body->getLowPrice());
455
        $this->assertIsFloat($body->getBestAskPrice());
456
        $this->assertIsFloat($body->getBestBidPrice());
457
        $this->assertIsFloat($body->getLastTradedPrice());
458
        $this->assertIsFloat($body->getTradingQuoteVolume());
459
        $this->assertIsString($body->getSymbol());
460
    }
461
}