Terminology (#4995)

* update exchange program: tradeOrder->Order, tradeRequest->OrderRequest, tradeCancel->OrderCancel

* Update bench-exchange: tradeOrder -> Order

* update bench exchange Readme
This commit is contained in:
Patrick Amato 2019-07-10 23:22:33 -06:00 committed by GitHub
parent 2abbc89dcd
commit bd92f37553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 88 deletions

View File

@ -6,10 +6,10 @@ learn how to start and interact with the exchange.
### Table of Contents
[Overview](#Overview)<br>
[Premiss](#Premiss)<br>
[Premise](#Premise)<br>
[Exchange startup](#Exchange-startup)<br>
[Trade requests](#Trade-requests)<br>
[Trade cancellations](#Trade-cancellations)<br>
[Order Requests](#Trade-requests)<br>
[Order Cancellations](#Trade-cancellations)<br>
[Trade swap](#Trade-swap)<br>
[Exchange program operations](#Exchange-program-operations)<br>
[Quotes and OHLCV](#Quotes-and-OHLCV)<br>
@ -22,9 +22,9 @@ An exchange is a marketplace where one asset can be traded for another. This
demo demonstrates one way to host an exchange on the Solana blockchain by
emulating a currency exchange.
The assets are virtual tokens held by investors who may post trade requests to
The assets are virtual tokens held by investors who may post order requests to
the exchange. A Swapper monitors the exchange and posts swap requests for
matching trade orders. All the transactions can execute concurrently.
matching orders. All the transactions can execute concurrently.
## Premise
@ -59,43 +59,43 @@ matching trade orders. All the transactions can execute concurrently.
ratios are represented as fixed point numbers. The fixed point scaler is
defined in
[exchange_state.rs](https://github.com/solana-labs/solana/blob/c2fdd1362a029dcf89c8907c562d2079d977df11/programs/exchange_api/src/exchange_state.rs#L7)
- Trade request
- Order request
- A Solana transaction executed by the exchange requesting the trade of one
type of token for another. Trade requests are made up of the token pair,
type of token for another. order requests are made up of the token pair,
the direction of the trade, quantity of the primary token, the price ratio,
and the two token accounts to be credited/deducted. An example trade
request looks like "T AB 5 2" which reads "Exchange 5 A tokens to B tokens
at a price ratio of 1:2" A fulfilled trade would result in 5 A tokens
deducted and 10 B tokens credited to the trade initiator's token accounts.
Successful trade requests result in a trade order.
- Trade order
- The result of a successful trade request. Trade orders are stored in
accounts owned by the submitter of the trade request. They can only be
Successful order requests result in an order.
- Order
- The result of a successful order request. orders are stored in
accounts owned by the submitter of the order request. They can only be
canceled by their owner but can be used by anyone in a trade swap. They
contain the same information as the trade request.
contain the same information as the order request.
- Price spread
- The difference between the two matching trade orders. The spread is the
- The difference between the two matching orders. The spread is the
profit of the Swapper initiating the swap request.
- Swap requirements
- Policies that result in a successful trade swap.
- Swap request
- A request to exchange tokens between to trade orders
- A request to exchange tokens between to orders
- Trade swap
- A successful trade. A swap consists of two matching trade orders that meet
- A successful trade. A swap consists of two matching orders that meet
swap requirements. A trade swap may not wholly satisfy one or both of the
trade orders in which case the trade orders are adjusted appropriately. As
orders in which case the orders are adjusted appropriately. As
long as the swap requirements are met there will be an exchange of tokens
between accounts. Any price spread is deposited into the Swapper's profit
account. All trade swaps are recorded in a new account for posterity.
- Investor
- Individual investors who hold a number of tokens and wish to trade them on
the exchange. Investors operate as Solana thin clients who own a set of
accounts containing tokens and/or trade requests. Investors post
accounts containing tokens and/or order requests. Investors post
transactions to the exchange in order to request tokens and post or cancel
trade requests.
order requests.
- Swapper
- An agent who facilitates trading between investors. Swappers operate as
Solana thin clients who monitor all the trade orders looking for a trade
Solana thin clients who monitor all the orders looking for a trade
match. Once found, the Swapper issues a swap request to the exchange.
Swappers are the engine of the exchange and are rewarded for their efforts by
accumulating the price spreads of the swaps they initiate. Swappers also
@ -123,7 +123,7 @@ the investors that trades submitted after that point will be analyzed. <!--This
is not ideal, and instead investors should be able to submit trades at any time,
and the Swapper could come and go without missing a trade. One way to achieve
this is for the Swapper to read the current state of all accounts looking for all
open trade orders.-->
open orders.-->
Investors will initially query the exchange to discover their current balance
for each type of token. If the investor does not already have an account for
@ -181,19 +181,19 @@ pub enum ExchangeInstruction {
}
```
## Trade requests
## Order Requests
When an investor decides to exchange a token of one type for another, they
submit a transaction to the Solana Blockchain containing a trade request, which,
if successful, is turned into a trade order. Trade orders do not expire but are
cancellable. <!-- Trade orders should have a timestamp to enable trade
expiration --> When a trade order is created, tokens are deducted from a token
account and the trade order acts as an escrow. The tokens are held until the
trade order is fulfilled or canceled. If the direction is `To`, then the number
submit a transaction to the Solana Blockchain containing an order request, which,
if successful, is turned into an order. orders do not expire but are
cancellable. <!-- orders should have a timestamp to enable trade
expiration --> When an order is created, tokens are deducted from a token
account and the order acts as an escrow. The tokens are held until the
order is fulfilled or canceled. If the direction is `To`, then the number
of `tokens` are deducted from the primary account, if `From` then `tokens`
multiplied by `price` are deducted from the secondary account. Trade orders are
multiplied by `price` are deducted from the secondary account. orders are
no longer valid when the number of `tokens` goes to zero, at which point they
can no longer be used. <!-- Could support refilling trade orders, so trade order
can no longer be used. <!-- Could support refilling orders, so order
accounts are refilled rather than accumulating -->
```rust
@ -205,7 +205,7 @@ pub enum Direction {
From,
}
pub struct TradeRequestInfo {
pub struct OrderRequestInfo {
/// Direction of trade
pub direction: Direction,
@ -224,7 +224,7 @@ pub struct TradeRequestInfo {
}
pub enum ExchangeInstruction {
/// Trade request
/// order request
/// key 0 - Signer
/// key 1 - Account in which to record the swap
/// key 2 - Token account associated with this trade
@ -233,7 +233,7 @@ pub enum ExchangeInstruction {
/// Trade accounts are populated with this structure
pub struct TradeOrderInfo {
/// Owner of the trade order
/// Owner of the order
pub owner: Pubkey,
/// Direction of the exchange
pub direction: Direction,
@ -252,7 +252,7 @@ pub struct TradeOrderInfo {
}
```
## Trade cancellations
## Order cancellations
An investor may cancel a trade at anytime, but only trades they own. If the
cancellation is successful, any tokens held in escrow are returned to the
@ -260,9 +260,9 @@ account from which they came.
```rust
pub enum ExchangeInstruction {
/// Trade cancellation
/// order cancellation
/// key 0 - Signer
/// key 1 -Trade order to cancel
/// key 1 -order to cancel
TradeCancellation,
}
```
@ -270,14 +270,14 @@ pub enum ExchangeInstruction {
## Trade swaps
The Swapper is monitoring the accounts assigned to the exchange program and
building a trade-order table. The trade order table is used to identify
matching trade orders which could be fulfilled. When a match is found the
building a trade-order table. The order table is used to identify
matching orders which could be fulfilled. When a match is found the
Swapper should issue a swap request. Swap requests may not satisfy the entirety
of either order, but the exchange will greedily fulfill it. Any leftover tokens
in either account will keep the trade order valid for further swap requests in
in either account will keep the order valid for further swap requests in
the future.
Matching trade orders are defined by the following swap requirements:
Matching orders are defined by the following swap requirements:
- Opposite polarity (one `To` and one `From`)
- Operate on the same token pair
@ -379,8 +379,8 @@ pub enum ExchangeInstruction {
/// Trade swap request
/// key 0 - Signer
/// key 1 - Account in which to record the swap
/// key 2 - 'To' trade order
/// key 3 - `From` trade order
/// key 2 - 'To' order
/// key 3 - `From` order
/// key 4 - Token account associated with the To Trade
/// key 5 - Token account associated with From trade
/// key 6 - Token account in which to deposit the Swappers profit from the swap.
@ -391,9 +391,9 @@ pub enum ExchangeInstruction {
pub struct TradeSwapInfo {
/// Pair swapped
pub pair: TokenPair,
/// `To` trade order
/// `To` order
pub to_trade_order: Pubkey,
/// `From` trade order
/// `From` order
pub from_trade_order: Pubkey,
/// Number of primary tokens exchanged
pub primary_tokens: u64,
@ -424,22 +424,22 @@ pub enum ExchangeInstruction {
/// the exchange has a limitless number of tokens it can transfer.
TransferRequest(Token, u64),
/// Trade request
/// order request
/// key 0 - Signer
/// key 1 - Account in which to record the swap
/// key 2 - Token account associated with this trade
TradeRequest(TradeRequestInfo),
/// Trade cancellation
/// order cancellation
/// key 0 - Signer
/// key 1 -Trade order to cancel
/// key 1 -order to cancel
TradeCancellation,
/// Trade swap request
/// key 0 - Signer
/// key 1 - Account in which to record the swap
/// key 2 - 'To' trade order
/// key 3 - `From` trade order
/// key 2 - 'To' order
/// key 3 - `From` order
/// key 4 - Token account associated with the To Trade
/// key 5 - Token account associated with From trade
/// key 6 - Token account in which to deposit the Swappers profit from the swap.
@ -478,6 +478,3 @@ To also see the cluster messages:
```bash
$ RUST_LOG=solana_bench_exchange=info,solana=info cargo test --release -- --nocapture test_exchange_local_cluster
```

View File

@ -332,7 +332,7 @@ fn do_tx_transfers<T>(
struct TradeInfo {
trade_account: Pubkey,
order_info: TradeOrderInfo,
order_info: OrderInfo,
}
#[allow(clippy::too_many_arguments)]
fn swapper<T>(
@ -538,7 +538,7 @@ fn trader<T>(
} else {
Direction::To
};
let order_info = TradeOrderInfo {
let order_info = OrderInfo {
/// Owner of the trade order
owner: Pubkey::default(), // don't care
direction,

View File

@ -10,7 +10,7 @@ use std::{error, fmt};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ToOrder {
pub pubkey: Pubkey,
pub info: TradeOrderInfo,
pub info: OrderInfo,
}
impl Ord for ToOrder {
@ -26,7 +26,7 @@ impl PartialOrd for ToOrder {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FromOrder {
pub pubkey: Pubkey,
pub info: TradeOrderInfo,
pub info: OrderInfo,
}
impl Ord for FromOrder {
@ -95,11 +95,7 @@ impl OrderBook {
// pub fn cancel(&mut self, pubkey: Pubkey) -> Result<(), Box<dyn error::Error>> {
// Ok(())
// }
pub fn push(
&mut self,
pubkey: Pubkey,
info: TradeOrderInfo,
) -> Result<(), Box<dyn error::Error>> {
pub fn push(&mut self, pubkey: Pubkey, info: OrderInfo) -> Result<(), Box<dyn error::Error>> {
check_trade(info.direction, info.tokens, info.price)?;
match info.direction {
Direction::To => {

View File

@ -7,7 +7,7 @@ use solana_sdk::instruction::{AccountMeta, Instruction};
use solana_sdk::pubkey::Pubkey;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct TradeRequestInfo {
pub struct OrderRequestInfo {
/// Direction of trade
pub direction: Direction,
@ -35,16 +35,16 @@ pub enum ExchangeInstruction {
/// the exchange has a limitless number of tokens it can transfer.
TransferRequest(Token, u64),
/// Trade request
/// Order request
/// key 0 - Signer
/// key 1 - Account in which to record the trade order
/// key 2 - Token account to source tokens from
TradeRequest(TradeRequestInfo),
OrderRequest(OrderRequestInfo),
/// Trade cancellation
/// Order cancellation
/// key 0 - Signer
/// key 1 - Trade order to cancel
TradeCancellation,
/// key 1 - Order to cancel
OrderCancellation,
/// Trade swap request
/// key 0 - Signer
@ -97,7 +97,7 @@ pub fn trade_request(
];
Instruction::new(
id(),
&ExchangeInstruction::TradeRequest(TradeRequestInfo {
&ExchangeInstruction::OrderRequest(OrderRequestInfo {
direction,
pair,
tokens,
@ -107,12 +107,12 @@ pub fn trade_request(
)
}
pub fn trade_cancellation(owner: &Pubkey, trade: &Pubkey) -> Instruction {
pub fn order_cancellation(owner: &Pubkey, order: &Pubkey) -> Instruction {
let account_metas = vec![
AccountMeta::new(*owner, true),
AccountMeta::new(*trade, false),
AccountMeta::new(*order, false),
];
Instruction::new(id(), &ExchangeInstruction::TradeCancellation, account_metas)
Instruction::new(id(), &ExchangeInstruction::OrderCancellation, account_metas)
}
pub fn swap_request(

View File

@ -39,7 +39,7 @@ impl ExchangeProcessor {
}
}
fn deserialize_trade(data: &[u8]) -> Result<TradeOrderInfo, InstructionError> {
fn deserialize_trade(data: &[u8]) -> Result<OrderInfo, InstructionError> {
let state: ExchangeState = bincode::deserialize(data).map_err(Self::map_to_invalid_arg)?;
if let ExchangeState::Trade(info) = state {
Ok(info)
@ -60,7 +60,7 @@ impl ExchangeProcessor {
}
}
fn trade_to_token_account(trade: &TradeOrderInfo) -> TokenAccountInfo {
fn trade_to_token_account(trade: &OrderInfo) -> TokenAccountInfo {
// Turn trade order into token account
let token = match trade.direction {
@ -75,8 +75,8 @@ impl ExchangeProcessor {
fn calculate_swap(
scaler: u64,
to_trade: &mut TradeOrderInfo,
from_trade: &mut TradeOrderInfo,
to_trade: &mut OrderInfo,
from_trade: &mut OrderInfo,
profit_account: &mut TokenAccountInfo,
) -> Result<(), InstructionError> {
if to_trade.tokens == 0 || from_trade.tokens == 0 {
@ -261,7 +261,7 @@ impl ExchangeProcessor {
fn do_trade_request(
keyed_accounts: &mut [KeyedAccount],
info: &TradeRequestInfo,
info: &OrderRequestInfo,
) -> Result<(), InstructionError> {
const OWNER_INDEX: usize = 0;
const TRADE_INDEX: usize = 1;
@ -299,7 +299,7 @@ impl ExchangeProcessor {
inc_new_counter_info!("exchange_processor-trades", 1, 1000, 1000);
Self::serialize(
&ExchangeState::Trade(TradeOrderInfo {
&ExchangeState::Trade(OrderInfo {
owner: *keyed_accounts[OWNER_INDEX].unsigned_key(),
direction: info.direction,
pair: info.pair,
@ -315,7 +315,7 @@ impl ExchangeProcessor {
)
}
fn do_trade_cancellation(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
fn do_order_cancellation(keyed_accounts: &mut [KeyedAccount]) -> Result<(), InstructionError> {
const OWNER_INDEX: usize = 0;
const TRADE_INDEX: usize = 1;
@ -446,11 +446,11 @@ pub fn process_instruction(
ExchangeInstruction::TransferRequest(token, tokens) => {
ExchangeProcessor::do_transfer_request(keyed_accounts, token, tokens)
}
ExchangeInstruction::TradeRequest(info) => {
ExchangeInstruction::OrderRequest(info) => {
ExchangeProcessor::do_trade_request(keyed_accounts, &info)
}
ExchangeInstruction::TradeCancellation => {
ExchangeProcessor::do_trade_cancellation(keyed_accounts)
ExchangeInstruction::OrderCancellation => {
ExchangeProcessor::do_order_cancellation(keyed_accounts)
}
ExchangeInstruction::SwapRequest => ExchangeProcessor::do_swap_request(keyed_accounts),
}
@ -487,8 +487,8 @@ mod test {
secondary_tokens,
secondary_price,
);
let mut to_trade = TradeOrderInfo::default();
let mut from_trade = TradeOrderInfo::default().direction(Direction::From);
let mut to_trade = OrderInfo::default();
let mut from_trade = OrderInfo::default().direction(Direction::From);
let mut profit_account = TokenAccountInfo::default();
to_trade.tokens = primary_tokens;
@ -714,7 +714,7 @@ mod test {
// check results
assert_eq!(
TradeOrderInfo {
OrderInfo {
owner: owner.pubkey(),
direction: Direction::To,
pair: TokenPair::AB,
@ -773,7 +773,7 @@ mod test {
// check results
assert_eq!(
TradeOrderInfo {
OrderInfo {
owner: owner.pubkey(),
direction: Direction::To,
pair: TokenPair::AB,

View File

@ -150,7 +150,7 @@ impl fmt::Display for Direction {
/// Trade accounts are populated with this structure
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TradeOrderInfo {
pub struct OrderInfo {
/// Owner of the trade order
pub owner: Pubkey,
/// Direction of the exchange
@ -167,7 +167,7 @@ pub struct TradeOrderInfo {
/// token account by the owner.
pub tokens_settled: u64,
}
impl Default for TradeOrderInfo {
impl Default for OrderInfo {
fn default() -> Self {
Self {
owner: Pubkey::default(),
@ -179,7 +179,7 @@ impl Default for TradeOrderInfo {
}
}
}
impl TradeOrderInfo {
impl OrderInfo {
pub fn pair(mut self, pair: TokenPair) -> Self {
self.pair = pair;
self
@ -228,7 +228,7 @@ pub enum ExchangeState {
// Token account
Account(TokenAccountInfo),
// Trade order account
Trade(TradeOrderInfo),
Trade(OrderInfo),
Invalid,
}
impl Default for ExchangeState {