def create_order( user_id: int, direction: Direction, amount: int, base_currency: Currencies, quote_currency: Currencies, ) -> Order: expiration_time = datetime.utcnow() + timedelta(minutes=10) conversion_rate = get_rate( base_currency=Currency(base_currency), quote_currency=Currency(quote_currency), ) request_amount = Amount().deserialize(amount) exchange_amount = request_amount * conversion_rate order_type = OrderType.Trade if CurrencyPair.is_diem_to_diem( CurrencyPair(Currency(base_currency), Currency(quote_currency))): order_type = OrderType.DirectConvert return storage.create_order( user_id=user_id, amount=request_amount.serialize(), direction=direction, base_currency=base_currency.value, quote_currency=quote_currency.value, expiration_time=expiration_time, exchange_amount=exchange_amount.serialize(), order_type=order_type.value, )
def _set_rate(base_currency: Currency, quote_currency: Currency): global RATES rate = _get_rate_internal(base_currency=base_currency, quote_currency=quote_currency) RATES[str(CurrencyPair(base_currency, quote_currency))] = rate unit = Amount().deserialize(Amount.unit) rate = unit / rate RATES[str(CurrencyPair(quote_currency, base_currency))] = rate
def trade_to_debt(trade: Trade) -> Optional[Debt]: currency_pair = trade.quote.currency_pair.value if is_fiat(currency_pair.base) and is_fiat(currency_pair.quote): raise AssertionError("Cannot calculate debt for pairs of fiat currencies") amount = Amount().deserialize(trade.quote.amount) rate = Amount().deserialize(trade.quote.rate) # Constants used to change the amount sign wallet_owns_lp = Amount().deserialize(1000000) lp_owns_wallet = Amount().deserialize(-1000000) if is_fiat(currency_pair.quote): if trade.direction == Direction.Buy: amount *= wallet_owns_lp else: amount *= lp_owns_wallet return Debt(currency=currency_pair.quote, amount=amount.serialize(),) if is_fiat(currency_pair.base): if trade.direction == Direction.Buy: amount /= rate * lp_owns_wallet else: amount /= rate * wallet_owns_lp return Debt(currency=currency_pair.base, amount=amount.serialize(),) return None
def _get_rate_internal(base_currency: Currency, quote_currency: Currency) -> Amount: currency_pair = CurrencyPair(base_currency, quote_currency) pair_str = f"{base_currency.value}_{quote_currency.value}" if pair_str in CurrencyPairs.__members__: quote = LpClient().get_quote(pair=currency_pair, amount=1) return Amount().deserialize(quote.rate.rate) raise LookupError(f"No conversion to currency pair {currency_pair}")
def tx_fiat_amount(tx: Transaction): rate = latest_rates[f"{tx.currency}_{fiat_currency}"] tx_amount = Amount().deserialize(tx.amount) fiat_amount = rate * tx_amount return fiat_amount.serialize()
# pyre-ignore-all-errors # Copyright (c) The Diem Core Contributors # SPDX-License-Identifier: Apache-2.0 from diem_utils.precise_amount import Amount ONE_DIEM = Amount().deserialize(1000000) TWO_DIEM = Amount().deserialize(2000000) TENTH_MILLIDIEM = Amount().deserialize(100) MAX_PRECISION_DIEM = Amount().deserialize(10000000000000000009) class TestAmount: def test_mul(self): x: Amount = ONE_DIEM * ONE_DIEM assert str(x) == "1.000000" assert x.serialize() == 1000000 x: Amount = TENTH_MILLIDIEM * TWO_DIEM assert str(x) == "0.000200" assert x.serialize() == 200 x: Amount = MAX_PRECISION_DIEM * TWO_DIEM assert str(x) == "20000000000000.000018" assert x.serialize() == 20000000000000000018 def test_div(self): x: Amount = ONE_DIEM / ONE_DIEM assert str(x) == "1.000000" assert x.serialize() == 1000000
def quote_price(self, quote_currency, amount): quote = self.quote(quote_currency, amount) unit = Amount().deserialize(Amount.unit) rate = unit / Amount().deserialize(quote.rate.rate) return (rate * Amount().deserialize(amount)).serialize()