@basedone/core 0.0.1 → 0.0.6

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.
Files changed (47) hide show
  1. package/dist/chunk-4UEJOM6W.mjs +9 -0
  2. package/dist/index.d.mts +462 -0
  3. package/dist/index.d.ts +462 -2
  4. package/dist/index.js +37465 -2
  5. package/dist/index.mjs +1027 -0
  6. package/dist/lib/cloid.d.ts.map +1 -1
  7. package/dist/lib/cloid.js +11 -1
  8. package/dist/lib/cloid.js.map +1 -1
  9. package/dist/meta-52Q5UUQ4.mjs +1474 -0
  10. package/dist/meta-FTWJX4LV.mjs +1445 -0
  11. package/dist/meta-IKWYLG3Q.mjs +1316 -0
  12. package/dist/meta-UUXKK7IB.mjs +1355 -0
  13. package/dist/perpDexs-PSE3LEVV.mjs +9 -0
  14. package/dist/perpDexs-S3TK25EU.mjs +17 -0
  15. package/dist/perpDexs-TZIQ57IW.mjs +537 -0
  16. package/dist/perpDexs-YNEAJ3R5.mjs +7 -0
  17. package/dist/perpDexs-YS3QQSHW.mjs +338 -0
  18. package/dist/spotMeta-7IJT3W6H.mjs +6442 -0
  19. package/dist/spotMeta-LEO5QFNS.mjs +26392 -0
  20. package/dist/spotMeta-MC5UYLQ7.mjs +6335 -0
  21. package/dist/spotMeta-TXJWYTKI.mjs +26403 -0
  22. package/dist/spotMeta-VAANYV77.mjs +6346 -0
  23. package/dist/spotMeta-ZVBZNUUE.mjs +26559 -0
  24. package/index.ts +6 -0
  25. package/lib/cloid/README.md +233 -0
  26. package/lib/cloid/cloid.ts +368 -0
  27. package/lib/cloid/encoder.ts +60 -0
  28. package/lib/constants/fee.ts +2 -0
  29. package/lib/constants/tokens.ts +28 -0
  30. package/lib/fee.ts +105 -0
  31. package/lib/hip3/market-info.ts +25 -0
  32. package/lib/hip3/utils.ts +9 -0
  33. package/lib/meta/README.md +471 -0
  34. package/lib/meta/data/mainnet/meta.json +1462 -0
  35. package/lib/meta/data/mainnet/perpDexs.json +11 -0
  36. package/lib/meta/data/mainnet/spotMeta.json +6432 -0
  37. package/lib/meta/data/testnet/dexs/rrrrr.json +33 -0
  38. package/lib/meta/data/testnet/meta.json +1343 -0
  39. package/lib/meta/data/testnet/perpDexs.json +531 -0
  40. package/lib/meta/data/testnet/spotMeta.json +26547 -0
  41. package/lib/meta/metadata.ts +600 -0
  42. package/lib/pup/calculator.ts +221 -0
  43. package/lib/pup/index.ts +9 -0
  44. package/lib/pup/types.ts +94 -0
  45. package/lib/utils/formatter.ts +97 -0
  46. package/package.json +21 -17
  47. package/readme.md +0 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1027 @@
1
+ import {
2
+ __glob
3
+ } from "./chunk-4UEJOM6W.mjs";
4
+
5
+ // lib/cloid/encoder.ts
6
+ var mask = (bits) => (1n << bits) - 1n;
7
+ function getEncodingLength(nbits, alphabet) {
8
+ return Math.floor(Number(nbits) / Math.log2(Number(alphabet.length)));
9
+ }
10
+ function encodeValue(value, nbits, alphabet) {
11
+ const encodingLength = getEncodingLength(nbits, alphabet);
12
+ if (value.length > encodingLength) {
13
+ value = value.slice(0, encodingLength);
14
+ }
15
+ if (value.length < encodingLength) {
16
+ value = value.padEnd(encodingLength, alphabet[alphabet.length - 1]);
17
+ }
18
+ const base = BigInt(alphabet.length);
19
+ let encoded = 0n;
20
+ for (const ch of value) {
21
+ const idx = alphabet.indexOf(ch);
22
+ if (idx === -1) throw new Error(`Invalid slug character: ${ch}`);
23
+ encoded = encoded * base + BigInt(idx);
24
+ }
25
+ if (encoded > Number(mask(nbits))) {
26
+ throw new Error(`Encoded value exceeds ${nbits} bits`);
27
+ }
28
+ return encoded;
29
+ }
30
+ function decodeValue(value, nbits, alphabet) {
31
+ if (value < 0 || value > Number(mask(nbits))) {
32
+ throw new Error(`Slug value out of range (must fit in ${nbits} bits)`);
33
+ }
34
+ const base = BigInt(alphabet.length);
35
+ let decoded = "";
36
+ for (let i = 0; i < getEncodingLength(nbits, alphabet); i++) {
37
+ const idx = value % base;
38
+ decoded = alphabet[Number(idx)] + decoded;
39
+ value = value / base;
40
+ }
41
+ return decoded.trim();
42
+ }
43
+
44
+ // lib/cloid/cloid.ts
45
+ var LEGACY_CLOID = "0x62baee7262baee7262baee7262baee72";
46
+ var BASED_VERSION = 1;
47
+ var DEFAULT_TENANT_CODE = "BASED";
48
+ var DEFAULT_OID = 0xba5ed10000ba5ed1n;
49
+ var BASED_HEX_PREFIX = 12213969;
50
+ var BASED_HEX_PREFIX_STR = "0xba5ed1";
51
+ var PREFIX_BITS = 24n;
52
+ var VERSION_BITS = 4n;
53
+ var SLUG_BITS = 26n;
54
+ var CLIENT_BITS = 5n;
55
+ var IS_MINI_APP_BITS = 1n;
56
+ var MINI_APP_TRIGGERED_BITS = 1n;
57
+ var WIDGET_TYPE_BITS = 3n;
58
+ var OID_BITS = 64n;
59
+ var TOTAL_BITS = 128n;
60
+ var SLUG_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
61
+ var OID_ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789|_- ";
62
+ var mask2 = (bits) => (1n << bits) - 1n;
63
+ function encodeSlug(slug) {
64
+ if (!slug) slug = DEFAULT_TENANT_CODE;
65
+ return encodeValue(slug, SLUG_BITS, SLUG_ALPHABET);
66
+ }
67
+ function decodeSlug(value) {
68
+ return decodeValue(value, SLUG_BITS, SLUG_ALPHABET);
69
+ }
70
+ function buildCloid(version, slug, clientId, oid, options) {
71
+ if (version > 15) version = BASED_VERSION;
72
+ if (clientId > Number(mask2(CLIENT_BITS))) {
73
+ clientId = CloidClientCode.Unset;
74
+ }
75
+ const isMiniApp = options?.isMiniApp ? 1 : 0;
76
+ const miniAppTriggered = options?.miniAppTriggered ? 1 : 0;
77
+ const widgetType = typeof options?.widgetType === "number" ? options.widgetType : WidgetType[options?.widgetType ?? "Unset"];
78
+ if (widgetType > Number(mask2(WIDGET_TYPE_BITS))) {
79
+ throw new Error(
80
+ `Component ID ${widgetType} exceeds maximum value ${Number(mask2(WIDGET_TYPE_BITS))}`
81
+ );
82
+ }
83
+ let oidBigInt;
84
+ if (typeof oid === "string") {
85
+ if (oid.startsWith("0x") || !isNaN(Number(oid))) {
86
+ oidBigInt = BigInt(oid);
87
+ } else {
88
+ oidBigInt = encodeValue(oid.toLowerCase(), OID_BITS, OID_ALPHABET);
89
+ }
90
+ } else {
91
+ oidBigInt = oid;
92
+ }
93
+ if (oidBigInt > mask2(OID_BITS)) {
94
+ oidBigInt = DEFAULT_OID;
95
+ }
96
+ const slugVal = encodeSlug(slug.toUpperCase());
97
+ let cloid = BigInt(BASED_HEX_PREFIX) << TOTAL_BITS - PREFIX_BITS;
98
+ cloid |= BigInt(version & 15) << TOTAL_BITS - PREFIX_BITS - VERSION_BITS;
99
+ cloid |= BigInt(slugVal) << TOTAL_BITS - PREFIX_BITS - VERSION_BITS - SLUG_BITS;
100
+ cloid |= BigInt(clientId) << OID_BITS;
101
+ cloid |= BigInt(isMiniApp) << OID_BITS + CLIENT_BITS;
102
+ cloid |= BigInt(miniAppTriggered) << OID_BITS + CLIENT_BITS + IS_MINI_APP_BITS;
103
+ cloid |= BigInt(widgetType) << OID_BITS + CLIENT_BITS + IS_MINI_APP_BITS + MINI_APP_TRIGGERED_BITS;
104
+ cloid |= oidBigInt & mask2(OID_BITS);
105
+ return `0x${cloid.toString(16)}`;
106
+ }
107
+ function parseCloid(cloidHex) {
108
+ if (cloidHex === LEGACY_CLOID) {
109
+ return {
110
+ prefix: LEGACY_CLOID,
111
+ version: 0,
112
+ slug: "BASED",
113
+ clientId: CloidClientCode.Unset,
114
+ isMiniApp: false,
115
+ miniAppTriggered: false,
116
+ widgetTypeId: WidgetType.Unset,
117
+ oid: 0xba5ed10000ba5ed1n,
118
+ decodedOid: decodeValue(0xba5ed10000ba5ed1n, OID_BITS, OID_ALPHABET),
119
+ clientName: "Unset",
120
+ widgetTypeName: "Unset"
121
+ };
122
+ }
123
+ try {
124
+ const cloid = BigInt(cloidHex);
125
+ const prefix = Number(cloid >> TOTAL_BITS - PREFIX_BITS);
126
+ const version = Number(
127
+ cloid >> TOTAL_BITS - PREFIX_BITS - VERSION_BITS & mask2(VERSION_BITS)
128
+ );
129
+ const slugVal = Number(
130
+ cloid >> OID_BITS + WIDGET_TYPE_BITS + MINI_APP_TRIGGERED_BITS + IS_MINI_APP_BITS + CLIENT_BITS & mask2(SLUG_BITS)
131
+ );
132
+ const clientId = Number(cloid >> OID_BITS & mask2(CLIENT_BITS));
133
+ const isMiniApp = Number(cloid >> OID_BITS + CLIENT_BITS & mask2(IS_MINI_APP_BITS)) === 1;
134
+ const miniAppTriggered = Number(
135
+ cloid >> OID_BITS + CLIENT_BITS + IS_MINI_APP_BITS & mask2(MINI_APP_TRIGGERED_BITS)
136
+ ) === 1;
137
+ const widgetType = Number(
138
+ cloid >> OID_BITS + CLIENT_BITS + IS_MINI_APP_BITS + MINI_APP_TRIGGERED_BITS & mask2(WIDGET_TYPE_BITS)
139
+ );
140
+ const oid = cloid & mask2(OID_BITS);
141
+ return {
142
+ prefix: `0x${prefix.toString(16)}`,
143
+ // should equal 0xBA5ED1
144
+ version,
145
+ slug: decodeSlug(BigInt(slugVal)),
146
+ clientId,
147
+ isMiniApp,
148
+ miniAppTriggered,
149
+ widgetTypeId: widgetType,
150
+ oid,
151
+ decodedOid: decodeValue(oid, OID_BITS, OID_ALPHABET),
152
+ clientName: getClientCodeNameById(clientId),
153
+ widgetTypeName: getWidgetTypeById(widgetType)
154
+ };
155
+ } catch (error) {
156
+ console.error("Invalid cloid", { cloidHex });
157
+ return null;
158
+ }
159
+ }
160
+ function isBasedCloid(cloidHex) {
161
+ if (!cloidHex) return false;
162
+ if (cloidHex === LEGACY_CLOID) return true;
163
+ return cloidHex.toLowerCase().startsWith(BASED_HEX_PREFIX_STR);
164
+ }
165
+ function isTenantCloid(tenantTrackingSlug, cloidHex) {
166
+ if (!cloidHex || !isBasedCloid(cloidHex)) return false;
167
+ const cloidData = parseCloid(cloidHex);
168
+ if (!cloidData) return false;
169
+ const { slug } = cloidData;
170
+ if (tenantTrackingSlug.length > 5) {
171
+ tenantTrackingSlug = tenantTrackingSlug.slice(0, 5);
172
+ }
173
+ const normalisedSlug = decodeSlug(encodeSlug(tenantTrackingSlug));
174
+ return slug === normalisedSlug;
175
+ }
176
+ function isTrackingIdCloid(trackingId, cloidHex) {
177
+ if (!cloidHex || !isBasedCloid(cloidHex)) return false;
178
+ const cloidData = parseCloid(cloidHex);
179
+ if (!cloidData) return false;
180
+ if (typeof trackingId === "string") {
181
+ const encodedTrackingId = normaliseTrackingId(trackingId);
182
+ return encodedTrackingId === cloidData.decodedOid;
183
+ } else {
184
+ const { oid } = cloidData;
185
+ return oid === trackingId;
186
+ }
187
+ }
188
+ function normaliseSlug(slug) {
189
+ if (!slug) return "";
190
+ return decodeSlug(encodeSlug(slug.toUpperCase()));
191
+ }
192
+ function normaliseTrackingId(trackingId) {
193
+ if (!trackingId) return "";
194
+ return decodeValue(
195
+ encodeValue(trackingId.toLowerCase(), OID_BITS, OID_ALPHABET),
196
+ OID_BITS,
197
+ OID_ALPHABET
198
+ );
199
+ }
200
+ var CloidClientCode = {
201
+ Unset: 0,
202
+ // 0x00
203
+ Web: 1,
204
+ App: 2,
205
+ TgBot: 3,
206
+ TSL: 4,
207
+ // Trailing Stop Loss
208
+ Grid: 5,
209
+ Chase: 6,
210
+ Desktop: 7,
211
+ API: 8
212
+ };
213
+ var CloidClientCodeNameById = {
214
+ [CloidClientCode.Unset]: "Unset",
215
+ [CloidClientCode.Web]: "Web",
216
+ [CloidClientCode.App]: "App",
217
+ [CloidClientCode.TgBot]: "TgBot",
218
+ [CloidClientCode.TSL]: "TSL",
219
+ [CloidClientCode.Grid]: "Grid",
220
+ [CloidClientCode.Chase]: "Chase",
221
+ [CloidClientCode.Desktop]: "Desktop",
222
+ [CloidClientCode.API]: "API"
223
+ };
224
+ function getClientCodeNameById(id) {
225
+ return CloidClientCodeNameById[id] ?? `client_${id}`;
226
+ }
227
+ var WidgetType = {
228
+ Unset: 0,
229
+ // 0x00
230
+ SidePanel: 1,
231
+ Widget: 2,
232
+ FloatingWidget: 3
233
+ };
234
+ var WidgetTypeById = {
235
+ [WidgetType.Unset]: "Unset",
236
+ [WidgetType.SidePanel]: "SidePanel",
237
+ [WidgetType.Widget]: "Widget",
238
+ [WidgetType.FloatingWidget]: "FloatingWidget"
239
+ };
240
+ function getWidgetTypeById(id) {
241
+ return WidgetTypeById[id] ?? `widget_${id}`;
242
+ }
243
+ function getCloid(tenantCode, clientCode, oid, attribution) {
244
+ try {
245
+ const clientIdx = typeof clientCode === "number" ? clientCode : CloidClientCode[clientCode ?? "Unset"];
246
+ return buildCloid(
247
+ BASED_VERSION,
248
+ tenantCode ?? DEFAULT_TENANT_CODE,
249
+ clientIdx,
250
+ oid ?? DEFAULT_OID,
251
+ attribution
252
+ );
253
+ } catch (error) {
254
+ console.error(
255
+ "Invalid cloid parameters, defaulting to legacy cloid",
256
+ error,
257
+ { tenantCode, clientCode, oid, options: attribution }
258
+ );
259
+ return LEGACY_CLOID;
260
+ }
261
+ }
262
+ function isClientCode(clientCode, cloidHex) {
263
+ const cloidData = parseCloid(cloidHex);
264
+ if (!cloidData) return false;
265
+ return cloidData.clientId === clientCode;
266
+ }
267
+ function isWidgetType(widgetType, cloidHex) {
268
+ const cloidData = parseCloid(cloidHex);
269
+ if (!cloidData) return false;
270
+ return cloidData.widgetTypeId === widgetType;
271
+ }
272
+ function isMiniAppCloid(cloidHex) {
273
+ const cloidData = parseCloid(cloidHex);
274
+ if (!cloidData) return false;
275
+ return cloidData.isMiniApp;
276
+ }
277
+ function isMiniAppTriggeredCloid(cloidHex) {
278
+ const cloidData = parseCloid(cloidHex);
279
+ if (!cloidData) return false;
280
+ return cloidData.miniAppTriggered;
281
+ }
282
+
283
+ // lib/constants/fee.ts
284
+ var BASED_FEE_WALLET = "0x1924b8561eeF20e70Ede628A296175D358BE80e5";
285
+ var BASED_REFERRAL_CODE = "SHIFU";
286
+
287
+ // lib/fee.ts
288
+ var TARGET_SPOT_BUILDER_FEE = 100;
289
+ var TARGET_FUTURES_BUILDER_FEE = 25;
290
+ var TARGET_APPROVED_MAX_BUILDER_FEE = Math.max(
291
+ TARGET_SPOT_BUILDER_FEE,
292
+ TARGET_FUTURES_BUILDER_FEE
293
+ );
294
+ var TARGET_APPROVED_MAX_BUILDER_FEE_PERCENT = `0.1%`;
295
+ var getApprovalAmount = ({
296
+ customFeeEnabled,
297
+ perpetualTradingFee,
298
+ spotTradingFee
299
+ }) => {
300
+ if (!customFeeEnabled) {
301
+ return {
302
+ approvalAmount: TARGET_APPROVED_MAX_BUILDER_FEE,
303
+ perpFee: TARGET_FUTURES_BUILDER_FEE,
304
+ spotFee: TARGET_SPOT_BUILDER_FEE,
305
+ approvalPercent: TARGET_APPROVED_MAX_BUILDER_FEE_PERCENT,
306
+ builder: BASED_FEE_WALLET,
307
+ referralCode: BASED_REFERRAL_CODE
308
+ };
309
+ }
310
+ let validatedPerpFeePct = perpetualTradingFee;
311
+ if (validatedPerpFeePct === void 0) {
312
+ validatedPerpFeePct = TARGET_FUTURES_BUILDER_FEE / 1e3;
313
+ }
314
+ if (validatedPerpFeePct > 0 && validatedPerpFeePct < 0.01) {
315
+ console.warn("Perp fee is less than 0.01%, setting to 0.01%");
316
+ validatedPerpFeePct = 0.01;
317
+ }
318
+ if (validatedPerpFeePct < 0) {
319
+ console.warn("Perp fee is less than 0, setting to 0");
320
+ validatedPerpFeePct = 0;
321
+ }
322
+ if (validatedPerpFeePct > 0.1) {
323
+ console.warn("Perp fee is greater than 0.1%, setting to 0.1%");
324
+ validatedPerpFeePct = 0.1;
325
+ }
326
+ let validatedSpotFeePct = spotTradingFee;
327
+ if (validatedSpotFeePct === void 0) {
328
+ validatedSpotFeePct = TARGET_SPOT_BUILDER_FEE / 1e3;
329
+ }
330
+ if (validatedSpotFeePct > 0 && validatedSpotFeePct < 0.025) {
331
+ console.warn("Spot fee is less than 0.025%, setting to 0.025%");
332
+ validatedSpotFeePct = 0.025;
333
+ }
334
+ if (validatedSpotFeePct < 0) {
335
+ console.warn("Spot fee is less than 0, setting to 0");
336
+ validatedSpotFeePct = 0;
337
+ }
338
+ if (validatedSpotFeePct > 1) {
339
+ console.warn("Spot fee is greater than 1%, setting to 1%");
340
+ validatedSpotFeePct = 1;
341
+ }
342
+ const perpFee = Math.floor(validatedPerpFeePct * 1e3);
343
+ const spotFee = Math.floor(validatedSpotFeePct * 1e3);
344
+ const requiredPercent = validatedPerpFeePct > validatedSpotFeePct ? validatedPerpFeePct : validatedSpotFeePct;
345
+ const requiredAmount = Math.max(Math.floor(requiredPercent * 1e3), 1);
346
+ const requiredPercentString = `${requiredAmount / 1e3}%`;
347
+ return {
348
+ approvalAmount: requiredAmount,
349
+ approvalPercent: requiredPercentString,
350
+ perpFee,
351
+ spotFee,
352
+ builder: BASED_FEE_WALLET,
353
+ referralCode: BASED_REFERRAL_CODE
354
+ };
355
+ };
356
+
357
+ // lib/pup/types.ts
358
+ var PUP_TOKEN_ADDRESS = "0x876e7f2f30935118a654fc0e1f807afc49efe500";
359
+ var PUP_TOKEN_THRESHOLDS = {
360
+ AIRDROP_70_PERCENT: 0.7,
361
+ AIRDROP_35_PERCENT: 0.35,
362
+ AIRDROP_110_PERCENT: 1.1,
363
+ NON_AIRDROP_TOKENS: 2e6
364
+ };
365
+ var XP_BOOST_PERCENTAGES = {
366
+ NO_BOOST: 0,
367
+ TIER_1: 25,
368
+ TIER_2: 50,
369
+ TIER_3: 60
370
+ };
371
+
372
+ // lib/pup/calculator.ts
373
+ function calculateTotalPupAmount(positions) {
374
+ let totalPupAmount = 0;
375
+ const pupAddress = PUP_TOKEN_ADDRESS.toLowerCase();
376
+ for (const position of positions) {
377
+ try {
378
+ if (position.version === "erc20" && position.pair === "PUP") {
379
+ const amount = parseFloat(position.amount) / 1e18;
380
+ totalPupAmount += amount;
381
+ console.log(`Found pure PUP position: ${amount} PUP`);
382
+ } else if (position.version === "v3" && position.v3LPTokenInfo) {
383
+ const { token0, token1 } = position.v3LPTokenInfo;
384
+ if (token0.address.toLowerCase() === pupAddress || token0.symbol === "PUP") {
385
+ totalPupAmount += token0.amount;
386
+ console.log(`Found V3 LP position with PUP as token0: ${token0.amount} PUP`);
387
+ } else if (token1.address.toLowerCase() === pupAddress || token1.symbol === "PUP") {
388
+ totalPupAmount += token1.amount;
389
+ console.log(`Found V3 LP position with PUP as token1: ${token1.amount} PUP`);
390
+ }
391
+ }
392
+ } catch (error) {
393
+ console.error(`Error processing position ${position.pair}:`, error);
394
+ }
395
+ }
396
+ console.log(`Total PUP amount calculated: ${totalPupAmount}`);
397
+ return totalPupAmount;
398
+ }
399
+ function calculateBoostPercentage(pupTokenAmount, normalizedAirDropAmount, isAirdropRecipient) {
400
+ if (isAirdropRecipient && normalizedAirDropAmount > 0) {
401
+ const retentionRatio = pupTokenAmount / normalizedAirDropAmount;
402
+ if (retentionRatio >= PUP_TOKEN_THRESHOLDS.AIRDROP_110_PERCENT) {
403
+ return XP_BOOST_PERCENTAGES.TIER_3;
404
+ }
405
+ if (retentionRatio >= PUP_TOKEN_THRESHOLDS.AIRDROP_70_PERCENT) {
406
+ return XP_BOOST_PERCENTAGES.TIER_2;
407
+ }
408
+ if (retentionRatio >= PUP_TOKEN_THRESHOLDS.AIRDROP_35_PERCENT) {
409
+ return XP_BOOST_PERCENTAGES.TIER_1;
410
+ }
411
+ return XP_BOOST_PERCENTAGES.NO_BOOST;
412
+ } else {
413
+ if (pupTokenAmount >= PUP_TOKEN_THRESHOLDS.NON_AIRDROP_TOKENS) {
414
+ return XP_BOOST_PERCENTAGES.TIER_1;
415
+ }
416
+ return XP_BOOST_PERCENTAGES.NO_BOOST;
417
+ }
418
+ }
419
+ function normalizeAirdropAmount(amount) {
420
+ if (!amount) return 0;
421
+ if (typeof amount === "bigint") {
422
+ return Number(amount) / 1e18;
423
+ } else if (amount && typeof amount.div === "function") {
424
+ return amount.div(1e18).toNumber();
425
+ }
426
+ return 0;
427
+ }
428
+ function getNextTierInfo(pupTokenAmount, normalizedAirDropAmount, isAirdropRecipient) {
429
+ const currentBoost = calculateBoostPercentage(pupTokenAmount, normalizedAirDropAmount, isAirdropRecipient);
430
+ let currentTier = 0;
431
+ if (currentBoost === XP_BOOST_PERCENTAGES.TIER_3) currentTier = 3;
432
+ else if (currentBoost === XP_BOOST_PERCENTAGES.TIER_2) currentTier = 2;
433
+ else if (currentBoost === XP_BOOST_PERCENTAGES.TIER_1) currentTier = 1;
434
+ if (isAirdropRecipient && normalizedAirDropAmount > 0) {
435
+ const retentionRatio = pupTokenAmount / normalizedAirDropAmount;
436
+ if (currentTier === 0) {
437
+ const threshold = normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_35_PERCENT;
438
+ return {
439
+ currentTier: 0,
440
+ currentBoost: XP_BOOST_PERCENTAGES.NO_BOOST,
441
+ nextTier: 1,
442
+ nextBoost: XP_BOOST_PERCENTAGES.TIER_1,
443
+ amountToNextTier: Math.max(0, threshold - pupTokenAmount),
444
+ nextTierThreshold: threshold,
445
+ progressPercentage: Math.min(100, pupTokenAmount / threshold * 100)
446
+ };
447
+ } else if (currentTier === 1) {
448
+ const threshold = normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_70_PERCENT;
449
+ return {
450
+ currentTier: 1,
451
+ currentBoost: XP_BOOST_PERCENTAGES.TIER_1,
452
+ nextTier: 2,
453
+ nextBoost: XP_BOOST_PERCENTAGES.TIER_2,
454
+ amountToNextTier: Math.max(0, threshold - pupTokenAmount),
455
+ nextTierThreshold: threshold,
456
+ progressPercentage: Math.min(100, (pupTokenAmount - normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_35_PERCENT) / (threshold - normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_35_PERCENT) * 100)
457
+ };
458
+ } else if (currentTier === 2) {
459
+ const threshold = normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_110_PERCENT;
460
+ return {
461
+ currentTier: 2,
462
+ currentBoost: XP_BOOST_PERCENTAGES.TIER_2,
463
+ nextTier: 3,
464
+ nextBoost: XP_BOOST_PERCENTAGES.TIER_3,
465
+ amountToNextTier: Math.max(0, threshold - pupTokenAmount),
466
+ nextTierThreshold: threshold,
467
+ progressPercentage: Math.min(100, (pupTokenAmount - normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_70_PERCENT) / (threshold - normalizedAirDropAmount * PUP_TOKEN_THRESHOLDS.AIRDROP_70_PERCENT) * 100)
468
+ };
469
+ } else {
470
+ return {
471
+ currentTier: 3,
472
+ currentBoost: XP_BOOST_PERCENTAGES.TIER_3,
473
+ nextTier: null,
474
+ nextBoost: null,
475
+ amountToNextTier: null,
476
+ nextTierThreshold: null,
477
+ progressPercentage: 100
478
+ };
479
+ }
480
+ } else {
481
+ const threshold = PUP_TOKEN_THRESHOLDS.NON_AIRDROP_TOKENS;
482
+ if (currentTier === 0) {
483
+ return {
484
+ currentTier: 0,
485
+ currentBoost: XP_BOOST_PERCENTAGES.NO_BOOST,
486
+ nextTier: 1,
487
+ nextBoost: XP_BOOST_PERCENTAGES.TIER_1,
488
+ amountToNextTier: Math.max(0, threshold - pupTokenAmount),
489
+ nextTierThreshold: threshold,
490
+ progressPercentage: Math.min(100, pupTokenAmount / threshold * 100)
491
+ };
492
+ } else {
493
+ return {
494
+ currentTier: 1,
495
+ currentBoost: XP_BOOST_PERCENTAGES.TIER_1,
496
+ nextTier: null,
497
+ nextBoost: null,
498
+ amountToNextTier: null,
499
+ nextTierThreshold: null,
500
+ progressPercentage: 100
501
+ };
502
+ }
503
+ }
504
+ }
505
+
506
+ // lib/constants/tokens.ts
507
+ var USDC_SPOT_TOKEN = {
508
+ name: "USDC",
509
+ szDecimals: 8,
510
+ weiDecimals: 8,
511
+ index: 0,
512
+ tokenId: "0x6d1e7cde53ba9467b783cb7c530ce054",
513
+ isCanonical: true,
514
+ evmContract: null,
515
+ fullName: null,
516
+ deployerTradingFeeShare: "0.0"
517
+ };
518
+ var TESTNET_USDC_SPOT_TOKEN = {
519
+ name: "USDC",
520
+ szDecimals: 8,
521
+ weiDecimals: 8,
522
+ index: 0,
523
+ tokenId: "0xeb62eee3685fc4c43992febcd9e75443",
524
+ isCanonical: true,
525
+ evmContract: {
526
+ address: "0xd9cbec81df392a88aeff575e962d149d57f4d6bc",
527
+ evm_extra_wei_decimals: 0
528
+ },
529
+ fullName: null,
530
+ deployerTradingFeeShare: "0.0"
531
+ };
532
+
533
+ // lib/meta/metadata.ts
534
+ import {
535
+ HttpTransport,
536
+ InfoClient
537
+ } from "@nktkas/hyperliquid";
538
+
539
+ // lib/hip3/utils.ts
540
+ function isHip3Symbol(symbol) {
541
+ if (!symbol) return false;
542
+ return symbol.includes(":");
543
+ }
544
+
545
+ // import("./data/**/*/spotMeta.json") in lib/meta/metadata.ts
546
+ var globImport_data_spotMeta_json = __glob({
547
+ "./data/mainnet/spotMeta.json": () => import("./spotMeta-7IJT3W6H.mjs"),
548
+ "./data/testnet/spotMeta.json": () => import("./spotMeta-ZVBZNUUE.mjs")
549
+ });
550
+
551
+ // import("./data/**/*/meta.json") in lib/meta/metadata.ts
552
+ var globImport_data_meta_json = __glob({
553
+ "./data/mainnet/meta.json": () => import("./meta-52Q5UUQ4.mjs"),
554
+ "./data/testnet/meta.json": () => import("./meta-UUXKK7IB.mjs")
555
+ });
556
+
557
+ // import("./data/**/*/perpDexs.json") in lib/meta/metadata.ts
558
+ var globImport_data_perpDexs_json = __glob({
559
+ "./data/mainnet/perpDexs.json": () => import("./perpDexs-S3TK25EU.mjs"),
560
+ "./data/testnet/perpDexs.json": () => import("./perpDexs-TZIQ57IW.mjs")
561
+ });
562
+
563
+ // lib/meta/metadata.ts
564
+ var MetadataClient = class {
565
+ constructor(config = {}) {
566
+ // Core metadata
567
+ this.spotMeta = null;
568
+ this.perpsMeta = null;
569
+ this.perpDexs = [];
570
+ // HIP-3 metadata cache
571
+ this.hip3DexsMeta = /* @__PURE__ */ new Map();
572
+ // Pre-computed lookup maps (populated on initialize)
573
+ this.perpsSymbolToIndex = /* @__PURE__ */ new Map();
574
+ this.spotTokenNameToIndex = /* @__PURE__ */ new Map();
575
+ this.spotPairToMarket = /* @__PURE__ */ new Map();
576
+ this.baseTokenToMarkets = /* @__PURE__ */ new Map();
577
+ this.quoteAssets = [];
578
+ // Unified symbol lookup (used by getMarketBySymbol for O(1) access)
579
+ // Maps symbol to MarketInfo for quick lookups
580
+ this.coinToMarket = /* @__PURE__ */ new Map();
581
+ // HIP-3 optimized lookups
582
+ // Maps "dex:coin" symbol to MarketInfo
583
+ this.hip3SymbolToMarket = /* @__PURE__ */ new Map();
584
+ // Maps dex name to dex index for quick lookups
585
+ this.dexNameToIndex = /* @__PURE__ */ new Map();
586
+ // Lazy init flag
587
+ this.initialized = false;
588
+ const transport = new HttpTransport({
589
+ isTestnet: config.isTestnet ?? false
590
+ });
591
+ this.infoClient = new InfoClient({ transport });
592
+ this.config = {
593
+ ...config,
594
+ useStaticFallback: config.useStaticFallback ?? true
595
+ };
596
+ this.isTestnet = config.isTestnet ?? false;
597
+ this.initialize();
598
+ }
599
+ /**
600
+ * Initialize metadata by fetching from Hyperliquid
601
+ */
602
+ async initialize() {
603
+ if (this.initialized) return;
604
+ if (this.config.onlyUseStaticFallback) {
605
+ await this.loadStaticMetadata();
606
+ this.buildLookupMaps();
607
+ if (this.config.hip3Dexs && this.config.hip3Dexs.length > 0) {
608
+ await Promise.all(
609
+ this.config.hip3Dexs.map((dex) => this.loadHip3Metadata(dex))
610
+ );
611
+ }
612
+ this.initialized = true;
613
+ return;
614
+ }
615
+ try {
616
+ [this.spotMeta, this.perpsMeta, this.perpDexs] = await Promise.all([
617
+ this.infoClient.spotMeta(),
618
+ this.infoClient.meta(),
619
+ this.infoClient.perpDexs()
620
+ ]);
621
+ this.buildLookupMaps();
622
+ if (this.config.hip3Dexs && this.config.hip3Dexs.length > 0) {
623
+ await Promise.all(
624
+ this.config.hip3Dexs.map((dex) => this.loadHip3Metadata(dex))
625
+ );
626
+ }
627
+ this.initialized = true;
628
+ } catch (error) {
629
+ if (this.config.useStaticFallback) {
630
+ console.warn(
631
+ "Failed to fetch metadata from API, using static fallback data",
632
+ error
633
+ );
634
+ await this.loadStaticMetadata();
635
+ this.buildLookupMaps();
636
+ this.initialized = true;
637
+ } else {
638
+ throw error;
639
+ }
640
+ }
641
+ }
642
+ /**
643
+ * Load static metadata from bundled JSON files
644
+ */
645
+ async loadStaticMetadata() {
646
+ const network = this.isTestnet ? "testnet" : "mainnet";
647
+ try {
648
+ const [spotMetaModule, perpsMetaModule, perpDexsModule] = await Promise.all([
649
+ globImport_data_spotMeta_json(`./data/${network}/spotMeta.json`),
650
+ globImport_data_meta_json(`./data/${network}/meta.json`),
651
+ globImport_data_perpDexs_json(`./data/${network}/perpDexs.json`)
652
+ ]);
653
+ this.spotMeta = spotMetaModule.default;
654
+ this.perpsMeta = perpsMetaModule.default;
655
+ this.perpDexs = perpDexsModule.default;
656
+ console.warn(`Using static ${network} metadata`);
657
+ } catch (error) {
658
+ console.error(`Failed to load static ${network} metadata:`, error);
659
+ throw new Error(`Could not load metadata for ${network}`);
660
+ }
661
+ }
662
+ /**
663
+ * Build optimized lookup maps from raw metadata
664
+ * Called after metadata is loaded (from API or static files)
665
+ */
666
+ buildLookupMaps() {
667
+ this.perpsSymbolToIndex.clear();
668
+ this.spotTokenNameToIndex.clear();
669
+ this.spotPairToMarket.clear();
670
+ this.baseTokenToMarkets.clear();
671
+ this.coinToMarket.clear();
672
+ this.hip3SymbolToMarket.clear();
673
+ this.dexNameToIndex.clear();
674
+ this.quoteAssets = [];
675
+ if (this.perpDexs) {
676
+ this.perpDexs.forEach((dex, index) => {
677
+ if (dex && dex.name) {
678
+ this.dexNameToIndex.set(dex.name.toLowerCase(), index);
679
+ }
680
+ });
681
+ }
682
+ if (this.perpsMeta) {
683
+ this.perpsMeta.universe.forEach((market, index) => {
684
+ const marketInfo = {
685
+ symbol: market.name,
686
+ coin: market.name,
687
+ assetId: index,
688
+ szDecimals: market.szDecimals,
689
+ type: "perps",
690
+ maxLeverage: market.maxLeverage
691
+ };
692
+ this.perpsSymbolToIndex.set(market.name.toUpperCase(), index);
693
+ this.coinToMarket.set(market.name, marketInfo);
694
+ });
695
+ }
696
+ if (this.spotMeta) {
697
+ this.spotMeta.tokens.forEach((token) => {
698
+ this.spotTokenNameToIndex.set(token.name.toUpperCase(), token.index);
699
+ });
700
+ const quoteIndices = /* @__PURE__ */ new Set();
701
+ this.spotMeta.universe.forEach((universe) => {
702
+ const baseToken = this.spotMeta.tokens[universe.tokens[0]];
703
+ const quoteToken = this.spotMeta.tokens[universe.tokens[1]];
704
+ if (!baseToken || !quoteToken) return;
705
+ const coin = universe.name;
706
+ quoteIndices.add(quoteToken.index);
707
+ const marketInfo = {
708
+ coin,
709
+ symbol: `${baseToken.name}/${quoteToken.name}`,
710
+ assetId: 1e4 + universe.index,
711
+ szDecimals: baseToken.szDecimals,
712
+ type: "spot",
713
+ baseToken,
714
+ quoteToken
715
+ };
716
+ const pairKey = `${baseToken.name}/${quoteToken.name}`.toUpperCase();
717
+ this.spotPairToMarket.set(pairKey, marketInfo);
718
+ this.coinToMarket.set(pairKey, marketInfo);
719
+ this.coinToMarket.set(coin, marketInfo);
720
+ const baseKey = baseToken.name.toUpperCase();
721
+ const existing = this.baseTokenToMarkets.get(baseKey) || [];
722
+ existing.push(marketInfo);
723
+ this.baseTokenToMarkets.set(baseKey, existing);
724
+ });
725
+ this.quoteAssets = Array.from(quoteIndices).map((idx) => this.spotMeta.tokens[idx].name).sort();
726
+ }
727
+ }
728
+ /**
729
+ * Load metadata for a specific HIP-3 DEX
730
+ * Also builds optimized lookups for this DEX's markets
731
+ */
732
+ async loadHip3Metadata(dexName) {
733
+ if (this.hip3DexsMeta.has(dexName)) return this.hip3DexsMeta.get(dexName);
734
+ try {
735
+ const [meta, contexts] = await this.infoClient.metaAndAssetCtxs({
736
+ dex: dexName
737
+ });
738
+ let dexIndex = this.dexNameToIndex.get(dexName.toLowerCase());
739
+ if (dexIndex === void 0) {
740
+ dexIndex = this.perpDexs.findIndex(
741
+ (d) => d && d.name.toLowerCase() === dexName.toLowerCase()
742
+ );
743
+ }
744
+ if (dexIndex === -1 || dexIndex === void 0) {
745
+ throw new Error(`DEX ${dexName} not found`);
746
+ }
747
+ const dex = this.perpDexs[dexIndex];
748
+ const collateralTokenIndex = meta.collateralToken ?? 0;
749
+ const spotMetaTokens = this.spotMeta?.tokens;
750
+ const collateralTokenSymbol = spotMetaTokens?.[collateralTokenIndex]?.name ?? "USDC";
751
+ const dexInfo = {
752
+ meta,
753
+ assetContext: contexts,
754
+ collateralTokenSymbol,
755
+ dexFullName: dex?.full_name ?? dexName,
756
+ dexName: dex?.name ?? dexName,
757
+ dexIndex
758
+ };
759
+ this.hip3DexsMeta.set(dexName, dexInfo);
760
+ this.buildHip3MarketsForDex(dexName, dexInfo);
761
+ return dexInfo;
762
+ } catch (error) {
763
+ console.error(`Failed to load HIP-3 metadata for ${dexName}:`, error);
764
+ throw error;
765
+ }
766
+ }
767
+ /**
768
+ * Build optimized lookups for HIP-3 markets of a specific DEX
769
+ */
770
+ buildHip3MarketsForDex(dexName, dexInfo) {
771
+ dexInfo.meta.universe.forEach((market, index) => {
772
+ const symbol = market.name;
773
+ const marketInfo = {
774
+ coin: symbol,
775
+ symbol,
776
+ assetId: 1e5 + dexInfo.dexIndex * 1e4 + index,
777
+ szDecimals: market.szDecimals,
778
+ type: "hip3",
779
+ maxLeverage: market.maxLeverage,
780
+ dexName,
781
+ dexIndex: dexInfo.dexIndex
782
+ };
783
+ this.coinToMarket.set(symbol, marketInfo);
784
+ this.hip3SymbolToMarket.set(symbol, marketInfo);
785
+ });
786
+ }
787
+ /**
788
+ * Ensure metadata is loaded (for lazy init)
789
+ */
790
+ async ensureInitialized() {
791
+ if (!this.initialized) {
792
+ await this.initialize();
793
+ }
794
+ }
795
+ /**
796
+ * Get market information by symbol
797
+ * Optimized: O(1) direct map lookup for most cases
798
+ * Lazily initialize hip-3 metadata if not already initialized
799
+ *
800
+ * @param symbol - Market symbol (e.g., "BTC", "PURR/USDC", "vntls:ABC")
801
+ * @param quoteAsset - Quote asset for spot markets (default: "USDC")
802
+ * @returns Market information or null if not found
803
+ */
804
+ async getMarketBySymbolAsync(symbol, quoteAsset = "USDC") {
805
+ await this.ensureInitialized();
806
+ if (symbol.includes(":")) {
807
+ return this.getHip3Market(symbol);
808
+ }
809
+ let lookupKey = symbol.toUpperCase();
810
+ if (!symbol.includes("/") && !symbol.includes("@")) {
811
+ const perpsMarket = this.coinToMarket.get(lookupKey);
812
+ if (perpsMarket?.type === "perps") {
813
+ return perpsMarket;
814
+ }
815
+ lookupKey = `${symbol}/${quoteAsset}`.toUpperCase();
816
+ }
817
+ return this.coinToMarket.get(lookupKey) || null;
818
+ }
819
+ getMarketByCoin(coin) {
820
+ return this.coinToMarket.get(coin) || null;
821
+ }
822
+ /**
823
+ * Get perpetuals market information
824
+ * Optimized: O(1) map lookup instead of O(n) array search
825
+ */
826
+ getPerpsMarket(symbol) {
827
+ if (!this.perpsMeta) return null;
828
+ if (isHip3Symbol(symbol)) {
829
+ const [dexName, coinName] = symbol.split(":");
830
+ if (!dexName || !coinName) return null;
831
+ let cachedMarket = this.hip3SymbolToMarket.get(symbol);
832
+ return cachedMarket || null;
833
+ }
834
+ const index = this.perpsSymbolToIndex.get(symbol.toUpperCase());
835
+ if (index === void 0) return null;
836
+ const market = this.perpsMeta.universe[index];
837
+ return {
838
+ coin: symbol,
839
+ symbol: market.name,
840
+ assetId: index,
841
+ // Perps asset ID is just the index
842
+ szDecimals: market.szDecimals,
843
+ type: "perps",
844
+ maxLeverage: market.maxLeverage
845
+ };
846
+ }
847
+ /**
848
+ * Get spot market information
849
+ * Optimized: O(1) map lookup instead of O(n) array searches
850
+ *
851
+ * @param baseSymbol - Base token symbol (e.g., "PURR", "UHYPE")
852
+ * @param quoteSymbol - Quote token symbol (default: "USDC")
853
+ */
854
+ getSpotMarket(baseSymbol, quoteSymbol = "USDC") {
855
+ if (!this.spotMeta) return null;
856
+ const pairKey = `${baseSymbol}/${quoteSymbol}`.toUpperCase();
857
+ const market = this.spotPairToMarket.get(pairKey);
858
+ return market || null;
859
+ }
860
+ /**
861
+ * Get HIP-3 market information
862
+ * Optimized: O(1) map lookup after DEX metadata is loaded
863
+ *
864
+ * @param symbol - HIP-3 market symbol (format: "dex:coin")
865
+ */
866
+ async getHip3Market(symbol) {
867
+ const [dexName, coinName] = symbol.split(":");
868
+ if (!dexName || !coinName) return null;
869
+ let cachedMarket = this.hip3SymbolToMarket.get(symbol);
870
+ if (cachedMarket) return cachedMarket;
871
+ const dexMeta = this.hip3DexsMeta.get(dexName);
872
+ if (!dexMeta && this.config.lazyInit) {
873
+ await this.loadHip3Metadata(dexName);
874
+ cachedMarket = this.hip3SymbolToMarket.get(symbol);
875
+ return cachedMarket || null;
876
+ }
877
+ return null;
878
+ }
879
+ async getHip3Dex(dexName) {
880
+ await this.ensureInitialized();
881
+ let dexInfo = this.hip3DexsMeta.get(dexName) ?? null;
882
+ if (this.config.lazyInit && !dexInfo) {
883
+ dexInfo = await this.loadHip3Metadata(dexName);
884
+ }
885
+ return dexInfo;
886
+ }
887
+ /**
888
+ * Get all available markets for a base token
889
+ * Optimized: O(1) map lookup instead of O(n) filter + map
890
+ * Useful for showing all quote asset options
891
+ */
892
+ getAllMarketsForBase(baseSymbol) {
893
+ if (!this.spotMeta) return [];
894
+ const baseKey = baseSymbol.toUpperCase();
895
+ return this.baseTokenToMarkets.get(baseKey) || [];
896
+ }
897
+ /**
898
+ * Get spot token information
899
+ * Optimized: O(1) map lookup instead of O(n) array search
900
+ */
901
+ getSpotTokenInfo(tokenSymbol) {
902
+ if (!this.spotMeta) return null;
903
+ const tokenIndex = this.spotTokenNameToIndex.get(tokenSymbol.toUpperCase());
904
+ if (tokenIndex === void 0) return null;
905
+ const token = this.spotMeta.tokens[tokenIndex];
906
+ return {
907
+ name: token.name,
908
+ index: token.index,
909
+ szDecimals: token.szDecimals,
910
+ weiDecimals: token.weiDecimals,
911
+ tokenId: token.tokenId
912
+ };
913
+ }
914
+ /**
915
+ * Get all available quote assets
916
+ * Optimized: O(1) pre-computed array instead of O(n) computation
917
+ */
918
+ getAvailableQuoteAssets() {
919
+ return this.quoteAssets;
920
+ }
921
+ /**
922
+ * Get raw metadata (for advanced use cases)
923
+ */
924
+ getRawMetadata() {
925
+ return {
926
+ spotMeta: this.spotMeta,
927
+ perpsMeta: this.perpsMeta,
928
+ perpDexs: this.perpDexs,
929
+ hip3DexsMeta: Object.fromEntries(this.hip3DexsMeta)
930
+ };
931
+ }
932
+ /**
933
+ * Get network configuration
934
+ */
935
+ getNetworkInfo() {
936
+ return {
937
+ isTestnet: this.isTestnet,
938
+ useStaticFallback: this.config.useStaticFallback,
939
+ initialized: this.initialized
940
+ };
941
+ }
942
+ };
943
+
944
+ // lib/utils/formatter.ts
945
+ import { Decimal } from "decimal.js";
946
+ var formatPriceAndSize = ({
947
+ px,
948
+ sz,
949
+ szDecimals,
950
+ isSpot
951
+ }) => {
952
+ const priceDecimals = getPriceDecimals(px, szDecimals, isSpot);
953
+ const price = new Decimal(px).toDP(priceDecimals).toNumber();
954
+ const size = new Decimal(sz).toDP(szDecimals, Decimal.ROUND_DOWN).toNumber();
955
+ return {
956
+ price,
957
+ size
958
+ };
959
+ };
960
+ var formatPriceForOrder = ({
961
+ px,
962
+ szDecimals,
963
+ isSpot
964
+ }) => {
965
+ const priceDecimals = getPriceDecimals(px, szDecimals, isSpot);
966
+ const price = new Decimal(px).toDP(priceDecimals).toNumber();
967
+ return price;
968
+ };
969
+ var formatSizeForOrder = ({
970
+ sz,
971
+ szDecimals
972
+ }) => {
973
+ return new Decimal(sz).toDP(szDecimals, Decimal.ROUND_DOWN).toNumber();
974
+ };
975
+ function getPriceDecimals(price, szDecimals, isSpot) {
976
+ const baseDecimals = isSpot ? 8 : 6;
977
+ const maxDP = Math.max(baseDecimals - szDecimals, 0);
978
+ const maxSigFigs = 5;
979
+ let minDecimals;
980
+ if (price >= 1e5) {
981
+ minDecimals = 0;
982
+ } else {
983
+ const exp = Math.floor(Math.log10(price));
984
+ const dp = Math.max(maxSigFigs - exp - 1, 0);
985
+ minDecimals = Math.min(dp, maxDP);
986
+ }
987
+ return minDecimals;
988
+ }
989
+ export {
990
+ CloidClientCode,
991
+ CloidClientCodeNameById,
992
+ MetadataClient,
993
+ PUP_TOKEN_ADDRESS,
994
+ PUP_TOKEN_THRESHOLDS,
995
+ TARGET_APPROVED_MAX_BUILDER_FEE,
996
+ TARGET_APPROVED_MAX_BUILDER_FEE_PERCENT,
997
+ TESTNET_USDC_SPOT_TOKEN,
998
+ USDC_SPOT_TOKEN,
999
+ WidgetType,
1000
+ WidgetTypeById,
1001
+ XP_BOOST_PERCENTAGES,
1002
+ buildCloid,
1003
+ calculateBoostPercentage,
1004
+ calculateTotalPupAmount,
1005
+ decodeSlug,
1006
+ encodeSlug,
1007
+ formatPriceAndSize,
1008
+ formatPriceForOrder,
1009
+ formatSizeForOrder,
1010
+ getApprovalAmount,
1011
+ getClientCodeNameById,
1012
+ getCloid,
1013
+ getNextTierInfo,
1014
+ getPriceDecimals,
1015
+ getWidgetTypeById,
1016
+ isBasedCloid,
1017
+ isClientCode,
1018
+ isMiniAppCloid,
1019
+ isMiniAppTriggeredCloid,
1020
+ isTenantCloid,
1021
+ isTrackingIdCloid,
1022
+ isWidgetType,
1023
+ normaliseSlug,
1024
+ normaliseTrackingId,
1025
+ normalizeAirdropAmount,
1026
+ parseCloid
1027
+ };