Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:

- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2.5.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"

- name: Auto-merge Dependabot PRs for semver-minor/patch updates
if: ${{steps.metadata.outputs.update-type != 'version-update:semver-major'}}
run: gh pr merge --auto --merge "$PR_URL"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/fix-php-code-style-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Fix PHP code style issues

on:
push:
branches:
- main
paths:
- '**.php'

Expand Down
84 changes: 68 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
Simplify the integration of the Bitkub API into your PHP application.
[Bitkub API Documentation](https://github.com/bitkub/bitkub-official-api-docs/blob/master/restful-api.md)

**Notes
**Requirements:** PHP 8.2+

**Notes**
We are not affiliated, associated, authorized, endorsed by, or in any way officially connected with Bitkub, or any of its subsidiaries or its affiliates.

## Installation
Expand Down Expand Up @@ -43,27 +45,26 @@ $myBTC = $response->json('result.BTC.available');
echo "My BTC balance: {$myBTC}";
```

Websocket API
WebSocket API

```php
$client = \Farzai\Bitkub\ClientBuilder::create()
->setCredentials('YOUR_API_KEY', 'YOUR_SECRET_KEY')
->build();

$websocket = new \Farzai\Bitkub\WebSocket\Endpoints\MarketEndpoint(
new \Farzai\Bitkub\WebSocketClient(
\Farzai\Bitkub\ClientBuilder::create()
->setCredentials('YOUR_API_KEY', 'YOUR_SECRET_KEY')
->build(),
),
);
$websocket = \Farzai\Bitkub\WebSocketClientBuilder::create()
->setClient($client)
->build();

$websocket->listen('trade.thb_ada', function (\Farzai\Bitkub\WebSocket\Message $message) {
$websocket->market()->listen('trade.thb_ada', function (\Farzai\Bitkub\WebSocket\Message $message) {
// Do something
echo $message->sym.PHP_EOL;
echo $message->sym . PHP_EOL;
});

// Or you can use multiple symbols like this
$websocket->listen(['trade.thb_ada', 'trade.thb_btc', function (\Farzai\Bitkub\WebSocket\Message $message) {
$websocket->market()->listen(['trade.thb_ada', 'trade.thb_btc'], function (\Farzai\Bitkub\WebSocket\Message $message) {
// Do something
echo $message->sym.PHP_EOL;
echo $message->sym . PHP_EOL;
});

$websocket->run();
Expand Down Expand Up @@ -104,6 +105,9 @@ $websocket->run();
- [User](#user)
- [Check trading credit balance.](#check-trading-credit-balance)
- [Check deposit/withdraw limitations and usage.](#check-depositwithdraw-limitations-and-usage)
- [WebSocket](#websocket)
- [Market streams](#market-streams)
- [Live order book](#live-order-book)
- [Testing](#testing)
- [Changelog](#changelog)
- [Contributing](#contributing)
Expand All @@ -112,7 +116,7 @@ $websocket->run();
- [License](#license)

### Market
Call the market endpoint.
Call the market endpoint.
This will return an instance of `Farzai\Bitkub\Endpoints\MarketEndpoint` class.

```php
Expand Down Expand Up @@ -192,7 +196,7 @@ $market->books([
```

#### Get user available balances
- GET `/api/market/wallet`
- POST `/api/v3/market/wallet`
```php
$market->wallet();
```
Expand Down Expand Up @@ -351,7 +355,7 @@ $crypto->addresses([
$crypto->withdrawal([
// string: Currency for withdrawal (e.g. BTC, ETH)
'cur' => 'BTC',

// float: Amount you want to withdraw
'amt' => 0.001,

Expand Down Expand Up @@ -474,6 +478,54 @@ $user->tradingCredits();
$user->limits();
```

### WebSocket

Create a WebSocket client using the `WebSocketClientBuilder`.

```php
$client = \Farzai\Bitkub\ClientBuilder::create()
->setCredentials('YOUR_API_KEY', 'YOUR_SECRET_KEY')
->build();

$websocket = \Farzai\Bitkub\WebSocketClientBuilder::create()
->setClient($client)
->build();
```

#### Market streams

Subscribe to market data streams (trades, tickers, etc.).

```php
$websocket->market()->listen('trade.thb_btc', function (\Farzai\Bitkub\WebSocket\Message $message) {
echo $message->sym . PHP_EOL;
});

// Or subscribe to multiple streams at once
$websocket->market()->listen(['trade.thb_btc', 'trade.thb_eth'], function (\Farzai\Bitkub\WebSocket\Message $message) {
echo $message->sym . PHP_EOL;
});

$websocket->run();
```

#### Live order book

Subscribe to live order book updates. Requires a REST client to resolve symbol names.

```php
$websocket->liveOrderBook()->listen('THB_BTC', function (\Farzai\Bitkub\WebSocket\Message $message) {
echo $message . PHP_EOL;
});

// Or use a numeric symbol ID directly
$websocket->liveOrderBook()->listen(1, function (\Farzai\Bitkub\WebSocket\Message $message) {
echo $message . PHP_EOL;
});

$websocket->run();
```

---

## Testing
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@
"phpstan/extension-installer": true
}
},
"minimum-stability": "dev",
"minimum-stability": "stable",
"prefer-stable": true
}
18 changes: 14 additions & 4 deletions src/Client.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub;

use Farzai\Bitkub\Contracts\ClientInterface;
Expand Down Expand Up @@ -40,24 +42,32 @@ public function __construct(
$this->logger = $logger;
}

private ?Endpoints\MarketEndpoint $marketEndpoint = null;

private ?Endpoints\CryptoEndpoint $cryptoEndpoint = null;

private ?Endpoints\UserEndpoint $userEndpoint = null;

private ?Endpoints\SystemEndpoint $systemEndpoint = null;

public function market(): Endpoints\MarketEndpoint
{
return new Endpoints\MarketEndpoint($this);
return $this->marketEndpoint ??= new Endpoints\MarketEndpoint($this);
}

public function crypto(): Endpoints\CryptoEndpoint
{
return new Endpoints\CryptoEndpoint($this);
return $this->cryptoEndpoint ??= new Endpoints\CryptoEndpoint($this);
}

public function user(): Endpoints\UserEndpoint
{
return new Endpoints\UserEndpoint($this);
return $this->userEndpoint ??= new Endpoints\UserEndpoint($this);
}

public function system(): Endpoints\SystemEndpoint
{
return new Endpoints\SystemEndpoint($this);
return $this->systemEndpoint ??= new Endpoints\SystemEndpoint($this);
}

public function getTransport(): Transport
Expand Down
20 changes: 10 additions & 10 deletions src/ClientBuilder.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub;

use Farzai\Bitkub\Exceptions\InvalidArgumentException;
Expand All @@ -10,7 +12,7 @@

final class ClientBuilder
{
const DEFAULT_HOST = 'api.bitkub.com';
private const DEFAULT_HOST = 'api.bitkub.com';

/**
* The config.
Expand All @@ -32,14 +34,12 @@ final class ClientBuilder
/**
* The number of times to retry failed requests.
*/
private $retries = 3;
private int $retries = 3;

/**
* Create a new client builder instance.
*
* @return static
*/
public static function create()
public static function create(): static
{
return new self;
}
Expand All @@ -49,7 +49,7 @@ public static function create()
*
* @return $this
*/
public function setCredentials(string $apiKey, string $secretKey)
public function setCredentials(string $apiKey, string $secretKey): static
{
$this->config = array_merge($this->config, [
'api_key' => $apiKey,
Expand All @@ -64,7 +64,7 @@ public function setCredentials(string $apiKey, string $secretKey)
*
* @return $this
*/
public function setHttpClient(PsrClientInterface $httpClient)
public function setHttpClient(PsrClientInterface $httpClient): static
{
$this->httpClient = $httpClient;

Expand All @@ -76,14 +76,14 @@ public function setHttpClient(PsrClientInterface $httpClient)
*
* @return $this
*/
public function setLogger(PsrLoggerInterface $logger)
public function setLogger(PsrLoggerInterface $logger): static
{
$this->logger = $logger;

return $this;
}

public function setRetries(int $retries)
public function setRetries(int $retries): static
{
if ($retries < 0) {
throw new \InvalidArgumentException('Retries must be greater than or equal to 0.');
Expand All @@ -94,7 +94,7 @@ public function setRetries(int $retries)
return $this;
}

public function build()
public function build(): Client
{
$this->ensureConfigIsValid();

Expand Down
2 changes: 2 additions & 0 deletions src/Constants/ErrorCodes.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub\Constants;

class ErrorCodes
Expand Down
5 changes: 4 additions & 1 deletion src/Contracts/ClientInterface.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub\Contracts;

use Farzai\Transport\Transport;
use Psr\Http\Message\RequestInterface as PsrRequestInterface;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
use Psr\Log\LoggerInterface;

interface ClientInterface
Expand All @@ -26,5 +29,5 @@ public function getLogger(): LoggerInterface;
/**
* Send the request.
*/
public function sendRequest(PsrRequestInterface $request);
public function sendRequest(PsrRequestInterface $request): PsrResponseInterface;
}
2 changes: 2 additions & 0 deletions src/Contracts/RequestInterceptor.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub\Contracts;

use Psr\Http\Message\RequestInterface as PsrRequestInterface;
Expand Down
7 changes: 7 additions & 0 deletions src/Contracts/WebSocketEngineInterface.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub\Contracts;

interface WebSocketEngineInterface
{
/**
* Handle WebSocket connections and dispatch messages to listeners.
*
* @param array<string, array<callable(\Farzai\Bitkub\WebSocket\Message): void>> $listeners
*/
public function handle(array $listeners): void;
}
7 changes: 7 additions & 0 deletions src/Endpoints/AbstractEndpoint.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Farzai\Bitkub\Endpoints;

use Farzai\Bitkub\Contracts\ClientInterface;
Expand All @@ -14,6 +16,11 @@ public function __construct(ClientInterface $client)
$this->client = $client;
}

protected function filterParams(array $params): array
{
return array_filter($params, fn ($value) => $value !== null && $value !== '');
}

protected function makeRequest(string $method, string $path, array $options = []): PendingRequest
{
return new PendingRequest($this->client, $method, $path, $options);
Expand Down
Loading
Loading