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
admin
feature)
- Name
create
- Description
Creates a new marginfi group. (Enabled with
admin
feature)
- 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
admin
feature)
- Name
update
- Description
Updates an existing marginfi group. (Enabled with
admin
feature)
- Name
update-lookup-table
- Description
Updates the token lookup table for the marginfi group. (Enabled with
admin
feature)
Bank
Handles operations related to lending banks within groups.
- Name
collect-fees
- Description
Collects fees from a lending bank. (Enabled with
admin
feature)
- 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
admin
feature)
- Name
setup-emissions
- Description
Sets up emissions (rewards) for a lending bank.
- Name
update
- Description
Updates the configuration of a lending bank. (Enabled with
admin
feature)
- Name
update-emissions
- Description
Updates the emissions (rewards) parameters for a lending bank. (Enabled with
admin
feature)
- Name
withdraw-fees
- Description
Withdraws fees from a lending bank. (Enabled with
admin
feature)
- Name
withdraw-insurance
- Description
Withdraws insurance funds from a lending bank. (Enabled with
admin
feature)
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!