├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── Api │ ├── Account.php │ ├── Api.php │ ├── Market.php │ └── PublicApi.php ├── BittrexClient.php ├── Exception │ ├── BittrexException.php │ ├── InvalidCredentialException.php │ └── TransformResponseException.php ├── Message │ └── ResponseTransformer.php └── Middleware │ └── Authentication.php └── tests ├── Api ├── AccountTest.php ├── ApiTestCase.php ├── MarketTest.php └── PublicApiTest.php ├── BittrexClientTest.php ├── Message └── ResponseTransformerTest.php └── Middleware └── AuthenticationTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | build 4 | phpunit.xml 5 | .phpunit.result.cache -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - php 3 | 4 | tools: 5 | external_code_coverage: true -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '7.2' 5 | - '7.3' 6 | - '7.4' 7 | 8 | sudo: false 9 | 10 | cache: 11 | directories: 12 | - $HOME/.composer/cache 13 | 14 | install: 15 | - travis_retry composer self-update && composer --version 16 | - travis_retry composer update --dev --prefer-dist --no-interaction 17 | 18 | before_script: 19 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter 20 | - chmod +x ./cc-test-reporter 21 | - ./cc-test-reporter before-build 22 | 23 | script: 24 | - composer validate --strict 25 | - vendor/bin/phpunit 26 | 27 | after_script: 28 | - if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT; fi 29 | - wget https://scrutinizer-ci.com/ocular.phar 30 | - php ocular.phar code-coverage:upload --format=php-clover ./build/logs/clover.xml 31 | 32 | notifications: 33 | email: 34 | recipients: 35 | - codenix.sv@gmail.com 36 | on_success: never 37 | on_failure: always 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Volodymyr Svyryd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bittrex-api 2 | [![Build Status](https://travis-ci.com/codenix-sv/bittrex-api.svg?branch=master)](https://travis-ci.com/codenix-sv/bittrex-api) 3 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/codenix-sv/bittrex-api/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/codenix-sv/bittrex-api/?branch=master) 4 | [![Test Coverage](https://api.codeclimate.com/v1/badges/49b696439195269120b4/test_coverage)](https://codeclimate.com/github/codenix-sv/bittrex-api/test_coverage) 5 | [![Maintainability](https://api.codeclimate.com/v1/badges/49b696439195269120b4/maintainability)](https://codeclimate.com/github/codenix-sv/bittrex-api/maintainability) 6 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/codenix-sv/bittrex-api/blob/master/LICENSE) 7 | ![Packagist](https://img.shields.io/packagist/dt/codenix-sv/bittrex-api) 8 | 9 | A simple PHP wrapper for [Bittrex API](https://bittrex.github.io/api/v1-1). Bittrex is the next generation crypto trading platform. 10 | 11 | ## Requirements 12 | 13 | * PHP >= 7.2 14 | * ext-json 15 | * [Bittrex account](https://global.bittrex.com/), API key and API secret 16 | 17 | ## Installation 18 | 19 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 20 | 21 | Either run 22 | 23 | ```bash 24 | $ composer require codenix-sv/bittrex-api 25 | ``` 26 | or add 27 | 28 | ```json 29 | "codenix-sv/bittrex-api" : "^1.0" 30 | ``` 31 | 32 | to the require section of your application's `composer.json` file. 33 | 34 | ## Basic usage 35 | 36 | ### Example 37 | ```php 38 | use Codenixsv\BittrexApi\BittrexClient; 39 | 40 | $client = new BittrexClient(); 41 | $client->setCredential('API_KEY', 'API_SECRET'); 42 | 43 | $data = $client->public()->getMarkets(); 44 | ``` 45 | ## Available methods 46 | 47 | ### Public API 48 | 49 | #### Get the open and available trading markets 50 | ```php 51 | $data = $client->public()->getMarkets(); 52 | ``` 53 | 54 | #### Get all supported currencies 55 | ```php 56 | $data = $client->public()->getCurrencies(); 57 | ``` 58 | 59 | #### Get the current tick values for a market 60 | ```php 61 | $data = $client->public()->getTicker('BTC-LTC'); 62 | ``` 63 | #### Get the last 24 hour summary of all active exchanges 64 | ```php 65 | $data = $client->public()->getMarketSummaries(); 66 | ``` 67 | 68 | #### Get the last 24 hour summary of all active exchanges for a market 69 | ```php 70 | $data = $client->public()->getMarketSummary('BTC-LTC'); 71 | ``` 72 | 73 | #### Get the orderbook for a given market 74 | ```php 75 | $data = $client->public()->getOrderBook('BTC-LTC'); 76 | ``` 77 | 78 | #### Get latest trades that have occurred for a specific market 79 | ```php 80 | $data = $client->public()->getMarketHistory('BTC-LTC'); 81 | ``` 82 | 83 | ### Market API 84 | 85 | #### Place a buy order in a specific market 86 | ```php 87 | $data = $client->market()->buyLimit('BTC-LTC', 1.2, 1.3); 88 | ``` 89 | 90 | #### Place a sell order in a specific market 91 | ```php 92 | $data = $client->market()->sellLimit('BTC-LTC', 1.2, 1.3); 93 | ``` 94 | 95 | #### Cancel a buy or sell order 96 | ```php 97 | $data = $client->market()->cancel('251c48e7-95d4-d53f-ad76-a7c6547b74ca9'); 98 | ``` 99 | 100 | #### Get all orders that you currently have opened 101 | ```php 102 | $data = $client->market()->getOpenOrders('BTC-LTC'); 103 | ``` 104 | 105 | ### Account API 106 | 107 | #### Get all balances from your account 108 | ```php 109 | $data = $client->account()->getBalances(); 110 | ``` 111 | 112 | #### Get balance from your account for a specific currency 113 | ```php 114 | $data = $client->account()->getBalance('BTC'); 115 | ``` 116 | 117 | #### Get or generate an address for a specific currency 118 | ```php 119 | $data = $client->account()->getDepositAddress('BTC'); 120 | ``` 121 | 122 | #### Withdraw funds from your account 123 | ```php 124 | $data = $client->account()->withdraw('BTC', 20.40, 'EAC_ADDRESS'); 125 | ``` 126 | 127 | #### Get a single order by uuid 128 | ```php 129 | $data = $client->account()->getOrder('251c48e7-95d4-d53f-ad76-a7c6547b74ca9'); 130 | ``` 131 | 132 | #### Get order history 133 | ```php 134 | $data = $client->account()->getOrderHistory('BTC-LTC'); 135 | ``` 136 | 137 | #### Get withdrawal history 138 | ```php 139 | $data = $client->account()->getWithdrawalHistory('BTC'); 140 | ``` 141 | 142 | #### Get deposit history 143 | ```php 144 | $data = $client->account()->getDepositHistory('BTC'); 145 | ``` 146 | 147 | ## Further Information 148 | Please, check the [Bittrex site](https://bittrex.github.io/api/v1-1) documentation for further 149 | information about API. 150 | 151 | ## License 152 | 153 | `codenix-sv/bittrex-api` is released under the MIT License. See the bundled [LICENSE](./LICENSE) for details. 154 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codenix-sv/bittrex-api", 3 | "type": "library", 4 | "description": "PHP client for Bittrex API", 5 | "homepage": "https://github.com/codenix-sv/bittrex-api", 6 | "keywords": ["client", "api", "php", "bittrex", "rest", "bittrex-api", "exchange"], 7 | "license": "MIT", 8 | "support": { 9 | "issues": "https://github.com/codenix-sv/bittrex-api/issues?state=open", 10 | "source": "https://github.com/codenix-sv/bittrex-api" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Volodymyr Svyryd", 15 | "email": "codenix.sv@gmail.com", 16 | "role": "Developer" 17 | } 18 | ], 19 | "require": { 20 | "php": ">=7.2", 21 | "ext-json": "*", 22 | "guzzlehttp/guzzle": "~6.0" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "^8.0" 26 | }, 27 | "autoload": { 28 | "psr-4": { "Codenixsv\\BittrexApi\\": "src/" } 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { "Codenixsv\\BittrexApi\\Tests\\": "tests/"} 32 | }, 33 | "prefer-stable": true 34 | } 35 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests 16 | 17 | 18 | 19 | 20 | ./src 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Api/Account.php: -------------------------------------------------------------------------------- 1 | get('/account/getbalances'); 22 | } 23 | 24 | /** 25 | * @param string $currency 26 | * @return array 27 | * @throws Exception 28 | */ 29 | public function getBalance(string $currency): array 30 | { 31 | $parameters = ['currency' => $currency]; 32 | 33 | return $this->get('/account/getbalance', $parameters); 34 | } 35 | 36 | /** 37 | * @param string $currency 38 | * @return array 39 | * @throws Exception 40 | */ 41 | public function getDepositAddress(string $currency): array 42 | { 43 | $parameters = ['currency' => $currency]; 44 | 45 | return $this->get('/account/getdepositaddress', $parameters); 46 | } 47 | 48 | /** 49 | * @param string $currency 50 | * @param float $quantity 51 | * @param string $address 52 | * @param string|null $paymentId 53 | * @return array 54 | * @throws Exception 55 | */ 56 | public function withdraw(string $currency, float $quantity, string $address, ?string $paymentId = null): array 57 | { 58 | $parameters = ['currency' => $currency, 'quantity' => (string)$quantity, 'address' => $address]; 59 | 60 | if (!is_null($paymentId)) { 61 | $parameters['paymentid'] = $paymentId; 62 | } 63 | 64 | return $this->get('/account/withdraw', $parameters); 65 | } 66 | 67 | /** 68 | * @param string $uuid 69 | * @return array 70 | * @throws Exception 71 | */ 72 | public function getOrder(string $uuid): array 73 | { 74 | $parameters = ['uuid' => $uuid]; 75 | 76 | return $this->get('/account/getorder', $parameters); 77 | } 78 | 79 | /** 80 | * @param string|null $market 81 | * @return array 82 | * @throws Exception 83 | */ 84 | public function getOrderHistory(?string $market = null): array 85 | { 86 | $parameters = []; 87 | 88 | if (!is_null($market)) { 89 | $parameters['market'] = $market; 90 | } 91 | 92 | return $this->get('/account/getorderhistory', $parameters); 93 | } 94 | 95 | /** 96 | * @param string|null $currency 97 | * @return array 98 | * @throws Exception 99 | */ 100 | public function getWithdrawalHistory(string $currency = null): array 101 | { 102 | $parameters = []; 103 | 104 | if (!is_null($currency)) { 105 | $parameters['currency'] = $currency; 106 | } 107 | 108 | return $this->get('/account/getwithdrawalhistory', $parameters); 109 | } 110 | 111 | /** 112 | * @param string|null $currency 113 | * @return array 114 | * @throws Exception 115 | */ 116 | public function getDepositHistory(?string $currency = null): array 117 | { 118 | $parameters = []; 119 | 120 | if (!is_null($currency)) { 121 | $parameters['currency'] = $currency; 122 | } 123 | 124 | return $this->get('/account/getdeposithistory', $parameters); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Api/Api.php: -------------------------------------------------------------------------------- 1 | client = $client; 33 | $this->transformer = new ResponseTransformer(); 34 | } 35 | 36 | /** 37 | * @param string $uri 38 | * @param array $query 39 | * @return array 40 | * @throws Exception 41 | */ 42 | public function get(string $uri, array $query = []): array 43 | { 44 | $response = $this->client->request('GET', '/api/' . $this->version 45 | . $uri, ['query' => $query]); 46 | 47 | return $this->transformer->transform($response); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Api/Market.php: -------------------------------------------------------------------------------- 1 | $market, 'quantity' => $quantity, 'rate' => $rate]; 25 | 26 | return $this->get('/market/buylimit', $parameters); 27 | } 28 | 29 | /** 30 | * @param string $market 31 | * @param float $quantity 32 | * @param float $rate 33 | * @return array 34 | * @throws Exception 35 | */ 36 | public function sellLimit(string $market, float $quantity, float $rate): array 37 | { 38 | $parameters = ['market' => $market, 'quantity' => $quantity, 'rate' => $rate]; 39 | 40 | return $this->get('/market/selllimit', $parameters); 41 | } 42 | 43 | /** 44 | * @param string $uuid 45 | * @return array 46 | * @throws Exception 47 | */ 48 | public function cancel(string $uuid): array 49 | { 50 | $parameters = ['uuid' => $uuid]; 51 | 52 | return $this->get('/market/cancel', $parameters); 53 | } 54 | 55 | /** 56 | * @param string|null $market 57 | * @return array 58 | * @throws Exception 59 | */ 60 | public function getOpenOrders(?string $market = null): array 61 | { 62 | $parameters = []; 63 | 64 | if (!is_null($market)) { 65 | $parameters['market'] = $market; 66 | } 67 | 68 | return $this->get('/market/getopenorders', $parameters); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Api/PublicApi.php: -------------------------------------------------------------------------------- 1 | get('/public/getmarkets'); 22 | } 23 | 24 | /** 25 | * @return array 26 | * @throws Exception 27 | */ 28 | public function getCurrencies(): array 29 | { 30 | return $this->get('/public/getcurrencies'); 31 | } 32 | 33 | /** 34 | * @param string $market 35 | * @return array 36 | * @throws Exception 37 | */ 38 | public function getTicker(string $market): array 39 | { 40 | $parameters = ['market' => $market]; 41 | 42 | return $this->get('/public/getticker', $parameters); 43 | } 44 | 45 | /** 46 | * @return array 47 | * @throws Exception 48 | */ 49 | public function getMarketSummaries(): array 50 | { 51 | return $this->get('/public/getmarketsummaries'); 52 | } 53 | 54 | /** 55 | * @param string $market 56 | * @return array 57 | * @throws Exception 58 | */ 59 | public function getMarketSummary(string $market): array 60 | { 61 | $parameters = ['market' => $market]; 62 | 63 | return $this->get('/public/getmarketsummary', $parameters); 64 | } 65 | 66 | /** 67 | * @param string $market 68 | * @param string $type 69 | * @return array 70 | * @throws Exception 71 | */ 72 | public function getOrderBook(string $market, $type = 'both'): array 73 | { 74 | $parameters = ['market' => $market, 'type' => $type]; 75 | 76 | return $this->get('/public/getorderbook', $parameters); 77 | } 78 | 79 | /** 80 | * @param string $market 81 | * @return array 82 | * @throws Exception 83 | */ 84 | public function getMarketHistory(string $market) 85 | { 86 | $parameters = ['market' => $market]; 87 | 88 | return $this->get('/public/getmarkethistory', $parameters); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/BittrexClient.php: -------------------------------------------------------------------------------- 1 | key = $key; 38 | $this->secret = $secret; 39 | } 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getKey(): string 45 | { 46 | return $this->key; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getSecret(): string 53 | { 54 | return $this->secret; 55 | } 56 | 57 | /** 58 | * @return PublicApi 59 | */ 60 | public function public(): PublicApi 61 | { 62 | return new PublicApi($this->getPublicClient()); 63 | } 64 | 65 | /** 66 | * @return Market 67 | * @throws InvalidCredentialException 68 | */ 69 | public function market(): Market 70 | { 71 | return new Market($this->getPrivateClient()); 72 | } 73 | 74 | /** 75 | * @return Account 76 | * @throws InvalidCredentialException 77 | */ 78 | public function account(): Account 79 | { 80 | return new Account($this->getPrivateClient()); 81 | } 82 | 83 | /** 84 | * @return Client 85 | */ 86 | private function createPublicClient(): Client 87 | { 88 | return new Client(['base_uri' => self::BASE_URI]); 89 | } 90 | 91 | /** 92 | * @return Client 93 | * @throws InvalidCredentialException 94 | */ 95 | private function createPrivateClient(): Client 96 | { 97 | if (empty($this->key) || empty($this->secret)) { 98 | throw new InvalidCredentialException('Key and secret must be set for authenticated API'); 99 | } 100 | $stack = HandlerStack::create(); 101 | $stack->push(new Authentication($this->getKey(), $this->getSecret(), (string)time())); 102 | 103 | return new Client(['handler' => $stack, 'base_uri' => self::BASE_URI]); 104 | } 105 | 106 | /** 107 | * @return Client 108 | * @throws InvalidCredentialException 109 | */ 110 | private function getPrivateClient(): Client 111 | { 112 | return $this->privateClient ?: $this->createPrivateClient(); 113 | } 114 | 115 | /** 116 | * @return Client 117 | */ 118 | private function getPublicClient(): Client 119 | { 120 | return $this->publicClient ?: $this->createPublicClient(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Exception/BittrexException.php: -------------------------------------------------------------------------------- 1 | getBody(); 24 | if (strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0) { 25 | $content = json_decode($body, true); 26 | if (JSON_ERROR_NONE === json_last_error()) { 27 | return $content; 28 | } 29 | 30 | throw new TransformResponseException('Error transforming response to array. JSON_ERROR: ' 31 | . json_last_error()); 32 | } 33 | 34 | throw new TransformResponseException('Error transforming response to array. Content-Type 35 | is not application/json'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Middleware/Authentication.php: -------------------------------------------------------------------------------- 1 | key = $key; 30 | $this->secret = $secret; 31 | $this->nonce = $nonce; 32 | } 33 | 34 | /** 35 | * @param callable $next 36 | * @return Closure 37 | */ 38 | public function __invoke(callable $next) 39 | { 40 | return function (RequestInterface $request, array $options = []) use ($next) { 41 | 42 | $request = $this->addAuthQueryParams($request); 43 | $sign = $this->generateSign($request->getUri()->__toString()); 44 | $request = $request->withAddedHeader('apisign', $sign); 45 | 46 | return $next($request, $options); 47 | }; 48 | } 49 | 50 | /** 51 | * @param RequestInterface $request 52 | * @return RequestInterface 53 | */ 54 | private function addAuthQueryParams(RequestInterface $request): RequestInterface 55 | { 56 | parse_str($request->getUri()->getQuery(), $params); 57 | $params['nonce'] = $this->nonce; 58 | $params['apikey'] = $this->key; 59 | $uri = $request->getUri()->withQuery(http_build_query($params)); 60 | 61 | return $request->withUri($uri); 62 | } 63 | 64 | /** 65 | * @param string $uri 66 | * @return string 67 | */ 68 | private function generateSign(string $uri): string 69 | { 70 | return hash_hmac('sha512', $uri, $this->secret); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/Api/AccountTest.php: -------------------------------------------------------------------------------- 1 | createApi()->getBalances(); 14 | $request = $this->getLastRequest(); 15 | 16 | $this->assertEquals( 17 | '/api/v1.1/account/getbalances?nonce=1585301777&apikey=API_KEY', 18 | $request->getUri()->__toString() 19 | ); 20 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 21 | } 22 | 23 | public function testGetBalance() 24 | { 25 | $this->createApi()->getBalance('BTC'); 26 | $request = $this->getLastRequest(); 27 | 28 | $this->assertEquals( 29 | '/api/v1.1/account/getbalance?currency=BTC&nonce=1585301777&apikey=API_KEY', 30 | $request->getUri()->__toString() 31 | ); 32 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 33 | } 34 | 35 | public function testGetDepositAddress() 36 | { 37 | $this->createApi()->getDepositAddress('BTC'); 38 | $request = $this->getLastRequest(); 39 | 40 | $this->assertEquals( 41 | '/api/v1.1/account/getdepositaddress?currency=BTC&nonce=1585301777&apikey=API_KEY', 42 | $request->getUri()->__toString() 43 | ); 44 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 45 | } 46 | 47 | public function testWithdraw() 48 | { 49 | $this->createApi()->withdraw('BTC', 1.40, '12rwaw7p4eTQ3DL5gu4fSYYx3M3kZxxQVn', 'paymentId'); 50 | 51 | $request = $this->getLastRequest(); 52 | $this->assertEquals( 53 | '/api/v1.1/account/withdraw?currency=BTC&quantity=1.4&address=12rwaw7p4eTQ3DL5gu4fSYYx3M3kZxxQVn' 54 | . '&paymentid=paymentId&nonce=1585301777&apikey=API_KEY', 55 | $request->getUri()->__toString() 56 | ); 57 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 58 | } 59 | 60 | public function testGetOrder() 61 | { 62 | $this->createApi()->getOrder('251c48e7-95d4-d53f-ad76-a7c6547b74ca9'); 63 | 64 | $request = $this->getLastRequest(); 65 | $this->assertEquals( 66 | '/api/v1.1/account/getorder?uuid=251c48e7-95d4-d53f-ad76-a7c6547b74ca9&nonce=1585301777&apikey=API_KEY', 67 | $request->getUri()->__toString() 68 | ); 69 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 70 | } 71 | 72 | public function testGetOrderHistory() 73 | { 74 | $this->createApi()->getOrderHistory('BTC-LTC'); 75 | 76 | $request = $this->getLastRequest(); 77 | $this->assertEquals( 78 | '/api/v1.1/account/getorderhistory?market=BTC-LTC&nonce=1585301777&apikey=API_KEY', 79 | $request->getUri()->__toString() 80 | ); 81 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 82 | } 83 | 84 | public function testGetWithdrawalHistory() 85 | { 86 | $this->createApi()->getWithdrawalHistory('BTC'); 87 | 88 | $request = $this->getLastRequest(); 89 | $this->assertEquals( 90 | '/api/v1.1/account/getwithdrawalhistory?currency=BTC&nonce=1585301777&apikey=API_KEY', 91 | $request->getUri()->__toString() 92 | ); 93 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 94 | } 95 | 96 | public function testGetDepositHistory() 97 | { 98 | $this->createApi()->getDepositHistory('BTC'); 99 | 100 | $request = $this->getLastRequest(); 101 | $this->assertEquals( 102 | '/api/v1.1/account/getdeposithistory?currency=BTC&nonce=1585301777&apikey=API_KEY', 103 | $request->getUri()->__toString() 104 | ); 105 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 106 | } 107 | 108 | private function createApi(): Account 109 | { 110 | return new Account($this->getMockClient(true)); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /tests/Api/ApiTestCase.php: -------------------------------------------------------------------------------- 1 | transactions)) === 0) { 24 | return null; 25 | } 26 | 27 | return $this->transactions[$count - 1]['request'] ?? null; 28 | } 29 | 30 | protected function getMockClient($isPrivateClient = false) 31 | { 32 | $mock = new MockHandler([ 33 | new Response(200, ['Content-Type' => 'application/json'], json_encode(['fo' => 'bar'])), 34 | ]); 35 | 36 | $handlerStack = HandlerStack::create($mock); 37 | 38 | if ($isPrivateClient) { 39 | $handlerStack->push(new Authentication('API_KEY', 'API_SECRET', (string)1585301777)); 40 | } 41 | 42 | $handlerStack->push(Middleware::history($this->transactions)); 43 | $this->mockClient = new Client(['handler' => $handlerStack]); 44 | 45 | return $this->mockClient; 46 | } 47 | 48 | protected function tearDown(): void 49 | { 50 | $this->mockClient = null; 51 | $this->transactions = []; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/Api/MarketTest.php: -------------------------------------------------------------------------------- 1 | createApi()->buyLimit('USDT-BTC', 1, 1); 14 | $request = $this->getLastRequest(); 15 | 16 | $this->assertEquals( 17 | '/api/v1.1/market/buylimit?market=USDT-BTC&quantity=1&rate=1&nonce=1585301777&apikey=API_KEY', 18 | $request->getUri()->__toString() 19 | ); 20 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 21 | } 22 | 23 | public function testSellLimit() 24 | { 25 | $this->createApi()->sellLimit('BTC-LTC', 1.2, 1.3); 26 | $request = $this->getLastRequest(); 27 | 28 | $this->assertEquals( 29 | '/api/v1.1/market/selllimit?market=BTC-LTC&quantity=1.2&rate=1.3&nonce=1585301777&apikey=API_KEY', 30 | $request->getUri()->__toString() 31 | ); 32 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 33 | } 34 | 35 | public function testCancel() 36 | { 37 | $this->createApi()->cancel('251c48e7-95d4-d53f-ad76-a7c6547b74ca9'); 38 | $request = $this->getLastRequest(); 39 | 40 | $this->assertEquals( 41 | '/api/v1.1/market/cancel?uuid=251c48e7-95d4-d53f-ad76-a7c6547b74ca9&nonce=1585301777&apikey=API_KEY', 42 | $request->getUri()->__toString() 43 | ); 44 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 45 | } 46 | 47 | public function testGetOpenOrders() 48 | { 49 | $this->createApi()->getOpenOrders(); 50 | 51 | $request = $this->getLastRequest(); 52 | $this->assertEquals( 53 | '/api/v1.1/market/getopenorders?nonce=1585301777&apikey=API_KEY', 54 | $request->getUri()->__toString() 55 | ); 56 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 57 | } 58 | 59 | public function testGetOpenOrdersWithMarket() 60 | { 61 | $this->createApi()->getOpenOrders('BTC-LTC'); 62 | 63 | $request = $this->getLastRequest(); 64 | $this->assertEquals( 65 | '/api/v1.1/market/getopenorders?market=BTC-LTC&nonce=1585301777&apikey=API_KEY', 66 | $request->getUri()->__toString() 67 | ); 68 | $this->assertNotEmpty($request->getHeaderLine('apisign')); 69 | } 70 | 71 | private function createApi(): Market 72 | { 73 | return new Market($this->getMockClient(true)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Api/PublicApiTest.php: -------------------------------------------------------------------------------- 1 | createApi()->getMarkets(); 14 | $request = $this->getLastRequest(); 15 | 16 | $this->assertEquals('/api/v1.1/public/getmarkets', $request->getUri()->__toString()); 17 | } 18 | 19 | public function testGetCurrencies() 20 | { 21 | $this->createApi()->getCurrencies(); 22 | $request = $this->getLastRequest(); 23 | 24 | $this->assertEquals('/api/v1.1/public/getcurrencies', $request->getUri()->__toString()); 25 | } 26 | 27 | public function testGetTicker() 28 | { 29 | $this->createApi()->getTicker('BTC-LTC'); 30 | $request = $this->getLastRequest(); 31 | $this->assertEquals('/api/v1.1/public/getticker?market=BTC-LTC', $request->getUri()->__toString()); 32 | } 33 | 34 | public function testGetMarketSummaries() 35 | { 36 | $this->createApi()->getMarketSummaries(); 37 | 38 | $request = $this->getLastRequest(); 39 | $this->assertEquals('/api/v1.1/public/getmarketsummaries', $request->getUri()->__toString()); 40 | } 41 | 42 | public function testGetMarketSummary() 43 | { 44 | $this->createApi()->getMarketSummary('BTC-LTC'); 45 | 46 | $request = $this->getLastRequest(); 47 | $this->assertEquals('/api/v1.1/public/getmarketsummary?market=BTC-LTC', $request->getUri()->__toString()); 48 | } 49 | 50 | public function testGetOrderBook() 51 | { 52 | $this->createApi()->getOrderBook('BTC-LTC'); 53 | 54 | $request = $this->getLastRequest(); 55 | $this->assertEquals('/api/v1.1/public/getorderbook?market=BTC-LTC&type=both', $request->getUri()->__toString()); 56 | } 57 | 58 | public function testGetMarketHistory() 59 | { 60 | $this->createApi()->getMarketHistory('BTC-LTC'); 61 | 62 | $request = $this->getLastRequest(); 63 | $this->assertEquals('/api/v1.1/public/getmarkethistory?market=BTC-LTC', $request->getUri()->__toString()); 64 | } 65 | 66 | private function createApi(): PublicApi 67 | { 68 | return new PublicApi($this->getMockClient()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/BittrexClientTest.php: -------------------------------------------------------------------------------- 1 | assertEmpty($client->getKey()); 21 | $this->assertEmpty($client->getSecret()); 22 | } 23 | 24 | public function testSetCredential() 25 | { 26 | $secret = 'API_SECRET'; 27 | $key = 'API_KEY'; 28 | 29 | $client = new BittrexClient(); 30 | $client->setCredential($key, $secret); 31 | 32 | $this->assertEquals($client->getKey(), $key); 33 | $this->assertEquals($client->getSecret(), $secret); 34 | } 35 | 36 | public function testPublic() 37 | { 38 | $client = new BittrexClient(); 39 | 40 | $this->assertInstanceOf(PublicApi::class, $client->public()); 41 | } 42 | 43 | public function testMarket() 44 | { 45 | $client = new BittrexClient(); 46 | $client->setCredential('API_KEY', 'API_SECRET'); 47 | 48 | $this->assertInstanceOf(Market::class, $client->market()); 49 | } 50 | 51 | public function testMarketThrowInvalidCredentialException() 52 | { 53 | $client = new BittrexClient(); 54 | 55 | $this->expectException(InvalidCredentialException::class); 56 | 57 | $client->market(); 58 | } 59 | 60 | public function testAccount() 61 | { 62 | $client = new BittrexClient(); 63 | $client->setCredential('API_KEY', 'API_SECRET'); 64 | 65 | $this->assertInstanceOf(Account::class, $client->account()); 66 | } 67 | 68 | public function testAccountThrowInvalidCredentialException() 69 | { 70 | $client = new BittrexClient(); 71 | 72 | $this->expectException(InvalidCredentialException::class); 73 | 74 | $client->account(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/Message/ResponseTransformerTest.php: -------------------------------------------------------------------------------- 1 | 'bar']; 18 | $response = new Response(200, ['Content-Type' => 'application/json'], json_encode($data)); 19 | 20 | $this->assertEquals($data, $transformer->transform($response)); 21 | } 22 | 23 | public function testTransformWithEmptyBody() 24 | { 25 | $transformer = new ResponseTransformer(); 26 | $data = []; 27 | $response = new Response(200, ['Content-Type' => 'application/json'], json_encode($data)); 28 | 29 | $this->assertEquals($data, $transformer->transform($response)); 30 | } 31 | 32 | public function testTransformThrowTransformResponseException() 33 | { 34 | $transformer = new ResponseTransformer(); 35 | $response = new Response(200, ['Content-Type' => 'application/json'], ''); 36 | 37 | $this->expectException(TransformResponseException::class); 38 | 39 | $transformer->transform($response); 40 | } 41 | 42 | public function testTransformWithIncorrectContentType() 43 | { 44 | $transformer = new ResponseTransformer(); 45 | $data = []; 46 | $response = new Response(200, ['Content-Type' => 'application/javascript'], json_encode($data)); 47 | 48 | $this->expectException(TransformResponseException::class); 49 | 50 | $this->assertEquals($data, $transformer->transform($response)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/Middleware/AuthenticationTest.php: -------------------------------------------------------------------------------- 1 | getHandledRequest(new Request(self::METHOD, self::URI, [])); 23 | $this->assertEquals( 24 | self::URI . '?nonce=' . self::NONCE . '&apikey=' . self::API_KEY, 25 | $request->getUri()->__toString() 26 | ); 27 | } 28 | 29 | public function testHeader() 30 | { 31 | $request = $this->getHandledRequest(new Request(self::METHOD, self::URI, [])); 32 | $this->assertEquals( 33 | '041fde5a91c95dc6606b216c48d7c19dd129d8f8b4b55b286b71c82fe4772b268f39b3788c60179180c4f73d00ae7380' 34 | . '47c62f62ed58553b436dab533a18f273', 35 | $request->getHeaderLine('apisign') 36 | ); 37 | } 38 | 39 | private function getHandledRequest(RequestInterface $request): RequestInterface 40 | { 41 | $middleware = new Authentication(self::API_KEY, self::API_SECRET, self::NONCE); 42 | return $middleware(function (RequestInterface $request) { 43 | return $request; 44 | })($request); 45 | } 46 | } 47 | --------------------------------------------------------------------------------