Skip to content

WebSocket API Usage

Igor Sazonov edited this page Jul 12, 2026 · 1 revision

Alongside the REST client, coinglass-php includes a built-in client for Coinglass's real-time WebSocket streams. This allows you to receive live liquidation orders, spot and futures trades, and futures ticker snapshots. The implementation is built directly on top of PHP's stream_socket_client(), so no extra Composer dependency is required — only the ext-openssl extension for secure wss:// connections.

Establishing a Connection

The WebSocket client is accessed via the websocket() method on the main CoinGlassClient. Calling connect() performs the RFC 6455 handshake with the Coinglass server and returns a CoinGlassStream object representing the live connection.

use Tigusigalpa\CoinGlass\CoinGlassClient;

$client = CoinGlassClient::make('YOUR_API_KEY');
$stream = $client->websocket()->connect();

In Laravel, you can use the facade:

use Tigusigalpa\CoinGlass\Laravel\Facades\CoinGlass;

$stream = CoinGlass::websocket()->connect();

Subscribing to Channels

A single connection multiplexes all subscriptions. You use the Channels helper class to generate the correct channel name strings, then pass them to $stream->subscribe().

use Tigusigalpa\CoinGlass\WebSocket\Channels;

$stream->subscribe(
    Channels::liquidationOrders(),
    Channels::futuresTicker('Binance', 'BTCUSDT'),
    Channels::spotTrades('Binance', 'BTCUSDT', 10000)
);

The table below lists all available channel helpers.

Helper Method Channel Format Description
Channels::liquidationOrders() liquidation_orders Real-time liquidation orders across all exchanges.
Channels::spotTrades($exchange, $symbol, $minVolumeUsd) spot_trades@{exchange}_{symbol}@{minVolumeUsd} Spot trades for a given exchange and symbol, filtered by minimum USD volume.
Channels::futuresTrades($exchange, $symbol, $minVolumeUsd) futures_trades@{exchange}_{symbol}@{minVolumeUsd} Futures trades for a given exchange and symbol, filtered by minimum USD volume.
Channels::futuresTicker($exchange, $symbol) futures_ticker@{exchange}_{symbol} Periodic ticker snapshots for a futures pair on a given exchange.

You can unsubscribe from channels at any time without closing the connection:

$stream->unsubscribe(Channels::futuresTicker('Binance', 'BTCUSDT'));

To inspect the currently active subscriptions, call $stream->subscriptions(), which returns a list of channel name strings.

Listening for Messages

The CoinGlassStream provides two modes for consuming messages: a blocking listen loop for long-running workers, and a manual read method for integration with existing event loops.

Blocking Listen Loop

The listen() method blocks indefinitely, calling your callback for every incoming message. It is the recommended approach for CLI workers or queued jobs. The SDK automatically sends the "ping" heartbeat that Coinglass expects every 20 seconds.

use Tigusigalpa\CoinGlass\WebSocket\Message;

$stream->listen(function (Message $message) {
    if ($message->channel === Channels::liquidationOrders()) {
        foreach ($message->collection() as $order) {
            echo "{$order->exchange} {$order->symbol} liquidated \${$order->volume_usd}\n";
        }
    }
});

You can also pass an optional error handler as the second argument. If provided, WebSocketException instances are passed to it instead of being rethrown, allowing the loop to continue:

use Tigusigalpa\CoinGlass\Exceptions\WebSocketException;

$stream->listen(
    onMessage: function (Message $message) { /* ... */ },
    onError: function (WebSocketException $e) {
        error_log("Stream error: " . $e->getMessage());
    }
);

Manual Reading

For finer control — for example, integrating the stream into a ReactPHP or Amp event loop — call $stream->read($timeoutSeconds) directly. It blocks for up to the specified number of seconds and returns either a Message object or null if no message arrived within the timeout. Ping/pong frames and connection close frames are handled transparently and never returned to the caller.

while (true) {
    $message = $stream->read(5.0);

    if ($message !== null) {
        // Process the message
    }

    // Perform other work in your loop
}

Working with Messages

Every incoming message is represented by a Tigusigalpa\CoinGlass\WebSocket\Message object. It exposes two public properties: $message->channel (the channel name string) and $message->data (the raw decoded array payload).

The collection() method hydrates the data payload into a CoinGlassCollection of CoinGlassDto records, using the same mechanism as the REST client. This means you can access fields using property syntax, array syntax, or the get() method.

$collection = $message->collection();

foreach ($collection as $record) {
    $exchange = $record->exchange;
    $symbol   = $record->symbol;
    $volume   = $record->get('volume_usd', 0);
}

Closing the Connection

When you are done streaming, call $stream->close() to send a WebSocket close frame and release the underlying socket. This method is safe to call multiple times.

$stream->close();

Error Handling

All connection, handshake, and read/write failures throw a Tigusigalpa\CoinGlass\Exceptions\WebSocketException. This class extends the base CoinGlassException, so it is caught by any existing catch (CoinGlassException $e) block you may already have.

use Tigusigalpa\CoinGlass\Exceptions\WebSocketException;

try {
    $stream = $client->websocket()->connect();
    $stream->subscribe(Channels::liquidationOrders());
    $stream->listen(function (Message $message) { /* ... */ });
} catch (WebSocketException $e) {
    echo "WebSocket error: " . $e->getMessage();
}

WebSocket Configuration

The WebSocket client has its own configuration object, CoinGlassWebSocketConfig, with the following parameters.

Parameter Environment Variable Default Description
apiKey COINGLASS_API_KEY (required) Sent as the cg-api-key query parameter during the handshake.
baseUrl COINGLASS_WS_BASE_URL wss://open-ws.coinglass.com/ws-api The WebSocket endpoint URL.
connectTimeout COINGLASS_WS_CONNECT_TIMEOUT 10.0 TCP/TLS connection and handshake timeout in seconds.
pingInterval COINGLASS_WS_PING_INTERVAL 20.0 How often the SDK sends the application-level "ping" heartbeat.

In a standalone application, pass overrides as an array to $client->websocket():

$stream = $client->websocket([
    'connect_timeout' => 30.0,
    'ping_interval'   => 15.0,
])->connect();

In Laravel, publish the configuration file and set the corresponding COINGLASS_WS_* environment variables, or edit the websocket block in config/coinglass.php directly.


Next: Responses and DTOs

Clone this wiki locally