The marginfi TypeScript SDK

The marginfi-client-v2 and mrgn-common NPM packages are the official TypeScript SDKs for interacting with the marginfi protocol. You can use these SDKs in your Node.js frontend and backend to perform tasks like creating banks, making deposits to existing banks, and more.


Installation

To get started, simply initialize your Node.js project and install the packages using your preferred package manager.

Using NPM

npm install @mrgnlabs/marginfi-client-v2 @mrgnlabs/mrgn-common

Using Yarn

yarn add @mrgnlabs/marginfi-client-v2 @mrgnlabs/mrgn-common

Getting Started

Step 1: Initialize the marginfi client

In order to interact with the marginfi SDK, we must first configure the marginfi client object using the MarginfiClient instance:

Example

import { Connection } from "@solana/web3.js";
import { MarginfiClient, getConfig } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet } from "@mrgnlabs/mrgn-common";

const connection = new Connection(CLUSTER_CONNECTION, "confirmed");
const wallet = NodeWallet.local();
const config = getConfig("dev");
const client = await MarginfiClient.fetch(config, wallet, connection);
  • connection establishes a connection to a Solana cluster
  • wallet creates an Anchor-compliant Node.js wallet from your local Solana keypair
  • config returns a configuration object specific to the specified environment (e.g. “production”, “development”)
  • client is a high-level SDK for interacting with the Marginfi protocol

Step 2: Create an Account

Accounts on marginfi are the entry point for interacting with the protocol, allowing users to deposit assets, take out loans, and manage their positions. Using the marginfi SDK, you can create an account with one line of code. With this ability, you can enable seamless user onboarding by creating dedicated accounts for each new user.

Example

const marginfiAccount = await client.createMarginfiAccount();

Step 3: Fetch a Bank

In order to interact with asset pools, or “banks,” on marginfi, you must first fetch the specific bank you want to borrow/lend from:

Example

const bankLabel = "SOL";
const bank = client.getBankByTokenSymbol(bankLabel);
if (!bank) throw Error(`${bankLabel} bank not found`);
  • bankLabel holds the symbol for the bank that you will fetch. Note that you can also query banks by the token mint address (using getBankByMint) or by the bank address (using getBankByPk).
  • bank1 fetches the specified bank using getBankByTokenSymbol, using the bank’s token symbol “SOL” as the query parameter.

Step 4: Make a Deposit

Once you’ve fetched the bank you want to interact with, you can make a deposit:

Example

await marginfiAccount.deposit(1, bank.address);

The deposit method on the marginfi account object allows you to make a deposit into the specified bank account using the bank's address as a parameter (second parameter). Note that the first parameter let’s you specify how much (in the denominated asset) you want to deposit into the bank.

Step 5: Borrow From a Bank

After lending liquidity on marginfi, you’re account is eligible to act as a Borrower. You can borrow liquidity from marginfi banks using one line of code:

Example

await marginfiAccount.borrow(1, bank.address);

The structure of the borrow method is identical to the deposit method. You specify the amount you want to borrow using the first parameter, and you specify which bank you want to interact with using the second parameter.

if you followed along with these steps, you just want through the full lending-and-borrowing lifecycle on marginfi. To execute your node, simply tun ts-node <file-path> in your terminal. You’re code should look like this:

Example

import { Connection } from "@solana/web3.js";
import { MarginfiClient, getConfig } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet } from "@mrgnlabs/mrgn-common";

const CLUSTER_CONNECTION = <your-rpc-url>;

const main = async () => {
	const connection = new Connection(CLUSTER_CONNECTION, "confirmed");
	const wallet = NodeWallet.local();
	const config = getConfig("dev");
	const client = await MarginfiClient.fetch(config, wallet, connection); // initialize client
	
	const marginfiAccount = await client.createMarginfiAccount(); // create an account
	
	const bankLabel = "SOL";
	const bank = client.getBankByTokenSymbol(bankLabel);
	if (!bank) throw Error(`${bankLabel} bank not found`); // fetch a bank
	
	await marginfiAccount.deposit(1, bank.address); // make a deposit
	await marginfiAccount.borrow(1, bank.address); // borrow from a bank
};

main();

You’re now a mrgn mama! For more details on the marginfi SDK and use cases, refer to the sections below.


Classes

MarginfiClient

The MarginfiClient instance is the entry point to interact with the marginfi protocol. You can setup your MarginfiClient like so:

Example

const connection = new Connection(CLUSTER_CONNECTION, "confirmed");
const wallet = NodeWallet.local()
const config = getConfig("dev");
const client = await MarginfiClient.fetch(config, wallet, connection);

Bank

The Bank class represents a bank account on the Marginfi protocol. It encapsulates all the properties and methods related to a specific bank, such as token details, vault addresses, share values, configuration settings, and computations for asset/liability quantities, interest rates, and remaining capacities. It serves as a central point for interacting with and managing a bank within the Marginfi ecosystem.

Properties

  • Name
    address
    Type
    PublicKey
    Description

    The public key or address of the bank.

  • Name
    tokenSymbol
    Type
    string | undefined
    Description

    The symbol or ticker of the token associated with the bank (if available).

  • Name
    group
    Type
    PublicKey
    Description

    The public key of the group that the bank belongs to.

  • Name
    mint
    Type
    PublicKey
    Description

    The public key of the mint associated with the bank's token.

  • Name
    mintDecimals
    Type
    number
    Description

    The number of decimals for the bank's token.

  • Name
    assetShareValue
    Type
    BigNumber
    Description

    The value of one asset share in the bank.

  • Name
    liabilityShareValue
    Type
    BigNumber
    Description

    The value of one liability share in the bank.

  • Name
    liquidityVault
    Type
    PublicKey
    Description

    The public key of the liquidity vault associated with the bank.

  • Name
    liquidityVaultBump
    Type
    number
    Description

    The bump seed used to derive the liquidity vault authority.

  • Name
    liquidityVaultAuthorityBump
    Type
    number
    Description

    The bump seed used to derive the liquidity vault authority.

  • Name
    insuranceVault
    Type
    PublicKey
    Description

    The public key of the insurance vault associated with the bank.

  • Name
    insuranceVaultBump
    Type
    number
    Description

    The bump seed used to derive the insurance vault authority.

  • Name
    insuranceVaultAuthorityBump
    Type
    number
    Description

    The bump seed used to derive the insurance vault authority.

  • Name
    collectedInsuranceFeesOutstanding
    Type
    BigNumber
    Description

    The amount of outstanding collected insurance fees.

  • Name
    feeVault
    Type
    PublicKey
    Description

    The public key of the fee vault associated with the bank.

  • Name
    feeVaultBump
    Type
    number
    Description

    The bump seed used to derive the fee vault authority.

  • Name
    feeVaultAuthorityBump
    Type
    number
    Description

    The bump seed used to derive the fee vault authority.

  • Name
    collectedGroupFeesOutstanding
    Type
    BigNumber
    Description

    The amount of outstanding collected group fees.

  • Name
    lastUpdate
    Type
    number
    Description

    The timestamp of the last update to the bank.

  • Name
    config
    Type
    BankConfig
    Description

    The configuration settings for the bank.

  • Name
    totalAssetShares
    Type
    BigNumber
    Description

    The total number of asset shares in the bank.

  • Name
    totalLiabilityShares
    Type
    BigNumber
    Description

    The total number of liability shares in the bank.

  • Name
    emissionsActiveBorrowing
    Type
    boolean
    Description

    Indicates whether emissions are active for borrowing.

  • Name
    emissionsActiveLending
    Type
    boolean
    Description

    Indicates whether emissions are active for lending.

  • Name
    emissionsRate
    Type
    number
    Description

    The rate of emissions for the bank.

  • Name
    emissionsMint
    Type
    PublicKey
    Description

    The public key of the mint associated with the bank's emissions.

  • Name
    emissionsRemaining
    Type
    BigNumber
    Description

    The amount of emissions remaining for the bank.

Methods

Method NameParametersResult Type(s)Description
decodeBankRawencoded: BufferBankRawA static method that decodes a raw bank account data buffer.
fromBufferaddress: PublicKey, buffer: BufferBankA static method that creates a Bank instance from a public key and account data buffer.
fromAccountParsedaddress: PublicKey, accountParsed: BankRaw, bankMetadata?: BankMetadataBankA static method that creates a Bank instance from a public key, parsed account data, and optional bank metadata.
getTotalAssetQuantityNoneBigNumberReturns the total quantity of assets in the bank.
getTotalLiabilityQuantityNoneBigNumberReturns the total quantity of liabilities in the bank.
getAssetQuantityassetShares: BigNumberBigNumberComputes the quantity of assets for a given number of asset shares.
getLiabilityQuantityliabilityShares: BigNumberBigNumberComputes the quantity of liabilities for a given number of liability shares.
getAssetSharesassetQuantity: BigNumberBigNumberComputes the number of asset shares for a given asset quantity.
getLiabilitySharesliabilityQuantity: BigNumberBigNumberComputes the number of liability shares for a given liability quantity.
computeAssetUsdValueoraclePrice: OraclePrice, assetShares: BigNumber, marginRequirementType: MarginRequirementType, priceBias: PriceBiasBigNumberComputes the USD value of a given number of asset shares.
computeLiabilityUsdValueoraclePrice: OraclePrice, liabilityShares: BigNumber, marginRequirementType: MarginRequirementType, priceBias: PriceBiasBigNumberComputes the USD value of a given number of liability shares.
computeUsdValueoraclePrice: OraclePrice, quantity: BigNumber, priceBias: PriceBias, weightedPrice: boolean, weight?: BigNumber, scaleToBase?: booleanBigNumberComputes the USD value of a given quantity with various configurations.
computeQuantityFromUsdValueoraclePrice: OraclePrice, usdValue: BigNumber, priceBias: PriceBias, weightedPrice: booleanBigNumberComputes the quantity from a given USD value with various configurations.
getPriceoraclePrice: OraclePrice, priceBias: PriceBias, weightedPrice: booleanBigNumberRetrieves the price of the bank's token with various configurations.
getAssetWeightmarginRequirementType: MarginRequirementType, oraclePrice: OraclePrice, ignoreSoftLimits?: booleanBigNumberRetrieves the asset weight based on the margin requirement type and other factors.
getLiabilityWeightmarginRequirementType: MarginRequirementTypeBigNumberRetrieves the liability weight based on the margin requirement type.
computeTvloraclePrice: OraclePriceBigNumberComputes the total value locked (TVL) of the bank based on the provided oracle price.
computeInterestRatesNone{ lendingRate: BigNumber; borrowingRate: BigNumber }Computes the lending and borrowing interest rates for the bank.
computeBaseInterestRateNoneBigNumberComputes the base interest rate for the bank.
computeUtilizationRateNoneBigNumberComputes the utilization rate of the bank.
computeRemainingCapacityNone{ depositCapacity: BigNumber; borrowCapacity: BigNumber }Computes the remaining deposit and borrow capacity of the bank.
describeoraclePrice: OraclePricestringReturns a string describing the bank and its configuration based on the provided oracle price.

NodeWallet

An Anchor-compliant wallet implementation for Node.js environments.

  • static local(): NodeWallet:
    • Description: Creates a NodeWallet instance using the MARGINFI_WALLET environment variable or defaults to reading your local keypair from $HOME/.config/solana/id.json.
  • static anchor(): NodeWallet:
    • Description: Creates a NodeWallet instance using the ANCHOR_WALLET environment variable, throwing an error if the variable is not set.

MarginfiGroup

Represents a group within the marginfi protocol, managed by an admin, and provides methods for performing administrative actions on marginfi accounts and banks. Users can create instances from raw data, enable or disable flash loans, manage account transfer authority, and configure banks within the group.

Balance

Represents the balance of a user's assets and liabilities within a specific bank in the Marginfi protocol. It includes properties for the bank's public key, asset shares, liability shares, outstanding emissions, and the last update timestamp.

Properties

  • Name
    active
    Type
    boolean
    Description

    Indicates whether the balance is active or not.

  • Name
    bankPk
    Type
    PublicKey
    Description

    The public key of the bank associated with the balance.

  • Name
    assetShares
    Type
    BigNumber
    Description

    The amount of asset shares held in the balance.

  • Name
    liabilityShares
    Type
    BigNumber
    Description

    The amount of liability shares held in the balance.

  • Name
    emissionsOutstanding
    Type
    BigNumber
    Description

    The amount of outstanding emissions associated with the balance.

  • Name
    lastUpdate
    Type
    number
    Description

    The timestamp of the last update to the balance.

Methods

Method NameParametersResult Type(s)Description
frombalanceRaw: BalanceRawBalanceA static method that creates a new Balance instance from a BalanceRaw object.
createEmptybankPk: PublicKeyBalanceA static method that creates a new empty Balance instance with the given bank public key.
computeUsdValuebank: Bank, oraclePrice: OraclePrice, marginRequirementType: MarginRequirementType = MarginRequirementType.Equity{ assets: BigNumber; liabilities: BigNumber }Computes the USD value of the assets and liabilities in the balance based on the provided bank, oracle price, and margin requirement type.
getUsdValueWithPriceBiasbank: Bank, oraclePrice: OraclePrice, marginRequirementType: MarginRequirementType = MarginRequirementType.Equity{ assets: BigNumber; liabilities: BigNumber }Similar to computeUsdValue, but applies a price bias when computing the USD value of assets and liabilities.
computeQuantitybank: Bank{ assets: BigNumber; liabilities: BigNumber }Computes the quantity of assets and liabilities in the balance based on the provided bank.
computeQuantityUibank: Bank{ assets: BigNumber; liabilities: BigNumber }Similar to computeQuantity, but converts the quantities to the user interface format.
computeTotalOutstandingEmissionsbank: BankBigNumberComputes the total outstanding emissions associated with the balance based on the provided bank.
computeClaimedEmissionsbank: Bank, currentTimestamp: numberBigNumberComputes the claimed emissions associated with the balance based on the provided bank and the current timestamp.
describebank: Bank, oraclePrice: OraclePricestringReturns a string describing the balance, including the asset and liability quantities and their USD values.

Attributes

  • Name
    getAllMarginfiAccountPubkeys
    Type
    Argument(s): None
    Description

    Retrieves the public keys of all marginfi accounts in the specified group.

  • Name
    getMultipleMarginfiAccounts
    Type
    Argument(s): pubkeys
    Description

    Fetches multiple marginfi accounts based on an array of public keys.

  • Name
    getAllMarginfiAccountAddresses
    Type
    Argument(s): None
    Description

    Retrieves the addresses of all marginfi accounts in the underlying group.

  • Name
    getMarginfiAccountsForAuthority
    Type
    Argument(s): authority (optional)
    Description

    Retrieves all marginfi accounts under the specified authority.

  • Name
    getAllProgramAccountAddresses
    Type
    Argument(s): type
    Description

    Retrieves the addresses of all accounts owned by the marginfi program of a specified type.

  • Name
    getBankByPk
    Type
    Argument(s): bankAddress
    Description

    Finds a bank by its public key address.

  • Name
    getBankByMint
    Type
    Argument(s): mint
    Description

    Finds a bank by its mint address.

  • Name
    getBankByTokenSymbol
    Type
    Argument(s): tokenSymbol
    Description

    Finds a bank by its token symbol.

  • Name
    getOraclePriceByBank
    Type
    Argument(s): bankAddress
    Description

    Retrieves the oracle price for a specified bank.


User actions

  • Name
    makeCreateMarginfiAccountIx
    Type
    Argument(s): marginfiAccountPk
    Description

    Creates a transaction instruction to create a new marginfi account under the authority of the user.

  • Name
    createMarginfiAccount
    Type
    Argument(s): opts (optional), createOpts (optional)
    Description

    Creates a new marginfi account under the authority of the user.


Helpers

  • Name
    processTransaction
    Type
    Argument(s): transaction, signers (optional), opts (optional)
    Description

    Processes a transaction, signs it, and sends it to the network.

  • Name
    simulateTransaction
    Type
    Argument(s): transaction, accountsToInspect
    Description

    Simulates a transaction and inspects the provided accounts.


Utilities

  • Name
    getBankVaultSeeds
    Type
    Argument(s): type
    Description

    Returns the seed buffer for a specific bank vault type.

  • Name
    getBankVaultAuthoritySeeds
    Type
    Argument(s): type
    Description

    Returns the authority seed buffer for a specific bank vault type.

  • Name
    getBankVaultAuthority
    Type
    Argument(s): bankVaultType, bankPk, programId
    Description

    Computes the authority Program Derived Address (PDA) for a specific marginfi group bank vault.

  • Name
    makeWrapSolIxs
    Type
    Argument(s): walletAddress, amount
    Description

    Creates instructions to wrap SOL into a native token account.

  • Name
    makeUnwrapSolIx
    Type
    Argument(s): walletAddress
    Description

    Creates an instruction to unwrap SOL from a native token account.

  • Name
    makeVersionedTransaction
    Type
    Argument(s): blockhash, transaction, payer, addressLookupTables (optional)
    Description

    Creates a versioned transaction from a given blockhash, transaction, and payer, optionally including address lookup tables.


Constants

Constant NameDescription
PDA_BANK_LIQUIDITY_VAULT_AUTH_SEEDSeed for the authority of the liquidity vault in a Program Derived Address (PDA).
PDA_BANK_INSURANCE_VAULT_AUTH_SEEDSeed for the authority of the insurance vault in a PDA.
PDA_BANK_FEE_VAULT_AUTH_SEEDSeed for the authority of the fee vault in a PDA.
PDA_BANK_LIQUIDITY_VAULT_SEEDSeed for the liquidity vault in a PDA.
PDA_BANK_INSURANCE_VAULT_SEEDSeed for the insurance vault in a PDA.
PDA_BANK_FEE_VAULT_SEEDSeed for the fee vault in a PDA.
PYTH_PRICE_CONF_INTERVALSConfidence interval for Pyth price feeds, set to 2.12.
SWB_PRICE_CONF_INTERVALSConfidence interval for SWB price feeds, set to 1.96.
MAX_CONFIDENCE_INTERVAL_RATIOMaximum allowed ratio for confidence intervals, set to 0.05.
USDC_DECIMALSNumber of decimal places for USDC, set to 6.
ADDRESS_LOOKUP_TABLE_FOR_GROUPA mapping of group identifiers to an array of public keys for address lookup tables.
DISABLED_FLAGFlag indicating that a feature is disabled, represented by the value 1 << 0.
FLASHLOAN_ENABLED_FLAGFlag indicating that flash loans are enabled, represented by the value 1 << 2.
TRANSFER_ACCOUNT_AUTHORITY_FLAGFlag indicating the transfer of account authority, represented by the value 1 << 3.

Errors

ErrorDescriptionSuggestion
NotRentExemptLamport balance is below the rent-exempt threshold.Increase the lamport balance of the account to meet the rent-exempt threshold.
InsufficientFundsThere are insufficient funds to complete the operation.Add more funds to the account before retrying the operation.
InvalidMintThe provided mint is invalid.Verify and provide a valid mint address.
MintMismatchThe account is not associated with the specified mint.Ensure the account is associated with the correct mint.
OwnerMismatchThe owner of the account does not match the expected owner.Confirm the account owner and use the correct owner for the operation.
FixedSupplyThe token's supply is fixed and new tokens cannot be minted.Use a token with a flexible supply if more tokens need to be minted.
AlreadyInUseThe account cannot be initialized because it is already in use.Use a different account or ensure the existing account is properly closed before re-initializing.
InvalidNumberOfProvidedSignersThe number of provided signers is invalid.Check the required number of signers and provide the correct amount.
InvalidNumberOfRequiredSignersThe number of required signers is invalid.Adjust the number of required signers to match the expected count.
UninitializedStateThe state is uninitialized.Initialize the state before performing the operation.
NativeNotSupportedThe instruction does not support native tokens.Use a different instruction that supports native tokens or use non-native tokens.
NonNativeHasBalanceNon-native account can only be closed if its balance is zero.Ensure the non-native account balance is zero before attempting to close it.
InvalidInstructionThe instruction is invalid.Review and correct the instruction being sent.
InvalidStateThe state is invalid for the requested operation.Verify the current state and ensure it is valid for the intended operation.
OverflowThe operation overflowed.Adjust the operation to avoid exceeding the maximum limit.
AuthorityTypeNotSupportedThe account does not support the specified authority type.Use a different account that supports the required authority type.
MintCannotFreezeThe token mint cannot freeze accounts.Use a token mint that has the capability to freeze accounts if needed.
AccountFrozenThe account is frozen, and all account operations will fail.Unfreeze the account before attempting any operations.
MintDecimalsMismatchThere is a mint decimals mismatch between the client and the mint.Ensure the mint decimals match between the client and the token mint.
NonNativeNotSupportedThe instruction does not support non-native tokens.Use a different instruction that supports non-native tokens or switch to using native tokens.

Types

  • Name
    Environment
    Description

    Defines the possible configuration environments for the Marginfi protocol.

  • Name
    BankVaultType
    Description

    Enum for marginfi bank vault types, which includes LiquidityVault, InsuranceVault, and FeeVault.

  • Name
    MarginfiConfig
    Description

    Configuration interface for Marginfi, including environment, cluster, program ID, and group public key.

  • Name
    BankAddress
    Description

    Interface representing a bank address with a label and a public key address.

  • Name
    AccountType
    Description

    Enum for on-chain account types, which includes MarginfiGroup, MarginfiAccount, and Bank.

  • Name
    BalanceRaw
    Description

    Represents the raw on-chain data structure for a user's balance in the Marginfi protocol.

  • Name
    MarginfiGroupRaw
    Description

    Represents the raw on-chain data structure for a Marginfi group.


Examples

Kickstart your development journey with a collection of insightful examples. Explore additional helpful examples within the marginfi monorepo.

Fetching All Banks Owned by the marginfi-v2 Program

Example

import { Connection, PublicKey } from "@solana/web3.js";
import { MarginfiClient, getConfig, AccountType, Bank } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet } from "@mrgnlabs/mrgn-common";

const RPC_ENDPOINT = "<RPC-URL>";

async function main() {
    const connection = new Connection(RPC_ENDPOINT, "confirmed");
    const wallet = NodeWallet.local();
    const config = getConfig("production");
    const client = await MarginfiClient.fetch(config, wallet, connection);

    // Fetch all public keys of banks owned by the mfi program
    const bankPubKeys = await client.getAllProgramAccountAddresses(AccountType.Bank);

    const banks = await Promise.all(
        bankPubKeys.map(async (bankPubKey) => {
            try {
                // Fetch account data for each bank
                const accountInfo = await connection.getAccountInfo(bankPubKey);
                if (accountInfo === null) {
                    console.error(`Failed to fetch account info for ${bankPubKey.toString()}`);
                    return null;
                }

                // Parse account data using Bank.fromBuffer
                const bank = Bank.fromBuffer(bankPubKey, accountInfo.data);
                return bank;
            } catch (error) {
                console.error(`Error processing bank ${bankPubKey.toString()}:`, error);
                return null;
            }
        })
    );

    // Filter out any null values (failed fetches/parses)
    const validBanks = banks.filter(bank => bank !== null);
    validBanks.forEach((bank, index) => {
        console.log(`Bank ${index + 1}:`, bank);
    });
}

main().catch((e) => console.log(e));

Fetching and Exporting Depositors for a Specific Bank

Using the marginfi SDK, fetch all Marginfi accounts that have an active deposit in a specific bank token (e.g., SOL). Then export the wallet address, user account address, and deposit amount for those accounts into a CSV file.

Example

import { PublicKey, Connection } from "@solana/web3.js";
import { MarginfiAccountWrapper, MarginfiClient, getConfig } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet, chunkedGetRawMultipleAccountInfos, chunks } from "@mrgnlabs/mrgn-common";
import fs from "fs";

const BANK_TOKEN = "SOL";

interface BankDepositor {
  wallet: string;
  userAccount: string;
  amount: number;
}

async function main() {
  const connection = new Connection("https://api.devnet.solana.com", "confirmed");
  const wallet = NodeWallet.local()
  const config = getConfig("dev");
  const client = await MarginfiClient.fetch(config, wallet, connection);

  const targetBank = client.getBankByTokenSymbol(BANK_TOKEN);
  if (!targetBank) {
    throw new Error(`Bank ${BANK_TOKEN} not found`);
  }

  console.log(`Fetching all marginfi accounts...`)
  const marginfiAccountAddresses = await client.getAllMarginfiAccountAddresses();
  console.log(`Found ${marginfiAccountAddresses.length} marginfi accounts`);

  const addressBatches = chunks(marginfiAccountAddresses, 25_000); // To avoid blowing memory

  const depositorFileName = `./marginfi_depositors_${BANK_TOKEN}_${Date.now()}.csv`;
  fs.writeFileSync(depositorFileName, "wallet,user_account,amount\n");

  for (let i = 0; i < addressBatches.length; i++) {
    const addressBatch = addressBatches[i];
    console.log(`Processing batch ${i + 1}/${addressBatches.length} of ${addressBatch.length} addresses`);

    const [_, accountInfoMap] = await chunkedGetRawMultipleAccountInfos(
      client.provider.connection,
      addressBatch.map((pk) => pk.toBase58())
    );

    let depositors: BankDepositor[] = [];
    for (const [address, accountInfo] of accountInfoMap) {
      const marginfiAccount = MarginfiAccountWrapper.fromAccountDataRaw(new PublicKey(address), client, accountInfo.data);
      const depositAmount = marginfiAccount.balances
        .find((b) => b.active && b.bankPk.equals(targetBank.address) && b.assetShares.gt(0))
        ?.computeQuantityUi(targetBank).assets;
      if (depositAmount) {
        depositors.push({
          wallet: marginfiAccount.authority.toString(),
          userAccount: marginfiAccount.address.toString(),
          amount: depositAmount.toNumber(),
        });
      }
    }
    const csvContent = depositors.map(depositor => `${depositor.wallet},${depositor.userAccount},${depositor.amount}`).join('\n');
    fs.appendFileSync(depositorFileName, csvContent);
  }
}

main().catch((e) => console.log(e));

Account Creation and Deposit

Use the marginfi SDK to create a new account and deposit tokens from two different banks (SOL and USDC) into the account. Then retrieve the active balances for the account, calculate the USD value of the assets and liabilities for each balance, and log this information to the console.

Example

import { Connection } from "@solana/web3.js";
import { MarginfiClient } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet } from "@mrgnlabs/mrgn-common";

async function main() {
	const connection = new Connection("<rpc-url>", "confirmed");
  const wallet = NodeWallet.local()
  const config = getConfig("<environment>");
  const client = await MarginfiClient.fetch(config, wallet, connection);

  console.log(`Using ${client.config.environment} environment; wallet: ${client.wallet.publicKey.toBase58()}`);

  const marginfiAccount = await client.createMarginfiAccount();

  const bankLabel1 = "SOL";
  const bank1 = client.getBankByTokenSymbol(bankLabel1);
  if (!bank1) throw Error(`${bankLabel1} bank not found`);
  const bankLabel2 = "USDC";
  const bank2 = client.getBankByTokenSymbol(bankLabel2);
  if (!bank2) throw Error(`${bankLabel2} bank not found`);

  await marginfiAccount.deposit(1, bank1.address);
  await marginfiAccount.deposit(2, bank2.address);

  await marginfiAccount.reload();

  marginfiAccount.activeBalances.forEach((balance) => {
    const bank = client.getBankByPk(balance.bankPk)!;
    const oraclePrice = client.getOraclePriceByBank(bank.address)!;
    const { assets, liabilities } = balance.computeUsdValue(bank, oraclePrice, MarginRequirementType.Equity);

    console.log(
      `Balance for ${shortenAddress(bank.mint)} (${shortenAddress(
        balance.bankPk
      )}) deposits: ${assets}, borrows: ${liabilities}`
    );
  });
}

main().catch((e) => console.log(e));

Display a Accounts

Fetch a marginfi account and display it’s data.

Example

import { Connection } from "@solana/web3.js";
import { MarginfiClient, MarginfiAccountWrapper } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet } from "@mrgnlabs/mrgn-common";

const MFI_ACCOUNT_ADDRESS = "<account-address>"; // e.g., 3oS3RJ8UYrYw7TAQEVh6u6ifrHi35o3DnvqyqGti4Gwa

async function main() {
	const connection = new Connection("<rpc-url>", "confirmed");
	const wallet = NodeWallet.local()
	const config = getConfig("<environment>");
	const client = await MarginfiClient.fetch(config, wallet, connection);

  const marginfiAccount = await MarginfiAccountWrapper.fetch(MFI_ACCOUNT_ADDRESS, client);

  console.log("Account state:");
  console.log(marginfiAccount.describe());
}

main().catch((e) => console.log(e));

Conduct a Flash Loan

Fetch a marginfi account, get a bank via token symbol, and perform a flashloan using the bank.

Example

import { Connection } from "@solana/web3.js";
import { MarginfiClient, MarginfiAccountWrapper } from '@mrgnlabs/marginfi-client-v2';
import { NodeWallet } from "@mrgnlabs/mrgn-common";

async function main() {
  const connection = new Connection("<rpc-url>", "confirmed");
	const wallet = NodeWallet.local()
	const config = getConfig("<environment>");
	const client = await MarginfiClient.fetch(config, wallet, connection);

  const marginfiAccounts = await client.getMarginfiAccountsForAuthority();
  if (marginfiAccounts.length === 0) throw Error("No marginfi account found");

  const marginfiAccount = marginfiAccounts[0];

  const solBank = client.getBankByTokenSymbol("SOL");
  if (!solBank) throw Error("SOL bank not found");

  const amount = 10; // SOL

  const borrowIx = await marginfiAccount.makeBorrowIx(amount, solBank.address);
  const repayIx = await marginfiAccount.makeRepayIx(amount, solBank.address, true);

  const flashLoanTx = await marginfiAccount.buildFlashLoanTx({
    ixs: [...borrowIx.instructions, ...repayIx.instructions],
    signers: [],
  });

  await client.processTransaction(flashLoanTx);
}

main().catch((e) => console.log(e));

Was this page helpful?