GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (5)

src/Api/TradingApi.php (1 issue)

1
<?php
2
/**
3
 * This file is part of Poloniex PHP SDK.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @copyright 2017-2018 Chasovskih Grisha <[email protected]>
9
 * @license https://github.com/signulls/poloniex-php-sdk/blob/master/LICENSE MIT
10
 */
11
12
namespace Poloniex\Api;
13
14
use function is_array;
15
use GuzzleHttp\RequestOptions;
16
use Poloniex\{ApiKey, Exception\TotalDeficiencyException, Response\SampleResponse};
17
use Poloniex\Request\{CreateLoanOfferRequest, MoveOrderRequest, TradeRequest};
18
use Poloniex\Response\TradingApi\{
19
    AvailableAccountBalances,
20
    Balance,
21
    MoveOrder,
22
    OrderStatus,
23
    TradeResult,
24
    CompleteBalance,
25
    DepositAddresses,
26
    DepositsWithdrawals,
27
    FeeInfo,
28
    ActiveLoans,
29
    CreateLoanOffer,
30
    LandingHistory,
31
    Loan,
32
    CloseMarginPosition,
33
    MarginPosition,
34
    MarginAccountSummary,
35
    MarginTrade,
36
    NewAddress,
37
    OpenOrder,
38
    OrderTrade,
39
    ResultingTrade,
40
    TradeHistory
41
};
42
43
/**
44
 * All calls to the trading API are sent via HTTP POST to https://poloniex.com/tradingApi and
45
 * must contain the following headers:
46
 *
47
 *  Key - Your API key.
48
 *  Sign - The query's POST data signed by your key's "secret" according to the HMAC-SHA512 method.
49
 *
50
 * Additionally, all queries must include a "nonce" POST parameter. The nonce parameter is an integer
51
 * which must always be greater than the previous nonce used.
52
 *
53
 * There are several methods accepted by the trading API, each of which is specified by the "command" POST parameter.
54
 *
55
 * @author Grisha Chasovskih <[email protected]>
56
 */
57
class TradingApi extends AbstractApi
58
{
59
    /**
60
     * @var ApiKey
61
     */
62
    private $apiKey;
63
64
    /**
65
     * {@inheritdoc}
66
     */
67
    public function request(string $command, array $params = []): array
68
    {
69
        $this->throwExceptionIf($this->apiKey === null, 'You need to set ApiKey to make trade request');
70
        $params = array_merge($params, ['nonce' => $this->getNonce(), 'command' => $command]);
71
        $data = http_build_query($params, '', '&');
72
73
        $this->options = [
74
            RequestOptions::FORM_PARAMS => $params,
75
            RequestOptions::HEADERS     => [
76
                'Key'          => $this->apiKey->getApiKey(),
77
                'Sign'         => hash_hmac('sha512', $data, $this->apiKey->getSecret()),
78
                'Content-Type' => 'application/x-www-form-urlencoded',
79
            ],
80
        ];
81
82
        $response = parent::request($command, $params);
83
        $this->apiKey = null;
84
85
        return $response;
86
    }
87
88
    /**
89
     * Set Api key
90
     *
91
     * @param ApiKey $apiKey
92
     *
93
     * @return TradingApi
94
     */
95
    public function setApiKey(ApiKey $apiKey): self
96
    {
97
        $this->apiKey = $apiKey;
98
99
        return $this;
100
    }
101
102
    /**
103
     * Returns all of your available balances.
104
     *
105
     * @return Balance
106
     */
107
    public function returnBalances(): Balance
108
    {
109
        $balance = new Balance();
110
        foreach ($this->request('returnBalances') as $currency => $value) {
111
            $balance->currencies[$currency] = $value;
112
        }
113
114
        return $balance;
115
    }
116
117
    /**
118
     * Returns all of your balances, including available balance, balance on orders, and the
119
     * estimated BTC value of your balance. By default, this call is limited to your exchange
120
     * account; set the "account" POST parameter to "all" to include your margin and lending accounts.
121
     *
122
     * Array keys are 3-digit coin codes
123
     *
124
     * @param  string $account
125
     * @return CompleteBalance[]
126
     */
127
    public function returnCompleteBalances(string $account = null): array
128
    {
129
        $balances = [];
130
        foreach ($this->request('returnCompleteBalances', compact('account')) as $coin => $balance) {
131
            $balances[$coin] = $this->factory(CompleteBalance::class, $balance);
132
        }
133
134
        return $balances;
135
    }
136
137
    /**
138
     * Returns all of your deposit addresses.
139
     *
140
     * @return DepositAddresses
141
     */
142
    public function returnDepositAddresses(): DepositAddresses
143
    {
144
        $depositAddresses = new DepositAddresses();
145
        foreach ($this->request('returnDepositAddresses') as $coin => $address) {
146
            $depositAddresses->addresses[$coin] = $address;
147
        }
148
149
        return $depositAddresses;
150
    }
151
152
    /**
153
     * Generates a new deposit address for the currency specified by the "currency" POST parameter.
154
     * Only one address per currency per day may be generated, and a new address may not be generated
155
     * before the previously-generated one has been used.
156
     *
157
     * @param string $currency 3-digit currency code
158
     *
159
     * @return NewAddress
160
     */
161
    public function generateNewAddress(string $currency): NewAddress
162
    {
163
        /* @var $newAddress NewAddress */
164
        $newAddress = $this->factory(
165
            NewAddress::class,
166
            $this->request('generateNewAddress', compact('currency'))
167
        );
168
169
        return $newAddress;
170
    }
171
172
    /**
173
     * Returns your deposit and withdrawal history within a range, specified by the "start" and "end" POST parameters,
174
     * both of which should be given as UNIX timestamps.
175
     *
176
     * @param int $start UNIX timestamps
177
     * @param int $end UNIX timestamps
178
     *
179
     * @return DepositsWithdrawals
180
     */
181
    public function returnDepositsWithdrawals(int $start, int $end): DepositsWithdrawals
182
    {
183
        /** @var $depositsWithdrawals DepositsWithdrawals*/
184
        $depositsWithdrawals = $this->factory(
185
            DepositsWithdrawals::class,
186
            $this->request('returnDepositsWithdrawals', compact('start', 'end'))
187
        );
188
189
        return $depositsWithdrawals;
190
    }
191
192
    /**
193
     * Returns your open orders for a given market.
194
     *
195
     * @param string $currencyPair
196
     * @return OpenOrder[]
197
     */
198
    public function returnOpenOrders(string $currencyPair): array
199
    {
200
        $this->throwExceptionIf($currencyPair === 'all', 'Please use TradingApi::returnAllOpenOrders() method');
201
202
        $openOrders = [];
203
        foreach ($this->request('returnOpenOrders', compact('currencyPair')) as $openOrder) {
204
            $openOrders[] = $this->factory(OpenOrder::class, $openOrder);
205
        }
206
207
        return $openOrders ?? [];
208
    }
209
210
    /**
211
     * Return open orders for all markets.
212
     *
213
     * OpenOrder[][]
214
     */
215
    public function returnAllOpenOrders(): array
216
    {
217
        $openOrders = [];
218
        foreach ($this->request('returnOpenOrders', ['currencyPair' => 'all']) as $pair => $orders) {
219
            if (is_array($orders)) {
220
                foreach ($orders as $openOrder) {
221
                    $openOrders[$pair][] = $this->factory(OpenOrder::class, $openOrder);
222
                }
223
            }
224
        }
225
226
        return $openOrders;
227
    }
228
229
    /**
230
     * Returns your trade history for a given market, specified by the "currencyPair" POST parameter.
231
     *
232
     * You may optionally specify a range via "start" and/or "end" POST parameters, given in UNIX timestamp format;
233
     * if you do not specify a range, it will be limited to one day. You may optionally limit the number of entries
234
     * returned using the "limit" parameter, up to a maximum of 10,000. If the "limit" parameter is not specified,
235
     * no more than 500 entries will be returned.
236
     *
237
     * @param string $currencyPair
238
     * @param int|null $start UNIX timestamp format
239
     * @param int|null $end UNIX timestamp format
240
     * @param int|null $limit
241
     *
242
     * @return TradeHistory[]
243
     */
244
    public function returnTradeHistory(
245
        string $currencyPair,
246
        int $start = null,
247
        int $end = null,
248
        int $limit = null
249
    ): array {
250
251
        $this->throwExceptionIf($currencyPair === 'all', 'Please use TradingApi::returnAllTradeHistory() method');
252
253
        foreach ($this->request('returnTradeHistory', compact('currencyPair', 'start', 'end', 'limit')) as $history) {
254
            $tradeHistory[] = $this->factory(TradeHistory::class, $history);
255
        }
256
257
        return $tradeHistory ?? [];
258
    }
259
260
    /**
261
     * Receive your trade history for all markets.
262
     * NOTE: Keys of response is currency pair codes like 'BTC_MAID'
263
     *
264
     * @param int|null $start
265
     * @param int|null $end
266
     * @param int|null $limit
267
     *
268
     * @return TradeHistory[][]
269
     */
270
    public function returnAllTradeHistory(
271
        int $start = null,
272
        int $end = null,
273
        int $limit = null
274
    ): array {
275
276
        $tradeHistory = [];
277
        $currencyPair = 'all';
278
        $response = $this->request('returnTradeHistory', compact('currencyPair', 'start', 'end', 'limit'));
279
280
        foreach ($response as $pair => $histories) {
281
            if (is_array($histories) && !empty($histories)) {
282
                foreach ($histories as $history) {
283
                    $tradeHistory[$pair][] = $this->factory(TradeHistory::class, $history);
284
                }
285
            }
286
        }
287
288
        return $tradeHistory;
289
    }
290
291
    /**
292
     * Returns all trades involving a given order, specified by the "orderNumber" POST parameter.
293
     * If no trades for the order have occurred or you specify an order that does
294
     * not belong to you, you will receive an error.
295
     *
296
     * @param int $orderNumber
297
     * @return OrderTrade[]
298
     */
299
    public function returnOrderTrades(int $orderNumber): array
300
    {
301
        $orderTrades = [];
302
        foreach ($this->request('returnOrderTrades', compact('orderNumber')) as $response) {
303
            $orderTrades[] = $this->factory(OrderTrade::class, $response);
304
        }
305
306
        return $orderTrades;
307
    }
308
309
    /**
310
     * Places a buy order in a given market.
311
     *
312
     * @param TradeRequest $tradeRequest
313
     * @return TradeResult
314
     */
315
    public function buy(TradeRequest $tradeRequest): TradeResult
316
    {
317
        return $this->tradeRequest('buy', $tradeRequest);
318
    }
319
320
    /**
321
     * Places a sell order in a given market.
322
     *
323
     * @param TradeRequest $tradeRequest
324
     * @return TradeResult
325
     */
326
    public function sell(TradeRequest $tradeRequest): TradeResult
327
    {
328
        return $this->tradeRequest('sell', $tradeRequest);
329
    }
330
331
    /**
332
     * Returns the status of a given order, specified by the "orderNumber" POST parameter.
333
     * If the specified orderNumber is not open, or it is not yours, you will receive an error.
334
     *
335
     * Note that returnOrderStatus, in concert with returnOrderTrades,
336
     * can be used to determine various status information about an order:
337
     *
338
     * 1) If returnOrderStatus returns status: "Open", the order is fully open.
339
     * 2) If returnOrderStatus returns status: "Partially filled", the order is partially filled,
340
     *    and returnOrderTrades may be used to find the list of those fills.
341
     * 3) If returnOrderStatus returns an error and returnOrderTrades returns an error,
342
     *    then the order was cancelled before it was filled.
343
     * 4) If returnOrderStatus returns an error and returnOrderTrades returns a list of trades, then the order
344
     *    had fills and is no longer open (due to being completely filled, or partially filled and then cancelled).
345
     *
346
     * @param int $orderNumber
347
     *
348
     * @return OrderStatus
349
     *
350
     * @throws \Poloniex\Exception\PoloniexException
351
     */
352
    public function returnOrderStatus(int $orderNumber): OrderStatus
353
    {
354
        $response = $this->request('returnOrderStatus', compact('orderNumber'));
355
356
        $message = 'Unable to return order status';
357
        $this->throwExceptionIf((int) $response['success'] === 0, $message);
358
        $this->throwExceptionIf(!isset($response['result'][$orderNumber]), $message);
359
360
        /* @var $orderStatus OrderStatus */
361
        $orderStatus = $this->factory(
362
            OrderStatus::class,
363
            $response['result'][$orderNumber]
364
        );
365
366
        return $orderStatus;
367
    }
368
369
    /**
370
     * Cancels an order you have placed in a given market.
371
     * Required POST parameter is "orderNumber".
372
     * If successful, the method will return: {"success":1}
373
     *
374
     * @param int $orderNumber
375
     * @return bool
376
     */
377
    public function cancelOrder(int $orderNumber): bool
378
    {
379
        $response = $this->request('cancelOrder', compact('orderNumber'));
380
381
        return isset($response['success']) ? (bool) $response['success'] : false;
382
    }
383
384
    /**
385
     * Cancels an order and places a new one of the same type in a single atomic
386
     * transaction, meaning either both operations will succeed or both will fail.
387
     * Required POST parameters are "orderNumber" and "rate"; you may optionally
388
     * specify "amount" if you wish to change the amount of the new order.
389
     *
390
     * "postOnly" or "immediateOrCancel" may be specified for exchange orders,
391
     * but will have no effect on margin orders.
392
     *
393
     * @param MoveOrderRequest $moveOrderRequest
394
     * @return MoveOrder
395
     */
396
    public function moveOrder(MoveOrderRequest $moveOrderRequest): MoveOrder
397
    {
398
        foreach (['orderNumber', 'rate'] as $requiredField) {
399
            $this->throwExceptionIf(
400
                $moveOrderRequest->{$requiredField} === null,
401
                sprintf('Unable to send "moveOrder" request. Field "%s" should be set.', $requiredField)
402
            );
403
        }
404
405
        /** @var $moveOrder MoveOrder */
406
        $moveOrder = $this->factory(
407
            MoveOrder::class,
408
            $this->request('moveOrder', get_object_vars($moveOrderRequest))
409
        );
410
411
        return $moveOrder;
412
    }
413
414
    /**
415
     * Immediately places a withdrawal for a given currency, with no email confirmation.
416
     * In order to use this method, the withdrawal privilege must be enabled for your API key.
417
     * Required POST parameters are "currency", "amount", and "address".
418
     * For XMR withdrawals, you may optionally specify "paymentId".
419
     *
420
     * @param string $currency
421
     * @param string $amount
422
     * @param string $address
423
     * @param int|null $paymentId
424
     *
425
     * @return string
426
     */
427
    public function withdraw(string $currency, string $amount, string $address, int $paymentId = null): string
428
    {
429
        $response = $this->request('withdraw', compact('currency', 'amount', 'address', 'paymentId'));
430
431
        return $response['response'] ?? 'Failed withdraw request.';
432
    }
433
434
    /**
435
     * If you are enrolled in the maker-taker fee schedule, returns your current trading fees
436
     * and trailing 30-day volume in BTC. This information is updated once every 24 hours.
437
     *
438
     * @return FeeInfo
439
     */
440
    public function returnFeeInfo(): FeeInfo
441
    {
442
        /** @var $feeInfo FeeInfo */
443
        $feeInfo = $this->factory(
444
            FeeInfo::class,
445
            $this->request('returnFeeInfo')
446
        );
447
448
        return $feeInfo;
449
    }
450
451
    /**
452
     * Returns your balances sorted by account. You may optionally specify the "account" POST parameter
453
     * if you wish to fetch only the balances of one account. Please note that balances in your margin
454
     * account may not be accessible if you have any open margin positions or orders.
455
     *
456
     * @param string|null $account
457
     * @return AvailableAccountBalances
458
     */
459
    public function returnAvailableAccountBalances(string $account = null): AvailableAccountBalances
460
    {
461
        $this->throwExceptionIf(
462
            $account !== null && !property_exists(AvailableAccountBalances::class, $account),
463
            sprintf('Invalid account type "%s" given', $account)
464
        );
465
466
        /* @var $availableAccountBalances AvailableAccountBalances */
467
        $availableAccountBalances = $this->factory(
468
            AvailableAccountBalances::class,
469
            $this->request('returnAvailableAccountBalances', compact('account'))
470
        );
471
472
        return $availableAccountBalances;
473
    }
474
475
    /**
476
     * Returns your current tradable balances for each currency in each market for which margin trading is enabled.
477
     * Please note that these balances may vary continually with market conditions. Sample output:
478
     *
479
     * "BTC_DASH" => [
480
     *      "BTC" => "8.50274777",
481
     *      "DASH":"654.05752077",
482
     * ], "BTC_LTC" => [
483
     *      "BTC" => "8.50274777",
484
     *      "LTC":"1214.67825290"
485
     * ],"BTC_XMR" => [
486
     *      "BTC" => "8.50274777",
487
     *      "XMR" => "3696.84685650"
488
     * ]
489
     *
490
     * @return array
491
     */
492
    public function returnTradableBalances(): array
493
    {
494
        return $this->request('returnTradableBalances');
495
    }
496
497
    /**
498
     * Transfers funds from one account to another (e.g. from your exchange account to your margin account).
499
     *
500
     * @param string $currency
501
     * @param float $amount
502
     * @param string $fromAccount
503
     * @param string $toAccount
504
     *
505
     * @return SampleResponse
506
     */
507
    public function transferBalance(
508
        string $currency,
509
        float $amount,
510
        string $fromAccount,
511
        string $toAccount
512
    ): SampleResponse {
513
        /* @var $response SampleResponse */
514
        $response = $this->factory(
515
            SampleResponse::class,
516
            $this->request('transferBalance', compact('currency', 'amount', 'fromAccount', 'toAccount'))
517
        );
518
519
        return $response;
520
    }
521
522
    /**
523
     * Returns a summary of your entire margin account. This is the same information you will find in the
524
     * Margin Account section of the Margin Trading page, under the Markets list.
525
     *
526
     * @return MarginAccountSummary
527
     */
528
    public function returnMarginAccountSummary(): MarginAccountSummary
529
    {
530
        /* @var $marginAccountSummary MarginAccountSummary */
531
        $marginAccountSummary = $this->factory(
532
            MarginAccountSummary::class,
533
            $this->request('returnMarginAccountSummary')
534
        );
535
536
        return $marginAccountSummary;
537
    }
538
539
    /**
540
     * Places a margin buy order in a given market.
541
     * You may optionally specify a maximum lending rate using the "lendingRate" parameter.
542
     * If successful, the method will return the order number and any trades immediately resulting from your order.
543
     *
544
     * @param string $currencyPair
545
     * @param float  $rate
546
     * @param float  $amount
547
     * @param float  $lendingRate
548
     *
549
     * @return MarginTrade
550
     */
551
    public function marginBuy(string $currencyPair, float $rate, float $amount, float $lendingRate = null): MarginTrade
552
    {
553
        return $this->marginTrade('marginBuy', compact('currencyPair', 'rate', 'amount', 'lendingRate'));
554
    }
555
556
    /**
557
     * Places a margin sell order in a given market.
558
     * Parameters and output are the same as for the marginBuy method.
559
     *
560
     * @param string     $currencyPair
561
     * @param float      $rate
562
     * @param float      $amount
563
     * @param float|null $lendingRate
564
     *
565
     * @return MarginTrade
566
     */
567
    public function marginSell(string $currencyPair, float $rate, float $amount, float $lendingRate = null): MarginTrade
568
    {
569
        return $this->marginTrade('marginSell', compact('currencyPair', 'rate', 'amount', 'lendingRate'));
570
571
    }
572
573
    /**
574
     * Returns information about your margin position in a given market.
575
     *
576
     * You may set "currencyPair" to "all" if you wish to fetch all of your margin positions at once.
577
     * If you have no margin position in the specified market, "type" will be set to "none".
578
     * "liquidationPrice" is an estimate, and does not necessarily represent the price at which an
579
     * actual forced liquidation will occur. If you have no liquidation price, the value will be -1.
580
     *
581
     * @param string $currencyPair
582
     * @return MarginPosition
583
     */
584
    public function getMarginPosition(string $currencyPair = 'all'): MarginPosition
585
    {
586
        /* @var $marginPosition MarginPosition */
587
        $marginPosition = $this->factory(
588
            MarginPosition::class,
589
            $this->request('getMarginPosition', compact('currencyPair'))
590
        );
591
592
        return $marginPosition;
593
    }
594
595
    /**
596
     * Closes your margin position in a given market using a market order.
597
     * This call will also return success if you do not have an open position in the specified market.
598
     *
599
     * @param string $currencyPair
600
     * @return CloseMarginPosition
601
     */
602
    public function closeMarginPosition(string $currencyPair): CloseMarginPosition
603
    {
604
        $response = $this->request('closeMarginPosition', compact('currencyPair'));
605
606
        $closeMarginPosition = new CloseMarginPosition();
607
        $closeMarginPosition->success = (bool) $response['success'];
608
        $closeMarginPosition->message = $response['message'];
609
610
        $responseResultingTrades = $response['resultingTrades'] ?? [];
611
612
        /* @var $resultingTrades array */
613
        foreach ($responseResultingTrades as $pair => $resultingTrades) {
614
            foreach ($resultingTrades as $resultingTrade) {
615
                $closeMarginPosition->resultingTrades[$pair][] = $this->factory(ResultingTrade::class, $resultingTrade);
616
            }
617
        }
618
619
        return $closeMarginPosition;
620
    }
621
622
    /**
623
     * Creates a loan offer for a given currency.
624
     *
625
     * @param CreateLoanOfferRequest $request
626
     * @return CreateLoanOffer
627
     */
628
    public function createLoanOffer(CreateLoanOfferRequest $request): CreateLoanOffer
629
    {
630
        foreach (get_object_vars($request) as $property => $value) {
631
            $this->throwExceptionIf(
632
                $value === null,
633
                sprintf('Unable to send "moveOrder" request. Field "%s" should be set.', $property)
634
            );
635
        }
636
637
        /* @var $createLoanOffer CreateLoanOffer */
638
        $createLoanOffer = $this->factory(
639
            CreateLoanOffer::class,
640
            $this->request('createLoanOffer', get_object_vars($request))
641
        );
642
643
        return $createLoanOffer;
644
    }
645
646
    /**
647
     * Cancels a loan offer specified by the "orderNumber" POST parameter.
648
     *
649
     * @param int $orderNumber
650
     * @return SampleResponse
651
     */
652
    public function cancelLoanOffer(int $orderNumber): SampleResponse
653
    {
654
        /* @var $response SampleResponse */
655
        $response = $this->factory(
656
            SampleResponse::class,
657
            $this->request('cancelLoanOffer', compact('orderNumber'))
658
        );
659
660
        return $response;
661
    }
662
663
    /**
664
     * Returns your open loan offers for each currency.
665
     * NOTE: Keys of result array is currency codes
666
     *
667
     * @return Loan[][]
668
     */
669
    public function returnOpenLoanOffers(): array
670
    {
671
        $openLoanOffers = [];
672
673
        /* @var $offers array */
674
        foreach ($this->request('returnOpenLoanOffers') as $currency => $offers) {
675
            foreach ($offers as $offer) {
676
                $openLoanOffers[$currency][] = $this->factory(Loan::class, $offer);
677
            }
678
        }
679
680
        return $openLoanOffers;
681
    }
682
683
    /**
684
     * Returns your active loans for each currency
685
     */
686
    public function returnActiveLoans(): ActiveLoans
687
    {
688
        /* @var $activeLoans ActiveLoans */
689
        $activeLoans = $this->factory(
690
            ActiveLoans::class,
691
            $this->request('returnActiveLoans')
692
        );
693
694
        return $activeLoans;
695
    }
696
697
    /**
698
     * Returns your lending history within a time range specified by the "start" and "end" POST parameters
699
     * as UNIX timestamps. "limit" may also be specified to limit the number of rows returned.
700
     *
701
     * @param int      $start
702
     * @param int      $end
703
     * @param int|null $limit
704
     *
705
     * @return LandingHistory[]
706
     */
707
    public function returnLendingHistory(int $start, int $end, int $limit = null): array
708
    {
709
        $history = [];
710
711
        foreach ($this->request('returnLendingHistory', compact('start', 'end', 'limit')) as $data) {
712
            $history[] = $this->factory(LandingHistory::class, $data);
713
        }
714
715
        return $history;
716
    }
717
718
    /**
719
     * Toggles the autoRenew setting on an active loan, specified by the "orderNumber" POST parameter.
720
     * If successful, "message" will indicate the new autoRenew setting.
721
     *
722
     * @param int $orderNumber
723
     *
724
     * @return SampleResponse
725
     */
726
    public function toggleAutoRenew(int $orderNumber): SampleResponse
727
    {
728
        /* @var $autoRenew SampleResponse */
729
        $autoRenew = $this->factory(
730
            SampleResponse::class,
731
            $this->request('toggleAutoRenew', compact('orderNumber'))
732
        );
733
734
        return $autoRenew;
735
    }
736
737
    /**
738
     * Places a limit buy order in a given market. Required POST parameters are "currencyPair", "rate", and "amount".
739
     * If successful, the method will return the order number.
740
     *
741
     * You may optionally set "fillOrKill", "immediateOrCancel", "postOnly" to 1. A fill-or-kill order will either
742
     * fill in its entirety or be completely aborted. An immediate-or-cancel order can be partially or completely
743
     * filled, but any portion of the order that cannot be filled immediately will be canceled rather than left on
744
     * the order book. A post-only order will only be placed if no portion of it fills immediately; this guarantees
745
     * you will never pay the taker fee on any part of the order that fills.
746
     *
747
     * @param string $command
748
     * @param TradeRequest $tradeRequest
749
     *
750
     * @return TradeResult
751
     */
752
    protected function tradeRequest(string $command, TradeRequest $tradeRequest): TradeResult
753
    {
754
        foreach (['currencyPair', 'rate', 'amount'] as $requiredField) {
755
            $this->throwExceptionIf(
756
                $tradeRequest->{$requiredField} === null,
757
                sprintf('Unable to send "%s" request. Field "%s" should be set.', $command, $requiredField)
758
            );
759
        }
760
761
        $coin = strtoupper(explode('_', $tradeRequest->currencyPair)[0]);
762
        $total = $tradeRequest->amount * $tradeRequest->rate;
763
764
        if (isset(TradeRequest::MIN_TOTAL[$coin]) && TradeRequest::MIN_TOTAL[$coin] > $total) {
765
            throw new TotalDeficiencyException(TradeRequest::MIN_TOTAL[$coin], $coin);
766
        }
767
768
        $response = $this->request($command, get_object_vars($tradeRequest));
769
        $this->throwExceptionIf(!isset($response['orderNumber'], $response['resultingTrades']), 'Poloniex buy error.');
770
771
        $buySell = new TradeResult();
772
        $buySell->orderNumber = (int) $response['orderNumber'];
773
        $resultingTrades = $response['resultingTrades'] ?? [];
774
775
        foreach ($resultingTrades as $trade) {
776
            $buySell->resultingTrades[] = $this->factory(ResultingTrade::class, $trade);
777
        }
778
779
        return $buySell;
780
    }
781
782
    /**
783
     * @param string $command
784
     * @param array  $params
785
     *
786
     * @return MarginTrade
787
     */
788
    protected function marginTrade(string $command, array $params): MarginTrade
789
    {
790
        $response = $this->request($command, $params);
791
792
        $marginTrade = new MarginTrade();
793
        $marginTrade->success = $response['success'] ?? null;
794
        $marginTrade->message = $response['message'] ?? null;
795
        $marginTrade->orderNumber = (int) $response['orderNumber'];
796
797
        $resultingTrades = $response['resultingTrades'] ?? [];
798
799
        /*  @var $trades array */
800
        foreach ($resultingTrades as $currencyPair => $trades) {
801
            foreach ($trades as $trade) {
802
                $marginTrade->resultingTrades[$currencyPair][] = $this->factory(ResultingTrade::class, $trade);
803
            }
804
        }
805
806
        return $marginTrade;
807
    }
808
809
    /**
810
     * The nonce parameter is an integer which must always be greater than the previous nonce used.
811
     * Generate a nonce to avoid problems with 32bit systems
812
     */
813
    public function getNonce(): int
814
    {
815
        $time = explode(' ', microtime());
816
817
        return $time[1] . substr($time[0], 2, 6);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $time[1] . substr($time[0], 2, 6) returns the type string which is incompatible with the type-hinted return integer.
Loading history...
818
    }
819
820
    /**
821
     * {@inheritdoc}
822
     */
823
    protected function setup(): void
824
    {
825
        $this->method = 'POST';
826
        $this->uri = 'tradingApi';
827
    }
828
}