diff --git a/programs/mango-v4/src/instructions/perp_place_order.rs b/programs/mango-v4/src/instructions/perp_place_order.rs index d08dd5212..fedd4d92f 100644 --- a/programs/mango-v4/src/instructions/perp_place_order.rs +++ b/programs/mango-v4/src/instructions/perp_place_order.rs @@ -84,7 +84,8 @@ pub fn perp_place_order(ctx: Context, order: Order, limit: u8) - let now_ts = Clock::get()?.unix_timestamp as u64; - // TODO reduce_only based on event queue + // TODO apply reduce_only flag to compute final base_lots, also process event queue + require!(order.reduce_only == false, MangoError::SomeError); book.new_order( order, diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index 4ace73043..a4344d02d 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -505,6 +505,7 @@ pub mod mango_v4 { max_quote_lots: i64, client_order_id: u64, order_type: PlaceOrderType, + reduce_only: bool, // Timestamp of when order expires // @@ -534,6 +535,7 @@ pub mod mango_v4 { max_base_lots, max_quote_lots, client_order_id, + reduce_only, time_in_force, params: match order_type { PlaceOrderType::Market => OrderParams::Market, @@ -566,6 +568,7 @@ pub mod mango_v4 { max_quote_lots: i64, client_order_id: u64, order_type: PlaceOrderType, + reduce_only: bool, // Timestamp of when order expires // @@ -595,6 +598,7 @@ pub mod mango_v4 { max_base_lots, max_quote_lots, client_order_id, + reduce_only, time_in_force, params: OrderParams::OraclePegged { price_offset_lots, diff --git a/programs/mango-v4/src/state/orderbook/order.rs b/programs/mango-v4/src/state/orderbook/order.rs index 4a38dc2f5..8e3823a0b 100644 --- a/programs/mango-v4/src/state/orderbook/order.rs +++ b/programs/mango-v4/src/state/orderbook/order.rs @@ -16,6 +16,9 @@ pub struct Order { /// Arbitrary user-controlled order id. pub client_order_id: u64, + /// Reduce only + pub reduce_only: bool, + /// Number of seconds the order shall live, 0 meaning forever pub time_in_force: u8, diff --git a/programs/mango-v4/tests/program_test/mango_client.rs b/programs/mango-v4/tests/program_test/mango_client.rs index 7e441d34b..37e81fd15 100644 --- a/programs/mango-v4/tests/program_test/mango_client.rs +++ b/programs/mango-v4/tests/program_test/mango_client.rs @@ -2402,7 +2402,8 @@ impl ClientInstruction for PerpPlaceOrderInstruction { max_base_lots: self.max_base_lots, max_quote_lots: self.max_quote_lots, client_order_id: self.client_order_id, - order_type: PlaceOrderType::Limit, + order_type: OrderType::Limit, + reduce_only: false, expiry_timestamp: 0, limit: 10, }; diff --git a/ts/client/src/client.ts b/ts/client/src/client.ts index 596d5909f..8f62d4fc1 100644 --- a/ts/client/src/client.ts +++ b/ts/client/src/client.ts @@ -1617,6 +1617,7 @@ export class MangoClient { maxQuoteQuantity: number | undefined, clientOrderId: number | undefined, orderType: PerpOrderType | undefined, + reduceOnly: boolean | undefined, expiryTimestamp: number | undefined, limit: number | undefined, ): Promise { @@ -1633,6 +1634,7 @@ export class MangoClient { maxQuoteQuantity, clientOrderId, orderType, + reduceOnly, expiryTimestamp, limit, ), @@ -1654,6 +1656,7 @@ export class MangoClient { maxQuoteQuantity?: number, clientOrderId?: number, orderType?: PerpOrderType, + reduceOnly?: boolean, expiryTimestamp?: number, limit?: number, ): Promise { @@ -1677,6 +1680,7 @@ export class MangoClient { : I64_MAX_BN, new BN(clientOrderId ? clientOrderId : Date.now()), orderType ? orderType : PerpOrderType.limit, + reduceOnly ? reduceOnly : false, new BN(expiryTimestamp ? expiryTimestamp : 0), limit ? limit : 10, ) diff --git a/ts/client/src/mango_v4.ts b/ts/client/src/mango_v4.ts index e32afc98f..2d394247a 100644 --- a/ts/client/src/mango_v4.ts +++ b/ts/client/src/mango_v4.ts @@ -2754,6 +2754,10 @@ export type MangoV4 = { "defined": "PlaceOrderType" } }, + { + "name": "reduceOnly", + "type": "bool" + }, { "name": "expiryTimestamp", "type": "u64" @@ -9583,6 +9587,10 @@ export const IDL: MangoV4 = { "defined": "PlaceOrderType" } }, + { + "name": "reduceOnly", + "type": "bool" + }, { "name": "expiryTimestamp", "type": "u64" diff --git a/ts/client/src/scripts/devnet-user.ts b/ts/client/src/scripts/devnet-user.ts index 6b1b7e94b..81a747db7 100644 --- a/ts/client/src/scripts/devnet-user.ts +++ b/ts/client/src/scripts/devnet-user.ts @@ -471,6 +471,7 @@ async function main() { quoteQty, clientId, PerpOrderType.limit, + false, 0, //Date.now() + 200, 1, ); @@ -513,6 +514,7 @@ async function main() { quoteQty, clientId, PerpOrderType.limit, + false, 0, //Date.now() + 200, 1, ); @@ -553,6 +555,7 @@ async function main() { quoteQty, clientId, PerpOrderType.limit, + false, 0, //Date.now() + 200, 1, ); @@ -584,6 +587,7 @@ async function main() { quoteQty, clientId, PerpOrderType.limit, + false, 0, //Date.now() + 200, 1, ); @@ -618,6 +622,7 @@ async function main() { price * 0.01, clientId, PerpOrderType.limit, + false, 0, //Date.now() + 200, 1, ); @@ -639,6 +644,7 @@ async function main() { price * 0.011, clientId, PerpOrderType.limit, + false, 0, //Date.now() + 200, 1, ); diff --git a/ts/client/src/scripts/mb-liqtest-make-candidates.ts b/ts/client/src/scripts/mb-liqtest-make-candidates.ts index 850643b4d..a8656b90f 100644 --- a/ts/client/src/scripts/mb-liqtest-make-candidates.ts +++ b/ts/client/src/scripts/mb-liqtest-make-candidates.ts @@ -238,6 +238,7 @@ async function main() { 0.044, // ui quote quantity 4200, PerpOrderType.limit, + false, 0, 5, ); @@ -281,6 +282,7 @@ async function main() { 0.044, // ui quote quantity 4200, PerpOrderType.limit, + false, 0, 5, ); @@ -295,6 +297,7 @@ async function main() { 0.044, // ui quote quantity 4200, PerpOrderType.market, + false, 0, 5, ); @@ -358,6 +361,7 @@ async function main() { 0.022, // ui quote quantity 4200, PerpOrderType.limit, + false, 0, 5, ); @@ -371,6 +375,7 @@ async function main() { 0.022, // ui quote quantity 4200, PerpOrderType.market, + false, 0, 5, ); @@ -391,6 +396,7 @@ async function main() { 0.044, // ui quote quantity 4201, PerpOrderType.limit, + false, 0, 5, ); @@ -404,6 +410,7 @@ async function main() { 0.044, // ui quote quantity 4201, PerpOrderType.market, + false, 0, 5, ); diff --git a/ts/client/src/scripts/mm/taker.ts b/ts/client/src/scripts/mm/taker.ts index 34766e80e..14e279d48 100644 --- a/ts/client/src/scripts/mm/taker.ts +++ b/ts/client/src/scripts/mm/taker.ts @@ -56,6 +56,7 @@ async function takeOrder( undefined, Date.now(), PerpOrderType.market, + false, 0, 10, );