@raydium-io/raydium-sdk-v2
Version:
An SDK for building applications on top of Raydium.
151 lines (134 loc) • 5.46 kB
text/typescript
import BN from 'bn.js';
import { TickLayout } from '../layout';
import { mulDivFloor, wrappingSubU128 } from './bigNum';
import { Q64 } from './constants';
export class PositionUtils {
static getfeeGrowthInside(
poolState: {
tickCurrent: number,
feeGrowthGlobalX64A: BN,
feeGrowthGlobalX64B: BN,
},
tickLowerState: ReturnType<typeof TickLayout.decode>,
tickUpperState: ReturnType<typeof TickLayout.decode>
): { feeGrowthInsideX64A: BN, feeGrowthInsideBX64: BN } {
let feeGrowthBelowX64A = new BN(0)
let feeGrowthBelowX64B = new BN(0)
if (poolState.tickCurrent >= tickLowerState.tick) {
feeGrowthBelowX64A = tickLowerState.feeGrowthOutsideX64A
feeGrowthBelowX64B = tickLowerState.feeGrowthOutsideX64B
} else {
feeGrowthBelowX64A = wrappingSubU128(poolState.feeGrowthGlobalX64A, tickLowerState.feeGrowthOutsideX64A)
feeGrowthBelowX64B = wrappingSubU128(poolState.feeGrowthGlobalX64B, tickLowerState.feeGrowthOutsideX64B)
}
let feeGrowthAboveX64A = new BN(0)
let feeGrowthAboveX64B = new BN(0)
if (poolState.tickCurrent < tickUpperState.tick) {
feeGrowthAboveX64A = tickUpperState.feeGrowthOutsideX64A
feeGrowthAboveX64B = tickUpperState.feeGrowthOutsideX64B
} else {
feeGrowthAboveX64A = wrappingSubU128(poolState.feeGrowthGlobalX64A, tickUpperState.feeGrowthOutsideX64A)
feeGrowthAboveX64B = wrappingSubU128(poolState.feeGrowthGlobalX64B, tickUpperState.feeGrowthOutsideX64B)
}
const feeGrowthInsideX64A = wrappingSubU128(
wrappingSubU128(poolState.feeGrowthGlobalX64A, feeGrowthBelowX64A),
feeGrowthAboveX64A,
)
const feeGrowthInsideBX64 = wrappingSubU128(
wrappingSubU128(poolState.feeGrowthGlobalX64B, feeGrowthBelowX64B),
feeGrowthAboveX64B,
)
return { feeGrowthInsideX64A, feeGrowthInsideBX64 }
}
static GetPositionFees(
ammPool: {
tickCurrent: number,
feeGrowthGlobalX64A: BN,
feeGrowthGlobalX64B: BN,
},
positionState: {
liquidity: BN
feeGrowthInsideLastX64A: BN
feeGrowthInsideLastX64B: BN
tokenFeesOwedA: BN
tokenFeesOwedB: BN
},
tickLowerState: ReturnType<typeof TickLayout.decode>,
tickUpperState: ReturnType<typeof TickLayout.decode>,
): { tokenFeeAmountA: BN, tokenFeeAmountB: BN } {
const { feeGrowthInsideX64A, feeGrowthInsideBX64 } = this.getfeeGrowthInside(
ammPool,
tickLowerState,
tickUpperState,
)
const feeGrowthdeltaA = mulDivFloor(
wrappingSubU128(feeGrowthInsideX64A, positionState.feeGrowthInsideLastX64A),
positionState.liquidity,
Q64,
)
const tokenFeeAmountA = positionState.tokenFeesOwedA.add(feeGrowthdeltaA)
const feeGrowthdelta1 = mulDivFloor(
wrappingSubU128(feeGrowthInsideBX64, positionState.feeGrowthInsideLastX64B),
positionState.liquidity,
Q64,
)
const tokenFeeAmountB = positionState.tokenFeesOwedB.add(feeGrowthdelta1)
return { tokenFeeAmountA, tokenFeeAmountB }
}
static GetPositionRewards(
ammPool: { tickCurrent: number, rewardInfos: { growthGlobalX64: BN }[] },
positionState: { liquidity: BN, rewardInfos: { growthInsideLastX64: BN, rewardAmountOwed: BN }[] },
tickLowerState: ReturnType<typeof TickLayout.decode>,
tickUpperState: ReturnType<typeof TickLayout.decode>,
): BN[] {
const rewards: BN[] = []
const rewardGrowthsInside = this.getRewardGrowthInside(
ammPool.tickCurrent,
tickLowerState,
tickUpperState,
ammPool.rewardInfos,
)
for (let i = 0; i < rewardGrowthsInside.length; i++) {
const rewardGrowthInside = rewardGrowthsInside[i]
const currRewardInfo = positionState.rewardInfos[i]
const rewardGrowthDelta = wrappingSubU128(rewardGrowthInside, currRewardInfo.growthInsideLastX64)
const amountOwedDelta = mulDivFloor(rewardGrowthDelta, positionState.liquidity, Q64)
const rewardAmountOwed = currRewardInfo.rewardAmountOwed.add(amountOwedDelta)
rewards.push(rewardAmountOwed)
}
return rewards
}
static getRewardGrowthInside(
tickCurrentIndex: number,
tickLowerState: ReturnType<typeof TickLayout.decode>,
tickUpperState: ReturnType<typeof TickLayout.decode>,
rewardInfos: { growthGlobalX64: BN }[]
): BN[] {
const rewardGrowthsInside: BN[] = []
for (let i = 0; i < rewardInfos.length; i++) {
let rewardGrowthsBelow = new BN(0)
if (tickLowerState.liquidityGross.eqn(0)) {
rewardGrowthsBelow = rewardInfos[i].growthGlobalX64
} else if (tickCurrentIndex < tickLowerState.tick) {
rewardGrowthsBelow = wrappingSubU128(rewardInfos[i].growthGlobalX64, tickLowerState.rewardGrowthsOutsideX64[i])
} else {
rewardGrowthsBelow = tickLowerState.rewardGrowthsOutsideX64[i]
}
let rewardGrowthsAbove = new BN(0)
if (tickUpperState.liquidityGross.eqn(0)) {
//
} else if (tickCurrentIndex < tickUpperState.tick) {
rewardGrowthsAbove = tickUpperState.rewardGrowthsOutsideX64[i]
} else {
rewardGrowthsAbove = wrappingSubU128(rewardInfos[i].growthGlobalX64, tickUpperState.rewardGrowthsOutsideX64[i])
}
rewardGrowthsInside.push(
wrappingSubU128(
wrappingSubU128(rewardInfos[i].growthGlobalX64, rewardGrowthsBelow),
rewardGrowthsAbove,
),
)
}
return rewardGrowthsInside
}
}