webSocketExchange<T> method

  1. @protected
Future<JsonRpcResponse<T>> webSocketExchange<T>(
  1. Uri uri,
  2. JsonRpcRequest request, {
  3. JsonRpcRequestConfig? config,
})

Makes a JSON-RPC data request to the web socket server.

The request's timeout duration can be set using the config object's JsonRpcRequestConfig.timeout property.

All other configurations are ignored.

Implementation

@protected
Future<JsonRpcResponse<T>> webSocketExchange<T>(
  final Uri uri,
  final JsonRpcRequest request, {
  final JsonRpcRequestConfig? config,
}) async {

  // The subscription's request/response cycle.
  WebSocketExchange<T>? exchange;

  try {
    // Connect the web socket.
    await socket.connect(uri);

    // Get the existing request/response cycle (if it exists).
    exchange = webSocketExchangeManager.get(request.hash());

    // If an exchange created using the current connection exists, return the response (which may
    // still be pending).
    if (exchange != null) {
      final DateTime? connectedAt = socket.connectedAt;
      if (connectedAt == null) {
        throw const WebSocketException('[WebSocketConnection.connectedAt] is null.');
      }
      if (exchange.createdAt.isBefore(connectedAt)) {
        if (exchange.isCompleted) {
          await webSocketSubscriptionManager.close(exchangeId: exchange.id);
        } else {
          throw const WebSocketException('The exchange request expired.');
        }
      } else {
        return exchange.response;
      }
    }

    // Check that existing requests have an id and new requests do not.
    assert(
      exchange == null ? request.id == null : request.id == exchange.id,
      'A [WebSocketExchange] must be initialized with a new or existing exchange request.',
    );

    // Create a WebSocketExchange for the subscription's request/response cycle.
    exchange = WebSocketExchange<T>(request);

    // Store the exchange (request/response) to be used for future subscriptions or cancellation.
    webSocketExchangeManager.set(exchange);

    // Send the [exchange.request] to the JSON-RPC web socket server (the response will be
    // recevied by `onSocketData`). The original request may have been modified by
    // WebSocketExchange, so use [exchange.request].
    //_debugWebSocketRequest(exchange.request);
    final List<int> data = json.encode(exchange.request.toJson()).codeUnits;
    socket.send(await encrypt(data));

    // Return the pending subscription that completes when a success response is received from the
    // web socket server (onSocketData) or the request times out.
    final Duration timeLimit = config?.timeout ?? const Duration(seconds: 60);
    return await exchange.response.timeout(timeLimit, onTimeout: onWebSocketExchangeTimeout());

  } catch (error, stackTrace) {
    webSocketExchangeManager.remove(exchange?.id);
    exchange?.completeError(error, stackTrace);
    return Future.error(error, stackTrace);
  }
}