syntax = "proto3";

package hydra_app;

import "google/protobuf/timestamp.proto";
import "primitives.proto";
import "currency.proto";

// Decentralized exchange (DEX) orderbook service.
//
// Provides market initialization, order management (limit, liquidity, market,
// swap), orderbook queries, trade history, and real-time event subscriptions
// for market updates and user-specific DEX events.
//
// JSON-RPC namespace: `orderbook`
service OrderbookService {
  // Initialize a market with two currencies.
  // This operation starts a task on the server that will
  // handle order matches and other market-related operations performing and
  // resolving swaps. If the provided market pair is invalid, the server
  // will return None.
  rpc InitMarket(InitMarketRequest) returns (InitMarketResponse) {}
  // Get the list of initialized markets.
  rpc GetInitializedMarkets(GetInitializedMarketsRequest)
      returns (GetInitializedMarketsResponse) {}
  // Get the info of the available markets.
  rpc GetMarketsInfo(GetMarketsInfoRequest) returns (GetMarketsInfoResponse) {}
  // Get the info of a specific market.
  rpc GetMarketInfo(GetMarketInfoRequest) returns (GetMarketInfoResponse) {}
  // Get the orderbook balances for the currencies in the market, including
  // the available and locked sending and receiving balances.
  rpc GetOrderbookBalances(GetOrderbookBalancesRequest)
      returns (GetOrderbookBalancesResponse) {}
  // Get the orderbook for the specified market.
  rpc GetOrderbook(GetOrderbookRequest) returns (GetOrderbookResponse) {}
  // Estimate the order matching for a specific market based on the
  // order operation that will be performed.
  rpc EstimateOrder(EstimateOrderRequest) returns (EstimateOrderResponse) {}
  // Create a new order for a specific market.
  rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse) {}
  // Cancel an existing order by its ID.
  rpc CancelOrder(CancelOrderRequest) returns (CancelOrderResponse) {}
  // Cancel all orders in the orderbook.
  rpc CancelAllOrders(CancelAllOrdersRequest)
      returns (CancelAllOrdersResponse) {}
  // Get all own orders in the orderbook.
  rpc GetAllOwnOrders(GetAllOwnOrdersRequest)
      returns (GetAllOwnOrdersResponse) {}
  // Get own orders in the orderbook for a specific market.
  rpc GetOwnOrders(GetOwnOrdersRequest) returns (GetOwnOrdersResponse) {}
  // Get a specific order by its ID.
  rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) {}
  // Get a specific order by the caller's `client_order_id` supplied at
  // creation time.
  rpc GetOrderByClientId(GetOrderByClientIdRequest) returns (GetOrderResponse) {
  }
  // Get the public trade history for a specific market.
  rpc GetTradeHistory(GetTradeHistoryRequest)
      returns (GetTradeHistoryResponse) {}
  // Get all the market trades performed by the user in the orderbook.
  rpc GetAllMarketTrades(GetAllMarketTradesRequest)
      returns (GetAllMarketTradesResponse) {}
  // Get the trades performed by the user in a specific market.
  rpc GetPairMarketTrades(GetPairMarketTradesRequest)
      returns (GetPairMarketTradesResponse) {}
  // Get all the swap trades performed by the user in the orderbook.
  rpc GetAllSwapTrades(GetAllSwapTradesRequest)
      returns (GetAllSwapTradesResponse) {}
  // Get the swap trades performed by the user for a specific pair of
  // currencies.
  rpc GetPairSwapTrades(GetPairSwapTradesRequest)
      returns (GetPairSwapTradesResponse) {}
  // This method is used to subscribe to the updates of a market.
  // The user will receive updates about the market activity, including
  // order book changes, trade executions, stats and candlestick updates.
  rpc SubscribeMarketEvents(SubscribeMarketEventsRequest)
      returns (stream MarketEvent) {}
  // This method is used to subscribe to the dex events.
  // The user will receive updates about their own orders, trades, and balances.
  rpc SubscribeDexEvents(SubscribeDexEventsRequest) returns (stream DexEvent) {}
}

// The side of an order: buy or sell.
enum OrderSide {
  // Unspecified order side (invalid default).
  ORDER_SIDE_UNSPECIFIED = 0;
  // A buy order.
  ORDER_SIDE_BUY = 1;
  // A sell order.
  ORDER_SIDE_SELL = 2;
}

// The type of an order in the orderbook.
enum OrderType {
  // Unspecified order type (invalid default).
  ORDER_TYPE_UNSPECIFIED = 0;
  // A limit order at a specified price.
  ORDER_TYPE_LIMIT = 1;
  // A liquidity provision order spanning a price range.
  ORDER_TYPE_LIQUIDITY = 2;
  // A market order executed at the best available price.
  ORDER_TYPE_MARKET = 3;
  // A swap order that may traverse multiple markets.
  ORDER_TYPE_SWAP = 4;
}

// Specifies whether an amount refers to the base or quote currency.
enum AmountSide {
  // Unspecified amount side (invalid default).
  AMOUNT_SIDE_UNSPECIFIED = 0;
  // The amount is in the base currency.
  AMOUNT_SIDE_BASE = 1;
  // The amount is in the quote currency.
  AMOUNT_SIDE_QUOTE = 2;
}

// An order amount specified in either base or quote currency.
message OrderAmount {
  // Amount denominated in the base currency.
  message Base {
    DecimalString amount = 1;
  }
  // Amount denominated in the quote currency.
  message Quote {
    DecimalString amount = 1;
  }

  oneof amount {
    Base base = 1;
    Quote quote = 2;
  }
}

// Metadata about a currency registered on the orderbook.
message CurrencyInfo {
  // The protocol of the currency's network.
  Protocol protocol = 1;
  // The network ID within the protocol.
  string network_id = 2;
  // The asset ID on the network.
  string asset_id = 3;
  // The number of decimal places for the currency.
  uint32 decimals = 4;
}

// A pair of base and quote currencies for a market.
message CurrencyInfoPair {
  // The base currency.
  CurrencyInfo base = 1;
  // The quote currency.
  CurrencyInfo quote = 2;
}

// Full market configuration including currencies, fees, and limits.
message MarketInfo {
  // The base currency.
  CurrencyInfo base = 1;
  // The quote currency.
  CurrencyInfo quote = 2;
  // Fee ratio charged to takers on the base side.
  DecimalString taker_base_fee = 3;
  // Fee ratio charged to takers on the quote side.
  DecimalString taker_quote_fee = 4;
  // Fee ratio charged to makers on the base side.
  DecimalString maker_base_fee = 5;
  // Fee ratio charged to makers on the quote side.
  DecimalString maker_quote_fee = 6;
  // The number of decimal precision digits for base amounts.
  uint32 base_precision = 7;
  // The number of decimal precision digits for quote amounts.
  uint32 quote_precision = 8;
  // The minimum order amount in the base currency.
  DecimalString min_base_amount = 9;
  // The minimum order amount in the quote currency.
  DecimalString min_quote_amount = 10;
}

// The balance of a currency in the orderbook context.
message OrderbookBalance {
  // The currency identifier.
  OrderbookCurrency currency = 1;
  // The detailed balance breakdown.
  CurrencyBalance balance = 2;
}

// Breakdown of a currency's balance across different states.
message CurrencyBalance {
  // Available balance for sending (placing sell/buy orders).
  DecimalString sending = 1;
  // Available balance for receiving (filling orders).
  DecimalString receiving = 2;
  // Balance locked in pending outgoing operations.
  DecimalString pending_sending = 3;
  // Balance locked in pending incoming operations.
  DecimalString pending_receiving = 4;
  // Balance unavailable for sending (e.g., channel reserves).
  DecimalString unavailable_sending = 5;
  // Balance unavailable for receiving.
  DecimalString unavailable_receiving = 6;
  // Balance currently locked in active orders (sending side).
  DecimalString in_use_sending = 7;
  // Balance currently locked in active orders (receiving side).
  DecimalString in_use_receiving = 8;
}

// A single liquidity position in the orderbook.
message LiquidityPosition {
  // The public key of the liquidity provider.
  bytes client_pubkey = 1;
  // The side of the order (buy or sell).
  OrderSide side = 2;
  // The price of the position.
  DecimalString price = 3;
  // The amount offered: base amount for sell orders, quote for buy orders.
  DecimalString amount = 4;
  // The amount already matched against this position.
  DecimalString matched_amount = 5;
  // Whether there is a pending cancellation for this position.
  bool pending_cancel = 6;
}

// A snapshot of the orderbook for a market.
message Orderbook {
  // The market configuration.
  MarketInfo info = 1;
  // Map of order IDs to active liquidity positions.
  map<string, LiquidityPosition> orders = 2;
}

message OrderVariant {
  message AddLiquidity {
    OrderbookCurrency base = 1;
    OrderbookCurrency quote = 2;
    DecimalString min_buy_price = 3;
    DecimalString mid_price = 4;
    DecimalString max_sell_price = 5;
    OrderAmount amount = 6;
    // remove the liquidity as soon as some part is filled
    bool remove_on_fill = 7;
  }

  message LimitOrder {
    OrderbookCurrency base = 1;
    OrderbookCurrency quote = 2;
    OrderSide side = 3;
    DecimalString price = 4;
    OrderAmount amount = 5;
  }

  message MarketOrder {
    OrderbookCurrency base = 1;
    OrderbookCurrency quote = 2;
    OrderAmount amount = 3;
    OrderSide side = 4;
  }

  message SwapOrder {
    OrderbookCurrency from_currency = 1;
    repeated OrderbookCurrency currency_path = 2;
    OrderbookCurrency to_currency = 3;
    SwapAmount amount = 4;
  }

  oneof order_variant {
    AddLiquidity add_liquidity = 1;
    LimitOrder limit_order = 2;
    MarketOrder market_order = 3;
    SwapOrder swap_order = 4;
  }
}

message OrderSideVariant {
  message Buy {
    DecimalString bought_base_amount = 1;
    DecimalString sold_quote_amount = 2;
    DecimalString paid_base_fee = 3;
  }

  message Sell {
    DecimalString sold_base_amount = 1;
    DecimalString bought_quote_amount = 2;
    DecimalString paid_quote_fee = 3;
  }

  oneof side {
    Buy buy = 1;
    Sell sell = 2;
  }
}

// Represents an order that adds liquidity to a pair of currencies in the
// orderbook.
message LiquidityOrder {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  google.protobuf.Timestamp created_at = 3;
  DecimalString min_buy_price = 4;
  DecimalString max_buy_price = 5;
  DecimalString min_sell_price = 6;
  DecimalString max_sell_price = 7;
  DecimalString remaining_base_amount = 8;
  DecimalString remaining_quote_amount = 9;
  DecimalString sold_base_amount = 10;
  DecimalString bought_base_amount = 11;
  DecimalString sold_quote_amount = 12;
  DecimalString bought_quote_amount = 13;
  DecimalString paid_base_fee = 14;
  DecimalString paid_quote_fee = 15;
  bool remove_on_fill = 16;
}

message LimitOrder {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  google.protobuf.Timestamp created_at = 3;
  DecimalString price = 4;
  OrderAmount remaining_amount = 5;
  OrderSideVariant variant = 6;
}

// Represents a market order for a pair of currencies in the orderbook.
// A market order is an order to buy or sell a currency at the best available
// price in the orderbook.
message MarketOrder {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  google.protobuf.Timestamp created_at = 3;
  OrderAmount remaining_amount = 4;
  OrderAmount unmatched_amount = 5;
  OrderAmount failed_amount = 6;
  OrderSideVariant variant = 7;
}

// Represents an order for a pair of currencies in the orderbook.
// It can either be a liquidity order, limit order or a market order.
// Liquidity orders are used to add liquidity to the orderbook, while market
// orders are used to buy or sell currencies at the best available price.
message PairOrder {
  oneof order {
    LiquidityOrder liquidity_order = 1;
    LimitOrder limit_order = 2;
    MarketOrder market_order = 3;
  }
}

// Represents an order for swapping one currency for another.
// It can involve multiple pair orders in a path to achieve the swap.
// The swap order contains information about the currencies involved, the
// created timestamp, the remaining amount to be swapped, and the amounts
// sold and bought in the swap, including any fees paid.
message SwapOrder {
  OrderbookCurrency from_currency = 1;
  repeated OrderbookCurrency currency_path = 2;
  OrderbookCurrency to_currency = 3;
  google.protobuf.Timestamp created_at = 4;
  SwapAmount remaining_amount = 5;
  SwapAmount unmatched_amount = 6;
  SwapAmount failed_amount = 7;
  DecimalString sold_from_currency_amount = 8;
  DecimalString bought_to_currency_amount = 9;
  DecimalString paid_to_currency_fee = 10;
}

// Represents an order that can be either a pair order or a swap order.
message Order {
  oneof order {
    PairOrder pair_order = 1;
    SwapOrder swap_order = 2;
  }
  // Caller's own order identifier supplied at creation time as
  // `client_order_id`. Absent when the caller did not supply one or
  // when the order has completed and its idempotency entry has been
  // pruned.
  optional string client_order_id = 3;
}

message Trade {
  string taker_order_id = 1;
  DecimalString base_amount = 2;
  DecimalString quote_amount = 3;
  DecimalString price = 4;
  DecimalString final_price = 5;
  google.protobuf.Timestamp timestamp = 6;
  OrderSide maker_order_side = 7;
}

message ClientMarketTrade {
  string swap_id = 1;
  string order_id = 2;
  DecimalString base_amount = 3;
  DecimalString quote_amount = 4;
  DecimalString base_fee = 5;
  DecimalString quote_fee = 6;
  DecimalString price = 7;
  DecimalString final_price = 8;
  google.protobuf.Timestamp timestamp = 9;
  OrderSide order_side = 10;
  OrderType order_type = 11;
}

message ClientSwapTrade {
  string swap_id = 1;
  string order_id = 2;
  DecimalString from_currency_amount = 3;
  DecimalString to_currency_amount = 4;
  DecimalString to_currency_fee = 5;
  google.protobuf.Timestamp timestamp = 6;
}

message InitMarketRequest {
  OrderbookCurrency first_currency = 1;
  OrderbookCurrency other_currency = 2;
}

message InitMarketResponse {
  optional MarketInfo market_info = 1;
}

message GetInitializedMarketsRequest {}

message GetInitializedMarketsResponse {
  repeated CurrencyInfoPair markets = 1;
}

message GetMarketsInfoRequest {}

message GetMarketsInfoResponse {
  repeated MarketInfo markets = 1;
}

message GetMarketInfoRequest {
  OrderbookCurrency first_currency = 1;
  OrderbookCurrency other_currency = 2;
}

message GetMarketInfoResponse {
  optional MarketInfo market_info = 1;
}

message GetOrderbookBalancesRequest {}

message GetOrderbookBalancesResponse {
  repeated OrderbookBalance balances = 1;
}

message GetOrderbookRequest {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
}

message GetOrderbookResponse {
  optional Orderbook orderbook = 1;
}

message EstimateOrderRequest {
  OrderVariant order_variant = 1;
}

message EstimateOrderResponse {
  optional OrderMatch order_match = 1;
}

message CreateOrderRequest {
  OrderVariant order_variant = 1;
  // Client-supplied order identifier. Optional, max 64 chars. When set
  // and unique among the caller's open orders, the orderbook stores it
  // on the order, returns the original `order_id` on retries with the
  // same value (idempotent), and exposes it on subsequent reads.
  optional string client_order_id = 2;
}

message CreateOrderResponse {
  string order_id = 1;
}

message CancelOrderRequest {
  string order_id = 1;
}

message CancelOrderResponse {
  bool removed = 1;
}

message CancelAllOrdersRequest {}

message CancelAllOrdersResponse {}

message GetOwnOrdersRequest {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
}

message GetOwnOrdersResponse {
  map<string, Order> orders = 1;  // key: order_id
}

message GetAllOwnOrdersRequest {}

message GetAllOwnOrdersResponse {
  map<string, Order> orders = 1;  // key: order_id
}

message GetOrderRequest {
  string order_id = 1;
}

message GetOrderByClientIdRequest {
  // `client_order_id` supplied at creation time.
  string client_order_id = 1;
}

message GetOrderResponse {
  Order order = 1;
}

message GetTradeHistoryRequest {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  // Pagination parameters.
  PaginationRequest pagination = 3;
}

message GetTradeHistoryResponse {
  // The trade history for the specified market.
  // Sorted by timestamp in descending order.
  // The most recent trades are at the beginning of the list.
  repeated Trade trade_history = 1;
  // Pagination metadata.
  PaginationResponse pagination = 2;
}

// A client market trade tagged with the market pair it belongs to.
// Used as the element of a flat, paginated list across all markets.
message FlatClientMarketTrade {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  ClientMarketTrade trade = 3;
}

message GetAllMarketTradesRequest {
  // Pagination parameters.
  PaginationRequest pagination = 1;
}

message GetAllMarketTradesResponse {
  // All client market trades across every market, sorted by timestamp
  // descending (most recent first). The `base` and `quote` fields on each
  // element identify the market the trade belongs to.
  repeated FlatClientMarketTrade trades = 1;
  // Pagination metadata.
  PaginationResponse pagination = 2;
}

message GetPairMarketTradesRequest {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  // Pagination parameters.
  PaginationRequest pagination = 3;
}

message GetPairMarketTradesResponse {
  // The trades performed by the user in the specified market.
  // Sorted by timestamp in descending order.
  // The most recent trades are at the beginning of the list.
  repeated ClientMarketTrade trades = 1;
  // Pagination metadata.
  PaginationResponse pagination = 2;
}

// A client swap trade tagged with the currency pair it belongs to.
// Used as the element of a flat, paginated list across all swap pairs.
message FlatClientSwapTrade {
  OrderbookCurrency from_currency = 1;
  OrderbookCurrency to_currency = 2;
  ClientSwapTrade trade = 3;
}

message GetAllSwapTradesRequest {
  // Pagination parameters.
  PaginationRequest pagination = 1;
}

message GetAllSwapTradesResponse {
  // All client swap trades across every currency pair, sorted by timestamp
  // descending (most recent first). The `from_currency` and `to_currency`
  // fields on each element identify the pair the trade belongs to.
  repeated FlatClientSwapTrade trades = 1;
  // Pagination metadata.
  PaginationResponse pagination = 2;
}

message GetPairSwapTradesRequest {
  OrderbookCurrency from_currency = 1;
  OrderbookCurrency to_currency = 2;
  // Pagination parameters.
  PaginationRequest pagination = 3;
}

message GetPairSwapTradesResponse {
  // The swap trades performed by the user for the specified pair of currencies.
  // Sorted by timestamp in descending order.
  // The most recent trades are at the beginning of the list.
  repeated ClientSwapTrade trades = 1;
  // Pagination metadata.
  PaginationResponse pagination = 2;
}

message OrderbookUpdate {
  map<string, LiquidityPosition> updated_orders = 1;  // order_id -> update
  repeated string removed_orders = 2;                 // order_ids
}

message MarketVolatility {
  DecimalString first_price = 1;
  DecimalString last_price = 2;
  DecimalString high_price = 3;
  DecimalString low_price = 4;
  DecimalString base_volume = 5;
  DecimalString quote_volume = 6;
}

message MarketDailyStats {
  MarketVolatility volatility = 1;
}

enum CandlestickInterval {
  // Unspecified interval (invalid default).
  CANDLESTICK_INTERVAL_UNSPECIFIED = 0;
  CANDLESTICK_INTERVAL_ONE_MINUTE = 1;
  CANDLESTICK_INTERVAL_THREE_MINUTES = 2;
  CANDLESTICK_INTERVAL_FIVE_MINUTES = 3;
  CANDLESTICK_INTERVAL_FIFTEEN_MINUTES = 4;
  CANDLESTICK_INTERVAL_THIRTY_MINUTES = 5;
  CANDLESTICK_INTERVAL_ONE_HOUR = 6;
  CANDLESTICK_INTERVAL_TWO_HOURS = 7;
  CANDLESTICK_INTERVAL_FOUR_HOURS = 8;
  CANDLESTICK_INTERVAL_SIX_HOURS = 9;
  CANDLESTICK_INTERVAL_EIGHT_HOURS = 10;
  CANDLESTICK_INTERVAL_TWELVE_HOURS = 11;
  CANDLESTICK_INTERVAL_ONE_DAY = 12;
  CANDLESTICK_INTERVAL_THREE_DAYS = 13;
  CANDLESTICK_INTERVAL_ONE_WEEK = 14;
  CANDLESTICK_INTERVAL_ONE_MONTH = 15;
}

message Candlestick {
  google.protobuf.Timestamp timestamp = 1;
  DecimalString open = 2;
  DecimalString close = 3;
  DecimalString high = 4;
  DecimalString low = 5;
  DecimalString base_volume = 6;
  DecimalString quote_volume = 7;
}

message CandlestickUpdate {
  CandlestickInterval interval = 1;
  Candlestick candlestick = 2;
}

message MarketEvent {
  oneof update {
    bool is_synced = 1;
    OrderbookUpdate orderbook_update = 2;
    Trade trade_update = 3;
    MarketDailyStats daily_stats_update = 4;
    CandlestickUpdate candlestick_update = 5;
  }
}

message BalanceUpdate {
  OrderbookCurrency currency = 1;
  CurrencyBalance balance = 2;
}

message OrderUpdate {
  message OrderCreated {
    string order_id = 1;
    Order order = 2;
  }
  message OrderUpdated {
    string order_id = 1;
    Order order = 2;
  }
  message OrderCompleted {
    string order_id = 1;
  }
  message OrderCanceled {
    string order_id = 1;
  }

  oneof update {
    OrderCreated order_created = 1;
    OrderUpdated order_updated = 2;
    OrderCompleted order_completed = 3;
    OrderCanceled order_canceled = 4;
  }
}

message SwapHop {
  OrderbookCurrency sending_currency = 1;
  OrderbookCurrency receiving_currency = 2;
  DecimalString sending_amount = 3;
  DecimalString receiving_amount = 4;
  DecimalString receiving_fee = 5;
}

message SwapPath {
  string swap_id = 1;
  SwapHop first_hop = 2;
  repeated SwapHop next_hops = 3;
}

/// Role of a participant in a specific matched swap.
///
///   * `SWAP_ROLE_LAST_MAKER` (1):           sole preimage generator;
///     creates `Hashlock::Known{P}`, calls PrepareSwap(Maker) immediately.
///   * `SWAP_ROLE_INTERMEDIATE_MAKER` (2):   non-last maker.
///     Follower protocol with `SwapSide::Maker` for PrepareSwap.
///   * `SWAP_ROLE_TAKER` (3):                taker (Market/Swap order).
///     Follower protocol with `SwapSide::Taker` for PrepareSwap.
enum SwapRole {
  // Invalid default value. A zero-valued SwapRole is always a protocol error.
  SWAP_ROLE_UNSPECIFIED = 0;
  /// Last (or sole) maker in the route. Generates the preimage.
  SWAP_ROLE_LAST_MAKER = 1;
  /// Intermediate maker — a maker order that is not the last hop.
  SWAP_ROLE_INTERMEDIATE_MAKER = 2;
  /// Taker side of the swap.
  SWAP_ROLE_TAKER = 3;
}

message MatchedOrder {
  string own_order_id = 1;
  repeated SwapPath swap_route = 2;
  SwapRole swap_role = 3;
}

enum SwapStatus {
  // Unspecified swap status (invalid default).
  SWAP_STATUS_UNSPECIFIED = 0;
  SWAP_STATUS_ORDER_MATCHED = 1;
  SWAP_STATUS_RECEIVING_INVOICE_CREATED = 2;
  SWAP_STATUS_PAYING_INVOICE_RECEIVED = 3;
  SWAP_STATUS_PAYMENT_SENT = 4;
  SWAP_STATUS_PAYMENT_RECEIVED = 5;
  SWAP_STATUS_PAYMENT_CLAIMED = 6;
  SWAP_STATUS_PAYMENT_CLAIMED_BY_COUNTERPARTY = 7;
  SWAP_STATUS_SWAP_COMPLETED = 8;
  SWAP_STATUS_SWAP_FAILED = 9;
}

message SwapUpdate {
  string order_id = 1;
  string swap_id = 2;
  SwapProgress progress = 3;
}

message SwapProgress {
  DecimalString receiving_amount = 1;
  DecimalString paying_amount = 2;
  SwapStatus status = 3;
  optional string error = 4;
}

message MarketTradeUpdate {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
  ClientMarketTrade trade = 3;
}

message SwapTradeUpdate {
  OrderbookCurrency from_currency = 1;
  OrderbookCurrency to_currency = 2;
  ClientSwapTrade trade = 3;
}

message DexEvent {
  google.protobuf.Timestamp timestamp = 1;
  oneof update {
    bool is_synced = 2;
    BalanceUpdate balance_update = 3;
    OrderUpdate order_update = 4;
    MatchedOrder order_matched = 5;
    SwapUpdate swap_update = 6;
    MarketTradeUpdate market_trade_update = 7;
    SwapTradeUpdate swap_trade_update = 8;
  }
}

message SubscribeMarketEventsRequest {
  OrderbookCurrency base = 1;
  OrderbookCurrency quote = 2;
}

message SubscribeDexEventsRequest {}
