Kraken : quatre corrections de fiabilité pour les clients WebSocket et Futures REST | eSeGeCe Blog

Kraken : quatre corrections de fiabilité pour les clients WebSocket et Futures REST

· Composants

Quatre défauts distincts touchant Kraken sont entrés dans la 2026.9, et aucun d'entre eux n'était du genre qu'on repère en relisant le code une seule fois. Chacun ne se manifeste que sous une condition bien précise : le mauvais point de terminaison au moment de la connexion, un corps de requête qui ne quitte jamais la machine, une reconnexion qui survient quelques centaines de millisecondes trop tôt. Les quatre sont corrigés, et les quatre méritent d'être compris, car dans chaque cas le symptôme ressemble à tout autre chose.

Le client spot parlait en v1 à un point de terminaison v2

TsgcWSAPI_Kraken construit et analyse le schéma v1 : event, pair, subscription, subscriptionStatus, systemStatus. Ce schéma existe pour une raison précise, c'est celui sur lequel chaque appel d'abonnement et chaque gestionnaire d'événement de ce composant est écrit. Le point de terminaison auquel il se connectait, en revanche, pointait par défaut vers le WebSocket v2 de Kraken, qui parle un schéma entièrement différent : method, params, channel, type. La connexion s'ouvrait sans erreur. Elle ne produisait simplement jamais le moindre accusé de réception d'abonnement ni le moindre événement de statut, parce que le serveur répondait dans une forme que le client n'analyse jamais.

Kraken.Version vaut désormais 1 par défaut, et le composant choisit le point de terminaison v1 correspondant :

uses
  sgcWebSocket, sgcWebSocket_APIs;

var
  oKraken: TsgcWSAPI_Kraken;
begin
  oKraken := TsgcWSAPI_Kraken.Create(nil);
  oKraken.Client := oClient;
  // Version defaults to 1, matching the event/pair/subscription
  // schema this component already builds and parses.
  oKraken.Kraken.Version := 1;
  oClient.Active := True;
  oKraken.SubscribeTicker('XBT/USD');
end;

Si votre application dépendait d'une manière ou d'une autre de l'ancienne valeur par défaut, silencieusement erronée, cela signifie qu'elle ne recevait en réalité aucun événement v1 non plus, il n'y a donc rien de fonctionnel aujourd'hui à préserver. Définir explicitement Kraken.Version := 2 continue de se connecter au point de terminaison v2, avec RawMessages activé et la charge utile traitée dans OnKrakenData ou OnMessage, pour quiconque développe volontairement contre ce schéma.

Les ordres Futures partaient en GET, corps abandonné

Celui-ci est plus discret et plus grave. Chaque requête privée sur le client REST Kraken Futures, envoyer un ordre, en modifier un, en annuler un, un transfert, un retrait, partait en HTTP GET. Le corps de requête signé était construit correctement, calculé, formaté, prêt à être envoyé, puis abandonné, parce qu'une requête GET n'a pas de corps où le placer. Kraken recevait un GET sans paramètres et le rejetait ou l'ignorait. Aucun de ces appels ne fonctionnait.

uses
  sgcHTTP_API_Kraken;

var
  oKraken: TsgcHTTP_API_Kraken_Futures_Rest;
  oOrder: TsgcHTTPKrakenFuturesOrder;
begin
  oKraken := TsgcHTTP_API_Kraken_Futures_Rest.Create(nil);
  oKraken.KrakenOptions.ApiKey := 'your_api_key';
  oKraken.KrakenOptions.ApiSecret := 'your_api_secret';

  oOrder := TsgcHTTPKrakenFuturesOrder.Create;
  try
    oOrder.OrderType := kotfLMT;
    oOrder.Symbol := 'PF_XBTUSD';
    oOrder.Side := kosfBuy;
    oOrder.Size := 1;
    oOrder.LimitPrice := 30000;
    // SendOrder now posts through DoHTTP_POST_PRIVATE, body included.
    ShowMessage(oKraken.SendOrder(oOrder));
  finally
    oOrder.Free;
  end;
end;

SendOrder, EditOrderByOrderId, EditOrderByCliOrderId, CancelOrderByOrderId, CancelOrderByCliOrderId, Transfer et WithdrawalToSpotWallet passent désormais tous par le chemin POST privé, avec le corps signé effectivement joint à la requête.

Abonnements privés perdus lors de la reconnexion

Le WatchDog se reconnecte, le journal affiche une reconnexion propre, et à partir de là vos canaux d'ordres, de solde et d'exécutions ont tout simplement disparu. Rien ne remonte d'erreur. Rien n'est journalisé. La reconnexion avait l'air parfaitement réussie, parce que la connexion elle-même avait effectivement réussi, seuls les abonnements privés émis avant la coupure n'étaient ensuite jamais rejoués. Cela touchait aussi bien Kraken spot que Kraken Futures, ainsi que plusieurs autres clients d'échanges corrigés dans la même passe. Cela fait désormais partie du rejeu de réabonnement standard, le même chemin qui restaure déjà vos abonnements de données de marché publiques après une reconnexion.

Futures se réabonnait avant que la session ne soit authentifiée

Un défaut étroitement lié, spécifique à Kraken Futures : après une reconnexion, le rejeu des abonnements actifs pouvait s'exécuter avant que la négociation d'authentification ne soit réellement terminée. Les requêtes d'abonnement partaient sur une session que Kraken n'avait pas encore authentifiée, si bien que les abonnements privés étaient rejetés, là encore sans rien dans le client permettant d'en comprendre la raison. Le rejeu attend désormais que l'authentification soit terminée avant de se réabonner.

Mise à jour

Les quatre corrections s'appliquent directement, il n'y a aucune API à migrer. Le seul changement de comportement à connaître est le basculement de la valeur par défaut de Kraken.Version, de l'ancienne valeur, en pratique non fonctionnelle, vers 1 ; si votre code définit déjà explicitement Version := 2, rien ne change pour vous.

Des questions, une remarque ou besoin d'aide pour la migration ? Contactez-nous — vous obtiendrez une réponse des personnes qui ont écrit le code.