-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CLI-based CLOB using the Miden client #206
Comments
We don't need to focus too much on UX. It is mostly a showcase for Composability Labs on how to build a simple order book. In my mind, a user would simply type the order type So in the CLI, I would expect:
An example of a full command would be Ideally, we would replace the |
@phklive for the matching algorithm: So the user should by able to type the CLI command: Then the program starts creating a sub-set of the sorted ETH order book (by price). Assuming that the order book is sorted ascending, so the cheapest price is on top, the order book looks like this
So our simple matching algorithm starts on the top of the list and sees if it can fulfill the order for the requested price or cheaper. use std::collections::HashMap;
#[derive(Debug, Clone)]
struct Order {
note_id: String,
amount_requested: f64, // ETH
amount_contained: f64, // BTC
price: f64, // Price = ETH/BTC
}
impl Order {
fn new(note_id: &str, amount_requested: f64, amount_contained: f64) -> Self {
let price = amount_requested / amount_contained;
Order {
note_id: note_id.to_string(),
amount_requested,
amount_contained,
price,
}
}
}
fn match_order(order_book: &[Order], buy_eth: f64, btc_offered: f64) -> Result<(Vec<String>, f64), bool> {
let mut remaining_eth = buy_eth;
let mut total_btc_needed = 0.0;
let mut matched_orders: Vec<String> = Vec::new();
let mut total_price = 0.0;
// Sort the order book by price in ascending order
let mut sorted_orders = order_book.to_vec();
sorted_orders.sort_by(|a, b| a.price.partial_cmp(&b.price).unwrap());
for order in sorted_orders.iter() {
if remaining_eth <= 0.0 {
break;
}
let eth_to_buy = remaining_eth.min(order.amount_requested);
let btc_needed = eth_to_buy / order.price;
if total_btc_needed + btc_needed > btc_offered {
return Err(false);
}
remaining_eth -= eth_to_buy;
total_btc_needed += btc_needed;
total_price += order.price * eth_to_buy;
matched_orders.push(order.note_id.clone());
}
if remaining_eth > 0.0 {
Err(false) // Not enough orders to fulfill the request
} else {
let average_price = total_price / buy_eth;
Ok((matched_orders, average_price))
}
}
fn main() {
// Sample order book
let order_book = vec![
Order::new("0x1a2b3c", 100.0, 2.0),
Order::new("0x1d2e3f", 200.0, 4.0),
Order::new("0x1g2h3i", 150.0, 3.5),
Order::new("0x1j2k3l", 50.0, 1.0),
];
// Example: Buying 250 ETH for 7 BTC
let buy_eth = 250.0;
let btc_offered = 7.0;
match match_order(&order_book, buy_eth, btc_offered) {
Ok((matched_orders, avg_price)) => {
println!("Order fulfilled with NoteIDs: {:?} at an average price of {:.2}", matched_orders, avg_price);
},
Err(_) => {
println!("Order cannot be fulfilled.");
}
}
} I created this with ChatGTP and reviewed, it looks correct. You probably need |
SWAPp note currently works and has basic tests in this repository here: https://github.com/compolabs/spark-miden-v1/tree/main/tests/mock_integration The CLI currently computes the expected P2ID of the SWAP note before it is consumed. This is fine, but will only work for the standard SWAP note, not the partially fillable SWAP note. Example: User 1 is selling 10 tokens A for 10 tokens B. We don't know how many tokens A User 2 wants in the future. When User 2 builds the transaction, "I want 5 tokens A", then we will know the output of the SWAPp note. Right now, this is a peer to peer order book. This is fine for the first PoC version, but in the future, we will need to make some sort of "clearing house" or "matcher" contract that can consume multiple SWAPp orders and fill them. |
Let's build a CLI-based order book
Do some research and tests first - Scripts to set up the order book
ASSET1
ASSET2
TAG
but different inputs. For the first version: use the normalSWAP
script.SWAPp
notes insteadThe program - Wrapper around the Miden client with a CLI
TAG
in the CLI. The program then queries the Miden Node and gets all public notes with the sameTAG
. As a result, all notes should be listed in the interface.(requested_asset/asset)
.buy 10 ETH for 1 BTC
cannot be fulfilled, so a new order will be added to the BTC/ETH order booksell 1 BTC for 10 ETH
. This will always result in a transaction.TransactionRequest
, since it is not a standard scriptCollect feedback
The text was updated successfully, but these errors were encountered: