mc/mango account units docs (#181)

* cleanup mango account docs

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* note

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from reviews

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from reviews

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from reviews

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-08-18 16:19:37 +02:00 committed by GitHub
parent 403226dc28
commit 7ad39238b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 107 additions and 30 deletions

View File

@ -99,12 +99,13 @@ export class MangoAccount {
return this.serum3.find((sa) => sa.marketIndex == marketIndex);
}
getNative(bank: Bank): I80F48 {
const ta = this.findToken(bank.tokenIndex);
return ta ? ta.native(bank) : ZERO_I80F48;
}
// How to navigate
// * if a function is returning a I80F48, then usually the return value is in native quote or native token, unless specified
// * if a function is returning a number, then usually the return value is in native tokens, unless specified
// * functions try to be explicit by having native or ui in the name to better reflect the value
// * some values might appear unexpected large or small, usually the doc contains a "note"
static getEquivalentNativeUsdcPosition(
static getEquivalentUsdcPosition(
sourceBank: Bank,
nativeTokenPosition: TokenPosition,
): I80F48 {
@ -117,7 +118,7 @@ export class MangoAccount {
: ZERO_I80F48;
}
static getEquivalentNativeTokenPosition(
static getEquivalentTokenPosition(
targetBank: Bank,
nativeUsdcPosition: I80F48,
): I80F48 {
@ -127,51 +128,100 @@ export class MangoAccount {
.mul(I80F48.fromNumber(Math.pow(10, targetBank.mintDecimals)));
}
getNativeDeposits(bank: Bank): I80F48 {
const native = this.getNative(bank);
/**
*
* @param bank
* @returns native balance for a token
*/
getTokenBalance(bank: Bank): I80F48 {
const ta = this.findToken(bank.tokenIndex);
return ta ? ta.native(bank) : ZERO_I80F48;
}
/**
*
* @param bank
* @returns native balance for a token, 0 or more
*/
getTokenDeposits(bank: Bank): I80F48 {
const native = this.getTokenBalance(bank);
return native.gte(ZERO_I80F48) ? native : ZERO_I80F48;
}
getNativeBorrows(bank: Bank): I80F48 {
const native = this.getNative(bank);
/**
*
* @param bank
* @returns native balance for a token, 0 or less
*/
getTokenBorrows(bank: Bank): I80F48 {
const native = this.getTokenBalance(bank);
return native.lte(ZERO_I80F48) ? native : ZERO_I80F48;
}
getUi(bank: Bank): number {
/**
*
* @param bank
* @returns UI balance for a token
*/
getTokenBalanceUi(bank: Bank): number {
const ta = this.findToken(bank.tokenIndex);
return ta ? ta.ui(bank) : 0;
return ta ? ta.balanceUi(bank) : 0;
}
deposits(bank: Bank): number {
/**
*
* @param bank
* @returns UI balance for a token, 0 or more
*/
getTokenDepositsUi(bank: Bank): number {
const ta = this.findToken(bank.tokenIndex);
return ta ? ta.uiDeposits(bank) : 0;
return ta ? ta.depositsUi(bank) : 0;
}
borrows(bank: Bank): number {
/**
*
* @param bank
* @returns UI balance for a token, 0 or less
*/
getTokenBorrowsUi(bank: Bank): number {
const ta = this.findToken(bank.tokenIndex);
return ta ? ta.uiBorrows(bank) : 0;
return ta ? ta.borrowsUi(bank) : 0;
}
/**
* Health, see health.rs or https://docs.mango.markets/mango-markets/health-overview
* @param healthType
* @returns raw health number, in native quote
*/
getHealth(healthType: HealthType): I80F48 {
return healthType == HealthType.init
? (this.accountData as MangoAccountData).initHealth
: (this.accountData as MangoAccountData).maintHealth;
}
/**
* Health ratio, which is computed so `100 * (assets-liabs)/liabs`
* Note: health ratio is technically if liabs are 0
* @param healthType
* @returns health ratio, in percentage form
*/
getHealthRatio(healthType: HealthType): I80F48 {
return this.accountData.healthCache.healthRatio(healthType);
}
/**
* Health ratio
* @param healthType
* @returns health ratio, in percentage form, capped to 100
*/
getHealthRatioUi(healthType: HealthType): number {
const ratio = this.accountData.healthCache
.healthRatio(healthType)
.toNumber();
const ratio = this.getHealthRatio(healthType).toNumber();
return ratio > 100 ? 100 : Math.trunc(ratio);
}
/**
* Sum of all the assets i.e. token deposits, borrows, total assets in spot open orders, (perps positions is todo) in terms of quote value.
* @returns equity, in native quote
*/
getEquity(): I80F48 {
const equity = (this.accountData as MangoAccountData).equity;
@ -184,6 +234,7 @@ export class MangoAccount {
/**
* The amount of native quote you could withdraw against your existing assets.
* @returns collateral value, in native quote
*/
getCollateralValue(): I80F48 {
return this.getHealth(HealthType.init);
@ -191,15 +242,17 @@ export class MangoAccount {
/**
* Sum of all positive assets.
* @returns assets, in native quote
*/
getAssetsVal(healthType: HealthType): I80F48 {
getAssetsValue(healthType: HealthType): I80F48 {
return this.accountData.healthCache.assets(healthType);
}
/**
* Sum of all negative assets.
* @returns liabs, in native quote
*/
getLiabsVal(healthType: HealthType): I80F48 {
getLiabsValue(healthType: HealthType): I80F48 {
return this.accountData.healthCache.liabs(healthType);
}
@ -207,16 +260,17 @@ export class MangoAccount {
* The amount of given native token you can borrow, considering all existing assets as collateral except the deposits for this token.
* Note 1: The existing native deposits need to be added to get the full amount that could be withdrawn.
* 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 {
const bank: Bank = group.getFirstBankByMint(mintPk);
const initHealth = (this.accountData as MangoAccountData).initHealth;
const inUsdcUnits = MangoAccount.getEquivalentNativeUsdcPosition(
const inUsdcUnits = MangoAccount.getEquivalentUsdcPosition(
bank,
this.findToken(bank.tokenIndex),
).max(ZERO_I80F48);
const newInitHealth = initHealth.sub(inUsdcUnits.mul(bank.initAssetWeight));
return MangoAccount.getEquivalentNativeTokenPosition(
return MangoAccount.getEquivalentTokenPosition(
bank,
newInitHealth.div(bank.initLiabWeight),
);
@ -227,6 +281,7 @@ export class MangoAccount {
* note: slippageAndFeesFactor is a normalized number, <1,
* e.g. a slippage of 5% and some fees which are 1%, then slippageAndFeesFactor = 0.94
* the factor is used to compute how much target can be obtained by swapping source
* @returns max amount of given source native token you can swap to a target token, in native token
*/
getMaxSourceForTokenSwap(
group: Group,
@ -247,6 +302,8 @@ export class MangoAccount {
/**
* Simulates new health ratio after applying tokenChanges to the token positions.
* e.g. useful to simulate health after a potential swap.
* Note: health ratio is technically if liabs are 0
* @returns health ratio, in percentage form
*/
simHealthRatioWithTokenPositionChanges(
group: Group,
@ -267,7 +324,7 @@ export class MangoAccount {
* The remaining native quote margin available for given market.
*
* TODO: this is a very bad estimation atm.
* It assumes quote asset is always USDC,
* It assumes quote asset is always quote,
* it assumes that there are no interaction effects,
* it assumes that there are no existing borrows for either of the tokens in the market.
*/
@ -284,7 +341,7 @@ export class MangoAccount {
* The remaining native quote margin available for given market.
*
* TODO: this is a very bad estimation atm.
* It assumes quote asset is always USDC,
* It assumes quote asset is always quote,
* it assumes that there are no interaction effects,
* it assumes that there are no existing borrows for either of the tokens in the market.
*/
@ -370,18 +427,38 @@ export class TokenPosition {
}
}
public ui(bank: Bank): number {
/**
* @param bank
* @returns position in UI decimals, is signed
*/
public balanceUi(bank: Bank): number {
return nativeI80F48ToUi(this.native(bank), bank.mintDecimals).toNumber();
}
public uiDeposits(bank: Bank): number {
/**
* @param bank
* @returns position in UI decimals, 0 if position has borrows
*/
public depositsUi(bank: Bank): number {
if (this.indexedPosition && this.indexedPosition.lt(ZERO_I80F48)) {
return 0;
}
return nativeI80F48ToUi(
bank.depositIndex.mul(this.indexedPosition),
bank.mintDecimals,
).toNumber();
}
public uiBorrows(bank: Bank): number {
/**
* @param bank
* @returns position in UI decimals, can be 0 or negative, 0 if position has deposits
*/
public borrowsUi(bank: Bank): number {
if (this.indexedPosition && this.indexedPosition.gt(ZERO_I80F48)) {
return 0;
}
return nativeI80F48ToUi(
bank.borrowIndex.mul(this.indexedPosition),
bank.mintDecimals,
@ -395,7 +472,7 @@ export class TokenPosition {
if (bank) {
const native = this.native(bank);
extra += ', native: ' + native.toNumber();
extra += ', ui: ' + this.ui(bank);
extra += ', ui: ' + this.balanceUi(bank);
extra += ', tokenName: ' + bank.name;
}
}