Skip to content

Commit

Permalink
refactor: support xdc chain
Browse files Browse the repository at this point in the history
  • Loading branch information
gzliudan committed Mar 21, 2023
1 parent 25e7496 commit 5d7c97c
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/chains/xdc/xdc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import abi from '../ethereum/ethereum.abi.json';
import { logger } from '../../services/logger';
import { Contract, Transaction, Wallet } from 'ethers';
import { EthereumBase } from '../ethereum/ethereum-base';
import { getEthereumConfig as getPolygonConfig } from '../ethereum/ethereum.config';
import { Provider } from '@ethersproject/abstract-provider';
import { UniswapConfig } from '../../connectors/uniswap/uniswap.config';
import { Ethereumish } from '../../services/common-interfaces';
import { ConfigManagerV2 } from '../../services/config-manager-v2';

export class Xdc extends EthereumBase implements Ethereumish {
private static _instances: { [name: string]: Xdc };
private _gasPrice: number;
private _nativeTokenSymbol: string;
private _chain: string;

private constructor(network: string) {
const config = getPolygonConfig('xdc', network);
super(
'xdc',
config.network.chainID,
config.network.nodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
config.gasLimitTransaction,
ConfigManagerV2.getInstance().get('server.nonceDbPath'),
ConfigManagerV2.getInstance().get('server.transactionDbPath')
);
this._chain = config.network.name;
this._nativeTokenSymbol = config.nativeCurrencySymbol;
this._gasPrice = config.manualGasPrice;
}

public static getInstance(network: string): Xdc {
if (Xdc._instances === undefined) {
Xdc._instances = {};
}
if (!(network in Xdc._instances)) {
Xdc._instances[network] = new Xdc(network);
}

return Xdc._instances[network];
}

public static getConnectedInstances(): { [name: string]: Xdc } {
return Xdc._instances;
}

public get gasPrice(): number {
return this._gasPrice;
}

public get nativeTokenSymbol(): string {
return this._nativeTokenSymbol;
}

public get chain(): string {
return this._chain;
}

getContract(tokenAddress: string, signerOrProvider?: Wallet | Provider) {
return new Contract(tokenAddress, abi.ERC20Abi, signerOrProvider);
}

getSpender(reqSpender: string): string {
let spender: string;
if (reqSpender === 'uniswap') {
spender = UniswapConfig.config.uniswapV3SmartOrderRouterAddress(
this._chain
);
} else {
spender = reqSpender;
}
return spender;
}

// cancel transaction
async cancelTx(wallet: Wallet, nonce: number): Promise<Transaction> {
logger.info(
'Canceling any existing transaction(s) with nonce number ' + nonce + '.'
);
return super.cancelTxWithGasPrice(wallet, nonce, this._gasPrice * 2);
}
}
36 changes: 36 additions & 0 deletions src/chains/xdc/xdc.validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
mkRequestValidator,
mkValidator,
RequestValidator,
Validator,
validateAmount,
validateToken,
validateTokenSymbols,
} from '../../services/validators';
import {
isAddress,
validateNonce,
validateAddress,
} from '../ethereum/ethereum.validators';

export const invalidSpenderError: string =
'The spender param is not a valid xdc address (0x followed by 40 hexidecimal characters).';

// given a request, look for a key called spender that is 'uniswap', 'sushi' or an Ethereum address
export const validateSpender: Validator = mkValidator(
'spender',
invalidSpenderError,
(val) => typeof val === 'string' && (val === 'uniswap' || isAddress(val))
);

export const validateXdcApproveRequest: RequestValidator =
mkRequestValidator([
validateAddress,
validateSpender,
validateToken,
validateAmount,
validateNonce,
]);

export const validateXdcAllowancesRequest: RequestValidator =
mkRequestValidator([validateAddress, validateSpender, validateTokenSymbols]);
47 changes: 47 additions & 0 deletions src/chains/xdc/xdc_tokens_apothem.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "apothem",
"tokens": [
{
"symbol": "WXDC",
"chainId": 51,
"address": "0x2a5c77b016Df1b3b0AE4E79a68F8adF64Ee741ba",
"decimals": 18
},
{
"symbol": "WBTC2",
"chainId": 51,
"address": "0x01B0500f82EF188D0410a46f2E8940133E213e83",
"decimals": 8
},
{
"symbol": "YFI2",
"chainId": 51,
"address": "0x22e4Eb82FF59c53B275aDEacd4EE4Bc47fc4f16d",
"decimals": 18
},
{
"symbol": "MKR2",
"chainId": 51,
"address": "0x258E445fEf3F41429e38ee124DA63aBfb08edc70",
"decimals": 18
},
{
"symbol": "AAVE2",
"chainId": 51,
"address": "0x3042207876c47D3c206df99b3279d97813B34Ea1",
"decimals": 18
},
{
"symbol": "UNI2",
"chainId": 51,
"address": "0xD9e33607d06cBB1Fef59488b9969426b10F310B8",
"decimals": 18
},
{
"symbol": "USDC2",
"chainId": 51,
"address": "0xF83B9Dc502A3F76c042b4043B6C1B5eBBE574389",
"decimals": 6
}
]
}
10 changes: 10 additions & 0 deletions src/network/network.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { BinanceSmartChain } from '../chains/binance-smart-chain/binance-smart-c
import { Ethereum } from '../chains/ethereum/ethereum';
import { Harmony } from '../chains/harmony/harmony';
import { Polygon } from '../chains/polygon/polygon';
import { Xdc } from '../chains/xdc/xdc';
import { TokenInfo } from '../chains/ethereum/ethereum-base';
import {
HttpException,
Expand Down Expand Up @@ -42,6 +43,8 @@ export async function getStatus(
connections.push(Ethereum.getInstance(req.network as string));
} else if (req.chain === 'polygon') {
connections.push(Polygon.getInstance(req.network as string));
} else if (req.chain === 'xdc') {
connections.push(Xdc.getInstance(req.network as string));
} else if (req.chain === 'near') {
connections.push(Near.getInstance(req.network as string));
} else if (req.chain === 'cronos') {
Expand Down Expand Up @@ -74,6 +77,11 @@ export async function getStatus(
polygonConnections ? Object.values(polygonConnections) : []
);

const xdcConnections = Xdc.getConnectedInstances();
connections = connections.concat(
xdcConnections ? Object.values(xdcConnections) : []
);

const cronosConnections = Cronos.getConnectedInstances();
connections = connections.concat(
cronosConnections ? Object.values(cronosConnections) : []
Expand Down Expand Up @@ -131,6 +139,8 @@ export async function getTokens(req: TokensRequest): Promise<TokensResponse> {
connection = Ethereum.getInstance(req.network);
} else if (req.chain === 'polygon') {
connection = Polygon.getInstance(req.network);
} else if (req.chain === 'xdc') {
connection = Xdc.getInstance(req.network);
} else if (req.chain === 'near') {
connection = Near.getInstance(req.network);
} else if (req.chain === 'cronos') {
Expand Down
2 changes: 2 additions & 0 deletions src/services/connection-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Ethereum } from '../chains/ethereum/ethereum';
import { BinanceSmartChain } from '../chains/binance-smart-chain/binance-smart-chain';
import { Harmony } from '../chains/harmony/harmony';
import { Polygon } from '../chains/polygon/polygon';
import { Xdc } from '../chains/xdc/xdc';
import { MadMeerkat } from '../connectors/mad_meerkat/mad_meerkat';
import { Openocean } from '../connectors/openocean/openocean';
import { Pangolin } from '../connectors/pangolin/pangolin';
Expand Down Expand Up @@ -46,6 +47,7 @@ export async function getChain<T>(
else if (chain === 'avalanche')
chainInstance = Avalanche.getInstance(network);
else if (chain === 'polygon') chainInstance = Polygon.getInstance(network);
else if (chain === 'xdc') chainInstance = Xdc.getInstance(network);
else if (chain === 'harmony') chainInstance = Harmony.getInstance(network);
else if (chain === 'near') chainInstance = Near.getInstance(network);
else if (chain === 'binance-smart-chain')
Expand Down
3 changes: 3 additions & 0 deletions src/services/wallet/wallet.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BinanceSmartChain } from '../../chains/binance-smart-chain/binance-smar
import { Cronos } from '../../chains/cronos/cronos';
import { Ethereum } from '../../chains/ethereum/ethereum';
import { Polygon } from '../../chains/polygon/polygon';
import { Xdc } from '../../chains/xdc/xdc';
import { Cosmos } from '../../chains/cosmos/cosmos';
import { Harmony } from '../../chains/harmony/harmony';

Expand Down Expand Up @@ -57,6 +58,8 @@ export async function addWallet(
connection = Cronos.getInstance(req.network);
} else if (req.chain === 'polygon') {
connection = Polygon.getInstance(req.network);
} else if (req.chain === 'xdc') {
connection = Xdc.getInstance(req.network);
} else if (req.chain === 'cosmos') {
connection = Cosmos.getInstance(req.network);
} else if (req.chain === 'near') {
Expand Down
6 changes: 6 additions & 0 deletions src/services/wallet/wallet.validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export const validatePrivateKey: Validator = mkSelectingValidator(
invalidEthPrivateKeyError,
(val) => typeof val === 'string' && isEthPrivateKey(val)
),
xdc: mkValidator(
'privateKey',
invalidEthPrivateKeyError,
(val) => typeof val === 'string' && isEthPrivateKey(val)
),
'binance-smart-chain': mkValidator(
'privateKey',
invalidEthPrivateKeyError,
Expand All @@ -101,6 +106,7 @@ export const validateChain: Validator = mkValidator(
(val === 'ethereum' ||
val === 'avalanche' ||
val === 'polygon' ||
val === 'xdc' ||
val == 'near' ||
val === 'harmony' ||
val === 'cronos' ||
Expand Down
4 changes: 4 additions & 0 deletions src/templates/root.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ configurations:
configurationPath: polygon.yml
schemaPath: ethereum-schema.json

$namespace xdc:
configurationPath: xdc.yml
schemaPath: ethereum-schema.json

$namespace defira:
configurationPath: defira.yml
schemaPath: defira-schema.json
Expand Down
17 changes: 17 additions & 0 deletions src/templates/xdc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# list the xdc networks available to gateway
networks:
xinfin:
chainID: 50
nodeURL: https://erpc.xinfin.network
tokenListType: 'URL'
tokenListSource: 'https://raw.githubusercontent.com/pro100skm/xdc-token-list/master/mainnet.tokenlist.json'
nativeCurrencySymbol: 'XDC'
apothem:
chainID: 51
nodeURL: https://erpc.apothem.network
tokenListType: 'FILE'
tokenListSource: 'src/chains/xdc/xdc_tokens_apothem.json'
nativeCurrencySymbol: 'XDC'

manualGasPrice: 1
gasLimitTransaction: 3000000

0 comments on commit 5d7c97c

Please sign in to comment.