future-private: add getSingleAccount request
This commit is contained in:
parent
18966eaad8
commit
45a0195ec1
30
README.md
30
README.md
|
|
@ -159,6 +159,32 @@ if ($response->getStatusCode() === 200) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Get Single Account
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Msr\LaravelBitunixApi\Requests\GetSingleAccountRequestContract;
|
||||||
|
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
$response = $api->getSingleAccount('USDT');
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
$account = $data['data'][0];
|
||||||
|
echo "Account retrieved successfully!";
|
||||||
|
echo "Margin Coin: " . $account['marginCoin'];
|
||||||
|
echo "Available: " . $account['available'];
|
||||||
|
echo "Frozen: " . $account['frozen'];
|
||||||
|
echo "Margin: " . $account['margin'];
|
||||||
|
echo "Transfer: " . $account['transfer'];
|
||||||
|
echo "Position Mode: " . $account['positionMode'];
|
||||||
|
echo "Cross Unrealized PnL: " . $account['crossUnrealizedPNL'];
|
||||||
|
echo "Isolation Unrealized PnL: " . $account['isolationUnrealizedPNL'];
|
||||||
|
echo "Bonus: " . $account['bonus'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Get Future Kline Data
|
### Get Future Kline Data
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
|
@ -179,6 +205,7 @@ if ($response->getStatusCode() === 200) {
|
||||||
|
|
||||||
- `changeLeverage(string $symbol, string $marginCoin, int $leverage)` - Change leverage
|
- `changeLeverage(string $symbol, string $marginCoin, int $leverage)` - Change leverage
|
||||||
- `changeMarginMode(string $symbol, string $marginCoin, string $marginMode)` - Change margin mode
|
- `changeMarginMode(string $symbol, string $marginCoin, string $marginMode)` - Change margin mode
|
||||||
|
- `getSingleAccount(string $marginCoin)` - Get account details for specific margin coin
|
||||||
|
|
||||||
### Trading
|
### Trading
|
||||||
|
|
||||||
|
|
@ -206,6 +233,7 @@ if ($response->getStatusCode() === 200) {
|
||||||
|
|
||||||
- **Change Leverage**: 10 req/sec/uid
|
- **Change Leverage**: 10 req/sec/uid
|
||||||
- **Change Margin Mode**: 10 req/sec/uid
|
- **Change Margin Mode**: 10 req/sec/uid
|
||||||
|
- **Get Single Account**: 10 req/sec/uid
|
||||||
- **Place Order**: 10 req/sec/uid
|
- **Place Order**: 10 req/sec/uid
|
||||||
- **Flash Close Position**: 5 req/sec/uid
|
- **Flash Close Position**: 5 req/sec/uid
|
||||||
- **Get Pending Positions**: 10 req/sec/uid
|
- **Get Pending Positions**: 10 req/sec/uid
|
||||||
|
|
@ -246,6 +274,7 @@ Run specific tests:
|
||||||
```bash
|
```bash
|
||||||
vendor/bin/pest tests/ChangeLeverageTest.php
|
vendor/bin/pest tests/ChangeLeverageTest.php
|
||||||
vendor/bin/pest tests/ChangeMarginModeTest.php
|
vendor/bin/pest tests/ChangeMarginModeTest.php
|
||||||
|
vendor/bin/pest tests/GetSingleAccountTest.php
|
||||||
vendor/bin/pest tests/PlaceOrderTest.php
|
vendor/bin/pest tests/PlaceOrderTest.php
|
||||||
vendor/bin/pest tests/FlashClosePositionTest.php
|
vendor/bin/pest tests/FlashClosePositionTest.php
|
||||||
vendor/bin/pest tests/GetPendingPositionsTest.php
|
vendor/bin/pest tests/GetPendingPositionsTest.php
|
||||||
|
|
@ -258,6 +287,7 @@ See the `examples/` directory for complete usage examples:
|
||||||
|
|
||||||
- `ChangeLeverageExample.php`
|
- `ChangeLeverageExample.php`
|
||||||
- `ChangeMarginModeExample.php`
|
- `ChangeMarginModeExample.php`
|
||||||
|
- `GetSingleAccountExample.php`
|
||||||
- `PlaceOrderExample.php`
|
- `PlaceOrderExample.php`
|
||||||
- `FlashClosePositionExample.php`
|
- `FlashClosePositionExample.php`
|
||||||
- `GetPendingPositionsExample.php`
|
- `GetPendingPositionsExample.php`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example usage of Get Single Account functionality
|
||||||
|
*
|
||||||
|
* This example demonstrates how to use the LaravelBitunixApi package
|
||||||
|
* to get account details from Bitunix exchange.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use Msr\LaravelBitunixApi\Requests\GetSingleAccountRequestContract;
|
||||||
|
|
||||||
|
// Example configuration (in real usage, these would be in your .env file)
|
||||||
|
config([
|
||||||
|
'bitunix-api.future_base_uri' => 'https://fapi.bitunix.com/',
|
||||||
|
'bitunix-api.api_key' => 'your-api-key-here',
|
||||||
|
'bitunix-api.api_secret' => 'your-api-secret-here',
|
||||||
|
'bitunix-api.language' => 'en-US',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the API instance
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
echo "💰 Get Single Account Examples\n\n";
|
||||||
|
|
||||||
|
// Example 1: Get USDT account details
|
||||||
|
echo "1. Getting USDT account details...\n";
|
||||||
|
$response = $api->getSingleAccount('USDT');
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "✅ USDT account details retrieved successfully!\n";
|
||||||
|
|
||||||
|
$account = $data['data'][0];
|
||||||
|
echo "Account Details:\n";
|
||||||
|
echo " Margin Coin: " . $account['marginCoin'] . "\n";
|
||||||
|
echo " Available: " . $account['available'] . "\n";
|
||||||
|
echo " Frozen: " . $account['frozen'] . "\n";
|
||||||
|
echo " Margin: " . $account['margin'] . "\n";
|
||||||
|
echo " Transfer: " . $account['transfer'] . "\n";
|
||||||
|
echo " Position Mode: " . $account['positionMode'] . "\n";
|
||||||
|
echo " Cross Unrealized PnL: " . $account['crossUnrealizedPNL'] . "\n";
|
||||||
|
echo " Isolation Unrealized PnL: " . $account['isolationUnrealizedPNL'] . "\n";
|
||||||
|
echo " Bonus: " . $account['bonus'] . "\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ API Error: " . $data['msg'] . "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
// Example 2: Get BTC account details
|
||||||
|
echo "2. Getting BTC account details...\n";
|
||||||
|
$response = $api->getSingleAccount('BTC');
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "✅ BTC account details retrieved successfully!\n";
|
||||||
|
|
||||||
|
$account = $data['data'][0];
|
||||||
|
echo "Account Details:\n";
|
||||||
|
echo " Margin Coin: " . $account['marginCoin'] . "\n";
|
||||||
|
echo " Available: " . $account['available'] . "\n";
|
||||||
|
echo " Frozen: " . $account['frozen'] . "\n";
|
||||||
|
echo " Margin: " . $account['margin'] . "\n";
|
||||||
|
echo " Transfer: " . $account['transfer'] . "\n";
|
||||||
|
echo " Position Mode: " . $account['positionMode'] . "\n";
|
||||||
|
echo " Cross Unrealized PnL: " . $account['crossUnrealizedPNL'] . "\n";
|
||||||
|
echo " Isolation Unrealized PnL: " . $account['isolationUnrealizedPNL'] . "\n";
|
||||||
|
echo " Bonus: " . $account['bonus'] . "\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ API Error: " . $data['msg'] . "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
// Example 3: Get multiple account details
|
||||||
|
echo "3. Getting multiple account details...\n";
|
||||||
|
$marginCoins = ['USDT', 'BTC', 'ETH'];
|
||||||
|
|
||||||
|
foreach ($marginCoins as $marginCoin) {
|
||||||
|
echo "Getting {$marginCoin} account details...\n";
|
||||||
|
|
||||||
|
$response = $api->getSingleAccount($marginCoin);
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
$account = $data['data'][0];
|
||||||
|
echo "✅ {$marginCoin} account: Available={$account['available']}, Frozen={$account['frozen']}, Margin={$account['margin']}\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ Failed to get {$marginCoin} account: " . $data['msg'] . "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error for {$marginCoin}: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
// Example 4: Error handling
|
||||||
|
echo "4. Error handling example...\n";
|
||||||
|
$invalidMarginCoin = 'INVALID';
|
||||||
|
|
||||||
|
$response = $api->getSingleAccount($invalidMarginCoin);
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "✅ Account details retrieved successfully!\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ API Error: " . $data['msg'] . "\n";
|
||||||
|
echo "This is expected for invalid margin coin\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo '❌ Exception: '.$e->getMessage()."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Single Account Features:
|
||||||
|
*
|
||||||
|
* - Get account details for specific margin coin
|
||||||
|
* - Rate limit: 10 req/sec/uid
|
||||||
|
* - Returns comprehensive account information
|
||||||
|
* - Supports multiple margin coins
|
||||||
|
*
|
||||||
|
* Response includes:
|
||||||
|
* - marginCoin: Margin Coin
|
||||||
|
* - available: Available quantity in the account
|
||||||
|
* - frozen: Locked quantity of orders
|
||||||
|
* - margin: Locked quantity of positions
|
||||||
|
* - transfer: Maximum transferable amount
|
||||||
|
* - positionMode: Position mode (ONE_WAY or HEDGE)
|
||||||
|
* - crossUnrealizedPNL: Unrealized PnL for cross positions
|
||||||
|
* - isolationUnrealizedPNL: Unrealized PnL for isolation positions
|
||||||
|
* - bonus: Futures Bonus
|
||||||
|
*
|
||||||
|
* Environment Variables Required:
|
||||||
|
*
|
||||||
|
* BITUNIX_API_KEY=your-api-key
|
||||||
|
* BITUNIX_API_SECRET=your-api-secret
|
||||||
|
* BITUNIX_LANGUAGE=en-US
|
||||||
|
*/
|
||||||
|
|
@ -8,11 +8,12 @@ use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\GetPendingPositionsRequestContract;
|
use Msr\LaravelBitunixApi\Requests\GetPendingPositionsRequestContract;
|
||||||
|
use Msr\LaravelBitunixApi\Requests\GetSingleAccountRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\Header;
|
use Msr\LaravelBitunixApi\Requests\Header;
|
||||||
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginModeRequestContract, FlashClosePositionRequestContract, FutureKLineRequestContract, GetPendingPositionsRequestContract, PlaceOrderRequestContract
|
class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginModeRequestContract, FlashClosePositionRequestContract, FutureKLineRequestContract, GetPendingPositionsRequestContract, GetSingleAccountRequestContract, PlaceOrderRequestContract
|
||||||
{
|
{
|
||||||
private Client $publicFutureClient;
|
private Client $publicFutureClient;
|
||||||
|
|
||||||
|
|
@ -187,4 +188,17 @@ class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginMo
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSingleAccount(string $marginCoin): ResponseInterface
|
||||||
|
{
|
||||||
|
$queryParams = [
|
||||||
|
'marginCoin' => $marginCoin,
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->getPrivateFutureClient($queryParams, [])->get('account', [
|
||||||
|
'query' => $queryParams,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\GetPendingPositionsRequestContract;
|
use Msr\LaravelBitunixApi\Requests\GetPendingPositionsRequestContract;
|
||||||
|
use Msr\LaravelBitunixApi\Requests\GetSingleAccountRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
||||||
use Spatie\LaravelPackageTools\Package;
|
use Spatie\LaravelPackageTools\Package;
|
||||||
use Spatie\LaravelPackageTools\PackageServiceProvider;
|
use Spatie\LaravelPackageTools\PackageServiceProvider;
|
||||||
|
|
@ -39,5 +40,6 @@ class LaravelBitunixApiServiceProvider extends PackageServiceProvider
|
||||||
$this->app->bind(PlaceOrderRequestContract::class, LaravelBitunixApi::class);
|
$this->app->bind(PlaceOrderRequestContract::class, LaravelBitunixApi::class);
|
||||||
$this->app->bind(FlashClosePositionRequestContract::class, LaravelBitunixApi::class);
|
$this->app->bind(FlashClosePositionRequestContract::class, LaravelBitunixApi::class);
|
||||||
$this->app->bind(GetPendingPositionsRequestContract::class, LaravelBitunixApi::class);
|
$this->app->bind(GetPendingPositionsRequestContract::class, LaravelBitunixApi::class);
|
||||||
|
$this->app->bind(GetSingleAccountRequestContract::class, LaravelBitunixApi::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Msr\LaravelBitunixApi\Requests;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
|
interface GetSingleAccountRequestContract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get account details with the given margin coin
|
||||||
|
*
|
||||||
|
* @param string $marginCoin Margin coin (e.g., 'USDT')
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function getSingleAccount(string $marginCoin): ResponseInterface;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Msr\LaravelBitunixApi\Requests\GetSingleAccountRequestContract;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
config([
|
||||||
|
'bitunix-api.future_base_uri' => 'https://fapi.bitunix.com/',
|
||||||
|
'bitunix-api.api_key' => 'test-api-key',
|
||||||
|
'bitunix-api.api_secret' => 'test-secret-key',
|
||||||
|
'bitunix-api.language' => 'en-US',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get single account successfully', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates required margin coin parameter', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
// Test with valid margin coin
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
|
||||||
|
// Test with different margin coins
|
||||||
|
expect(fn() => $api->getSingleAccount('BTC'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle different margin coins', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
$marginCoins = ['USDT', 'BTC', 'ETH', 'BNB', 'ADA'];
|
||||||
|
|
||||||
|
foreach ($marginCoins as $marginCoin) {
|
||||||
|
expect(fn() => $api->getSingleAccount($marginCoin))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates get single account method exists', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
expect(method_exists($api, 'getSingleAccount'))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle edge cases for margin coin', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
// Test with uppercase margin coin
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
|
||||||
|
// Test with lowercase margin coin
|
||||||
|
expect(fn() => $api->getSingleAccount('usdt'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates get single account response structure', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
// This test verifies the method can be called without throwing exceptions
|
||||||
|
// The actual response structure will be validated by the API
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle multiple get single account calls', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
$marginCoins = ['USDT', 'BTC', 'ETH'];
|
||||||
|
|
||||||
|
foreach ($marginCoins as $marginCoin) {
|
||||||
|
expect(fn() => $api->getSingleAccount($marginCoin))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates margin coin parameter type', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
// Test with string margin coin
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
|
||||||
|
// Test with different string formats
|
||||||
|
expect(fn() => $api->getSingleAccount('BTC'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle special characters in margin coin', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
// Test with margin coin containing special characters
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
|
||||||
|
// Test with margin coin containing numbers
|
||||||
|
expect(fn() => $api->getSingleAccount('USDT'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates get single account with empty string', function () {
|
||||||
|
$api = app(GetSingleAccountRequestContract::class);
|
||||||
|
|
||||||
|
// This should not throw an exception at the method level
|
||||||
|
// The API will handle validation
|
||||||
|
expect(fn() => $api->getSingleAccount(''))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue