Beispiel #1
0
def estimate_fee(exchange: str, is_maker: bool) -> TradeFee:
    if exchange not in CONNECTOR_SETTINGS:
        raise Exception(f"Invalid connector. {exchange} does not exist in CONNECTOR_SETTINGS")
    use_gas = CONNECTOR_SETTINGS[exchange].use_eth_gas_lookup
    if use_gas:
        gas_amount = get_gas_price(in_gwei=False) * CONNECTOR_SETTINGS[exchange].gas_limit
        return TradeFee(percent=0, flat_fees=[("ETH", gas_amount)])
    fee_type = CONNECTOR_SETTINGS[exchange].fee_type
    fee_token = CONNECTOR_SETTINGS[exchange].fee_token
    default_fees = CONNECTOR_SETTINGS[exchange].default_fees
    fee_side = "maker" if is_maker else "taker"
    override_key = f"{exchange}_{fee_side}"
    if fee_type is TradeFeeType.FlatFee:
        override_key += "_fee_amount"
    elif fee_type is TradeFeeType.Percent:
        override_key += "_fee"
    fee = default_fees[0] if is_maker else default_fees[1]
    fee_config = fee_overrides_config_map.get(override_key)
    if fee_config is not None and fee_config.value is not None:
        fee = fee_config.value
    fee = Decimal(str(fee))
    if fee_type is TradeFeeType.Percent:
        return TradeFee(percent=fee / Decimal("100"), flat_fees=[])
    elif fee_type is TradeFeeType.FlatFee:
        return TradeFee(percent=0, flat_fees=[(fee_token, fee)])
Beispiel #2
0
 async def approve_balancer_spender(self, token_symbol: str) -> Decimal:
     """
     Approves Balancer contract as a spender for a token.
     :param token_symbol: token to approve.
     """
     resp = await self._api_request(
         "post", "eth/approve", {
             "tokenAddress": self._token_addresses[token_symbol],
             "gasPrice": str(get_gas_price())
         })
     amount_approved = Decimal(str(resp["amount"]))
     if amount_approved > 0:
         self.logger().info(
             f"Approved Balancer spender contract for {token_symbol}.")
     else:
         self.logger().info(
             f"Balancer spender contract approval failed on {token_symbol}."
         )
     return amount_approved
 async def approve_uniswap_spender(self, token_symbol: str) -> Decimal:
     """
     Approves Uniswap contract as a spender for a token.
     :param token_symbol: token to approve.
     """
     resp = await self._api_request(
         "post",
         "eth/approve",
         {
             "tokenAddress": self._token_addresses[token_symbol],
             "gasPrice": str(get_gas_price()),
             "decimals": self._token_decimals[
                 token_symbol],  # if not supplied, gateway would treat it eth-like with 18 decimals
             "connector": self.name
         })
     amount_approved = Decimal(str(resp["amount"]))
     if amount_approved > 0:
         self.logger().info(
             f"Approved Uniswap spender contract for {token_symbol}.")
     else:
         self.logger().info(
             f"Uniswap spender contract approval failed on {token_symbol}.")
     return amount_approved
    async def _create_order(self, trade_type: TradeType, order_id: str,
                            trading_pair: str, amount: Decimal,
                            price: Decimal):
        """
        Calls buy or sell API end point to place an order, starts tracking the order and triggers relevant order events.
        :param trade_type: BUY or SELL
        :param order_id: Internal order id (also called client_order_id)
        :param trading_pair: The market to place order
        :param amount: The order amount (in base token value)
        :param price: The order price
        """

        amount = self.quantize_order_amount(trading_pair, amount)
        price = self.quantize_order_price(trading_pair, price)
        base, quote = trading_pair.split("-")
        gas_price = get_gas_price()
        api_params = {
            "base": self._token_addresses[base],
            "quote": self._token_addresses[quote],
            "amount": str(amount),
            "maxPrice": str(price),
            "maxSwaps": str(self._max_swaps),
            "gasPrice": str(gas_price),
        }
        self.start_tracking_order(order_id, None, trading_pair, trade_type,
                                  price, amount, gas_price)
        try:
            order_result = await self._api_request(
                "post", f"balancer/{trade_type.name.lower()}", api_params)
            hash = order_result.get("txHash")
            tracked_order = self._in_flight_orders.get(order_id)
            if tracked_order is not None:
                self.logger().info(
                    f"Created {trade_type.name} order {order_id} txHash: {hash} "
                    f"for {amount} {trading_pair}.")
                tracked_order.update_exchange_order_id(hash)
                tracked_order.gas_price = gas_price
            if hash is not None:
                tracked_order.fee_asset = "ETH"
                tracked_order.executed_amount_base = amount
                tracked_order.executed_amount_quote = amount * price
                event_tag = MarketEvent.BuyOrderCreated if trade_type is TradeType.BUY else MarketEvent.SellOrderCreated
                event_class = BuyOrderCreatedEvent if trade_type is TradeType.BUY else SellOrderCreatedEvent
                self.trigger_event(
                    event_tag,
                    event_class(self.current_timestamp, OrderType.LIMIT,
                                trading_pair, amount, price, order_id, hash))
            else:
                self.trigger_event(
                    MarketEvent.OrderFailure,
                    MarketOrderFailureEvent(self.current_timestamp, order_id,
                                            OrderType.LIMIT))
        except asyncio.CancelledError:
            raise
        except Exception as e:
            self.stop_tracking_order(order_id)
            self.logger().network(
                f"Error submitting {trade_type.name} order to Balancer for "
                f"{amount} {trading_pair} "
                f"{price}.",
                exc_info=True,
                app_warning_msg=str(e))
            self.trigger_event(
                MarketEvent.OrderFailure,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        OrderType.LIMIT))