-
Notifications
You must be signed in to change notification settings - Fork 24
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
feat: quotes-server #430
feat: quotes-server #430
Conversation
66dd6de
to
1623be6
Compare
|
||
message GetQuoteToBuyCentsRequest { | ||
oneof quote_for { | ||
uint64 amount_to_sell_in_sats = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one might want to "sell $100 worth of bitcoin", so the amount as an input should be dollar, not sats.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s what the next line is for. You can specify either the btc amount to sell or the USD amount to buy (your scenario). See the oneof keyword
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a different use case. yours is buy BTC with a USD amount
. the one I mention is sell BTC with a USD amount
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a matrix of 2x2x2 = 8 use cases.
The 3 binary variables are:
buy / sell USD
denominate amount in BTC / USB
execute immediately / execute in future
The api of the current price server has each of the 8 use cases as its own function call.
In this api I'm proposing to reduce the number of exposed endpoint to 2 (buy / sell) and pass the other binaries as function variables (denomination / execution).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If as a user, I request to sell $100 of bitcoin, but get credited 99.98 because of some math approximation and because if a mismatch of source of truth, then I would think there are hidden fees in here or that the system doesn't really work well.
If stablesats is going to be the source of truth, we can make those shortcuts because it would worsen the user experience and reduce trust in the system
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in your example the request would call GetQuoteToBuyCents(GetQuoteToBuyCentsRequest)
because we are buying USD (ie. selling bitcoin). But we want to denominate the amount in usd
($100 worth). That means in the oneof
argument I would specify the amount_to_buy_in_cents = 100
message GetQuoteToBuyCentsRequest {
oneof quote_for {
uint64 amount_to_sell_in_sats = 1;
uint64 amount_to_buy_in_cents = 2;
}
bool immediate_execution = 3;
}
=>
GetQUoteToBuyCentsRequest {
quote_for: { amount_to_buy_in_cents: 100 }
immediate_execution: false
}
This is the same way it works now with the GetSatsFromCentsForFutureBuy
call.
The only difference here is that we are passing some arguments instead of separating each method call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I misread the initial interface.
If I want to buy $100 of bitcoin, can I get a quote by passing a dollar amount?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes (see example above)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok.
I think message GetQuoteToBuyCentsRequest
would be better worded withmessage GetQuoteToBuyDollarRequest
or message GetQuoteToBuyStablesatsRequest
because otherwise it's a bit convoluted that we using cents as both the assets and unit of account.
This may be why I have been mis interpreting the API (I skimed through it and didnt' try to read it thoroughly)
@@ -4,6 +4,7 @@ members = [ | |||
"shared", | |||
"ledger", | |||
"price-server", | |||
"quotes-server", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it make sense to be different than the price server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Easier to immutably replace rather than try to merge legacy with new server IMO
proto/quotes/quote_service.proto
Outdated
rpc AcceptQuote(AcceptQuoteRequest) returns (AcceptQuoteResponse) {} | ||
} | ||
|
||
message GetQuoteToBuyCentsRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we don't support this as yet, but do we also want to be more specific about the currency we're dealing with here, or more generic about the unit somehow?
For e.g. if we decided to add Euros to stablesats in the future somehow, a quote could be for buying EurCents
or UsdCents
. There's also the possibility that we use a non-cent currency like GBP (penny) or JPY (no minor unit).
We can pivot on the currency codes instead and think about some way to genericize the minor unit we're using? E.g.:
GetQuoteToBuyUsdRequest
with a base and an offset for the request params / response fields?
Not sure if this is premature optimization though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Premature IMO.
Another general comment. I have the problem right now where it's not easy to reason about whether I'm using the right quote type for the right circumstance. I'd have to refer back to this test case to see how the different prices behave with spreads, and the implications for using the wrong method are that we open ourselves up to arbitrage attacks. I like that with these changes we explicitly have only 2 options, |
8ce0459
to
282f89a
Compare
282f89a
to
990ea90
Compare
a4aa81d
to
b95e5c3
Compare
direction direction_enum NOT NULL, | ||
immediate_execution BOOLEAN NOT NULL, | ||
sat_amount BIGINT NOT NULL, | ||
cent_amount BIGINT NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these need to be indexed?
quotes-server/src/quote/entity.rs
Outdated
@@ -3,6 +3,7 @@ use derive_builder::Builder; | |||
use serde::{Deserialize, Serialize}; | |||
|
|||
use crate::currency::*; | |||
use crate::EntityEvents; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't be exposed in top level. Also use crate::{..}
quotes-server/src/app/mod.rs
Outdated
.price_calculator | ||
.cents_from_sats_for_buy(Satoshis::from(sats), immediate_execution) | ||
.await?; | ||
let new_quote = NewQuote::builder() | ||
.direction(Direction::BuyCents) | ||
.immediate_execution(immediate_execution) | ||
.cent_amount(usd_amount) | ||
.sat_amount(Satoshis::from(sats)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant Satoshis::from
.. just set it to a local var the same you use line 77.
@@ -2,10 +2,13 @@ use thiserror::Error; | |||
|
|||
use shared::time::*; | |||
|
|||
use crate::cache::OrderBookCacheError; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newline missing?
quotes-server/tests/quotes_app.rs
Outdated
let quote = app | ||
.quote_cents_from_sats_for_buy(dec!(100_000_000), false) | ||
.await; | ||
tokio::time::sleep(std::time::Duration::from_secs(5)).await; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not 2? And magic number...
0b7ca7b
to
da7c5db
Compare
.await | ||
} | ||
|
||
pub async fn quotes_btc_liability(&self) -> Result<Option<AccountBalance>, LedgerError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btc is not a liability
quotes-server/src/app/config.rs
Outdated
} | ||
|
||
fn default_expiration_interval() -> Duration { | ||
const DEFAULT_EXPIRATION_INTERVAL: std::time::Duration = std::time::Duration::from_secs(120); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant const. default...
fn already identifies unique access point + its not shared outside of this file or even outside this function.
quotes-server/src/app/mod.rs
Outdated
.expect("Could not build quote"); | ||
let quote = self.quotes.create(new_quote).await?; | ||
if immediate_execution { | ||
self.accept_quote(quote.id).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to be in transaction
quotes-server/src/app/mod.rs
Outdated
.direction(Direction::BuyCents) | ||
.immediate_execution(immediate_execution) | ||
.cent_amount(usd_amount) | ||
.sat_amount(sats) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing cent_spread / sat_spread
quotes-server/src/app/mod.rs
Outdated
.expect("Could not build quote"); | ||
let quote = self.quotes.create(new_quote).await?; | ||
if immediate_execution { | ||
self.accept_quote(quote.id).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs to be in transactoi
quotes-server/src/app/mod.rs
Outdated
.expect("Could not build quote"); | ||
let quote = self.quotes.create(new_quote).await?; | ||
if immediate_execution { | ||
self.accept_quote(quote.id).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accept_quote(id) ->
accept_quote_in_tx(quote, tx)
quotes-server/src/app/mod.rs
Outdated
return Err(QuotesAppError::QuoteExpired(id.to_string())); | ||
} | ||
|
||
quote.accept(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accept should fail with expired / already accepted errors.
quotes-server/src/app/mod.rs
Outdated
) | ||
.await?; | ||
} | ||
self.quotes.update(quote).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not atomic?
shared/src/macros.rs
Outdated
@@ -124,3 +124,58 @@ macro_rules! decimal_wrapper_common { | |||
} | |||
}; | |||
} | |||
|
|||
#[macro_export] | |||
macro_rules! entity_id { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant
59f60ed
to
7688148
Compare
24c3f06
to
3dc60d9
Compare
c69dcb1
to
e162af3
Compare
e162af3
to
bc940f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spread calcs look good
closing since most of the work on this has been done via multiple smaller pr's. |
No description provided.