Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

program: add cancelOrdersByPrice #1197

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,77 @@ pub fn cancel_orders(
Ok(canceled_order_ids)
}

pub fn cancel_orders_by_price(
user: &mut User,
user_key: &Pubkey,
perp_market_map: &PerpMarketMap,
spot_market_map: &SpotMarketMap,
oracle_map: &mut OracleMap,
now: i64,
slot: u64,
direction: Option<PositionDirection>,
max_price: Option<u64>,
min_price: Option<u64>,
) -> DriftResult {

// check max_price or min_price is set
if max_price.is_none() && min_price.is_none() {
return Err(ErrorCode::MissingPriceParameters);
}

for order_index in 0..user.orders.len() {
// get cur order
let order = &user.orders[order_index];

// check open
if order.status != OrderStatus::Open {
continue;
}

// check direction
if let Some(direction) = direction{
if order.direction != direction {
continue;
}
}


// filter by price
if let Some(max_price) = max_price {
if order.price <= max_price {
continue;
}
}

if let Some(min_price) = min_price {
if order.price >= min_price {
continue;
}
}

// cancel order
cancel_order(
order_index,
user,
user_key,
perp_market_map,
spot_market_map,
oracle_map,
now,
slot,
OrderActionExplanation::None,
None,
0,
false,
)?;
}

user.update_last_active_slot(slot);

Ok(())
}


pub fn cancel_order_by_order_id(
order_id: u32,
user: &AccountLoader<User>,
Expand Down
2 changes: 2 additions & 0 deletions programs/drift/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,8 @@ pub enum ErrorCode {
LiquidationOrderFailedToFill,
#[msg("Invalid prediction market order")]
InvalidPredictionMarketOrder,
#[msg("Missing both maximum and minimum price parameters.")]
MissingPriceParameters,
}

#[macro_export]
Expand Down
44 changes: 44 additions & 0 deletions programs/drift/src/instructions/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,50 @@ pub fn handle_cancel_orders_by_ids<'c: 'info, 'info>(
Ok(())
}

#[access_control(
exchange_not_paused(&ctx.accounts.state)
)]
pub fn handle_cancel_orders_by_price<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, CancelOrder>,
max_price: Option<u64>,
min_price: Option<u64>,
direction: Option<PositionDirection>,
) -> Result<()> {
let clock = &Clock::get()?;
let state = &ctx.accounts.state;

let AccountMaps {
perp_market_map,
spot_market_map,
mut oracle_map,
} = load_maps(
&mut ctx.remaining_accounts.iter().peekable(),
&MarketSet::new(),
&MarketSet::new(),
clock.slot,
Some(state.oracle_guard_rails),
)?;

let user_key = ctx.accounts.user.key();
let mut user = load_mut!(ctx.accounts.user)?;

controller::orders::cancel_orders_by_price(
&mut user,
&user_key,
&perp_market_map,
&spot_market_map,
&mut oracle_map,
clock.unix_timestamp,
clock.slot,
direction,
max_price,
min_price,
)?;

Ok(())

}

#[access_control(
exchange_not_paused(&ctx.accounts.state)
)]
Expand Down
9 changes: 9 additions & 0 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ pub mod drift {
handle_cancel_order_by_user_id(ctx, user_order_id)
}

pub fn cancel_orders_by_price<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, CancelOrder>,
max_price: Option<u64>,
min_price: Option<u64>,
direction: Option<PositionDirection>,
) -> Result<()> {
handle_cancel_orders_by_price(ctx, max_price, min_price, direction)
}

pub fn cancel_orders<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, CancelOrder<'info>>,
market_type: Option<MarketType>,
Expand Down
51 changes: 51 additions & 0 deletions sdk/src/driftClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3355,6 +3355,57 @@ export class DriftClient {
});
}

public async cancelOrdersByPrice(
direction: PositionDirection,
maxPrice?: BN,
minPrice?: BN,
txParams?: TxParams,
subAccountId?: number
): Promise<TransactionSignature> {
const { txSig } = await this.sendTransaction(
await this.buildTransaction(
await this.getCancelOrdersByPriceIx(
direction,
maxPrice,
minPrice,
subAccountId
),
txParams
),
[],
this.opts
);
return txSig;
}

public async getCancelOrdersByPriceIx(
direction: PositionDirection,
maxPrice?: BN,
minPrice?: BN,
subAccountId?: number
): Promise<TransactionInstruction> {
const user = await this.getUserAccountPublicKey(subAccountId);

const remainingAccounts = this.getRemainingAccounts({
userAccounts: [this.getUserAccount(subAccountId)],
useMarketLastSlotCache: true,
});

return await this.program.instruction.cancelOrdersByPrice(
maxPrice || null,
minPrice || null,
direction,
{
accounts: {
state: await this.getStatePublicKey(),
user,
authority: this.wallet.publicKey,
},
remainingAccounts,
}
);
}

public async cancelOrders(
marketType?: MarketType,
marketIndex?: number,
Expand Down
Loading