Skip to content

Commit

Permalink
fix reading meteora (#450)
Browse files Browse the repository at this point in the history
* Update IDL + add meteora IDL

* Modify kamino SDK with new IDL

* Add meteora to ignore prettier

* Add more meteora handling

* Add meteora logic

* v3.0.29-staging

* Add changes

* Update gitignore

* v3.0.30-staging

* v3.0.29-staging-01

* Update with latest changes

* v3.0.29-staging-02

* update fee tier computation for meteora

* v3.0.29-staging-03

* Override global config automatically when staging

* v3.0.29-staging-04

* .

* Change === to equals

* wip: tests

* v3.0.29-staging-05

* 3.0.29-staging-06

* fix decimals reading

* v3.0.29-staging-07

* return explicit tupe

* Update meteora service

* v3.0.29-staging-08

* One small fix

* v3.0.29-staging-09

* fix account size

* v3.0.29-staging-10

* wip

* fix meteora NaN issues

* linting

* cleanup

* address Nejc's comments

* fix lint

---------

Co-authored-by: alittlezz <valentinwhite2@gmail.com>
  • Loading branch information
silviutroscot and alittlezz authored Jan 26, 2024
1 parent 73ba59c commit 0cfc746
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,4 @@ packages/kamino-sdk/deps/scope.so
packages/kamino-sdk/deps/whirlpool.so
.DS_Store


keypair.json
8 changes: 2 additions & 6 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
{
"packages": [
"packages/*"
],
"packages": ["packages/*"],
"version": "4.0.0",
"command": {
"publish": {
"ignoreChanges": [
"tests/**"
]
"ignoreChanges": ["tests/**"]
}
}
}
94 changes: 56 additions & 38 deletions packages/kamino-sdk/src/Kamino.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1587,9 +1587,10 @@ export class Kamino {
collateralInfos: CollateralInfo[],
prices?: OraclePrices
): Promise<StrategyBalances> => {
const strategyPrices = await this.getStrategyPrices(strategy, collateralInfos, prices);
const strategyPricesPromise = this.getStrategyPrices(strategy, collateralInfos, prices);
const rebalanceKind = numberToRebalanceType(strategy.rebalanceType);
const tokenHoldings = await this.getMeteoraTokensBalances(strategy);
const tokenHoldingsPromise = this.getMeteoraTokensBalances(strategy);
let [strategyPrices, tokenHoldings] = await Promise.all([strategyPricesPromise, tokenHoldingsPromise]);

let computedHoldings: Holdings = this.getStrategyHoldingsUsd(
tokenHoldings.available.a,
Expand Down Expand Up @@ -2307,7 +2308,7 @@ export class Kamino {
decimalsA: number,
decimalsB: number
): Promise<PositionRange> => {
if (positionPk.toString() === PublicKey.default.toString()) {
if (positionPk.equals(PublicKey.default)) {
return { lowerPrice: ZERO, upperPrice: ZERO };
}
let position = await PositionV2.fetch(this._connection, positionPk);
Expand Down Expand Up @@ -2399,7 +2400,7 @@ export class Kamino {
};

getMeteoraPositions = async (positions: PublicKey[]): Promise<(PositionV2 | null)[]> => {
const nonDefaults = positions.filter((value) => value.toBase58() !== PublicKey.default.toBase58());
const nonDefaults = positions.filter((value) => !value.equals(PublicKey.default));
const fetched = await batchFetch(nonDefaults, (chunk) => PositionV2.fetchMultiple(this._connection, chunk));
const fetchedMap: Record<string, PositionV2 | null> = fetched.reduce((map, position, i) => {
map[nonDefaults[i].toBase58()] = position;
Expand Down Expand Up @@ -3881,10 +3882,8 @@ export class Kamino {
}
poolRewardVault0 = poolState.rewardInfos[0].vault;
poolRewardVault1 = poolState.rewardInfos[1].vault;
poolRewardVault2 = poolState.rewardInfos[2].vault;
rewardMint0 = poolState.rewardInfos[0].mint;
rewardMint1 = poolState.rewardInfos[1].mint;
rewardMint2 = poolState.rewardInfos[2].mint;
}

const accounts: CollectFeesAndRewardsAccounts = {
Expand All @@ -3906,13 +3905,12 @@ export class Kamino {
baseVaultAuthority: strategyState.baseVaultAuthority,
reward0Vault: strategyState.reward0Vault,
reward1Vault: strategyState.reward1Vault,
reward2Vault: strategyState.reward2Vault,
reward2Vault: strategyState.baseVaultAuthority,
poolRewardVault0:
strategyState.reward0Decimals.toNumber() > 0 ? poolRewardVault0 : strategyState.baseVaultAuthority,
poolRewardVault1:
strategyState.reward1Decimals.toNumber() > 0 ? poolRewardVault1 : strategyState.baseVaultAuthority,
poolRewardVault2:
strategyState.reward2Decimals.toNumber() > 0 ? poolRewardVault2 : strategyState.baseVaultAuthority,
poolRewardVault2: strategyState.baseVaultAuthority,
tickArrayLower: strategyState.tickArrayLower,
tickArrayUpper: strategyState.tickArrayUpper,
raydiumProtocolPositionOrBaseVaultAuthority: strategyState.raydiumProtocolPositionOrBaseVaultAuthority,
Expand All @@ -3921,7 +3919,7 @@ export class Kamino {
instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
reward0Mint: strategyState.reward0Decimals.toNumber() > 0 ? rewardMint0 : this._kaminoProgramId,
reward1Mint: strategyState.reward1Decimals.toNumber() > 0 ? rewardMint1 : this._kaminoProgramId,
reward2Mint: strategyState.reward2Decimals.toNumber() > 0 ? rewardMint2 : this._kaminoProgramId,
reward2Mint: this._kaminoProgramId,
eventAuthority,
};

Expand Down Expand Up @@ -4036,21 +4034,27 @@ export class Kamino {

private readMeteoraPosition = async (poolPk: PublicKey, positionPk: PublicKey): Promise<MeteoraPosition> => {
let pool = await LbPair.fetch(this._connection, poolPk);
if (!pool) {
throw new Error(`Could not find position ${poolPk}`);
}
let position = await PositionV2.fetch(this._connection, positionPk);
if (!position) {
throw new Error(`Could not find position ${positionPk} for pool ${poolPk}`);
if (!pool || !position) {
return {
publicKey: positionPk,
amountX: new Decimal(0),
amountY: new Decimal(0),
};
}

let { lowerTick: lowerTickPk, upperTick: upperTickPk } = this.getStartEndTicketIndexProgramAddressesMeteora(
poolPk,
position.lowerBinId
);
let lowerBinArray = await BinArray.fetch(this._connection, lowerTickPk);
let upperBinArray = await BinArray.fetch(this._connection, upperTickPk);
if (!lowerBinArray || !upperBinArray) {
throw new Error(`Could not find either ${lowerTickPk} or ${upperTickPk}`);
return {
publicKey: positionPk,
amountX: new Decimal(0),
amountY: new Decimal(0),
};
}
let binArrays = [lowerBinArray, upperBinArray];
let totalAmountX = new Decimal(0);
Expand Down Expand Up @@ -4763,12 +4767,6 @@ export class Kamino {
getNearestValidTickIndexFromTickIndex(rebalanceParams[0].toNumber(), whilrpoolState.tickSpacing)
);
}
} else if (dex == 'RAYDIUM') {
// no processing needed
} else if (dex == 'METEORA') {
// no processing needed
} else {
throw Error(`Invalid dex ${dex}`);
}

return processedRebalanceParams;
Expand Down Expand Up @@ -6602,17 +6600,41 @@ export class Kamino {
let amountADecimal = new Decimal(0);
let amountBDecimal = new Decimal(0);
if (bin) {
amountADecimal = new Decimal(bin.amountX.toString());
amountBDecimal = new Decimal(bin.amountY.toString());
if (!bin.amountX.eq(new BN(0))) {
amountADecimal = new Decimal(bin.amountX.toString());
}
if (!bin.amountY.eq(new BN(0))) {
amountBDecimal = new Decimal(bin.amountY.toString());
}
} else {
throw new Error(`bin ${poolState.activeId.toString()} is not found`);
}

if (amountADecimal.eq(ZERO) && amountBDecimal.eq(ZERO)) {
const decimalsA = await getMintDecimals(this._connection, strategyState.tokenAMint);
const decimalsB = await getMintDecimals(this._connection, strategyState.tokenBMint);
const poolPrice = getPriceOfBinByBinIdWithDecimals(poolState.activeId, poolState.binStep, decimalsA, decimalsB);
return [tokenAAmount || tokenBAmount!.div(poolPrice), tokenBAmount || tokenAAmount!.mul(poolPrice)];
}

if (amountBDecimal.eq(ZERO)) {
return [tokenAAmount!, ZERO];
}

if (amountADecimal.eq(ZERO)) {
return [ZERO, tokenBAmount!];
}

const ratio = amountADecimal.div(amountBDecimal);
if (tokenAAmount === undefined || tokenAAmount.eq(ZERO)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return [tokenBAmount!.mul(ratio), tokenBAmount!];
let amountA = tokenBAmount!.mul(ratio) || new Decimal(0);
return [amountA, tokenBAmount!];
}

if (tokenBAmount === undefined || tokenBAmount.eq(ZERO)) {
return [tokenAAmount, tokenAAmount.div(ratio)];
let amountB = tokenAAmount.div(ratio) || new Decimal(0);
return [tokenAAmount, amountB];
}
}

Expand Down Expand Up @@ -6744,16 +6766,14 @@ export class Kamino {
): Promise<{ amountSlippageA: BN; amountSlippageB: BN }> {
const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);

const poolState = await LbPair.fetch(this._connection, strategyState.pool);
const poolStatePromise = LbPair.fetch(this._connection, strategyState.pool);
const positionPromise = PositionV2.fetch(this._connection, strategyState.position);

let [poolState, _position] = await Promise.all([poolStatePromise, positionPromise]);
if (!poolState) {
throw Error(`Could not fetch lb pair state with pubkey ${strategyState.pool.toString()}`);
}

const position = await PositionV2.fetch(this._connection, strategyState.position);
if (!position) {
throw new Error(`Meteora position ${strategyState.position} does not exist`);
}

return { amountSlippageA: new BN(0), amountSlippageB: new BN(0) };
}

Expand All @@ -6763,16 +6783,14 @@ export class Kamino {
): Promise<{ amountSlippageA: BN; amountSlippageB: BN }> {
const { strategy: strategyState } = await this.getStrategyStateIfNotFetched(strategy);

const poolState = await LbPair.fetch(this._connection, strategyState.pool);
const poolStatePromise = await LbPair.fetch(this._connection, strategyState.pool);
const positionPromise = await PositionV2.fetch(this._connection, strategyState.position);
let [poolState, _position] = await Promise.all([poolStatePromise, positionPromise]);

if (!poolState) {
throw Error(`Could not fetch lb pair state with pubkey ${strategyState.pool.toString()}`);
}

const position = await PositionV2.fetch(this._connection, strategyState.position);
if (!position) {
throw new Error(`Meteora position ${strategyState.position} does not exist`);
}

return { amountSlippageA: new BN(0), amountSlippageB: new BN(0) };
}

Expand Down
Loading

0 comments on commit 0cfc746

Please sign in to comment.