diff --git a/openapi/openapi.json b/openapi/openapi.json index 3e87f02..2d80d1e 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -261,7 +261,8 @@ "amount", "tokenOut", "quoteType", - "protocol" + "protocol", + "feeBps" ], "properties": { "amount": { @@ -270,6 +271,17 @@ "250000000" ] }, + "feeBps": { + "type": "integer", + "format": "int32", + "description": "Fee in basis points to be charged by the Market Maker", + "examples": [ + "1", + "20" + ], + "maximum": 10000, + "minimum": 0 + }, "protocol": { "$ref": "#/components/schemas/Protocol" }, @@ -499,4 +511,4 @@ "description": "Webhook API for RFQ providers" } ] -} \ No newline at end of file +} diff --git a/order-engine-sdk/src/fill.rs b/order-engine-sdk/src/fill.rs index 73ef42d..da95537 100644 --- a/order-engine-sdk/src/fill.rs +++ b/order-engine-sdk/src/fill.rs @@ -97,7 +97,7 @@ pub fn validate_fill_sanitized_message( ensure!(data.len() >= 8, "Not enough data in fill instruction"); // Must slice off anchor's discriminator first - let (discriminator, ix_data) = data.split_at(8); + let (discriminator, mut ix_data) = data.split_at(8); ensure!( discriminator == order_engine::client::args::Fill::DISCRIMINATOR, "Not a fill discriminator" @@ -116,7 +116,7 @@ pub fn validate_fill_sanitized_message( ensure!(input_mint == &order.input_mint, "Invalid input mint"); ensure!(output_mint == &order.output_mint, "Invalid output mint"); - let fill_ix = order_engine::client::args::Fill::try_from_slice(ix_data) + let fill_ix = order_engine::client::args::Fill::deserialize(&mut ix_data) .map_err(|e| anyhow!("Invalid fill ix data {e}"))?; // Check the input and output amount @@ -250,13 +250,13 @@ pub fn validate_similar_fill_sanitized_message( "Duplicated fill instruction" ); ensure!(data.len() >= 8, "Not enough data in fill instruction"); - let (discriminator, ix_data) = data.split_at(8); + let (discriminator, mut ix_data) = data.split_at(8); ensure!( discriminator == order_engine::client::args::Fill::DISCRIMINATOR, "Not a fill discriminator" ); - let fill_ix = order_engine::client::args::Fill::try_from_slice(ix_data) + let fill_ix = order_engine::client::args::Fill::deserialize(&mut ix_data) .map_err(|e| anyhow!("Invalid fill ix data {e}"))?; // We check if the taker has enough balance to fill the order first let taker = accounts.first().context("Invalid fill ix data")?.pubkey; diff --git a/programs/order-engine/tests/test_fill.rs b/programs/order-engine/tests/test_fill.rs index 719a5a9..9d742df 100644 --- a/programs/order-engine/tests/test_fill.rs +++ b/programs/order-engine/tests/test_fill.rs @@ -223,13 +223,17 @@ impl TestEnvironment { temporary_wsol_token_account, .. } = self; - let data = order_engine::instruction::Fill { + let mut data = order_engine::instruction::Fill { input_amount: *input_amount, output_amount: *output_amount, expire_at: i64::MAX, } .data(); + // TODO: unused data to track fee_bps + let fee_bps: u16 = 0; + data.extend(fee_bps.to_le_bytes()); + let mut instruction = Instruction { program_id: order_engine::ID, accounts: order_engine::accounts::Fill { diff --git a/webhook-api/src/enums.rs b/webhook-api/src/enums.rs index a5f3e39..76e631b 100644 --- a/webhook-api/src/enums.rs +++ b/webhook-api/src/enums.rs @@ -2,14 +2,18 @@ use serde::{Deserialize, Serialize}; use strum::{Display, EnumString}; use utoipa::ToSchema; -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema, EnumString)] +#[derive( + Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema, EnumString, Display, +)] #[serde(rename_all = "camelCase")] pub enum QuoteType { ExactIn, ExactOut, } -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema, EnumString)] +#[derive( + Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema, EnumString, Display, +)] #[serde(rename_all = "camelCase")] pub enum Protocol { V1, diff --git a/webhook-api/src/requests.rs b/webhook-api/src/requests.rs index c899149..5df1ac8 100644 --- a/webhook-api/src/requests.rs +++ b/webhook-api/src/requests.rs @@ -32,6 +32,9 @@ pub struct QuoteRequest { #[schema(examples("10000"))] #[serde(skip_serializing_if = "Option::is_none")] pub suggested_prioritization_fees: Option, + /// Fee in basis points to be charged by the Market Maker + #[schema(examples("1", "20"), maximum = 10_000)] + pub fee_bps: u16, } /// Order to be fulfilled by the Market Maker