Skip to content

Commit

Permalink
(merge) merge in uniswap celo
Browse files Browse the repository at this point in the history
  • Loading branch information
fengtality committed Jul 26, 2024
2 parents 1ba268a + 2776ecc commit 7a0ca31
Show file tree
Hide file tree
Showing 17 changed files with 1,011 additions and 222 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
'src/chains/binance-smart-chain/binance-smart-chain.ts',
'src/chains/ethereum/ethereum.ts',
'src/chains/avalanche/avalanche.ts',
'src/chains/celo/celo.ts',
'src/chains/avalanche/pangolin/pangolin.ts',
'src/chains/cosmos/cosmos.ts',
'src/chains/near/near.ts',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"coinalpha-ref-sdk": "1.1.0",
"dayjs": "^1.10.6",
"decimal.js-light": "^2.5.1",
"ethers": "^5.6.2",
"ethers": "^5.7.2",
"ethers-xdc": "file:./vendor/ethers-xdc",
"express": "^4.17.1",
"express-winston": "^4.1.0",
Expand Down
130 changes: 130 additions & 0 deletions src/chains/celo/celo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
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 getCeloConfig } from '../ethereum/ethereum.config';
import { Provider } from '@ethersproject/abstract-provider';
import { Ethereumish } from '../../services/common-interfaces';
import { ConfigManagerV2 } from '../../services/config-manager-v2';
import { EVMController } from '../ethereum/evm.controllers';
import { UniswapConfig } from '../../connectors/uniswap/uniswap.config';

export class Celo extends EthereumBase implements Ethereumish {
private static _instances: { [name: string]: Celo };
private _gasPrice: number;
private _gasPriceRefreshInterval: number | null;
private _nativeTokenSymbol: string;
private _chain: string;
public controller;

private constructor(network: string) {
const config = getCeloConfig('celo', network);
super(
'celo',
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;

this._gasPriceRefreshInterval =
config.network.gasPriceRefreshInterval !== undefined
? config.network.gasPriceRefreshInterval
: null;

this.updateGasPrice();
this.controller = EVMController;
}

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

return Celo._instances[network];
}

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

// getters

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(
'celo',
this._chain,
);
} else if (reqSpender === 'uniswapLP') {
spender = UniswapConfig.config.uniswapV3NftManagerAddress('celo', 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);
}

/**
* Automatically update the prevailing gas price on the network.
*/
async updateGasPrice(): Promise<void> {
if (this._gasPriceRefreshInterval === null) {
return;
}

const gasPrice = await this.getGasPrice();
if (gasPrice !== null) {
this._gasPrice = gasPrice;
} else {
logger.info('gasPrice is unexpectedly null.');
}

setTimeout(
this.updateGasPrice.bind(this),
this._gasPriceRefreshInterval * 1000
);
}

async close() {
await super.close();
if (this._chain in Celo._instances) {
delete Celo._instances[this._chain];
}
}
}
41 changes: 41 additions & 0 deletions src/chains/celo/celo.validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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 Celo address (0x followed by 40 hexidecimal characters).';

// given a request, look for a key called spender that is 'uniswap' or an Ethereum address
export const validateSpender: Validator = mkValidator(
'spender',
invalidSpenderError,

(val) =>
typeof val === 'string' &&
(val === 'uniswap' ||
val === 'uniswapLP' ||
isAddress(val))
);

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

export const validateCeloAllowancesRequest: RequestValidator =
mkRequestValidator([validateAddress, validateSpender, validateTokenSymbols]);
7 changes: 5 additions & 2 deletions src/connectors/uniswap/uniswap.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export namespace UniswapConfig {

export const config: NetworkConfig = {
allowedSlippage: ConfigManagerV2.getInstance().get(
`uniswap.allowedSlippage`
`uniswap.allowedSlippage`,
),
gasLimitEstimate: ConfigManagerV2.getInstance().get(
`uniswap.gasLimitEstimate`
`uniswap.gasLimitEstimate`,
),
ttl: ConfigManagerV2.getInstance().get(`uniswap.ttl`),
maximumHops: ConfigManagerV2.getInstance().get(`uniswap.maximumHops`),
Expand Down Expand Up @@ -76,6 +76,9 @@ export namespace UniswapConfig {
{ chain: 'avalanche',
networks: ['avalanche']
},
{ chain: 'celo',
networks: ['celo']
},
],
useRouter: ConfigManagerV2.getInstance().get(`uniswap.useRouter`),
feeTier: ConfigManagerV2.getInstance().get(`uniswap.feeTier`),
Expand Down
5 changes: 4 additions & 1 deletion src/connectors/uniswap/uniswap.lp.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ import {
} from './uniswap.lp.interfaces';
import * as math from 'mathjs';
import { getAddress } from 'ethers/lib/utils';
import { Celo } from '../../chains/celo/celo';

export class UniswapLPHelper {
protected chain: Ethereum | Polygon | BinanceSmartChain | Avalanche;
protected chain: Ethereum | Polygon | BinanceSmartChain | Avalanche | Celo;
protected chainId;
private _factory: string;
private _router: string;
Expand All @@ -48,6 +49,8 @@ export class UniswapLPHelper {
this.chain = BinanceSmartChain.getInstance(network);
} else if (chain === 'avalanche') {
this.chain = Avalanche.getInstance(network);
} else if (chain === 'celo') {
this.chain = Celo.getInstance(network);
} else {
throw new Error('Unsupported chain');
}
Expand Down
Loading

0 comments on commit 7a0ca31

Please sign in to comment.