Skip to content

Commit b9fd8c3

Browse files
Merge pull request #7843 from BitGo/coin-7060-2
feat: xdc token support
2 parents 7cb500d + 507ede7 commit b9fd8c3

File tree

12 files changed

+205
-55
lines changed

12 files changed

+205
-55
lines changed

modules/bitgo/src/v2/coinFactory.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ import {
215215
World,
216216
WorldToken,
217217
Xdc,
218+
XdcToken,
218219
Xlm,
219220
Xrp,
220221
XrpToken,
@@ -556,6 +557,10 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
556557
coinFactory.register(name, coinConstructor);
557558
});
558559

560+
XdcToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
561+
coinFactory.register(name, coinConstructor);
562+
});
563+
559564
// Generic ERC20 token registration for coins with SUPPORTS_ERC20 feature
560565
coins
561566
.filter((coin) => coin.features.includes(CoinFeature.SUPPORTS_ERC20) && !coin.isToken)
@@ -1081,10 +1086,8 @@ export function getTokenConstructor(tokenConfig: TokenConfig): CoinConstructor |
10811086
return EthLikeErc20Token.createTokenConstructor(tokenConfig as EthLikeTokenConfig, coinNames);
10821087
}
10831088
case 'xdc':
1084-
case 'txdc': {
1085-
const coinNames = { Mainnet: 'xdc', Testnet: 'txdc' };
1086-
return EthLikeErc20Token.createTokenConstructor(tokenConfig as EthLikeTokenConfig, coinNames);
1087-
}
1089+
case 'txdc':
1090+
return XdcToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
10881091
default:
10891092
return undefined;
10901093
}

modules/bitgo/src/v2/coins/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ import { StellarToken, Txlm, Xlm } from '@bitgo/sdk-coin-xlm';
6868
import { Vet, Tvet, VetToken } from '@bitgo/sdk-coin-vet';
6969
import { Wemix, Twemix } from '@bitgo/sdk-coin-wemix';
7070
import { World, Tworld, WorldToken } from '@bitgo/sdk-coin-world';
71-
import { Xdc, Txdc } from '@bitgo/sdk-coin-xdc';
71+
import { Xdc, Txdc, XdcToken } from '@bitgo/sdk-coin-xdc';
7272
import { Txrp, Xrp, XrpToken } from '@bitgo/sdk-coin-xrp';
7373
import { Txtz, Xtz } from '@bitgo/sdk-coin-xtz';
7474
import { Tzec, Zec } from '@bitgo/sdk-coin-zec';
@@ -142,7 +142,7 @@ export { Injective, Tinjective };
142142
export { Islm, Tislm };
143143
export { Trx, Ttrx };
144144
export { Vet, Tvet, VetToken };
145-
export { Xdc, Txdc };
145+
export { Xdc, Txdc, XdcToken };
146146
export { StellarToken, Txlm, Xlm };
147147
export { Txrp, Xrp, XrpToken };
148148
export { Txtz, Xtz };

modules/bitgo/test/browser/browser.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ describe('Coins', () => {
5858
EthLikeErc721Token: 1,
5959
HashToken: 1,
6060
FlrToken: 1,
61+
XdcToken: 1,
6162
JettonToken: 1,
6263
};
6364
Object.keys(BitGoJS.Coin)

modules/sdk-coin-xdc/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
"@bitgo/abstract-eth": "^24.19.4",
4444
"@bitgo/sdk-core": "^36.25.0",
4545
"@bitgo/statics": "^58.19.0",
46-
"@bitgo/sdk-coin-evm": "^1.11.0",
4746
"@ethereumjs/common": "^2.6.5",
4847
"@ethereumjs/tx": "^3.3.0"
4948
},

modules/sdk-coin-xdc/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './lib';
22
export * from './xdc';
33
export * from './txdc';
44
export * from './register';
5+
export * from './xdcToken';
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { BitGoBase } from '@bitgo/sdk-core';
2-
import { EthLikeErc20Token } from '@bitgo/sdk-coin-evm';
32
import { Xdc } from './xdc';
43
import { Txdc } from './txdc';
4+
import { XdcToken } from './xdcToken';
55

66
export const register = (sdk: BitGoBase): void => {
77
sdk.register('xdc', Xdc.createInstance);
88
sdk.register('txdc', Txdc.createInstance);
9-
EthLikeErc20Token.createTokenConstructors({
10-
Mainnet: 'xdc',
11-
Testnet: 'txdc',
12-
}).forEach(({ name, coinConstructor }) => {
9+
XdcToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
1310
sdk.register(name, coinConstructor);
1411
});
1512
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @prettier
3+
*/
4+
import { EthLikeTokenConfig, coins } from '@bitgo/statics';
5+
import { BitGoBase, CoinConstructor, NamedCoinConstructor, common, MPCAlgorithm } from '@bitgo/sdk-core';
6+
import { CoinNames, EthLikeToken, recoveryBlockchainExplorerQuery } from '@bitgo/abstract-eth';
7+
8+
import { TransactionBuilder } from './lib';
9+
export { EthLikeTokenConfig };
10+
11+
export class XdcToken extends EthLikeToken {
12+
public readonly tokenConfig: EthLikeTokenConfig;
13+
static coinNames: CoinNames = {
14+
Mainnet: 'xdc',
15+
Testnet: 'txdc',
16+
};
17+
constructor(bitgo: BitGoBase, tokenConfig: EthLikeTokenConfig) {
18+
super(bitgo, tokenConfig, XdcToken.coinNames);
19+
}
20+
static createTokenConstructor(config: EthLikeTokenConfig): CoinConstructor {
21+
return super.createTokenConstructor(config, XdcToken.coinNames);
22+
}
23+
24+
static createTokenConstructors(): NamedCoinConstructor[] {
25+
return super.createTokenConstructors(XdcToken.coinNames);
26+
}
27+
28+
protected getTransactionBuilder(): TransactionBuilder {
29+
return new TransactionBuilder(coins.get(this.getBaseChain()));
30+
}
31+
32+
/**
33+
* Make a query to XDC Etherscan for information such as balance, token balance, solidity calls
34+
* @param {Object} query key-value pairs of parameters to append after /api
35+
* @returns {Promise<Object>} response from XDC Etherscan
36+
*/
37+
async recoveryBlockchainExplorerQuery(query: Record<string, string>): Promise<Record<string, unknown>> {
38+
const apiToken = common.Environments[this.bitgo.getEnv()].xdcExplorerApiToken;
39+
const explorerUrl = common.Environments[this.bitgo.getEnv()].xdcExplorerBaseUrl;
40+
return await recoveryBlockchainExplorerQuery(query, explorerUrl as string, apiToken);
41+
}
42+
43+
getFullName(): string {
44+
return 'XDC Token';
45+
}
46+
47+
supportsTss(): boolean {
48+
return true;
49+
}
50+
51+
/** @inheritDoc */
52+
getMPCAlgorithm(): MPCAlgorithm {
53+
return 'ecdsa';
54+
}
55+
}

modules/sdk-coin-xdc/test/unit/xdcToken.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe('XDC Token:', function () {
1919
it('should return constants', function () {
2020
xdcTokenCoin.getChain().should.equal('xdc:usdc');
2121
xdcTokenCoin.getBaseChain().should.equal('xdc');
22-
xdcTokenCoin.getFullName().should.equal('ERC20 Token');
22+
xdcTokenCoin.getFullName().should.equal('XDC Token');
2323
xdcTokenCoin.getBaseFactor().should.equal(1e6);
2424
xdcTokenCoin.type.should.equal(tokenName);
2525
xdcTokenCoin.name.should.equal('USD Coin');

modules/statics/src/account.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,16 @@ export class FlrERC20Token extends ContractAddressDefinedToken {
530530
}
531531
}
532532

533+
/**
534+
* The XDC network supports tokens
535+
* XDC Tokens are ERC20 tokens
536+
*/
537+
export class XdcERC20Token extends ContractAddressDefinedToken {
538+
constructor(options: Erc20ConstructorOptions) {
539+
super(options);
540+
}
541+
}
542+
533543
/**
534544
* The Xrp network supports tokens
535545
* Xrp tokens are identified by their issuer address
@@ -2856,6 +2866,96 @@ export function tflrErc20(
28562866
);
28572867
}
28582868

2869+
/**
2870+
* Factory function for XdcErc20 token instances.
2871+
*
2872+
* @param id uuid v4
2873+
* @param name unique identifier of the token
2874+
* @param fullName Complete human-readable name of the token
2875+
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
2876+
* @param contractAddress Contract address of this token
2877+
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
2878+
* @param prefix? Optional token prefix. Defaults to empty string
2879+
* @param suffix? Optional token suffix. Defaults to token name.
2880+
* @param network? Optional token network. Defaults to XDC mainnet network.
2881+
* @param features? Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
2882+
* @param primaryKeyCurve The elliptic curve for this chain/token
2883+
*/
2884+
export function xdcErc20(
2885+
id: string,
2886+
name: string,
2887+
fullName: string,
2888+
decimalPlaces: number,
2889+
contractAddress: string,
2890+
asset: UnderlyingAsset,
2891+
features: CoinFeature[] = [...AccountCoin.DEFAULT_FEATURES, CoinFeature.EIP1559],
2892+
prefix = '',
2893+
suffix: string = name.toUpperCase(),
2894+
network: AccountNetwork = Networks.main.xdc,
2895+
primaryKeyCurve: KeyCurve = KeyCurve.Secp256k1
2896+
) {
2897+
return Object.freeze(
2898+
new XdcERC20Token({
2899+
id,
2900+
name,
2901+
fullName,
2902+
network,
2903+
contractAddress,
2904+
prefix,
2905+
suffix,
2906+
features,
2907+
decimalPlaces,
2908+
asset,
2909+
isToken: true,
2910+
primaryKeyCurve,
2911+
baseUnit: BaseUnit.ETH,
2912+
})
2913+
);
2914+
}
2915+
2916+
/**
2917+
* Factory function for XDC testnet XdcErc20 token instances.
2918+
*
2919+
* @param id uuid v4
2920+
* @param name unique identifier of the token
2921+
* @param fullName Complete human-readable name of the token
2922+
* @param decimalPlaces Number of decimal places this token supports (divisibility exponent)
2923+
* @param contractAddress Contract address of this token
2924+
* @param asset Asset which this coin represents. This is the same for both mainnet and testnet variants of a coin.
2925+
* @param prefix? Optional token prefix. Defaults to empty string
2926+
* @param suffix? Optional token suffix. Defaults to token name.
2927+
* @param network? Optional token network. Defaults to the XDC test network.
2928+
* @param features? Features of this coin. Defaults to the DEFAULT_FEATURES defined in `AccountCoin`
2929+
* @param primaryKeyCurve The elliptic curve for this chain/token
2930+
*/
2931+
export function txdcErc20(
2932+
id: string,
2933+
name: string,
2934+
fullName: string,
2935+
decimalPlaces: number,
2936+
contractAddress: string,
2937+
asset: UnderlyingAsset,
2938+
features: CoinFeature[] = AccountCoin.DEFAULT_FEATURES,
2939+
prefix = '',
2940+
suffix: string = name.toUpperCase(),
2941+
network: AccountNetwork = Networks.test.xdc,
2942+
primaryKeyCurve: KeyCurve = KeyCurve.Secp256k1
2943+
) {
2944+
return xdcErc20(
2945+
id,
2946+
name,
2947+
fullName,
2948+
decimalPlaces,
2949+
contractAddress,
2950+
asset,
2951+
features,
2952+
prefix,
2953+
suffix,
2954+
network,
2955+
primaryKeyCurve
2956+
);
2957+
}
2958+
28592959
/**
28602960
* Factory function for xrp token instances.
28612961
*

modules/statics/src/allCoinsAndTokens.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
erc721Token,
1717
fiat,
1818
flrErc20,
19+
xdcErc20,
1920
gasTankAccount,
2021
hederaCoin,
2122
hederaToken,
@@ -34,6 +35,7 @@ import {
3435
terc1155,
3536
terc721,
3637
tflrErc20,
38+
txdcErc20,
3739
topethErc20,
3840
tronToken,
3941
tstellarToken,
@@ -2980,61 +2982,55 @@ export const allCoinsAndTokens = [
29802982
),
29812983

29822984
// XDC mainnet tokens
2983-
erc20Token(
2985+
xdcErc20(
29842986
'b820932d-5772-49ae-a055-a59760f3e4cf',
29852987
'xdc:usdc',
29862988
'USD Coin',
29872989
6,
29882990
'0xfa2958cb79b0491cc627c1557f441ef849ca8eb1',
2989-
UnderlyingAsset['xdc:usdc'],
2990-
Networks.main.xdc
2991+
UnderlyingAsset['xdc:usdc']
29912992
),
2992-
erc20Token(
2993+
xdcErc20(
29932994
'8914a1bd-1495-46df-84da-445c6d49edb2',
29942995
'xdc:lbt',
29952996
'Law Block Token',
29962997
18,
29972998
'0x05940b2df33d6371201e7ae099ced4c363855dfe',
2998-
UnderlyingAsset['xdc:lbt'],
2999-
Networks.main.xdc
2999+
UnderlyingAsset['xdc:lbt']
30003000
),
3001-
erc20Token(
3001+
xdcErc20(
30023002
'f03302de-b06b-4ddc-94a2-ad7e89896725',
30033003
'xdc:gama',
30043004
'Gama Token',
30053005
18,
30063006
'0x3a170c7c987f55c84f28733bfa27962d8cdd5d3b',
3007-
UnderlyingAsset['xdc:gama'],
3008-
Networks.main.xdc
3007+
UnderlyingAsset['xdc:gama']
30093008
),
3010-
erc20Token(
3009+
xdcErc20(
30113010
'bdf602ea-3a6c-407a-8afd-33d6c04a8bc3',
30123011
'xdc:srx',
30133012
'STORX',
30143013
18,
30153014
'0x5d5f074837f5d4618b3916ba74de1bf9662a3fed',
3016-
UnderlyingAsset['xdc:srx'],
3017-
Networks.main.xdc
3015+
UnderlyingAsset['xdc:srx']
30183016
),
3019-
erc20Token(
3017+
xdcErc20(
30203018
'd42c9497-0987-497d-97f2-8b19c539e350',
30213019
'xdc:weth',
30223020
'Wrapped Ether',
30233021
18,
30243022
'0xa7348290de5cf01772479c48d50dec791c3fc212',
3025-
UnderlyingAsset['xdc:weth'],
3026-
Networks.main.xdc
3023+
UnderlyingAsset['xdc:weth']
30273024
),
30283025

30293026
// XDC testnet tokens
3030-
erc20Token(
3027+
txdcErc20(
30313028
'5fc561e7-5fb5-4702-9860-9f48d90f1d45',
30323029
'txdc:tmt',
30333030
'XDC Network TMT',
30343031
6,
30353032
'0xb283ec8dad644effc5c4c50bb7bb21442ac3c2db',
3036-
UnderlyingAsset['txdc:tmt'],
3037-
Networks.test.xdc
3033+
UnderlyingAsset['txdc:tmt']
30383034
),
30393035

30403036
// MON mainnet tokens

0 commit comments

Comments
 (0)