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

feat/ add ETCswap V3 and V2 connectors #340

Merged
merged 18 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
115 changes: 115 additions & 0 deletions src/chains/etc/etc.ts

This comment was marked as resolved.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
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 getETCChainConfig } from '../ethereum/ethereum.config';
import { Provider } from '@ethersproject/abstract-provider';
import { Chain as Ethereumish } from '../../services/common-interfaces';
import { ConfigManagerV2 } from '../../services/config-manager-v2';
import { EVMController } from '../ethereum/evm.controllers';
import { ETCSwapConfig } from '../../connectors/etcswap/etcswap.config';

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

private constructor(network: string) {
const config = getETCChainConfig('etc', network);
super(
'etc',
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): ETCChain {
if (ETCChain._instances === undefined) {
ETCChain._instances = {};
}
if (!(network in ETCChain._instances)) {
ETCChain._instances[network] = new ETCChain(network);
}

return ETCChain._instances[network];
}

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

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

const gasPrice: number = (await this.provider.getGasPrice()).toNumber();

this._gasPrice = gasPrice * 1e-9;

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

// 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 === 'etcswapLP') {
spender = ETCSwapConfig.config.etcswapV3NftManagerAddress(
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);
}
}
1 change: 1 addition & 0 deletions src/chains/ethereum/ethereum.validators.ts

This comment was marked as resolved.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have followed existing naming convention as the Uniswap connectors.
Any deviation may require modifications on the Hummingbot client.

Copy link

@chris-mercer chris-mercer Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay thanks for clarification! great, i want it to follow the schema already present in the codebase

Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const validateSpender: Validator = mkValidator(
val === 'curve' ||
val === 'carbonamm' ||
val === 'balancer' ||
val === 'etcswapLP' ||
isAddress(val))
);

Expand Down
8 changes: 8 additions & 0 deletions src/connectors/connectors.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { QuipuswapConfig } from './quipuswap/quipuswap.config';
import { OsmosisConfig } from '../chains/osmosis/osmosis.config';
import { CarbonConfig } from './carbon/carbon.config';
import { BalancerConfig } from './balancer/balancer.config';
import { ETCSwapConfig } from './etcswap/etcswap.config';

export namespace ConnectorsRoutes {
export const router = Router();
Expand Down Expand Up @@ -190,6 +191,13 @@ export namespace ConnectorsRoutes {
chain_type: BalancerConfig.config.chainType,
available_networks: BalancerConfig.config.availableNetworks,
},
{
name: 'etcswapLP',
trading_type: ETCSwapConfig.config.tradingTypes('LP'),
chain_type: ETCSwapConfig.config.chainType,
available_networks: ETCSwapConfig.config.availableNetworks,
additional_spenders: ['etcswap'],
},
],
});
})
Expand Down
45 changes: 45 additions & 0 deletions src/connectors/etcswap/etcswap.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
buildConfig,
NetworkConfig as V2NetworkConfig,
} from '../../network/network.utils';
import { ConfigManagerV2 } from '../../services/config-manager-v2';

export namespace ETCSwapConfig {
export interface NetworkConfig extends Omit<V2NetworkConfig, 'tradingTypes'> {
maximumHops: number;
etcswapV3SmartOrderRouterAddress: (network: string) => string;
etcswapV3NftManagerAddress: (network: string) => string;
tradingTypes: (type: string) => Array<string>;
useRouter?: boolean;
feeTier?: string;
}

export const v2Config: V2NetworkConfig = buildConfig(
'etcswap',
['AMM'],
[
{ chain: 'etc', networks: ['mainnet'] },
],
'EVM',
);

export const config: NetworkConfig = {
...v2Config,
...{
maximumHops: ConfigManagerV2.getInstance().get(`etcswap.maximumHops`),
etcswapV3SmartOrderRouterAddress: (network: string) =>
ConfigManagerV2.getInstance().get(
`etcswap.contractAddresses.${network}.etcswapV3SmartOrderRouterAddress`,
),
etcswapV3NftManagerAddress: (network: string) =>
ConfigManagerV2.getInstance().get(
`etcswap.contractAddresses.${network}.etcswapV3NftManagerAddress`,
),
tradingTypes: (type: string) => {
return type === 'swap' ? ['AMM'] : ['AMM_LP'];
},
useRouter: ConfigManagerV2.getInstance().get(`etcswap.useRouter`),
feeTier: ConfigManagerV2.getInstance().get(`etcswap.feeTier`),
},
};
}
Loading
Loading