Skip to content

Commit

Permalink
Add quoteId parameter to orders (#231)
Browse files Browse the repository at this point in the history
Partially fulfills #170

This PR adds the ability to set the quoteId parameter while creating Orders. This way the order can be linked to a quote and enable providing more metadata when analyzing order slippage.

Currently, it doesn't involve interaction with the Database i.e. Storing or retrieving the quoteId. This will be a part of a separate PR.

Also api/v1/quote now also returns an ID. Currently, implemented as a counter which gets reset on orderbook restarts.

Users can now pass an optional parameter quoteId while creating orders for easier debugging.
  • Loading branch information
ahhda authored May 30, 2022
1 parent 5e2f927 commit 6581af3
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 132 deletions.
1 change: 1 addition & 0 deletions crates/model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod app_id;
pub mod auction;
pub mod bytes_hex;
pub mod order;
pub mod quote;
pub mod ratio_as_decimal;
pub mod signature;
pub mod solver_competition;
Expand Down
3 changes: 3 additions & 0 deletions crates/model/src/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::{
app_id::AppId,
quote::QuoteId,
signature::{EcdsaSignature, EcdsaSigningScheme, Signature},
u256_decimal::{self, DecimalU256},
DomainSeparator, TokenPair,
Expand Down Expand Up @@ -283,10 +284,12 @@ pub struct OrderCreation {
}

#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderCreationPayload {
#[serde(flatten)]
pub order_creation: OrderCreation,
pub from: Option<H160>,
pub quote_id: Option<QuoteId>,
}

impl Default for OrderCreation {
Expand Down
126 changes: 126 additions & 0 deletions crates/model/src/quote.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use crate::{
app_id::AppId,
order::{BuyTokenDestination, OrderKind, SellTokenSource},
signature::SigningScheme,
u256_decimal,
};
use chrono::{DateTime, Utc};
use primitive_types::{H160, U256};
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum PriceQuality {
Fast,
Optimal,
}

impl Default for PriceQuality {
fn default() -> Self {
Self::Optimal
}
}

/// The order parameters to quote a price and fee for.
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct OrderQuoteRequest {
pub from: H160,
pub sell_token: H160,
pub buy_token: H160,
pub receiver: Option<H160>,
#[serde(flatten)]
pub side: OrderQuoteSide,
pub valid_to: u32,
pub app_data: AppId,
pub partially_fillable: bool,
#[serde(default)]
pub sell_token_balance: SellTokenSource,
#[serde(default)]
pub buy_token_balance: BuyTokenDestination,
#[serde(default)]
pub signing_scheme: SigningScheme,
#[serde(default)]
pub price_quality: PriceQuality,
}

#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum OrderQuoteSide {
#[serde(rename_all = "camelCase")]
Sell {
#[serde(flatten)]
sell_amount: SellAmount,
},
#[serde(rename_all = "camelCase")]
Buy {
#[serde(with = "u256_decimal")]
buy_amount_after_fee: U256,
},
}

impl Default for OrderQuoteSide {
fn default() -> Self {
Self::Buy {
buy_amount_after_fee: U256::one(),
}
}
}

#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
pub enum SellAmount {
BeforeFee {
#[serde(rename = "sellAmountBeforeFee", with = "u256_decimal")]
value: U256,
},
AfterFee {
#[serde(rename = "sellAmountAfterFee", with = "u256_decimal")]
value: U256,
},
}

/// The quoted order by the service.
#[derive(Clone, Debug, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderQuote {
pub sell_token: H160,
pub buy_token: H160,
pub receiver: Option<H160>,
#[serde(with = "u256_decimal")]
pub sell_amount: U256,
#[serde(with = "u256_decimal")]
pub buy_amount: U256,
pub valid_to: u32,
pub app_data: AppId,
#[serde(with = "u256_decimal")]
pub fee_amount: U256,
pub kind: OrderKind,
pub partially_fillable: bool,
pub sell_token_balance: SellTokenSource,
pub buy_token_balance: BuyTokenDestination,
}

pub type QuoteId = u64;

#[derive(Clone, Debug, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderQuoteResponse {
pub quote: OrderQuote,
pub from: H160,
pub expiration: DateTime<Utc>,
pub id: QuoteId,
}

impl OrderQuoteRequest {
/// This method is used by the old, deprecated, fee endpoint to convert {Buy, Sell}Requests
pub fn new(sell_token: H160, buy_token: H160, side: OrderQuoteSide) -> Self {
Self {
sell_token,
buy_token,
side,
valid_to: u32::MAX,
..Default::default()
}
}
}
25 changes: 21 additions & 4 deletions crates/orderbook/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -551,15 +551,15 @@ components:
SellTokenSource:
description: Where should the sell token be drawn from?
type: string
enum: [ erc20, internal, external ]
enum: [erc20, internal, external]
BuyTokenDestination:
description: Where should the buy token be transfered to?
type: string
enum: [ erc20, internal ]
enum: [erc20, internal]
PriceQuality:
description: How good should the price estimate be?
type: string
enum: [ fast, optimal ]
enum: [fast, optimal]
OrderStatus:
description: The current order status
type: string
Expand Down Expand Up @@ -641,6 +641,12 @@ components:
any balance.
$ref: "#/components/schemas/Address"
nullable: true
quoteId:
description: |
Orders can optionally include a quote ID. This way the order can be linked to a quote
and enable providing more metadata when analyzing order slippage.
type: integer
nullable: true
required:
- signingScheme
- signature
Expand Down Expand Up @@ -892,7 +898,13 @@ components:
properties:
errorType:
type: string
enum: ["NoLiquidity", "UnsupportedToken", "AmountIsZero", "SellAmountDoesNotCoverFee"]
enum:
[
"NoLiquidity",
"UnsupportedToken",
"AmountIsZero",
"SellAmountDoesNotCoverFee",
]
description:
type: string
required:
Expand Down Expand Up @@ -1003,6 +1015,11 @@ components:
the fee after this expiration date. Encoded as ISO 8601 UTC.
type: string
example: "1985-03-10T18:35:18.814523Z"
id:
description: |
Order ID linked to a quote to enable providing more metadata when analyzing
order slippage.
type: integer
SolverCompetitionResponse:
type: object
properties:
Expand Down
3 changes: 2 additions & 1 deletion crates/orderbook/src/api/create_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ pub fn create_order(
create_order_request().and_then(move |order_payload: OrderCreationPayload| {
let orderbook = orderbook.clone();
async move {
let quote_id = order_payload.quote_id;
let result = orderbook.add_order(order_payload).await;
if let Ok(order_uid) = result {
tracing::debug!("order created with uid {}", order_uid);
tracing::debug!(%order_uid, ?quote_id, "order created");
}
Result::<_, Infallible>::Ok(create_order_response(result))
}
Expand Down
10 changes: 5 additions & 5 deletions crates/orderbook/src/api/get_fee_and_quote.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::api::{
convert_json_response,
post_quote::{OrderQuoteRequest, OrderQuoteResponse, OrderQuoteSide, OrderQuoter, SellAmount},
};
use crate::api::{convert_json_response, post_quote::OrderQuoter};
use anyhow::Result;
use chrono::{DateTime, Utc};
use ethcontract::{H160, U256};
use model::u256_decimal;
use model::{
quote::{OrderQuoteRequest, OrderQuoteResponse, OrderQuoteSide, SellAmount},
u256_decimal,
};
use serde::{Deserialize, Serialize};
use std::{convert::Infallible, sync::Arc};
use warp::{Filter, Rejection};
Expand Down
Loading

0 comments on commit 6581af3

Please sign in to comment.