Skip to content
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
27 changes: 20 additions & 7 deletions modules/bitgo/src/v2/coinFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -904,31 +904,44 @@ export function getCoinConstructor(coinName: string): CoinConstructor | undefine
}
}

export const buildEthLikeChainToTestnetMap = (): Record<string, string> => {
const map: Record<string, string> = {};
export const buildEthLikeChainToTestnetMap = (): {
mainnetToTestnetMap: Record<string, string>;
testnetToMainnetMap: Record<string, string>;
} => {
const testnetToMainnetMap: Record<string, string> = {};
const mainnetToTestnetMap: Record<string, string> = {};

const enabledEvmCoins = ['ip'];

// TODO: remove ip coin here and remove other evm coins from switch block, once changes are tested (Ticket: https://bitgoinc.atlassian.net/browse/WIN-7835)
coins.forEach((coin) => {
if (coin.network.type === NetworkType.TESTNET && !coin.isToken && enabledEvmCoins.includes(coin.family)) {
if (coins.get(coin.family)?.features.includes(CoinFeature.SUPPORTS_ERC20)) {
map[coin.family] = `${coin.name}`;
mainnetToTestnetMap[coin.family] = `${coin.name}`;
testnetToMainnetMap[coin.name] = `${coin.family}`;
}
}
});

return map;
return { mainnetToTestnetMap, testnetToMainnetMap };
};

// TODO: add IP token here and test changes (Ticket: https://bitgoinc.atlassian.net/browse/WIN-7835)
const ethLikeChainToTestnetMap: Record<string, string> = buildEthLikeChainToTestnetMap();
const { mainnetToTestnetMap, testnetToMainnetMap } = buildEthLikeChainToTestnetMap();

export function getTokenConstructor(tokenConfig: TokenConfig): CoinConstructor | undefined {
if (tokenConfig.coin in ethLikeChainToTestnetMap) {
const testnetCoin = mainnetToTestnetMap[tokenConfig.coin];
if (testnetCoin) {
return EthLikeErc20Token.createTokenConstructor(tokenConfig as EthLikeTokenConfig, {
Mainnet: tokenConfig.coin,
Testnet: ethLikeChainToTestnetMap[tokenConfig.coin],
Testnet: testnetCoin,
});
}
const mainnetCoin = testnetToMainnetMap[tokenConfig.coin];
if (mainnetCoin) {
return EthLikeErc20Token.createTokenConstructor(tokenConfig as EthLikeTokenConfig, {
Mainnet: mainnetCoin,
Testnet: tokenConfig.coin,
});
}
switch (tokenConfig.coin) {
Expand Down
22 changes: 22 additions & 0 deletions modules/bitgo/test/v2/resources/amsTokenConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,26 @@ export const reducedAmsTokenConfig = {
contractAddress: '0x89a959b9184b4f8c8633646d5dfd049d2ebc983a',
},
],
'tip:faketoken': [
{
id: 'a1b2c3d4-e5f6-4789-8abc-def123456789',
fullName: 'Story Testnet Faketoken',
name: 'tip:faketoken',
prefix: '',
suffix: 'TIP:FAKETOKEN',
baseUnit: 'wei',
kind: 'crypto',
family: 'ip',
isToken: true,
additionalFeatures: [],
excludedFeatures: [],
decimalPlaces: 18,
asset: 'tip:faketoken',
network: {
name: 'BaseChainTestnet',
},
primaryKeyCurve: 'secp256k1',
contractAddress: '0x1234567890123456789012345678901234567890',
},
],
};
31 changes: 31 additions & 0 deletions modules/bitgo/test/v2/unit/ams/ams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,36 @@ describe('Asset metadata service', () => {
const coin = bitgo.coin(tokenName);
should.exist(coin);
});

it('should register a EVM coin token from statics library if available', async () => {
const bitgo = TestBitGo.decorate(BitGo, { env: 'mock', microservicesUri, useAms: true } as BitGoOptions);
bitgo.initializeTestVars();
await bitgo.registerToken('tip:usdc');
const coin = bitgo.coin('tip:usdc');
should.exist(coin);
});

it('should register an EVM coin token from AMS', async () => {
const bitgo = TestBitGo.decorate(BitGo, { env: 'mock', microservicesUri, useAms: true } as BitGoOptions);
bitgo.initializeTestVars();

const tokenName = 'tip:faketoken';

// Setup nocks for AMS API call
nock(microservicesUri).get(`/api/v1/assets/name/${tokenName}`).reply(200, reducedAmsTokenConfig[tokenName][0]);

await bitgo.registerToken(tokenName);
const coin = bitgo.coin(tokenName);
should.exist(coin);
coin.type.should.equal(tokenName);
const staticsCoin = coin.getConfig();
staticsCoin.name.should.equal('tip');
staticsCoin.decimalPlaces.should.equal(18);
// For EVM tokens, contractAddress is available on the statics coin
if ('contractAddress' in staticsCoin && staticsCoin.contractAddress) {
(staticsCoin.contractAddress as string).should.equal('0x1234567890123456789012345678901234567890');
}
staticsCoin.family.should.equal('ip');
});
});
});
12 changes: 11 additions & 1 deletion modules/statics/src/coins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ export function createToken(token: AmsTokenConfig): Readonly<BaseCoin> | undefin
];

switch (family) {
case erc20ChainToNameMap[family]:
return initializer(
...commonArgs.slice(0, 4), // id, name, fullName, decimalPlaces
token.contractAddress || token.tokenAddress, // contractAddress
token.asset,
token.network,
token.features,
token.prefix,
token.suffix,
token.primaryKeyCurve
);
case 'arbeth':
case 'avaxc':
case 'baseeth':
Expand All @@ -152,7 +163,6 @@ export function createToken(token: AmsTokenConfig): Readonly<BaseCoin> | undefin
case 'opeth':
case 'polygon':
case 'trx':
case erc20ChainToNameMap[family]:
return initializer(
...commonArgs.slice(0, 4), // id, name, fullName, decimalPlaces
token.contractAddress || token.tokenAddress, // contractAddress
Expand Down
2 changes: 2 additions & 0 deletions modules/statics/src/tokenConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,8 @@ export function getFormattedTokenConfigForCoin(coin: Readonly<BaseCoin>): TokenC
return getJettonTokenConfig(coin);
} else if (coin instanceof FlrERC20Token) {
return getFlrTokenConfig(coin);
} else if (coin instanceof EthLikeERC20Token) {
return getEthLikeTokenConfig(coin);
}
return undefined;
}
19 changes: 19 additions & 0 deletions modules/statics/test/unit/coins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import {
reducedAmsTokenConfig,
reducedTokenConfigForAllChains,
} from './resources/amsTokenConfig';
import { EthLikeErc20Token } from '../../../sdk-coin-evm/src';
import { allCoinsAndTokens } from '../../src/allCoinsAndTokens';

interface DuplicateCoinObject {
name: string;
Expand Down Expand Up @@ -1280,4 +1282,21 @@ describe('create token map using config details', () => {
}
}
});

it('should create tokens for all EVM coins using createToken', () => {
const evmCoinTokens = allCoinsAndTokens
.filter((coin) => coin.isToken && coins.get(coin.family)?.features.includes(CoinFeature.SUPPORTS_ERC20))
.map((coin) => coin);

for (const coin of evmCoinTokens) {
const token = createToken(coin);
token?.should.not.be.undefined();
token?.name.should.eql(coin.name);
token?.family.should.eql(coin.family);
token?.decimalPlaces.should.eql(coin.decimalPlaces);
if (token instanceof EthLikeErc20Token) {
(token as EthLikeErc20Token).tokenContractAddress.should.eql(coin?.contractAddress);
}
}
});
});