baconfy/exchanges

Maintainers

Package info

github.com/baconfy/exchanges

pkg:composer/baconfy/exchanges

Transparency log

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.0 2026-07-31 17:31 UTC

This package is auto-updated.

Last update: 2026-07-31 20:41:18 UTC


README

Framework-agnostic Composer package for connecting to cryptocurrency exchanges. A single Exchange contract lets consumers fetch market data across multiple exchanges (Bybit, Binance, OKX, ...), where each exchange is an interchangeable driver — consumers program against the contract, never against a specific exchange.

v0 scope: klines() only (public candlestick data, no authentication). Balance, positions and orders come in later versions.

Requirements

  • PHP ^8.4
  • A PSR-18 HTTP client and a PSR-17 request factory (e.g. guzzlehttp/guzzle)

Installation

composer require baconfy/exchanges

The package requires only PSR interfaces — bring your own PSR-18/PSR-17 implementation:

composer require guzzlehttp/guzzle

Usage

use Baconfy\Exchanges\ExchangeManager;
use Baconfy\Exchanges\Enums\MarketType;
use Baconfy\Exchanges\Enums\Timeframe;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;

$manager = new ExchangeManager(new Client(), new HttpFactory());

$candles = $manager->make('bybit', MarketType::Perpetual)->klines('BTCUSDT', Timeframe::M5, 100);

foreach ($candles as $candle) {
    // oldest to newest, every OHLCV field is an exact Brick\Math\BigDecimal
    echo "{$candle->openTime->format('c')}: {$candle->close}\n";
}

Supported timeframes

Timeframe::M1, M5, M15, M30, H1, H4, D1, W1 — each driver translates these to its own dialect (e.g. Bybit's interval=240 for H4).

Error handling

Every failure the package throws implements Baconfy\Exchanges\Exceptions\ExchangeException, so you can catch broadly or narrowly:

use Baconfy\Exchanges\Exceptions\ApiException;
use Baconfy\Exchanges\Exceptions\ExchangeException;
use Baconfy\Exchanges\Exceptions\TransportException;

try {
    $manager->make('bybit', MarketType::Perpetual)->klines('BTCUSDT', Timeframe::M5);
} catch (ApiException $e) {
    // the exchange responded with an error: $e->retCode / $e->retMsg
} catch (TransportException $e) {
    // network failure, HTTP error status, or invalid JSON
} catch (ExchangeException $e) {
    // any other package failure (unknown driver, wrong credentials type, ...)
}

Registering another driver

$manager->register('binance', BinanceDriver::class);
$manager->available(); // ['bybit', 'binance']

Every driver constructor follows the same shape — (ClientInterface $http, RequestFactoryInterface $requests, MarketType $market, ?Credentials $credentials = null) — so ExchangeManager::make() can build any of them generically.

Laravel

The package ships an optional ExchangesServiceProvider, auto-discovered via Composer. It registers ExchangeManager as a container singleton, wired to whatever PSR-18/PSR-17 implementations your app has bound — it does not bind Exchange::class itself, since each connection may use a different driver and credentials:

$manager = app(\Baconfy\Exchanges\ExchangeManager::class);
$exchange = $manager->make($connection->driver, MarketType::Perpetual, $credentials);

illuminate/support is a suggest, never a hard dependency — the core works in a plain PHP script with no framework at all.

Testing

composer install
vendor/bin/pest

No test hits the network: HTTP is mocked at the PSR-18 boundary, and Bybit fixtures under tests/Fixtures/ are real API responses, versioned deliberately.

Architecture

Design decisions, invariants and the full build rationale live in .claude/ARCHITECTURE.md — the source of truth for this package.