Skip to content

Commit 2c94ce1

Browse files
Jli/cli pll claim evict (#31)
* add get seat manager info * add psm claim and evict seat * add doc comments to claim and evict * update versions for SDK and PSM * check for market authority managed by PSM in get seat manager info * increment version
1 parent c2ca8ab commit 2c94ce1

File tree

8 files changed

+185
-12
lines changed

8 files changed

+185
-12
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "phoenix-cli"
3-
version = "0.2.4"
3+
version = "0.3.0"
44
description = "CLI and associated library for interacting with the Phoenix program from the command line"
55
edition = "2021"
66
license = "MIT"
@@ -34,7 +34,8 @@ serde = { version = "1.0", features = ["derive"] }
3434
serde_json = "1.0"
3535
spl-associated-token-account = { version = "1.1.1", features = [ "no-entrypoint" ] }
3636
phoenix-v1 = { version = "0.2.2", features = ["no-entrypoint"] }
37-
phoenix-sdk = "0.3.6"
37+
phoenix-sdk = "0.4.0"
3838
bytemuck = "1.13.0"
3939
reqwest = "0.11.14"
4040
bincode = "1.3.3"
41+
phoenix-seat-manager = "0.1.0"

src/command.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ pub enum PhoenixCLICommand {
2828
/// Get the full order book for a given market
2929
GetFullBook { market_pubkey: Pubkey },
3030
/// Get the market events that occured in a given transaction signature
31-
GetTransaction {
32-
signature: Signature,
33-
},
31+
GetTransaction { signature: Signature },
3432
/// Get the current status of a market
3533
GetMarketStatus { market_pubkey: Pubkey },
3634
/// Get the status and address of a seat for a given market and trader
@@ -47,11 +45,12 @@ pub enum PhoenixCLICommand {
4745
#[clap(short, long, required = false)]
4846
trader_pubkey: Option<Pubkey>,
4947
},
50-
/// Send a transaction on chain to allocate a seat for the payer on the given market. This will cost ~.0018 SOL for rent.
51-
/// Note that the seat will have to then be approved by the market authority.
48+
/// Send a transaction on chain to allocate a seat for the payer on the given market. This will cost ~.0018 SOL for rent.
49+
/// Note that the seat will have to then be approved by the market authority. Only relevant for permissioned markets.
50+
/// For permissionless markets (with an automated seat manager), you can claim a seat with the claim-seat CLI command.
5251
RequestSeat { market_pubkey: Pubkey },
5352
/// Mint tokens to a recipient for a given ticker string (for example SOL or USDC). Default amount is 100_000_000_000.
54-
/// This is only for markets associated with the ellipsis token faucet.
53+
/// This is only for markets associated with the ellipsis token faucet.
5554
MintTokens {
5655
/// Ticker string, example: SOL
5756
mint_ticker: String,
@@ -62,7 +61,7 @@ pub enum PhoenixCLICommand {
6261
amount: u64,
6362
},
6463
/// Mint both base and quote tokens to a recipient for a given market. Default amounts are 100_000_000_000 for base and 100_000_000 for quote.
65-
/// This is only for markets associated with the ellipsis token faucet.
64+
/// This is only for markets associated with the ellipsis token faucet.
6665
MintTokensForMarket {
6766
market_pubkey: Pubkey,
6867
/// Pubkey of the recipient of the tokens
@@ -74,4 +73,16 @@ pub enum PhoenixCLICommand {
7473
#[clap(short, long, required = false, default_value = "100000000")]
7574
quote_amount: u64,
7675
},
76+
/// For the given market, get the seat manager data fields, including authority, successor, and designated market makers.
77+
GetSeatManagerInfo { market_pubkey: Pubkey },
78+
/// On the given market, claim a maker seat for the public key of the keypair at the indicated file path.
79+
/// Indicate a different keypair file to use by specifying the file path with flag `-k`.
80+
ClaimSeat { market_pubkey: Pubkey },
81+
/// Evict a trader from the given market if that market's trader state is at capacity.
82+
/// If no trader is given, this function will greedily find a trader to evict.
83+
/// Note that eviction will not work if the market's trader state is not at capacity.
84+
EvictSeat {
85+
market_pubkey: Pubkey,
86+
trader_to_evict: Option<Pubkey>,
87+
},
7788
}

src/lib/helpers/market_helpers.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use phoenix::state::markets::{Ladder, Market};
88
use phoenix::state::OrderPacket;
99

1010
use phoenix_sdk::sdk_client::*;
11+
use phoenix_seat_manager::get_seat_manager_address;
12+
use phoenix_seat_manager::seat_manager::SeatManager;
1113
use solana_account_decoder::UiAccountEncoding;
1214
use solana_client::rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig};
1315
use solana_client::rpc_filter::{Memcmp, MemcmpEncodedBytes, RpcFilterType};
@@ -202,3 +204,21 @@ pub async fn get_market_header(
202204

203205
Ok(*header)
204206
}
207+
208+
pub async fn get_seat_manager_data_with_market(
209+
client: &EllipsisClient,
210+
market: &Pubkey,
211+
) -> anyhow::Result<SeatManager> {
212+
let seat_manager_address = get_seat_manager_address(market).0;
213+
get_seat_manager_data_with_pubkey(client, &seat_manager_address).await
214+
}
215+
216+
pub async fn get_seat_manager_data_with_pubkey(
217+
client: &EllipsisClient,
218+
seat_manager_pubkey: &Pubkey,
219+
) -> anyhow::Result<SeatManager> {
220+
let seat_manager_account = client.get_account(seat_manager_pubkey).await?;
221+
let seat_manager_data = SeatManager::load(&seat_manager_account.data)?;
222+
223+
Ok(*seat_manager_data)
224+
}

src/lib/processor/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
pub mod process_claim_seat;
2+
pub mod process_evict_seat;
13
pub mod process_get_all_markets;
24
pub mod process_get_book_levels;
35
pub mod process_get_full_book;
46
pub mod process_get_market;
57
pub mod process_get_market_status;
68
pub mod process_get_open_orders;
79
pub mod process_get_seat_info;
10+
pub mod process_get_seat_manager_info;
811
pub mod process_get_top_of_book;
912
pub mod process_get_traders_for_market;
1013
pub mod process_get_transaction;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use ellipsis_client::EllipsisClient;
2+
use phoenix_sdk::utils::create_claim_seat_ix_if_needed;
3+
use solana_sdk::{pubkey::Pubkey, signer::Signer};
4+
5+
pub async fn process_claim_seat(
6+
client: &EllipsisClient,
7+
market_pubkey: &Pubkey,
8+
) -> anyhow::Result<()> {
9+
let claim_seat_ix =
10+
create_claim_seat_ix_if_needed(client, market_pubkey, &client.payer.pubkey()).await?;
11+
println!("Claiming seat for pubkey: {}", client.payer.pubkey());
12+
13+
if !claim_seat_ix.is_empty() {
14+
let tx = client.sign_send_instructions(claim_seat_ix, vec![]).await?;
15+
println!("Claim seat transaction: {}", tx);
16+
} else {
17+
println!("Seat already created for pubkey: {}", client.payer.pubkey());
18+
}
19+
20+
Ok(())
21+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use std::mem::size_of;
2+
3+
use ellipsis_client::EllipsisClient;
4+
use phoenix::program::MarketHeader;
5+
use phoenix_sdk::utils::get_evictable_trader_ix;
6+
use phoenix_seat_manager::instruction_builders::{
7+
create_evict_seat_instruction, EvictTraderAccountBackup,
8+
};
9+
use solana_sdk::pubkey::Pubkey;
10+
11+
pub async fn process_evict_seat(
12+
client: &EllipsisClient,
13+
market_pubkey: &Pubkey,
14+
trader_to_evict: &Option<Pubkey>,
15+
) -> anyhow::Result<()> {
16+
let market_bytes = client.get_account_data(market_pubkey).await?;
17+
let (header_bytes, _market_bytes) = market_bytes.split_at(size_of::<MarketHeader>());
18+
let market_header = bytemuck::try_from_bytes::<MarketHeader>(header_bytes)
19+
.map_err(|e| anyhow::anyhow!("Error deserializing market header. Error: {:?}", e))?;
20+
21+
let maybe_evict_trader_ix = if let Some(trader_pubkey) = trader_to_evict {
22+
let evict_trader_state = EvictTraderAccountBackup {
23+
trader_pubkey: *trader_pubkey,
24+
base_token_account_backup: None,
25+
quote_token_account_backup: None,
26+
};
27+
Some(create_evict_seat_instruction(
28+
market_pubkey,
29+
&market_header.base_params.mint_key,
30+
&market_header.quote_params.mint_key,
31+
trader_pubkey,
32+
vec![evict_trader_state],
33+
))
34+
} else {
35+
get_evictable_trader_ix(client, market_pubkey).await?
36+
};
37+
38+
if let Some(evict_trader_ix) = maybe_evict_trader_ix {
39+
println!("Evicting trader: {}", evict_trader_ix.accounts[13].pubkey);
40+
let tx = client
41+
.sign_send_instructions(vec![evict_trader_ix], vec![])
42+
.await?;
43+
println!("Evict trader tx: {}", tx);
44+
} else {
45+
println!("Cannot evict a trader when the market's trader state is not full.");
46+
return Ok(());
47+
}
48+
49+
Ok(())
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use std::mem::size_of;
2+
3+
use ellipsis_client::EllipsisClient;
4+
use phoenix::program::MarketHeader;
5+
use phoenix_seat_manager::{get_seat_manager_address, seat_manager::SeatManager};
6+
use solana_sdk::pubkey::Pubkey;
7+
8+
use crate::helpers::market_helpers::get_seat_manager_data_with_market;
9+
10+
pub async fn process_get_seat_manager_info(
11+
client: &EllipsisClient,
12+
market_pubkey: &Pubkey,
13+
) -> anyhow::Result<()> {
14+
let seat_manager_address = get_seat_manager_address(market_pubkey).0;
15+
let market_data = client.get_account_data(market_pubkey).await?;
16+
let market_header =
17+
bytemuck::from_bytes::<MarketHeader>(market_data.split_at(size_of::<MarketHeader>()).0);
18+
if market_header.authority != seat_manager_address {
19+
println!(
20+
"Authority for Market {} is not the seat manager.",
21+
market_pubkey
22+
);
23+
println!("Market authority: {}", market_header.authority);
24+
println!("Seat manager address: {}", seat_manager_address);
25+
return Ok(());
26+
}
27+
let seat_manager_info = get_seat_manager_data_with_market(client, market_pubkey).await?;
28+
print_seat_manager_struct(&seat_manager_info, &seat_manager_address);
29+
Ok(())
30+
}
31+
32+
pub fn print_seat_manager_struct(seat_manager: &SeatManager, seat_manager_pubkey: &Pubkey) {
33+
println!("Seat Manager Address: {}", seat_manager_pubkey);
34+
println!("SM Market: {}", seat_manager.market);
35+
println!("SM Authority: {}", seat_manager.authority);
36+
println!("SM Successor: {}", seat_manager.successor);
37+
println!(
38+
"Number of designated market makers: {}",
39+
seat_manager.num_makers
40+
);
41+
42+
let dmms: Vec<&Pubkey> = seat_manager
43+
.designated_market_makers
44+
.iter()
45+
.filter(|&&dmm| dmm != Pubkey::default())
46+
.collect();
47+
if !dmms.is_empty() {
48+
println!("DMMs: {:?}", dmms);
49+
}
50+
}

src/main.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ use crate::command::PhoenixCLICommand;
44
use anyhow::anyhow;
55
use clap::Parser;
66
use ellipsis_client::EllipsisClient;
7+
use phoenix_cli_processor::processor::process_claim_seat::process_claim_seat;
8+
use phoenix_cli_processor::processor::process_evict_seat::process_evict_seat;
79
use phoenix_cli_processor::processor::{
810
process_get_all_markets::*, process_get_book_levels::*, process_get_full_book::*,
911
process_get_market::*, process_get_market_status::*, process_get_open_orders::*,
10-
process_get_seat_info::*, process_get_top_of_book::*, process_get_traders_for_market::*,
11-
process_get_transaction::*, process_mint_tokens::*, process_mint_tokens_for_market::*,
12-
process_request_seat::*,
12+
process_get_seat_info::*, process_get_seat_manager_info::*, process_get_top_of_book::*,
13+
process_get_traders_for_market::*, process_get_transaction::*, process_mint_tokens::*,
14+
process_mint_tokens_for_market::*, process_request_seat::*,
1315
};
1416
use phoenix_sdk::sdk_client::*;
1517
use solana_cli_config::{Config, ConfigInput, CONFIG_FILE};
@@ -154,6 +156,21 @@ async fn main() -> anyhow::Result<()> {
154156
)
155157
.await?
156158
}
159+
PhoenixCLICommand::GetSeatManagerInfo { market_pubkey } => {
160+
sdk.add_market(&market_pubkey).await?;
161+
process_get_seat_manager_info(&sdk.client, &market_pubkey).await?;
162+
}
163+
PhoenixCLICommand::ClaimSeat { market_pubkey } => {
164+
sdk.add_market(&market_pubkey).await?;
165+
process_claim_seat(&sdk.client, &market_pubkey).await?
166+
}
167+
PhoenixCLICommand::EvictSeat {
168+
market_pubkey,
169+
trader_to_evict,
170+
} => {
171+
sdk.add_market(&market_pubkey).await?;
172+
process_evict_seat(&sdk.client, &market_pubkey, &trader_to_evict).await?
173+
}
157174
}
158175

159176
Ok(())

0 commit comments

Comments
 (0)