@xchainjs/xchain-mayachain-query 2.1.1 → 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 })));
@@ -211,6 +212,22 @@ class Mayanode {
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 })));
@@ -219,6 +220,22 @@ class Mayanode {
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.1",
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": [