From e89d79365086512d845bb498deed7ee66ecd2fc0 Mon Sep 17 00:00:00 2001 From: Mohammed Ryaan Date: Wed, 30 Jul 2025 19:30:25 +0530 Subject: [PATCH] feat: use statics to get denom of tokens TICKET: COIN-5004 --- modules/abstract-cosmos/src/lib/utils.ts | 14 ++++++++++++++ modules/abstract-cosmos/test/unit/cosmosToken.ts | 5 +++++ modules/sdk-coin-asi/src/lib/constants.ts | 5 ++++- modules/sdk-coin-atom/src/lib/constants.ts | 5 ++++- modules/sdk-coin-baby/src/lib/constants.ts | 5 ++++- modules/sdk-coin-bld/src/lib/constants.ts | 5 ++++- modules/sdk-coin-coreum/src/lib/constants.ts | 7 ++++--- modules/sdk-coin-coreum/src/lib/utils.ts | 7 +------ modules/sdk-coin-cronos/src/lib/constants.ts | 11 ++++++++++- modules/sdk-coin-hash/src/lib/constants.ts | 5 ++++- modules/sdk-coin-initia/src/lib/constants.ts | 5 ++++- modules/sdk-coin-injective/src/lib/constants.ts | 5 ++++- modules/sdk-coin-osmo/src/lib/constants.ts | 5 ++++- modules/sdk-coin-rune/src/lib/constants.ts | 6 ++++-- modules/sdk-coin-rune/src/lib/utils.ts | 6 +----- modules/sdk-coin-sei/src/lib/constants.ts | 5 ++++- modules/sdk-coin-tia/src/lib/constants.ts | 5 ++++- modules/sdk-coin-zeta/src/lib/constants.ts | 5 ++++- modules/statics/src/base.ts | 3 +++ 19 files changed, 86 insertions(+), 28 deletions(-) diff --git a/modules/abstract-cosmos/src/lib/utils.ts b/modules/abstract-cosmos/src/lib/utils.ts index d1452d96b8..2ac2abf1ef 100644 --- a/modules/abstract-cosmos/src/lib/utils.ts +++ b/modules/abstract-cosmos/src/lib/utils.ts @@ -19,6 +19,7 @@ import { Registry, } from '@cosmjs/proto-signing'; import { Coin, defaultRegistryTypes } from '@cosmjs/stargate'; +import { coins } from '@bitgo/statics'; import BigNumber from 'bignumber.js'; import { SignDoc, TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'; import { Any } from 'cosmjs-types/google/protobuf/any'; @@ -933,6 +934,19 @@ export class CosmosUtils implements BaseUtils { getHashFunction(): Hash { return createHash('sha256'); } + + getTokenDenomsUsingCoinFamily(coinFamily: string): string[] { + // using set to remove duplicates as denom can be same on testnet and mainnet for a few tokens + return [ + ...new Set( + coins + .filter( + (coin) => coin.family.toLowerCase() === coinFamily.toLowerCase() && coin.isToken && coin.denom !== undefined + ) + .map((coin) => coin.denom as string) + ), + ]; + } } const utils = new CosmosUtils(); diff --git a/modules/abstract-cosmos/test/unit/cosmosToken.ts b/modules/abstract-cosmos/test/unit/cosmosToken.ts index b06fe15473..4023cd5b85 100644 --- a/modules/abstract-cosmos/test/unit/cosmosToken.ts +++ b/modules/abstract-cosmos/test/unit/cosmosToken.ts @@ -3,6 +3,7 @@ import 'should'; import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test'; import { BitGoAPI } from '@bitgo/sdk-api'; import { CosmosToken } from '../../src'; +import CosmosUtils from '../../src/lib/utils'; describe('Cosmos Tokens', function () { let bitgo: TestBitGoAPI; @@ -46,4 +47,8 @@ describe('Cosmos Tokens', function () { mainnetCosmosToken.denom.should.equal('uylds.fcc'); mainnetCosmosToken.decimalPlaces.should.equal(6); }); + + it('should return denomination for YLDS token on hash using hash as coinFamily', function () { + CosmosUtils.getTokenDenomsUsingCoinFamily('hash').should.deepEqual(['uylds.fcc']); + }); }); diff --git a/modules/sdk-coin-asi/src/lib/constants.ts b/modules/sdk-coin-asi/src/lib/constants.ts index 24739fd1d2..76eafa25ad 100644 --- a/modules/sdk-coin-asi/src/lib/constants.ts +++ b/modules/sdk-coin-asi/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['fet', 'tfet', 'afet', 'atestfet']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['fet', 'tfet', 'afet', 'atestfet', ...cosmosUtils.getTokenDenomsUsingCoinFamily('asi')]; export const accountAddressRegex = /^(fetch)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(fetchvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(fetch)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-atom/src/lib/constants.ts b/modules/sdk-coin-atom/src/lib/constants.ts index 20099da7f8..1e52d8b5b8 100644 --- a/modules/sdk-coin-atom/src/lib/constants.ts +++ b/modules/sdk-coin-atom/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['natom', 'uatom', 'matom', 'atom']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['natom', 'uatom', 'matom', 'atom', ...cosmosUtils.getTokenDenomsUsingCoinFamily('atom')]; export const accountAddressRegex = /^(cosmos)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(cosmosvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(cosmos)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-baby/src/lib/constants.ts b/modules/sdk-coin-baby/src/lib/constants.ts index c49e787523..d66efb5c25 100644 --- a/modules/sdk-coin-baby/src/lib/constants.ts +++ b/modules/sdk-coin-baby/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['baby', 'tbaby', 'ubbn']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['baby', 'tbaby', 'ubbn', ...cosmosUtils.getTokenDenomsUsingCoinFamily('baby')]; export const accountAddressRegex = /^(bbn)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(bbnvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(bbn)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-bld/src/lib/constants.ts b/modules/sdk-coin-bld/src/lib/constants.ts index 4c37bc7386..9d339c3019 100644 --- a/modules/sdk-coin-bld/src/lib/constants.ts +++ b/modules/sdk-coin-bld/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['nbld', 'ubld', 'mbld', 'bld']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['nbld', 'ubld', 'mbld', 'bld', ...cosmosUtils.getTokenDenomsUsingCoinFamily('bld')]; export const accountAddressRegex = /^(agoric)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(agoricvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(agoric)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-coreum/src/lib/constants.ts b/modules/sdk-coin-coreum/src/lib/constants.ts index dbf4406a5b..9eb480e28d 100644 --- a/modules/sdk-coin-coreum/src/lib/constants.ts +++ b/modules/sdk-coin-coreum/src/lib/constants.ts @@ -1,9 +1,10 @@ -export const mainnetValidDenoms = ['ucore']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['ucore', 'utestcore', ...cosmosUtils.getTokenDenomsUsingCoinFamily('coreum')]; export const mainnetAccountAddressRegex = /^(core)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const mainnetValidatorAddressRegex = /^(corevaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const MAINNET_ADDRESS_PREFIX = 'core'; - -export const testnetValidDenoms = ['utestcore']; export const testnetAccountAddressRegex = /^(testcore)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const testnetValidatorAddressRegex = /^(testcorevaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const TESTNET_ADDRESS_PREFIX = 'testcore'; diff --git a/modules/sdk-coin-coreum/src/lib/utils.ts b/modules/sdk-coin-coreum/src/lib/utils.ts index 6c448f5334..0c4bc44d5b 100644 --- a/modules/sdk-coin-coreum/src/lib/utils.ts +++ b/modules/sdk-coin-coreum/src/lib/utils.ts @@ -35,12 +35,7 @@ export class CoreumUtils extends CosmosUtils { if (amountBig.isLessThanOrEqualTo(0)) { throw new InvalidTransactionError('transactionBuilder: validateAmount: Invalid amount: ' + amount.amount); } - if ( - (this.networkType === NetworkType.TESTNET && - !constants.testnetValidDenoms.find((denom) => denom === amount.denom)) || - (this.networkType === NetworkType.MAINNET && - !constants.mainnetValidDenoms.find((denom) => denom === amount.denom)) - ) { + if (!constants.validDenoms.find((denom) => denom === amount.denom)) { throw new InvalidTransactionError('transactionBuilder: validateAmount: Invalid denom: ' + amount.denom); } } diff --git a/modules/sdk-coin-cronos/src/lib/constants.ts b/modules/sdk-coin-cronos/src/lib/constants.ts index 9855d0f711..2b94306e81 100644 --- a/modules/sdk-coin-cronos/src/lib/constants.ts +++ b/modules/sdk-coin-cronos/src/lib/constants.ts @@ -1,4 +1,13 @@ -export const validDenoms = ['cro', 'tcro', 'basecro', 'basetcro']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = [ + 'cro', + 'tcro', + 'basecro', + 'basetcro', + ...cosmosUtils.getTokenDenomsUsingCoinFamily('cronos'), +]; export const mainnetAccountAddressRegex = /^(cro)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const mainnetValidatorAddressRegex = /^(crocncl)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; diff --git a/modules/sdk-coin-hash/src/lib/constants.ts b/modules/sdk-coin-hash/src/lib/constants.ts index 09ad0b3f05..0cc6531c35 100644 --- a/modules/sdk-coin-hash/src/lib/constants.ts +++ b/modules/sdk-coin-hash/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['nhash', 'uhash', 'mhash', 'hash', 'uylds.fcc']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['nhash', 'uhash', 'mhash', 'hash', ...cosmosUtils.getTokenDenomsUsingCoinFamily('hash')]; export const mainnetAccountAddressRegex = /^(pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const mainnetValidatorAddressRegex = /^(pbvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const mainnetContractAddressRegex = /^(pb)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-initia/src/lib/constants.ts b/modules/sdk-coin-initia/src/lib/constants.ts index 15bbda5ed3..52911c816e 100644 --- a/modules/sdk-coin-initia/src/lib/constants.ts +++ b/modules/sdk-coin-initia/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['init', 'tinit', 'uinit']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['init', 'tinit', 'uinit', ...cosmosUtils.getTokenDenomsUsingCoinFamily('initia')]; export const accountAddressRegex = /^(init)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(initvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(init)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-injective/src/lib/constants.ts b/modules/sdk-coin-injective/src/lib/constants.ts index e2bcc1100f..63be5e92f8 100644 --- a/modules/sdk-coin-injective/src/lib/constants.ts +++ b/modules/sdk-coin-injective/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['ninj', 'uinj', 'minj', 'inj']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['ninj', 'uinj', 'minj', 'inj', ...cosmosUtils.getTokenDenomsUsingCoinFamily('injective')]; export const accountAddressRegex = /^(inj)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(injvaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(inj)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-osmo/src/lib/constants.ts b/modules/sdk-coin-osmo/src/lib/constants.ts index 5be7e1b0c7..6dff560844 100644 --- a/modules/sdk-coin-osmo/src/lib/constants.ts +++ b/modules/sdk-coin-osmo/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['nosmo', 'uosmo', 'mosmo', 'osmo']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['nosmo', 'uosmo', 'mosmo', 'osmo', ...cosmosUtils.getTokenDenomsUsingCoinFamily('osmo')]; export const accountAddressRegex = /^(osmo)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(osmovaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(osmo)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-rune/src/lib/constants.ts b/modules/sdk-coin-rune/src/lib/constants.ts index d3ab80c953..b8517a0eea 100644 --- a/modules/sdk-coin-rune/src/lib/constants.ts +++ b/modules/sdk-coin-rune/src/lib/constants.ts @@ -1,9 +1,11 @@ -export const mainnetValidDenoms = ['rune']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['rune', ...cosmosUtils.getTokenDenomsUsingCoinFamily('thor')]; export const mainnetAccountAddressRegex = /^(thor)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const mainnetValidatorAddressRegex = /^(thor)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const MAINNET_ADDRESS_PREFIX = 'thor'; -export const testnetValidDenoms = ['rune']; export const testnetAccountAddressRegex = /^(sthor)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const testnetValidatorAddressRegex = /^(sthor)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const TESTNET_ADDRESS_PREFIX = 'sthor'; diff --git a/modules/sdk-coin-rune/src/lib/utils.ts b/modules/sdk-coin-rune/src/lib/utils.ts index 9ec2aa8c5e..58f3028e04 100644 --- a/modules/sdk-coin-rune/src/lib/utils.ts +++ b/modules/sdk-coin-rune/src/lib/utils.ts @@ -152,11 +152,7 @@ export class RuneUtils extends CosmosUtils { } validateDenomination(amountDenom: string): void { - if ( - (this.networkType === NetworkType.TESTNET && - !constants.testnetValidDenoms.find((denom) => denom === amountDenom)) || - (this.networkType === NetworkType.MAINNET && !constants.mainnetValidDenoms.find((denom) => denom === amountDenom)) - ) { + if (!constants.validDenoms.find((denom) => denom === amountDenom)) { throw new InvalidTransactionError('transactionBuilder: validateAmount: Invalid denom: ' + amountDenom); } } diff --git a/modules/sdk-coin-sei/src/lib/constants.ts b/modules/sdk-coin-sei/src/lib/constants.ts index c3235dab75..5d0656f74e 100644 --- a/modules/sdk-coin-sei/src/lib/constants.ts +++ b/modules/sdk-coin-sei/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['nsei', 'usei', 'msei', 'sei']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['nsei', 'usei', 'msei', 'sei', ...cosmosUtils.getTokenDenomsUsingCoinFamily('sei')]; export const accountAddressRegex = /^(sei)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(seivaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(sei)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-tia/src/lib/constants.ts b/modules/sdk-coin-tia/src/lib/constants.ts index 86ffd7f756..bfd041259b 100644 --- a/modules/sdk-coin-tia/src/lib/constants.ts +++ b/modules/sdk-coin-tia/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['ntia', 'utia', 'mtia', 'tia']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['ntia', 'utia', 'mtia', 'tia', ...cosmosUtils.getTokenDenomsUsingCoinFamily('tia')]; export const accountAddressRegex = /^(celestia)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(celestiavaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(celestia)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/sdk-coin-zeta/src/lib/constants.ts b/modules/sdk-coin-zeta/src/lib/constants.ts index ac502c7d59..b930697cb0 100644 --- a/modules/sdk-coin-zeta/src/lib/constants.ts +++ b/modules/sdk-coin-zeta/src/lib/constants.ts @@ -1,4 +1,7 @@ -export const validDenoms = ['azeta']; +import { CosmosUtils } from '@bitgo/abstract-cosmos'; + +const cosmosUtils = new CosmosUtils(); +export const validDenoms = ['azeta', ...cosmosUtils.getTokenDenomsUsingCoinFamily('zeta')]; export const accountAddressRegex = /^(zeta)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const validatorAddressRegex = /^(zetavaloper)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]{38})$/; export const contractAddressRegex = /^(zeta)1(['qpzry9x8gf2tvdw0s3jn54khce6mua7l]+)$/; diff --git a/modules/statics/src/base.ts b/modules/statics/src/base.ts index 2d303eb89b..ae9d9eee17 100644 --- a/modules/statics/src/base.ts +++ b/modules/statics/src/base.ts @@ -2990,6 +2990,7 @@ export interface BaseCoinConstructorOptions { alias?: string; // alternative name usually used during name migrations prefix?: string; suffix?: string; + denom?: string; // the denomination of the coin baseUnit: string; // the base unit for each coin. e.g. satoshi for BTC kind: CoinKind; isToken: boolean; @@ -3012,6 +3013,7 @@ export abstract class BaseCoin { public readonly name: string; public readonly prefix?: string; public readonly suffix?: string; + public readonly denom?: string; public readonly baseUnit: string; /* Property to help during migration of token names. @@ -3110,6 +3112,7 @@ export abstract class BaseCoin { this.alias = options.alias; this.prefix = options.prefix; this.suffix = options.suffix; + this.denom = options.denom; this.baseUnit = options.baseUnit; this.kind = options.kind; this.family = options.network.family;