The marginfi Rust CLI
With the marginfi CLI tool, you can interact with the marginfi protocol directly from your terminal, taking advantage of its borrowing and lending services. Built in Rust, this command-line interface simplifies the process of managing your marginfi activities. Whether you want to create a new bank, make deposits to existing banks, or perform other operations, the marginfi CLI provides a streamlined experience.
Access the Rust (CLI) SDK source code using this link.
Installation
To get started, install the latest stable Rust toolchain and set it to default:
rustup default stable-x86_64-apple-darwin
rustc --version
Then, download the CLI tool, navigate inside the folder, and execute the build with the --all-features flag and target x86_64:
git clone https://github.com/mrgnlabs/marginfi-v2.git
cd marginfi-v2/clients/rust/marginfi-cli
cargo install --path . --target x86_64-apple-darwin --all-features
You can then test if the CLI has been installed correctly by running mfi. You should see output like so:
mfi
marginfi-v2-cli 0.1.0
USAGE:
    mfi [OPTIONS] <SUBCOMMAND>
OPTIONS:
        --dry-run              Dry run for any transactions involved
    -h, --help                 Print help information
    -V, --version              Print version information
    -y, --skip-confirmation
SUBCOMMANDS:
    account
    bank
    group
    help                        Print this message or the help of the given subcommand(s)
    inspect-padding
    inspect-size
    inspect-switchboard-feed
    lip
    profile
Getting Started
Step 1: Create a Profile
First, we must create a profile which we will use to interact with the marginfi protocol. To create a profile, use the profile subcommand:
mfi profile create --name <NAME> --cluster <CLUSTER> --keypair-path <KEYPAIR_PATH> --rpc-url <RPC_URL>
For example:
mfi profile create --name masterzorgon --cluster mainnet --keypair-path /Users/MasterZorgon/Documents/Keypairs/UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV.json --rpc-url https://api.mainnet-beta.solana.com
If you don’t already have a file system wallet, create one using solana-keygen.
Confirm that you’ve successfully created a profile like so:
mfi profile show
The output should look like the following:
Profile:
    Name: masterzorgon
    Program: MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA
    Marginfi Group: None
    Marginfi Account: None
    Cluster: mainnet
    Rpc URL: https://api.mainnet-beta.solana.com
    Fee Payer: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Authority: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Keypair: /Users/MasterZorgon/Documents/Keypairs/UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV.json
    Multisig: None
Step 2: Create a Group
This step will require a transaction fee denominated in SOL. Your file system wallet must be funded with enough mainnet-beta SOL to cover the transaction fee of creating an account on-chain.
A group represents a lending pool with a set of rules and configurations. It acts as a container for multiple lending banks, each with its own settings. The group defines the overall parameters for the lending and borrowing activities within its scope.
You can create a group using the group subcommand:
mfi group create
You will then be shown the profile you recently created. Type the name of your profile to continue:
Command: Create
Profile:
    Name: masterzorgon
    Program: MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA
    Marginfi Group: None
    Marginfi Account: None
    Cluster: mainnet
    Rpc URL: https://api.mainnet-beta.solana.com
    Fee Payer: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Authority: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Keypair: /Users/MasterZorgon/Documents/Keypairs/UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV.json
    Multisig: None
        
Type the name of the profile [masterzorgon] to continue  
Step 3: Create an Account
This step will require a transaction fee denominated in SOL. Your file system wallet must be funded with enough mainnet-beta SOL to cover the transaction fee of creating an account on-chain.
An account represents an individual user's position within a group. Each user has their own account, which manages their deposits, borrows, and collateral levels. Accounts interact with the lending banks within a group to perform actions like depositing funds, borrowing assets, or repaying loans.
Before you can start borrowing and lending via the CLI, you must set an account and link it to your profile:
mfi account create
You will then be shown the profile you recently created. Type the name of your profile to continue:
Command: Create
Profile:
    Name: masterzorgon
    Program: MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA
    Marginfi Group: None
    Marginfi Account: None
    Cluster: mainnet
    Rpc URL: https://api.mainnet-beta.solana.com
    Fee Payer: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Authority: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Keypair: /Users/MasterZorgon/Documents/Keypairs/UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV.json
    Multisig: None
        
Type the name of the profile [masterzorgon] to continue
Step 4: Deposit to a Bank
Now that you’ve created your account, you can interact with the marginfi protocol. Let’s start with lending to a marginfi bank. In this example, we’re going to deposit 1 USDC into the USDC pool 3uxNepDbmkDNq6JhRja5Z8QwbTrfmkKP8AKZV5chYDGG:
mfi account deposit 3uxNepDbmkDNq6JhRja5Z8QwbTrfmkKP8AKZV5chYDGG 1
You will then be shown your profile and asked to confirm the profile you want to interact with by typing the profile name:
Command: Deposit {
    bank: 3uxNepDbmkDNq6JhRja5Z8QwbTrfmkKP8AKZV5chYDGG,
    ui_amount: 1.0,
}
Profile:
    Name: masterzorgon
    Program: MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA
    Marginfi Group: None
    Marginfi Account: None
    Cluster: mainnet
    Rpc URL: https://api.mainnet-beta.solana.com
    Fee Payer: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Authority: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Keypair: /Users/MasterZorgon/Documents/Keypairs/UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV.json
    Multisig: None
        
Type the name of the profile [masterzorgon] to continue
Subcommands
Group
Manages lending groups in the marginlend protocol.
- Name
 add-bank- Description
 Adds a new lending bank to the marginfi group. (Enabled with
adminfeature)
- Name
 create- Description
 Creates a new marginfi group. (Enabled with
adminfeature)
- Name
 get- Description
 Retrieves information about the specified marginfi group.
- Name
 get-all- Description
 Retrieves information about all marginfi groups.
- Name
 handle-bankruptcy- Description
 Handles bankruptcy for the specified marginfi accounts in the group. (Enabled with
adminfeature)
- Name
 update- Description
 Updates an existing marginfi group. (Enabled with
adminfeature)
- Name
 update-lookup-table- Description
 Updates the token lookup table for the marginfi group. (Enabled with
adminfeature)
Bank
Handles operations related to lending banks within groups.
- Name
 collect-fees- Description
 Collects fees from a lending bank. (Enabled with
adminfeature)
- Name
 get- Description
 Retrieves information about the specified lending bank.
- Name
 get-all- Description
 Retrieves information about all lending banks in the specified marginfi group.
- Name
 inspect-price-oracle- Description
 Inspects the price oracle for a lending bank.
- Name
 settle-all-emissions- Description
 Settles all pending emissions (rewards) for a lending bank. (Enabled with
adminfeature)
- Name
 setup-emissions- Description
 Sets up emissions (rewards) for a lending bank.
- Name
 update- Description
 Updates the configuration of a lending bank. (Enabled with
adminfeature)
- Name
 update-emissions- Description
 Updates the emissions (rewards) parameters for a lending bank. (Enabled with
adminfeature)
- Name
 withdraw-fees- Description
 Withdraws fees from a lending bank. (Enabled with
adminfeature)
- Name
 withdraw-insurance- Description
 Withdraws insurance funds from a lending bank. (Enabled with
adminfeature)
Profile
Manages user profiles or configurations.
- Name
 create- Description
 Creates a new profile configuration.
- Name
 list- Description
 Lists all available profile configurations.
- Name
 set- Description
 Sets the current profile configuration.
- Name
 show- Description
 Shows the current profile configuration.
- Name
 update- Description
 Updates an existing profile configuration.
InspectPadding
The inspect-padding subcommand, which is compiled only when the dev feature is enabled,  is used to inspect the padding or memory layout-related information for development or debugging purposes.
PatchIdl
The patch-idl subcommand, which is compiled only when the dev feature is enabled, is used to modify the JSON Interface Definition Library (IDL) file for the MarginFi program.
InspectSize
The inspect-size subcommand, which is compiled only when the dev feature is enabled, is used to print the size (in bytes) of various data structures used in the application.
Account
Manages user accounts within the marginlend protocol.
- Name
 borrow- Description
 Borrows funds from a lending bank.
- Name
 create- Description
 Creates a new marginfi account.
- Name
 deposit- Description
 Deposits funds into a lending bank.
- Name
 get- Description
 Retrieves information about the specified marginfi account or the currently active account.
- Name
 liquidate- Description
 Liquidates a marginfi account by repaying its debt and seizing collateral.
- Name
 list- Description
 Lists all available marginfi accounts.
- Name
 set-flag- Description
 Sets a flag on a marginfi account.
- Name
 use- Description
 Sets the currently active marginfi account.
- Name
 withdraw- Description
 Withdraws funds from a lending bank.
Lip
The lip subcommand is related to managing LIP (Liquidity Incentive Program) campaigns and deposits.
- Name
 list-campaigns- Description
 Lists all LIP campaigns.
- Name
 list-deposits- Description
 Lists all deposits made to LIP campaigns.
InspectSwitchboardFeed
The inspect-switchboard-feed subcommand, which is compiled only when the dev feature is enabled, inspects Switchboard oracle feeds, used for obtaining price data on listings.
ShowOracleAges
Displays information about the ages or staleness of oracle data sources, with an option to filter for only stale oracles.
Examples
Create a Permissionless Isolated Bank
With marginfi permissionless banks, you can create your own isolated bank for any token you want backed by any collateral you want. Below is an example of how to create your first permissionless bank using the marginfi CLI.
Before you begin, ensure that you have the latest version of the marginfi CLI installed. Click here to get started.
Step 2. Assign your CLI profile to a group
Every bank belongs to a group, which acts as a container for banks, setting their configuration and administrative rules. If you have already setup your CLI profile with a group, you can skip this step.
To create a bank within a group, your CLI profile must be assigned to that group.
To get started, query your currency profile configuration and confirm that the Marginfi Group field is empty:
Profile:
    Name: nathan
    Program: MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA
    Marginfi Group: None
    Marginfi Account: None
    Cluster: mainnet
    Rpc URL: <YOUR-RPC-URL>
    Fee Payer: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Authority: UPX866A3Lrdghw1BUdxBkCUMpVEZaokZqFxLskUTiMV
    Keypair: <PATH-TO-LOCAL-KEYPAIR>>
    Multisig: None
If the Marginfi Group field is empty, update the field with a group pubkey like so:
mfi profile show update <PROFILE-NAME> --group <GROUP-PUBKEY>
For example:
mfi profile update nathan --group 4qp6Fx6tnZkY5Wropq9wUYgtFxXKwE6viZxFHg3rdAG8
Step 3. Use the bank creation command
Using the CLI, type the command mfi group add-bank. This command initializes the process of creating a new bank within your group. You will be prompted to provide several arguments to set up your bank correctly.
A group represents a container that sets configuration and admin rules for banks. It acts as a container for multiple lending banks, each with its own settings. The group defines the overall parameters for the lending and borrowing activities within its scope.
We create a bank using the add-bank subcommand under group because the group serves as the overarching structure that manages and coordinates the individual banks.
error: The following required arguments were not provided:
    --mint <MINT>
    --asset-weight-init <ASSET_WEIGHT_INIT>
    --asset-weight-maint <ASSET_WEIGHT_MAINT>
    --liability-weight-init <LIABILITY_WEIGHT_INIT>
    --liability-weight-maint <LIABILITY_WEIGHT_MAINT>
    --deposit-limit-ui <DEPOSIT_LIMIT_UI>
    --borrow-limit-ui <BORROW_LIMIT_UI>
    --pyth-oracle <PYTH_ORACLE>
    --optimal-utilization-rate <OPTIMAL_UTILIZATION_RATE>
    --plateau-interest-rate <PLATEAU_INTEREST_RATE>
    --max-interest-rate <MAX_INTEREST_RATE>
    --insurance-fee-fixed-apr <INSURANCE_FEE_FIXED_APR>
    --insurance-ir-fee <INSURANCE_IR_FEE>
    --protocol-fixed-fee-apr <PROTOCOL_FIXED_FEE_APR>
    --protocol-ir-fee <PROTOCOL_IR_FEE>
    --risk-tier <RISK_TIER>
    --oracle-type <ORACLE_TYPE>
Here is an explanation for each argument:
- Name
 --mint- Type
 - Pubkey
 - Description
 The token mint address.
- Name
 --seed- Type
 - bool
 - Description
 Generates a PDA for the bank key.
- Name
 --asset-weight-init- Type
 - f64
 - Description
 Initial weight of the asset for risk calculations.
- Name
 --asset-weight-maint- Type
 - f64
 - Description
 Maintenance weight of the asset for risk calculations.
- Name
 --liability-weight-init- Type
 - f64
 - Description
 Initial weight of the liability for risk calculations.
- Name
 --liability-weight-maint- Type
 - f64
 - Description
 Maintenance weight of the liability for risk calculations.
- Name
 --deposit-limit-ui- Type
 - u64
 - Description
 User interface limit for deposits.
- Name
 --borrow-limit-ui- Type
 - u64
 - Description
 User interface limit for borrowing.
- Name
 --pyth-oracle- Type
 - Pubkey
 - Description
 Pyth oracle for price feeds.
- Name
 --optimal-utilization-rate- Type
 - f64
 - Description
 Optimal rate at which the asset is utilized.
- Name
 --plateau-interest-rate- Type
 - f64
 - Description
 Interest rate at the optimal utilization rate.
- Name
 --max-interest-rate- Type
 - f64
 - Description
 Maximum possible interest rate.
- Name
 --insurance-fee-fixed-apr- Type
 - f64
 - Description
 Fixed annual insurance fee rate.
- Name
 --insurance-ir-fee- Type
 - f64
 - Description
 Interest rate component of the insurance fee.
- Name
 --protocol-fixed-fee-apr- Type
 - f64
 - Description
 Fixed annual protocol fee rate.
- Name
 --protocol-ir-fee- Type
 - f64
 - Description
 Interest rate component of the protocol fee.
- Name
 --risk-tier- Type
 - RiskTierArg: Collateral (0), Isolated (1)
 - Description
 The risk tier classification of the asset.
- Name
 --oracle-type- Type
 - OracleTypeArg: PythEma (0), Switchboard (1)
 - Description
 The type of oracle used for price feeds.
- Name
 --oracle-max-age- Type
 - u16
 - Description
 Max oracle age in seconds, 0 for default (60s).
Step 4. Provide the required arguments
Using the CLI, type the command mfi group add-bank and provide the required arguments using double-dashes.
In this example, I will create a permissionless pool for the $BODEN token.
This demonstration is not an advertisement of any token, nor a soliciation to purchase any token or conduct financial activity with any token. This demonstration is purely for educational purposes.
mfi group add-bank  
  --mint 3psH1Mj1f7yUfaD5gh6Zj7epE8hhrMkMETgv5TshQA4o 
  --asset-weight-init 0.5 
  --asset-weight-maint 0.4 
  --liability-weight-init 1.5 
  --liability-weight-maint 1.6 
  --deposit-limit-ui 1000000 
  --borrow-limit-ui 500000 
  --pyth-oracle HdmQWanpTqq6eKASuBKe1ejrHkgSiaAfjZ4qEJEKM9jj 
  --optimal-utilization-rate 0.7 
  --plateau-interest-rate 0.08 
  --insurance-fee-fixed-apr 0.02 
  --insurance-ir-fee 0.05 
  --protocol-fixed-fee-apr 0.02 
  --protocol-ir-fee 0.05 
  --risk-tier 'isolated' 
  --oracle-type 'switchboard' 
  --max-interest-rate 0.25 
  --oracle-max-age 30
Here are explanations for each argument:
- Name
 --mint- Type
 - Pubkey: 3psH1Mj1f7yUfaD5gh6Zj7epE8hhrMkMETgv5TshQA4o
 - Description
 This is the unique address of the token being added to the bank. It remains unchanged as it's specific to the asset.
- Name
 --asset-weight-init- Type
 - f64: 0.5
 - Description
 For risk calculations, only 50% of the asset's value is considered initially, reflecting its high volatility.
- Name
 --asset-weight-maint- Type
 - f64: 0.4
 - Description
 For ongoing risk maintenance, only 40% of the asset's value is considered, providing an extra safety margin.
- Name
 --liability-weight-init- Type
 - f64: 1.5
 - Description
 Borrowed amounts are treated as 150% of their value for initial risk calculations, accounting for higher volatility risk.
- Name
 --liability-weight-maint- Type
 - f64: 1.6
 - Description
 For ongoing risk maintenance, borrowed amounts are treated as 160% of their value, providing an extra safety buffer.
- Name
 --deposit-limit-ui- Type
 - u64: 1000000
 - Description
 Allows for larger deposits, assuming this is a cryptocurrency with lower individual token value.
- Name
 --borrow-limit-ui- Type
 - u64: 500000
 - Description
 Borrowing limit is set lower than the deposit limit to maintain a safety buffer for this volatile asset.
- Name
 --pyth-oracle- Type
 - Pubkey: HdmQWanpTqq6eKASuBKe1ejrHkgSiaAfjZ4qEJEKM9jj
 - Description
 This remains unchanged as it's the specific address for the Pyth oracle providing price information for this asset.
- Name
 --optimal-utilization-rate- Type
 - f64: 0.7
 - Description
 The bank aims to have 70% of its assets in use, slightly lower than before to maintain more liquidity for a volatile asset.
- Name
 --plateau-interest-rate- Type
 - f64: 0.08
 - Description
 The interest rate is 8% when utilization is at the optimal rate, increased to reflect the higher risk of the volatile asset.
- Name
 --insurance-fee-fixed-apr- Type
 - f64: 0.02
 - Description
 A fixed 2% annual fee for insurance, doubled from the previous value due to higher risk.
- Name
 --insurance-ir-fee- Type
 - f64: 0.05
 - Description
 An additional 5% of the interest rate goes to insurance, increased to cover potential rapid value changes.
- Name
 --protocol-fixed-fee-apr- Type
 - f64: 0.02
 - Description
 A fixed 2% annual fee for the protocol, doubled to compensate for higher operational risks.
- Name
 --protocol-ir-fee- Type
 - f64: 0.05
 - Description
 An additional 5% of the interest rate goes to the protocol, increased due to higher risk.
- Name
 --risk-tier- Type
 - RiskTierArg: Isolated (1)
 - Description
 The asset remains classified as "Isolated" risk, appropriate for a highly volatile asset.
- Name
 --oracle-type- Type
 - OracleTypeArg: PythEma (0)
 - Description
 The bank continues to use Pyth as its oracle for price information.
- Name
 --max-interest-rate- Type
 - f64: 0.25
 - Description
 The highest possible interest rate is now 25%, significantly increased to account for the asset's volatility.
- Name
 --oracle-max-age- Type
 - u16: 30
 - Description
 New parameter added to ensure price updates occur at least every 30 seconds, providing more up-to-date information for this volatile asset.
Conclusion
Congrats! You just created a permissionless bank using the marginfi CLI. If you're building an application using marginfi's permissionless banks, please reach out to @nathanzebedee on Telegram for support. We would love to assist you!