mc/i80F48 in-place cleanups (#203)
* ts: use in place I80F48 wherever applicable Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * ts: dont overwrite I80F48 constants Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> * Fix script Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
0c6cc16023
commit
5f62f15549
|
@ -197,16 +197,16 @@ export class I80F48 {
|
|||
return this.data.cmp(x.getData());
|
||||
}
|
||||
neg(): I80F48 {
|
||||
return this.mul(NEG_ONE_I80F48);
|
||||
return this.mul(_NEG_ONE_I80F48);
|
||||
}
|
||||
isPos(): boolean {
|
||||
return this.gt(ZERO_I80F48);
|
||||
return this.gt(_ZERO_I80F48);
|
||||
}
|
||||
isNeg(): boolean {
|
||||
return this.data.isNeg();
|
||||
}
|
||||
isZero(): boolean {
|
||||
return this.eq(ZERO_I80F48);
|
||||
return this.eq(_ZERO_I80F48);
|
||||
}
|
||||
min(x: I80F48): I80F48 {
|
||||
return this.lte(x) ? this : x;
|
||||
|
@ -224,10 +224,22 @@ export class I80F48 {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
export const ONE_I80F48 = I80F48.fromNumber(1);
|
||||
const _ZERO_I80F48 = I80F48.fromNumber(0);
|
||||
/** @internal */
|
||||
export const ZERO_I80F48 = I80F48.fromNumber(0);
|
||||
/** @internal */
|
||||
export const NEG_ONE_I80F48 = I80F48.fromNumber(-1);
|
||||
export const HUNDRED_I80F48 = I80F48.fromNumber(100);
|
||||
export const MAX_I80F48 = new I80F48(I80F48.MAX_BN);
|
||||
const _NEG_ONE_I80F48 = I80F48.fromNumber(-1);
|
||||
|
||||
export function ONE_I80F48(): I80F48 {
|
||||
return I80F48.fromNumber(1);
|
||||
}
|
||||
|
||||
export function ZERO_I80F48(): I80F48 {
|
||||
return I80F48.fromNumber(0);
|
||||
}
|
||||
|
||||
export function HUNDRED_I80F48(): I80F48 {
|
||||
return I80F48.fromNumber(100);
|
||||
}
|
||||
|
||||
export function MAX_I80F48(): I80F48 {
|
||||
return new I80F48(I80F48.MAX_BN);
|
||||
}
|
||||
|
|
|
@ -286,8 +286,8 @@ export class Bank {
|
|||
const totalBorrows = this.nativeBorrows();
|
||||
const totalDeposits = this.nativeDeposits();
|
||||
|
||||
if (totalDeposits.eq(ZERO_I80F48) && totalBorrows.eq(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (totalDeposits.isZero() && totalBorrows.isZero()) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
if (totalDeposits.lte(totalBorrows)) {
|
||||
return this.maxRate;
|
||||
|
@ -329,9 +329,9 @@ export class Bank {
|
|||
const totalBorrows = this.nativeBorrows();
|
||||
const totalDeposits = this.nativeDeposits();
|
||||
|
||||
if (totalDeposits.eq(ZERO_I80F48) && totalBorrows.eq(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
} else if (totalDeposits.eq(ZERO_I80F48)) {
|
||||
if (totalDeposits.isZero() && totalBorrows.isZero()) {
|
||||
return ZERO_I80F48();
|
||||
} else if (totalDeposits.isZero()) {
|
||||
return this.maxRate;
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ export class Group {
|
|||
for (const [index, price] of prices.entries()) {
|
||||
for (const bank of banks[index]) {
|
||||
if (bank.name === 'USDC') {
|
||||
bank.price = ONE_I80F48;
|
||||
bank.price = ONE_I80F48();
|
||||
bank.uiPrice = 1;
|
||||
} else {
|
||||
// TODO: Implement switchboard oracle type
|
||||
|
|
|
@ -53,31 +53,31 @@ export class HealthCache {
|
|||
}
|
||||
|
||||
public health(healthType: HealthType): I80F48 {
|
||||
let health = ZERO_I80F48;
|
||||
const health = ZERO_I80F48();
|
||||
for (const tokenInfo of this.tokenInfos) {
|
||||
const contrib = tokenInfo.healthContribution(healthType);
|
||||
health = health.add(contrib);
|
||||
health.iadd(contrib);
|
||||
}
|
||||
for (const serum3Info of this.serum3Infos) {
|
||||
const contrib = serum3Info.healthContribution(
|
||||
healthType,
|
||||
this.tokenInfos,
|
||||
);
|
||||
health = health.add(contrib);
|
||||
health.iadd(contrib);
|
||||
}
|
||||
for (const perpInfo of this.perpInfos) {
|
||||
const contrib = perpInfo.healthContribution(healthType);
|
||||
health = health.add(contrib);
|
||||
health.iadd(contrib);
|
||||
}
|
||||
return health;
|
||||
}
|
||||
|
||||
public assets(healthType: HealthType): I80F48 {
|
||||
let assets = ZERO_I80F48;
|
||||
const assets = ZERO_I80F48();
|
||||
for (const tokenInfo of this.tokenInfos) {
|
||||
const contrib = tokenInfo.healthContribution(healthType);
|
||||
if (contrib.isPos()) {
|
||||
assets = assets.add(contrib);
|
||||
assets.iadd(contrib);
|
||||
}
|
||||
}
|
||||
for (const serum3Info of this.serum3Infos) {
|
||||
|
@ -86,24 +86,24 @@ export class HealthCache {
|
|||
this.tokenInfos,
|
||||
);
|
||||
if (contrib.isPos()) {
|
||||
assets = assets.add(contrib);
|
||||
assets.iadd(contrib);
|
||||
}
|
||||
}
|
||||
for (const perpInfo of this.perpInfos) {
|
||||
const contrib = perpInfo.healthContribution(healthType);
|
||||
if (contrib.isPos()) {
|
||||
assets = assets.add(contrib);
|
||||
assets.iadd(contrib);
|
||||
}
|
||||
}
|
||||
return assets;
|
||||
}
|
||||
|
||||
public liabs(healthType: HealthType): I80F48 {
|
||||
let liabs = ZERO_I80F48;
|
||||
const liabs = ZERO_I80F48();
|
||||
for (const tokenInfo of this.tokenInfos) {
|
||||
const contrib = tokenInfo.healthContribution(healthType);
|
||||
if (contrib.isNeg()) {
|
||||
liabs = liabs.sub(contrib);
|
||||
liabs.isub(contrib);
|
||||
}
|
||||
}
|
||||
for (const serum3Info of this.serum3Infos) {
|
||||
|
@ -112,28 +112,28 @@ export class HealthCache {
|
|||
this.tokenInfos,
|
||||
);
|
||||
if (contrib.isNeg()) {
|
||||
liabs = liabs.sub(contrib);
|
||||
liabs.isub(contrib);
|
||||
}
|
||||
}
|
||||
for (const perpInfo of this.perpInfos) {
|
||||
const contrib = perpInfo.healthContribution(healthType);
|
||||
if (contrib.isNeg()) {
|
||||
liabs = liabs.sub(contrib);
|
||||
liabs.isub(contrib);
|
||||
}
|
||||
}
|
||||
return liabs;
|
||||
}
|
||||
|
||||
public healthRatio(healthType: HealthType): I80F48 {
|
||||
let assets = ZERO_I80F48;
|
||||
let liabs = ZERO_I80F48;
|
||||
const assets = ZERO_I80F48();
|
||||
const liabs = ZERO_I80F48();
|
||||
|
||||
for (const tokenInfo of this.tokenInfos) {
|
||||
const contrib = tokenInfo.healthContribution(healthType);
|
||||
if (contrib.isPos()) {
|
||||
assets = assets.add(contrib);
|
||||
assets.iadd(contrib);
|
||||
} else {
|
||||
liabs = liabs.sub(contrib);
|
||||
liabs.isub(contrib);
|
||||
}
|
||||
}
|
||||
for (const serum3Info of this.serum3Infos) {
|
||||
|
@ -142,24 +142,24 @@ export class HealthCache {
|
|||
this.tokenInfos,
|
||||
);
|
||||
if (contrib.isPos()) {
|
||||
assets = assets.add(contrib);
|
||||
assets.iadd(contrib);
|
||||
} else {
|
||||
liabs = liabs.sub(contrib);
|
||||
liabs.isub(contrib);
|
||||
}
|
||||
}
|
||||
for (const perpInfo of this.perpInfos) {
|
||||
const contrib = perpInfo.healthContribution(healthType);
|
||||
if (contrib.isPos()) {
|
||||
assets = assets.add(contrib);
|
||||
assets.iadd(contrib);
|
||||
} else {
|
||||
liabs = liabs.sub(contrib);
|
||||
liabs.isub(contrib);
|
||||
}
|
||||
}
|
||||
|
||||
if (liabs.isPos()) {
|
||||
return HUNDRED_I80F48.mul(assets.sub(liabs).div(liabs));
|
||||
return HUNDRED_I80F48().mul(assets.sub(liabs).div(liabs));
|
||||
} else {
|
||||
return MAX_I80F48;
|
||||
return MAX_I80F48();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,27 +189,18 @@ export class HealthCache {
|
|||
) {
|
||||
const baseEntryIndex = this.findTokenInfoIndex(baseTokenIndex);
|
||||
const quoteEntryIndex = this.findTokenInfoIndex(quoteTokenIndex);
|
||||
let reservedAmount = ZERO_I80F48;
|
||||
|
||||
const baseEntry = this.tokenInfos[baseEntryIndex];
|
||||
reservedAmount = reservedBaseChange.mul(baseEntry.oraclePrice);
|
||||
const reservedAmount = reservedBaseChange.mul(baseEntry.oraclePrice);
|
||||
|
||||
const quoteEntry = this.tokenInfos[quoteEntryIndex];
|
||||
reservedAmount = reservedAmount.add(
|
||||
reservedQuoteChange.mul(quoteEntry.oraclePrice),
|
||||
);
|
||||
reservedAmount.iadd(reservedQuoteChange.mul(quoteEntry.oraclePrice));
|
||||
|
||||
// Apply it to the tokens
|
||||
baseEntry.serum3MaxReserved =
|
||||
baseEntry.serum3MaxReserved.add(reservedAmount);
|
||||
baseEntry.balance = baseEntry.balance.add(
|
||||
freeBaseChange.mul(baseEntry.oraclePrice),
|
||||
);
|
||||
quoteEntry.serum3MaxReserved =
|
||||
quoteEntry.serum3MaxReserved.add(reservedAmount);
|
||||
quoteEntry.balance = quoteEntry.balance.add(
|
||||
freeQuoteChange.mul(quoteEntry.oraclePrice),
|
||||
);
|
||||
baseEntry.serum3MaxReserved.iadd(reservedAmount);
|
||||
baseEntry.balance.iadd(freeBaseChange.mul(baseEntry.oraclePrice));
|
||||
quoteEntry.serum3MaxReserved.iadd(reservedAmount);
|
||||
quoteEntry.balance.iadd(freeQuoteChange.mul(quoteEntry.oraclePrice));
|
||||
|
||||
// Apply it to the serum3 info
|
||||
const serum3Info = this.serum3Infos.find(
|
||||
|
@ -263,9 +254,9 @@ export class HealthCache {
|
|||
throw new Error(
|
||||
`Oracle price not loaded for ${change.mintPk.toString()}`,
|
||||
);
|
||||
adjustedCache.tokenInfos[changeIndex].balance = adjustedCache.tokenInfos[
|
||||
changeIndex
|
||||
].balance.add(change.nativeTokenAmount.mul(bank.price));
|
||||
adjustedCache.tokenInfos[changeIndex].balance.iadd(
|
||||
change.nativeTokenAmount.mul(bank.price),
|
||||
);
|
||||
}
|
||||
// HealthCache.logHealthCache('afterChange', adjustedCache);
|
||||
return adjustedCache.healthRatio(healthType);
|
||||
|
@ -291,19 +282,19 @@ export class HealthCache {
|
|||
// essentially simulating a place order
|
||||
|
||||
// Reduce token balance for quote
|
||||
adjustedCache.tokenInfos[quoteIndex].balance = adjustedCache.tokenInfos[
|
||||
quoteIndex
|
||||
].balance.sub(bidNativeQuoteAmount.mul(quote.oraclePrice));
|
||||
adjustedCache.tokenInfos[quoteIndex].balance.isub(
|
||||
bidNativeQuoteAmount.mul(quote.oraclePrice),
|
||||
);
|
||||
|
||||
// Increase reserved in Serum3Info for quote
|
||||
adjustedCache.adjustSerum3Reserved(
|
||||
serum3Market.marketIndex,
|
||||
serum3Market.baseTokenIndex,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48(),
|
||||
ZERO_I80F48(),
|
||||
serum3Market.quoteTokenIndex,
|
||||
bidNativeQuoteAmount,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48(),
|
||||
);
|
||||
return adjustedCache.healthRatio(healthType);
|
||||
}
|
||||
|
@ -328,19 +319,19 @@ export class HealthCache {
|
|||
// essentially simulating a place order
|
||||
|
||||
// Reduce token balance for base
|
||||
adjustedCache.tokenInfos[baseIndex].balance = adjustedCache.tokenInfos[
|
||||
baseIndex
|
||||
].balance.sub(askNativeBaseAmount.mul(base.oraclePrice));
|
||||
adjustedCache.tokenInfos[baseIndex].balance.isub(
|
||||
askNativeBaseAmount.mul(base.oraclePrice),
|
||||
);
|
||||
|
||||
// Increase reserved in Serum3Info for base
|
||||
adjustedCache.adjustSerum3Reserved(
|
||||
serum3Market.marketIndex,
|
||||
serum3Market.baseTokenIndex,
|
||||
askNativeBaseAmount,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48(),
|
||||
serum3Market.quoteTokenIndex,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48(),
|
||||
ZERO_I80F48(),
|
||||
);
|
||||
return adjustedCache.healthRatio(healthType);
|
||||
}
|
||||
|
@ -399,20 +390,20 @@ export class HealthCache {
|
|||
const targetBank: Bank = group.getFirstBankByMint(targetMintPk);
|
||||
|
||||
if (sourceMintPk.equals(targetMintPk)) {
|
||||
return ZERO_I80F48;
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
if (!sourceBank.price || sourceBank.price.lte(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (!sourceBank.price || sourceBank.price.lte(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
if (
|
||||
sourceBank.initLiabWeight
|
||||
.sub(targetBank.initAssetWeight)
|
||||
.abs()
|
||||
.lte(ZERO_I80F48)
|
||||
.lte(ZERO_I80F48())
|
||||
) {
|
||||
return ZERO_I80F48;
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
// The health_ratio is a nonlinear based on swap amount.
|
||||
|
@ -424,8 +415,8 @@ export class HealthCache {
|
|||
// - be careful about finding the minRatio point: the function isn't convex
|
||||
|
||||
const initialRatio = this.healthRatio(HealthType.init);
|
||||
if (initialRatio.lte(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (initialRatio.lte(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
const healthCacheClone: HealthCache = _.cloneDeep(this);
|
||||
|
@ -443,10 +434,8 @@ export class HealthCache {
|
|||
function cacheAfterSwap(amount: I80F48) {
|
||||
const adjustedCache: HealthCache = _.cloneDeep(healthCacheClone);
|
||||
// HealthCache.logHealthCache('beforeSwap', adjustedCache);
|
||||
adjustedCache.tokenInfos[sourceIndex].balance =
|
||||
adjustedCache.tokenInfos[sourceIndex].balance.sub(amount);
|
||||
adjustedCache.tokenInfos[targetIndex].balance =
|
||||
adjustedCache.tokenInfos[targetIndex].balance.add(amount);
|
||||
adjustedCache.tokenInfos[sourceIndex].balance.isub(amount);
|
||||
adjustedCache.tokenInfos[targetIndex].balance.iadd(amount);
|
||||
// HealthCache.logHealthCache('afterSwap', adjustedCache);
|
||||
return adjustedCache;
|
||||
}
|
||||
|
@ -457,10 +446,10 @@ export class HealthCache {
|
|||
|
||||
const point0Amount = source.balance
|
||||
.min(target.balance.neg())
|
||||
.max(ZERO_I80F48);
|
||||
.max(ZERO_I80F48());
|
||||
const point1Amount = source.balance
|
||||
.max(target.balance.neg())
|
||||
.max(ZERO_I80F48);
|
||||
.max(ZERO_I80F48());
|
||||
const cache0 = cacheAfterSwap(point0Amount);
|
||||
const point0Ratio = cache0.healthRatio(HealthType.init);
|
||||
const cache1 = cacheAfterSwap(point1Amount);
|
||||
|
@ -484,15 +473,15 @@ export class HealthCache {
|
|||
} else if (point1Ratio.gt(initialRatio)) {
|
||||
amount = point1Amount;
|
||||
} else {
|
||||
amount = ZERO_I80F48;
|
||||
amount = ZERO_I80F48();
|
||||
}
|
||||
} else if (point1Ratio.gte(minRatio)) {
|
||||
// If point1Ratio is still bigger than minRatio, the target amount must be >point1Amount
|
||||
// search to the right of point1Amount: but how far?
|
||||
// At point1, source.balance < 0 and target.balance > 0, so use a simple estimation for
|
||||
// zero health: health - source_liab_weight * a + target_asset_weight * a = 0.
|
||||
if (point1Health.lte(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (point1Health.lte(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
const zeroHealthAmount = point1Amount.add(
|
||||
point1Health.div(source.initLiabWeight.sub(target.initAssetWeight)),
|
||||
|
@ -525,7 +514,7 @@ export class HealthCache {
|
|||
return amount
|
||||
.div(source.oraclePrice)
|
||||
.div(
|
||||
ONE_I80F48.add(
|
||||
ONE_I80F48().add(
|
||||
group.getFirstBankByMint(sourceMintPk).loanOriginationFeeRate,
|
||||
),
|
||||
);
|
||||
|
@ -553,9 +542,7 @@ export class HealthCache {
|
|||
const healthCacheClone: HealthCache = _.cloneDeep(this);
|
||||
|
||||
const baseIndex = healthCacheClone.getOrCreateTokenInfoIndex(baseBank);
|
||||
const quoteIndex = healthCacheClone.getOrCreateTokenInfoIndex(
|
||||
quoteBank,
|
||||
);
|
||||
const quoteIndex = healthCacheClone.getOrCreateTokenInfoIndex(quoteBank);
|
||||
const base = healthCacheClone.tokenInfos[baseIndex];
|
||||
const quote = healthCacheClone.tokenInfos[quoteIndex];
|
||||
|
||||
|
@ -563,11 +550,11 @@ export class HealthCache {
|
|||
// an amount to trade which will bring health to 0.
|
||||
|
||||
// Current health and amount i.e. 0
|
||||
const initialAmount = ZERO_I80F48;
|
||||
const initialAmount = ZERO_I80F48();
|
||||
const initialHealth = this.health(HealthType.init);
|
||||
const initialRatio = this.healthRatio(HealthType.init);
|
||||
if (initialRatio.lte(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (initialRatio.lte(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
// Amount which would bring health to 0
|
||||
|
@ -577,9 +564,9 @@ export class HealthCache {
|
|||
// and when its a bid, then quote->bid
|
||||
let zeroAmount;
|
||||
if (side == Serum3Side.ask) {
|
||||
const quoteBorrows = quote.balance.lt(ZERO_I80F48)
|
||||
const quoteBorrows = quote.balance.lt(ZERO_I80F48())
|
||||
? quote.balance.abs()
|
||||
: ZERO_I80F48;
|
||||
: ZERO_I80F48();
|
||||
zeroAmount = base.balance
|
||||
.max(quoteBorrows)
|
||||
.add(
|
||||
|
@ -590,9 +577,9 @@ export class HealthCache {
|
|||
),
|
||||
);
|
||||
} else {
|
||||
const baseBorrows = base.balance.lt(ZERO_I80F48)
|
||||
const baseBorrows = base.balance.lt(ZERO_I80F48())
|
||||
? base.balance.abs()
|
||||
: ZERO_I80F48;
|
||||
: ZERO_I80F48();
|
||||
zeroAmount = quote.balance
|
||||
.max(baseBorrows)
|
||||
.add(
|
||||
|
@ -610,19 +597,17 @@ export class HealthCache {
|
|||
const adjustedCache: HealthCache = _.cloneDeep(healthCacheClone);
|
||||
|
||||
side === Serum3Side.ask
|
||||
? (adjustedCache.tokenInfos[baseIndex].balance =
|
||||
adjustedCache.tokenInfos[baseIndex].balance.sub(amount))
|
||||
: (adjustedCache.tokenInfos[quoteIndex].balance =
|
||||
adjustedCache.tokenInfos[quoteIndex].balance.sub(amount));
|
||||
? adjustedCache.tokenInfos[baseIndex].balance.isub(amount)
|
||||
: adjustedCache.tokenInfos[quoteIndex].balance.isub(amount);
|
||||
|
||||
adjustedCache.adjustSerum3Reserved(
|
||||
serum3Market.marketIndex,
|
||||
serum3Market.baseTokenIndex,
|
||||
side === Serum3Side.ask ? amount.div(base.oraclePrice) : ZERO_I80F48,
|
||||
ZERO_I80F48,
|
||||
side === Serum3Side.ask ? amount.div(base.oraclePrice) : ZERO_I80F48(),
|
||||
ZERO_I80F48(),
|
||||
serum3Market.quoteTokenIndex,
|
||||
side === Serum3Side.bid ? amount.div(quote.oraclePrice) : ZERO_I80F48,
|
||||
ZERO_I80F48,
|
||||
side === Serum3Side.bid ? amount.div(quote.oraclePrice) : ZERO_I80F48(),
|
||||
ZERO_I80F48(),
|
||||
);
|
||||
|
||||
return adjustedCache;
|
||||
|
@ -647,12 +632,12 @@ export class HealthCache {
|
|||
return side === Serum3Side.bid
|
||||
? amount
|
||||
.div(quote.oraclePrice)
|
||||
.div(ONE_I80F48.add(baseBank.loanOriginationFeeRate))
|
||||
.div(ONE_I80F48.add(I80F48.fromNumber(group.getFeeRate(false))))
|
||||
.div(ONE_I80F48().add(baseBank.loanOriginationFeeRate))
|
||||
.div(ONE_I80F48().add(I80F48.fromNumber(group.getFeeRate(false))))
|
||||
: amount
|
||||
.div(base.oraclePrice)
|
||||
.div(ONE_I80F48.add(quoteBank.loanOriginationFeeRate))
|
||||
.div(ONE_I80F48.add(I80F48.fromNumber(group.getFeeRate(false))));
|
||||
.div(ONE_I80F48().add(quoteBank.loanOriginationFeeRate))
|
||||
.div(ONE_I80F48().add(I80F48.fromNumber(group.getFeeRate(false))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,8 +681,8 @@ export class TokenInfo {
|
|||
bank.maintLiabWeight,
|
||||
bank.initLiabWeight,
|
||||
bank.price,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48(),
|
||||
ZERO_I80F48(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -753,7 +738,7 @@ export class Serum3Info {
|
|||
const reserved = this.reserved;
|
||||
|
||||
if (reserved.isZero()) {
|
||||
return ZERO_I80F48;
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
// How much the health would increase if the reserved balance were applied to the passed
|
||||
|
@ -768,9 +753,9 @@ export class Serum3Info {
|
|||
let assetPart, liabPart;
|
||||
if (maxBalance.gte(reserved)) {
|
||||
assetPart = reserved;
|
||||
liabPart = ZERO_I80F48;
|
||||
liabPart = ZERO_I80F48();
|
||||
} else if (maxBalance.isNeg()) {
|
||||
assetPart = ZERO_I80F48;
|
||||
assetPart = ZERO_I80F48();
|
||||
liabPart = reserved;
|
||||
} else {
|
||||
assetPart = maxBalance;
|
||||
|
@ -829,7 +814,7 @@ export class PerpInfo {
|
|||
|
||||
// FUTURE: Allow v3-style "reliable" markets where we can return
|
||||
// `self.quote + weight * self.base` here
|
||||
return this.quote.add(weight.mul(this.base)).min(ZERO_I80F48);
|
||||
return this.quote.add(weight.mul(this.base)).min(ZERO_I80F48());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ export class MangoAccount {
|
|||
*/
|
||||
getTokenBalance(bank: Bank): I80F48 {
|
||||
const tp = this.findToken(bank.tokenIndex);
|
||||
return tp ? tp.balance(bank) : ZERO_I80F48;
|
||||
return tp ? tp.balance(bank) : ZERO_I80F48();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +135,7 @@ export class MangoAccount {
|
|||
*/
|
||||
getTokenDeposits(bank: Bank): I80F48 {
|
||||
const tp = this.findToken(bank.tokenIndex);
|
||||
return tp ? tp.deposits(bank) : ZERO_I80F48;
|
||||
return tp ? tp.deposits(bank) : ZERO_I80F48();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,7 +145,7 @@ export class MangoAccount {
|
|||
*/
|
||||
getTokenBorrows(bank: Bank): I80F48 {
|
||||
const tp = this.findToken(bank.tokenIndex);
|
||||
return tp ? tp.borrows(bank) : ZERO_I80F48;
|
||||
return tp ? tp.borrows(bank) : ZERO_I80F48();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,7 +222,7 @@ export class MangoAccount {
|
|||
const equity = this.accountData.equity;
|
||||
const total_equity = equity.tokens.reduce(
|
||||
(a, b) => a.add(b.value),
|
||||
ZERO_I80F48,
|
||||
ZERO_I80F48(),
|
||||
);
|
||||
return total_equity;
|
||||
}
|
||||
|
@ -268,8 +268,8 @@ export class MangoAccount {
|
|||
|
||||
// Case 1:
|
||||
// Cannot withdraw if init health is below 0
|
||||
if (initHealth.lte(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (initHealth.lte(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
|
||||
// Deposits need special treatment since they would neither count towards liabilities
|
||||
|
@ -277,12 +277,12 @@ export class MangoAccount {
|
|||
|
||||
const tp = this.findToken(tokenBank.tokenIndex);
|
||||
if (!tokenBank.price) return undefined;
|
||||
const existingTokenDeposits = tp ? tp.deposits(tokenBank) : ZERO_I80F48;
|
||||
let existingPositionHealthContrib = ZERO_I80F48;
|
||||
if (existingTokenDeposits.gt(ZERO_I80F48)) {
|
||||
existingPositionHealthContrib = existingTokenDeposits
|
||||
.mul(tokenBank.price)
|
||||
.mul(tokenBank.initAssetWeight);
|
||||
const existingTokenDeposits = tp ? tp.deposits(tokenBank) : ZERO_I80F48();
|
||||
const existingPositionHealthContrib = ZERO_I80F48();
|
||||
if (existingTokenDeposits.gt(ZERO_I80F48())) {
|
||||
existingTokenDeposits
|
||||
.imul(tokenBank.price)
|
||||
.imul(tokenBank.initAssetWeight);
|
||||
}
|
||||
|
||||
// Case 2: token deposits have higher contribution than initHealth,
|
||||
|
@ -309,7 +309,7 @@ export class MangoAccount {
|
|||
.div(tokenBank.initLiabWeight)
|
||||
.div(tokenBank.price);
|
||||
const maxBorrowNativeWithoutFees = maxBorrowNative.div(
|
||||
ONE_I80F48.add(tokenBank.loanOriginationFeeRate),
|
||||
ONE_I80F48().add(tokenBank.loanOriginationFeeRate),
|
||||
);
|
||||
// console.log(`initHealth ${initHealth}`);
|
||||
// console.log(
|
||||
|
@ -357,7 +357,7 @@ export class MangoAccount {
|
|||
group,
|
||||
sourceMintPk,
|
||||
targetMintPk,
|
||||
ONE_I80F48, // target 1% health
|
||||
ONE_I80F48(), // target 1% health
|
||||
)
|
||||
.mul(I80F48.fromNumber(slippageAndFeesFactor));
|
||||
}
|
||||
|
@ -690,7 +690,7 @@ export class MangoAccount {
|
|||
const initHealth = this.accountData.initHealth;
|
||||
const perpMarket = group.perpMarketsMap.get(marketName)!;
|
||||
const marketAssetWeight = perpMarket.initAssetWeight;
|
||||
return initHealth.div(ONE_I80F48.sub(marketAssetWeight));
|
||||
return initHealth.div(ONE_I80F48().sub(marketAssetWeight));
|
||||
}
|
||||
|
||||
toString(group?: Group): string {
|
||||
|
@ -768,8 +768,8 @@ export class TokenPosition {
|
|||
* @returns native deposits, 0 if position has borrows
|
||||
*/
|
||||
public deposits(bank: Bank): I80F48 {
|
||||
if (this.indexedPosition && this.indexedPosition.lt(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (this.indexedPosition && this.indexedPosition.lt(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
return this.balance(bank);
|
||||
}
|
||||
|
@ -780,8 +780,8 @@ export class TokenPosition {
|
|||
* @returns native borrows, 0 if position has deposits
|
||||
*/
|
||||
public borrows(bank: Bank): I80F48 {
|
||||
if (this.indexedPosition && this.indexedPosition.gt(ZERO_I80F48)) {
|
||||
return ZERO_I80F48;
|
||||
if (this.indexedPosition && this.indexedPosition.gt(ZERO_I80F48())) {
|
||||
return ZERO_I80F48();
|
||||
}
|
||||
return this.balance(bank).abs();
|
||||
}
|
||||
|
|
|
@ -72,14 +72,14 @@ export class Serum3Market {
|
|||
}
|
||||
|
||||
if (
|
||||
quoteBank.initLiabWeight.sub(baseBank.initAssetWeight).lte(ZERO_I80F48)
|
||||
quoteBank.initLiabWeight.sub(baseBank.initAssetWeight).lte(ZERO_I80F48())
|
||||
) {
|
||||
return MAX_I80F48.toNumber();
|
||||
return MAX_I80F48().toNumber();
|
||||
}
|
||||
|
||||
return ONE_I80F48.div(
|
||||
quoteBank.initLiabWeight.sub(baseBank.initAssetWeight),
|
||||
).toNumber();
|
||||
return ONE_I80F48()
|
||||
.div(quoteBank.initLiabWeight.sub(baseBank.initAssetWeight))
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,14 +104,14 @@ export class Serum3Market {
|
|||
}
|
||||
|
||||
if (
|
||||
baseBank.initLiabWeight.sub(quoteBank.initAssetWeight).lte(ZERO_I80F48)
|
||||
baseBank.initLiabWeight.sub(quoteBank.initAssetWeight).lte(ZERO_I80F48())
|
||||
) {
|
||||
return MAX_I80F48.toNumber();
|
||||
return MAX_I80F48().toNumber();
|
||||
}
|
||||
|
||||
return ONE_I80F48.div(
|
||||
baseBank.initLiabWeight.sub(quoteBank.initAssetWeight),
|
||||
).toNumber();
|
||||
return ONE_I80F48()
|
||||
.div(baseBank.initLiabWeight.sub(quoteBank.initAssetWeight))
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
public async loadBids(client: MangoClient, group: Group): Promise<Orderbook> {
|
||||
|
|
|
@ -40,8 +40,8 @@ async function main() {
|
|||
const banks = Array.from(group.banksMapByMint.values()).flat();
|
||||
const banksMapUsingTokenIndex = new Map(
|
||||
banks.map((bank) => {
|
||||
(bank as any).indexedDepositsByMangoAccounts = ZERO_I80F48;
|
||||
(bank as any).indexedBorrowsByMangoAccounts = ZERO_I80F48;
|
||||
(bank as any).indexedDepositsByMangoAccounts = ZERO_I80F48();
|
||||
(bank as any).indexedBorrowsByMangoAccounts = ZERO_I80F48();
|
||||
return [bank.tokenIndex, bank];
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -24,8 +24,8 @@ async function debugUser(
|
|||
group,
|
||||
mangoAccount,
|
||||
[
|
||||
group.banksMapByName.get('BTC')[0],
|
||||
group.banksMapByName.get('USDC')[0],
|
||||
group.banksMapByName.get('BTC')![0],
|
||||
group.banksMapByName.get('USDC')![0],
|
||||
],
|
||||
[],
|
||||
)
|
||||
|
@ -34,15 +34,15 @@ async function debugUser(
|
|||
);
|
||||
console.log(
|
||||
'mangoAccount.getEquity() ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getEquity().toNumber()),
|
||||
toUiDecimalsForQuote(mangoAccount.getEquity()!.toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'mangoAccount.getHealth(HealthType.init) ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getHealth(HealthType.init).toNumber()),
|
||||
toUiDecimalsForQuote(mangoAccount.getHealth(HealthType.init)!.toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'mangoAccount.getHealthRatio(HealthType.init) ' +
|
||||
mangoAccount.getHealthRatio(HealthType.init).toNumber(),
|
||||
mangoAccount.getHealthRatio(HealthType.init)!.toNumber(),
|
||||
);
|
||||
console.log(
|
||||
'mangoAccount.getHealthRatioUi(HealthType.init) ' +
|
||||
|
@ -50,7 +50,7 @@ async function debugUser(
|
|||
);
|
||||
console.log(
|
||||
'mangoAccount.getHealthRatio(HealthType.maint) ' +
|
||||
mangoAccount.getHealthRatio(HealthType.maint).toNumber(),
|
||||
mangoAccount.getHealthRatio(HealthType.maint)!.toNumber(),
|
||||
);
|
||||
console.log(
|
||||
'mangoAccount.getHealthRatioUi(HealthType.maint) ' +
|
||||
|
@ -58,18 +58,18 @@ async function debugUser(
|
|||
);
|
||||
console.log(
|
||||
'mangoAccount.getCollateralValue() ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getCollateralValue().toNumber()),
|
||||
toUiDecimalsForQuote(mangoAccount.getCollateralValue()!.toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'mangoAccount.getAssetsValue() ' +
|
||||
toUiDecimalsForQuote(
|
||||
mangoAccount.getAssetsValue(HealthType.init).toNumber(),
|
||||
mangoAccount.getAssetsValue(HealthType.init)!.toNumber(),
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
'mangoAccount.getLiabsValue() ' +
|
||||
toUiDecimalsForQuote(
|
||||
mangoAccount.getLiabsValue(HealthType.init).toNumber(),
|
||||
mangoAccount.getLiabsValue(HealthType.init)!.toNumber(),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -78,7 +78,7 @@ async function debugUser(
|
|||
`mangoAccount.getMaxWithdrawWithBorrowForTokenUi(group, ${token}) ` +
|
||||
mangoAccount.getMaxWithdrawWithBorrowForTokenUi(
|
||||
group,
|
||||
group.banksMapByName.get(token)[0].mint,
|
||||
group.banksMapByName.get(token)![0].mint,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -94,29 +94,28 @@ async function debugUser(
|
|||
}
|
||||
for (const srcToken of Array.from(group.banksMapByName.keys())) {
|
||||
simHealthRatioWithTokenPositionChangesWrapper(`${srcToken} 1 `, {
|
||||
mintPk: group.banksMapByName.get(srcToken)[0].mint,
|
||||
mintPk: group.banksMapByName.get(srcToken)![0].mint,
|
||||
uiTokenAmount: 1,
|
||||
});
|
||||
simHealthRatioWithTokenPositionChangesWrapper(`${srcToken} -1 `, {
|
||||
mintPk: group.banksMapByName.get(srcToken)[0].mint,
|
||||
mintPk: group.banksMapByName.get(srcToken)![0].mint,
|
||||
uiTokenAmount: -1,
|
||||
});
|
||||
}
|
||||
|
||||
function getMaxSourceForTokenSwapWrapper(src, tgt) {
|
||||
// console.log();
|
||||
console.log(
|
||||
`getMaxSourceForTokenSwap ${src.padEnd(4)} ${tgt.padEnd(4)} ` +
|
||||
mangoAccount
|
||||
.getMaxSourceForTokenSwap(
|
||||
group,
|
||||
group.banksMapByName.get(src)[0].mint,
|
||||
group.banksMapByName.get(tgt)[0].mint,
|
||||
group.banksMapByName.get(src)![0].mint,
|
||||
group.banksMapByName.get(tgt)![0].mint,
|
||||
1,
|
||||
)
|
||||
)!
|
||||
.div(
|
||||
I80F48.fromNumber(
|
||||
Math.pow(10, group.banksMapByName.get(src)[0].mintDecimals),
|
||||
Math.pow(10, group.banksMapByName.get(src)![0].mintDecimals),
|
||||
),
|
||||
)
|
||||
.toNumber(),
|
||||
|
@ -153,8 +152,8 @@ async function main() {
|
|||
const group = await client.getGroupForCreator(admin.publicKey, 2);
|
||||
|
||||
for (const keypair of [
|
||||
process.env.MB_PAYER_KEYPAIR,
|
||||
process.env.MB_USER2_KEYPAIR,
|
||||
process.env.MB_PAYER_KEYPAIR!,
|
||||
process.env.MB_USER2_KEYPAIR!,
|
||||
]) {
|
||||
console.log();
|
||||
const user = Keypair.fromSecretKey(
|
||||
|
|
Loading…
Reference in New Issue