From 41e42da620351c38853bd17ac3fa8ee458249f74 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Sat, 13 Aug 2022 19:36:09 +0200 Subject: [PATCH] debug banks helper script Signed-off-by: microwavedcola1 --- ts/client/src/accounts/bank.ts | 2 + ts/client/src/client.ts | 16 ++- ts/client/src/debug-scripts/mb-debug-banks.ts | 116 ++++++++++++++++++ ts/client/src/scripts/example1-user.ts | 9 +- .../src/scripts/mb-example1-close-account.ts | 10 +- 5 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 ts/client/src/debug-scripts/mb-debug-banks.ts diff --git a/ts/client/src/accounts/bank.ts b/ts/client/src/accounts/bank.ts index 0637e8992..db197f2be 100644 --- a/ts/client/src/accounts/bank.ts +++ b/ts/client/src/accounts/bank.ts @@ -26,6 +26,7 @@ export class Bank { public util0: I80F48; public util1: I80F48; public price: I80F48; + public collectedFeesNative: I80F48; public loanFeeRate: I80F48; public loanOriginationFeeRate: I80F48; public initAssetWeight: I80F48; @@ -166,6 +167,7 @@ export class Bank { this.rate0 = I80F48.from(rate0); this.util1 = I80F48.from(util1); this.rate1 = I80F48.from(rate1); + this.collectedFeesNative = I80F48.from(collectedFeesNative); this.loanFeeRate = I80F48.from(loanFeeRate); this.loanOriginationFeeRate = I80F48.from(loanOriginationFeeRate); this.maintAssetWeight = I80F48.from(maintAssetWeight); diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index ba3288c27..d71a673ec 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -15,7 +15,6 @@ import { AccountMeta, Cluster, Keypair, - LAMPORTS_PER_SOL, MemcmpFilter, PublicKey, Signer, @@ -596,6 +595,21 @@ export class MangoClient { }); } + public async getAllMangoAccounts(group: Group): Promise { + return ( + await this.program.account.mangoAccount.all([ + { + memcmp: { + bytes: group.publicKey.toBase58(), + offset: 8, + }, + }, + ]) + ).map((pa) => { + return MangoAccount.from(pa.publicKey, pa.account); + }); + } + public async closeMangoAccount( group: Group, mangoAccount: MangoAccount, diff --git a/ts/client/src/debug-scripts/mb-debug-banks.ts b/ts/client/src/debug-scripts/mb-debug-banks.ts new file mode 100644 index 000000000..234577921 --- /dev/null +++ b/ts/client/src/debug-scripts/mb-debug-banks.ts @@ -0,0 +1,116 @@ +import { AnchorProvider, Wallet } from '@project-serum/anchor'; +import { coder } from '@project-serum/anchor/dist/cjs/spl/token'; +import { Connection, Keypair } from '@solana/web3.js'; +import fs from 'fs'; +import { ZERO_I80F48 } from '../accounts/I80F48'; +import { MangoClient } from '../client'; +import { MANGO_V4_ID } from '../constants'; + +async function main() { + const options = AnchorProvider.defaultOptions(); + const connection = new Connection(process.env.MB_CLUSTER_URL!, options); + + const admin = Keypair.fromSecretKey( + Buffer.from( + JSON.parse(fs.readFileSync(process.env.MB_PAYER_KEYPAIR!, 'utf-8')), + ), + ); + + const adminWallet = new Wallet(admin); + const adminProvider = new AnchorProvider(connection, adminWallet, options); + const client = MangoClient.connect( + adminProvider, + 'mainnet-beta', + MANGO_V4_ID['mainnet-beta'], + ); + + const group = await client.getGroupForCreator(admin.publicKey, 0); + console.log(`Group ${group.publicKey.toBase58()}`); + + const banks = await client.getBanksForGroup(group); + const banksMapUsingTokenIndex = new Map( + banks.map((bank) => { + (bank as any).indexedDepositsByMangoAccounts = ZERO_I80F48; + (bank as any).indexedBorrowsByMangoAccounts = ZERO_I80F48; + return [bank.tokenIndex, bank]; + }), + ); + + const mangoAccounts = await client.getAllMangoAccounts(group); + mangoAccounts.forEach((mangoAccount) => + console.log( + `MangoAccount pk - ${mangoAccount.publicKey}, owner - ${mangoAccount.owner}`, + ), + ); + mangoAccounts.map((mangoAccount) => + mangoAccount.tokensActive().forEach((token) => { + const bank = banksMapUsingTokenIndex.get(token.tokenIndex); + if (token.indexedPosition.isPos()) { + (bank as any).indexedDepositsByMangoAccounts = ( + bank as any + ).indexedDepositsByMangoAccounts.add( + token.indexedPosition.mul( + banksMapUsingTokenIndex.get(token.tokenIndex).depositIndex, + ), + ); + } + if (token.indexedPosition.isNeg()) { + (bank as any).indexedBorrowsByMangoAccounts = ( + bank as any + ).indexedBorrowsByMangoAccounts.add( + token.indexedPosition + .abs() + .mul(banksMapUsingTokenIndex.get(token.tokenIndex).borrowIndex), + ); + } + }), + ); + + for (const bank of await Array.from(banksMapUsingTokenIndex.values()).sort( + (a, b) => a.tokenIndex - b.tokenIndex, + )) { + let res = `${bank.name}`; + res = + res + + `\n ${'collectedFeesNative'.padEnd(40)} ${bank.collectedFeesNative}` + + `\n ${'deposits'.padEnd(40)} ${bank.indexedDeposits.mul( + bank.depositIndex, + )}` + + `\n ${'deposits (sum over all mango accounts)'.padEnd(40)} ${ + (bank as any).indexedDepositsByMangoAccounts + }` + + `\n ${'cachedIndexedTotalDeposits'.padEnd(40)} ${( + bank as any + ).cachedIndexedTotalDeposits.mul(bank.depositIndex)}` + + `\n ${'indexedBorrows'.padEnd(40)} ${bank.indexedBorrows.mul( + bank.borrowIndex, + )}` + + `\n ${'borrows (sum over all mango accounts)'.padEnd(40)} ${ + (bank as any).indexedBorrowsByMangoAccounts + }` + + `\n ${'cachedIndexedTotalBorrows'.padEnd(40)} ${( + bank as any + ).cachedIndexedTotalBorrows.mul(bank.borrowIndex)}` + + `\n ${'avgUtilization'.padEnd(40)} ${bank.avgUtilization}` + + `\n ${'depositRate'.padEnd(40)} ${bank.getDepositRate()}` + + `\n ${'borrowRate'.padEnd(40)} ${bank.getBorrowRate()}` + + `\n ${'vault'.padEnd(40)} ${coder() + .accounts.decode( + 'token', + await ( + await client.program.provider.connection.getAccountInfo(bank.vault) + ).data, + ) + .amount.toNumber()}`; + + console.log(`${res}`); + } + + process.exit(); +} + +try { + main(); +} catch (error) { + console.log(error); +} diff --git a/ts/client/src/scripts/example1-user.ts b/ts/client/src/scripts/example1-user.ts index 93e39b12d..a2e750689 100644 --- a/ts/client/src/scripts/example1-user.ts +++ b/ts/client/src/scripts/example1-user.ts @@ -10,6 +10,7 @@ import { } from '../accounts/serum3'; import { MangoClient } from '../client'; import { MANGO_V4_ID } from '../constants'; +import { toUiDecimalsForQuote } from '../utils'; // // An example for users based on high level api i.e. the client @@ -240,11 +241,15 @@ async function main() { ); console.log( '...mangoAccount.getAssetsVal() ' + - toUiDecimalsForQuote(mangoAccount.getAssetsVal().toNumber()), + toUiDecimalsForQuote( + mangoAccount.getAssetsVal(HealthType.init).toNumber(), + ), ); console.log( '...mangoAccount.getLiabsVal() ' + - toUiDecimalsForQuote(mangoAccount.getLiabsVal().toNumber()), + toUiDecimalsForQuote( + mangoAccount.getLiabsVal(HealthType.init).toNumber(), + ), ); console.log( '...mangoAccount.getMaxWithdrawWithBorrowForToken(group, "SOL") ' + diff --git a/ts/client/src/scripts/mb-example1-close-account.ts b/ts/client/src/scripts/mb-example1-close-account.ts index ed9f54c4d..f1f165916 100644 --- a/ts/client/src/scripts/mb-example1-close-account.ts +++ b/ts/client/src/scripts/mb-example1-close-account.ts @@ -3,6 +3,7 @@ import { Connection, Keypair } from '@solana/web3.js'; import fs from 'fs'; import { Serum3Side } from '../accounts/serum3'; import { MangoClient } from '../client'; +import { MANGO_V4_ID } from '../constants'; // // (untested?) script which closes a mango account cleanly, first closes all positions, withdraws all tokens and then closes it @@ -14,14 +15,15 @@ async function main() { // user const user = Keypair.fromSecretKey( Buffer.from( - JSON.parse(fs.readFileSync(process.env.MB_PAYER_KEYPAIR!, 'utf-8')), + JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')), ), ); const userWallet = new Wallet(user); const userProvider = new AnchorProvider(connection, userWallet, options); - const client = await MangoClient.connectForGroupName( + const client = await MangoClient.connect( userProvider, - 'mainnet-beta.microwavedcola' /* Use ids json instead of getProgramAccounts */, + 'mainnet-beta', + MANGO_V4_ID['mainnet-beta'], ); console.log(`User ${userWallet.publicKey.toBase58()}`); @@ -34,7 +36,7 @@ async function main() { console.log(`Admin ${admin.publicKey.toBase58()}`); // fetch group - const group = await client.getGroupForCreator(admin.publicKey); + const group = await client.getGroupForCreator(admin.publicKey, 0); console.log(`Found group ${group.publicKey.toBase58()}`); // account