Skip to content

feat(bitgo): add method to register single token from ams in coin factory #6256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions modules/bitgo/src/bitgo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import * as _ from 'lodash';

import { BaseCoin, CoinFactory, common } from '@bitgo/sdk-core';
import { BitGoAPI, BitGoAPIOptions } from '@bitgo/sdk-api';
import { createTokenMapUsingTrimmedConfigDetails, TrimmedAmsTokenConfig } from '@bitgo/statics';
import { GlobalCoinFactory, registerCoinConstructors } from './v2/coinFactory';
import {
createTokenMapUsingTrimmedConfigDetails,
TrimmedAmsTokenConfig,
createToken,
getFormattedTokenConfigForCoin,
} from '@bitgo/statics';
import { GlobalCoinFactory, registerCoinConstructors, getTokenConstructor } from './v2/coinFactory';

// constructor params used exclusively for BitGo class
export type BitGoOptions = BitGoAPIOptions & {
Expand Down Expand Up @@ -56,8 +61,12 @@ export class BitGo extends BitGoAPI {
this._coinFactory = new CoinFactory();
}

/**
* Initialize the coin factory with token configurations
* @param tokenConfigMap - A map of token metadata from AMS
*/
initCoinFactory(tokenConfigMap: Record<string, TrimmedAmsTokenConfig[]>): void {
// TODO(WIN-5057): use AMS endpoint to fetch config details
// TODO(WIN-5839): use AMS endpoint to fetch config details
const coinMap = createTokenMapUsingTrimmedConfigDetails(tokenConfigMap);
this._coinFactory = new CoinFactory();
registerCoinConstructors(this._coinFactory, coinMap);
Expand All @@ -74,6 +83,27 @@ export class BitGo extends BitGoAPI {
return GlobalCoinFactory.getInstance(this, coinName);
}

/**
* Register a token in the coin factory
* @param tokenConfig - The token metadata from AMS
*/
registerToken(tokenConfig: TrimmedAmsTokenConfig): void {
if (!this._useAms) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we set this to true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consumer sets this variable to true when initializing bitgo class.

throw new Error('registerToken is only supported when useAms is set to true');
}
// TODO(WIN-5839): use AMS endpoint to fetch token metadata
const staticsBaseCoin = createToken(tokenConfig);
if (staticsBaseCoin) {
const formattedTokenConfig = getFormattedTokenConfigForCoin(staticsBaseCoin);
if (formattedTokenConfig) {
const tokenConstructor = getTokenConstructor(formattedTokenConfig);
if (tokenConstructor) {
this._coinFactory.registerToken(staticsBaseCoin, tokenConstructor);
}
}
}
}

/**
* Create a basecoin object for a virtual token
* @param tokenName
Expand Down
100 changes: 98 additions & 2 deletions modules/bitgo/src/v2/coinFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,29 @@ import { HbarToken } from '@bitgo/sdk-coin-hbar';
import { Near, TNear } from '@bitgo/sdk-coin-near';
import { SolToken } from '@bitgo/sdk-coin-sol';
import { TrxToken } from '@bitgo/sdk-coin-trx';
import { CoinFactory } from '@bitgo/sdk-core';
import { CoinMap, coins, getFormattedTokens } from '@bitgo/statics';
import { CoinFactory, CoinConstructor } from '@bitgo/sdk-core';
import {
CoinMap,
coins,
getFormattedTokens,
TokenConfig,
Erc20TokenConfig,
StellarTokenConfig,
OfcTokenConfig,
CeloTokenConfig,
EthLikeTokenConfig,
EosTokenConfig,
AvaxcTokenConfig,
SolTokenConfig,
HbarTokenConfig,
AdaTokenConfig,
AlgoTokenConfig,
TrxTokenConfig,
XrpTokenConfig,
SuiTokenConfig,
AptTokenConfig,
Sip10TokenConfig,
} from '@bitgo/statics';
import {
Ada,
Algo,
Expand Down Expand Up @@ -457,6 +478,81 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
);
}

export function getTokenConstructor(tokenConfig: TokenConfig): CoinConstructor | undefined {
switch (tokenConfig.coin) {
case 'eth':
case 'hteth':
return Erc20Token.createTokenConstructor(tokenConfig as Erc20TokenConfig);
case 'xlm':
case 'txlm':
return StellarToken.createTokenConstructor(tokenConfig as StellarTokenConfig);
case 'ofc':
return OfcToken.createTokenConstructor(tokenConfig as OfcTokenConfig);
case 'celo':
case 'tcelo':
return CeloToken.createTokenConstructor(tokenConfig as CeloTokenConfig);
case 'bsc':
case 'tbsc':
return BscToken.createTokenConstructor(tokenConfig as Erc20TokenConfig);
case 'eos':
case 'teos':
return EosToken.createTokenConstructor(tokenConfig as EosTokenConfig);
case 'algo':
case 'talgo':
return AlgoToken.createTokenConstructor(tokenConfig as AlgoTokenConfig);
case 'avaxc':
case 'tavaxc':
return AvaxCToken.createTokenConstructor(tokenConfig as AvaxcTokenConfig);
case 'polygon':
case 'tpolygon':
return PolygonToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'soneium':
case 'tsoneium':
return SoneiumToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'arbeth':
case 'tarbeth':
return ArbethToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'opeth':
case 'topeth':
return OpethToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'zketh':
case 'tzketh':
return ZkethToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'bera':
case 'tbera':
return BeraToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'coredao':
case 'tcoredao':
return CoredaoToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
case 'sol':
case 'tsol':
return SolToken.createTokenConstructor(tokenConfig as SolTokenConfig);
case 'hbar':
case 'thbar':
return HbarToken.createTokenConstructor(tokenConfig as HbarTokenConfig);
case 'trx':
case 'ttrx':
return TrxToken.createTokenConstructor(tokenConfig as TrxTokenConfig);
case 'ada':
case 'tada':
return AdaToken.createTokenConstructor(tokenConfig as AdaTokenConfig);
case 'sui':
case 'tsui':
return SuiToken.createTokenConstructor(tokenConfig as SuiTokenConfig);
case 'xrp':
case 'txrp':
return XrpToken.createTokenConstructor(tokenConfig as XrpTokenConfig);
case 'apt':
case 'tapt':
return AptToken.createTokenConstructor(tokenConfig as AptTokenConfig);
case 'sip10':
case 'tsip10':
return Sip10Token.createTokenConstructor(tokenConfig as Sip10TokenConfig);
default:
return undefined;
}
}

export const GlobalCoinFactory: CoinFactory = new CoinFactory();

registerCoinConstructors(GlobalCoinFactory);
12 changes: 12 additions & 0 deletions modules/bitgo/test/v2/unit/ams/ams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,16 @@ describe('Asset metadata service', () => {
'Coin or token type hteth:faketoken not supported or not compiled. Please be sure that you are using the latest version of BitGoJS. If using @bitgo/sdk-api, please confirm you have registered hteth:faketoken first.'
);
});

it('should be able to register a token in the coin factory', () => {
const tokenName = 'hteth:faketoken';
const amsToken = reducedAmsTokenConfig[tokenName][0];
bitgo.registerToken(amsToken);
const coin = bitgo.coin(tokenName);
should.exist(coin);
coin.type.should.equal(tokenName);
coin.name.should.equal('Holesky Testnet fake token');
coin.decimalPlaces.should.equal(6);
coin.tokenContractAddress.should.equal('0x89a959b9184b4f8c8633646d5dfd049d2ebc983a');
});
});