@blackcube/xgate-sdk 0.20.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/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Blackcube
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @blackcube/xgate-sdk
2
+
3
+ La passerelle NestJS qui unifie les dix SDK d'exchange Blackcube derrière **une seule surface** :
4
+ un catalogue, des bougies, des prix, un portefeuille et du trading — quelle que soit la venue.
5
+
6
+ > **SDK communautaire / non officiel.** Non affilié aux exchanges couverts. Usage à vos risques.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pnpm add @blackcube/xgate-sdk
12
+ ```
13
+
14
+ Node.js ≥ 22. Les SDK de venue sont des dépendances : on n'en installe aucun séparément.
15
+
16
+ ## Ce que XGate gère, venue par venue
17
+
18
+ Trois niveaux, et ils ne se valent pas. **Le tableau dit ce qui est PROUVÉ, pas ce qui est écrit** :
19
+ une capacité n'est comptée que si un test réel l'a exercée.
20
+
21
+ | Venue | Catalogue · bougies · prix | Portefeuille | Trading | Ouverture protégée |
22
+ |---|:---:|:---:|:---:|:---:|
23
+ | **hyperliquid** | ✔ | ✔ | ✔ | ✔ **prouvée** |
24
+ | **pacifica** | ✔ | ✔ | ✔ | ✔ **prouvée** |
25
+ | **aster** | ✔ | ✔ | ✔ | ⚠ **à valider** |
26
+ | lighter | ✔ | — | — | — |
27
+ | extended | ✔ | — | — | — |
28
+ | paradex | ✔ | — | — | — |
29
+ | bullet | ✔ | — | — | — |
30
+ | blofin | ✔ | ✔ | ✔ | — |
31
+ | binance | ✔ *(+ comptant)* | — | — | — |
32
+ | bybit | ✔ *(+ comptant)* | — | — | — |
33
+
34
+ **hyperliquid et pacifica sont complètes et prouvées.** Le cycle entier — ouvrir avec stop, lire la
35
+ position, refermer sans reliquat — tourne sur leur testnet à chaque exécution de la suite de tests.
36
+
37
+ **aster est complète mais non validée**, et le refus est délibéré. Son `/fapi/v3/batchOrders` coupe
38
+ à ~3,26 s en répondant « The request has timed out. » *alors que la venue a déjà créé une partie des
39
+ ordres* : deux exécutions identiques ont produit deux sous-ensembles différents. Un statut inconnu
40
+ sur une ouverture protégée, c'est la position nue que ce paquet existe pour rendre impossible — donc
41
+ `openWithProtection` y **lève** tant que la preuve manque. Tout le reste (positions, ordres,
42
+ historique, clôture) fonctionne. Détail complet dans le backlog.
43
+
44
+ **Les autres sont en lecture.** Elles servent le catalogue, les bougies et les prix ; il leur manque
45
+ un accès de compte (clé d'API pour bullet, adresse active pour lighter, extended et paradex) ou la
46
+ partie signée n'est pas câblée. Binance et bybit sont volontairement limitées au **public** : leurs
47
+ SDK ne couvrent que catalogue, bougies et prix, et toute route signée y lève.
48
+
49
+ ## Les services
50
+
51
+ Chacun est un `@Injectable()` NestJS, utilisable seul ou via `XgateModule`.
52
+
53
+ | Service | Ce qu'il rend |
54
+ |---|---|
55
+ | `CatalogService` | les paires perpétuelles de toutes les venues, normalisées |
56
+ | `SpotCatalogService` | les paires **comptant** — binance et bybit uniquement |
57
+ | `CandlesService` | les bougies REST, avec agrégation quand la venue ne sert pas l'intervalle |
58
+ | `WsCandlesService` | les bougies en temps réel, un handler pour N venues |
59
+ | `PricesService` | mark, oracle, mid, bid/ask, funding, open interest |
60
+ | `WalletService` | soldes, mouvements, historique d'équité |
61
+ | `TradingService` | positions, ordres, exécutions, ouverture protégée, clôture |
62
+
63
+ ## Le trading
64
+
65
+ **Jamais un ordre sans stop.** `openWithProtection` est la seule façon d'ouvrir une position, et
66
+ elle exige un `slPct`. La protection part **avec** l'entrée, en un geste que la venue traite
67
+ atomiquement : si l'entrée ne remplit pas, la protection ne naît jamais.
68
+
69
+ **L'appelant donne des pourcentages, jamais des prix.** XGate calcule les niveaux depuis le prix
70
+ d'entrée, les arrondit à la grille de la paire, et garantit qu'au-delà de 80 % de parts cumulées la
71
+ position ferme entièrement — sans reliquat de 0,01 qui traîne.
72
+
73
+ ```typescript
74
+ import { TradingService, XgateEx } from '@blackcube/xgate-sdk';
75
+
76
+ const trading = new TradingService();
77
+ const access = {
78
+ xex: XgateEx.Hyperliquid,
79
+ address: '0x…',
80
+ privateKey: '0x…',
81
+ network: 'testnet' as const,
82
+ };
83
+
84
+ const orders = await trading.openWithProtection(access, {
85
+ xex: XgateEx.Hyperliquid,
86
+ symbolXex: 'ETH',
87
+ direction: 'long',
88
+ size: 0.02,
89
+ entry: 3120,
90
+ slPct: 0.02, // stop à 2 % sous l'entrée
91
+ tps: [{ pct: 0.03, part: 0.5 }, // 50 % à +3 %
92
+ { pct: 0.06, part: 0.5 }], // 50 % à +6 % → somme 100 %, clôture intégrale
93
+ tif: 'ioc',
94
+ });
95
+ ```
96
+
97
+ Le premier ordre rendu est l'entrée ; les suivants sont le stop et les take-profits.
98
+
99
+ ### Fermer
100
+
101
+ `closePosition` relit la position **sur la venue** avant de la fermer, et sort la taille que la venue
102
+ déclare — jamais celle qu'on avait prévue. Fermer la taille planifiée laisse un reliquat dès que le
103
+ fill a différé du plan, et ce reliquat reste ouvert, sans stop.
104
+
105
+ ```typescript
106
+ await trading.closePosition(access, 'ETH'); // null s'il n'y avait rien à fermer
107
+ ```
108
+
109
+ ### Le réseau est explicite
110
+
111
+ `network` vaut `mainnet` par défaut. **Le préciser est la seule chose qui sépare un test d'un ordre
112
+ réel** : sur les venues à testnet, `network: 'testnet'` fait tout basculer, signature comprise.
113
+
114
+ Le vocabulaire est le même partout — `mainnet` / `testnet` — y compris chez blofin, qui appelle le
115
+ second « demo trading ». Une clé de démo envoyée au mainnet fait répondre « Access key does not
116
+ exist » : le message accuse la clé alors que c'est l'adresse qui est fausse.
117
+
118
+ ## Les statuts d'ordre
119
+
120
+ Sept valeurs, **identiques à celles des SDK de venue**, orthographe comprise :
121
+
122
+ ```
123
+ open · partiallyFilled · filled · canceled · rejected · expired · other
124
+ ```
125
+
126
+ `canceled` prend **un seul L**. Un statut inconnu retombe sur `other` plutôt que de traverser la
127
+ passerelle tel quel : `ORDER_STATUSES` est exporté pour valider plutôt que caster.
128
+
129
+ ## Les conventions qui traversent tout
130
+
131
+ - **Une bougie inclut sa dernière milliseconde** : 10:00:00.000 → 10:59:59.999. `closedAt` se
132
+ **calcule**, il ne se recopie jamais du wire.
133
+ - **Aucun `time: number`** : chaque date dit ce qu'elle date — `openedAt`, `closedAt`, `quotedAt`,
134
+ `occurredAt`, `measuredAt`, `placedAt`, `filledAt`.
135
+ - **Les montants sont des chaînes.** Un `number` sur un prix de BTC perd des décimales là où ça
136
+ compte.
137
+ - **Une taille de position est toujours positive** : le sens est porté par `side`.
138
+ - **Pas de mensuel.** Les intervalles s'arrêtent à `1w`.
139
+
140
+ ## Documentation
141
+
142
+ Le détail par service vit dans les docblocks — ils portent le *pourquoi*, pas la paraphrase du code.