@blackcube/xgate-sdk 0.21.1 → 0.22.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 +72 -5
- package/dist/index.cjs +140 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -2
- package/dist/index.d.ts +101 -2
- package/dist/index.js +138 -3
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -23,10 +23,10 @@ une capacité n'est comptée que si un test réel l'a exercée.
|
|
|
23
23
|
| **hyperliquid** | ✔ | ✔ | ✔ | ✔ **prouvée** |
|
|
24
24
|
| **pacifica** | ✔ | ✔ | ✔ | ✔ **prouvée** |
|
|
25
25
|
| **aster** | ✔ | ✔ | ✔ | ⚠ **à valider** |
|
|
26
|
-
| lighter | ✔ |
|
|
26
|
+
| lighter | ✔ | ✔ *(sans clé)* | — | — |
|
|
27
27
|
| extended | ✔ | — | — | — |
|
|
28
28
|
| paradex | ✔ | — | — | — |
|
|
29
|
-
| bullet | ✔ | — | — | — |
|
|
29
|
+
| bullet | ✔ *(bougies en WS seulement)* | — | — | — |
|
|
30
30
|
| blofin | ✔ | ✔ | ✔ | — |
|
|
31
31
|
| binance | ✔ *(+ comptant)* | — | — | — |
|
|
32
32
|
| bybit | ✔ *(+ comptant)* | — | — | — |
|
|
@@ -41,9 +41,19 @@ sur une ouverture protégée, c'est la position nue que ce paquet existe pour re
|
|
|
41
41
|
`openWithProtection` y **lève** tant que la preuve manque. Tout le reste (positions, ordres,
|
|
42
42
|
historique, clôture) fonctionne. Détail complet dans le backlog.
|
|
43
43
|
|
|
44
|
+
**lighter se lit sans aucune clé.** Sa documentation classe `/account`, `accountsByL1Address` et
|
|
45
|
+
`positions` parmi les routes **sans authentification**, et `/account` accepte « an account's index,
|
|
46
|
+
**or L1 address** » : une adresse suffit, comme sur les autres DEX. Son trading, lui, demanderait
|
|
47
|
+
une clé d'API — aucune n'existe aujourd'hui.
|
|
48
|
+
|
|
49
|
+
**bullet ne sert aucune bougie en REST.** Sa documentation officielle ne comporte aucune section de
|
|
50
|
+
données historiques, et six noms d'endpoint testés répondent tous 404 — son REST existe pourtant
|
|
51
|
+
(`/fapi/v1/depth`, `trades`, `premiumIndex`, `fundingRate`, `ticker/24hr`, `openInterest`). Ses
|
|
52
|
+
bougies passent donc par `WsCandlesService` ; `CandlesService` y lève.
|
|
53
|
+
|
|
44
54
|
**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
|
|
46
|
-
|
|
55
|
+
un accès de compte (clé d'API pour bullet, adresse active pour extended et paradex) ou la partie
|
|
56
|
+
signée n'est pas câblée. Binance et bybit sont volontairement limitées au **public** : leurs
|
|
47
57
|
SDK ne couvrent que catalogue, bougies et prix, et toute route signée y lève.
|
|
48
58
|
|
|
49
59
|
## Les services
|
|
@@ -54,7 +64,8 @@ Chacun est un `@Injectable()` NestJS, utilisable seul ou via `XgateModule`.
|
|
|
54
64
|
|---|---|
|
|
55
65
|
| `CatalogService` | les paires perpétuelles de toutes les venues, normalisées |
|
|
56
66
|
| `SpotCatalogService` | les paires **comptant** — binance et bybit uniquement |
|
|
57
|
-
| `CandlesService` | les bougies REST
|
|
67
|
+
| `CandlesService` | les bougies REST **perpétuelles**, avec agrégation quand la venue ne sert pas l'intervalle |
|
|
68
|
+
| `SpotCandlesService` | les bougies REST **comptant** — binance et bybit |
|
|
58
69
|
| `WsCandlesService` | les bougies en temps réel, un handler pour N venues |
|
|
59
70
|
| `PricesService` | mark, oracle, mid, bid/ask, funding, open interest |
|
|
60
71
|
| `WalletService` | soldes, mouvements, historique d'équité |
|
|
@@ -204,6 +215,58 @@ open · partiallyFilled · filled · canceled · rejected · expired · other
|
|
|
204
215
|
`canceled` prend **un seul L**. Un statut inconnu retombe sur `other` plutôt que de traverser la
|
|
205
216
|
passerelle tel quel : `ORDER_STATUSES` est exporté pour valider plutôt que caster.
|
|
206
217
|
|
|
218
|
+
## Comptant et perpétuel ne se mélangent pas
|
|
219
|
+
|
|
220
|
+
Deux services, jamais un drapeau : `CandlesService` sert le perpétuel, `SpotCandlesService` le
|
|
221
|
+
comptant.
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
await spotCandles.candles(XgateEx.Binance, { symbol: 'BTCUSDT', interval: '1h', limit: 100 });
|
|
225
|
+
await spotCandles.candlesOf([XgateEx.Binance, XgateEx.Bybit], { symbol: 'BTCUSDT', interval: '1h' });
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Ce n'est pas de la coquetterie d'API : **les échelles de cotation diffèrent entre les deux
|
|
229
|
+
marchés**. `SATSUSDT` au comptant chez bybit cote ×1 quand son perpétuel cote ×10000 — mélanger les
|
|
230
|
+
deux séries fabrique un graphe qui saute d'un facteur 10 000. Une venue sans comptant lève.
|
|
231
|
+
|
|
232
|
+
## La semaine s'ouvre le lundi, partout
|
|
233
|
+
|
|
234
|
+
`hyperliquid` sert des bougies `1w` **alignées sur jeudi** (elle aligne ses seaux sur l'epoch Unix,
|
|
235
|
+
qui tombe un jeudi), là où binance et pacifica ouvrent le lundi. XGate ne les prend donc pas : il
|
|
236
|
+
**reconstruit sa semaine depuis le journalier**, et les bougies rendues portent `derived: true`.
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
hyperliquid lun 2026-06-01* lun 2026-06-08* lun 2026-06-15* ← reconstruites
|
|
240
|
+
binance lun 2026-06-01 lun 2026-06-08 lun 2026-06-15 ← natives
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Sans cela, deux séries portant le même intervalle `1w` couvriraient des jours différents et se
|
|
244
|
+
compareraient silencieusement.
|
|
245
|
+
|
|
246
|
+
## Le catalogue : deux pièges que les venues ne signalent pas
|
|
247
|
+
|
|
248
|
+
**Le multiplicateur de cotation.** Aucune venue ne le publie — il n'existe que dans le préfixe du
|
|
249
|
+
nom, que le canonique fait disparaître. `IPair.multiplier` le conserve :
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
SATS binance:1000SATSUSDT = ×1000 bybit:10000SATSUSDT = ×10000 bybit-spot:SATSUSDT = ×1
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Trois échelles pour le même actif sur trois sources. **Une médiane calculée sur ces prix bruts ne
|
|
256
|
+
veut rien dire** ; divisés par `multiplier`, ils redeviennent comparables. 98 lignes du catalogue
|
|
257
|
+
sont concernées.
|
|
258
|
+
|
|
259
|
+
**Les contrats à échéance.** 44 lignes portent `kind: 'perp'` alors qu'elles expirent, dont neuf
|
|
260
|
+
sur le seul BTC chez bybit. `IPair.expiresAt` les distingue — `undefined` pour un perpétuel.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
pairs.filter((pair) => pair.expiresAt === undefined); // les vrais perpétuels
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
L'échéance est dérivée du **type de contrat**, jamais de la date de livraison : binance publie
|
|
267
|
+
`deliveryDate: 4133404800000` — le 1ᵉʳ janvier 2100 — sur **tous** ses perpétuels. S'y fier
|
|
268
|
+
marquerait le catalogue entier comme daté.
|
|
269
|
+
|
|
207
270
|
## Les conventions qui traversent tout
|
|
208
271
|
|
|
209
272
|
- **Une bougie inclut sa dernière milliseconde** : 10:00:00.000 → 10:59:59.999. `closedAt` se
|
|
@@ -214,6 +277,10 @@ passerelle tel quel : `ORDER_STATUSES` est exporté pour valider plutôt que cas
|
|
|
214
277
|
compte.
|
|
215
278
|
- **Une taille de position est toujours positive** : le sens est porté par `side`.
|
|
216
279
|
- **Pas de mensuel.** Les intervalles s'arrêtent à `1w`.
|
|
280
|
+
- **Le suffixe d'un symbole n'est pas sa cotation.** bybit nomme ses perpétuels USDC avec `PERP`
|
|
281
|
+
(`1000BONKPERP` → `BONK`/`USDC`), binance suffixe ses trimestriels par leur date
|
|
282
|
+
(`BTCUSDT_260925`). XGate lit ce que la venue **déclare** (`baseAsset`, `baseCoin`) plutôt que de
|
|
283
|
+
re-parser le nom.
|
|
217
284
|
|
|
218
285
|
## Versions
|
|
219
286
|
|
package/dist/index.cjs
CHANGED
|
@@ -150,6 +150,8 @@ function sum(left, right) {
|
|
|
150
150
|
var CONCAT_QUOTE_XEXS = /* @__PURE__ */ new Set(["aster", "binance", "bybit"]);
|
|
151
151
|
var K_MULTIPLIER = /^k(?=[A-Z])/u;
|
|
152
152
|
var NUMERIC_MULTIPLIER = /^10{3,}(?=[A-Z0-9])/u;
|
|
153
|
+
var ABBREV_MULTIPLIER = /^1([MK])(?=[A-Z]{2,})/u;
|
|
154
|
+
var ABBREV_FACTOR = { M: 1e6, K: 1e3 };
|
|
153
155
|
var STOCK_24_5 = /_24_5$/u;
|
|
154
156
|
var TICKER_ALIASES = {
|
|
155
157
|
GOOG: "GOOGL",
|
|
@@ -174,13 +176,26 @@ function canonicalFromXex(rawSymbol, xexId) {
|
|
|
174
176
|
s = s.replace(/-USD-PERP$/u, "").replace(/-PERP$/u, "").replace(/-USDT$/u, "").replace(/-USDC$/u, "").replace(/-USD$/u, "");
|
|
175
177
|
}
|
|
176
178
|
s = s.replace(NUMERIC_MULTIPLIER, "");
|
|
179
|
+
s = s.replace(ABBREV_MULTIPLIER, "");
|
|
177
180
|
s = s.replace(STOCK_24_5, "");
|
|
178
181
|
return TICKER_ALIASES[s] ?? s;
|
|
179
182
|
}
|
|
180
183
|
function canonicalFromBase(base) {
|
|
181
|
-
const s = base.replace(K_MULTIPLIER, "").toUpperCase().replace(NUMERIC_MULTIPLIER, "").replace(STOCK_24_5, "");
|
|
184
|
+
const s = base.replace(K_MULTIPLIER, "").toUpperCase().replace(NUMERIC_MULTIPLIER, "").replace(ABBREV_MULTIPLIER, "").replace(STOCK_24_5, "");
|
|
182
185
|
return TICKER_ALIASES[s] ?? s;
|
|
183
186
|
}
|
|
187
|
+
function multiplierFromXex(rawSymbol) {
|
|
188
|
+
if (K_MULTIPLIER.test(rawSymbol)) {
|
|
189
|
+
return 1e3;
|
|
190
|
+
}
|
|
191
|
+
const upper = rawSymbol.toUpperCase();
|
|
192
|
+
const abbrev = ABBREV_MULTIPLIER.exec(upper);
|
|
193
|
+
if (abbrev !== null) {
|
|
194
|
+
return ABBREV_FACTOR[abbrev[1]] ?? 1;
|
|
195
|
+
}
|
|
196
|
+
const zeros = NUMERIC_MULTIPLIER.exec(upper);
|
|
197
|
+
return zeros === null ? 1 : Number(zeros[0]);
|
|
198
|
+
}
|
|
184
199
|
|
|
185
200
|
// src/helpers/candle-mapper.ts
|
|
186
201
|
function toCandle(wire, xex, interval, quote) {
|
|
@@ -265,6 +280,19 @@ function createAccountXex(xex, access) {
|
|
|
265
280
|
},
|
|
266
281
|
{ default: "a" }
|
|
267
282
|
);
|
|
283
|
+
case "lighter" /* Lighter */:
|
|
284
|
+
return new lighterSdk.Lighter(
|
|
285
|
+
{
|
|
286
|
+
a: {
|
|
287
|
+
apiPrivateKey: access.privateKey ?? NULL_KEY,
|
|
288
|
+
apiKeyIndex: access.apiKeyIndex ?? 0,
|
|
289
|
+
accountIndex: access.accountIndex ?? 0,
|
|
290
|
+
l1Address: adresse(),
|
|
291
|
+
network: access.network ?? "mainnet"
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
{ default: "a" }
|
|
295
|
+
);
|
|
268
296
|
case "aster" /* Aster */:
|
|
269
297
|
if (access.privateKey === void 0 || access.privateKey === "") {
|
|
270
298
|
throw new Error(
|
|
@@ -305,6 +333,7 @@ var WALLET_XEXES = [
|
|
|
305
333
|
"hyperliquid" /* Hyperliquid */,
|
|
306
334
|
"pacifica" /* Pacifica */,
|
|
307
335
|
"aster" /* Aster */,
|
|
336
|
+
"lighter" /* Lighter */,
|
|
308
337
|
"blofin" /* Blofin */
|
|
309
338
|
];
|
|
310
339
|
function createPublicXex(xex) {
|
|
@@ -349,8 +378,11 @@ function createPublicSpotXex(xex) {
|
|
|
349
378
|
}
|
|
350
379
|
|
|
351
380
|
// src/helpers/xex-timeframes.ts
|
|
381
|
+
var HYPERLIQUID_NATIVE = Object.values(Timeframe).filter(
|
|
382
|
+
(interval) => interval !== "1w" /* W */
|
|
383
|
+
);
|
|
352
384
|
var NATIVE = {
|
|
353
|
-
["hyperliquid" /* Hyperliquid */]:
|
|
385
|
+
["hyperliquid" /* Hyperliquid */]: HYPERLIQUID_NATIVE,
|
|
354
386
|
["pacifica" /* Pacifica */]: Object.values(Timeframe),
|
|
355
387
|
["aster" /* Aster */]: Object.values(Timeframe),
|
|
356
388
|
["blofin" /* Blofin */]: Object.values(Timeframe),
|
|
@@ -478,6 +510,43 @@ exports.CandlesService = class CandlesService {
|
|
|
478
510
|
exports.CandlesService = __decorateClass([
|
|
479
511
|
common.Injectable()
|
|
480
512
|
], exports.CandlesService);
|
|
513
|
+
|
|
514
|
+
// src/helpers/contract-expiry.ts
|
|
515
|
+
var DATED_CONTRACT_TYPES = /* @__PURE__ */ new Set([
|
|
516
|
+
// binance : les trimestriels (`BTCUSDT_260925`, `ETHUSDT_261225`).
|
|
517
|
+
"CURRENT_QUARTER",
|
|
518
|
+
"NEXT_QUARTER",
|
|
519
|
+
"CURRENT_QUARTER_DELIVERING",
|
|
520
|
+
"NEXT_QUARTER_DELIVERING",
|
|
521
|
+
"PERPETUAL_DELIVERING",
|
|
522
|
+
// bybit : les datés (`BTCUSDT-25DEC26`), face à `LinearPerpetual`.
|
|
523
|
+
"LinearFutures",
|
|
524
|
+
"InverseFutures"
|
|
525
|
+
]);
|
|
526
|
+
var EXPIRY_FIELDS = ["deliveryTime", "deliveryDate", "expiryTime", "settleTime"];
|
|
527
|
+
function expiryOf(xtras) {
|
|
528
|
+
if (xtras === void 0) {
|
|
529
|
+
return void 0;
|
|
530
|
+
}
|
|
531
|
+
const type = xtras.contractType;
|
|
532
|
+
if (typeof type !== "string" || DATED_CONTRACT_TYPES.has(type) === false) {
|
|
533
|
+
return void 0;
|
|
534
|
+
}
|
|
535
|
+
for (const field of EXPIRY_FIELDS) {
|
|
536
|
+
const brut = xtras[field];
|
|
537
|
+
const ms = typeof brut === "string" ? Number(brut) : brut;
|
|
538
|
+
if (typeof ms === "number" && Number.isFinite(ms) === true && ms > 0) {
|
|
539
|
+
return new Date(ms);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return void 0;
|
|
543
|
+
}
|
|
544
|
+
function isDated(xtras) {
|
|
545
|
+
const type = xtras?.contractType;
|
|
546
|
+
return typeof type === "string" && DATED_CONTRACT_TYPES.has(type);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// src/services/catalog.service.ts
|
|
481
550
|
var NAMES_ITS_BASE = /* @__PURE__ */ new Set(["binance" /* Binance */, "bybit" /* Bybit */]);
|
|
482
551
|
exports.CatalogService = class CatalogService {
|
|
483
552
|
logger = new common.Logger(exports.CatalogService.name);
|
|
@@ -523,6 +592,8 @@ exports.CatalogService = class CatalogService {
|
|
|
523
592
|
symbolXex: pair.name,
|
|
524
593
|
xex,
|
|
525
594
|
kind: pair.kind,
|
|
595
|
+
multiplier: multiplierFromXex(pair.name),
|
|
596
|
+
expiresAt: expiryOf(pair.xtras),
|
|
526
597
|
ref: pair.ref ?? null,
|
|
527
598
|
szDecimals: pair.szDecimals,
|
|
528
599
|
tickSize: pair.tickSize,
|
|
@@ -597,6 +668,65 @@ exports.PricesService = class PricesService {
|
|
|
597
668
|
exports.PricesService = __decorateClass([
|
|
598
669
|
common.Injectable()
|
|
599
670
|
], exports.PricesService);
|
|
671
|
+
exports.SpotCandlesService = class SpotCandlesService {
|
|
672
|
+
logger = new common.Logger(exports.SpotCandlesService.name);
|
|
673
|
+
/** Les venues dont XGate sert le comptant. */
|
|
674
|
+
venues() {
|
|
675
|
+
return SPOT_XEXES;
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Les bougies comptant d'une venue, sur une plage de **dates**.
|
|
679
|
+
*
|
|
680
|
+
* **Lève** si la venue ne sert pas de comptant, plutôt que de rendre une liste vide : « cette
|
|
681
|
+
* venue n'a pas de marché comptant » et « ce marché n'a pas coté » appellent des suites très
|
|
682
|
+
* différentes.
|
|
683
|
+
*/
|
|
684
|
+
async candles(xex, query) {
|
|
685
|
+
if (servesSpot(xex) === false) {
|
|
686
|
+
throw new Error(
|
|
687
|
+
`spotCandles(${xex}) : cette venue ne sert pas de comptant. Disponibles : ${SPOT_XEXES.join(", ")}.`
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
const spot = createPublicSpotXex(xex).spot();
|
|
691
|
+
if (spot.getCandles === void 0) {
|
|
692
|
+
throw new Error(`spotCandles(${xex}) : cette venue ne sert pas de bougies comptant en REST.`);
|
|
693
|
+
}
|
|
694
|
+
const wires = await spot.getCandles(toXexQuery(query));
|
|
695
|
+
return wires.map((wire) => toCandle(wire, xex, query.interval, ""));
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Les bougies comptant d'un même marché chez PLUSIEURS venues, en une liste.
|
|
699
|
+
*
|
|
700
|
+
* Même politique d'échec que partout ailleurs : seule, une venue en échec fait échouer l'appel ;
|
|
701
|
+
* parmi d'autres, elle est journalisée et ignorée. Chaque bougie porte son `xex`.
|
|
702
|
+
*/
|
|
703
|
+
async candlesOf(xexes, query) {
|
|
704
|
+
if (xexes.length === 0) {
|
|
705
|
+
throw new Error("spotCandlesOf() : aucune venue demand\xE9e \u2014 pr\xE9cise au moins un XgateEx.");
|
|
706
|
+
}
|
|
707
|
+
const solo = xexes.length === 1;
|
|
708
|
+
const collected = await Promise.all(
|
|
709
|
+
xexes.map(async (xex) => {
|
|
710
|
+
try {
|
|
711
|
+
return await this.candles(xex, query);
|
|
712
|
+
} catch (error) {
|
|
713
|
+
if (solo === true) {
|
|
714
|
+
throw error;
|
|
715
|
+
}
|
|
716
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
717
|
+
this.logger.error(
|
|
718
|
+
`spotCandles(${xex}, ${query.interval}) a \xE9chou\xE9, venue ignor\xE9e : ${message}`
|
|
719
|
+
);
|
|
720
|
+
return [];
|
|
721
|
+
}
|
|
722
|
+
})
|
|
723
|
+
);
|
|
724
|
+
return collected.flat();
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
exports.SpotCandlesService = __decorateClass([
|
|
728
|
+
common.Injectable()
|
|
729
|
+
], exports.SpotCandlesService);
|
|
600
730
|
exports.SpotCatalogService = class SpotCatalogService {
|
|
601
731
|
logger = new common.Logger(exports.SpotCatalogService.name);
|
|
602
732
|
/** Les venues dont XGate sert le comptant. */
|
|
@@ -648,6 +778,9 @@ exports.SpotCatalogService = class SpotCatalogService {
|
|
|
648
778
|
symbolXex: pair.name,
|
|
649
779
|
xex,
|
|
650
780
|
kind: pair.kind,
|
|
781
|
+
// Le comptant porte les mêmes échelles que le perp : `SATSUSDT` (×1) et `1000SATSUSDT`
|
|
782
|
+
// coexistent, et c'est justement entre eux que la comparaison serait fausse.
|
|
783
|
+
multiplier: multiplierFromXex(pair.name),
|
|
651
784
|
ref: pair.ref ?? null,
|
|
652
785
|
szDecimals: pair.szDecimals,
|
|
653
786
|
tickSize: pair.tickSize,
|
|
@@ -1212,6 +1345,7 @@ exports.XgateModule = __decorateClass([
|
|
|
1212
1345
|
exports.WsCandlesService,
|
|
1213
1346
|
exports.PricesService,
|
|
1214
1347
|
exports.SpotCatalogService,
|
|
1348
|
+
exports.SpotCandlesService,
|
|
1215
1349
|
exports.WalletService
|
|
1216
1350
|
],
|
|
1217
1351
|
exports: [
|
|
@@ -1220,6 +1354,7 @@ exports.XgateModule = __decorateClass([
|
|
|
1220
1354
|
exports.WsCandlesService,
|
|
1221
1355
|
exports.PricesService,
|
|
1222
1356
|
exports.SpotCatalogService,
|
|
1357
|
+
exports.SpotCandlesService,
|
|
1223
1358
|
exports.WalletService
|
|
1224
1359
|
]
|
|
1225
1360
|
})
|
|
@@ -1236,6 +1371,9 @@ exports.buildLevels = buildLevels;
|
|
|
1236
1371
|
exports.buildProtection = buildProtection;
|
|
1237
1372
|
exports.canonicalFromBase = canonicalFromBase;
|
|
1238
1373
|
exports.canonicalFromXex = canonicalFromXex;
|
|
1374
|
+
exports.expiryOf = expiryOf;
|
|
1375
|
+
exports.isDated = isDated;
|
|
1376
|
+
exports.multiplierFromXex = multiplierFromXex;
|
|
1239
1377
|
exports.roundPrice = roundPrice;
|
|
1240
1378
|
exports.roundToStep = roundToStep;
|
|
1241
1379
|
exports.servesNatively = servesNatively;
|