Skip to content

Commit 75e453d

Browse files
committed
Adding CLI commands
1 parent a08a381 commit 75e453d

16 files changed

+602
-32
lines changed

Cargo.lock

Lines changed: 24 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

token-lending/cli/Cargo.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,22 @@ license = "Apache-2.0"
99
repository = "https://github.com/solendprotocol/solana-program-library"
1010

1111
[dependencies]
12+
bincode = "1.3.3"
1213
clap = "=2.34.0"
14+
indicatif = "0.17.11"
15+
reqwest = { version = "0.12.2", features = ["blocking", "json"] }
16+
serde_json = "1.0.120"
17+
solana-account-decoder = "1.14.10"
1318
solana-clap-utils = "1.14.10"
1419
solana-cli-config = "1.14.10"
1520
solana-client = "1.14.10"
1621
solana-logger = "1.14.10"
17-
solana-sdk = "1.14.10"
1822
solana-program = "1.14.10"
19-
solend-sdk = { path = "../sdk" }
23+
solana-sdk = "1.14.10"
2024
solend-program = { path = "../program", features = ["no-entrypoint"] }
21-
spl-token = { version = "3.3.0", features = ["no-entrypoint"] }
25+
solend-sdk = { path = "../sdk" }
2226
spl-associated-token-account = "1.0"
23-
solana-account-decoder = "1.14.10"
24-
reqwest = { version = "0.12.2", features = ["blocking", "json"] }
25-
bincode = "1.3.3"
26-
serde_json = "1.0.120"
27+
spl-token = { version = "3.3.0", features = ["no-entrypoint"] }
2728

2829
[[bin]]
2930
name = "solend-cli"
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
//! CLI commands related to liquidity mining.
22
3+
mod add_pool_reward;
4+
mod claim_pool_reward;
5+
mod close_pool_reward;
6+
mod crank_pool_rewards;
7+
mod edit_pool_reward;
8+
mod find_obligations_to_fund;
39
mod migrate_all_reserves;
410

5-
pub(crate) use migrate_all_reserves::command_upgrade_reserves_to_v2_1_0;
11+
pub(crate) use add_pool_reward::command as command_add_pool_reward;
12+
pub(crate) use crank_pool_rewards::command as command_crank_pool_rewards;
13+
pub(crate) use find_obligations_to_fund::command as command_find_obligations_to_fund_for_liquidity_mining;
14+
pub(crate) use migrate_all_reserves::command as command_migrate_all_reserves_for_liquidity_mining;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//! Adds a pool reward to a reserve.
2+
//!
3+
//! The signer must be the owner of the lending market, and there must be a free slot in the reserve.
4+
5+
use std::{borrow::Borrow, str::FromStr};
6+
7+
use solana_program::program_pack::Pack;
8+
use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer, system_instruction};
9+
use solend_sdk::{
10+
instruction::{add_pool_reward, find_reward_vault_authority},
11+
state::{LendingMarket, PoolRewardEntry, PositionKind, Reserve},
12+
};
13+
14+
use crate::{send_transaction, CommandResult, Config};
15+
16+
pub(crate) fn command(
17+
config: &mut Config,
18+
reserve_pubkey: Pubkey,
19+
position_kind: PositionKind,
20+
source_reward_token_account_pubkey: Pubkey,
21+
start_time_secs: u64,
22+
duration_secs: u32,
23+
token_amount: u64,
24+
) -> CommandResult {
25+
let reserve_info = config.rpc_client.get_account(&reserve_pubkey)?;
26+
let reserve = Reserve::unpack_from_slice(reserve_info.data.borrow())?;
27+
let lending_market_info = config.rpc_client.get_account(&reserve.lending_market)?;
28+
let lending_market = LendingMarket::unpack(lending_market_info.data.borrow())?;
29+
30+
if config.fee_payer.pubkey() != lending_market.owner {
31+
return Err(format!(
32+
"The fee payer must be the owner of the lending market '{}'",
33+
reserve.lending_market
34+
)
35+
.into());
36+
}
37+
38+
let has_free_slot = reserve
39+
.pool_reward_manager(position_kind)
40+
.pool_rewards
41+
.iter()
42+
.any(|pr| matches!(pr, PoolRewardEntry::Vacant { .. }));
43+
44+
if !has_free_slot {
45+
return Err(format!(
46+
"There are no vacant slots to add the pool reward. Please crank it first"
47+
)
48+
.into());
49+
}
50+
51+
let Some(source_reward_token_account) = config
52+
.rpc_client
53+
.get_token_account(&source_reward_token_account_pubkey)?
54+
else {
55+
return Err(format!(
56+
"Failed to fetch source token account '{}'",
57+
source_reward_token_account_pubkey
58+
))?;
59+
};
60+
61+
let reward_mint = Pubkey::from_str(&source_reward_token_account.mint)?;
62+
63+
let reward_vault_keypair = Keypair::new();
64+
65+
let create_account_ix = system_instruction::create_account(
66+
&config.fee_payer.pubkey(),
67+
&reward_vault_keypair.pubkey(),
68+
config
69+
.rpc_client
70+
.get_minimum_balance_for_rent_exemption(spl_token::state::Account::LEN)?,
71+
spl_token::state::Account::LEN as _,
72+
&spl_token::id(),
73+
);
74+
75+
let (reward_vault_authority, reward_authority_bump) = find_reward_vault_authority(
76+
&config.lending_program_id,
77+
&reserve.lending_market,
78+
&reward_vault_keypair.pubkey(),
79+
);
80+
81+
let add_reward_ix = add_pool_reward(
82+
config.lending_program_id,
83+
reward_authority_bump,
84+
position_kind,
85+
start_time_secs,
86+
start_time_secs + duration_secs as u64,
87+
token_amount,
88+
reserve_pubkey,
89+
reward_mint,
90+
source_reward_token_account_pubkey,
91+
reward_vault_authority,
92+
reward_vault_keypair.pubkey(),
93+
reserve.lending_market,
94+
lending_market.owner,
95+
);
96+
97+
let recent_blockhash = config.rpc_client.get_latest_blockhash()?;
98+
99+
let message = solana_sdk::message::Message::new_with_blockhash(
100+
&[create_account_ix, add_reward_ix],
101+
Some(&config.fee_payer.pubkey()),
102+
&recent_blockhash,
103+
);
104+
105+
let transaction = solana_sdk::transaction::Transaction::new(
106+
&vec![config.fee_payer.as_ref()],
107+
message,
108+
recent_blockhash,
109+
);
110+
111+
send_transaction(config, transaction)?;
112+
113+
Ok(())
114+
}

token-lending/cli/src/liquidity_mining/claim_pool_reward.rs

Whitespace-only changes.

token-lending/cli/src/liquidity_mining/close_pool_reward.rs

Whitespace-only changes.

0 commit comments

Comments
 (0)