future-private: add change margin mode request
This commit is contained in:
parent
ccebbf8f70
commit
d561f69ece
190
README.md
190
README.md
|
|
@ -1,84 +1,184 @@
|
|||
# composer package for using bitunix api trading
|
||||
# Laravel Bitunix API Package
|
||||
|
||||
[](https://packagist.org/packages/mahdimsr/laravel-bitunix-api)
|
||||
[](https://github.com/mahdimsr/laravel-bitunix-api/actions?query=workflow%3Arun-tests+branch%3Amain)
|
||||
[](https://github.com/mahdimsr/laravel-bitunix-api/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain)
|
||||
[](https://packagist.org/packages/mahdimsr/laravel-bitunix-api)
|
||||
|
||||
This is where your description should go. Limit it to a paragraph or two. Consider adding a small example.
|
||||
|
||||
## Support us
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/laravel-bitunix-api.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/laravel-bitunix-api)
|
||||
|
||||
We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).
|
||||
|
||||
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).
|
||||
A Laravel package for interacting with the Bitunix cryptocurrency exchange API.
|
||||
|
||||
## Installation
|
||||
|
||||
You can install the package via composer:
|
||||
|
||||
```bash
|
||||
composer require mahdimsr/laravel-bitunix-api
|
||||
composer require msr/laravel-bitunix-api
|
||||
```
|
||||
|
||||
You can publish and run the migrations with:
|
||||
## Configuration
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag="laravel-bitunix-api-migrations"
|
||||
php artisan migrate
|
||||
### 1. Environment Variables
|
||||
|
||||
Add the following variables to your `.env` file:
|
||||
|
||||
```env
|
||||
BITUNIX_API_KEY=your-api-key-here
|
||||
BITUNIX_API_SECRET=your-api-secret-here
|
||||
BITUNIX_LANGUAGE=en-US
|
||||
```
|
||||
|
||||
You can publish the config file with:
|
||||
### 2. Publish Configuration (Optional)
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag="laravel-bitunix-api-config"
|
||||
php artisan vendor:publish --tag=bitunix-api-config
|
||||
```
|
||||
|
||||
This is the contents of the published config file:
|
||||
### 3. Verify Configuration
|
||||
|
||||
```php
|
||||
return [
|
||||
];
|
||||
```
|
||||
|
||||
Optionally, you can publish the views using
|
||||
Run the configuration check script:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag="laravel-bitunix-api-views"
|
||||
php scripts/check-config.php
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Change Leverage
|
||||
|
||||
```php
|
||||
$laravelBitunixApi = new Msr\LaravelBitunixApi();
|
||||
echo $laravelBitunixApi->echoPhrase('Hello, Msr!');
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
||||
|
||||
$api = app(ChangeLeverageRequestContract::class);
|
||||
$response = $api->changeLeverage('BTCUSDT', 'USDT', 12);
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$data = json_decode($response->getBody()->getContents(), true);
|
||||
if ($data['code'] === 0) {
|
||||
echo "Leverage changed successfully!";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Change Margin Mode
|
||||
|
||||
```php
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
$response = $api->changeMarginMode('BTCUSDT', 'USDT', 'ISOLATION');
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$data = json_decode($response->getBody()->getContents(), true);
|
||||
if ($data['code'] === 0) {
|
||||
echo "Margin mode changed successfully!";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Future Kline Data
|
||||
|
||||
```php
|
||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||
|
||||
$api = app(FutureKLineRequestContract::class);
|
||||
$response = $api->getFutureKline('BTCUSDT', '1h', 100);
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$data = json_decode($response->getBody()->getContents(), true);
|
||||
// Process kline data
|
||||
}
|
||||
```
|
||||
|
||||
## API Methods
|
||||
|
||||
### Account Management
|
||||
|
||||
- `changeLeverage(string $symbol, string $marginCoin, int $leverage)` - Change leverage
|
||||
- `changeMarginMode(string $symbol, string $marginCoin, string $marginMode)` - Change margin mode
|
||||
|
||||
### Market Data
|
||||
|
||||
- `getFutureKline(string $symbol, string $interval, int $limit, ?int $startTime, ?int $endTime, string $type)` - Get kline data
|
||||
|
||||
## Configuration Options
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `future_base_uri` | Bitunix API base URI | `https://fapi.bitunix.com/` |
|
||||
| `api_key` | Your API key | From `BITUNIX_API_KEY` env var |
|
||||
| `api_secret` | Your API secret | From `BITUNIX_API_SECRET` env var |
|
||||
| `language` | API language | From `BITUNIX_LANGUAGE` env var or `en-US` |
|
||||
|
||||
## Rate Limits
|
||||
|
||||
- **Change Leverage**: 10 req/sec/uid
|
||||
- **Change Margin Mode**: 10 req/sec/uid
|
||||
|
||||
## Error Handling
|
||||
|
||||
All methods return a `ResponseInterface` object. Check the response status and parse the JSON response:
|
||||
|
||||
```php
|
||||
$response = $api->changeLeverage('BTCUSDT', 'USDT', 12);
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$data = json_decode($response->getBody()->getContents(), true);
|
||||
|
||||
if ($data['code'] === 0) {
|
||||
// Success
|
||||
echo "Operation successful: " . $data['msg'];
|
||||
} else {
|
||||
// API Error
|
||||
echo "API Error: " . $data['msg'];
|
||||
}
|
||||
} else {
|
||||
// HTTP Error
|
||||
echo "HTTP Error: " . $response->getStatusCode();
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run the test suite:
|
||||
|
||||
```bash
|
||||
composer test
|
||||
vendor/bin/pest
|
||||
```
|
||||
|
||||
## Changelog
|
||||
Run specific tests:
|
||||
|
||||
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
|
||||
```bash
|
||||
vendor/bin/pest tests/ChangeLeverageTest.php
|
||||
vendor/bin/pest tests/ChangeMarginModeTest.php
|
||||
vendor/bin/pest tests/HeaderTest.php
|
||||
```
|
||||
|
||||
## Contributing
|
||||
## Examples
|
||||
|
||||
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
|
||||
See the `examples/` directory for complete usage examples:
|
||||
|
||||
## Security Vulnerabilities
|
||||
- `ChangeLeverageExample.php`
|
||||
- `ChangeMarginModeExample.php`
|
||||
|
||||
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
|
||||
## Troubleshooting
|
||||
|
||||
## Credits
|
||||
### API credentials not loading from .env
|
||||
|
||||
- [mahdi mansouri](https://github.com/mahdimsr)
|
||||
- [All Contributors](../../contributors)
|
||||
1. Make sure your `.env` file is in the project root
|
||||
2. Check that the variable names match exactly (case-sensitive)
|
||||
3. Restart your application/server after changing .env
|
||||
4. Clear config cache: `php artisan config:clear`
|
||||
|
||||
### Signature generation fails
|
||||
|
||||
1. Verify API key and secret are correct
|
||||
2. Check that the credentials have the necessary permissions
|
||||
3. Ensure your system time is synchronized
|
||||
|
||||
## Security
|
||||
|
||||
- Never commit API credentials to version control
|
||||
- Use environment variables for all sensitive data
|
||||
- Restrict API key permissions to minimum required
|
||||
- Regularly rotate API keys
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
||||
MIT License. See LICENSE file for details.
|
||||
|
||||
## Support
|
||||
|
||||
For issues and questions, please create an issue on the GitHub repository.
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Example usage of Change Margin Mode functionality
|
||||
*
|
||||
* This example demonstrates how to use the LaravelBitunixApi package
|
||||
* to change margin mode for a trading pair on Bitunix exchange.
|
||||
*/
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||
|
||||
// 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(ChangeMarginModeRequestContract::class);
|
||||
|
||||
// Change margin mode for BTCUSDT pair
|
||||
$symbol = 'BTCUSDT';
|
||||
$marginCoin = 'USDT';
|
||||
$marginMode = 'ISOLATION'; // or 'CROSS'
|
||||
|
||||
echo "Changing margin mode for {$symbol} to {$marginMode}...\n";
|
||||
|
||||
$response = $api->changeMarginMode($symbol, $marginCoin, $marginMode);
|
||||
|
||||
// Check response status
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$data = json_decode($response->getBody()->getContents(), true);
|
||||
|
||||
if ($data['code'] === 0) {
|
||||
echo "✅ Margin mode changed successfully!\n";
|
||||
echo 'Symbol: '.$data['data'][0]['symbol']."\n";
|
||||
echo 'Margin Coin: '.$data['data'][0]['marginCoin']."\n";
|
||||
echo 'Margin Mode: '.$data['data'][0]['marginMode']."\n";
|
||||
} else {
|
||||
echo '❌ API Error: '.$data['msg']."\n";
|
||||
}
|
||||
} else {
|
||||
echo '❌ HTTP Error: '.$response->getStatusCode()."\n";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo '❌ Exception: '.$e->getMessage()."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Available Margin Modes:
|
||||
* - ISOLATION: Isolated margin mode
|
||||
* - CROSS: Cross margin mode
|
||||
*
|
||||
* Environment Variables Required:
|
||||
*
|
||||
* BITUNIX_API_KEY=your-api-key
|
||||
* BITUNIX_API_SECRET=your-api-secret
|
||||
* BITUNIX_LANGUAGE=en-US
|
||||
*/
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Configuration Check Script
|
||||
*
|
||||
* This script helps you verify that your Bitunix API configuration is working correctly.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Msr\LaravelBitunixApi\Requests\Header;
|
||||
|
||||
echo "🔍 Checking Bitunix API Configuration...\n\n";
|
||||
|
||||
// Check if .env file exists
|
||||
$envFile = __DIR__ . '/../.env';
|
||||
if (!file_exists($envFile)) {
|
||||
echo "❌ .env file not found. Please create one based on .env.example\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Load environment variables
|
||||
if (file_exists($envFile)) {
|
||||
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, '=') !== false && strpos($line, '#') !== 0) {
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
putenv(trim($key) . '=' . trim($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check environment variables
|
||||
$apiKey = getenv('BITUNIX_API_KEY');
|
||||
$apiSecret = getenv('BITUNIX_API_SECRET');
|
||||
$language = getenv('BITUNIX_LANGUAGE') ?: 'en-US';
|
||||
|
||||
echo "📋 Environment Variables:\n";
|
||||
echo " BITUNIX_API_KEY: " . (empty($apiKey) ? "❌ Not set" : "✅ Set (" . substr($apiKey, 0, 8) . "...)") . "\n";
|
||||
echo " BITUNIX_API_SECRET: " . (empty($apiSecret) ? "❌ Not set" : "✅ Set (" . substr($apiSecret, 0, 8) . "...)") . "\n";
|
||||
echo " BITUNIX_LANGUAGE: " . ($language) . "\n\n";
|
||||
|
||||
if (empty($apiKey) || empty($apiSecret)) {
|
||||
echo "❌ API credentials not configured properly.\n";
|
||||
echo "Please set BITUNIX_API_KEY and BITUNIX_API_SECRET in your .env file.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Test configuration loading
|
||||
config([
|
||||
'bitunix-api.future_base_uri' => 'https://fapi.bitunix.com/',
|
||||
'bitunix-api.api_key' => $apiKey,
|
||||
'bitunix-api.api_secret' => $apiSecret,
|
||||
'bitunix-api.language' => $language,
|
||||
]);
|
||||
|
||||
echo "🔧 Configuration Test:\n";
|
||||
echo " Base URI: " . config('bitunix-api.future_base_uri') . "\n";
|
||||
echo " API Key: " . substr(config('bitunix-api.api_key'), 0, 8) . "...\n";
|
||||
echo " API Secret: " . substr(config('bitunix-api.api_secret'), 0, 8) . "...\n";
|
||||
echo " Language: " . config('bitunix-api.language') . "\n\n";
|
||||
|
||||
// Test header generation
|
||||
try {
|
||||
echo "🔐 Testing Header Generation:\n";
|
||||
$headers = Header::generateHeaders([], '{"test":"value"}');
|
||||
|
||||
echo " API Key: " . $headers['api-key'] . "\n";
|
||||
echo " Sign: " . substr($headers['sign'], 0, 16) . "...\n";
|
||||
echo " Nonce: " . $headers['nonce'] . "\n";
|
||||
echo " Timestamp: " . $headers['timestamp'] . "\n";
|
||||
echo " Language: " . $headers['language'] . "\n";
|
||||
echo " Content-Type: " . $headers['Content-Type'] . "\n\n";
|
||||
|
||||
echo "✅ Configuration is working correctly!\n";
|
||||
echo "You can now use the Bitunix API package in your application.\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "❌ Error generating headers: " . $e->getMessage() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -4,11 +4,12 @@ namespace Msr\LaravelBitunixApi;
|
|||
|
||||
use GuzzleHttp\Client;
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||
use Msr\LaravelBitunixApi\Requests\Header;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class LaravelBitunixApi implements ChangeLeverageRequestContract, FutureKLineRequestContract
|
||||
class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginModeRequestContract, FutureKLineRequestContract
|
||||
{
|
||||
private Client $publicFutureClient;
|
||||
|
||||
|
|
@ -60,4 +61,19 @@ class LaravelBitunixApi implements ChangeLeverageRequestContract, FutureKLineReq
|
|||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function changeMarginMode(string $symbol, string $marginCoin, string $marginMode): ResponseInterface
|
||||
{
|
||||
$body = [
|
||||
'symbol' => $symbol,
|
||||
'marginCoin' => $marginCoin,
|
||||
'marginMode' => $marginMode,
|
||||
];
|
||||
|
||||
$response = $this->getPrivateFutureClient([], $body)->post('account/change_margin_mode', [
|
||||
'json' => $body,
|
||||
]);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Msr\LaravelBitunixApi;
|
|||
|
||||
use Msr\LaravelBitunixApi\Commands\LaravelBitunixApiCommand;
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||
use Spatie\LaravelPackageTools\Package;
|
||||
use Spatie\LaravelPackageTools\PackageServiceProvider;
|
||||
|
|
@ -31,5 +32,6 @@ class LaravelBitunixApiServiceProvider extends PackageServiceProvider
|
|||
|
||||
$this->app->bind(FutureKLineRequestContract::class, LaravelBitunixApi::class);
|
||||
$this->app->bind(ChangeLeverageRequestContract::class, LaravelBitunixApi::class);
|
||||
$this->app->bind(ChangeMarginModeRequestContract::class, LaravelBitunixApi::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Msr\LaravelBitunixApi\Requests;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface ChangeMarginModeRequestContract
|
||||
{
|
||||
/**
|
||||
* Change margin mode for a trading pair
|
||||
*
|
||||
* @param string $symbol Trading pair (e.g., 'BTCUSDT')
|
||||
* @param string $marginCoin Margin coin (e.g., 'USDT')
|
||||
* @param string $marginMode Margin mode ('ISOLATION' or 'CROSS')
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function changeMarginMode(string $symbol, string $marginCoin, string $marginMode): ResponseInterface;
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||
|
||||
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 change margin mode successfully', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
expect(fn() => $api->changeMarginMode('BTCUSDT', 'USDT', 'ISOLATION'))
|
||||
->not->toThrow(Exception::class)
|
||||
->and(fn() => $api->changeMarginMode('BTCUSDT', 'USDT', 'CROSS'))
|
||||
->not->toThrow(Exception::class);
|
||||
|
||||
});
|
||||
|
||||
it('validates required parameters for change margin mode', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
expect(fn() => $api->changeMarginMode('BTCUSDT', 'USDT', 'ISOLATION'))
|
||||
->not->toThrow(Exception::class)
|
||||
->and(fn() => $api->changeMarginMode('ETHUSDT', 'USDT', 'CROSS'))
|
||||
->not->toThrow(Exception::class);
|
||||
|
||||
});
|
||||
|
||||
it('handles different margin modes correctly', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
$marginModes = ['ISOLATION', 'CROSS'];
|
||||
|
||||
foreach ($marginModes as $mode) {
|
||||
expect(fn () => $api->changeMarginMode('BTCUSDT', 'USDT', $mode))
|
||||
->not->toThrow(Exception::class);
|
||||
}
|
||||
});
|
||||
|
||||
it('validates margin mode parameter values', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
expect(fn() => $api->changeMarginMode('BTCUSDT', 'USDT', 'ISOLATION'))
|
||||
->not->toThrow(Exception::class)
|
||||
->and(fn() => $api->changeMarginMode('BTCUSDT', 'USDT', 'CROSS'))
|
||||
->not->toThrow(Exception::class);
|
||||
|
||||
});
|
||||
|
||||
it('can handle different trading pairs', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
$tradingPairs = ['BTCUSDT', 'ETHUSDT', 'ADAUSDT'];
|
||||
|
||||
foreach ($tradingPairs as $symbol) {
|
||||
expect(fn () => $api->changeMarginMode($symbol, 'USDT', 'ISOLATION'))
|
||||
->not->toThrow(Exception::class);
|
||||
}
|
||||
});
|
||||
|
||||
it('can handle different margin coins', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
$marginCoins = ['USDT', 'BTC', 'ETH'];
|
||||
|
||||
foreach ($marginCoins as $coin) {
|
||||
expect(fn () => $api->changeMarginMode('BTCUSDT', $coin, 'ISOLATION'))
|
||||
->not->toThrow(Exception::class);
|
||||
}
|
||||
});
|
||||
|
||||
it('validates margin mode constants', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
$validModes = ['ISOLATION', 'CROSS'];
|
||||
|
||||
foreach ($validModes as $mode) {
|
||||
expect(fn () => $api->changeMarginMode('BTCUSDT', 'USDT', $mode))
|
||||
->not->toThrow(Exception::class);
|
||||
}
|
||||
});
|
||||
|
||||
it('handles edge cases for margin mode', function () {
|
||||
$api = app(ChangeMarginModeRequestContract::class);
|
||||
|
||||
expect(fn() => $api->changeMarginMode('BTCUSDT', 'USDT', 'ISOLATION'))
|
||||
->not->toThrow(Exception::class)
|
||||
->and(fn() => $api->changeMarginMode('ETHUSDT', 'USDT', 'CROSS'))
|
||||
->not->toThrow(Exception::class);
|
||||
|
||||
});
|
||||
Loading…
Reference in New Issue