Merge branch 'mc/update-risk' into deploy

This commit is contained in:
microwavedcola1 2023-11-14 08:58:53 +01:00
commit 888a270cf2
1 changed files with 98 additions and 90 deletions

View File

@ -1,9 +1,6 @@
import {
LISTING_PRESETS,
LISTING_PRESETS_PYTH,
MidPriceImpact,
getMidPriceImpacts,
getProposedTier,
} from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools';
import { AnchorProvider, Wallet } from '@coral-xyz/anchor';
import { BN } from '@project-serum/anchor';
@ -21,12 +18,14 @@ import {
TransactionInstruction,
} from '@solana/web3.js';
import fs from 'fs';
import { OracleProvider } from '../src/accounts/oracle';
import { Bank } from '../src/accounts/bank';
import { Group } from '../src/accounts/group';
import { Builder } from '../src/builder';
import { MangoClient } from '../src/client';
import { NullTokenEditParams } from '../src/clientIxParamBuilder';
import { MANGO_V4_MAIN_GROUP as MANGO_V4_PRIMARY_GROUP } from '../src/constants';
import { toUiDecimalsForQuote } from '../src/utils';
import { getEquityForMangoAccounts } from '../src/risk';
import { buildFetch } from '../src/utils';
import {
MANGO_DAO_WALLET_GOVERNANCE,
MANGO_GOVERNANCE_PROGRAM,
@ -77,6 +76,52 @@ async function setupVsr(
return vsrClient;
}
async function getTotalLiqorEquity(
client: MangoClient,
group: Group,
mangoAccounts: import('/Users/mc/repos/mango-v4/ts/client/src/accounts/mangoAccount').MangoAccount[],
): Promise<number> {
const liqors = (
await (
await (
await buildFetch()
)(
`https://api.mngo.cloud/data/v4/stats/liqors-over_period?over_period=1MONTH`,
{
mode: 'cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
},
)
).json()
).map((data) => new PublicKey(data['liqor']));
const ttlLiqorEquity = (
await getEquityForMangoAccounts(client, group, liqors, mangoAccounts)
).reduce((partialSum, ae) => partialSum + ae.Equity.val, 0);
return ttlLiqorEquity;
}
function getPriceImpactForBank(
midPriceImpacts: MidPriceImpact[],
bank: Bank,
): MidPriceImpact {
const tokenToPriceImpact = midPriceImpacts
.filter((x) => x.avg_price_impact_percent < 1)
.reduce((acc: { [key: string]: MidPriceImpact }, val: MidPriceImpact) => {
if (
!acc[val.symbol] ||
val.target_amount > acc[val.symbol].target_amount
) {
acc[val.symbol] = val;
}
return acc;
}, {});
const priceImpact = tokenToPriceImpact[getApiTokenName(bank.name)];
return priceImpact;
}
async function updateTokenParams(): Promise<void> {
const [client, wallet] = await Promise.all([buildClient(), setupWallet()]);
const vsrClient = await setupVsr(client.connection, wallet);
@ -84,87 +129,65 @@ async function updateTokenParams(): Promise<void> {
const group = await client.getGroup(MANGO_V4_PRIMARY_GROUP);
const instructions: TransactionInstruction[] = [];
const mangoAccounts = await client.getAllMangoAccounts(group, true);
const ttlLiqorEquityUi = await getTotalLiqorEquity(
client,
group,
mangoAccounts,
);
const midPriceImpacts = getMidPriceImpacts(group.pis);
Array.from(group.banksMapByTokenIndex.values())
.map((banks) => banks[0])
.filter(
(bank) =>
bank.mint.toBase58() == 'So11111111111111111111111111111111111111112' ||
bank.name.toLocaleLowerCase().indexOf('usdc') > -1 ||
bank.name.toLocaleLowerCase().indexOf('stsol') > -1,
// // low low liquidity
// bank.name.includes('DUAL') ||
// bank.name.includes('MNGO') ||
// // low liquidity
// bank.name.includes('ALL') ||
// bank.name.includes('CROWN') ||
// bank.name.includes('GUAC') ||
// bank.name.includes('HNT') ||
// bank.name.includes('KIN') ||
// bank.name.includes('OPOS') ||
// bank.name.includes('RLB') ||
// bank.name.includes('USDH') ||
// better liquidity
bank.name.includes('BONK') ||
bank.name.includes('bSOL') ||
bank.name.includes('CHAI') ||
bank.name.includes('DAI') ||
bank.name.includes('ETH (Portal)') ||
bank.name.includes('JitoSOL') ||
bank.name.includes('LDO') ||
bank.name.includes('MSOL') ||
bank.name.includes('ORCA') ||
bank.name.includes('RAY') ||
bank.name.includes('SOL') ||
bank.name.includes('stSOL') ||
bank.name.includes('TBTC') ||
bank.name.includes('USDC') ||
bank.name.includes('wBTC (Portal)') ||
bank.name.includes('USDT'),
)
.forEach(async (bank) => {
// Limit borrows to 1/3rd of deposit, rounded to 1000, only update if more than 10% different
const depositsInUsd = bank.nativeDeposits().mul(bank.price);
let newNetBorrowLimitPerWindowQuote: number | null =
depositsInUsd.toNumber() / 3;
newNetBorrowLimitPerWindowQuote =
Math.round(newNetBorrowLimitPerWindowQuote / 1_000_000_000) *
1_000_000_000;
newNetBorrowLimitPerWindowQuote =
Math.abs(
(newNetBorrowLimitPerWindowQuote -
bank.netBorrowLimitPerWindowQuote.toNumber()) /
bank.netBorrowLimitPerWindowQuote.toNumber(),
) > 0.1
? newNetBorrowLimitPerWindowQuote
: null;
const priceImpact = getPriceImpactForBank(midPriceImpacts, bank);
// Kick in weight scaling as late as possible until liquidation fee remains reasonable
// Only update if more than 10% different
let newWeightScaleQuote: number | null = null;
if (
bank.tokenIndex != 0 && // USDC
bank.mint.toBase58() != 'So11111111111111111111111111111111111111112' // SOL
) {
const PRESETS =
bank?.oracleProvider === OracleProvider.Pyth
? LISTING_PRESETS_PYTH
: LISTING_PRESETS;
const scaleStartQuoteUi = Math.min(
50 * ttlLiqorEquityUi,
4 * priceImpact.target_amount,
);
const tokenToPriceImpact = midPriceImpacts
.filter((x) => x.avg_price_impact_percent < 1)
.reduce(
(acc: { [key: string]: MidPriceImpact }, val: MidPriceImpact) => {
if (
!acc[val.symbol] ||
val.target_amount > acc[val.symbol].target_amount
) {
acc[val.symbol] = val;
}
return acc;
},
{},
);
const priceImpact = tokenToPriceImpact[getApiTokenName(bank.name)];
const suggestedTier = getProposedTier(
PRESETS,
priceImpact?.target_amount,
bank.oracleProvider === OracleProvider.Pyth,
);
newWeightScaleQuote =
PRESETS[suggestedTier].borrowWeightScaleStartQuote;
const newNetDepositsUi = Math.max(
10_000,
Math.min(bank.uiDeposits(), 300_000) / 3 +
Math.max(0, bank.uiDeposits() - 300_000) / 5,
);
newWeightScaleQuote =
bank.depositWeightScaleStartQuote !== newWeightScaleQuote ||
bank.borrowWeightScaleStartQuote !== newWeightScaleQuote
? newWeightScaleQuote
: null;
}
if (
newNetBorrowLimitPerWindowQuote == null &&
newWeightScaleQuote == null
) {
return;
}
const params = Builder(NullTokenEditParams)
.netBorrowLimitPerWindowQuote(newNetBorrowLimitPerWindowQuote)
.borrowWeightScaleStartQuote(newWeightScaleQuote)
.depositWeightScaleStartQuote(newWeightScaleQuote)
.build();
const params = Builder(NullTokenEditParams).build();
const ix = await client.program.methods
.tokenEdit(
@ -224,21 +247,6 @@ async function updateTokenParams(): Promise<void> {
throw simulated.value.logs;
}
console.log(`Bank ${bank.name}`);
console.log(
`- netBorrowLimitPerWindowQuote UI old ${toUiDecimalsForQuote(
bank.netBorrowLimitPerWindowQuote.toNumber(),
).toLocaleString()} new ${toUiDecimalsForQuote(
newNetBorrowLimitPerWindowQuote!,
).toLocaleString()}`,
);
console.log(
`- WeightScaleQuote UI old ${toUiDecimalsForQuote(
bank.depositWeightScaleStartQuote,
).toLocaleString()} new ${toUiDecimalsForQuote(
newWeightScaleQuote!,
).toLocaleString()}`,
);
instructions.push(ix);
});