diff --git a/modules/abstract-cosmos/src/cosmosToken.ts b/modules/abstract-cosmos/src/cosmosToken.ts new file mode 100644 index 0000000000..ade0f80100 --- /dev/null +++ b/modules/abstract-cosmos/src/cosmosToken.ts @@ -0,0 +1,63 @@ +import { BitGoBase, CoinConstructor, NamedCoinConstructor } from '@bitgo/sdk-core'; +import { CosmosTokenConfig, coins, tokens } from '@bitgo/statics'; +import { CosmosCoin } from './cosmosCoin'; + +export class CosmosToken extends CosmosCoin { + public readonly tokenConfig: CosmosTokenConfig; + + constructor(bitgo: BitGoBase, tokenConfig: CosmosTokenConfig) { + const staticsCoin = coins.get(tokenConfig.coin); + super(bitgo, staticsCoin); + this.tokenConfig = tokenConfig; + } + + static createTokenConstructor(config: CosmosTokenConfig): CoinConstructor { + return (bitgo: BitGoBase) => new CosmosToken(bitgo, config); + } + + static createTokenConstructors(): NamedCoinConstructor[] { + const tokensCtors: NamedCoinConstructor[] = []; + for (const token of [...tokens.bitcoin.cosmos.tokens, ...tokens.testnet.cosmos.tokens]) { + const tokenConstructor = CosmosToken.createTokenConstructor(token); + tokensCtors.push({ name: token.type, coinConstructor: tokenConstructor }); + } + return tokensCtors; + } + + get name(): string { + return this.tokenConfig.name; + } + + get coin(): string { + return this.tokenConfig.coin; + } + + get network(): string { + return this.tokenConfig.network; + } + + get denom(): string { + return this.tokenConfig.denom; + } + + get decimalPlaces(): number { + return this.tokenConfig.decimalPlaces; + } + + getChain(): string { + return this.tokenConfig.type; + } + + getBaseChain(): string { + return this.coin; + } + + getFullName(): string { + // Eg - returns "Atom Token", "Osmo Token" + return `${this.tokenConfig.coin.charAt(0).toUpperCase()}${this.tokenConfig.coin.slice(1)} Token`; + } + + getBaseFactor(): number { + return Math.pow(10, this.tokenConfig.decimalPlaces); + } +} diff --git a/modules/abstract-cosmos/src/index.ts b/modules/abstract-cosmos/src/index.ts index 017c99c5c0..f1de7d43ac 100644 --- a/modules/abstract-cosmos/src/index.ts +++ b/modules/abstract-cosmos/src/index.ts @@ -1,2 +1,3 @@ export * from './lib'; export { CosmosCoin } from './cosmosCoin'; +export { CosmosToken } from './cosmosToken'; diff --git a/modules/abstract-cosmos/src/register.ts b/modules/abstract-cosmos/src/register.ts new file mode 100644 index 0000000000..acf83d28b9 --- /dev/null +++ b/modules/abstract-cosmos/src/register.ts @@ -0,0 +1,8 @@ +import { BitGoBase } from '@bitgo/sdk-core'; +import { CosmosToken } from './cosmosToken'; + +export const register = (sdk: BitGoBase): void => { + CosmosToken.createTokenConstructors().forEach(({ name, coinConstructor }) => { + sdk.register(name, coinConstructor); + }); +}; diff --git a/modules/statics/src/index.ts b/modules/statics/src/index.ts index 18d0035be3..b001d8119d 100644 --- a/modules/statics/src/index.ts +++ b/modules/statics/src/index.ts @@ -27,6 +27,7 @@ export { Sip10Token, Nep141Token, VetToken, + CosmosChainToken, } from './account'; export { CoinMap } from './map'; export { networkFeatureMapForTokens } from './networkFeatureMapForTokens'; diff --git a/modules/statics/src/tokenConfig.ts b/modules/statics/src/tokenConfig.ts index 2c4abbbc78..eadb1d33ab 100644 --- a/modules/statics/src/tokenConfig.ts +++ b/modules/statics/src/tokenConfig.ts @@ -26,6 +26,7 @@ import { WorldERC20Token, XrpCoin, ZkethERC20Token, + CosmosChainToken, } from './account'; import { CoinFamily, CoinKind, BaseCoin } from './base'; import { coins } from './coins'; @@ -118,6 +119,10 @@ export type VetTokenConfig = BaseNetworkConfig & { contractAddress: string; }; +export type CosmosTokenConfig = BaseNetworkConfig & { + denom: string; +}; + export type TokenConfig = | Erc20TokenConfig | StellarTokenConfig @@ -219,6 +224,9 @@ export interface Tokens { vet: { tokens: VetTokenConfig[]; }; + cosmos: { + tokens: CosmosTokenConfig[]; + }; }; testnet: { eth: { @@ -300,6 +308,9 @@ export interface Tokens { vet: { tokens: VetTokenConfig[]; }; + cosmos: { + tokens: CosmosTokenConfig[]; + }; }; } @@ -878,6 +889,25 @@ const getFormattedVetTokens = (customCoinMap = coins) => return acc; }, []); +const getFormattedCosmosChainTokens = (customCoinMap = coins) => + customCoinMap.reduce((acc: CosmosTokenConfig[], coin) => { + if (coin instanceof CosmosChainToken) { + acc.push(getCosmosTokenConfig(coin)); + } + return acc; + }, []); + +function getCosmosTokenConfig(coin: CosmosChainToken): CosmosTokenConfig { + return { + type: coin.name, + coin: coin.name.split(':')[0].toLowerCase(), + network: coin.network.type === NetworkType.MAINNET ? 'Mainnet' : 'Testnet', + name: coin.fullName, + denom: coin.denom, + decimalPlaces: coin.decimalPlaces, + }; +} + export const getFormattedTokens = (coinMap = coins): Tokens => { const formattedAptNFTCollections = getFormattedAptNFTCollections(coinMap); return { @@ -965,6 +995,9 @@ export const getFormattedTokens = (coinMap = coins): Tokens => { vet: { tokens: getFormattedVetTokens(coinMap).filter((token) => token.network === 'Mainnet'), }, + cosmos: { + tokens: getFormattedCosmosChainTokens(coinMap).filter((token) => token.network === 'Mainnet'), + }, }, testnet: { eth: { @@ -1050,6 +1083,9 @@ export const getFormattedTokens = (coinMap = coins): Tokens => { vet: { tokens: getFormattedVetTokens(coinMap).filter((token) => token.network === 'Testnet'), }, + cosmos: { + tokens: getFormattedCosmosChainTokens(coinMap).filter((token) => token.network === 'Testnet'), + }, }, }; };