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

Get underlying assets of tick range #6595

Closed
wants to merge 15 commits into from
Closed

Conversation

hieuvubk
Copy link
Contributor

Closes: #6340

What is the purpose of the change

Create a query to get underlying assets of a tick range but currently we can only get the assets of 2 consecutive ticks, need to think of a way to get assets between any 2 ticks.

(E.g.: This pull request improves documentation of area A by adding ....

Testing and Verifying

(Please pick one of the following options)

This change is a trivial rework / code cleanup without any test coverage.

(or)

This change is already covered by existing tests, such as (please describe tests).

(or)

This change added tests and can be verified as follows:

(example:)

  • Added unit test that validates ...
  • Added integration tests for end-to-end deployment with ...
  • Extended integration test for ...
  • Manually verified the change by ...

Documentation and Release Note

  • Does this pull request introduce a new feature or user-facing behavior changes?
  • Changelog entry added to Unreleased section of CHANGELOG.md?

Where is the change documented?

  • Specification (x/{module}/README.md)
  • Osmosis documentation site
  • Code comments?
  • N/A

@mattverse mattverse self-assigned this Sep 29, 2023
@pysel
Copy link
Member

pysel commented Sep 29, 2023

hey @hieuvubk. could you please mark this as draft while CI is not passing? thanks!

@hieuvubk hieuvubk marked this pull request as draft October 1, 2023 19:11
@hieuvubk hieuvubk added the V:state/compatible/no_backport State machine compatible PR, depends on prior breaks label Oct 2, 2023
@hieuvubk hieuvubk marked this pull request as ready for review October 2, 2023 11:19
@@ -318,3 +318,16 @@ func (q Querier) NumNextInitializedTicks(ctx sdk.Context, req clquery.NumNextIni

return &clquery.NumNextInitializedTicksResponse{LiquidityDepths: liquidityDepths, CurrentLiquidity: pool.GetLiquidity(), CurrentTick: pool.GetCurrentTick()}, nil
}

// TickRangeUnderlyingAssets returns uderlying asset of a tick range
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// TickRangeUnderlyingAssets returns uderlying asset of a tick range
// TickRangeUnderlyingAssets returns underlying asset of a tick range

@@ -336,3 +336,93 @@ func (k Keeper) GetNumNextInitializedTicks(ctx sdk.Context, poolId, numberOfNext

return liquidityDepths, nil
}

// GetNumNextInitializedTicks is a method that returns underlying assets of a tick range
Copy link
Member

Choose a reason for hiding this comment

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

I think godoc has a wrong function name here

// GetNumNextInitializedTicks is a method that returns underlying assets of a tick range
// Errors:
// * ticks given not found
// * There exists at least 1 tick inside the given range
Copy link
Member

Choose a reason for hiding this comment

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

I might be missing something, but why do we have to restrict a query for only consecutive ticks?

Copy link
Member

Choose a reason for hiding this comment

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

Same question for me as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sr guys for the late reply, I'm keeping the current logic limited to 2 consecutive ticks because it's quite confusing with the tick range overlaps different positions.
Lets say I have an example below, range [10, 13] is not the intersection of the 3 given positions while [10, 11] is the intersection of positions 10 and 50 have liquidity 60, [11, 13] is the intersection of 3 positions have liquidity 160. So what liquidity of range [10, 13] should be, I'm leaning towards 100 because the tick range is wider but I'm not sure.
If u can help me with this issue it would be great thank so so much
cc @pysel @mattverse
Ảnh chụp Màn hình 2023-09-25 lúc 21 41 18

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sr guys for the late reply, I'm keeping the current logic limited to 2 consecutive ticks because it's quite confusing with the tick range overlaps different positions.
Lets say I have an example below, range [10, 13] is not the intersection of the 3 given positions while [10, 11] is the intersection of positions 10 and 50 have liquidity 60, [11, 13] is the intersection of 3 positions have liquidity 160. So what liquidity of range [10, 13] should be, I'm leaning towards 60 because the tick range is wider but I'm not sure.
If u can help me with this issue it would be great thank so so much
cc @pysel @mattverse
Ảnh chụp Màn hình 2023-09-25 lúc 21 41 18

// Find first tick initialized
// use false for zeroForOne since we're going from lower tick -> upper tick
zeroForOne := false
swapStrategy := swapstrategy.New(zeroForOne, osmomath.ZeroBigDec(), k.storeKey, osmomath.ZeroDec())
Copy link
Member

Choose a reason for hiding this comment

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

I think we should not introduce a variable if we only use it once

Suggested change
swapStrategy := swapstrategy.New(zeroForOne, osmomath.ZeroBigDec(), k.storeKey, osmomath.ZeroDec())
swapStrategy := swapstrategy.New(false, osmomath.ZeroBigDec(), k.storeKey, osmomath.ZeroDec())

zeroForOne := false
swapStrategy := swapstrategy.New(zeroForOne, osmomath.ZeroBigDec(), k.storeKey, osmomath.ZeroDec())

nextTickIter := swapStrategy.InitializeNextTickIterator(ctx, poolId, types.MinCurrentTick)
Copy link
Member

@pysel pysel Oct 2, 2023

Choose a reason for hiding this comment

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

asking to learn: is it possible to get an iterator without swap strategy? it is weird using swap strategy in this context

Copy link
Member

Choose a reason for hiding this comment

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

also, why are we using a minimum tick here and not a lower tick?

Copy link
Member

Choose a reason for hiding this comment

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

yeah we use swap strategy for iterating over ticks, perhaps we need to rename it some day

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I feel like we should be starting from lower tick

// Create a full-range position
data0, err := s.App.ConcentratedLiquidityKeeper.CreatePosition(
s.Ctx,
1,
Copy link
Member

Choose a reason for hiding this comment

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

nit: just a personal pedantic suggestion: I think it would be better to dynamically get pool's id from returned by PrepareCustomConcentratedPool pool extension

s.Ctx,
1,
s.TestAccs[0],
sdk.NewCoins(sdk.NewCoin("uosmo", sdk.NewInt(1000000)), sdk.NewCoin("atom", sdk.NewInt(1000000))),
Copy link
Member

Choose a reason for hiding this comment

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

nit: we can define these coins at the beginning of a test

tests := []struct {
name string
req queryproto.TickRangeUnderlyingAssetsRequest
expectedAmount0 sdk.Int
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
expectedAmount0 sdk.Int
expectedAmount0 osmomath.Int

UpperTick: types.MaxTick,
},
expectedAmount0: math.CalcAmount0Delta(osmomath.BigDecFromDec(data2.Liquidity), positive100TickSqrtPrice, maxTickSqrtPrice, true).Dec().TruncateInt(),
expectedAmount1: sdk.ZeroInt(),
Copy link
Member

@pysel pysel Oct 2, 2023

Choose a reason for hiding this comment

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

we are using osmomath's numericals

Suggested change
expectedAmount1: sdk.ZeroInt(),
expectedAmount1: osmomath.ZeroInt(),

s.Run(test.name, func() {
res, err := s.App.ConcentratedLiquidityKeeper.TickRangeUnderlyingAssets(s.Ctx, test.req.PoolId, test.req.LowerTick, test.req.UpperTick)
if test.expectedError {
s.Require().Error(err)
Copy link
Member

Choose a reason for hiding this comment

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

nit: shall we check for a specific error in this test?

Copy link
Member

@mattverse mattverse left a comment

Choose a reason for hiding this comment

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

Left some comments please take a look

Generally, I don't see how this differs from the GetTickLiquidityNetInDirection query, @hieuvubk can you explain how this is different from the GetTickLiquidityNetInDirection query?


// TickRangeUnderlyingAssets returns uderlying asset of a tick range
func (q Querier) TickRangeUnderlyingAssets(ctx sdk.Context, req clquery.TickRangeUnderlyingAssetsRequest) (*clquery.TickRangeUnderlyingAssetsResponse, error) {
if req.PoolId == 0 {
Copy link
Member

Choose a reason for hiding this comment

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

Lets move all checks into one place for code sanity please, I think we can move this check to query.go

// GetNumNextInitializedTicks is a method that returns underlying assets of a tick range
// Errors:
// * ticks given not found
// * There exists at least 1 tick inside the given range
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// * There exists at least 1 tick inside the given range
// * No tick initialized is in the given range

// GetNumNextInitializedTicks is a method that returns underlying assets of a tick range
// Errors:
// * ticks given not found
// * There exists at least 1 tick inside the given range
Copy link
Member

Choose a reason for hiding this comment

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

Same question for me as well

// need to think of a way to get assets between any 2 ticks
func (k Keeper) TickRangeUnderlyingAssets(ctx sdk.Context, poolId uint64, lowerTick, upperTick int64) (queryproto.TickRangeUnderlyingAssetsResponse, error) {
pool, err := k.getPoolById(ctx, poolId)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to return nils here instead of empty structs?


// Find first tick initialized
// use false for zeroForOne since we're going from lower tick -> upper tick
zeroForOne := false
Copy link
Member

Choose a reason for hiding this comment

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

Why is that we are going zero for one as default? Should it not differ according to the asset?

zeroForOne := false
swapStrategy := swapstrategy.New(zeroForOne, osmomath.ZeroBigDec(), k.storeKey, osmomath.ZeroDec())

nextTickIter := swapStrategy.InitializeNextTickIterator(ctx, poolId, types.MinCurrentTick)
Copy link
Member

Choose a reason for hiding this comment

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

yeah we use swap strategy for iterating over ticks, perhaps we need to rename it some day

zeroForOne := false
swapStrategy := swapstrategy.New(zeroForOne, osmomath.ZeroBigDec(), k.storeKey, osmomath.ZeroDec())

nextTickIter := swapStrategy.InitializeNextTickIterator(ctx, poolId, types.MinCurrentTick)
Copy link
Member

Choose a reason for hiding this comment

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

Yeah I feel like we should be starting from lower tick

@hieuvubk
Copy link
Contributor Author

Left some comments please take a look

Generally, I don't see how this differs from the GetTickLiquidityNetInDirection query, @hieuvubk can you explain how this is different from the GetTickLiquidityNetInDirection query?

I think GetTickLiquidityNetInDirection returns the LiquidityNet of all ticks in the range [start, bound] in one direction whilte this func aims to return how many tokens are locked within the price range (get liquidity of range then convert to virtual tokens locked)

@github-actions
Copy link
Contributor

This pull request has been automatically marked as stale because it has not had any recent activity. It will be closed if no further activity occurs. Thank you!

@github-actions github-actions bot added the Stale label Oct 25, 2023
@github-actions github-actions bot closed this Oct 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C:CLI C:x/concentrated-liquidity Stale V:state/compatible/no_backport State machine compatible PR, depends on prior breaks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[CL]: Add query for getting underlying assets for unit of liquidity
3 participants