@blackcube/xgate-sdk 0.21.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +239 -12
- package/dist/index.cjs +559 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -2
- package/dist/index.d.ts +294 -2
- package/dist/index.js +554 -137
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.d.cts
CHANGED
|
@@ -68,6 +68,23 @@ interface IPair {
|
|
|
68
68
|
xex: XgateEx;
|
|
69
69
|
/** Type de marché (`perp`/`spot`). */
|
|
70
70
|
kind: MarketKind;
|
|
71
|
+
/**
|
|
72
|
+
* FACTEUR D'ÉCHELLE DE COTATION — `1000` pour `kPEPE`, `1000000` pour `1MBABYDOGE`, `1` sinon.
|
|
73
|
+
*
|
|
74
|
+
* **Aucune venue ne le publie** : l'information n'existe que dans le préfixe du nom, et le
|
|
75
|
+
* canonique la fait disparaître. Sans elle, comparer des prix entre venues est faux — `SATS`
|
|
76
|
+
* porte trois échelles sur quatre sources (×1, ×1000, ×10000). Diviser le prix par ce facteur
|
|
77
|
+
* ramène toutes les venues à la même unité.
|
|
78
|
+
*/
|
|
79
|
+
multiplier: number;
|
|
80
|
+
/**
|
|
81
|
+
* ÉCHÉANCE du contrat. `undefined` pour un perpétuel — l'immense majorité.
|
|
82
|
+
*
|
|
83
|
+
* Un future daté ne cote pas le comptant : sa base peut s'écarter de plusieurs pour cent. Neuf
|
|
84
|
+
* lignes BTC de bybit sont dans ce cas. Dérivée du **type de contrat**, jamais de la date de
|
|
85
|
+
* livraison : binance publie l'an 2100 sur ses perpétuels.
|
|
86
|
+
*/
|
|
87
|
+
expiresAt?: Date;
|
|
71
88
|
/**
|
|
72
89
|
* L'identifiant TECHNIQUE que la venue exige pour agir, quand il diffère du symbole (index de
|
|
73
90
|
* marché chez lighter, index spot chez hyperliquid). `null` quand le symbole suffit.
|
|
@@ -295,6 +312,120 @@ declare class WsCandlesService {
|
|
|
295
312
|
private quoteOf;
|
|
296
313
|
}
|
|
297
314
|
|
|
315
|
+
/**
|
|
316
|
+
* LE FLUX DE BOUGIES D'UNE VENUE — porté de
|
|
317
|
+
* `Blips/server/src/candles/services/internal/dex-candles-stream.service.ts`, où il tourne en
|
|
318
|
+
* production. Même surface, mêmes garanties ; seul le type de bougie change (celui d'XGate).
|
|
319
|
+
*
|
|
320
|
+
* **UNE INSTANCE PAR VENUE, DONC UNE SOCKET PAR VENUE.** La façade est mémoïsée (`instance()`) et
|
|
321
|
+
* `ws()` n'est appelé qu'une fois, hors de la boucle : les N souscriptions partagent la même
|
|
322
|
+
* connexion. Créer la façade à chaque souscription ouvrirait une socket par marché — 200 marchés
|
|
323
|
+
* suivis, 200 sockets, quand hyperliquid n'en accepte que 10 par IP.
|
|
324
|
+
*
|
|
325
|
+
* **UNE SOUSCRIPTION PAR MARCHÉ, et non `subscribeAllCandles`.** Ce dernier ne coûte qu'un
|
|
326
|
+
* abonnement, mais il est bâti sur un flux de prix agrégé : mesuré le 2026-08-02, il rend un prix
|
|
327
|
+
* MILIEU (40 % des valeurs sur un demi-tick contre 8 % au REST) et AUCUN volume (`"v":"0"` sur les
|
|
328
|
+
* six dex). Le canal `candle` par marché rend la vraie bougie de trades, avec son volume.
|
|
329
|
+
*
|
|
330
|
+
* **LE SYMBOLE VIENT DU MESSAGE**, jamais de la souscription. Les SDK hyperliquid et pacifica
|
|
331
|
+
* livraient tout le canal à tous les abonnés jusqu'à la 0.15.0 — trois souscriptions recevaient le
|
|
332
|
+
* même flux. C'est corrigé, mais la règle reste : on lit ce que le wire déclare, on ne suppose pas.
|
|
333
|
+
*/
|
|
334
|
+
declare class CandlesStreamService {
|
|
335
|
+
readonly xex: XgateEx;
|
|
336
|
+
/** Le marché écouté. Le comptant n'est servi que par binance et bybit. */
|
|
337
|
+
readonly kind: MarketKind;
|
|
338
|
+
private readonly logger;
|
|
339
|
+
private source;
|
|
340
|
+
private readonly unsubscribes;
|
|
341
|
+
/** Le plafond de souscriptions documenté par la venue, ou `null` si personne ne l'a publié. */
|
|
342
|
+
readonly maxSubscriptions: number | null;
|
|
343
|
+
constructor(xex: XgateEx,
|
|
344
|
+
/** Le marché écouté. Le comptant n'est servi que par binance et bybit. */
|
|
345
|
+
kind?: MarketKind);
|
|
346
|
+
/**
|
|
347
|
+
* Ouvre le flux sur une LISTE de marchés, sur une seule socket.
|
|
348
|
+
*
|
|
349
|
+
* **UNE ERREUR DE FLUX COUPE TOUT, PUIS LÈVE.** Elle n'arrive pas à la souscription : mesuré le
|
|
350
|
+
* 2026-08-07, la venue accepte un symbole inconnu sans broncher, puis ferme la connexion en le
|
|
351
|
+
* découvrant. Le SDK reconnecte, elle referme — cinq cycles en douze secondes, et sur une socket
|
|
352
|
+
* partagée **tous** les marchés valides cessent de recevoir, en silence.
|
|
353
|
+
*
|
|
354
|
+
* On refuse cette boucle : à la première erreur, les souscriptions sont coupées, l'incident est
|
|
355
|
+
* journalisé en `error`, et l'exception part. Un flux à moitié mort qui se tait coûte plus cher
|
|
356
|
+
* qu'un arrêt franc — on ne découvre le premier qu'en constatant l'absence de données.
|
|
357
|
+
*
|
|
358
|
+
* ⚠️ L'exception naît dans un rappel de socket : elle ne remonte pas à l'appelant de `start()`,
|
|
359
|
+
* elle sort en erreur non capturée. C'est délibéré — elle doit être impossible à ignorer.
|
|
360
|
+
*
|
|
361
|
+
* **binance et bybit ne remontent pas encore leurs erreurs** : leur client gère la fermeture en
|
|
362
|
+
* interne sans l'exposer. Sur ces deux venues, la boucle silencieuse reste possible.
|
|
363
|
+
*/
|
|
364
|
+
start(symbolsXex: string[], interval: Timeframe, onCandle: (candle: ICandle) => void): void;
|
|
365
|
+
/** Coupe tout. Un désabonnement qui échoue ne doit pas empêcher les autres de se fermer. */
|
|
366
|
+
stop(): void;
|
|
367
|
+
/** Le nombre de souscriptions ouvertes. La liste des désabonnements EST le compteur. */
|
|
368
|
+
subscriptionCount(): number;
|
|
369
|
+
/**
|
|
370
|
+
* Le client temps réel, sur le bon marché.
|
|
371
|
+
*
|
|
372
|
+
* Les deux contrats ne signent pas `ws()` pareil, et c'est voulu : côté comptant le marché est
|
|
373
|
+
* **obligatoire** (`ws('spot')`), parce que les façades ouvrent du perpétuel par défaut — un
|
|
374
|
+
* `ws()` nu y diffuserait des prix de perpétuel à qui croit écouter le comptant.
|
|
375
|
+
*/
|
|
376
|
+
private wire;
|
|
377
|
+
/** La façade de la venue, créée une seule fois : c'est elle qui porte la socket partagée. */
|
|
378
|
+
private instance;
|
|
379
|
+
/** Voir `CandlesService.quoteOf` : la cotation se déduit du symbole natif, faute d'être publiée. */
|
|
380
|
+
private quoteOf;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* LA FAÇADE : un flux par venue, et un seul.
|
|
384
|
+
*
|
|
385
|
+
* Blips instancie `DexCandlesStreamService` une fois par venue et garde la référence. XGate offre
|
|
386
|
+
* la même chose sans que l'appelant ait à tenir cette table : `of(xex)` rend **toujours la même
|
|
387
|
+
* instance** pour une venue et un marché donnés — donc toujours la même socket.
|
|
388
|
+
*
|
|
389
|
+
* Demander deux fois `of(hyperliquid)` et souscrire 100 marchés à chaque fois ouvre **une** socket
|
|
390
|
+
* avec 200 souscriptions, pas deux sockets. C'est exactement ce qui manquait.
|
|
391
|
+
*/
|
|
392
|
+
declare class CandlesStreamRegistry {
|
|
393
|
+
private readonly streams;
|
|
394
|
+
/** Le flux d'une venue, créé au premier appel puis réutilisé. */
|
|
395
|
+
of(xex: XgateEx, kind?: MarketKind): CandlesStreamService;
|
|
396
|
+
/** Coupe tous les flux ouverts, toutes venues confondues. */
|
|
397
|
+
stopAll(): void;
|
|
398
|
+
/** Ce qui est ouvert, par venue — pour surveiller sans avoir à tenir de compteur soi-même. */
|
|
399
|
+
counts(): Record<string, number>;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* LES PLAFONDS DE SOUSCRIPTION, PAR VENUE — uniquement ceux qu'une documentation officielle donne.
|
|
404
|
+
*
|
|
405
|
+
* Repris de `Blips/server/src/candles/services/internal/dex-candles-stream.service.ts`, où ils ont
|
|
406
|
+
* été établis puis vérifiés en réel.
|
|
407
|
+
*
|
|
408
|
+
* **aster**, section « Websocket Market Streams » : « A single connection can listen to a maximum
|
|
409
|
+
* of 200 streams », et « A connection that goes beyond the limit will be disconnected; IPs that are
|
|
410
|
+
* repeatedly disconnected may be banned ». Vérifié le 2026-08-03 sur `fstream.asterdex.com` : 200
|
|
411
|
+
* tiennent, 300 tuent la connexion.
|
|
412
|
+
* <https://github.com/asterdex/api-docs/blob/master/V3(Recommended)/EN/aster-finance-futures-api-v3.md>
|
|
413
|
+
*
|
|
414
|
+
* **hyperliquid** : 1 000 souscriptions et 10 connexions par IP.
|
|
415
|
+
*
|
|
416
|
+
* **Une venue ABSENTE de cette table n'a pas de plafond DOCUMENTÉ** — ce qui n'est pas la même
|
|
417
|
+
* chose que « pas de plafond ». On ne devine aucun chiffre : le jour où l'une d'elles s'en
|
|
418
|
+
* approche, on lit sa documentation et on l'ajoute.
|
|
419
|
+
*/
|
|
420
|
+
declare const WS_SUBSCRIPTION_LIMITS: Partial<Record<XgateEx, number>>;
|
|
421
|
+
/**
|
|
422
|
+
* Le plafond documenté d'une venue, ou `undefined` si personne ne l'a publié.
|
|
423
|
+
*
|
|
424
|
+
* Rendre `Infinity` par défaut serait un mensonge commode : l'absence de plafond connu n'est pas
|
|
425
|
+
* une garantie d'illimité.
|
|
426
|
+
*/
|
|
427
|
+
declare function subscriptionLimitOf(xex: XgateEx): number | undefined;
|
|
428
|
+
|
|
298
429
|
/**
|
|
299
430
|
* UNE COTATION, TELLE QU'XGATE LA REND — quelle que soit la venue d'où elle vient.
|
|
300
431
|
*
|
|
@@ -407,6 +538,112 @@ declare class SpotCatalogService {
|
|
|
407
538
|
private catalogOf;
|
|
408
539
|
}
|
|
409
540
|
|
|
541
|
+
/**
|
|
542
|
+
* LES BOUGIES DU **COMPTANT**, en REST — binance et bybit.
|
|
543
|
+
*
|
|
544
|
+
* **Un service à part, et non un drapeau sur {@link CandlesService}.** C'est la même règle que pour
|
|
545
|
+
* le catalogue : un `candles()` qui servirait tantôt du perpétuel tantôt du comptant selon un
|
|
546
|
+
* paramètre produirait des erreurs silencieuses — on croirait lire des perpétuels et on lirait du
|
|
547
|
+
* comptant, sans que rien ne le signale. Deux marchés, deux services ; l'appelant choisit
|
|
548
|
+
* explicitement ce qu'il interroge.
|
|
549
|
+
*
|
|
550
|
+
* La différence n'est pas cosmétique : **le perpétuel porte un funding et s'écarte du comptant**.
|
|
551
|
+
* C'est cet écart que certaines stratégies exploitent — le confondre le rendrait invisible.
|
|
552
|
+
*
|
|
553
|
+
* En revanche, les échelles de cotation ne posent aucun problème entre les deux marchés :
|
|
554
|
+
* `SATSUSDT` (×1) et `10000SATSUSDT` (×10000) sont **deux paires distinctes**, chacune portant son
|
|
555
|
+
* `multiplier` au catalogue. Une bougie appartient à une paire, identifiée par `xex` +
|
|
556
|
+
* `symbolXex` + `kind` : il n'y a rien à réconcilier.
|
|
557
|
+
*
|
|
558
|
+
* **Aucune agrégation ici**, contrairement au perpétuel : binance et bybit servent nativement tous
|
|
559
|
+
* les intervalles de `1m` à `1w`. Le jour où une venue comptant en manquerait un, ce serait à
|
|
560
|
+
* ajouter — pas à supposer.
|
|
561
|
+
*/
|
|
562
|
+
declare class SpotCandlesService {
|
|
563
|
+
private readonly logger;
|
|
564
|
+
/** Les venues dont XGate sert le comptant. */
|
|
565
|
+
venues(): readonly XgateEx[];
|
|
566
|
+
/**
|
|
567
|
+
* Les bougies comptant d'une venue, sur une plage de **dates**.
|
|
568
|
+
*
|
|
569
|
+
* **Lève** si la venue ne sert pas de comptant, plutôt que de rendre une liste vide : « cette
|
|
570
|
+
* venue n'a pas de marché comptant » et « ce marché n'a pas coté » appellent des suites très
|
|
571
|
+
* différentes.
|
|
572
|
+
*/
|
|
573
|
+
candles(xex: XgateEx, query: ICandlesQuery): Promise<ICandle[]>;
|
|
574
|
+
/**
|
|
575
|
+
* Les bougies comptant d'un même marché chez PLUSIEURS venues, en une liste.
|
|
576
|
+
*
|
|
577
|
+
* Même politique d'échec que partout ailleurs : seule, une venue en échec fait échouer l'appel ;
|
|
578
|
+
* parmi d'autres, elle est journalisée et ignorée. Chaque bougie porte son `xex`.
|
|
579
|
+
*/
|
|
580
|
+
candlesOf(xexes: XgateEx[], query: ICandlesQuery): Promise<ICandle[]>;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* LES PRIX DU **COMPTANT** — binance et bybit.
|
|
585
|
+
*
|
|
586
|
+
* Séparé de `PricesService` comme le catalogue et les bougies le sont : deux marchés, deux
|
|
587
|
+
* services. Ici la raison est encore plus directe qu'ailleurs — **un prix comptant et un prix
|
|
588
|
+
* perpétuel ne sont pas le même nombre**. Le perpétuel porte un funding et s'écarte du comptant ;
|
|
589
|
+
* c'est justement cet écart que certaines stratégies exploitent, et le confondre le rendrait
|
|
590
|
+
* invisible.
|
|
591
|
+
*
|
|
592
|
+
* **La moitié des champs sont `null` au comptant, et c'est correct** : `mark`, `oracle`, `funding`
|
|
593
|
+
* et `openInterest` n'existent que pour un perpétuel. Le comptant renseigne `bid`, `ask`, `last`,
|
|
594
|
+
* `volume24h` — ce qui est mesuré, pas ce qui est dérivé d'un contrat.
|
|
595
|
+
*/
|
|
596
|
+
declare class SpotPricesService {
|
|
597
|
+
private readonly logger;
|
|
598
|
+
/** Les venues dont XGate sert les prix comptant. */
|
|
599
|
+
venues(): readonly XgateEx[];
|
|
600
|
+
/**
|
|
601
|
+
* Les prix comptant d'une ou plusieurs venues, en une seule liste.
|
|
602
|
+
*
|
|
603
|
+
* Même politique d'échec que partout : seule, une venue en échec fait échouer l'appel ; parmi
|
|
604
|
+
* d'autres, elle est journalisée et ignorée. Chaque prix porte son `xex`.
|
|
605
|
+
*/
|
|
606
|
+
prices(...xexes: XgateEx[]): Promise<IPrice[]>;
|
|
607
|
+
/** Les prix comptant d'UNE venue, traduits vers {@link IPrice}. */
|
|
608
|
+
private pricesOf;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* LES BOUGIES DU **COMPTANT** EN TEMPS RÉEL — binance et bybit.
|
|
613
|
+
*
|
|
614
|
+
* Le pendant de `WsCandlesService`, sur l'autre marché. La séparation n'est pas une symétrie
|
|
615
|
+
* décorative : les façades exposent `ws(kind = 'perp')`, donc **un `ws()` nu ouvre un flux de
|
|
616
|
+
* perpétuels**. Un service unique qui aurait oublié de passer le marché aurait diffusé des prix
|
|
617
|
+
* de perpétuel à qui croyait écouter le comptant — deux séries voisines, jamais égales, et rien
|
|
618
|
+
* pour le signaler.
|
|
619
|
+
*
|
|
620
|
+
* Le contrat {@link IXexSpotSource} exige donc `ws('spot')` explicitement, sans valeur par défaut.
|
|
621
|
+
*/
|
|
622
|
+
declare class SpotWsCandlesService {
|
|
623
|
+
private readonly logger;
|
|
624
|
+
/** Les venues dont XGate diffuse le comptant en temps réel. */
|
|
625
|
+
venues(): readonly XgateEx[];
|
|
626
|
+
/**
|
|
627
|
+
* Souscrit aux bougies **comptant** d'un marché. Rend la fonction de désabonnement.
|
|
628
|
+
*
|
|
629
|
+
* Le handler reçoit une bougie à la fois, au format unifié ; la bougie en cours est repoussée à
|
|
630
|
+
* chaque mise à jour tant qu'elle n'est pas close.
|
|
631
|
+
*/
|
|
632
|
+
subscribe(xex: XgateEx, query: {
|
|
633
|
+
symbol: string;
|
|
634
|
+
interval: Timeframe;
|
|
635
|
+
}, handler: (candle: ICandle) => void): Unsubscribe;
|
|
636
|
+
/**
|
|
637
|
+
* Souscrit au MÊME marché comptant chez plusieurs venues, avec un seul handler.
|
|
638
|
+
*
|
|
639
|
+
* Chaque bougie porte son `xex`. La fonction rendue coupe tous les flux d'un coup.
|
|
640
|
+
*/
|
|
641
|
+
subscribeAll(xexes: XgateEx[], query: {
|
|
642
|
+
symbol: string;
|
|
643
|
+
interval: Timeframe;
|
|
644
|
+
}, handler: (candle: ICandle) => void): Unsubscribe;
|
|
645
|
+
}
|
|
646
|
+
|
|
410
647
|
/** Une paire, telle qu'un SDK de venue la rend. */
|
|
411
648
|
interface IXexPair {
|
|
412
649
|
name: string;
|
|
@@ -499,6 +736,18 @@ interface IXexSpotSource {
|
|
|
499
736
|
}): Promise<IXexCandle[]>;
|
|
500
737
|
getPrices?(): Promise<IXexPrice[]>;
|
|
501
738
|
};
|
|
739
|
+
/**
|
|
740
|
+
* Le temps réel du COMPTANT. **`kind` est obligatoire ici**, contrairement aux façades qui le
|
|
741
|
+
* rendent optionnel : leur défaut est `'perp'`, et un `ws()` nu ouvre donc un flux de perpétuels
|
|
742
|
+
* en croyant écouter le comptant — deux marchés dont les prix diffèrent, sans que rien ne le
|
|
743
|
+
* signale.
|
|
744
|
+
*/
|
|
745
|
+
ws(kind: 'spot'): {
|
|
746
|
+
subscribeCandles(query: {
|
|
747
|
+
name: string;
|
|
748
|
+
interval: string;
|
|
749
|
+
}, handler: (candle: IXexCandle) => void): () => void;
|
|
750
|
+
};
|
|
502
751
|
}
|
|
503
752
|
/**
|
|
504
753
|
* De quoi lire UN compte chez une venue.
|
|
@@ -535,7 +784,7 @@ interface IXexAccess {
|
|
|
535
784
|
* Les venues dont XGate sait lire le portefeuille aujourd'hui.
|
|
536
785
|
*
|
|
537
786
|
* Les autres ne sont pas exclues par principe : il leur manque un accès (clé d'API pour bullet, une
|
|
538
|
-
* adresse active pour
|
|
787
|
+
* adresse active pour extended et paradex). Voir le backlog.
|
|
539
788
|
*/
|
|
540
789
|
declare const WALLET_XEXES: readonly XgateEx[];
|
|
541
790
|
/**
|
|
@@ -1104,5 +1353,48 @@ declare function canonicalFromXex(rawSymbol: string, xexId: string): string;
|
|
|
1104
1353
|
* symbole.
|
|
1105
1354
|
*/
|
|
1106
1355
|
declare function canonicalFromBase(base: string): string;
|
|
1356
|
+
/**
|
|
1357
|
+
* LE MULTIPLICATEUR DE COTATION, extrait du nom — **la seule source qui existe**.
|
|
1358
|
+
*
|
|
1359
|
+
* Aucune venue ne le publie : `kPEPE` chez hyperliquid ne porte que `{"marginTableId":52}`,
|
|
1360
|
+
* `1000PEPEUSDT` chez binance ne mentionne aucun facteur. L'information n'est QUE dans le préfixe
|
|
1361
|
+
* du nom, et le canonique la fait disparaître — jusqu'ici sans la conserver nulle part.
|
|
1362
|
+
*
|
|
1363
|
+
* Or elle est indispensable dès qu'on compare des prix entre venues. `SATS` porte **trois échelles
|
|
1364
|
+
* différentes sur quatre sources** : `SATSUSDT` (×1) chez bybit-spot, `1000SATSUSDT` (×1000) chez
|
|
1365
|
+
* binance, `10000SATSUSDT` (×10000) chez bybit. Une médiane calculée sur ces prix bruts ne veut
|
|
1366
|
+
* rien dire ; divisés par leur facteur, ils redeviennent comparables.
|
|
1367
|
+
*
|
|
1368
|
+
* Rend `1` quand le nom ne porte aucune échelle — le cas de l'immense majorité.
|
|
1369
|
+
*/
|
|
1370
|
+
declare function multiplierFromXex(rawSymbol: string): number;
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* LES CONTRATS À ÉCHÉANCE, séparés des perpétuels — parce qu'un future daté ne cote pas le comptant.
|
|
1374
|
+
*
|
|
1375
|
+
* Le catalogue les mélangeait : 44 lignes portaient `kind: 'perp'` alors qu'elles expirent, dont
|
|
1376
|
+
* neuf sur le seul BTC chez bybit. Un consommateur qui prend « le prix du BTC » y ramassait une
|
|
1377
|
+
* échéance de décembre, dont la base au comptant peut s'écarter de plusieurs pour cent.
|
|
1378
|
+
*
|
|
1379
|
+
* **`contractType` fait foi, JAMAIS la date de livraison.** binance publie `deliveryDate:
|
|
1380
|
+
* 4133404800000` — le 1er janvier 2100 — sur ses **perpétuels** : s'y fier marquerait tout le
|
|
1381
|
+
* catalogue comme daté. bybit, lui, met `deliveryTime: '0'` sur les siens. Deux conventions
|
|
1382
|
+
* incompatibles pour dire « ceci n'expire pas », d'où la lecture du type et de lui seul.
|
|
1383
|
+
*/
|
|
1384
|
+
/**
|
|
1385
|
+
* L'ÉCHÉANCE D'UN CONTRAT, ou `undefined` s'il est perpétuel.
|
|
1386
|
+
*
|
|
1387
|
+
* On ne lit la date **que** si le type de contrat annonce une échéance : c'est ce qui neutralise le
|
|
1388
|
+
* `deliveryDate` de l'an 2100 des perpétuels binance. Un type inconnu est traité comme perpétuel —
|
|
1389
|
+
* l'immense majorité des lignes, et se tromper dans ce sens n'invente pas d'échéance.
|
|
1390
|
+
*/
|
|
1391
|
+
declare function expiryOf(xtras?: Record<string, unknown>): Date | undefined;
|
|
1392
|
+
/**
|
|
1393
|
+
* LE CONTRAT EXPIRE-T-IL ? Vrai pour un future daté, faux pour un perpétuel.
|
|
1394
|
+
*
|
|
1395
|
+
* Séparé d'{@link expiryOf} à dessein : une venue peut annoncer un type daté sans publier de date
|
|
1396
|
+
* exploitable, et il faut alors pouvoir écarter la ligne quand même.
|
|
1397
|
+
*/
|
|
1398
|
+
declare function isDated(xtras?: Record<string, unknown>): boolean;
|
|
1107
1399
|
|
|
1108
|
-
export { CandlesService, CatalogService, type Direction, type IBalance, type ICandle, type ICandlesQuery, type IEntryWithProtection, type IEquityPoint, type IMoveStop, type IMovement, type IOrder, type IPair, type IPosition, type IPrice, type IProtection, type IProtectionInput, type IProtectionLeg, type ITrade, type ITradingAccess, type IWalletAccess, type IXexAccess, type IXexSpotSource, type MarketKind, type MovementKind, type MovementStatus, ORDER_STATUSES, type OrderStatus, type OrderType, PricesService, SPOT_XEXES, type Side, SpotCatalogService, TIMEFRAME_MINUTES, type TimeInForce, Timeframe, TradingService, type Unsubscribe, WALLET_XEXES, WalletService, WsCandlesService, XGATE_EXCHANGES, XgateEx, XgateModule, buildLevels, buildProtection, canonicalFromBase, canonicalFromXex, roundPrice, roundToStep, servesNatively, servesSpot, sourceFor, timeframeMs };
|
|
1400
|
+
export { CandlesService, CandlesStreamRegistry, CandlesStreamService, CatalogService, type Direction, type IBalance, type ICandle, type ICandlesQuery, type IEntryWithProtection, type IEquityPoint, type IMoveStop, type IMovement, type IOrder, type IPair, type IPosition, type IPrice, type IProtection, type IProtectionInput, type IProtectionLeg, type ITrade, type ITradingAccess, type IWalletAccess, type IXexAccess, type IXexSpotSource, type MarketKind, type MovementKind, type MovementStatus, ORDER_STATUSES, type OrderStatus, type OrderType, PricesService, SPOT_XEXES, type Side, SpotCandlesService, SpotCatalogService, SpotPricesService, SpotWsCandlesService, TIMEFRAME_MINUTES, type TimeInForce, Timeframe, TradingService, type Unsubscribe, WALLET_XEXES, WS_SUBSCRIPTION_LIMITS, WalletService, WsCandlesService, XGATE_EXCHANGES, XgateEx, XgateModule, buildLevels, buildProtection, canonicalFromBase, canonicalFromXex, expiryOf, isDated, multiplierFromXex, roundPrice, roundToStep, servesNatively, servesSpot, sourceFor, subscriptionLimitOf, timeframeMs };
|
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,23 @@ interface IPair {
|
|
|
68
68
|
xex: XgateEx;
|
|
69
69
|
/** Type de marché (`perp`/`spot`). */
|
|
70
70
|
kind: MarketKind;
|
|
71
|
+
/**
|
|
72
|
+
* FACTEUR D'ÉCHELLE DE COTATION — `1000` pour `kPEPE`, `1000000` pour `1MBABYDOGE`, `1` sinon.
|
|
73
|
+
*
|
|
74
|
+
* **Aucune venue ne le publie** : l'information n'existe que dans le préfixe du nom, et le
|
|
75
|
+
* canonique la fait disparaître. Sans elle, comparer des prix entre venues est faux — `SATS`
|
|
76
|
+
* porte trois échelles sur quatre sources (×1, ×1000, ×10000). Diviser le prix par ce facteur
|
|
77
|
+
* ramène toutes les venues à la même unité.
|
|
78
|
+
*/
|
|
79
|
+
multiplier: number;
|
|
80
|
+
/**
|
|
81
|
+
* ÉCHÉANCE du contrat. `undefined` pour un perpétuel — l'immense majorité.
|
|
82
|
+
*
|
|
83
|
+
* Un future daté ne cote pas le comptant : sa base peut s'écarter de plusieurs pour cent. Neuf
|
|
84
|
+
* lignes BTC de bybit sont dans ce cas. Dérivée du **type de contrat**, jamais de la date de
|
|
85
|
+
* livraison : binance publie l'an 2100 sur ses perpétuels.
|
|
86
|
+
*/
|
|
87
|
+
expiresAt?: Date;
|
|
71
88
|
/**
|
|
72
89
|
* L'identifiant TECHNIQUE que la venue exige pour agir, quand il diffère du symbole (index de
|
|
73
90
|
* marché chez lighter, index spot chez hyperliquid). `null` quand le symbole suffit.
|
|
@@ -295,6 +312,120 @@ declare class WsCandlesService {
|
|
|
295
312
|
private quoteOf;
|
|
296
313
|
}
|
|
297
314
|
|
|
315
|
+
/**
|
|
316
|
+
* LE FLUX DE BOUGIES D'UNE VENUE — porté de
|
|
317
|
+
* `Blips/server/src/candles/services/internal/dex-candles-stream.service.ts`, où il tourne en
|
|
318
|
+
* production. Même surface, mêmes garanties ; seul le type de bougie change (celui d'XGate).
|
|
319
|
+
*
|
|
320
|
+
* **UNE INSTANCE PAR VENUE, DONC UNE SOCKET PAR VENUE.** La façade est mémoïsée (`instance()`) et
|
|
321
|
+
* `ws()` n'est appelé qu'une fois, hors de la boucle : les N souscriptions partagent la même
|
|
322
|
+
* connexion. Créer la façade à chaque souscription ouvrirait une socket par marché — 200 marchés
|
|
323
|
+
* suivis, 200 sockets, quand hyperliquid n'en accepte que 10 par IP.
|
|
324
|
+
*
|
|
325
|
+
* **UNE SOUSCRIPTION PAR MARCHÉ, et non `subscribeAllCandles`.** Ce dernier ne coûte qu'un
|
|
326
|
+
* abonnement, mais il est bâti sur un flux de prix agrégé : mesuré le 2026-08-02, il rend un prix
|
|
327
|
+
* MILIEU (40 % des valeurs sur un demi-tick contre 8 % au REST) et AUCUN volume (`"v":"0"` sur les
|
|
328
|
+
* six dex). Le canal `candle` par marché rend la vraie bougie de trades, avec son volume.
|
|
329
|
+
*
|
|
330
|
+
* **LE SYMBOLE VIENT DU MESSAGE**, jamais de la souscription. Les SDK hyperliquid et pacifica
|
|
331
|
+
* livraient tout le canal à tous les abonnés jusqu'à la 0.15.0 — trois souscriptions recevaient le
|
|
332
|
+
* même flux. C'est corrigé, mais la règle reste : on lit ce que le wire déclare, on ne suppose pas.
|
|
333
|
+
*/
|
|
334
|
+
declare class CandlesStreamService {
|
|
335
|
+
readonly xex: XgateEx;
|
|
336
|
+
/** Le marché écouté. Le comptant n'est servi que par binance et bybit. */
|
|
337
|
+
readonly kind: MarketKind;
|
|
338
|
+
private readonly logger;
|
|
339
|
+
private source;
|
|
340
|
+
private readonly unsubscribes;
|
|
341
|
+
/** Le plafond de souscriptions documenté par la venue, ou `null` si personne ne l'a publié. */
|
|
342
|
+
readonly maxSubscriptions: number | null;
|
|
343
|
+
constructor(xex: XgateEx,
|
|
344
|
+
/** Le marché écouté. Le comptant n'est servi que par binance et bybit. */
|
|
345
|
+
kind?: MarketKind);
|
|
346
|
+
/**
|
|
347
|
+
* Ouvre le flux sur une LISTE de marchés, sur une seule socket.
|
|
348
|
+
*
|
|
349
|
+
* **UNE ERREUR DE FLUX COUPE TOUT, PUIS LÈVE.** Elle n'arrive pas à la souscription : mesuré le
|
|
350
|
+
* 2026-08-07, la venue accepte un symbole inconnu sans broncher, puis ferme la connexion en le
|
|
351
|
+
* découvrant. Le SDK reconnecte, elle referme — cinq cycles en douze secondes, et sur une socket
|
|
352
|
+
* partagée **tous** les marchés valides cessent de recevoir, en silence.
|
|
353
|
+
*
|
|
354
|
+
* On refuse cette boucle : à la première erreur, les souscriptions sont coupées, l'incident est
|
|
355
|
+
* journalisé en `error`, et l'exception part. Un flux à moitié mort qui se tait coûte plus cher
|
|
356
|
+
* qu'un arrêt franc — on ne découvre le premier qu'en constatant l'absence de données.
|
|
357
|
+
*
|
|
358
|
+
* ⚠️ L'exception naît dans un rappel de socket : elle ne remonte pas à l'appelant de `start()`,
|
|
359
|
+
* elle sort en erreur non capturée. C'est délibéré — elle doit être impossible à ignorer.
|
|
360
|
+
*
|
|
361
|
+
* **binance et bybit ne remontent pas encore leurs erreurs** : leur client gère la fermeture en
|
|
362
|
+
* interne sans l'exposer. Sur ces deux venues, la boucle silencieuse reste possible.
|
|
363
|
+
*/
|
|
364
|
+
start(symbolsXex: string[], interval: Timeframe, onCandle: (candle: ICandle) => void): void;
|
|
365
|
+
/** Coupe tout. Un désabonnement qui échoue ne doit pas empêcher les autres de se fermer. */
|
|
366
|
+
stop(): void;
|
|
367
|
+
/** Le nombre de souscriptions ouvertes. La liste des désabonnements EST le compteur. */
|
|
368
|
+
subscriptionCount(): number;
|
|
369
|
+
/**
|
|
370
|
+
* Le client temps réel, sur le bon marché.
|
|
371
|
+
*
|
|
372
|
+
* Les deux contrats ne signent pas `ws()` pareil, et c'est voulu : côté comptant le marché est
|
|
373
|
+
* **obligatoire** (`ws('spot')`), parce que les façades ouvrent du perpétuel par défaut — un
|
|
374
|
+
* `ws()` nu y diffuserait des prix de perpétuel à qui croit écouter le comptant.
|
|
375
|
+
*/
|
|
376
|
+
private wire;
|
|
377
|
+
/** La façade de la venue, créée une seule fois : c'est elle qui porte la socket partagée. */
|
|
378
|
+
private instance;
|
|
379
|
+
/** Voir `CandlesService.quoteOf` : la cotation se déduit du symbole natif, faute d'être publiée. */
|
|
380
|
+
private quoteOf;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* LA FAÇADE : un flux par venue, et un seul.
|
|
384
|
+
*
|
|
385
|
+
* Blips instancie `DexCandlesStreamService` une fois par venue et garde la référence. XGate offre
|
|
386
|
+
* la même chose sans que l'appelant ait à tenir cette table : `of(xex)` rend **toujours la même
|
|
387
|
+
* instance** pour une venue et un marché donnés — donc toujours la même socket.
|
|
388
|
+
*
|
|
389
|
+
* Demander deux fois `of(hyperliquid)` et souscrire 100 marchés à chaque fois ouvre **une** socket
|
|
390
|
+
* avec 200 souscriptions, pas deux sockets. C'est exactement ce qui manquait.
|
|
391
|
+
*/
|
|
392
|
+
declare class CandlesStreamRegistry {
|
|
393
|
+
private readonly streams;
|
|
394
|
+
/** Le flux d'une venue, créé au premier appel puis réutilisé. */
|
|
395
|
+
of(xex: XgateEx, kind?: MarketKind): CandlesStreamService;
|
|
396
|
+
/** Coupe tous les flux ouverts, toutes venues confondues. */
|
|
397
|
+
stopAll(): void;
|
|
398
|
+
/** Ce qui est ouvert, par venue — pour surveiller sans avoir à tenir de compteur soi-même. */
|
|
399
|
+
counts(): Record<string, number>;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* LES PLAFONDS DE SOUSCRIPTION, PAR VENUE — uniquement ceux qu'une documentation officielle donne.
|
|
404
|
+
*
|
|
405
|
+
* Repris de `Blips/server/src/candles/services/internal/dex-candles-stream.service.ts`, où ils ont
|
|
406
|
+
* été établis puis vérifiés en réel.
|
|
407
|
+
*
|
|
408
|
+
* **aster**, section « Websocket Market Streams » : « A single connection can listen to a maximum
|
|
409
|
+
* of 200 streams », et « A connection that goes beyond the limit will be disconnected; IPs that are
|
|
410
|
+
* repeatedly disconnected may be banned ». Vérifié le 2026-08-03 sur `fstream.asterdex.com` : 200
|
|
411
|
+
* tiennent, 300 tuent la connexion.
|
|
412
|
+
* <https://github.com/asterdex/api-docs/blob/master/V3(Recommended)/EN/aster-finance-futures-api-v3.md>
|
|
413
|
+
*
|
|
414
|
+
* **hyperliquid** : 1 000 souscriptions et 10 connexions par IP.
|
|
415
|
+
*
|
|
416
|
+
* **Une venue ABSENTE de cette table n'a pas de plafond DOCUMENTÉ** — ce qui n'est pas la même
|
|
417
|
+
* chose que « pas de plafond ». On ne devine aucun chiffre : le jour où l'une d'elles s'en
|
|
418
|
+
* approche, on lit sa documentation et on l'ajoute.
|
|
419
|
+
*/
|
|
420
|
+
declare const WS_SUBSCRIPTION_LIMITS: Partial<Record<XgateEx, number>>;
|
|
421
|
+
/**
|
|
422
|
+
* Le plafond documenté d'une venue, ou `undefined` si personne ne l'a publié.
|
|
423
|
+
*
|
|
424
|
+
* Rendre `Infinity` par défaut serait un mensonge commode : l'absence de plafond connu n'est pas
|
|
425
|
+
* une garantie d'illimité.
|
|
426
|
+
*/
|
|
427
|
+
declare function subscriptionLimitOf(xex: XgateEx): number | undefined;
|
|
428
|
+
|
|
298
429
|
/**
|
|
299
430
|
* UNE COTATION, TELLE QU'XGATE LA REND — quelle que soit la venue d'où elle vient.
|
|
300
431
|
*
|
|
@@ -407,6 +538,112 @@ declare class SpotCatalogService {
|
|
|
407
538
|
private catalogOf;
|
|
408
539
|
}
|
|
409
540
|
|
|
541
|
+
/**
|
|
542
|
+
* LES BOUGIES DU **COMPTANT**, en REST — binance et bybit.
|
|
543
|
+
*
|
|
544
|
+
* **Un service à part, et non un drapeau sur {@link CandlesService}.** C'est la même règle que pour
|
|
545
|
+
* le catalogue : un `candles()` qui servirait tantôt du perpétuel tantôt du comptant selon un
|
|
546
|
+
* paramètre produirait des erreurs silencieuses — on croirait lire des perpétuels et on lirait du
|
|
547
|
+
* comptant, sans que rien ne le signale. Deux marchés, deux services ; l'appelant choisit
|
|
548
|
+
* explicitement ce qu'il interroge.
|
|
549
|
+
*
|
|
550
|
+
* La différence n'est pas cosmétique : **le perpétuel porte un funding et s'écarte du comptant**.
|
|
551
|
+
* C'est cet écart que certaines stratégies exploitent — le confondre le rendrait invisible.
|
|
552
|
+
*
|
|
553
|
+
* En revanche, les échelles de cotation ne posent aucun problème entre les deux marchés :
|
|
554
|
+
* `SATSUSDT` (×1) et `10000SATSUSDT` (×10000) sont **deux paires distinctes**, chacune portant son
|
|
555
|
+
* `multiplier` au catalogue. Une bougie appartient à une paire, identifiée par `xex` +
|
|
556
|
+
* `symbolXex` + `kind` : il n'y a rien à réconcilier.
|
|
557
|
+
*
|
|
558
|
+
* **Aucune agrégation ici**, contrairement au perpétuel : binance et bybit servent nativement tous
|
|
559
|
+
* les intervalles de `1m` à `1w`. Le jour où une venue comptant en manquerait un, ce serait à
|
|
560
|
+
* ajouter — pas à supposer.
|
|
561
|
+
*/
|
|
562
|
+
declare class SpotCandlesService {
|
|
563
|
+
private readonly logger;
|
|
564
|
+
/** Les venues dont XGate sert le comptant. */
|
|
565
|
+
venues(): readonly XgateEx[];
|
|
566
|
+
/**
|
|
567
|
+
* Les bougies comptant d'une venue, sur une plage de **dates**.
|
|
568
|
+
*
|
|
569
|
+
* **Lève** si la venue ne sert pas de comptant, plutôt que de rendre une liste vide : « cette
|
|
570
|
+
* venue n'a pas de marché comptant » et « ce marché n'a pas coté » appellent des suites très
|
|
571
|
+
* différentes.
|
|
572
|
+
*/
|
|
573
|
+
candles(xex: XgateEx, query: ICandlesQuery): Promise<ICandle[]>;
|
|
574
|
+
/**
|
|
575
|
+
* Les bougies comptant d'un même marché chez PLUSIEURS venues, en une liste.
|
|
576
|
+
*
|
|
577
|
+
* Même politique d'échec que partout ailleurs : seule, une venue en échec fait échouer l'appel ;
|
|
578
|
+
* parmi d'autres, elle est journalisée et ignorée. Chaque bougie porte son `xex`.
|
|
579
|
+
*/
|
|
580
|
+
candlesOf(xexes: XgateEx[], query: ICandlesQuery): Promise<ICandle[]>;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* LES PRIX DU **COMPTANT** — binance et bybit.
|
|
585
|
+
*
|
|
586
|
+
* Séparé de `PricesService` comme le catalogue et les bougies le sont : deux marchés, deux
|
|
587
|
+
* services. Ici la raison est encore plus directe qu'ailleurs — **un prix comptant et un prix
|
|
588
|
+
* perpétuel ne sont pas le même nombre**. Le perpétuel porte un funding et s'écarte du comptant ;
|
|
589
|
+
* c'est justement cet écart que certaines stratégies exploitent, et le confondre le rendrait
|
|
590
|
+
* invisible.
|
|
591
|
+
*
|
|
592
|
+
* **La moitié des champs sont `null` au comptant, et c'est correct** : `mark`, `oracle`, `funding`
|
|
593
|
+
* et `openInterest` n'existent que pour un perpétuel. Le comptant renseigne `bid`, `ask`, `last`,
|
|
594
|
+
* `volume24h` — ce qui est mesuré, pas ce qui est dérivé d'un contrat.
|
|
595
|
+
*/
|
|
596
|
+
declare class SpotPricesService {
|
|
597
|
+
private readonly logger;
|
|
598
|
+
/** Les venues dont XGate sert les prix comptant. */
|
|
599
|
+
venues(): readonly XgateEx[];
|
|
600
|
+
/**
|
|
601
|
+
* Les prix comptant d'une ou plusieurs venues, en une seule liste.
|
|
602
|
+
*
|
|
603
|
+
* Même politique d'échec que partout : seule, une venue en échec fait échouer l'appel ; parmi
|
|
604
|
+
* d'autres, elle est journalisée et ignorée. Chaque prix porte son `xex`.
|
|
605
|
+
*/
|
|
606
|
+
prices(...xexes: XgateEx[]): Promise<IPrice[]>;
|
|
607
|
+
/** Les prix comptant d'UNE venue, traduits vers {@link IPrice}. */
|
|
608
|
+
private pricesOf;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* LES BOUGIES DU **COMPTANT** EN TEMPS RÉEL — binance et bybit.
|
|
613
|
+
*
|
|
614
|
+
* Le pendant de `WsCandlesService`, sur l'autre marché. La séparation n'est pas une symétrie
|
|
615
|
+
* décorative : les façades exposent `ws(kind = 'perp')`, donc **un `ws()` nu ouvre un flux de
|
|
616
|
+
* perpétuels**. Un service unique qui aurait oublié de passer le marché aurait diffusé des prix
|
|
617
|
+
* de perpétuel à qui croyait écouter le comptant — deux séries voisines, jamais égales, et rien
|
|
618
|
+
* pour le signaler.
|
|
619
|
+
*
|
|
620
|
+
* Le contrat {@link IXexSpotSource} exige donc `ws('spot')` explicitement, sans valeur par défaut.
|
|
621
|
+
*/
|
|
622
|
+
declare class SpotWsCandlesService {
|
|
623
|
+
private readonly logger;
|
|
624
|
+
/** Les venues dont XGate diffuse le comptant en temps réel. */
|
|
625
|
+
venues(): readonly XgateEx[];
|
|
626
|
+
/**
|
|
627
|
+
* Souscrit aux bougies **comptant** d'un marché. Rend la fonction de désabonnement.
|
|
628
|
+
*
|
|
629
|
+
* Le handler reçoit une bougie à la fois, au format unifié ; la bougie en cours est repoussée à
|
|
630
|
+
* chaque mise à jour tant qu'elle n'est pas close.
|
|
631
|
+
*/
|
|
632
|
+
subscribe(xex: XgateEx, query: {
|
|
633
|
+
symbol: string;
|
|
634
|
+
interval: Timeframe;
|
|
635
|
+
}, handler: (candle: ICandle) => void): Unsubscribe;
|
|
636
|
+
/**
|
|
637
|
+
* Souscrit au MÊME marché comptant chez plusieurs venues, avec un seul handler.
|
|
638
|
+
*
|
|
639
|
+
* Chaque bougie porte son `xex`. La fonction rendue coupe tous les flux d'un coup.
|
|
640
|
+
*/
|
|
641
|
+
subscribeAll(xexes: XgateEx[], query: {
|
|
642
|
+
symbol: string;
|
|
643
|
+
interval: Timeframe;
|
|
644
|
+
}, handler: (candle: ICandle) => void): Unsubscribe;
|
|
645
|
+
}
|
|
646
|
+
|
|
410
647
|
/** Une paire, telle qu'un SDK de venue la rend. */
|
|
411
648
|
interface IXexPair {
|
|
412
649
|
name: string;
|
|
@@ -499,6 +736,18 @@ interface IXexSpotSource {
|
|
|
499
736
|
}): Promise<IXexCandle[]>;
|
|
500
737
|
getPrices?(): Promise<IXexPrice[]>;
|
|
501
738
|
};
|
|
739
|
+
/**
|
|
740
|
+
* Le temps réel du COMPTANT. **`kind` est obligatoire ici**, contrairement aux façades qui le
|
|
741
|
+
* rendent optionnel : leur défaut est `'perp'`, et un `ws()` nu ouvre donc un flux de perpétuels
|
|
742
|
+
* en croyant écouter le comptant — deux marchés dont les prix diffèrent, sans que rien ne le
|
|
743
|
+
* signale.
|
|
744
|
+
*/
|
|
745
|
+
ws(kind: 'spot'): {
|
|
746
|
+
subscribeCandles(query: {
|
|
747
|
+
name: string;
|
|
748
|
+
interval: string;
|
|
749
|
+
}, handler: (candle: IXexCandle) => void): () => void;
|
|
750
|
+
};
|
|
502
751
|
}
|
|
503
752
|
/**
|
|
504
753
|
* De quoi lire UN compte chez une venue.
|
|
@@ -535,7 +784,7 @@ interface IXexAccess {
|
|
|
535
784
|
* Les venues dont XGate sait lire le portefeuille aujourd'hui.
|
|
536
785
|
*
|
|
537
786
|
* Les autres ne sont pas exclues par principe : il leur manque un accès (clé d'API pour bullet, une
|
|
538
|
-
* adresse active pour
|
|
787
|
+
* adresse active pour extended et paradex). Voir le backlog.
|
|
539
788
|
*/
|
|
540
789
|
declare const WALLET_XEXES: readonly XgateEx[];
|
|
541
790
|
/**
|
|
@@ -1104,5 +1353,48 @@ declare function canonicalFromXex(rawSymbol: string, xexId: string): string;
|
|
|
1104
1353
|
* symbole.
|
|
1105
1354
|
*/
|
|
1106
1355
|
declare function canonicalFromBase(base: string): string;
|
|
1356
|
+
/**
|
|
1357
|
+
* LE MULTIPLICATEUR DE COTATION, extrait du nom — **la seule source qui existe**.
|
|
1358
|
+
*
|
|
1359
|
+
* Aucune venue ne le publie : `kPEPE` chez hyperliquid ne porte que `{"marginTableId":52}`,
|
|
1360
|
+
* `1000PEPEUSDT` chez binance ne mentionne aucun facteur. L'information n'est QUE dans le préfixe
|
|
1361
|
+
* du nom, et le canonique la fait disparaître — jusqu'ici sans la conserver nulle part.
|
|
1362
|
+
*
|
|
1363
|
+
* Or elle est indispensable dès qu'on compare des prix entre venues. `SATS` porte **trois échelles
|
|
1364
|
+
* différentes sur quatre sources** : `SATSUSDT` (×1) chez bybit-spot, `1000SATSUSDT` (×1000) chez
|
|
1365
|
+
* binance, `10000SATSUSDT` (×10000) chez bybit. Une médiane calculée sur ces prix bruts ne veut
|
|
1366
|
+
* rien dire ; divisés par leur facteur, ils redeviennent comparables.
|
|
1367
|
+
*
|
|
1368
|
+
* Rend `1` quand le nom ne porte aucune échelle — le cas de l'immense majorité.
|
|
1369
|
+
*/
|
|
1370
|
+
declare function multiplierFromXex(rawSymbol: string): number;
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* LES CONTRATS À ÉCHÉANCE, séparés des perpétuels — parce qu'un future daté ne cote pas le comptant.
|
|
1374
|
+
*
|
|
1375
|
+
* Le catalogue les mélangeait : 44 lignes portaient `kind: 'perp'` alors qu'elles expirent, dont
|
|
1376
|
+
* neuf sur le seul BTC chez bybit. Un consommateur qui prend « le prix du BTC » y ramassait une
|
|
1377
|
+
* échéance de décembre, dont la base au comptant peut s'écarter de plusieurs pour cent.
|
|
1378
|
+
*
|
|
1379
|
+
* **`contractType` fait foi, JAMAIS la date de livraison.** binance publie `deliveryDate:
|
|
1380
|
+
* 4133404800000` — le 1er janvier 2100 — sur ses **perpétuels** : s'y fier marquerait tout le
|
|
1381
|
+
* catalogue comme daté. bybit, lui, met `deliveryTime: '0'` sur les siens. Deux conventions
|
|
1382
|
+
* incompatibles pour dire « ceci n'expire pas », d'où la lecture du type et de lui seul.
|
|
1383
|
+
*/
|
|
1384
|
+
/**
|
|
1385
|
+
* L'ÉCHÉANCE D'UN CONTRAT, ou `undefined` s'il est perpétuel.
|
|
1386
|
+
*
|
|
1387
|
+
* On ne lit la date **que** si le type de contrat annonce une échéance : c'est ce qui neutralise le
|
|
1388
|
+
* `deliveryDate` de l'an 2100 des perpétuels binance. Un type inconnu est traité comme perpétuel —
|
|
1389
|
+
* l'immense majorité des lignes, et se tromper dans ce sens n'invente pas d'échéance.
|
|
1390
|
+
*/
|
|
1391
|
+
declare function expiryOf(xtras?: Record<string, unknown>): Date | undefined;
|
|
1392
|
+
/**
|
|
1393
|
+
* LE CONTRAT EXPIRE-T-IL ? Vrai pour un future daté, faux pour un perpétuel.
|
|
1394
|
+
*
|
|
1395
|
+
* Séparé d'{@link expiryOf} à dessein : une venue peut annoncer un type daté sans publier de date
|
|
1396
|
+
* exploitable, et il faut alors pouvoir écarter la ligne quand même.
|
|
1397
|
+
*/
|
|
1398
|
+
declare function isDated(xtras?: Record<string, unknown>): boolean;
|
|
1107
1399
|
|
|
1108
|
-
export { CandlesService, CatalogService, type Direction, type IBalance, type ICandle, type ICandlesQuery, type IEntryWithProtection, type IEquityPoint, type IMoveStop, type IMovement, type IOrder, type IPair, type IPosition, type IPrice, type IProtection, type IProtectionInput, type IProtectionLeg, type ITrade, type ITradingAccess, type IWalletAccess, type IXexAccess, type IXexSpotSource, type MarketKind, type MovementKind, type MovementStatus, ORDER_STATUSES, type OrderStatus, type OrderType, PricesService, SPOT_XEXES, type Side, SpotCatalogService, TIMEFRAME_MINUTES, type TimeInForce, Timeframe, TradingService, type Unsubscribe, WALLET_XEXES, WalletService, WsCandlesService, XGATE_EXCHANGES, XgateEx, XgateModule, buildLevels, buildProtection, canonicalFromBase, canonicalFromXex, roundPrice, roundToStep, servesNatively, servesSpot, sourceFor, timeframeMs };
|
|
1400
|
+
export { CandlesService, CandlesStreamRegistry, CandlesStreamService, CatalogService, type Direction, type IBalance, type ICandle, type ICandlesQuery, type IEntryWithProtection, type IEquityPoint, type IMoveStop, type IMovement, type IOrder, type IPair, type IPosition, type IPrice, type IProtection, type IProtectionInput, type IProtectionLeg, type ITrade, type ITradingAccess, type IWalletAccess, type IXexAccess, type IXexSpotSource, type MarketKind, type MovementKind, type MovementStatus, ORDER_STATUSES, type OrderStatus, type OrderType, PricesService, SPOT_XEXES, type Side, SpotCandlesService, SpotCatalogService, SpotPricesService, SpotWsCandlesService, TIMEFRAME_MINUTES, type TimeInForce, Timeframe, TradingService, type Unsubscribe, WALLET_XEXES, WS_SUBSCRIPTION_LIMITS, WalletService, WsCandlesService, XGATE_EXCHANGES, XgateEx, XgateModule, buildLevels, buildProtection, canonicalFromBase, canonicalFromXex, expiryOf, isDated, multiplierFromXex, roundPrice, roundToStep, servesNatively, servesSpot, sourceFor, subscriptionLimitOf, timeframeMs };
|