From 82159d928481952e1d94704b407931b18ec3bff4 Mon Sep 17 00:00:00 2001 From: microwavedcola1 Date: Mon, 6 May 2024 08:16:20 +0200 Subject: [PATCH] ts: script to withdraw fees Signed-off-by: microwavedcola1 --- ts/client/scripts/withdraw-fees-to-admin.ts | 152 ++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 ts/client/scripts/withdraw-fees-to-admin.ts diff --git a/ts/client/scripts/withdraw-fees-to-admin.ts b/ts/client/scripts/withdraw-fees-to-admin.ts new file mode 100644 index 000000000..c0709d7c3 --- /dev/null +++ b/ts/client/scripts/withdraw-fees-to-admin.ts @@ -0,0 +1,152 @@ +import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; +import { + getAllProposals, + getTokenOwnerRecord, + getTokenOwnerRecordAddress, +} from '@solana/spl-governance'; + +import { getAssociatedTokenAddress } from '@solana/spl-token'; +import { + Connection, + Keypair, + PublicKey, + Transaction, + TransactionInstruction, +} from '@solana/web3.js'; +import fs from 'fs'; +import { MangoClient } from '../src/client'; +import { MANGO_V4_MAIN_GROUP as MANGO_V4_PRIMARY_GROUP } from '../src/constants'; +import { + MANGO_DAO_WALLET_GOVERNANCE, + MANGO_GOVERNANCE_PROGRAM, + MANGO_MINT, + MANGO_REALM_PK, +} from './governanceInstructions/constants'; +import { createProposal } from './governanceInstructions/createProposal'; +import { + DEFAULT_VSR_ID, + VsrClient, +} from './governanceInstructions/voteStakeRegistryClient'; + +const { + MB_CLUSTER_URL, + PROPOSAL_TITLE, + PROPOSAL_LINK, + VSR_DELEGATE_KEYPAIR, + VSR_DELEGATE_FROM_PK, + DRY_RUN, +} = process.env; + +async function buildClient(): Promise { + return await MangoClient.connectDefault(MB_CLUSTER_URL!); +} + +async function setupWallet(): Promise { + const clientKeypair = Keypair.fromSecretKey( + Buffer.from(JSON.parse(fs.readFileSync(VSR_DELEGATE_KEYPAIR!, 'utf-8'))), + ); + const clientWallet = new Wallet(clientKeypair); + return clientWallet; +} + +async function setupVsr( + connection: Connection, + clientWallet: Wallet, +): Promise { + const options = AnchorProvider.defaultOptions(); + const provider = new AnchorProvider(connection, clientWallet, options); + const vsrClient = await VsrClient.connect(provider, DEFAULT_VSR_ID); + return vsrClient; +} + +async function updateSpotMarkets(): Promise { + const [client, wallet] = await Promise.all([buildClient(), setupWallet()]); + const vsrClient = await setupVsr(client.connection, wallet); + + const group = await client.getGroup(MANGO_V4_PRIMARY_GROUP); + + const instructions: TransactionInstruction[] = []; + + Array.from(group.banksMapByTokenIndex.values()) + .map((banks) => banks[0]) + .sort((a, b) => a.name.localeCompare(b.name)) + .forEach(async (bank) => { + if (bank.name == 'SOL') { + return; + } + + const tokenAccount = await getAssociatedTokenAddress( + bank.mint, + new PublicKey('8SSLjXBEVk9nesbhi9UMCA32uijbVBUqWoKPPQPTekzt'), + ); + + const ix = await client.program.methods + .adminTokenWithdrawFees() + .accounts({ + group: group.publicKey, + admin: group.admin, + bank: bank.publicKey, + vault: bank.vault, + tokenAccount, + }) + .instruction(); + + const tx = new Transaction({ feePayer: wallet.publicKey }).add(ix); + const simulated = await client.connection.simulateTransaction(tx); + + if (simulated.value.err) { + console.log(`${bank.name} Sim error` + simulated.value.logs); + throw simulated.value.logs; + } + + instructions.push(ix); + }); + + const tokenOwnerRecordPk = await getTokenOwnerRecordAddress( + MANGO_GOVERNANCE_PROGRAM, + MANGO_REALM_PK, + MANGO_MINT, + new PublicKey(VSR_DELEGATE_FROM_PK!), + ); + + const [tokenOwnerRecord, proposals] = await Promise.all([ + getTokenOwnerRecord(client.connection, tokenOwnerRecordPk), + getAllProposals( + client.connection, + MANGO_GOVERNANCE_PROGRAM, + MANGO_REALM_PK, + ), + ]); + + const walletSigner = wallet as never; + + if (!DRY_RUN) { + const proposalAddress = await createProposal( + client.connection, + walletSigner, + MANGO_DAO_WALLET_GOVERNANCE, + tokenOwnerRecord, + PROPOSAL_TITLE ? PROPOSAL_TITLE : 'Withdraw token fees in mango-v4', + PROPOSAL_LINK ?? '', + Object.values(proposals).length, + instructions, + vsrClient!, + false, + ); + console.log(proposalAddress.toBase58()); + } +} + +async function main(): Promise { + try { + await updateSpotMarkets(); + } catch (error) { + console.log(error); + } +} + +try { + main(); +} catch (error) { + console.log(error); +}