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

Fee Policies API #2809

Merged
merged 16 commits into from
Jul 18, 2024
Merged

Fee Policies API #2809

merged 16 commits into from
Jul 18, 2024

Conversation

squadgazzz
Copy link
Contributor

@squadgazzz squadgazzz commented Jul 12, 2024

Description

Includes policy fees in the /trades API associated with the trade/order.

Changes

More details are in the PR comments.

How to test

Existing and new tests.

Related Issues

Fixes #2642

num::BigUint,
primitive_types::{H160, H256},
serde::{Deserialize, Serialize},
serde_with::{serde_as, DisplayFromStr},
};

#[serde_as]
#[derive(Eq, PartialEq, Clone, Debug, Default, Deserialize, Serialize)]
#[derive(PartialEq, Clone, Debug, Default, Deserialize, Serialize)]
Copy link
Contributor Author

@squadgazzz squadgazzz Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eq was removed since FeePolicy contains f64 fields that don't derive this trait. Also, couldn't find a reason why this was required.

@squadgazzz squadgazzz marked this pull request as ready for review July 12, 2024 08:50
@squadgazzz squadgazzz requested a review from a team as a code owner July 12, 2024 08:50
Copy link
Contributor

@sunce86 sunce86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a good approach.

Copy link
Contributor

@fleupold fleupold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite having additional comments in the PR, I think the description should contain a clear overview for the reviewer and future reader of the change summarising of the core challenge faced here, the different options considered and why the one that was chosen prevailed.

IMO, we should keep our queries very lean and basic (ie pretty straight forward "fetch raw data") and do joins and filtering logic in the rust code (unless there is very big performance considerations, which I don't believe is the case here).
Otherwise we will stand in front of a monumental challenge the day we need to move away from postgres (which will likely come at some point as we scale and receive more and more orders).

Concretely, here this would mean to first fetch the trades and then fetch the fee policies in a second roundtrip by using the order and auction ids.

@squadgazzz
Copy link
Contributor Author

IMO, we should keep our queries very lean and basic (ie pretty straight forward "fetch raw data") and do joins and filtering logic in the rust code (unless there is very big performance considerations, which I don't believe is the case here).

Makes sense. Initially, it looked like a tiny change, but due to sqlx limitations, it is now more complex than expected. Will separate the queries.

crates/database/src/trades.rs Outdated Show resolved Hide resolved
crates/database/src/byte_array.rs Outdated Show resolved Hide resolved
@squadgazzz squadgazzz marked this pull request as draft July 15, 2024 11:14
@squadgazzz squadgazzz marked this pull request as ready for review July 15, 2024 16:26
@squadgazzz
Copy link
Contributor Author

Got rid of the additional complexity, as Felix suggested. Now it uses 3 SQL queries instead of a single one. There is an option to include the quote fetching right into the trades SQL query, but semantically, the quote is required for the policy fee where the latter is no longer a part of the trades SQL.

Copy link
Contributor

@fleupold fleupold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach looks good. Some questions around inconsistencies and combining the third roundtrip to the db (fetching all required quotes at once)

crates/database/src/trades.rs Show resolved Hide resolved
};

#[async_trait::async_trait]
pub trait FeePolicyRetrieving: Send + Sync {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this trait if there is only a single impl?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required, removed.

.with_label_values(&["order_quote"])
.start_timer();

let order_quote = database::orders::read_quote(&mut ex, &order_uid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be collected and then fetched in a single roundtrip imo (can use existing read_quotes).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, reworked.

crates/model/src/fee_policy.rs Outdated Show resolved Hide resolved
@@ -1,5 +1,6 @@
pub mod app_data;
pub mod auctions;
mod fee_policy;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this is the only module that's using singular (c.f auctions, trades, etc).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed.

@squadgazzz squadgazzz mentioned this pull request Jul 16, 2024
2 tasks
async move {
match trade.auction_id {
Some(auction_id) => {
self.fee_policies(auction_id, trade.order_uid, quote).await
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a single roundtrip (fetch fee policies for a list of auction/order pairs) and then only for the ones that require a quote we fetch the quote (in another roundtrip)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with a single roundtrip.

if i > 0 {
query_builder.push(" OR ");
}
query_builder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not to use format!() instead? it has many string reallocation...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use QueryBuilder for such cases as the most convenient option, which should be safe since it uses write! macro under the hood.

) -> anyhow::Result<HashMap<(AuctionId, OrderUid), Vec<FeePolicy>>> {
let mut ex = self.pool.acquire().await?;

let _timer = super::Metrics::get()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it this timer stopped?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, forgot to stop it after refactoring.

@squadgazzz squadgazzz force-pushed the fee-policy-api branch 2 times, most recently from a6bebad to 22bac33 Compare July 16, 2024 16:46
Copy link
Contributor

@MartinquaXD MartinquaXD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nits

crates/orderbook/openapi.yml Outdated Show resolved Hide resolved
"missing price improvement quote for order '{:?}'",
order_uid
))?;
let fee = quote.gas_amount * quote.gas_price / quote.sell_token_price;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function already supports error handling so I would suggest to use checked_div() here just to be safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. Used BigRational.

crates/database/src/fee_policies.rs Outdated Show resolved Hide resolved
crates/model/src/fee_policy.rs Outdated Show resolved Hide resolved
crates/orderbook/src/database/trades.rs Outdated Show resolved Hide resolved
@squadgazzz squadgazzz changed the title Fee Policy API Fee Policies API Jul 17, 2024
@sunce86 sunce86 merged commit 9473850 into main Jul 18, 2024
10 checks passed
@sunce86 sunce86 deleted the fee-policy-api branch July 18, 2024 09:36
@github-actions github-actions bot locked and limited conversation to collaborators Jul 18, 2024
PriceImprovement {
factor: f64,
max_volume_factor: f64,
quote: Quote,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this is not documented in the openapi.yml definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: Make protocol fee accessible via orderbook API
6 participants