ts: Fix getMaxWithdrawWithBorrowForToken and add getGroupTokenVaultBalanceByMint

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-08-22 13:02:43 +02:00
parent 9aa0a94794
commit 357710dc24
4 changed files with 46 additions and 20 deletions

View File

@ -1,16 +1,17 @@
import { BorshAccountsCoder } from '@project-serum/anchor'; import { BorshAccountsCoder } from '@project-serum/anchor';
import { coder } from '@project-serum/anchor/dist/cjs/spl/associated-token';
import { Market } from '@project-serum/serum'; import { Market } from '@project-serum/serum';
import { parsePriceData, PriceData } from '@pythnetwork/client'; import { parsePriceData, PriceData } from '@pythnetwork/client';
import { PublicKey } from '@solana/web3.js'; import { PublicKey } from '@solana/web3.js';
import BN from 'bn.js';
import { MangoClient } from '../client'; import { MangoClient } from '../client';
import { SERUM3_PROGRAM_ID } from '../constants'; import { SERUM3_PROGRAM_ID } from '../constants';
import { Id } from '../ids'; import { Id } from '../ids';
import { toNativeDecimals } from '../utils';
import { Bank, MintInfo } from './bank'; import { Bank, MintInfo } from './bank';
import { I80F48, ONE_I80F48 } from './I80F48'; import { I80F48, ONE_I80F48 } from './I80F48';
import { PerpMarket } from './perp'; import { PerpMarket } from './perp';
import { Serum3Market } from './serum3'; import { Serum3Market } from './serum3';
import { toNativeDecimals } from '../utils';
import BN from 'bn.js';
export class Group { export class Group {
static from( static from(
@ -267,6 +268,30 @@ export class Group {
return this.banksMapByTokenIndex.get(tokenIndex)[0]; return this.banksMapByTokenIndex.get(tokenIndex)[0];
} }
/**
*
* @param client
* @param mintPk
* @returns sum of native balances of all vaults for a token
*/
public async getGroupTokenVaultBalanceByMint(
client: MangoClient,
mintPk: PublicKey,
): Promise<I80F48> {
const banks = this.banksMapByMint.get(mintPk.toString());
const amount = new BN(0);
for (const bank of banks) {
amount.add(
coder().accounts.decode(
'token',
(await client.program.provider.connection.getAccountInfo(bank.vault))
.data,
).amount,
);
}
return new I80F48(amount);
}
public consoleLogBanks() { public consoleLogBanks() {
for (const mintBanks of this.banksMapByMint.values()) { for (const mintBanks of this.banksMapByMint.values()) {
for (const bank of mintBanks) { for (const bank of mintBanks) {

View File

@ -365,8 +365,8 @@ export class HealthCache {
return amount return amount
.div(source.oraclePrice) .div(source.oraclePrice)
.mul( .div(
ONE_I80F48.sub( ONE_I80F48.add(
group.getFirstBankByMint(sourceMintPk).loanOriginationFeeRate, group.getFirstBankByMint(sourceMintPk).loanOriginationFeeRate,
), ),
); );

View File

@ -101,11 +101,9 @@ export class MangoAccount {
static getEquivalentUsdcPosition( static getEquivalentUsdcPosition(
sourceBank: Bank, sourceBank: Bank,
nativeTokenPosition: TokenPosition, tp: TokenPosition,
): I80F48 { ): I80F48 {
return nativeTokenPosition return tp ? tp.balance(sourceBank).mul(sourceBank.price) : ZERO_I80F48;
? nativeTokenPosition.balance(sourceBank).mul(sourceBank.price)
: ZERO_I80F48;
} }
static getEquivalentTokenPosition( static getEquivalentTokenPosition(
@ -244,23 +242,27 @@ export class MangoAccount {
} }
/** /**
* The amount of given native token you can borrow, considering all existing assets as collateral except the deposits for this token. * The amount of given native token you can withdraw including borrows, considering all existing assets as collateral.
* Note 1: The existing native deposits need to be added to get the full amount that could be withdrawn. * @returns amount of given native token you can borrow, considering all existing assets as collateral, in native token
* Note 2: The group might have less native deposits than what this returns. TODO: loan origination fees
* @returns amount of given native token you can borrow, considering all existing assets as collateral except the deposits for this token, in native token
*/ */
getMaxWithdrawWithBorrowForToken(group: Group, mintPk: PublicKey): I80F48 { getMaxWithdrawWithBorrowForToken(group: Group, mintPk: PublicKey): I80F48 {
const bank: Bank = group.getFirstBankByMint(mintPk); const bank: Bank = group.getFirstBankByMint(mintPk);
const initHealth = (this.accountData as MangoAccountData).initHealth; const initHealth = (this.accountData as MangoAccountData).initHealth;
const inUsdcUnits = MangoAccount.getEquivalentUsdcPosition( const existingPositioninUsdcUnits = MangoAccount.getEquivalentUsdcPosition(
bank, bank,
this.findToken(bank.tokenIndex), this.findToken(bank.tokenIndex),
).max(ZERO_I80F48); ).max(ZERO_I80F48);
const newInitHealth = initHealth.sub(inUsdcUnits.mul(bank.initAssetWeight)); const initHealthWithoutExistingPosition = initHealth.sub(
return MangoAccount.getEquivalentTokenPosition( existingPositioninUsdcUnits.mul(bank.initAssetWeight),
bank,
newInitHealth.div(bank.initLiabWeight),
); );
const maxBorrowNative = MangoAccount.getEquivalentTokenPosition(
bank,
initHealthWithoutExistingPosition.div(bank.initLiabWeight),
);
const maxBorrowNativeWithoutFees = maxBorrowNative.div(
ONE_I80F48.add(bank.loanOriginationFeeRate),
);
return maxBorrowNativeWithoutFees.add(this.getTokenBalance(bank));
} }
/** /**

View File

@ -73,9 +73,8 @@ async function main() {
coder() coder()
.accounts.decode( .accounts.decode(
'token', 'token',
await ( (await client.program.provider.connection.getAccountInfo(bank.vault))
await client.program.provider.connection.getAccountInfo(bank.vault) .data,
).data,
) )
.amount.toNumber(), .amount.toNumber(),
); );