Skip to content
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

Fix/Uniswap Liquidity Error #225 [WIP] #257

Closed
wants to merge 11 commits into from
1 change: 1 addition & 0 deletions src/chains/avalanche/avalanche.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class Avalanche extends EthereumBase implements Ethereumish {
'avalanche',
config.network.chainID,
config.network.nodeURL,
config.network.secondaryNodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
Expand Down
1 change: 1 addition & 0 deletions src/chains/binance-smart-chain/binance-smart-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class BinanceSmartChain extends EthereumBase implements Ethereumish {
'binance-smart-chain',
config.network.chainID,
config.network.nodeURL,
config.network.secondaryNodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
Expand Down
1 change: 1 addition & 0 deletions src/chains/cronos/cronos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class Cronos extends EthereumBase implements Ethereumish {
'cronos',
config.network.chainID,
config.network.nodeURL,
config.network.secondaryNodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
Expand Down
67 changes: 55 additions & 12 deletions src/chains/ethereum/ethereum-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export type NewDebugMsgHandler = (msg: any) => void;

export class EthereumBase {
private _provider;
private _secondaryProvider;
protected tokenList: TokenInfo[] = [];
private _tokenMap: Record<string, TokenInfo> = {};
// there are async values set in the constructor
Expand All @@ -43,6 +44,7 @@ export class EthereumBase {
public chainName;
public chainId;
public rpcUrl;
public sedondaryRpcUrl;
public gasPriceConstant;
private _gasLimitTransaction;
public tokenListSource: string;
Expand All @@ -56,6 +58,7 @@ export class EthereumBase {
chainName: string,
chainId: number,
rpcUrl: string,
sedondaryRpcUrl: string,
tokenListSource: string,
tokenListType: TokenListType,
gasPriceConstant: number,
Expand All @@ -64,9 +67,13 @@ export class EthereumBase {
transactionDbPath: string
) {
this._provider = new providers.StaticJsonRpcProvider(rpcUrl);
this._secondaryProvider = new providers.StaticJsonRpcProvider(
sedondaryRpcUrl
);
this.chainName = chainName;
this.chainId = chainId;
this.rpcUrl = rpcUrl;
this.sedondaryRpcUrl = sedondaryRpcUrl;
this.gasPriceConstant = gasPriceConstant;
this.tokenListSource = tokenListSource;
this.tokenListType = tokenListType;
Expand Down Expand Up @@ -95,6 +102,10 @@ export class EthereumBase {
return this._provider;
}

public get secondaryProvider() {
return this._secondaryProvider;
}

public get gasLimitTransaction() {
return this._gasLimitTransaction;
}
Expand Down Expand Up @@ -242,14 +253,46 @@ export class EthereumBase {
// returns the balance for an ERC-20 token
async getERC20Balance(
contract: Contract,
secondaryContract: Contract,
wallet: Wallet,
decimals: number
): Promise<TokenValue> {
logger.info('Requesting balance for owner ' + wallet.address + '.');
const balance: BigNumber = await contract.balanceOf(wallet.address);
const maxRetry = 5;
let retry = 0;
let stopRetry = false;
let executingContract = contract;
let balance: BigNumber = BigNumber.from('0');

while (retry < maxRetry && !stopRetry) {
try {
balance = await executingContract.balanceOf(wallet.address);
stopRetry = true;
} catch (error) {
retry++;
logger.info(
`Error in getERC20Balance for owner ${wallet.address}:`,
error
);
logger.info(`Retrying...${retry} time`);
if (retry >= maxRetry) {
throw new Error(
`Error in getERC20Balance for owner ${wallet.address}: ${error}`
);
} else {
// if retry is odd set contract with second provider, else set with first provider
if (retry % 2 === 1) {
executingContract = secondaryContract;
} else {
executingContract = contract;
}
}
}
}

logger.info(
`Raw balance of ${contract.address} for ` +
`${wallet.address}: ${balance.toString()}`
`${wallet.address}: ${balance.toString()}`
);
return { value: balance, decimals: decimals };
}
Expand All @@ -263,10 +306,10 @@ export class EthereumBase {
): Promise<TokenValue> {
logger.info(
'Requesting spender ' +
spender +
' allowance for owner ' +
wallet.address +
'.'
spender +
' allowance for owner ' +
wallet.address +
'.'
);
const allowance = await contract.allowance(wallet.address, spender);
logger.info(allowance);
Expand Down Expand Up @@ -319,12 +362,12 @@ export class EthereumBase {
): Promise<Transaction> {
logger.info(
'Calling approve method called for spender ' +
spender +
' requesting allowance ' +
amount.toString() +
' from owner ' +
wallet.address +
'.'
spender +
' requesting allowance ' +
amount.toString() +
' from owner ' +
wallet.address +
'.'
);
return this.nonceManager.provideNonce(
nonce,
Expand Down
4 changes: 4 additions & 0 deletions src/chains/ethereum/ethereum.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface NetworkConfig {
name: string;
chainID: number;
nodeURL: string;
secondaryNodeURL: string;
tokenListType: TokenListType;
tokenListSource: string;
gasPriceRefreshInterval: number | undefined;
Expand Down Expand Up @@ -37,6 +38,9 @@ export function getEthereumConfig(
nodeURL: ConfigManagerV2.getInstance().get(
chainName + '.networks.' + network + '.nodeURL'
),
secondaryNodeURL: ConfigManagerV2.getInstance().get(
chainName + '.networks.' + network + '.secondaryNodeURL'
),
tokenListType: ConfigManagerV2.getInstance().get(
chainName + '.networks.' + network + '.tokenListType'
),
Expand Down
5 changes: 5 additions & 0 deletions src/chains/ethereum/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class Ethereum extends EthereumBase implements Ethereumish {
'ethereum',
config.network.chainID,
config.network.nodeURL,
config.network.secondaryNodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
Expand Down Expand Up @@ -128,6 +129,10 @@ export class Ethereum extends EthereumBase implements Ethereumish {
return super.provider;
}

public get secondaryProvider() {
return super.secondaryProvider;
}

/**
* Automatically update the prevailing gas price on the network.
*
Expand Down
7 changes: 7 additions & 0 deletions src/chains/ethereum/evm.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,15 @@ export class EVMController {
address,
ethereumish.provider
);

const secondaryContract = ethereumish.getContract(
address,
ethereumish.secondaryProvider
);

const balance = await ethereumish.getERC20Balance(
contract,
secondaryContract,
wallet,
decimals
);
Expand Down
4 changes: 4 additions & 0 deletions src/chains/harmony/harmony.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ interface NetworkConfig {
name: string;
chainID: number;
nodeURL: string;
secondaryNodeURL: string;
tokenListType: TokenListType;
tokenListSource: string;
}
Expand Down Expand Up @@ -31,6 +32,9 @@ export function getHarmonyConfig(
nodeURL: ConfigManagerV2.getInstance().get(
chainName + '.networks.' + network + '.nodeURL'
),
secondaryNodeURL: ConfigManagerV2.getInstance().get(
chainName + '.networks.' + network + '.secondaryNodeURL'
),
tokenListType: ConfigManagerV2.getInstance().get(
chainName + '.networks.' + network + '.tokenListType'
),
Expand Down
1 change: 1 addition & 0 deletions src/chains/harmony/harmony.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class Harmony extends EthereumBase implements Ethereumish {
'harmony',
config.network.chainID,
config.network.nodeURL,
config.network.secondaryNodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
Expand Down
1 change: 1 addition & 0 deletions src/chains/polygon/polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class Polygon extends EthereumBase implements Ethereumish {
'polygon',
config.network.chainID,
config.network.nodeURL,
config.network.secondaryNodeURL,
config.network.tokenListSource,
config.network.tokenListType,
config.manualGasPrice,
Expand Down
36 changes: 34 additions & 2 deletions src/chains/xdc/xdc.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,46 @@ export class XdcBase {
// returns the balance for an ERC-20 token
async getERC20Balance(
contract: Contract,
secondaryContract: Contract,
wallet: Wallet,
decimals: number
): Promise<TokenValue> {
logger.info('Requesting balance for owner ' + wallet.address + '.');
const balance: BigNumber = await contract.balanceOf(wallet.address);
const maxRetry = 5;
let retry = 0;
let stopRetry = false;
let executingContract = contract;
let balance: BigNumber = BigNumber.from('0');

while (retry < maxRetry && !stopRetry) {
try {
balance = await executingContract.balanceOf(wallet.address);
stopRetry = true;
} catch (error) {
retry++;
logger.info(
`Error in getERC20Balance for owner ${wallet.address}:`,
error
);
logger.info(`Retrying...${retry} time`);
if (retry >= maxRetry) {
throw new Error(
`Error in getERC20Balance for owner ${wallet.address}: ${error}`
);
} else {
// if retry is odd set contract with second provider, else set with first provider
if (retry % 2 === 1) {
executingContract = secondaryContract;
} else {
executingContract = contract;
}
}
}
}

logger.info(
`Raw balance of ${contract.address} for ` +
`${wallet.address}: ${balance.toString()}`
`${wallet.address}: ${balance.toString()}`
);
return { value: balance, decimals: decimals };
}
Expand Down
64 changes: 53 additions & 11 deletions src/connectors/uniswap/uniswap.lp.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from './uniswap.lp.interfaces';
import * as math from 'mathjs';
import { getAddress } from 'ethers/lib/utils';
import { logger } from '../../services/logger';

export class UniswapLPHelper {
protected ethereum: Ethereum;
Expand Down Expand Up @@ -154,10 +155,23 @@ export class UniswapLPHelper {
poolAddress: string,
fee: uniV3.FeeAmount
): Promise<PoolState> {
const maxRetry = 5;
let retry = 0;
let stopRetry = false;
let executingContract: Contract;

const poolContract = this.getPoolContract(
poolAddress,
this.ethereum.provider
);

const secondaryPoolContract = this.getPoolContract(
poolAddress,
this.ethereum.secondaryProvider
);

executingContract = poolContract;

const minTick = uniV3.nearestUsableTick(
uniV3.TickMath.MIN_TICK,
uniV3.TICK_SPACINGS[fee]
Expand All @@ -166,18 +180,46 @@ export class UniswapLPHelper {
uniV3.TickMath.MAX_TICK,
uniV3.TICK_SPACINGS[fee]
);
const poolDataReq = await Promise.allSettled([
poolContract.liquidity(),
poolContract.slot0(),
poolContract.ticks(minTick),
poolContract.ticks(maxTick),
]);

const rejected = poolDataReq.filter(
(r) => r.status === 'rejected'
) as PromiseRejectedResult[];

if (rejected.length > 0) throw new Error('Unable to fetch pool state');
let poolDataReq: any[] = [];

while (retry < maxRetry && !stopRetry) {
try {
poolDataReq = await Promise.allSettled([
executingContract.liquidity(),
executingContract.slot0(),
executingContract.ticks(minTick),
executingContract.ticks(maxTick),
]);

const rejected = poolDataReq.filter(
(r) => r.status === 'rejected'
) as PromiseRejectedResult[];

if (rejected.length > 0) throw new Error('Unable to fetch pool state');

stopRetry = true;
} catch (error) {
retry++;
logger.info(
`Error in fetching pool state for pool ${poolAddress}:`,
error
);
logger.info(`Retrying...${retry} time`);
if (retry >= maxRetry) {
throw new Error(
`Error in fetching pool state for pool ${poolAddress}: ${error}`
);
} else {
// if retry is odd set contract with second provider, else set with first provider
if (retry % 2 === 1) {
executingContract = secondaryPoolContract;
} else {
executingContract = poolContract;
}
}
}
}

const poolData = (
poolDataReq.filter(
Expand Down
Loading
Loading