Skip to content

Commit

Permalink
support out of range deposit (#427)
Browse files Browse the repository at this point in the history
* allow out of range single sided deposit

* fix tests

* cleanup

* remove comments
  • Loading branch information
silviutroscot authored Nov 22, 2023
1 parent ab16cf7 commit 796f2b6
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 16 deletions.
63 changes: 54 additions & 9 deletions packages/kamino-sdk/src/Kamino.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2443,6 +2443,8 @@ export class Kamino {
allAccounts: PublicKey[]
) => this.getJupSwapIxsV6(input, tokenAMint, tokenBMint, user, slippageBps, false, allAccounts, profiler);

console.log('single sided deposit tokenA tokenAMinPostDepositBalance', tokenAMinPostDepositBalance);
console.log('single sided deposit tokenA userTokenBalances.b', userTokenBalances.b);
return await profiler(
this.getSingleSidedDepositIxs(
strategyWithAddress,
Expand Down Expand Up @@ -2727,11 +2729,11 @@ export class Kamino {
);

const getGlobalConfigPromise = GlobalConfig.fetch(this._connection, strategyState.globalConfig);
const [createAtasIxns, amountsToDepositWithSwap, globalConfig] = await profiler(
Promise.all([createAtasIxnsPromise, amountsToDepositWithSwapPromise, getGlobalConfigPromise]),
'B-promiseAll(createAtasIxns, amountsToDepositWithSwap)',
[]
);
const [createAtasIxns, amountsToDepositWithSwap, globalConfig] = await Promise.all([
createAtasIxnsPromise,
amountsToDepositWithSwapPromise,
getGlobalConfigPromise,
]);

let checkExpectedVaultsBalancesIx = await profiler(
this.getCheckExpectedVaultsBalancesIx(strategyWithAddress, owner, tokenAAta, tokenBAta, {
Expand Down Expand Up @@ -2766,7 +2768,7 @@ export class Kamino {
sharesMint: strategyState.sharesMint,
sharesMintAuthority: strategyState.sharesMintAuthority,
scopePrices: strategyState.scopePrices,
tokenInfos: globalConfig.tokenInfos,
tokenInfos: globalConfig!.tokenInfos,
tokenProgram: TOKEN_PROGRAM_ID,
instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
};
Expand All @@ -2788,6 +2790,15 @@ export class Kamino {
...extractKeys(cleanupIxs),
];

// if we have no tokens to sell skip the jup tx
if (
amountsToDepositWithSwap.tokenAToSwapAmount.gte(ZERO) &&
amountsToDepositWithSwap.tokenBToSwapAmount.gte(ZERO)
) {
result = result.concat([checkExpectedVaultsBalancesIx, singleSidedDepositIx, ...cleanupIxs]);
return { instructions: result, lookupTablesAddresses: [] };
}

let [jupSwapIxs, lookupTablesAddresses] = await profiler(
Kamino.retryAsync(async () =>
profiler(
Expand Down Expand Up @@ -5120,14 +5131,48 @@ export class Kamino {
let orcaAmountA = aAmounts.div(new Decimal(10).pow(tokenADecimals));
let orcaAmountB = bAmounts.div(new Decimal(10).pow(tokenBDecimals));

let ratio = orcaAmountA.div(orcaAmountB);
ratio = ratio.div(priceBInA);

// multiply by tokens delta to make sure that both values uses the same about of decimals
let totalUserDepositInA = aAmount
.mul(10 ** tokenAAddDecimals)
.add(bAmount.mul(10 ** tokenBAddDecimals).mul(priceBInA));

// if the strategy is out of range we will deposit only one token so we will need to swap everything to that token
if (orcaAmountA.eq(ZERO)) {
let requiredAAmountToDeposit = ZERO;
let requiredBAmountToDeposit = totalUserDepositInA.mul(priceAInB);

let tokenAToSwapAmount = requiredAAmountToDeposit.sub(tokenAAmountUserDeposit);
let tokenBToSwapAmount = requiredBAmountToDeposit.sub(tokenBAmountUserDeposit);

let depositAmountsForSwap: DepositAmountsForSwap = {
requiredAAmountToDeposit,
requiredBAmountToDeposit,
tokenAToSwapAmount,
tokenBToSwapAmount,
};

return depositAmountsForSwap;
}

if (orcaAmountB.eq(ZERO)) {
let requiredAAmountToDeposit = totalUserDepositInA;
let requiredBAmountToDeposit = ZERO;

let tokenAToSwapAmount = requiredAAmountToDeposit.sub(tokenAAmountUserDeposit);
let tokenBToSwapAmount = requiredBAmountToDeposit.sub(tokenBAmountUserDeposit);

let depositAmountsForSwap: DepositAmountsForSwap = {
requiredAAmountToDeposit,
requiredBAmountToDeposit,
tokenAToSwapAmount,
tokenBToSwapAmount,
};

return depositAmountsForSwap;
}
let ratio = orcaAmountA.div(orcaAmountB);
ratio = ratio.div(priceBInA);

let requiredAAmountToDeposit = totalUserDepositInA
.mul(ratio)
.div(ratio.add(1))
Expand Down
2 changes: 1 addition & 1 deletion packages/kamino-sdk/src/services/JupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export class JupService {
params.vsAmount = 100;
}

const res = await axios.get('https://quote-api.jup.ag/v4/price', { params });
const res = await axios.get('https://quote-api.jup.ag/v6/price', { params });
return res.data.data[inputMint.toString()].price;
};

Expand Down
12 changes: 6 additions & 6 deletions packages/kamino-sdk/tests/stratCreation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1526,7 +1526,7 @@ describe('Kamino strategy creation SDK Tests', () => {
let bAtaBalance = await balance(kamino.getConnection(), signer, strategyState.tokenBMint);
console.log('balances ', toJson({ aAtaBalance, bAtaBalance, sharesAtaBalanceBefore }));

let aPrice = await jupService.getPrice(strategyState.tokenAMint, USDCMintMainnet);
let aPrice = await JupService.getPrice(strategyState.tokenAMint, USDCMintMainnet);

console.log('shareData', toJson(shareDataBefore));
console.log('shares minted', strategyState.sharesIssued.toString());
Expand Down Expand Up @@ -1592,8 +1592,8 @@ describe('Kamino strategy creation SDK Tests', () => {
let bAtaBalance = await balance(kamino.getConnection(), signer, strategyState.tokenBMint);
console.log('balances ', toJson({ aAtaBalance, bAtaBalance, sharesAtaBalanceAfter }));

let aPrice = await jupService.getPrice(strategyState.tokenAMint, USDCMintMainnet);
let bPrice = await jupService.getPrice(strategyState.tokenBMint, USDCMintMainnet);
let aPrice = await JupService.getPrice(strategyState.tokenAMint, USDCMintMainnet);
let bPrice = await JupService.getPrice(strategyState.tokenBMint, USDCMintMainnet);

console.log('shareData', toJson(shareDataAfter));
console.log('shares minted', strategyState.sharesIssued.toString());
Expand Down Expand Up @@ -1694,14 +1694,14 @@ describe('Kamino strategy creation SDK Tests', () => {
RAYDIUM_PROGRAM_ID
);

let [, ix] = await kamino.initializeTickForOrcaPool(
let initPoolTickIfNeeded = await kamino.initializeTickForOrcaPool(
signer.publicKey,
new PublicKey('7qbRF6YsyGuLUVs6Y1q64bdVrfe4ZcUUz1JRdoVNUJnm'),
new Decimal(0.1)
);

if (ix) {
const initTickIx = await kamino.getTransactionV2Message(signer.publicKey, [ix]);
if (initPoolTickIfNeeded.initTickIx) {
const initTickIx = await kamino.getTransactionV2Message(signer.publicKey, [initPoolTickIfNeeded.initTickIx]);
const txV0 = new VersionedTransaction(initTickIx);
txV0.sign([signer]);
//@ts-ignore
Expand Down

0 comments on commit 796f2b6

Please sign in to comment.