Skip to content

Instantly share code, notes, and snippets.

@staccDOTsol
Last active January 6, 2025 11:56
Show Gist options
  • Select an option

  • Save staccDOTsol/8b0ee614a87a0819539240692fb3cdc7 to your computer and use it in GitHub Desktop.

Select an option

Save staccDOTsol/8b0ee614a87a0819539240692fb3cdc7 to your computer and use it in GitHub Desktop.
pissed off
import {
AddressLookupTableAccount,
Connection,
Keypair,
PublicKey,
TransactionInstruction,
} from "@solana/web3.js";
import { getMarginfiClient } from "./utils";
import { createJupiterApiClient } from "@jup-ag/api";
import { nativeToUi } from "@mrgnlabs/mrgn-common";
import { Wallet } from "@coral-xyz/anchor";
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
import { BN } from "bn.js";
import { SystemProgram } from "@solana/web3.js";
import { ComputeBudgetProgram } from "@solana/web3.js";
const wallet = new Wallet(Keypair.fromSecretKey(new Uint8Array(bs58.decode(process.env.PRIVATE_KEY!))));
async function main() {
const client = await getMarginfiClient({ wallet: wallet });
console.log("signer:", client.wallet.publicKey.toBase58());
const jupiterQuoteApi = createJupiterApiClient();
const marginfiAccounts = await client.getMarginfiAccountsForAuthority();
if (marginfiAccounts.length === 0) throw Error("No marginfi account found");
const marginfiAccount = marginfiAccounts[0];
// Assumption: account has enough USDC to repay the whole USDT borrow, accounting for slippage
const usdcBank = client.getBankByTokenSymbol("USDC");
if (!usdcBank) throw Error("USDC bank not found");
const usdtBank = client.getBankByTokenSymbol("USDT");
if (!usdtBank) throw Error("USDT bank not found");
while (true) {
const usdtAmountToRepay = new BN(Math.floor((Math.random() * 900000+50000) * 10 ** 6));
const quoteParams = {
amount: usdtAmountToRepay.toNumber(),
inputMint: usdcBank.mint.toBase58(),
outputMint: usdtBank.mint.toBase58(),
slippageBps: 5000,
includeDexes: ["Raydium", "Raydium CLMM"] as any,
maxAccounts: 22,
};
const swapQuote = await jupiterQuoteApi.quoteGet(quoteParams);
const withdrawAmount = nativeToUi(swapQuote.outAmount, usdcBank.mintDecimals);
const borrowIx = await marginfiAccount.makeBorrowIx(nativeToUi(usdtAmountToRepay, usdtBank.mintDecimals), usdcBank.address);
const { swapInstruction, addressLookupTableAddresses } = await jupiterQuoteApi.swapInstructionsPost({
swapRequest: {
quoteResponse: swapQuote,
userPublicKey: client.wallet.publicKey.toBase58(),
},
});
const swapIx = deserializeInstruction(swapInstruction);
const quoteParams2 = {
amount: withdrawAmount * 10 ** usdcBank.mintDecimals,
inputMint: usdtBank.mint.toBase58(),
outputMint: usdcBank.mint.toBase58(),
slippageBps: 5000,
excludeDexes: ["Saber", "Saber (Decimals)", "Raydium", "Raydium CLMM"] as any,
maxAccounts: 22,
};
const swapQuote2 = await jupiterQuoteApi.quoteGet(quoteParams2);
const { swapInstruction: swapInstruction2, addressLookupTableAddresses: addressLookupTableAddresses2 } = await jupiterQuoteApi.swapInstructionsPost({
swapRequest: {
quoteResponse: swapQuote2,
userPublicKey: client.wallet.publicKey.toBase58(),
},
});
const swapIx2 = deserializeInstruction(swapInstruction2);
const depositIx = await marginfiAccount.makeRepayIx(new BN(swapQuote2.outAmount).div(new BN(10).pow(new BN(usdcBank.mintDecimals))).toNumber(), usdcBank.address, true);
const addressLookupTableAccounts: AddressLookupTableAccount[] = [];
addressLookupTableAccounts.push(
...(await getAdressLookupTableAccounts(client.provider.connection, addressLookupTableAddresses.concat(addressLookupTableAddresses2)))
);
const flashLoanTx = await marginfiAccount.buildFlashLoanTx({
ixs: [...borrowIx.instructions, swapIx, swapIx2, ...depositIx.instructions, SystemProgram.transfer({
fromPubkey: client.wallet.publicKey,
toPubkey: new PublicKey("ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49"),
lamports: 0.01 * 10 ** 9,
})],
addressLookupTableAccounts,
});
console.log("flashLoanTx");
client.processTransaction(flashLoanTx);
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
main().catch((e) => console.log(e));
// ------------------------------------------------------------
// Helpers
// ------------------------------------------------------------
const deserializeInstruction = (instruction: any) => {
return new TransactionInstruction({
programId: new PublicKey(instruction.programId),
keys: instruction.accounts.map((key: any) => ({
pubkey: new PublicKey(key.pubkey),
isSigner: key.isSigner,
isWritable: key.isWritable,
})),
data: Buffer.from(instruction.data, "base64"),
});
};
const getAdressLookupTableAccounts = async (
connection: Connection,
keys: string[]
): Promise<AddressLookupTableAccount[]> => {
const addressLookupTableAccountInfos = await connection.getMultipleAccountsInfo(
keys.map((key) => new PublicKey(key))
);
return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => {
const addressLookupTableAddress = keys[index];
if (accountInfo) {
const addressLookupTableAccount = new AddressLookupTableAccount({
key: new PublicKey(addressLookupTableAddress),
state: AddressLookupTableAccount.deserialize(accountInfo.data),
});
acc.push(addressLookupTableAccount);
}
return acc;
}, new Array<AddressLookupTableAccount>());
};
@capitalsteez47
Copy link

can you please make a tutorial on how to use this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment