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(camelot-v3): Camelot V3 DEX integration. #20

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

kustrun
Copy link

@kustrun kustrun commented Jan 18, 2025

Supported functionalities:

  • swap tokens
  • add liquidity
  • manage liquidity (increase, decrease, remove)

Files Changed

  1. projects/camelot-v3

Supported functionalities:
- swap tokens
- add liquidity
- manage liquidity (increase, decrease, remove)
@kustrun kustrun changed the title feat(camelot-v3): Initial Camelot V3 DEX integration. feat(camelot-v3): Camelot V3 DEX integration. Jan 18, 2025
@kustrun kustrun closed this Jan 18, 2025
@kustrun kustrun deleted the feature/camelot-v3-integration branch January 18, 2025 21:35
@kustrun kustrun restored the feature/camelot-v3-integration branch January 18, 2025 21:36
@kustrun kustrun reopened this Jan 18, 2025
{
name: 'exactInputSingle',
description: 'Swap exact amount of X tokens A for token B receiving at least Y tokens B and optionally send them to another recipient',
required: ['chainName', 'account', 'tokenIn', 'tokenOut', 'amountIn'],
Copy link
Contributor

Choose a reason for hiding this comment

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


export async function collect(
{ chainName, account, tokenA, tokenB, tokenId, collectPercentage, amountAMax, amountBMax, recipient }: Props,
{ sendTransactions, notify, getProvider }: FunctionOptions,
Copy link
Contributor

@OoXooOx OoXooOx Feb 10, 2025

Choose a reason for hiding this comment

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

add validation for tokenId. If it will be 3.52, then you will receive error at 47 line

Copy link
Contributor

Choose a reason for hiding this comment

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

collectPercentage same 111 line

const result = await sendTransactions({ chainId, account, transactions });
const collectFees = result.data[result.data.length - 1];

return toResult(result.isMultisig ? collectFees.message : `Successfully collected fees on Camelot V3. ${collectFees.message}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

consider read events and display info from there to user

Copy link
Author

Choose a reason for hiding this comment

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

Could you clarify what you mean in more detail? The idea is that after a user performs an action, they receive a more meaningful message. For example:

  1. A message confirming that the transaction is being processed.
  2. A message returning the transaction hash (SHOULD this be included?).
  3. A message with the action results—for example, how many fees were collected in this case (SHOULD this be included?).

Adding (2) is straightforward, but (3) could be more challenging since it requires waiting for the transaction to be mined.

Copy link
Contributor

Choose a reason for hiding this comment

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

export async function amountToWei(provider: PublicClient, token: Address, amount: string | undefined): Promise<bigint> {
if (!amount) return 0n;

const decimals = await getDecimals(provider, token);
Copy link
Contributor

Choose a reason for hiding this comment

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

if(!name || !symbol || !decimals) throw new Error(Invalid ERC20 token contract at address ${address}. Failed to fetch token details (name: ${name}, symbol: ${symbol}, decimals: ${decimals}));

Copy link
Author

Choose a reason for hiding this comment

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

I believe this is already handled in the getDecimals() function, which throws this error (*I’ve adjusted the error message). Since amountToWei and weiToAmount rely on getDecimals(), they automatically return the rejected Promise when the error is thrown, as they don’t catch it internally.

export async function getDecimals(provider: PublicClient, token: Address): Promise<number> {
    // Try-catch to detect invalid token address
    try {
        return provider.readContract({
            address: token,
            abi: erc20Abi,
            functionName: 'decimals',
            args: [],
        });
    } catch (error) {
        throw new Error(`Invalid ERC20 token contract at address ${token}. Failed to fetch token details`);
    }
}

const [simulatedAmount0, simulatedAmount1] = await simulateDecreaseLiquidityAmounts(chainId, provider, positionId, liquidityToRemove);

// Set 0.2% slippage tolerance
if (amount0MinWei == 0n) {
Copy link
Contributor

Choose a reason for hiding this comment

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

what if user need 0.5% slippage?

},
{
name: 'exactOutputSingle',
description: 'Swap token A for exact amount of X tokens B while spending at most Y tokens A and optionally send them to another recipient',
Copy link
Contributor

Choose a reason for hiding this comment

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

If you use tokenA tokenB then this arguments must be in function. I don't get it what for you use this examples.

Copy link
Contributor

Choose a reason for hiding this comment

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

like in mint function

Copy link
Author

Choose a reason for hiding this comment

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

The exactOutputSingle function allows you to buy EXACTLY 0.1 ETH using an arbitrary amount of USDC. In contrast, exactInputSingle lets you spend EXACTLY 1000 USDC to purchase an arbitrary amount of ETH.

Copy link
Contributor

Choose a reason for hiding this comment

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

The exactOutputSingle function allows you to buy EXACTLY 0.1 ETH using an arbitrary amount of USDC. In contrast, exactInputSingle lets you spend EXACTLY 1000 USDC to purchase an arbitrary amount of ETH.

how it corresponding to my question?

}

// TODO: How can we detect if user has input wrong lowerPrice? We can inverse it if necessary (i.e. tokenA != token0)
// TODO: How can we detect if user has input wrong upperPrice? We can inverse it if necessary (i.e. tokenA != token0)
Copy link
Contributor

Choose a reason for hiding this comment

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

yes. This function not ready. You must handle case when price inverted.

Copy link
Author

Choose a reason for hiding this comment

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

I've been thinking about absolute price inputs for a while, and I believe it might make sense to remove them. They can be too ambiguous for both the end user and the code to handle properly.

For example, if the current price of Ethereum is 2800 USD/ETH, the inverse price would be around 0.0003571 ETH/USD. If a user mistakenly defines a liquidity range as 0.0003 USD/ETH to 0.0004 USD/ETH (note the incorrect units), how would we know that the input was an error? We could introduce a threshold (e.g., if the price is more than 50% away from the current one, trigger an error), but that would still leave room for mistakes.

To avoid this, it might be safer to just use relative pricing, where the user sets the price as a percentage of the current price.

I’d love to hear your thoughts on this.

}

function priceToTick(
price: string | undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is any problems with UniswapV3 SDK usage? priceToTick you can use from SDK

@kustrun
Copy link
Author

kustrun commented Feb 13, 2025

@OoXooOx I’ve addressed the highlighted comments. There are still a few outstanding ones, and I’d love to hear your feedback on them. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants