syntax = "proto3";
package provenance.exchange.v1;

option go_package = "github.com/provenance-io/provenance/x/exchange";

option java_package        = "io.provenance.exchange.v1";
option java_multiple_files = true;

import "cosmos/auth/v1beta1/auth.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";

// MarketAccount is an account type for use with the accounts module to hold some basic information about a market.
message MarketAccount {
  option (gogoproto.goproto_getters)  = false;
  option (gogoproto.goproto_stringer) = false;

  // base_account is the base cosmos account information.
  cosmos.auth.v1beta1.BaseAccount base_account = 1 [(gogoproto.embed) = true];

  // market_id is the numerical identifier for this market.
  uint32 market_id = 2;
  // market_details is some human-consumable information about this market.
  MarketDetails market_details = 3 [(gogoproto.nullable) = false];
}

// MarketDetails contains information about a market.
message MarketDetails {
  option (gogoproto.equal) = true;

  // name is a moniker that people can use to refer to this market.
  string name = 1;
  // description extra information about this market. The field is meant to be human-readable.
  string description = 2;
  // website_url is a url people can use to get to this market, or at least get more information about this market.
  string website_url = 3;
  // icon_uri is a uri for an icon to associate with this market.
  string icon_uri = 4;
}

// MarketBrief is a message containing brief, superficial information about a market.
message MarketBrief {
  // market_id is the numerical identifier for this market.
  uint32 market_id = 1;
  // market_address is the bech32 address string of this market's account.
  string market_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  // market_details is some information about this market.
  MarketDetails market_details = 3 [(gogoproto.nullable) = false];
}

// Market contains all information about a market.
message Market {
  // market_id is the numerical identifier for this market.
  uint32 market_id = 1;
  // market_details is some information about this market.
  MarketDetails market_details = 2 [(gogoproto.nullable) = false];

  // fee_create_ask_flat is the flat fee charged for creating an ask order.
  // Each coin entry is a separate option. When an ask is created, one of these must be paid.
  // If empty, no fee is required to create an ask order.
  repeated cosmos.base.v1beta1.Coin fee_create_ask_flat = 3 [(gogoproto.nullable) = false];

  // fee_create_bid_flat is the flat fee charged for creating a bid order.
  // Each coin entry is a separate option. When a bid is created, one of these must be paid.
  // If empty, no fee is required to create a bid order.
  repeated cosmos.base.v1beta1.Coin fee_create_bid_flat = 4 [(gogoproto.nullable) = false];

  // fee_seller_settlement_flat is the flat fee charged to the seller during settlement.
  // Each coin entry is a separate option.
  // When an ask is settled, the seller will pay the amount in the denom that matches the price they received.
  repeated cosmos.base.v1beta1.Coin fee_seller_settlement_flat = 5 [(gogoproto.nullable) = false];

  // fee_seller_settlement_ratios is the fee to charge a seller during settlement based on the price they are receiving.
  // The price and fee denoms must be equal for each entry, and only one entry for any given denom is allowed.
  repeated FeeRatio fee_seller_settlement_ratios = 6 [(gogoproto.nullable) = false];

  // fee_buyer_settlement_flat is the flat fee charged to the buyer during settlement.
  // Each coin entry is a separate option.
  // When a bid is created, the settlement fees provided must contain one of these.
  repeated cosmos.base.v1beta1.Coin fee_buyer_settlement_flat = 7 [(gogoproto.nullable) = false];

  // fee_buyer_settlement_ratios is the fee to charge a buyer during settlement based on the price they are spending.
  // The price and fee denoms do not have to equal. Multiple entries for any given price or fee denom are allowed, but
  // each price denom to fee denom pair can only have one entry.
  repeated FeeRatio fee_buyer_settlement_ratios = 8 [(gogoproto.nullable) = false];

  // accepting_orders is whether this market is allowing orders to be created for it.
  bool accepting_orders = 9;

  // allow_user_settlement is whether this market allows users to initiate their own settlements.
  // For example, the FillBids and FillAsks endpoints are available if and only if this is true.
  // The MarketSettle endpoint is only available to market actors regardless of the value of this field.
  bool allow_user_settlement = 10;

  // access_grants is the list of addresses and permissions granted for this market.
  repeated AccessGrant access_grants = 11 [(gogoproto.nullable) = false];

  // req_attr_create_ask is a list of attributes required on an account for it to be allowed to create an ask order.
  // An account must have all of these attributes in order to create an ask order in this market.
  // If the list is empty, any account can create ask orders in this market.
  //
  // An entry that starts with "*." will match any attributes that end with the rest of it.
  // E.g. "*.b.a" will match all of "c.b.a", "x.b.a", and "e.d.c.b.a"; but not "b.a", "xb.a", "b.x.a", or "c.b.a.x".
  repeated string req_attr_create_ask = 12;

  // req_attr_create_ask is a list of attributes required on an account for it to be allowed to create a bid order.
  // An account must have all of these attributes in order to create a bid order in this market.
  // If the list is empty, any account can create bid orders in this market.
  //
  // An entry that starts with "*." will match any attributes that end with the rest of it.
  // E.g. "*.b.a" will match all of "c.b.a", "x.b.a", and "e.d.c.b.a"; but not "b.a", "xb.a", "c.b.x.a", or "c.b.a.x".
  repeated string req_attr_create_bid = 13;

  // accepting_commitments is whether the market is allowing users to commit funds to it.
  bool accepting_commitments = 14;

  // fee_create_commitment_flat is the flat fee charged for creating a commitment.
  // Each coin entry is a separate option. When a commitment is created, one of these must be paid.
  // If empty, no fee is required to create a commitment.
  repeated cosmos.base.v1beta1.Coin fee_create_commitment_flat = 15 [(gogoproto.nullable) = false];

  // commitment_settlement_bips is the fraction of a commitment settlement that will be paid to the exchange.
  // It is represented in basis points (1/100th of 1%, e.g. 0.0001) and is limited to 0 to 10,000 inclusive.
  // During a commitment settlement, the inputs are summed and NAVs are used to convert that total to the
  // intermediary denom, then to the fee denom. That is then multiplied by this value to get the fee amount
  // that will be transferred out of the market's account into the exchange for that settlement.
  //
  // Summing the inputs effectively doubles the value of the settlement from what what is usually thought of
  // as the value of a trade. That should be taken into account when setting this value.
  // E.g. if two accounts are trading 10apples for 100grapes, the inputs total will be 10apples,100grapes
  // (which might then be converted to USD then nhash before applying this ratio); Usually, though, the value
  // of that trade would be viewed as either just 10apples or just 100grapes.
  uint32 commitment_settlement_bips = 16;

  // intermediary_denom is the denom that funds get converted to (before being converted to the chain's fee denom)
  // when calculating the fees that are paid to the exchange. NAVs are used for this conversion and actions will fail
  // if a NAV is needed but not available.
  string intermediary_denom = 17;

  // req_attr_create_commitment is a list of attributes required on an account for it to be allowed to create a
  // commitment. An account must have all of these attributes in order to create a commitment in this market.
  // If the list is empty, any account can create commitments in this market.
  //
  // An entry that starts with "*." will match any attributes that end with the rest of it.
  // E.g. "*.b.a" will match all of "c.b.a", "x.b.a", and "e.d.c.b.a"; but not "b.a", "xb.a", "c.b.x.a", or "c.b.a.x".
  repeated string req_attr_create_commitment = 18;
}

// FeeRatio defines a ratio of price amount to fee amount.
// For an order to be valid, its price must be evenly divisible by a FeeRatio's price.
message FeeRatio {
  option (gogoproto.goproto_stringer) = false;
  // price is the unit the order price is divided by to get how much of the fee should apply.
  cosmos.base.v1beta1.Coin price = 1 [(gogoproto.nullable) = false];
  // fee is the amount to charge per price unit.
  cosmos.base.v1beta1.Coin fee = 2 [(gogoproto.nullable) = false];
}

// AddrPermissions associates an address with a list of permissions available for that address.
message AccessGrant {
  // address is the address that these permissions apply to.
  string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
  // allowed is the list of permissions available for the address.
  repeated Permission permissions = 2;
}

// Permission defines the different types of permission that can be given to an account for a market.
enum Permission {
  // PERMISSION_UNSPECIFIED is the zero-value Permission; it is an error to use it.
  PERMISSION_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "unspecified"];
  // PERMISSION_SETTLE is the ability to use the Settle Tx endpoint on behalf of a market.
  PERMISSION_SETTLE = 1 [(gogoproto.enumvalue_customname) = "settle"];
  // PERMISSION_SET_IDS is the ability to use the SetOrderExternalID Tx endpoint on behalf of a market.
  PERMISSION_SET_IDS = 2 [(gogoproto.enumvalue_customname) = "set_ids"];
  // PERMISSION_CANCEL is the ability to use the Cancel Tx endpoint on behalf of a market.
  PERMISSION_CANCEL = 3 [(gogoproto.enumvalue_customname) = "cancel"];
  // PERMISSION_WITHDRAW is the ability to use the MarketWithdraw Tx endpoint.
  PERMISSION_WITHDRAW = 4 [(gogoproto.enumvalue_customname) = "withdraw"];
  // PERMISSION_UPDATE is the ability to use the MarketUpdate* Tx endpoints.
  PERMISSION_UPDATE = 5 [(gogoproto.enumvalue_customname) = "update"];
  // PERMISSION_PERMISSIONS is the ability to use the MarketManagePermissions Tx endpoint.
  PERMISSION_PERMISSIONS = 6 [(gogoproto.enumvalue_customname) = "permissions"];
  // PERMISSION_ATTRIBUTES is the ability to use the MarketManageReqAttrs Tx endpoint.
  PERMISSION_ATTRIBUTES = 7 [(gogoproto.enumvalue_customname) = "attributes"];
}
