From 4aabad21b7bcb0d138d8dda0cd70859d9ef39d45 Mon Sep 17 00:00:00 2001 From: Daniel Wedul Date: Tue, 7 Nov 2023 13:13:20 -0700 Subject: [PATCH] Add the spec docs for the exchange module (#1729) * [1700]: make update-tocs to fix some existing TOCs. * [1700]: First crack at the exchange spec main README. * [1700]: First crack at the concepts spec doc. * [1700]: First crack at the state spec doc. * [1700]: Add empty place-holder files for the rest of the exchange spec docs. * [1700]: Initial write-up of messages spec doc. * [1700]: Events spec doc. * [1700]: Standardize the hr below the tocs. * [1700]: in the messages spec doc, include more sub-message content and add link references to those sections. * [1700]: Spec doc on the queries. * [1700]: Params spec doc. * [1700]: Turn lots of stuff into links and fix some inconsistent spacing. * [1700]: Reorder some market state entries. * [1700]: Add some missing blurbs under L1 headings. Remove the hrs above the L2 headings, and put a hr above each TOC. A L2 heading is underlined, so it looks weird when there's an hr above them too. * [1700]: Some updates to concepts from proof-reading them. Should be pretty solid now. * [1700]: Tweaks to state doc upon proof-reading. * [1700]: Proof reading of messages spec. * [1700]: Proof-read of the queries spec doc. * [1700]: Small tweak to the params spec doc upon proofreading. * Update x/exchange/spec/03_messages.md Co-authored-by: Jason Talis --------- Co-authored-by: Jason Talis --- x/exchange/spec/01_concepts.md | 336 +++++++++++++++++++++++ x/exchange/spec/02_state.md | 283 ++++++++++++++++++++ x/exchange/spec/03_messages.md | 472 +++++++++++++++++++++++++++++++++ x/exchange/spec/04_events.md | 240 +++++++++++++++++ x/exchange/spec/05_queries.md | 256 ++++++++++++++++++ x/exchange/spec/06_params.md | 25 ++ x/exchange/spec/README.md | 6 +- x/marker/spec/01_state.md | 1 + x/marker/spec/03_messages.md | 3 +- x/marker/spec/10_governance.md | 1 - 10 files changed, 1617 insertions(+), 6 deletions(-) create mode 100644 x/exchange/spec/01_concepts.md create mode 100644 x/exchange/spec/02_state.md create mode 100644 x/exchange/spec/03_messages.md create mode 100644 x/exchange/spec/04_events.md create mode 100644 x/exchange/spec/05_queries.md create mode 100644 x/exchange/spec/06_params.md diff --git a/x/exchange/spec/01_concepts.md b/x/exchange/spec/01_concepts.md new file mode 100644 index 0000000000..501768fb64 --- /dev/null +++ b/x/exchange/spec/01_concepts.md @@ -0,0 +1,336 @@ +# Exchange Concepts + +The `x/exchange` module facilitates the trading of on-chain assets. + +Markets provide fee structures and are responsible for identifying and triggering settlements. +Orders are created by users to indicate a desire to trade on-chain funds in a market. +The exchange module defines a portion of market fees to be paid to the chain (distributed like gas fees). + +--- + + - [Markets](#markets) + - [Required Attributes](#required-attributes) + - [Market Permissions](#market-permissions) + - [Settlement](#settlement) + - [Orders](#orders) + - [Ask Orders](#ask-orders) + - [Bid Orders](#bid-orders) + - [Partial Orders](#partial-orders) + - [External IDs](#external-ids) + - [Fees](#fees) + - [Order Creation Fees](#order-creation-fees) + - [Settlement Flat Fees](#settlement-flat-fees) + - [Settlement Ratio Fees](#settlement-ratio-fees) + - [Exchange Fees](#exchange-fees) + + +## Markets + +A market is a combination of on-chain setup and off-chain processes. +They are created by a governance proposal using the [MsgGovCreateMarketRequest](03_messages.md#msggovcreatemarketrequest) message. +Most aspects of the market are then manageable using permissioned endpoints. +Fees can only be managed with a governance proposal using the [MsgGovManageFeesRequest](03_messages.md#msggovmanagefeesrequest) message. + +Each market has a set of optional details designed for human-use, e.g. name, description, website url. + +A market is responsible (off-chain) for identifying order matches and triggering (on-chain) settlement. + +A market receives fees for order creation and order settlement. It also defines what fees are required and what is acceptable as payments. + +A market can delegate various [permissions](#market-permissions) to other accounts, allowing those accounts to use specific endpoints on behalf of the market. + +Markets can restrict who can create orders with them by defining account attributes that are required to create orders. See [Required Attributes](#required-attributes). + +Markets can control whether user-settlement is allowed. +When user-settlement is allowed, the [FillBids](03_messages.md#fillbids) and [FillAsks](03_messages.md#fillasks) endpoints can be used for orders in the market. + +A market can also control whether orders can be created for it. +When order creation is not allowed, any existing orders can still be settled or cancelled, but no new ones can be made (in that market). + +The fees collected by a market are kept in the market's account, and can be accessed using the [MarketWithdraw](03_messages.md#marketwithdraw) endpoint. + +See also: [Market](03_messages.md#market). + +### Required Attributes + +There is a separate list of attributes required to create each order type. +If one or more attributes are required to create an order of a certain type, the order creator (buyer or seller) must have all of them on their account. + +Required attributes can have a wildcard at the start to indicate that any attribute with the designated base and one (or more) level(s) is applicable. +The only place a wildcard `*` is allowed is at the start of the string and must be immediately followed by a period. +For example, a required attribute of `*.kyc.pb` would match an account attribute of `buyer.kyc.pb` or `special.seller.kyc.pb`, but not `buyer.xkyc.pb` (wrong base) or `kyc.pb` (no extra level). + +Attributes are defined using the [x/name](/x/name/spec/README.md) module, and are managed on accounts using the [x/attributes](/x/attribute/spec/README.md) module. + +### Market Permissions + +The different available permissions are defined by the [Permission](03_messages.md#permission) proto enum message. + +Each market manages its own set of [AccessGrants](03_messages.md#accessgrant), which confer specific permissions to specific addresses. + +* `PERMISSION_UNSPECIFIED`: it is an error to try to use this permission for anything. +* `PERMISSION_SETTLE`: accounts with this permission can use the [MarketSettle](03_messages.md#marketsettle) endpoint for a market. +* `PERMISSION_SET_IDS`: accounts with this permission can use the [MarketSetOrderExternalID](03_messages.md#marketsetorderexternalid) endpoint for a market. +* `PERMISSION_CANCEL`: accounts with this permission can use the [CancelOrder](03_messages.md#cancelorder) endpoint to cancel orders in a market. +* `PERMISSION_WITHDRAW`: accounts with this permission can use the [MarketWithdraw](03_messages.md#marketwithdraw) endpoint for a market. +* `PERMISSION_UPDATE`: accounts with this permission can use the [MarketUpdateDetails](03_messages.md#marketupdatedetails), [MarketUpdateEnabled](03_messages.md#marketupdateenabled), and [MarketUpdateUserSettle](03_messages.md#marketupdateusersettle) endpoints for a market. +* `PERMISSION_PERMISSIONS`: accounts with this permission can use the [MarketManagePermissions](03_messages.md#marketmanagepermissions) endpoint for a market. +* `PERMISSION_ATTRIBUTES`: accounts with this permission can use the [MarketManageReqAttrs](03_messages.md#marketmanagereqattrs) endpoint for a market. + + +### Settlement + +Each market is responsible for the settlement of its orders. +To do this, it must first identify a matching set of asks and bids. +The [MarketSettle](03_messages.md#marketsettle) endpoint is then used to settle and clear orders. +If the market allows, users can also settlement orders with their own funds using the [FillBids](03_messages.md#fillbids) or [FillAsks](03_messages.md#fillasks) endpoints. + +During settlement, at most one order can be partially filled, and it must be the last order in its list (in [MsgMarketSettleRequest](03_messages.md#msgmarketsettlerequest)). +That order must allow partial settlement (defined at order creation) and be evenly divisible (see [Partial Orders](#partial-orders)). +The market must also set the `expect_partial` field to `true` in the request. +If all of the orders are being filled in full, the `expect_partial` field must be `false`. + +All orders in a settlement must have the same `assets` denoms, and also the same `price` denoms, but the fees can be anything. +The total bid price must be at least the total ask price (accounting for partial fulfillment if applicable). + +During settlement: + +1. The `assets` are transferred directly from the seller(s) to the buyer(s). +2. The `price` funds are transferred directly from the buyer(s) to the seller(s). +3. All settlement fees are transferred directly from the seller(s) and buyer(s) to the market. +4. The exchange's portion of the fees is transferred from the market to the chain's fee collector. + +With complex settlements, it's possible that an ask order's `assets` go to a different account than the `price` funds come from, and vice versa for bid orders. + +Transfers of the `assets` and `price` bypass the quarantine module since order creation can be viewed as acceptance of those funds. + +Transfers do not bypass any other send-restrictions (e.g. `x/marker` or `x/sanction` module restrictions). +E.g. If an order's funds are in a sanctioned account, settlement of that order will fail since those funds cannot be removed from that account. +Or, if a marker has required attributes, but the recipient does not have those attributes, settlement will fail. + + +## Orders + +Orders are created by users that want to trade assets in a market. + +When an order is created, a hold is placed on the applicable funds. +Those funds will remain in the user's account until the order is settled or cancelled. +The holds ensure that the required funds are available at settlement without the need of an intermediary holding/clearing account. +During settlement, the funds get transferred directly between the buyers and sellers, and fees are paid from the buyers and sellers directly to the market. + +Orders can be cancelled by either the user or the market. + +Once an order is created, it cannot be modified except in these specific ways: + +1. When an order is partially filled, the amounts in it will be reduced accordingly. +2. An order's external id can be changed by the market. +3. Cancelling an order will release the held funds and delete the order. +4. Settling an order in full will delete the order. + + +### Ask Orders + +Ask orders represent a desire to sell some specific `assets` at a minimum `price`. +When an ask order is created, a hold is placed on the `assets` being sold. +If the denom of the `seller_settlement_flat_fee` is different from the denom of the price, a hold is placed on that flat fee too. +It's possible for an ask order to be filled at a larger `price` than initially defined. + +The `seller_settlement_flat_fee` is verified at the time of order creation, but only paid during settlement. + +When an ask order is settled, the `assets` are transferred directly to the buyer(s) and the `price` is transferred directly from the buyer(s). +Then the seller settlement fees are transferred from the seller to the market. + +During settlement, the seller settlement fee ratio with the appropriate `price` denom is applied to the price the seller is receiving. +That result is then added to the ask order's `seller_settlement_flat_fee` to get the total settlement fee to be paid for the ask order. +In this way, the seller's settlement ratio fee can be taken out of the `price` funds that the seller is receiving. +If the `seller_settlement_flat_fee` is the same denom as the price, it can come out of the `price` funds too. + +Because the fees can come out of the `price` funds, it's possible (probable) that the total `price` funds that the seller ends up with, is less than their requested price. + +For example, a user creates an ask order to sell `2cow` (the `assets`) and wants at least `15chicken` (the `price`). +The market finds a way to settle that order where the seller will get `16chicken`, but the seller's settlement fee will end up being `2chicken`. +During settlement, the `2cow` are transferred from the seller to the buyer, and `16chicken` are transferred from the buyer to the seller. +Then, `2chicken` are transferred from the seller to the market. +So the seller ends up with `14chicken` for their `2cow`. + +See also: [AskOrder](03_messages.md#askorder). + + +### Bid Orders + +Bid orders represent a desire to buy some specific `assets` at a specific `price`. +When a bid order is created, a hold is placed on the order's `price` and `buyer_settlement_fees`. + +When a bid order is settled, the `price` is transferred directly to the seller(s) and the assets are transferred directly from the seller(s). +Then, the buyer settlement fees are transferred from the buyer to the market. + +The `buyer_settlement_fees` are verified at the time of order creation, but only paid during settlement. +They are paid in addition to the `price` the buyer is paying. + +See also: [BidOrder](03_messages.md#bidorder). + + +### Partial Orders + +Both Ask orders and Bid orders can optionally allow partial fulfillment by setting the `allow_partial` field to `true` when creating the order. + +When an order is partially filled, the order's same `assets:price` and `assets:settlement-fees` ratios are maintained. + +Since only whole numbers are allowed, this means that: + +* ` * / ` must be a whole number. +* ` * / ` must also be a whole number. + +When an ask order is partially filled, it's `price` and `seller_settlement_flat_fee` are reduced at the same rate as the assets, even if the seller is receiving a higher price than requested. +E.g. If an ask order selling `2cow` for `10chicken` is partially settled for `1cow` at a price of `6chicken`, the seller will receive the `6chicken` but the updated ask order will list that there's still `1cow` for sale for `5chicken`. + +When an order is partially filled, its amounts are updated to reflect what hasn't yet been filled. + +An order that allows partial fulfillment can be partially filled multiple times (as long as the numbers allow for it). + +Settlement will fail if an order is being partially filled that either doesn't allow it, or cannot be evenly split at the needed `assets` amount. + + +### External IDs + +Orders can be identified using an off-chain identifier. +These can be provided during order creation (in the `external_id` field). +They can also be set by the market after the order has been created using the [MarketSetOrderExternalID](03_messages.md#marketsetorderexternalid) endpoint. + +Each external id is unique inside a market. +I.e. two orders in the same market cannot have the same external id, but two orders in different markets **can** have the same external id. +An attempt (by a user) to create an order with a duplicate external id, will fail. +An attempt (by a market) to change an order's external id to one already in use, will fail. + +The external ids are optional, so it's possible that multiple orders in a market have an empty string for the external id. +Orders with external ids can be looked up using the [GetOrderByExternalID](05_queries.md#getorderbyexternalid) query (as well as the other order queries). + +External ids are limited to 100 characters. + + +## Fees + +Markets dictate the minimum required fees. It's possible to pay more than the required fees, but not less. + +A portion of the fees that a market collects are sent to the blockchain and distributed similar to gas fees. +This portion is dictated by the exchange module in its [params](06_params.md). + +There are three types of fees: + +* Order creation: Flat fees paid at the time that an order is created. +* Settlement flat fees: A fee paid during settlement that is the same for each order. +* Settlement ratio fees: A fee paid during settlement that is based off of the order's price. + +For each fee type, there is a configuration for each order type. +E.g. the ask-order creation fee is configured separately from the bid-order creation fee. + +Each fee type is only paid in a single denom, but a market can define multiple options for each. +E.g. if flat fee options for a specific fee are `5chicken,1cow`, users can provide **either** `5chicken` or `1cow` to fulfill that required fee. + +If a market does not have any options defined for a given fee type, that fee is not required. +E.g. if the `fee_create_ask_flat` field is empty, there is no fee required to create an ask order. + +All fees except the seller settlement ratio fees must be provided with order creation, and are validated at order creation. + + +### Order Creation Fees + +This is a fee provided in the `order_creation_fee` field of the order creation `Msg`s and is collected immediately. +These are paid on top of any gas or message fees required. + +Each order type has its own creation fee configuration: + +* `fee_create_ask_flat`: The available `Coin` fee options for creating an ask order. +* `fee_create_bid_flat`: The available `Coin` fee options for creating a bid order. + + +### Settlement Flat Fees + +This is a fee provided as part of an order, but is not collected until settlement. + +Each order type has its own settlement flat fee configuration: + +* `fee_seller_settlement_flat`: The available `Coin` fee options that are paid by the seller during settlement. +* `fee_buyer_settlement_flat`: The available `Coin` fee options that are paid by the buyer during settlement. + +The ask order's `seller_settlement_flat_fee` must be at least one of the available `fee_seller_settlement_flat` options. +The bid order's `buyer_settlement_fees` must be enough to cover one of the `fee_buyer_settlement_flat` options plus one of the buyer settlement ratio fee options. + + +### Settlement Ratio Fees + +A [FeeRatio](03_messages.md#feeratio) is a pair of `Coin`s defining a `price` to `fee` ratio. + +Each order type has its own settlement ratio fee configurations: + +* `fee_seller_settlement_ratios`: The available `FeeRatio` options that are applied to the `price` received. +* `fee_buyer_settlement_ratios`: The available `FeeRatio` options that are applied to the bid order's `price`. + +If a market defines both buyer and seller settlement ratios, they should define ratios in each with the same set of `price` denoms. +E.g. if there's a `fee_buyer_settlement_ratios` entry of `100chicken:1cow`, there should be an entry in `fee_seller_settlement_ratios` with a price denom of `chicken` (or `fee_seller_settlement_ratios` should be empty). + +If a market requires both, but there's a price denom in the `fee_buyer_settlement_ratios` that isn't in `fee_seller_settlement_ratios`, then orders with that denom in their `price` cannot be settled. +If a market requires both, but there's a price denom in the `fee_seller_settlement_ratios` that isn't in `fee_buyer_settlement_ratios`, then bid orders with that denom in their `price` cannot be created, so ask orders with that price denom will have nothing to settle with. + +A `FeeRatio` can have a zero `fee` amount (but not a zero `price` amount), e.g. `1chicken:0chicken` is okay, but `0chicken:1chicken` is bad. +This allows a market to not charge a ratio fee for a specific `price` denom. + +A `FeeRatio` with the same `price` and `fee` denoms must have a larger price amount than fee amount. + + +#### Seller Settlement Ratio Fee + +A market's `fee_seller_settlement_ratios` are limited to `FeeRatio`s that have the same `price` and `fee` denom. +This ensures that the seller settlement fee can always be paid by the funds the seller is receiving. + +To calculate the seller settlement ratio fee, the following formula is used: ` * / `. +If that is not a whole number, it is rounded up to the next whole number. + +E.g. A market has `1000chicken:3chicken` in `fee_seller_settlement_ratios`. + +* An order is settling for `400chicken`: `400 * 3 / 1000` = `1.2`, which is rounded up to `2chicken`. +* An order is settling for `3000chicken`: `3000 * 3 / 1000` = `9`, which doesn't need rounding, so stays at `9chicken`. + +The actual amount isn't known until settlement, but a minimum can be calculated by applying the applicable ratio to an ask order's `price`. +The seller settlement ratio fee will be at least that amount, but since it gets larger slower than the price, ` - - ` is the least amount the seller will end up with. + + +#### Buyer Settlement Ratio Fee + +A market's `fee_buyer_settlement_ratios` can have `FeeRatios` with any denom pair, i.e. the `price` and `fee` do not need to be the same denom. +It can also have multiple entries with the same `price` denom or `fee` denom, but it can only have one entry for each `price` to `fee` denom pair. +E.g. a market can have `100chicken:1cow` and also `100chicken:7chicken`, `500cow:1cow`, and `5cow:1chicken`, but it couldn't also have `105chicken:2cow`. + +To calculate the buyer settlement ratio fee, the following formula is used: ` * / `. +If that is not a whole number, the chosen ratio is not applicable to the bid order's price and cannot be used. +The user will need to either use a different ratio or change their bid price. + +The buyer settlement ratio fee should be added to the buyer settlement flat fee and provided in the `buyer_settlement_fees` in the bid order. +The ratio and flat fees can be in any denoms allowed by the market, and do not have to be the same. + + +### Exchange Fees + +A portion of the fees collected by a market, are given to the exchange. +The amount is defined using basis points in the exchange module's [Params](06_params.md#params) and can be configured differently for specific denoms. + +When the market collects fees, the applicable basis points are looked up and applied to the amount being collected. +That amount is then transferred from the market's account to the chain's fee collector (similar to gas fees). + +The following formula is used for each denom in the fees being collected: ` * / 10,000`. +If that is not a whole number, it is rounded up to the next whole number. + +For example, Say the exchange has a default split of `500` (basis points), and a specific split of `100` for `rooster`. +When a market collects a fee of `1500hen,710rooster`: +There is no specific split for `hen`, so the default `500` is used for them. `1500 * 500 / 10,000` = `75hen` (a whole number, so no rounding is needed). +The specific `rooster` split of `100` is used for those: `710 * 100 / 10,000` = `7.1` which gets rounded up to `8rooster`. +So the market will first receive `1500hen,710rooster` from the buyer(s)/seller(s), then `75hen,8rooster` is transferred from the market to the fee collector. +The market is then left with `1425hen:702rooster`. + +During [MarketSettle](03_messages.md#marketsettle), the math and rounding is applied to the total fee being collected (as opposed to applying it to each order's fee first, then summing that). + +During order creation, the exchange's portion of the order creation fee is calculated and collected from the creation fee provided in the `Msg`. + +During [FillBids](03_messages.md#fillbids) or [FillAsks](03_messages.md#fillasks), the settlement fees are summed and collected separately from the order creation fee. +That means the math and rounding is done twice, once for the total settlement fees and again for the order creation fee. +This is done so that the fees are collected the same as if an order were created and later settled by the market. diff --git a/x/exchange/spec/02_state.md b/x/exchange/spec/02_state.md new file mode 100644 index 0000000000..710d6a7dd8 --- /dev/null +++ b/x/exchange/spec/02_state.md @@ -0,0 +1,283 @@ +# Exchange State + +The Exchange module manages several things in state. + +Big-endian ordering is used for all conversions between numbers and byte arrays. + +--- + + - [Params](#params) + - [Default Split](#default-split) + - [Specific Denom Split](#specific-denom-split) + - [Markets](#markets) + - [Market Create-Ask Flat Fee](#market-create-ask-flat-fee) + - [Market Create-Bid Flat Fee](#market-create-bid-flat-fee) + - [Market Seller Settlement Flat Fee](#market-seller-settlement-flat-fee) + - [Market Seller Settlement Ratio Fee](#market-seller-settlement-ratio-fee) + - [Market Buyer Settlement Flat Fee](#market-buyer-settlement-flat-fee) + - [Market Buyer Settlement Ratio Fee](#market-buyer-settlement-ratio-fee) + - [Market Inactive Indicator](#market-inactive-indicator) + - [Market User-Settle Indicator](#market-user-settle-indicator) + - [Market Permissions](#market-permissions) + - [Market Create-Ask Required Attributes](#market-create-ask-required-attributes) + - [Market Create-Bid Required Attributes](#market-create-bid-required-attributes) + - [Market Account](#market-account) + - [Market Details](#market-details) + - [Known Market ID](#known-market-id) + - [Last Market ID](#last-market-id) + - [Orders](#orders) + - [Ask Orders](#ask-orders) + - [Bid Orders](#bid-orders) + - [Last Order ID](#last-order-id) + - [Indexes](#indexes) + - [Market to Order](#market-to-order) + - [Owner Address to Order](#owner-address-to-order) + - [Asset Denom to Order](#asset-denom-to-order) + - [Market External ID to Order](#market-external-id-to-order) + + +## Params + +All params entries start with the type byte `0x00` followed by a string identifying the entry type. + +Each `` is stored as a `uint16` (2 bytes) in big-endian order. + +The byte `0x1E` is used in a few places as a record separator. + +See also: [Params](06_params.md#params). + + +### Default Split + +The default split defines the split amount (in basis points) the exchange receives of fees when there is not an applicable specific denom split. + +* Key:`0x00 | "split" (5 bytes)` +* Value: `` + + +### Specific Denom Split + +A specific denom split is a split amount (in basis points) the exchange receives of fees for fees paid in a specific denom. + +* Key: `0x00 | "split" (5 bytes) | ` +* Value: `` + +See also: [DenomSplit](06_params.md#denomsplit). + + +## Markets + +Each aspect of a market is stored separately for specific lookup. + +Each `` is a `uint32` (4 bytes) in big-endian order. + +Most aspects of a market have keys that start with the type byte `0x01`, followed by the `` then another type byte. + +See also: [Market](03_messages.md#market). + + +### Market Create-Ask Flat Fee + +One entry per configured denom. + +* Key: `0x01 | | 0x00 | ` +* Value: `` + + +### Market Create-Bid Flat Fee + +One entry per configured denom. + +* Key: `0x01 | | 0x01 | ` +* Value: `` + + +### Market Seller Settlement Flat Fee + +One entry per configured denom. + +* Key: `0x01 | | 0x02 | ` +* Value: `` + + +### Market Seller Settlement Ratio Fee + +One entry per configured price:fee denom pair. + +* Key: `0x01 | | 0x03 | | 0x1E | ` +* Value: ` | 0x1E | ` + +See also: [FeeRatio](03_messages.md#feeratio). + + +### Market Buyer Settlement Flat Fee + +One entry per configured denom. + +* Key: `0x01 | | 0x04 | ` +* Value: `` + + +### Market Buyer Settlement Ratio Fee + +One entry per configured price:fee denom pair. + +* Key: `0x01 | | 0x05 | | 0x1E | ` +* Value: ` | 0x1E | ` + +See also: [FeeRatio](03_messages.md#feeratio). + + +### Market Inactive Indicator + +When a market has `accepting_orders = false`, this state entry will exist. +When it has `accepting_orders = true`, this entry will not exist. + +* Key: `0x01 | | 0x06` +* Value: `` + + +### Market User-Settle Indicator + +When a market has `allow_user_settlement = true`, this state entry will exist. +When it has `allow_user_settlement = false`, this entry will not exist. + +* Key: `0x01 | | 0x07` +* Value: `` + + +### Market Permissions + +When an address has a given permission in a market, the following entry will exist. + +* Key: `0x01 | | 0x08 | | | ` +* Value: `` + +The `` is a single byte as `uint8` with the same values as the enum entries, e.g. `PERMISSION_CANCEL` is `0x03`. + +See also: [AccessGrant](03_messages.md#accessgrant) and [Permission](03_messages.md#permission). + + +### Market Create-Ask Required Attributes + +* Key: `0x01 | | 0x09 | 0x00` +* Value: `` + + +### Market Create-Bid Required Attributes + +* Key: `0x01 | | 0x09 | 0x01` +* Value: `` + + +### Market Account + +Each market has an associated `MarketAccount` with an address derived from the `market_id`. +Each `MarketAccount` is stored using the `Accounts` module. + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L14-L26 + + +### Market Details + +The [MarketDetails](03_messages.md#marketdetails) are stored as part of the `MarketAccount` (in the `x/auth` module). + + +### Known Market ID + +These entries are used to indicate that a given market exists. + +* Key: `0x07 | ` +* Value: `` + + +### Last Market ID + +This indicates the last market-id that was auto-selected for use. + +When a `MsgGovCreateMarketRequest` is processed that has a `market_id` of `0` (zero), the next available market id is auto selected. +Starting with the number after what's in this state entry, each market id is sequentially checked until an available one is found. +The new market gets that id, then this entry is then updated to indicate what that was. + +* Key: `0x06` +* Value: `` + +When a `MsgGovCreateMarketRequest` is processed that has a non-zero `market_id`, this entry is not considered or altered. + + +## Orders + +Each `` is a `uint64` (8 bytes) in big-endian order. + +Orders are stored using the following format: + +* Key: `0x02 | ` +* Value ` | protobuf(order type)` + +The `` has these possible values: +* `0x00` => Ask Order +* `0x01` => Bid Order + + +### Ask Orders + +* Key: `0x02 | ` +* Value: `0x00 | protobuf(AskOrder)` + +See also: [AskOrder](03_messages.md#askorder). + + +### Bid Orders + +* Key: `0x02 | ` +* Value: `0x01 | protobuf(BidOrder)` + +See also: [BidOrder](03_messages.md#bidorder). + + +### Last Order ID + +Whenever an order is created, this value is looked up and incremented to get the new order's id. +Then this entry is updated to reflect the new order. + +* Key: `0x08` +* Value: `` + + +## Indexes + +Several index entries are maintained to help facilitate look-ups. + +The `` values are the same as those described in [Orders](#orders). + + +### Market to Order + +This index can be used to find orders in a given market. + +* Key: `0x03 | | ` +* Value: `` + + +### Owner Address to Order + +This index can be used to find orders with a given buyer or seller. + +* Key: `0x04 | | | ` +* Value: `` + + +### Asset Denom to Order + +This index can be used to find orders involving a given `assets` denom. + +* Key: `0x05 | | ` +* Value: `` + + +### Market External ID to Order + +This index is used to look up orders by their market and external id. + +* Key: `0x09 | | ` +* Value: `` diff --git a/x/exchange/spec/03_messages.md b/x/exchange/spec/03_messages.md new file mode 100644 index 0000000000..b2e18557f9 --- /dev/null +++ b/x/exchange/spec/03_messages.md @@ -0,0 +1,472 @@ +# Exchange Messages + +The exchange module has `Msg` endpoints for users, markets, and governance proposals. + +--- + + - [User Endpoints](#user-endpoints) + - [CreateAsk](#createask) + - [CreateBid](#createbid) + - [CancelOrder](#cancelorder) + - [FillBids](#fillbids) + - [FillAsks](#fillasks) + - [Market Endpoints](#market-endpoints) + - [MarketSettle](#marketsettle) + - [MarketSetOrderExternalID](#marketsetorderexternalid) + - [MarketWithdraw](#marketwithdraw) + - [MarketUpdateDetails](#marketupdatedetails) + - [MarketUpdateEnabled](#marketupdateenabled) + - [MarketUpdateUserSettle](#marketupdateusersettle) + - [MarketManagePermissions](#marketmanagepermissions) + - [MarketManageReqAttrs](#marketmanagereqattrs) + - [Governance Proposals](#governance-proposals) + - [GovCreateMarket](#govcreatemarket) + - [GovManageFees](#govmanagefees) + - [GovUpdateParams](#govupdateparams) + + +## User Endpoints + +There are several endpoints available for all users, but some markets might have restrictions on their use. + + +### CreateAsk + +An ask order indicates the desire to sell some `assets` at a minimum `price`. +They are created using the `CreateAsk` endpoint. + +Markets can define a set of attributes that an account must have in order to create ask orders in them. +So, this endpoint might not be available, depending on the `seller` and the `market_id`. +Markets can also disable order creation altogether, making this endpoint unavailable for that `market_id`. + +It is expected to fail if: +* The `market_id` does not exist. +* The market is not allowing orders to be created. +* The market requires attributes in order to create ask orders and the `seller` is missing one or more. +* The `assets` are not in the `seller`'s account. +* The `price` is in a denom not supported by the market. +* The `seller_settlement_flat_fee` is in a denom different from the `price`, and is not in the `seller`'s account. +* The `seller_settlement_flat_fee` is insufficient (as dictated by the market). +* The `external_id` value is not empty and is already in use in the market. +* The `order_creation_fee` is not in the `seller`'s account. + +#### MsgCreateAskRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L68-L76 + +#### AskOrder + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/orders.proto#L28-L53 + +#### MsgCreateAskResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L78-L82 + + +### CreateBid + +A bid order indicates the desire to buy some `assets` at a specific `price`. +They are created using the `CreateBid` endpoint. + +Markets can define a set of attributes that an account must have in order to create bid orders in them. +So, this endpoint might not be available, depending on the `buyer` and the `market_id`. +Markets can also disable order creation altogether, making this endpoint unavailable for that `market_id`. + +It is expected to fail if: +* The `market_id` does not exist. +* The market is not allowing orders to be created. +* The market requires attributes in order to create bid orders and the `buyer` is missing one or more. +* The `price` funds are not in the `buyer`'s account. +* The `price` is in a denom not supported by the market. +* The `buyer_settlement_fees` are not in the `buyer`'s account. +* The `buyer_settlement_fees` are insufficient (as dictated by the market). +* The `external_id` value is not empty and is already in use in the market. +* The `order_creation_fee` is not in the `buyer`'s account. + +#### MsgCreateBidRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L84-L92 + +#### BidOrder + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/orders.proto#L55-L78 + +#### MsgCreateBidResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L94-L98 + + +### CancelOrder + +Orders can be cancelled using the `CancelOrder` endpoint. +When an order is cancelled, the hold on its funds is released and the order is deleted. + +Users can cancel their own orders at any time. +Market actors with the `PERMISSION_CANCEL` permission can also cancel orders in that market at any time. + +Order creation fees are **not** refunded when an order is cancelled. + +It is expected to fail if: +* The order does not exist. +* The `signer` is not one of: + * The order's owner (e.g. `buyer` or `seller`). + * An account with `PERMISSION_CANCEL` in the order's market. + * The governance module account (`authority`). + +#### MsgCancelOrderRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L100-L110 + +#### MsgCancelOrderResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L112-L113 + + +### FillBids + +If a market allows user-settlement, users can use the `FillBids` endpoint to settle one or more bids with their own `assets`. +This is similar to an "Immediate or cancel" `AskOrder` with the sum of the provided bids' assets and prices. +Fees are paid the same as if an `AskOrder` were actually created and settled normally with the provided bids. +The `seller` must be allowed to create an `AskOrder` in the given market. + +It is expected to fail if: +* The market does not exist. +* The market is not allowing orders to be created. +* The market does not allow user-settlement. +* The market requires attributes in order to create ask orders and the `seller` is missing one or more. +* One or more `bid_order_ids` are not bid orders (or do not exist). +* One or more `bid_order_ids` are in a market other than the provided `market_id`. +* The `total_assets` are not in the `seller`'s account. +* The sum of bid order `assets` does not equal the provided `total_assets`. +* The `seller` or one of the `buyer`s are sanctioned, or are not allowed to possess the funds they are to receive. +* The `seller_settlement_flat_fee` is insufficient. +* The `seller_settlement_flat_fee` is not in the `seller`'s account (after `assets` and `price` funds have been transferred). +* The `ask_order_creation_fee` is insufficient. +* The `ask_order_creation_fee` is not in the `seller`'s account (after all other transfers have been made). + +#### MsgFillBidsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L115-L135 + +#### MsgFillBidsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L137-L138 + + +### FillAsks + +If a market allows user-settlement, users can use the `FillAsks` endpoint to settle one or more asks with their own price funds. +This is similar to an "Immediate or cancel" `BidOrder` with the sum of the provided asks' assets and prices. +Fees are paid the same as if a `BidOrder` were actually created and settled normally with the provided asks. +The `buyer` must be allowed to create a `BidOrder` in the given market. + +It is expected to fail if: +* The market does not exist. +* The market is not allowing orders to be created. +* The market does not allow user-settlement. +* The market requires attributes in order to create bid orders and the `buyer` is missing one or more. +* One or more `ask_order_ids` are not ask orders (or do not exist). +* One or more `ask_order_ids` are in a market other than the provided `market_id`. +* The `total_price` funds are not in the `buyer`'s account. +* The sum of ask order `price`s does not equal the provided `total_price`. +* The `buyer` or one of the `seller`s are sanctioned, or are not allowed to possess the funds they are to receive. +* The `buyer_settlement_fees` are insufficient. +* The `buyer_settlement_fees` are not in the `buyer`'s account (after `assets` and `price` funds have been transferred). +* The `bid_order_creation_fee` is insufficient. +* The `bid_order_creation_fee` is not in the `buyer`'s account (after all other transfers have been made). + +#### MsgFillAsksRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L140-L161 + +#### MsgFillAsksResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L163-L164 + + +## Market Endpoints + +Several endpoints are only available to accounts designated by the market. +These are all also available for use in governance proposals using the governance module account (aka `authority`) as the `admin`. + + +### MarketSettle + +Orders are settled using the `MarketSettle` endpoint. +The `admin` must have the `PERMISSION_SETTLE` permission in the market (or be the `authority`). + +The market is responsible for identifying order matches. +Once identified, this endpoint is used to settle and clear the matched orders. + +All orders in a settlement must have the same asset denom and the same price denom. + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_SETTLE` in the market, and is not the `authority`. +* One or more `ask_order_ids` are not ask orders, or do not exist, or are in a market other than the provided `market_id`. +* One or more `bid_order_ids` are not bid orders, or do not exist, or are in a market other than the provided `market_id`. +* There is more than one denom in the `assets` of all the provided orders. +* There is more than one denom in the `price` of all the provided orders. +* The market requires a seller settlement ratio fee, but there is no ratio defined for the `price` denom. +* Two or more orders are being partially filled. +* One or more orders cannot be filled at all with the `assets` or `price` funds available in the settlement. +* An order is being partially filled, but `expect_partial` is `false`. +* All orders are being filled in full, but `expect_partial` is `true`. +* One or more of the `buyer`s and `seller`s are sanctioned, or are not allowed to possess the funds they are to receive. + +#### MsgMarketSettleRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L166-L183 + +#### MsgMarketSettleResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L185-L186 + + +### MarketSetOrderExternalID + +Some markets might want to attach their own identifiers to orders. +This is done using the `MarketSetOrderExternalID` endpoint. +The `admin` must have the `PERMISSION_SET_IDS` permission in the market (or be the `authority`). + +Orders with external ids can be looked up using the [GetOrderByExternalID](05_queries.md#getorderbyexternalid) query. + +External ids must be unique in a market, but multiple markets can use the same external id. + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_SET_IDS` in the market, and is not the `authority`. +* The order does not exist, or is in a different market than the provided `market_id`. +* The provided `external_id` equals the order's current `external_id`. +* The provided `external_id` is already associated with another order in the same market. + +#### MsgMarketSetOrderExternalIDRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L188-L202 + +#### MsgMarketSetOrderExternalIDResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L204-L205 + + +### MarketWithdraw + +When fees are collected by a market, they are given to the market's account. +Those funds can then be withdrawn/transferred using the `MarketWithdraw` endpoint. +The `admin` must have the `PERMISSION_WITHDRAW` permission in the market (or be the `authority`). + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_WITHDRAW` in the market, and is not the `authority`. +* The `amount` funds are not in the market's account. +* The `to_address` is not allowed to possess the requested funds. + +#### MsgMarketWithdrawRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L207-L221 + +#### MsgMarketWithdrawResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L223-L224 + + +### MarketUpdateDetails + +A market's details can be updated using the `MarketUpdateDetails` endpoint. +The `admin` must have the `PERMISSION_UPDATE` permission in the market (or be the `authority`). + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_UPDATE` in the market, and is not the `authority`. +* One or more of the [MarketDetails](#marketdetails) fields is too large. + +#### MsgMarketUpdateDetailsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L226-L237 + +See also: [MarketDetails](#marketdetails). + +#### MsgMarketUpdateDetailsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L239-L240 + + +### MarketUpdateEnabled + +A market can enable or disable order creation using the `MarketUpdateEnabled` endpoint. +The `admin` must have the `PERMISSION_UPDATE` permission in the market (or be the `authority`). + +With `accepting_orders` = `false`, no one can create any new orders in the market, but existing orders can still be settled or cancelled. + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_UPDATE` in the market, and is not the `authority`. +* The provided `accepting_orders` value equals the market's current setting. + +#### MsgMarketUpdateEnabledRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L242-L253 + +#### MsgMarketUpdateEnabledResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L255-L256 + + +### MarketUpdateUserSettle + +Using the `MarketUpdateUserSettle` endpoint, markets can control whether user-settlement is allowed. +The `admin` must have the `PERMISSION_UPDATE` permission in the market (or be the `authority`). + +The [FillBids](#fillbids) and [FillAsks](#fillasks) endpoints are only available for markets where `allow_user_settlement` = `true`. +The [MarketSettle](#marketsettle) endpoint is usable regardless of this setting. + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_UPDATE` in the market, and is not the `authority`. +* The provided `allow_user_settlement` value equals the market's current setting. + +#### MsgMarketUpdateUserSettleRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L258-L271 + +#### MsgMarketUpdateUserSettleResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L273-L274 + + +### MarketManagePermissions + +Permissions in a market are managed using the `MarketManagePermissions` endpoint. +The `admin` must have the `PERMISSION_PERMISSIONS` permission in the market (or be the `authority`). + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_PERMISSIONS` in the market, and is not the `authority`. +* One or more `revoke_all` addresses do not currently have any permissions in the market. +* One or more `to_revoke` entries do not currently exist in the market. +* One or more `to_grant` entries already exist in the market (after `revoke_all` and `to_revoke` are processed). + +#### MsgMarketManagePermissionsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L276-L291 + +See also: [AccessGrant](#accessgrant) and [Permission](#permission). + +#### MsgMarketManagePermissionsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L293-L295 + + +### MarketManageReqAttrs + +The attributes required to create orders in a market can be managed using the `MarketManageReqAttrs` endpoint. +The `admin` must have the `PERMISSION_ATTRIBUTES` permission in the market (or be the `authority`). + +See also: [Required Attributes](#required-attributes). + +It is expected to fail if: +* The market does not exist. +* The `admin` does not have `PERMISSION_ATTRIBUTES` in the market, and is not the `authority`. +* One or more attributes to add are already required by the market (for the given order type). +* One or more attributes to remove are not currently required by the market (for the given order type). + +#### MsgMarketManageReqAttrsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L296-L313 + +#### MsgMarketManageReqAttrsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L315-L316 + + +## Governance Proposals + +There are several governance-proposal-only endpoints. + + +### GovCreateMarket + +Market creation must be done via governance proposal with a `MsgGovCreateMarketRequest`. + +If the provided `market_id` is `0` (zero), the next available market id will be assigned to the new market. +If it is not zero, the provided `market_id` will be used (unless it's already in use by another market). +If it's already in use, the proposal will fail. + +It is recommended that the message be checked using the [ValidateCreateMarket](05_queries.md#validatecreatemarket) query first, to reduce the risk of failure or problems. + +It is expected to fail if: +* The provided `authority` is not the governance module's account. +* The provided `market_id` is not zero, and is already in use by another market. +* One or more of the [MarketDetails](#marketdetails) fields is too large. +* One or more required attributes are invalid. + +#### MsgGovCreateMarketRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L318-L329 + +#### Market + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L52-L103 + +#### MarketDetails + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L28-L40 + +* The `name` is limited to 250 characters max. +* The `description` is limited to 2000 characters max. +* The `website_url` is limited to 200 characters max. +* The `icon_uri` is limited to 2000 characters max. + +#### FeeRatio + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L105-L113 + +#### AccessGrant + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L115-L121 + +#### Permission + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L123-L141 + +#### MsgGovCreateMarketResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L331-L332 + + +### GovManageFees + +A market's fees can only be altered via governance proposal with a `MsgGovManageFeesRequest`. + +It is recommended that the message be checked using the [ValidateManageFees](05_queries.md#validatemanagefees) query first, to ensure the updated fees do not present any problems. + +It is expected to fail if: +* The provided `authority` is not the governance module's account. + +#### MsgGovManageFeesRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L334-L372 + +See also: [FeeRatio](#feeratio). + +#### MsgGovManageFeesResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L374-L375 + + +### GovUpdateParams + +The exchange module params are updated via governance proposal with a `MsgGovUpdateParamsRequest`. + +It is expected to fail if: +* The provided `authority` is not the governance module's account. + +#### MsgGovUpdateParamsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L377-L386 + +See also: [Params](06_params.md#params). + +#### MsgGovUpdateParamsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/tx.proto#L388-L389 diff --git a/x/exchange/spec/04_events.md b/x/exchange/spec/04_events.md new file mode 100644 index 0000000000..5290a41515 --- /dev/null +++ b/x/exchange/spec/04_events.md @@ -0,0 +1,240 @@ +# Exchange Events + +The exchange module emits several events for various actions. + +--- + + - [EventOrderCreated](#eventordercreated) + - [EventOrderCancelled](#eventordercancelled) + - [EventOrderFilled](#eventorderfilled) + - [EventOrderPartiallyFilled](#eventorderpartiallyfilled) + - [EventOrderExternalIDUpdated](#eventorderexternalidupdated) + - [EventMarketWithdraw](#eventmarketwithdraw) + - [EventMarketDetailsUpdated](#eventmarketdetailsupdated) + - [EventMarketEnabled](#eventmarketenabled) + - [EventMarketDisabled](#eventmarketdisabled) + - [EventMarketUserSettleEnabled](#eventmarketusersettleenabled) + - [EventMarketUserSettleDisabled](#eventmarketusersettledisabled) + - [EventMarketPermissionsUpdated](#eventmarketpermissionsupdated) + - [EventMarketReqAttrUpdated](#eventmarketreqattrupdated) + - [EventMarketCreated](#eventmarketcreated) + - [EventMarketFeesUpdated](#eventmarketfeesupdated) + - [EventParamsUpdated](#eventparamsupdated) + + +## EventOrderCreated + +Any time an order is created, an `EventOrderCreated` is emitted. + +Event Type: `provenance.exchange.v1.EventOrderCreated` + +| Attribute Key | Attribute Value | +|---------------|-----------------------------------------------------------| +| order_id | The id of the order just created. | +| order_type | The type of the order just created (e.g. "ask" or "bid"). | +| market_id | The id of the market that the order was created in. | +| external_id | The external id of the order just created. | + + +## EventOrderCancelled + +When an order is cancelled (either by the owner or the market), an `EventOrderCancelled` is emitted. + +Event Type: `provenance.exchange.v1.EventOrderCancelled` + +| Attribute Key | Attribute Value | +|---------------|-------------------------------------------------------------| +| order_id | The id of the cancelled order. | +| cancelled_by | The bech32 address of the account that cancelled the order. | +| market_id | The id of the market that the cancelled order was in. | +| external_id | The external id of the order that was just cancelled. | + + +## EventOrderFilled + +When an order is filled in full, an `EventOrderFilled` is emitted. + +This event indicates that an order has been settled, cleared, and deleted. + +Event Type: `provenance.exchange.v1.EventOrderFilled` + +| Attribute Key | Attribute Value | +|---------------|------------------------------------------------------| +| order_id | The id of the settled order. | +| assets | The assets that were bought or sold (`Coin` string). | +| price | The price received (`Coin` string). | +| fees | The fees paid to settle the order (`Coins` string). | +| market_id | The id of the market that the order was in. | +| external_id | The external id of the order. | + +The `assets`, `price`, and `fees`, reflect the funds that were actually transferred. +E.g. when an ask order is settled for a higher price than set in the order, the `price` reflects what the seller actually received. +Similarly, the `fees` reflect the actual settlement fees paid (both flat and ratio) by the order's owner. + +If an order was previously partially filled, but now, the rest is being filled, this event is emitted. + + +## EventOrderPartiallyFilled + +When an order is partially filled, an `EventOrderPartiallyFilled` is emitted. + +This event indicates that some of an order was filled, but that the order has been reduced and still exists. + +Event Type: `provenance.exchange.v1.EventOrderPartiallyFilled` + +| Attribute Key | Attribute Value | +|---------------|--------------------------------------------------------------------------| +| order_id | The id of the partially settled order. | +| assets | The assets that were bought or sold (`Coin` string). | +| price | The price received (`Coin` string). | +| fees | The fees paid for the partial settlement of this order (`Coins` string). | +| market_id | The id of the market that the order is in. | +| external_id | The external id of the order. | + +The `assets`, `price`, and `fees`, reflect the funds that were actually transferred. + +If an order was previously partially filled, but now, the rest is being filled, an `EventOrderFilled` is emitted. + + +## EventOrderExternalIDUpdated + +When an order's external id is updated, an `EventOrderExternalIDUpdated` is emitted. + +Event Type: `provenance.exchange.v1.EventOrderExternalIDUpdated` + +| Attribute Key | Attribute Value | +|----------------|--------------------------------------------| +| order_id | The id of the updated order. | +| market_id | The id of the market that the order is in. | +| external_id | The new external id of the order. | + + +## EventMarketWithdraw + +Any time a market's funds are withdrawn, an `EventMarketWithdraw` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketWithdraw` + +| Attribute Key | Attribute Value | +|---------------|--------------------------------------------------------------------------| +| market_id | The id of the market the funds were withdrawn from. | +| amount | The funds withdrawn (`Coins` string). | +| destination | The bech32 address string of the account that received the funds. | +| withdrawn_by | The bech32 address string of the admin account that made the withdrawal. | + + +## EventMarketDetailsUpdated + +When a market's details are updated, an `EventMarketDetailsUpdated` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketDetailsUpdated` + +| Attribute Key | Attribute Value | +|---------------|-----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketEnabled + +When a market's `accepting_orders` changes from `false` to `true`, an `EventMarketEnabled` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketEnabled` + +| Attribute Key | Attribute Value | +|---------------|----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketDisabled + +When a market's `accepting_orders` changes from `true` to `false`, an `EventMarketDisabled` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketDisabled` + +| Attribute Key | Attribute Value | +|---------------|----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketUserSettleEnabled + +When a market's `allow_user_settlement` changes from `false` to `true`, an `EventMarketUserSettleEnabled` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketUserSettleEnabled` + +| Attribute Key | Attribute Value | +|---------------|----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketUserSettleDisabled + +When a market's `allow_user_settlement` changes from `true` to `false`, an `EventMarketUserSettleDisabled` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketUserSettleDisabled` + +| Attribute Key | Attribute Value | +|---------------|----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketPermissionsUpdated + +Any time a market's permissions are managed, an `EventMarketPermissionsUpdated` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketPermissionsUpdated` + +| Attribute Key | Attribute Value | +|---------------|----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketReqAttrUpdated + +When a market's required attributes are altered, an `EventMarketReqAttrUpdated` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketReqAttrUpdated` + +| Attribute Key | Attribute Value | +|---------------|----------------------------------------------------------------------| +| market_id | The id of the updated market. | +| updated_by | The bech32 address string of the admin account that made the change. | + + +## EventMarketCreated + +When a market is created, an `EventMarketCreated` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketCreated` + +| Attribute Key | Attribute Value | +|---------------|---------------------------| +| market_id | The id of the new market. | + + +## EventMarketFeesUpdated + +When a market's fees are updated, an `EventMarketFeesUpdated` is emitted. + +Event Type: `provenance.exchange.v1.EventMarketFeesUpdated` + +| Attribute Key | Attribute Value | +|---------------|-------------------------------| +| market_id | The id of the updated market. | + + +## EventParamsUpdated + +An `EventParamsUpdated` is emitted when the exchange module's params are changed. + +Event Type: `provenance.exchange.v1.EventParamsUpdated` + +| Attribute Key | Attribute Value | +|---------------|-----------------| +| (none) | | diff --git a/x/exchange/spec/05_queries.md b/x/exchange/spec/05_queries.md new file mode 100644 index 0000000000..1dec79ce45 --- /dev/null +++ b/x/exchange/spec/05_queries.md @@ -0,0 +1,256 @@ +# Exchange Queries + +There are several queries for getting information about things in the exchange module. + +--- + + - [OrderFeeCalc](#orderfeecalc) + - [GetOrder](#getorder) + - [GetOrderByExternalID](#getorderbyexternalid) + - [GetMarketOrders](#getmarketorders) + - [GetOwnerOrders](#getownerorders) + - [GetAssetOrders](#getassetorders) + - [GetAllOrders](#getallorders) + - [GetMarket](#getmarket) + - [GetAllMarkets](#getallmarkets) + - [Params](#params) + - [ValidateCreateMarket](#validatecreatemarket) + - [ValidateMarket](#validatemarket) + - [ValidateManageFees](#validatemanagefees) + + +## OrderFeeCalc + +The `OrderFeeCalc` query is used to find out the various required fee options for a given order. +The idea is that you can provide your [AskOrder](03_messages.md#askorder) or [BidOrder](03_messages.md#bidorder) in this query in order to identify what fees you'll need to pay. + +Either an `ask_order` or a `bid_order` must be provided, but not both. + +Each response field is a list of options available for the requested order. +If a response field is empty, then no fee of that type is required. + +When creating the `AskOrder`, choose one entry from `creation_fee_options` to provide as the `order_creation_fee`. +Then, choose one entry from `settlement_flat_fee_options` and provide that as the `seller_settlement_flat_fee`. +For ask orders, the `settlement_ratio_fee_options` is purely informational and is the minimum that seller's settlement ratio fee that will be for the order. + +When creating the `BidOrder`, choose one entry from `creation_fee_options` to provide as the `order_creation_fee`. +Then choose one entry from each of `settlement_flat_fee_options` and `settlement_ratio_fee_options`, add them together, and provide that as the `buyer_settlement_fees`. + +### QueryOrderFeeCalcRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L96-L103 + +See also: [AskOrder](03_messages.md#askorder), and [BidOrder](03_messages.md#bidorder). + +### QueryOrderFeeCalcResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L105-L124 + + +## GetOrder + +Use the `GetOrder` query to look up an order by its id. + +### QueryGetOrderRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L126-L130 + +### QueryGetOrderResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L132-L136 + +### Order + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/orders.proto#L13-L26 + +See also: [AskOrder](03_messages.md#askorder), and [BidOrder](03_messages.md#bidorder). + + +## GetOrderByExternalID + +Orders with external ids can be looked up using the `GetOrderByExternalID` query. + +### QueryGetOrderByExternalIDRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L138-L144 + +### QueryGetOrderByExternalIDResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L146-L150 + +See also: [Order](#order). + + +## GetMarketOrders + +To get all of the orders in a given market, use the `GetMarketOrders` query. +Results can be optionally limited by order type (e.g. "ask" or "bid") and/or a minimum (exclusive) order id. + +This query is paginated. + +### QueryGetMarketOrdersRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L152-L163 + +### QueryGetMarketOrdersResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L165-L172 + +See also: [Order](#order). + + +## GetOwnerOrders + +To get all of the orders with a specific owner (e.g. buyer or seller), use the `GetOwnerOrders` query. +Results can be optionally limited by order type (e.g. "ask" or "bid") and/or a minimum (exclusive) order id. + +This query is paginated. + +### QueryGetOwnerOrdersRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L174-L185 + +### QueryGetOwnerOrdersResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L187-L194 + +See also: [Order](#order). + + +## GetAssetOrders + +To get all of the orders with a specific asset denom, use the `GetAssetOrders` query. +Results can be optionally limited by order type (e.g. "ask" or "bid") and/or a minimum (exclusive) order id. + +This query is paginated. + +### QueryGetAssetOrdersRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L196-L207 + +### QueryGetAssetOrdersResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L209-L216 + +See also: [Order](#order). + + +## GetAllOrders + +To get all existing orders, use the `GetAllOrders` query. + +This query is paginated. + +### QueryGetAllOrdersRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L218-L222 + +### QueryGetAllOrdersResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L224-L231 + +See also: [Order](#order). + + +## GetMarket + +All the information and setup for a market can be looked up using the `GetMarket` query. + +### QueryGetMarketRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L233-L237 + +### QueryGetMarketResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L239-L245 + +See also: [Market](03_messages.md#market). + + +## GetAllMarkets + +Use the `GetAllMarkets` query to get brief information about all markets. + +### QueryGetAllMarketsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L247-L251 + +### QueryGetAllMarketsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L253-L260 + +### MarketBrief + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/market.proto#L42-L50 + + +## Params + +The exchange module params can be looked up using the `Params` query. + +### QueryParamsRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L262-L263 + +### QueryParamsResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L265-L269 + +See also: [Params](06_params.md#params). + + +## ValidateCreateMarket + +It's possible for a [MsgGovCreateMarketRequest](03_messages.md#msggovcreatemarketrequest) to result in a market setup that is problematic. +To verify that one is not problematic, this `ValidateCreateMarket` can be used. + +If the result has: +* `gov_prop_will_pass` = `false`, then either submitting the proposal will fail, or the `Msg` will result in an error ("failed") after the proposal is passed. The `error` field will have details. +* `gov_prop_will_pass` = `true` and a non-empty `error` field, then the `Msg` would successfully run, but would result in the problems identified in the `error` field. +* `gov_prop_will_pass` = `true` and an empty `error` field, then there are no problems with the provided `Msg`. + +### QueryValidateCreateMarketRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L271-L275 + +See also: [MsgGovCreateMarketRequest](03_messages.md#msggovcreatemarketrequest). + +### QueryValidateCreateMarketResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L277-L287 + + +## ValidateMarket + +An existing market's setup can be checked for problems using the `ValidateMarket` query. + +Any problems detected will be returned in the `error` field. + +### QueryValidateMarketRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L289-L293 + +### QueryValidateMarketResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L295-L299 + + +## ValidateManageFees + +It's possible for a [MsgGovManageFeesRequest](03_messages.md#msggovmanagefeesrequest) to result in a problematic setup for a market. +To verify that one does not result in such a state, use this `ValidateManageFees` query. + +If the result has: +* `gov_prop_will_pass` = `false`, then either submitting the proposal will fail, or the `Msg` will result in an error ("failed") after the proposal is passed. The `error` field will have details. +* `gov_prop_will_pass` = `true` and a non-empty `error` field, then the `Msg` would successfully run, but would result in the problems identified in the `error` field. +* `gov_prop_will_pass` = `true` and an empty `error` field, then there are no problems with the provided `Msg`. + +### QueryValidateManageFeesRequest + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L301-L305 + +See also: [MsgGovManageFeesRequest](03_messages.md#msggovmanagefeesrequest). + +### QueryValidateManageFeesResponse + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/query.proto#L307-L317 diff --git a/x/exchange/spec/06_params.md b/x/exchange/spec/06_params.md new file mode 100644 index 0000000000..d2450a867c --- /dev/null +++ b/x/exchange/spec/06_params.md @@ -0,0 +1,25 @@ +# Exchange Params + +The exchange module params dictate how much of the fees (collected by markets) go to the exchange/chain. +The split values are in basis points and are limited to between `0` and `10,000` (both inclusive). +The `default_split` is used when a specific `DenomSplit` does not exist for a given denom. + +* A split of `0` is 0% and would mean that the exchange receives none of the fees (of the applicable denom), and the market keeps all of it. +* A split of `500` is 5%, and would mean that the exchange receives 5% of the fees (of the applicable denom) collected by any market, and the market keeps 95%. +* A split of `10,000` is 100% and would mean that the exchange receives all of the fees (of the applicable denom) and the market gets nothing. + +The default `Params` have a `default_split` of `500` and no `DenomSplit`s. + +Params are set using the [GovUpdateParams](03_messages.md#govupdateparams) governance proposal endpoint. + +The current params can be looked up using the [Params](05_queries.md#params) query. + +See also: [Exchange Fees](01_concepts.md#exchange-fees). + +## Params + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/params.proto#L11-L19 + +## DenomSplit + ++++ https://github.com/provenance-io/provenance/blob/v1.17.0/proto/provenance/exchange/v1/params.proto#L21-L28 diff --git a/x/exchange/spec/README.md b/x/exchange/spec/README.md index 898659b4a8..74eb52792f 100644 --- a/x/exchange/spec/README.md +++ b/x/exchange/spec/README.md @@ -2,9 +2,9 @@ ## Overview -The exchange module is used to facilitate the buying and selling of on-chain assets. - - +The exchange module is used to facilitate the trading of on-chain assets. +Funds being traded remain (on hold) in the buyers' and sellers' accounts. +Settlement is done directly between the two parties without the funds touching a 3rd party's account. ## Contents diff --git a/x/marker/spec/01_state.md b/x/marker/spec/01_state.md index 92c08e484e..70059aaede 100644 --- a/x/marker/spec/01_state.md +++ b/x/marker/spec/01_state.md @@ -8,6 +8,7 @@ - [Forced Transfers](#forced-transfers) - [Required Attributes](#required-attributes) - [Marker Address Cache](#marker-address-cache) + - [Marker Net Asset Value](#marker-net-asset-value) - [Params](#params) diff --git a/x/marker/spec/03_messages.md b/x/marker/spec/03_messages.md index 049cbf1ccc..38f9438aa0 100644 --- a/x/marker/spec/03_messages.md +++ b/x/marker/spec/03_messages.md @@ -5,7 +5,6 @@ All created/modified state objects specified by each message are defined within [state](./02_state_transitions.md) section. -- [Messages](#messages) - [Msg/AddMarkerRequest](#msgaddmarkerrequest) - [Msg/AddAccessRequest](#msgaddaccessrequest) - [Msg/DeleteAccessRequest](#msgdeleteaccessrequest) @@ -425,4 +424,4 @@ This service message is expected to fail if: - No marker with the provided denom exists. - The signer is the governance module account address but the marker does not allow governance control. - The signer is not the governance module account and does not have any access on the marker. -- The provided net value asset properties are invalid. \ No newline at end of file +- The provided net value asset properties are invalid. diff --git a/x/marker/spec/10_governance.md b/x/marker/spec/10_governance.md index 11085ae468..021dc42b56 100644 --- a/x/marker/spec/10_governance.md +++ b/x/marker/spec/10_governance.md @@ -5,7 +5,6 @@ marker to be defined where no single account is allowed to make modifications an issue change requests through passing a governance proposal. -- [Governance Proposal Control](#governance-proposal-control) - [Add Marker Proposal](#add-marker-proposal) - [Supply Increase Proposal](#supply-increase-proposal) - [Supply Decrease Proposal](#supply-decrease-proposal)