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:
parent
403226dc28
commit
7ad39238b1
|
@ -99,12 +99,13 @@ export class MangoAccount {
|
||||||
return this.serum3.find((sa) => sa.marketIndex == marketIndex);
|
return this.serum3.find((sa) => sa.marketIndex == marketIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
getNative(bank: Bank): I80F48 {
|
// How to navigate
|
||||||
const ta = this.findToken(bank.tokenIndex);
|
// * if a function is returning a I80F48, then usually the return value is in native quote or native token, unless specified
|
||||||
return ta ? ta.native(bank) : ZERO_I80F48;
|
// * 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,
|
sourceBank: Bank,
|
||||||
nativeTokenPosition: TokenPosition,
|
nativeTokenPosition: TokenPosition,
|
||||||
): I80F48 {
|
): I80F48 {
|
||||||
|
@ -117,7 +118,7 @@ export class MangoAccount {
|
||||||
: ZERO_I80F48;
|
: ZERO_I80F48;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getEquivalentNativeTokenPosition(
|
static getEquivalentTokenPosition(
|
||||||
targetBank: Bank,
|
targetBank: Bank,
|
||||||
nativeUsdcPosition: I80F48,
|
nativeUsdcPosition: I80F48,
|
||||||
): I80F48 {
|
): I80F48 {
|
||||||
|
@ -127,51 +128,100 @@ export class MangoAccount {
|
||||||
.mul(I80F48.fromNumber(Math.pow(10, targetBank.mintDecimals)));
|
.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;
|
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;
|
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);
|
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);
|
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);
|
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 {
|
getHealth(healthType: HealthType): I80F48 {
|
||||||
return healthType == HealthType.init
|
return healthType == HealthType.init
|
||||||
? (this.accountData as MangoAccountData).initHealth
|
? (this.accountData as MangoAccountData).initHealth
|
||||||
: (this.accountData as MangoAccountData).maintHealth;
|
: (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 {
|
getHealthRatio(healthType: HealthType): I80F48 {
|
||||||
return this.accountData.healthCache.healthRatio(healthType);
|
return this.accountData.healthCache.healthRatio(healthType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health ratio
|
||||||
|
* @param healthType
|
||||||
|
* @returns health ratio, in percentage form, capped to 100
|
||||||
|
*/
|
||||||
getHealthRatioUi(healthType: HealthType): number {
|
getHealthRatioUi(healthType: HealthType): number {
|
||||||
const ratio = this.accountData.healthCache
|
const ratio = this.getHealthRatio(healthType).toNumber();
|
||||||
.healthRatio(healthType)
|
|
||||||
.toNumber();
|
|
||||||
|
|
||||||
return ratio > 100 ? 100 : Math.trunc(ratio);
|
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.
|
* 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 {
|
getEquity(): I80F48 {
|
||||||
const equity = (this.accountData as MangoAccountData).equity;
|
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.
|
* The amount of native quote you could withdraw against your existing assets.
|
||||||
|
* @returns collateral value, in native quote
|
||||||
*/
|
*/
|
||||||
getCollateralValue(): I80F48 {
|
getCollateralValue(): I80F48 {
|
||||||
return this.getHealth(HealthType.init);
|
return this.getHealth(HealthType.init);
|
||||||
|
@ -191,15 +242,17 @@ export class MangoAccount {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sum of all positive assets.
|
* Sum of all positive assets.
|
||||||
|
* @returns assets, in native quote
|
||||||
*/
|
*/
|
||||||
getAssetsVal(healthType: HealthType): I80F48 {
|
getAssetsValue(healthType: HealthType): I80F48 {
|
||||||
return this.accountData.healthCache.assets(healthType);
|
return this.accountData.healthCache.assets(healthType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sum of all negative assets.
|
* Sum of all negative assets.
|
||||||
|
* @returns liabs, in native quote
|
||||||
*/
|
*/
|
||||||
getLiabsVal(healthType: HealthType): I80F48 {
|
getLiabsValue(healthType: HealthType): I80F48 {
|
||||||
return this.accountData.healthCache.liabs(healthType);
|
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.
|
* 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 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
|
* 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.getEquivalentNativeUsdcPosition(
|
const inUsdcUnits = 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 newInitHealth = initHealth.sub(inUsdcUnits.mul(bank.initAssetWeight));
|
||||||
return MangoAccount.getEquivalentNativeTokenPosition(
|
return MangoAccount.getEquivalentTokenPosition(
|
||||||
bank,
|
bank,
|
||||||
newInitHealth.div(bank.initLiabWeight),
|
newInitHealth.div(bank.initLiabWeight),
|
||||||
);
|
);
|
||||||
|
@ -227,6 +281,7 @@ export class MangoAccount {
|
||||||
* note: slippageAndFeesFactor is a normalized number, <1,
|
* note: slippageAndFeesFactor is a normalized number, <1,
|
||||||
* e.g. a slippage of 5% and some fees which are 1%, then slippageAndFeesFactor = 0.94
|
* 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
|
* 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(
|
getMaxSourceForTokenSwap(
|
||||||
group: Group,
|
group: Group,
|
||||||
|
@ -247,6 +302,8 @@ export class MangoAccount {
|
||||||
/**
|
/**
|
||||||
* Simulates new health ratio after applying tokenChanges to the token positions.
|
* Simulates new health ratio after applying tokenChanges to the token positions.
|
||||||
* e.g. useful to simulate health after a potential swap.
|
* 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(
|
simHealthRatioWithTokenPositionChanges(
|
||||||
group: Group,
|
group: Group,
|
||||||
|
@ -267,7 +324,7 @@ export class MangoAccount {
|
||||||
* The remaining native quote margin available for given market.
|
* The remaining native quote margin available for given market.
|
||||||
*
|
*
|
||||||
* TODO: this is a very bad estimation atm.
|
* 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 interaction effects,
|
||||||
* it assumes that there are no existing borrows for either of the tokens in the market.
|
* 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.
|
* The remaining native quote margin available for given market.
|
||||||
*
|
*
|
||||||
* TODO: this is a very bad estimation atm.
|
* 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 interaction effects,
|
||||||
* it assumes that there are no existing borrows for either of the tokens in the market.
|
* 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();
|
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(
|
return nativeI80F48ToUi(
|
||||||
bank.depositIndex.mul(this.indexedPosition),
|
bank.depositIndex.mul(this.indexedPosition),
|
||||||
bank.mintDecimals,
|
bank.mintDecimals,
|
||||||
).toNumber();
|
).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(
|
return nativeI80F48ToUi(
|
||||||
bank.borrowIndex.mul(this.indexedPosition),
|
bank.borrowIndex.mul(this.indexedPosition),
|
||||||
bank.mintDecimals,
|
bank.mintDecimals,
|
||||||
|
@ -395,7 +472,7 @@ export class TokenPosition {
|
||||||
if (bank) {
|
if (bank) {
|
||||||
const native = this.native(bank);
|
const native = this.native(bank);
|
||||||
extra += ', native: ' + native.toNumber();
|
extra += ', native: ' + native.toNumber();
|
||||||
extra += ', ui: ' + this.ui(bank);
|
extra += ', ui: ' + this.balanceUi(bank);
|
||||||
extra += ', tokenName: ' + bank.name;
|
extra += ', tokenName: ' + bank.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue