@xchainjs/xchain-mayachain-query 2.1.0 → 2.1.2

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/lib/index.esm.js CHANGED
@@ -2,7 +2,7 @@ import { assetFromStringEx, assetToString, baseAmount, CryptoAmount, CachedValue
2
2
  import { MidgardQuery } from '@xchainjs/xchain-mayamidgard-query';
3
3
  import BigNumber from 'bignumber.js';
4
4
  import { Network } from '@xchainjs/xchain-client';
5
- import { QuoteApi, Configuration, MimirApi, NetworkApi, TradeUnitApi, TradeUnitsApi, TradeAccountApi, TradeAccountsApi } from '@xchainjs/xchain-mayanode';
5
+ import { QuoteApi, Configuration, MimirApi, NetworkApi, PoolsApi, TradeUnitApi, TradeUnitsApi, TradeAccountApi, TradeAccountsApi } from '@xchainjs/xchain-mayanode';
6
6
  import axios from 'axios';
7
7
  import axiosRetry from 'axios-retry';
8
8
 
@@ -60,6 +60,7 @@ class Mayanode {
60
60
  this.quoteApis = this.config.mayanodeBaseUrls.map((url) => new QuoteApi(new Configuration({ basePath: url })));
61
61
  this.mimirApis = this.config.mayanodeBaseUrls.map((url) => new MimirApi(new Configuration({ basePath: url })));
62
62
  this.networkApis = this.config.mayanodeBaseUrls.map((url) => new NetworkApi(new Configuration({ basePath: url })));
63
+ this.poolsApis = this.config.mayanodeBaseUrls.map((url) => new PoolsApi(new Configuration({ basePath: url })));
63
64
  this.tradeUnitApis = this.config.mayanodeBaseUrls.map((url) => new TradeUnitApi(new Configuration({ basePath: url })));
64
65
  this.tradeUnitsApis = this.config.mayanodeBaseUrls.map((url) => new TradeUnitsApi(new Configuration({ basePath: url })));
65
66
  this.tradeAccountApis = this.config.mayanodeBaseUrls.map((url) => new TradeAccountApi(new Configuration({ basePath: url })));
@@ -88,7 +89,7 @@ class Mayanode {
88
89
  streamingInterval, streamingQuantity, toleranceBps, undefined, // liquidityToleranceBps
89
90
  affiliateBps === null || affiliateBps === void 0 ? void 0 : affiliateBps.toString(), affiliate)).data;
90
91
  }
91
- catch (e) { }
92
+ catch (_e) { }
92
93
  }
93
94
  throw new Error(`MAYANode not responding`);
94
95
  });
@@ -103,7 +104,7 @@ class Mayanode {
103
104
  try {
104
105
  return (yield api.mimir()).data;
105
106
  }
106
- catch (e) { }
107
+ catch (_e) { }
107
108
  }
108
109
  throw Error(`MAYANode not responding`);
109
110
  });
@@ -119,7 +120,7 @@ class Mayanode {
119
120
  const resp = (yield api.inboundAddresses()).data;
120
121
  return resp;
121
122
  }
122
- catch (e) { }
123
+ catch (_e) { }
123
124
  }
124
125
  throw new Error(`MAYANode not responding`);
125
126
  });
@@ -135,7 +136,7 @@ class Mayanode {
135
136
  try {
136
137
  return (yield api.lastblock(height)).data;
137
138
  }
138
- catch (e) { }
139
+ catch (_e) { }
139
140
  }
140
141
  throw Error(`MAYANode not responding`);
141
142
  });
@@ -153,7 +154,7 @@ class Mayanode {
153
154
  const resp = (yield api.tradeUnit(asset, height)).data;
154
155
  return resp;
155
156
  }
156
- catch (e) { }
157
+ catch (_e) { }
157
158
  }
158
159
  throw new Error(`MAYANode not responding. Can not get asset trade units`);
159
160
  });
@@ -170,7 +171,7 @@ class Mayanode {
170
171
  const resp = (yield api.tradeUnits(height)).data;
171
172
  return resp;
172
173
  }
173
- catch (e) { }
174
+ catch (_e) { }
174
175
  }
175
176
  throw new Error(`MAYANode not responding. Can not get trade units`);
176
177
  });
@@ -188,7 +189,7 @@ class Mayanode {
188
189
  const resp = (yield api.tradeAccount(address, height)).data;
189
190
  return resp;
190
191
  }
191
- catch (e) { }
192
+ catch (_e) { }
192
193
  }
193
194
  throw new Error(`MAYANode not responding. Can not get trade asset account`);
194
195
  });
@@ -206,11 +207,27 @@ class Mayanode {
206
207
  const resp = (yield api.tradeAccounts(asset, height)).data;
207
208
  return resp;
208
209
  }
209
- catch (e) { }
210
+ catch (_e) { }
210
211
  }
211
212
  throw new Error(`MAYANode not responding. Can not get trade asset accounts`);
212
213
  });
213
214
  }
215
+ /**
216
+ * Get all available pools.
217
+ * @param height - optional MAYAChain height, default, latest block
218
+ * @returns pool data
219
+ */
220
+ getPools(height) {
221
+ return __awaiter(this, void 0, void 0, function* () {
222
+ for (const api of this.poolsApis) {
223
+ try {
224
+ return (yield api.pools(height)).data;
225
+ }
226
+ catch (_e) { }
227
+ }
228
+ throw new Error(`MAYANode not responding`);
229
+ });
230
+ }
214
231
  }
215
232
 
216
233
  const BtcAsset = assetFromStringEx('BTC.BTC');
@@ -245,6 +262,10 @@ const getBaseAmountWithDiffDecimals = (inputAmount, outDecimals) => {
245
262
  const getCryptoAmountWithNotation = (amount, notation) => {
246
263
  const inputAmountBaseNotation = amount.baseAmount.amount();
247
264
  const decimalsDiff = notation - amount.baseAmount.decimal;
265
+ // Ensure we don't create negative decimals
266
+ if (notation < 0) {
267
+ throw new Error(`Invalid notation: ${notation}. Decimals cannot be negative.`);
268
+ }
248
269
  return new CryptoAmount(baseAmount(inputAmountBaseNotation.times(Math.pow(10, decimalsDiff)), notation), amount.asset);
249
270
  };
250
271
 
@@ -291,14 +312,29 @@ class MayachainCache {
291
312
  return __awaiter(this, void 0, void 0, function* () {
292
313
  if (!this.assetDecimalsCache)
293
314
  throw Error(`Could not refresh assets decimals`);
294
- return yield this.assetDecimalsCache.getValue();
315
+ try {
316
+ return yield this.assetDecimalsCache.getValue();
317
+ }
318
+ catch (error) {
319
+ // Fallback: if cache refresh fails (e.g., Mayamidgard is down), use static fallback
320
+ console.warn('Maya asset decimals cache refresh failed, using static fallback:', error);
321
+ return this.getFallbackAssetDecimals();
322
+ }
295
323
  });
296
324
  }
297
325
  getPools() {
298
326
  return __awaiter(this, void 0, void 0, function* () {
299
327
  if (!this.poolsCache)
300
328
  throw Error(`Could not refresh pools cache`);
301
- return yield this.poolsCache.getValue();
329
+ try {
330
+ return yield this.poolsCache.getValue();
331
+ }
332
+ catch (error) {
333
+ // If pools cache fails to refresh (e.g., Mayamidgard is down), throw the error
334
+ // The calling code should handle this gracefully with optimistic fallbacks
335
+ console.warn('Maya pools cache refresh failed:', error);
336
+ throw error;
337
+ }
302
338
  });
303
339
  }
304
340
  /**
@@ -356,29 +392,117 @@ class MayachainCache {
356
392
  */
357
393
  refreshAssetDecimalsCache() {
358
394
  return __awaiter(this, void 0, void 0, function* () {
359
- // Implementation details for refreshing the asset decimals cache
360
- // TODO: As soon as Mayachain returns native decimals from any endpoint of its API, refactor the function
361
- return {
362
- 'BTC.BTC': 8,
363
- 'ETH.ETH': 18,
364
- 'DASH.DASH': 8,
365
- 'KUJI.KUJI': 6,
366
- 'THOR.RUNE': 8,
367
- 'MAYA.CACAO': 10,
368
- 'ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7': 6,
369
- 'ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': 6,
370
- 'ETH.WSTETH-0X7F39C581F595B53C5CB19BD0B3F8DA6C935E2CA0': 18,
371
- 'KUJI.USK': 6,
372
- };
395
+ try {
396
+ // Try to get pool data and extract decimals if available
397
+ const pools = yield this.midgardQuery.getPools();
398
+ const decimals = {};
399
+ for (const pool of pools) {
400
+ if (pool.nativeDecimal) {
401
+ const decimal = Number(pool.nativeDecimal);
402
+ // Only use the decimal value if it's a valid positive number
403
+ if (decimal >= 0) {
404
+ decimals[pool.asset] = decimal;
405
+ }
406
+ }
407
+ }
408
+ // Merge with fallback data for assets that don't have native decimals specified
409
+ return Object.assign(Object.assign({}, this.getFallbackAssetDecimals()), decimals);
410
+ }
411
+ catch (error) {
412
+ console.warn('Failed to refresh Maya asset decimals from pools, using fallback:', error);
413
+ return this.getFallbackAssetDecimals();
414
+ }
373
415
  });
374
416
  }
417
+ /**
418
+ * Provides fallback decimal values for Maya assets when Mayamidgard is unavailable.
419
+ * Data sourced from https://mayanode.mayachain.info/mayachain/pools
420
+ * Updated with live pool data as of latest fetch
421
+ */
422
+ getFallbackAssetDecimals() {
423
+ return {
424
+ // Current Maya pools with verified decimals from Mayanode
425
+ 'BTC.BTC': 8,
426
+ 'ARB.USDC-0xaf88d065e77c8cC2239327C5EDb3A432268e5831': 6,
427
+ 'ARB.USDT-0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9': 6,
428
+ 'ARB.LEO-0x5985D2Dc68E67aeE82F4e30e8e74F1ea8e532a3c': 3,
429
+ 'ARB.TGT-0X429FED88F10285E61B12BDF00848315FBDFCC341': 18,
430
+ 'ARB.TGT-0x429FED88F10285E61B12BDF00848315FBDFCC341': 18,
431
+ 'ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': 6,
432
+ 'ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7': 6,
433
+ 'KUJI.KUJI': 6,
434
+ 'KUJI.USK': 6,
435
+ 'THOR.RUNE': 8,
436
+ // Chain defaults for native assets
437
+ 'ETH.ETH': 18,
438
+ 'ARB.ETH': 18,
439
+ 'MAYA.CACAO': 10,
440
+ // Additional pool assets (using chain defaults where decimals not specified)
441
+ 'DASH.DASH': 8,
442
+ 'XDR.XDR': 18,
443
+ 'ZEC.ZEC': 8,
444
+ // Legacy mappings for backward compatibility
445
+ 'ETH.WSTETH-0X7F39C581F595B53C5CB19BD0B3F8DA6C935E2CA0': 18,
446
+ };
447
+ }
375
448
  /**
376
449
  * Refreshes the Pools cache
377
450
  * @returns {PoolDetail[]} the list of pools
378
451
  */
379
452
  refreshPoolsCache() {
380
453
  return __awaiter(this, void 0, void 0, function* () {
381
- return this.midgardQuery.getPools();
454
+ try {
455
+ // Try Mayanode first (like THORChain uses Thornode first)
456
+ const mayanodePools = yield this.mayanode.getPools();
457
+ return this.convertMayanodePoolsToMidgardFormat(mayanodePools);
458
+ }
459
+ catch (error) {
460
+ console.warn('Mayanode pools unavailable, falling back to Mayamidgard:', error);
461
+ // Fallback to Midgard like before
462
+ return this.midgardQuery.getPools();
463
+ }
464
+ });
465
+ }
466
+ /**
467
+ * Convert Mayanode pool format to Midgard PoolDetail format
468
+ * @param pools - Pools from Mayanode API
469
+ * @returns PoolDetail array compatible with Midgard format
470
+ */
471
+ convertMayanodePoolsToMidgardFormat(pools) {
472
+ return pools.map((pool) => {
473
+ var _a;
474
+ // Get the fallback decimal for this asset if available
475
+ const fallbackDecimals = this.getFallbackAssetDecimals();
476
+ const nativeDecimal = ((_a = fallbackDecimals[pool.asset]) === null || _a === void 0 ? void 0 : _a.toString()) || '8';
477
+ // Calculate units from liquidityUnits and synthUnits
478
+ const liquidityUnits = pool.LP_units;
479
+ const synthUnits = '0';
480
+ return {
481
+ // Core pool data from Mayanode
482
+ asset: pool.asset,
483
+ assetDepth: pool.balance_asset,
484
+ runeDepth: pool.balance_cacao,
485
+ liquidityUnits,
486
+ status: 'available', // Assume available if returned by Mayanode
487
+ // Calculated fields
488
+ assetPrice: pool.balance_cacao && pool.balance_asset
489
+ ? (parseFloat(pool.balance_cacao) / parseFloat(pool.balance_asset)).toString()
490
+ : '0',
491
+ // Required fields with appropriate defaults
492
+ annualPercentageRate: '0',
493
+ assetPriceUSD: '0',
494
+ nativeDecimal,
495
+ poolAPY: '0',
496
+ saversAPR: '0',
497
+ saversDepth: '0',
498
+ saversUnits: '0',
499
+ synthSupply: '0',
500
+ synthUnits,
501
+ totalCollateral: '0',
502
+ totalDebtTor: '0',
503
+ units: new BigNumber(liquidityUnits || '0').plus(new BigNumber(synthUnits)).toString(),
504
+ volume24h: '0',
505
+ };
382
506
  });
383
507
  }
384
508
  }
@@ -572,12 +696,41 @@ class MayachainQuery {
572
696
  if (isSynthAsset(asset))
573
697
  return DEFAULT_MAYACHAIN_DECIMALS;
574
698
  const assetNotation = assetToString(asset);
575
- const assetsDecimals = yield this.mayachainCache.getAssetDecimals();
576
- if (!assetsDecimals[assetNotation])
577
- throw Error(`Can not get decimals for ${assetNotation}`);
578
- return assetsDecimals[assetNotation];
699
+ try {
700
+ const assetsDecimals = yield this.mayachainCache.getAssetDecimals();
701
+ if (assetsDecimals[assetNotation]) {
702
+ return assetsDecimals[assetNotation];
703
+ }
704
+ // Fallback for unknown assets: use chain defaults
705
+ console.warn(`No decimal mapping found for ${assetNotation}, using chain default`);
706
+ return this.getChainDefaultDecimals(asset.chain);
707
+ }
708
+ catch (error) {
709
+ // Fallback if asset decimals cache fails entirely
710
+ console.warn(`Failed to get asset decimals for ${assetNotation}, using chain default:`, error);
711
+ return this.getChainDefaultDecimals(asset.chain);
712
+ }
579
713
  });
580
714
  }
715
+ /**
716
+ * Get default decimal places for a chain when specific asset data is unavailable
717
+ * @param chain - The chain to get default decimals for
718
+ * @returns Default decimal places for the chain
719
+ */
720
+ getChainDefaultDecimals(chain) {
721
+ const chainDefaults = {
722
+ BTC: 8,
723
+ ETH: 18,
724
+ ARB: 18,
725
+ KUJI: 6,
726
+ THOR: 8,
727
+ MAYA: 10,
728
+ DASH: 8,
729
+ XDR: 18,
730
+ ZEC: 8,
731
+ };
732
+ return chainDefaults[chain] || 8; // Ultimate fallback to 8 decimals
733
+ }
581
734
  /**
582
735
  * Get pools details
583
736
  * @returns {PoolDetail[]} pools details
@@ -603,10 +756,12 @@ class MayachainQuery {
603
756
  const poolDetails = yield this.mayachainCache.getPools();
604
757
  const getCryptoAmount = (assetDecimals, asset, amount) => {
605
758
  const decimals = asset in assetDecimals ? assetDecimals[asset] : DEFAULT_MAYACHAIN_DECIMALS;
759
+ // Ensure decimals is valid (not negative or undefined)
760
+ const validDecimals = typeof decimals === 'number' && decimals >= 0 ? decimals : DEFAULT_MAYACHAIN_DECIMALS;
606
761
  const assetFormatted = assetFromStringEx(asset);
607
- return decimals === DEFAULT_MAYACHAIN_DECIMALS || eqAsset(CacaoAsset, assetFormatted)
608
- ? new CryptoAmount(baseAmount(amount, decimals), assetFormatted)
609
- : getCryptoAmountWithNotation(new CryptoAmount(baseAmount(amount), assetFormatted), decimals);
762
+ return validDecimals === DEFAULT_MAYACHAIN_DECIMALS || eqAsset(CacaoAsset, assetFormatted)
763
+ ? new CryptoAmount(baseAmount(amount, validDecimals), assetFormatted)
764
+ : getCryptoAmountWithNotation(new CryptoAmount(baseAmount(amount), assetFormatted), validDecimals);
610
765
  };
611
766
  return {
612
767
  count: actionsResume.count ? Number(actionsResume.count) : 0,
package/lib/index.js CHANGED
@@ -68,6 +68,7 @@ class Mayanode {
68
68
  this.quoteApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.QuoteApi(new xchainMayanode.Configuration({ basePath: url })));
69
69
  this.mimirApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.MimirApi(new xchainMayanode.Configuration({ basePath: url })));
70
70
  this.networkApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.NetworkApi(new xchainMayanode.Configuration({ basePath: url })));
71
+ this.poolsApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.PoolsApi(new xchainMayanode.Configuration({ basePath: url })));
71
72
  this.tradeUnitApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.TradeUnitApi(new xchainMayanode.Configuration({ basePath: url })));
72
73
  this.tradeUnitsApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.TradeUnitsApi(new xchainMayanode.Configuration({ basePath: url })));
73
74
  this.tradeAccountApis = this.config.mayanodeBaseUrls.map((url) => new xchainMayanode.TradeAccountApi(new xchainMayanode.Configuration({ basePath: url })));
@@ -96,7 +97,7 @@ class Mayanode {
96
97
  streamingInterval, streamingQuantity, toleranceBps, undefined, // liquidityToleranceBps
97
98
  affiliateBps === null || affiliateBps === void 0 ? void 0 : affiliateBps.toString(), affiliate)).data;
98
99
  }
99
- catch (e) { }
100
+ catch (_e) { }
100
101
  }
101
102
  throw new Error(`MAYANode not responding`);
102
103
  });
@@ -111,7 +112,7 @@ class Mayanode {
111
112
  try {
112
113
  return (yield api.mimir()).data;
113
114
  }
114
- catch (e) { }
115
+ catch (_e) { }
115
116
  }
116
117
  throw Error(`MAYANode not responding`);
117
118
  });
@@ -127,7 +128,7 @@ class Mayanode {
127
128
  const resp = (yield api.inboundAddresses()).data;
128
129
  return resp;
129
130
  }
130
- catch (e) { }
131
+ catch (_e) { }
131
132
  }
132
133
  throw new Error(`MAYANode not responding`);
133
134
  });
@@ -143,7 +144,7 @@ class Mayanode {
143
144
  try {
144
145
  return (yield api.lastblock(height)).data;
145
146
  }
146
- catch (e) { }
147
+ catch (_e) { }
147
148
  }
148
149
  throw Error(`MAYANode not responding`);
149
150
  });
@@ -161,7 +162,7 @@ class Mayanode {
161
162
  const resp = (yield api.tradeUnit(asset, height)).data;
162
163
  return resp;
163
164
  }
164
- catch (e) { }
165
+ catch (_e) { }
165
166
  }
166
167
  throw new Error(`MAYANode not responding. Can not get asset trade units`);
167
168
  });
@@ -178,7 +179,7 @@ class Mayanode {
178
179
  const resp = (yield api.tradeUnits(height)).data;
179
180
  return resp;
180
181
  }
181
- catch (e) { }
182
+ catch (_e) { }
182
183
  }
183
184
  throw new Error(`MAYANode not responding. Can not get trade units`);
184
185
  });
@@ -196,7 +197,7 @@ class Mayanode {
196
197
  const resp = (yield api.tradeAccount(address, height)).data;
197
198
  return resp;
198
199
  }
199
- catch (e) { }
200
+ catch (_e) { }
200
201
  }
201
202
  throw new Error(`MAYANode not responding. Can not get trade asset account`);
202
203
  });
@@ -214,11 +215,27 @@ class Mayanode {
214
215
  const resp = (yield api.tradeAccounts(asset, height)).data;
215
216
  return resp;
216
217
  }
217
- catch (e) { }
218
+ catch (_e) { }
218
219
  }
219
220
  throw new Error(`MAYANode not responding. Can not get trade asset accounts`);
220
221
  });
221
222
  }
223
+ /**
224
+ * Get all available pools.
225
+ * @param height - optional MAYAChain height, default, latest block
226
+ * @returns pool data
227
+ */
228
+ getPools(height) {
229
+ return __awaiter(this, void 0, void 0, function* () {
230
+ for (const api of this.poolsApis) {
231
+ try {
232
+ return (yield api.pools(height)).data;
233
+ }
234
+ catch (_e) { }
235
+ }
236
+ throw new Error(`MAYANode not responding`);
237
+ });
238
+ }
222
239
  }
223
240
 
224
241
  const BtcAsset = xchainUtil.assetFromStringEx('BTC.BTC');
@@ -253,6 +270,10 @@ const getBaseAmountWithDiffDecimals = (inputAmount, outDecimals) => {
253
270
  const getCryptoAmountWithNotation = (amount, notation) => {
254
271
  const inputAmountBaseNotation = amount.baseAmount.amount();
255
272
  const decimalsDiff = notation - amount.baseAmount.decimal;
273
+ // Ensure we don't create negative decimals
274
+ if (notation < 0) {
275
+ throw new Error(`Invalid notation: ${notation}. Decimals cannot be negative.`);
276
+ }
256
277
  return new xchainUtil.CryptoAmount(xchainUtil.baseAmount(inputAmountBaseNotation.times(Math.pow(10, decimalsDiff)), notation), amount.asset);
257
278
  };
258
279
 
@@ -299,14 +320,29 @@ class MayachainCache {
299
320
  return __awaiter(this, void 0, void 0, function* () {
300
321
  if (!this.assetDecimalsCache)
301
322
  throw Error(`Could not refresh assets decimals`);
302
- return yield this.assetDecimalsCache.getValue();
323
+ try {
324
+ return yield this.assetDecimalsCache.getValue();
325
+ }
326
+ catch (error) {
327
+ // Fallback: if cache refresh fails (e.g., Mayamidgard is down), use static fallback
328
+ console.warn('Maya asset decimals cache refresh failed, using static fallback:', error);
329
+ return this.getFallbackAssetDecimals();
330
+ }
303
331
  });
304
332
  }
305
333
  getPools() {
306
334
  return __awaiter(this, void 0, void 0, function* () {
307
335
  if (!this.poolsCache)
308
336
  throw Error(`Could not refresh pools cache`);
309
- return yield this.poolsCache.getValue();
337
+ try {
338
+ return yield this.poolsCache.getValue();
339
+ }
340
+ catch (error) {
341
+ // If pools cache fails to refresh (e.g., Mayamidgard is down), throw the error
342
+ // The calling code should handle this gracefully with optimistic fallbacks
343
+ console.warn('Maya pools cache refresh failed:', error);
344
+ throw error;
345
+ }
310
346
  });
311
347
  }
312
348
  /**
@@ -364,29 +400,117 @@ class MayachainCache {
364
400
  */
365
401
  refreshAssetDecimalsCache() {
366
402
  return __awaiter(this, void 0, void 0, function* () {
367
- // Implementation details for refreshing the asset decimals cache
368
- // TODO: As soon as Mayachain returns native decimals from any endpoint of its API, refactor the function
369
- return {
370
- 'BTC.BTC': 8,
371
- 'ETH.ETH': 18,
372
- 'DASH.DASH': 8,
373
- 'KUJI.KUJI': 6,
374
- 'THOR.RUNE': 8,
375
- 'MAYA.CACAO': 10,
376
- 'ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7': 6,
377
- 'ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': 6,
378
- 'ETH.WSTETH-0X7F39C581F595B53C5CB19BD0B3F8DA6C935E2CA0': 18,
379
- 'KUJI.USK': 6,
380
- };
403
+ try {
404
+ // Try to get pool data and extract decimals if available
405
+ const pools = yield this.midgardQuery.getPools();
406
+ const decimals = {};
407
+ for (const pool of pools) {
408
+ if (pool.nativeDecimal) {
409
+ const decimal = Number(pool.nativeDecimal);
410
+ // Only use the decimal value if it's a valid positive number
411
+ if (decimal >= 0) {
412
+ decimals[pool.asset] = decimal;
413
+ }
414
+ }
415
+ }
416
+ // Merge with fallback data for assets that don't have native decimals specified
417
+ return Object.assign(Object.assign({}, this.getFallbackAssetDecimals()), decimals);
418
+ }
419
+ catch (error) {
420
+ console.warn('Failed to refresh Maya asset decimals from pools, using fallback:', error);
421
+ return this.getFallbackAssetDecimals();
422
+ }
381
423
  });
382
424
  }
425
+ /**
426
+ * Provides fallback decimal values for Maya assets when Mayamidgard is unavailable.
427
+ * Data sourced from https://mayanode.mayachain.info/mayachain/pools
428
+ * Updated with live pool data as of latest fetch
429
+ */
430
+ getFallbackAssetDecimals() {
431
+ return {
432
+ // Current Maya pools with verified decimals from Mayanode
433
+ 'BTC.BTC': 8,
434
+ 'ARB.USDC-0xaf88d065e77c8cC2239327C5EDb3A432268e5831': 6,
435
+ 'ARB.USDT-0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9': 6,
436
+ 'ARB.LEO-0x5985D2Dc68E67aeE82F4e30e8e74F1ea8e532a3c': 3,
437
+ 'ARB.TGT-0X429FED88F10285E61B12BDF00848315FBDFCC341': 18,
438
+ 'ARB.TGT-0x429FED88F10285E61B12BDF00848315FBDFCC341': 18,
439
+ 'ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': 6,
440
+ 'ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7': 6,
441
+ 'KUJI.KUJI': 6,
442
+ 'KUJI.USK': 6,
443
+ 'THOR.RUNE': 8,
444
+ // Chain defaults for native assets
445
+ 'ETH.ETH': 18,
446
+ 'ARB.ETH': 18,
447
+ 'MAYA.CACAO': 10,
448
+ // Additional pool assets (using chain defaults where decimals not specified)
449
+ 'DASH.DASH': 8,
450
+ 'XDR.XDR': 18,
451
+ 'ZEC.ZEC': 8,
452
+ // Legacy mappings for backward compatibility
453
+ 'ETH.WSTETH-0X7F39C581F595B53C5CB19BD0B3F8DA6C935E2CA0': 18,
454
+ };
455
+ }
383
456
  /**
384
457
  * Refreshes the Pools cache
385
458
  * @returns {PoolDetail[]} the list of pools
386
459
  */
387
460
  refreshPoolsCache() {
388
461
  return __awaiter(this, void 0, void 0, function* () {
389
- return this.midgardQuery.getPools();
462
+ try {
463
+ // Try Mayanode first (like THORChain uses Thornode first)
464
+ const mayanodePools = yield this.mayanode.getPools();
465
+ return this.convertMayanodePoolsToMidgardFormat(mayanodePools);
466
+ }
467
+ catch (error) {
468
+ console.warn('Mayanode pools unavailable, falling back to Mayamidgard:', error);
469
+ // Fallback to Midgard like before
470
+ return this.midgardQuery.getPools();
471
+ }
472
+ });
473
+ }
474
+ /**
475
+ * Convert Mayanode pool format to Midgard PoolDetail format
476
+ * @param pools - Pools from Mayanode API
477
+ * @returns PoolDetail array compatible with Midgard format
478
+ */
479
+ convertMayanodePoolsToMidgardFormat(pools) {
480
+ return pools.map((pool) => {
481
+ var _a;
482
+ // Get the fallback decimal for this asset if available
483
+ const fallbackDecimals = this.getFallbackAssetDecimals();
484
+ const nativeDecimal = ((_a = fallbackDecimals[pool.asset]) === null || _a === void 0 ? void 0 : _a.toString()) || '8';
485
+ // Calculate units from liquidityUnits and synthUnits
486
+ const liquidityUnits = pool.LP_units;
487
+ const synthUnits = '0';
488
+ return {
489
+ // Core pool data from Mayanode
490
+ asset: pool.asset,
491
+ assetDepth: pool.balance_asset,
492
+ runeDepth: pool.balance_cacao,
493
+ liquidityUnits,
494
+ status: 'available', // Assume available if returned by Mayanode
495
+ // Calculated fields
496
+ assetPrice: pool.balance_cacao && pool.balance_asset
497
+ ? (parseFloat(pool.balance_cacao) / parseFloat(pool.balance_asset)).toString()
498
+ : '0',
499
+ // Required fields with appropriate defaults
500
+ annualPercentageRate: '0',
501
+ assetPriceUSD: '0',
502
+ nativeDecimal,
503
+ poolAPY: '0',
504
+ saversAPR: '0',
505
+ saversDepth: '0',
506
+ saversUnits: '0',
507
+ synthSupply: '0',
508
+ synthUnits,
509
+ totalCollateral: '0',
510
+ totalDebtTor: '0',
511
+ units: new BigNumber__default.default(liquidityUnits || '0').plus(new BigNumber__default.default(synthUnits)).toString(),
512
+ volume24h: '0',
513
+ };
390
514
  });
391
515
  }
392
516
  }
@@ -580,12 +704,41 @@ class MayachainQuery {
580
704
  if (xchainUtil.isSynthAsset(asset))
581
705
  return DEFAULT_MAYACHAIN_DECIMALS;
582
706
  const assetNotation = xchainUtil.assetToString(asset);
583
- const assetsDecimals = yield this.mayachainCache.getAssetDecimals();
584
- if (!assetsDecimals[assetNotation])
585
- throw Error(`Can not get decimals for ${assetNotation}`);
586
- return assetsDecimals[assetNotation];
707
+ try {
708
+ const assetsDecimals = yield this.mayachainCache.getAssetDecimals();
709
+ if (assetsDecimals[assetNotation]) {
710
+ return assetsDecimals[assetNotation];
711
+ }
712
+ // Fallback for unknown assets: use chain defaults
713
+ console.warn(`No decimal mapping found for ${assetNotation}, using chain default`);
714
+ return this.getChainDefaultDecimals(asset.chain);
715
+ }
716
+ catch (error) {
717
+ // Fallback if asset decimals cache fails entirely
718
+ console.warn(`Failed to get asset decimals for ${assetNotation}, using chain default:`, error);
719
+ return this.getChainDefaultDecimals(asset.chain);
720
+ }
587
721
  });
588
722
  }
723
+ /**
724
+ * Get default decimal places for a chain when specific asset data is unavailable
725
+ * @param chain - The chain to get default decimals for
726
+ * @returns Default decimal places for the chain
727
+ */
728
+ getChainDefaultDecimals(chain) {
729
+ const chainDefaults = {
730
+ BTC: 8,
731
+ ETH: 18,
732
+ ARB: 18,
733
+ KUJI: 6,
734
+ THOR: 8,
735
+ MAYA: 10,
736
+ DASH: 8,
737
+ XDR: 18,
738
+ ZEC: 8,
739
+ };
740
+ return chainDefaults[chain] || 8; // Ultimate fallback to 8 decimals
741
+ }
589
742
  /**
590
743
  * Get pools details
591
744
  * @returns {PoolDetail[]} pools details
@@ -611,10 +764,12 @@ class MayachainQuery {
611
764
  const poolDetails = yield this.mayachainCache.getPools();
612
765
  const getCryptoAmount = (assetDecimals, asset, amount) => {
613
766
  const decimals = asset in assetDecimals ? assetDecimals[asset] : DEFAULT_MAYACHAIN_DECIMALS;
767
+ // Ensure decimals is valid (not negative or undefined)
768
+ const validDecimals = typeof decimals === 'number' && decimals >= 0 ? decimals : DEFAULT_MAYACHAIN_DECIMALS;
614
769
  const assetFormatted = xchainUtil.assetFromStringEx(asset);
615
- return decimals === DEFAULT_MAYACHAIN_DECIMALS || xchainUtil.eqAsset(CacaoAsset, assetFormatted)
616
- ? new xchainUtil.CryptoAmount(xchainUtil.baseAmount(amount, decimals), assetFormatted)
617
- : getCryptoAmountWithNotation(new xchainUtil.CryptoAmount(xchainUtil.baseAmount(amount), assetFormatted), decimals);
770
+ return validDecimals === DEFAULT_MAYACHAIN_DECIMALS || xchainUtil.eqAsset(CacaoAsset, assetFormatted)
771
+ ? new xchainUtil.CryptoAmount(xchainUtil.baseAmount(amount, validDecimals), assetFormatted)
772
+ : getCryptoAmountWithNotation(new xchainUtil.CryptoAmount(xchainUtil.baseAmount(amount), assetFormatted), validDecimals);
618
773
  };
619
774
  return {
620
775
  count: actionsResume.count ? Number(actionsResume.count) : 0,
@@ -46,9 +46,21 @@ export declare class MayachainCache {
46
46
  * Refreshes the number of decimals of the supported Mayachain tokens.
47
47
  */
48
48
  private refreshAssetDecimalsCache;
49
+ /**
50
+ * Provides fallback decimal values for Maya assets when Mayamidgard is unavailable.
51
+ * Data sourced from https://mayanode.mayachain.info/mayachain/pools
52
+ * Updated with live pool data as of latest fetch
53
+ */
54
+ private getFallbackAssetDecimals;
49
55
  /**
50
56
  * Refreshes the Pools cache
51
57
  * @returns {PoolDetail[]} the list of pools
52
58
  */
53
59
  private refreshPoolsCache;
60
+ /**
61
+ * Convert Mayanode pool format to Midgard PoolDetail format
62
+ * @param pools - Pools from Mayanode API
63
+ * @returns PoolDetail array compatible with Midgard format
64
+ */
65
+ private convertMayanodePoolsToMidgardFormat;
54
66
  }
@@ -67,6 +67,12 @@ export declare class MayachainQuery {
67
67
  * @throws {Error} if the asset is not supported in Mayachain
68
68
  */
69
69
  getAssetDecimals(asset: CompatibleAsset): Promise<number>;
70
+ /**
71
+ * Get default decimal places for a chain when specific asset data is unavailable
72
+ * @param chain - The chain to get default decimals for
73
+ * @returns Default decimal places for the chain
74
+ */
75
+ private getChainDefaultDecimals;
70
76
  /**
71
77
  * Get pools details
72
78
  * @returns {PoolDetail[]} pools details
@@ -1,5 +1,5 @@
1
1
  import { Network } from '@xchainjs/xchain-client';
2
- import { InboundAddress, LastBlock, MimirResponse, QuoteSwapResponse, TradeAccountsResponse, TradeUnitResponse, TradeUnitsResponse } from '@xchainjs/xchain-mayanode';
2
+ import { InboundAddress, LastBlock, MimirResponse, PoolsResponse, QuoteSwapResponse, TradeAccountsResponse, TradeUnitResponse, TradeUnitsResponse } from '@xchainjs/xchain-mayanode';
3
3
  import { Address } from '@xchainjs/xchain-util';
4
4
  export type MayanodeConfig = {
5
5
  apiRetries: number;
@@ -11,6 +11,7 @@ export declare class Mayanode {
11
11
  private quoteApis;
12
12
  private mimirApis;
13
13
  private networkApis;
14
+ private poolsApis;
14
15
  private tradeUnitApis;
15
16
  private tradeUnitsApis;
16
17
  private tradeAccountApis;
@@ -74,4 +75,10 @@ export declare class Mayanode {
74
75
  * @returns Returns all trade accounts for an asset
75
76
  */
76
77
  getTradeAssetAccounts(asset: string, height?: number): Promise<TradeAccountsResponse>;
78
+ /**
79
+ * Get all available pools.
80
+ * @param height - optional MAYAChain height, default, latest block
81
+ * @returns pool data
82
+ */
83
+ getPools(height?: number): Promise<PoolsResponse>;
77
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xchainjs/xchain-mayachain-query",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "license": "MIT",
5
5
  "description": "Mayachain query module that is responsible for estimating swap calculations and add/remove liquidity for thorchain",
6
6
  "keywords": [
@@ -29,18 +29,18 @@
29
29
  "build:release": "yarn exec rm -rf release && yarn pack && yarn exec \"mkdir release && tar zxvf package.tgz --directory release && rm package.tgz\"",
30
30
  "test": "jest",
31
31
  "e2e": "jest --config jest.config.e2e.mjs",
32
- "lint": "eslint \"{src,__tests__}/**/*.ts\" --fix --max-warnings 0",
32
+ "lint": "eslint --config ../../eslint.config.mjs \"{src,__tests__}/**/*.ts\" --fix --max-warnings 0",
33
33
  "postversion": "git push --follow-tags"
34
34
  },
35
35
  "dependencies": {
36
- "@xchainjs/xchain-client": "2.0.8",
36
+ "@xchainjs/xchain-client": "2.0.9",
37
37
  "@xchainjs/xchain-mayamidgard": "1.0.4",
38
- "@xchainjs/xchain-mayamidgard-query": "1.0.9",
38
+ "@xchainjs/xchain-mayamidgard-query": "1.0.10",
39
39
  "@xchainjs/xchain-mayanode": "1.1.0",
40
- "@xchainjs/xchain-util": "2.0.4",
41
- "axios": "1.8.4",
40
+ "@xchainjs/xchain-util": "2.0.5",
41
+ "axios": "1.12.1",
42
42
  "axios-retry": "3.2.5",
43
- "bignumber.js": "^9.0.0"
43
+ "bignumber.js": "^9.1.2"
44
44
  },
45
45
  "devDependencies": {
46
46
  "axios-mock-adapter": "2.1.0"