@basedone/core 0.0.6 → 0.0.8
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/dist/index.d.mts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +173 -39
- package/dist/index.mjs +132 -39
- package/dist/staticMeta-D2V74GCG.mjs +23 -0
- package/dist/staticMeta-GM7T3OYL.mjs +23 -0
- package/dist/staticMeta-HRXST42O.mjs +24 -0
- package/dist/staticMeta-OKNVBUQ5.mjs +25 -0
- package/dist/staticMeta-QV2KMX57.mjs +25 -0
- package/dist/staticMeta-QWPQK3MD.mjs +22 -0
- package/lib/meta/data/mainnet/dexs/xyz.json +26 -0
- package/lib/meta/data/mainnet/staticMeta.json +15 -0
- package/lib/meta/data/testnet/staticMeta.json +13 -0
- package/lib/meta/metadata.ts +191 -50
- package/package.json +1 -1
package/lib/meta/metadata.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HttpTransport,
|
|
3
3
|
InfoClient,
|
|
4
|
-
PerpDex,
|
|
5
4
|
PerpsAssetCtx,
|
|
6
5
|
PerpsMeta,
|
|
7
6
|
SpotMeta,
|
|
8
7
|
SpotToken,
|
|
9
8
|
} from "@nktkas/hyperliquid";
|
|
10
9
|
import { isHip3Symbol } from "../hip3/utils";
|
|
10
|
+
import { Hex } from "@nktkas/hyperliquid/script/src/types/mod";
|
|
11
|
+
|
|
12
|
+
export interface PerpDex {
|
|
13
|
+
/** Short name of the perpetual dex. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Complete name of the perpetual dex. */
|
|
16
|
+
fullName: string;
|
|
17
|
+
/** Hex address of the dex deployer. */
|
|
18
|
+
deployer: Hex;
|
|
19
|
+
/** Hex address of the oracle updater, or null if not available. */
|
|
20
|
+
oracleUpdater: Hex | null;
|
|
21
|
+
|
|
22
|
+
feeRecipient: Hex | null;
|
|
23
|
+
assetToStreamingOiCap: [string, string][];
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
/**
|
|
13
27
|
* Market information for trading operations
|
|
@@ -19,6 +33,9 @@ export interface MarketInfo {
|
|
|
19
33
|
type: "perps" | "spot" | "hip3";
|
|
20
34
|
coin: string; // Format used in info endpoint (e.g., "@107") for spot hype, "HYPE" for perps, "dex:coin" for hip3
|
|
21
35
|
|
|
36
|
+
displayName?: string; // Display name for the market
|
|
37
|
+
imageUrl?: string; // Image URL for the market
|
|
38
|
+
|
|
22
39
|
maxLeverage?: number; // For perps only
|
|
23
40
|
|
|
24
41
|
// Spot-specific fields
|
|
@@ -28,6 +45,8 @@ export interface MarketInfo {
|
|
|
28
45
|
// HIP-3 specific fields
|
|
29
46
|
dexName?: string; // DEX name for HIP-3 markets
|
|
30
47
|
dexIndex?: number; // DEX index for asset ID calculation
|
|
48
|
+
dexDisplayName?: string; // Display name override for the DEX
|
|
49
|
+
dexImageUrl?: string; // Image URL override for the DEX
|
|
31
50
|
}
|
|
32
51
|
|
|
33
52
|
export interface DexInfo {
|
|
@@ -37,6 +56,9 @@ export interface DexInfo {
|
|
|
37
56
|
dexName: string; // DEX name for HIP-3 markets
|
|
38
57
|
dexIndex: number; // DEX index for asset ID calculation
|
|
39
58
|
collateralTokenSymbol: string;
|
|
59
|
+
displayName?: string; // Display name override for the DEX
|
|
60
|
+
imageUrl?: string; // Image URL override for the DEX
|
|
61
|
+
accountName?: string; // Account name override for the DEX
|
|
40
62
|
}
|
|
41
63
|
|
|
42
64
|
export type ExtendedPerpsMeta = PerpsMeta & {
|
|
@@ -54,6 +76,25 @@ export interface TokenInfo {
|
|
|
54
76
|
tokenId: string;
|
|
55
77
|
}
|
|
56
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Static metadata structure for display overrides
|
|
81
|
+
*/
|
|
82
|
+
interface StaticMetadata {
|
|
83
|
+
coins?: {
|
|
84
|
+
[symbol: string]: {
|
|
85
|
+
displayName?: string;
|
|
86
|
+
imageUrl?: string;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
dexs?: {
|
|
90
|
+
[dexName: string]: {
|
|
91
|
+
displayName?: string;
|
|
92
|
+
imageUrl?: string;
|
|
93
|
+
accountName?: string;
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
57
98
|
/**
|
|
58
99
|
* Configuration for MetadataClient
|
|
59
100
|
*/
|
|
@@ -84,6 +125,8 @@ interface MetadataClientConfig {
|
|
|
84
125
|
* - Spot: 10000 + index
|
|
85
126
|
* - HIP-3: 100000 + perp_dex_index * 10000 + index_in_meta
|
|
86
127
|
*/
|
|
128
|
+
export const ROOT_DEX = "hyperliquid";
|
|
129
|
+
|
|
87
130
|
export class MetadataClient {
|
|
88
131
|
private infoClient: InfoClient;
|
|
89
132
|
private config: MetadataClientConfig;
|
|
@@ -93,6 +136,7 @@ export class MetadataClient {
|
|
|
93
136
|
private spotMeta: SpotMeta | null = null;
|
|
94
137
|
private perpsMeta: PerpsMeta | null = null;
|
|
95
138
|
private perpDexs: (PerpDex | null)[] = [];
|
|
139
|
+
private staticMeta: StaticMetadata | null = null;
|
|
96
140
|
|
|
97
141
|
// HIP-3 metadata cache
|
|
98
142
|
private hip3DexsMeta: Map<string, DexInfo> = new Map();
|
|
@@ -116,6 +160,7 @@ export class MetadataClient {
|
|
|
116
160
|
|
|
117
161
|
// Lazy init flag
|
|
118
162
|
private initialized: boolean = false;
|
|
163
|
+
private initializing: Promise<void> | null = null;
|
|
119
164
|
|
|
120
165
|
constructor(config: MetadataClientConfig = {}) {
|
|
121
166
|
const transport = new HttpTransport({
|
|
@@ -124,6 +169,7 @@ export class MetadataClient {
|
|
|
124
169
|
this.infoClient = new InfoClient({ transport });
|
|
125
170
|
this.config = {
|
|
126
171
|
...config,
|
|
172
|
+
hip3Dexs: config.hip3Dexs?.filter((dex) => dex !== ROOT_DEX),
|
|
127
173
|
useStaticFallback: config.useStaticFallback ?? true,
|
|
128
174
|
};
|
|
129
175
|
this.isTestnet = config.isTestnet ?? false;
|
|
@@ -135,54 +181,82 @@ export class MetadataClient {
|
|
|
135
181
|
*/
|
|
136
182
|
async initialize(): Promise<void> {
|
|
137
183
|
if (this.initialized) return;
|
|
184
|
+
if (this.initializing) return this.initializing;
|
|
185
|
+
this.initializing = new Promise(async (resolve, reject) => {
|
|
186
|
+
// Always load staticMeta.json regardless of config.useStaticFallback
|
|
187
|
+
await this.loadStaticMetaOverrides();
|
|
138
188
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
189
|
+
if (this.config.onlyUseStaticFallback) {
|
|
190
|
+
await this.loadStaticMetadata();
|
|
191
|
+
this.buildLookupMaps();
|
|
142
192
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
193
|
+
// Fetch HIP-3 metadata if configured
|
|
194
|
+
if (this.config.hip3Dexs && this.config.hip3Dexs.length > 0) {
|
|
195
|
+
await Promise.all(
|
|
196
|
+
this.config.hip3Dexs.map((dex) => this.loadHip3Metadata(dex)),
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
resolve();
|
|
200
|
+
this.initialized = true;
|
|
201
|
+
return;
|
|
148
202
|
}
|
|
149
203
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.infoClient.spotMeta(),
|
|
158
|
-
this.infoClient.meta(),
|
|
159
|
-
this.infoClient.perpDexs(),
|
|
160
|
-
]);
|
|
204
|
+
try {
|
|
205
|
+
// Fetch core metadata from API
|
|
206
|
+
[this.spotMeta, this.perpsMeta, this.perpDexs] = await Promise.all([
|
|
207
|
+
this.infoClient.spotMeta(),
|
|
208
|
+
this.infoClient.meta(),
|
|
209
|
+
this.infoClient.perpDexs() as Promise<PerpDex[] | null[]>,
|
|
210
|
+
]);
|
|
161
211
|
|
|
162
|
-
|
|
163
|
-
|
|
212
|
+
// Build optimized lookup maps
|
|
213
|
+
this.buildLookupMaps();
|
|
164
214
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
215
|
+
// Fetch HIP-3 metadata if configured
|
|
216
|
+
if (this.config.hip3Dexs && this.config.hip3Dexs.length > 0) {
|
|
217
|
+
await Promise.all(
|
|
218
|
+
this.config.hip3Dexs.map((dex) => this.loadHip3Metadata(dex)),
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
this.initialized = true;
|
|
222
|
+
resolve();
|
|
223
|
+
} catch (error) {
|
|
224
|
+
// Fall back to static data if API fetch fails and fallback is enabled
|
|
225
|
+
if (this.config.useStaticFallback) {
|
|
226
|
+
console.warn(
|
|
227
|
+
"Failed to fetch metadata from API, using static fallback data",
|
|
228
|
+
error,
|
|
229
|
+
);
|
|
230
|
+
await this.loadStaticMetadata();
|
|
231
|
+
this.buildLookupMaps();
|
|
232
|
+
this.initialized = true;
|
|
233
|
+
resolve();
|
|
234
|
+
} else {
|
|
235
|
+
reject(error);
|
|
236
|
+
}
|
|
237
|
+
} finally {
|
|
238
|
+
this.initialized = true;
|
|
239
|
+
resolve();
|
|
170
240
|
}
|
|
241
|
+
});
|
|
242
|
+
return this.initializing;
|
|
243
|
+
}
|
|
171
244
|
|
|
172
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Load staticMeta.json for display overrides
|
|
247
|
+
* This is always loaded regardless of config.useStaticFallback
|
|
248
|
+
*/
|
|
249
|
+
private async loadStaticMetaOverrides(): Promise<void> {
|
|
250
|
+
const network = this.isTestnet ? "testnet" : "mainnet";
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
const staticMetaModule = await import(
|
|
254
|
+
`./data/${network}/staticMeta.json`
|
|
255
|
+
);
|
|
256
|
+
this.staticMeta = staticMetaModule.default as StaticMetadata;
|
|
173
257
|
} catch (error) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
console.warn(
|
|
177
|
-
"Failed to fetch metadata from API, using static fallback data",
|
|
178
|
-
error,
|
|
179
|
-
);
|
|
180
|
-
await this.loadStaticMetadata();
|
|
181
|
-
this.buildLookupMaps();
|
|
182
|
-
this.initialized = true;
|
|
183
|
-
} else {
|
|
184
|
-
throw error;
|
|
185
|
-
}
|
|
258
|
+
console.warn(`Failed to load staticMeta.json for ${network}:`, error);
|
|
259
|
+
this.staticMeta = null;
|
|
186
260
|
}
|
|
187
261
|
}
|
|
188
262
|
|
|
@@ -194,16 +268,22 @@ export class MetadataClient {
|
|
|
194
268
|
|
|
195
269
|
try {
|
|
196
270
|
// Dynamic imports for static data
|
|
197
|
-
const [
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
271
|
+
const [
|
|
272
|
+
spotMetaModule,
|
|
273
|
+
perpsMetaModule,
|
|
274
|
+
perpDexsModule,
|
|
275
|
+
staticMetaModule,
|
|
276
|
+
] = await Promise.all([
|
|
277
|
+
import(`./data/${network}/spotMeta.json`),
|
|
278
|
+
import(`./data/${network}/meta.json`),
|
|
279
|
+
import(`./data/${network}/perpDexs.json`),
|
|
280
|
+
import(`./data/${network}/staticMeta.json`),
|
|
281
|
+
]);
|
|
203
282
|
|
|
204
283
|
this.spotMeta = spotMetaModule.default as SpotMeta;
|
|
205
284
|
this.perpsMeta = perpsMetaModule.default as PerpsMeta;
|
|
206
285
|
this.perpDexs = perpDexsModule.default as (PerpDex | null)[];
|
|
286
|
+
this.staticMeta = staticMetaModule.default as StaticMetadata;
|
|
207
287
|
|
|
208
288
|
console.warn(`Using static ${network} metadata`);
|
|
209
289
|
} catch (error) {
|
|
@@ -223,10 +303,16 @@ export class MetadataClient {
|
|
|
223
303
|
this.spotPairToMarket.clear();
|
|
224
304
|
this.baseTokenToMarkets.clear();
|
|
225
305
|
this.coinToMarket.clear();
|
|
226
|
-
this.hip3SymbolToMarket.clear();
|
|
227
306
|
this.dexNameToIndex.clear();
|
|
228
307
|
this.quoteAssets = [];
|
|
229
308
|
|
|
309
|
+
console.info(
|
|
310
|
+
"[MetadataClient] Building lookup maps",
|
|
311
|
+
this.perpDexs,
|
|
312
|
+
this.perpsMeta,
|
|
313
|
+
this.spotMeta,
|
|
314
|
+
);
|
|
315
|
+
|
|
230
316
|
// Build dex name to index map
|
|
231
317
|
if (this.perpDexs) {
|
|
232
318
|
this.perpDexs.forEach((dex, index) => {
|
|
@@ -248,6 +334,17 @@ export class MetadataClient {
|
|
|
248
334
|
maxLeverage: market.maxLeverage,
|
|
249
335
|
};
|
|
250
336
|
|
|
337
|
+
// Apply static metadata overrides for perps
|
|
338
|
+
const staticOverrides = this.staticMeta?.coins?.[market.name];
|
|
339
|
+
if (staticOverrides) {
|
|
340
|
+
if (staticOverrides.displayName) {
|
|
341
|
+
marketInfo.displayName = staticOverrides.displayName;
|
|
342
|
+
}
|
|
343
|
+
if (staticOverrides.imageUrl) {
|
|
344
|
+
marketInfo.imageUrl = staticOverrides.imageUrl;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
251
348
|
// Case-insensitive lookup
|
|
252
349
|
this.perpsSymbolToIndex.set(market.name.toUpperCase(), index);
|
|
253
350
|
|
|
@@ -288,6 +385,17 @@ export class MetadataClient {
|
|
|
288
385
|
quoteToken: quoteToken,
|
|
289
386
|
};
|
|
290
387
|
|
|
388
|
+
// Apply static metadata overrides for spot
|
|
389
|
+
const staticOverrides = this.staticMeta?.coins?.[coin];
|
|
390
|
+
if (staticOverrides) {
|
|
391
|
+
if (staticOverrides.displayName) {
|
|
392
|
+
marketInfo.displayName = staticOverrides.displayName;
|
|
393
|
+
}
|
|
394
|
+
if (staticOverrides.imageUrl) {
|
|
395
|
+
marketInfo.imageUrl = staticOverrides.imageUrl;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
291
399
|
// Store by full pair (case-insensitive)
|
|
292
400
|
const pairKey = `${baseToken.name}/${quoteToken.name}`.toUpperCase();
|
|
293
401
|
this.spotPairToMarket.set(pairKey, marketInfo);
|
|
@@ -347,15 +455,29 @@ export class MetadataClient {
|
|
|
347
455
|
const collateralTokenSymbol =
|
|
348
456
|
spotMetaTokens?.[collateralTokenIndex]?.name ?? "USDC";
|
|
349
457
|
|
|
350
|
-
const dexInfo = {
|
|
458
|
+
const dexInfo: DexInfo = {
|
|
351
459
|
meta,
|
|
352
460
|
assetContext: contexts,
|
|
353
461
|
collateralTokenSymbol,
|
|
354
|
-
dexFullName: dex?.
|
|
462
|
+
dexFullName: dex?.fullName ?? dexName,
|
|
355
463
|
dexName: dex?.name ?? dexName,
|
|
356
464
|
dexIndex: dexIndex,
|
|
357
465
|
};
|
|
358
466
|
|
|
467
|
+
// Apply static metadata overrides for DEX
|
|
468
|
+
const staticDexOverrides = this.staticMeta?.dexs?.[dexName];
|
|
469
|
+
if (staticDexOverrides) {
|
|
470
|
+
if (staticDexOverrides.displayName) {
|
|
471
|
+
dexInfo.displayName = staticDexOverrides.displayName;
|
|
472
|
+
}
|
|
473
|
+
if (staticDexOverrides.imageUrl) {
|
|
474
|
+
dexInfo.imageUrl = staticDexOverrides.imageUrl;
|
|
475
|
+
}
|
|
476
|
+
if (staticDexOverrides.accountName) {
|
|
477
|
+
dexInfo.accountName = staticDexOverrides.accountName;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
359
481
|
this.hip3DexsMeta.set(dexName, dexInfo);
|
|
360
482
|
|
|
361
483
|
// Build HIP-3 market lookups for this DEX
|
|
@@ -374,6 +496,7 @@ export class MetadataClient {
|
|
|
374
496
|
private buildHip3MarketsForDex(dexName: string, dexInfo: DexInfo): void {
|
|
375
497
|
dexInfo.meta.universe.forEach((market, index) => {
|
|
376
498
|
const symbol = market.name;
|
|
499
|
+
|
|
377
500
|
const marketInfo: MarketInfo = {
|
|
378
501
|
coin: symbol,
|
|
379
502
|
symbol,
|
|
@@ -383,8 +506,23 @@ export class MetadataClient {
|
|
|
383
506
|
maxLeverage: market.maxLeverage,
|
|
384
507
|
dexName,
|
|
385
508
|
dexIndex: dexInfo.dexIndex,
|
|
509
|
+
dexDisplayName: dexInfo.displayName,
|
|
510
|
+
dexImageUrl: dexInfo.imageUrl,
|
|
386
511
|
};
|
|
387
512
|
|
|
513
|
+
// Apply static metadata overrides for HIP-3
|
|
514
|
+
const staticOverrides = this.staticMeta?.coins?.[symbol];
|
|
515
|
+
if (staticOverrides) {
|
|
516
|
+
if (staticOverrides.displayName) {
|
|
517
|
+
marketInfo.displayName = staticOverrides.displayName;
|
|
518
|
+
}
|
|
519
|
+
if (staticOverrides.imageUrl) {
|
|
520
|
+
marketInfo.imageUrl = staticOverrides.imageUrl;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
console.info("[MetadataClient] caching market", symbol, marketInfo);
|
|
525
|
+
|
|
388
526
|
this.coinToMarket.set(symbol, marketInfo);
|
|
389
527
|
this.hip3SymbolToMarket.set(symbol, marketInfo);
|
|
390
528
|
});
|
|
@@ -425,7 +563,7 @@ export class MetadataClient {
|
|
|
425
563
|
// If no "/" in symbol, it could be perps or need quote asset
|
|
426
564
|
if (!symbol.includes("/") && !symbol.includes("@")) {
|
|
427
565
|
// Try perps lookup first (O(1))
|
|
428
|
-
const perpsMarket = this.coinToMarket.get(
|
|
566
|
+
const perpsMarket = this.coinToMarket.get(symbol);
|
|
429
567
|
if (perpsMarket?.type === "perps") {
|
|
430
568
|
return perpsMarket;
|
|
431
569
|
}
|
|
@@ -507,6 +645,7 @@ export class MetadataClient {
|
|
|
507
645
|
// Try O(1) lookup first (if DEX metadata already loaded)
|
|
508
646
|
let cachedMarket = this.hip3SymbolToMarket.get(symbol);
|
|
509
647
|
if (cachedMarket) return cachedMarket;
|
|
648
|
+
console.warn("Missing market", symbol, this.hip3SymbolToMarket);
|
|
510
649
|
|
|
511
650
|
// If not found, check if we need to load DEX metadata
|
|
512
651
|
const dexMeta = this.hip3DexsMeta.get(dexName);
|
|
@@ -584,6 +723,8 @@ export class MetadataClient {
|
|
|
584
723
|
perpsMeta: this.perpsMeta,
|
|
585
724
|
perpDexs: this.perpDexs,
|
|
586
725
|
hip3DexsMeta: Object.fromEntries(this.hip3DexsMeta),
|
|
726
|
+
coinToMarket: Object.fromEntries(this.coinToMarket),
|
|
727
|
+
hip3SymbolToMarket: Object.fromEntries(this.hip3SymbolToMarket),
|
|
587
728
|
};
|
|
588
729
|
}
|
|
589
730
|
|