You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.8 KiB
139 lines
4.8 KiB
use crate::monero;
|
|
use crate::network::cbor_request_response::CborCodec;
|
|
use libp2p::core::ProtocolName;
|
|
use libp2p::request_response::{RequestResponse, RequestResponseEvent, RequestResponseMessage};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
pub const PROTOCOL: &str = "/comit/xmr/btc/spot-price/1.0.0";
|
|
pub type OutEvent = RequestResponseEvent<Request, Response>;
|
|
pub type Message = RequestResponseMessage<Request, Response>;
|
|
|
|
pub type Behaviour = RequestResponse<CborCodec<SpotPriceProtocol, Request, Response>>;
|
|
|
|
/// The spot price protocol allows parties to **initiate** a trade by requesting
|
|
/// a spot price.
|
|
///
|
|
/// A spot price is binding for both parties, i.e. after the spot-price protocol
|
|
/// completes, both parties are expected to follow up with the `execution-setup`
|
|
/// protocol.
|
|
///
|
|
/// If a party wishes to only inquire about the current price, they should use
|
|
/// the `quote` protocol instead.
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
pub struct SpotPriceProtocol;
|
|
|
|
impl ProtocolName for SpotPriceProtocol {
|
|
fn protocol_name(&self) -> &[u8] {
|
|
PROTOCOL.as_bytes()
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
pub struct Request {
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
pub btc: bitcoin::Amount,
|
|
pub blockchain_network: BlockchainNetwork,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
pub enum Response {
|
|
Xmr(monero::Amount),
|
|
Error(Error),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub enum Error {
|
|
NoSwapsAccepted,
|
|
AmountBelowMinimum {
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
min: bitcoin::Amount,
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
buy: bitcoin::Amount,
|
|
},
|
|
AmountAboveMaximum {
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
max: bitcoin::Amount,
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
buy: bitcoin::Amount,
|
|
},
|
|
BalanceTooLow {
|
|
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
|
buy: bitcoin::Amount,
|
|
},
|
|
BlockchainNetworkMismatch {
|
|
cli: BlockchainNetwork,
|
|
asb: BlockchainNetwork,
|
|
},
|
|
/// To be used for errors that cannot be explained on the CLI side (e.g.
|
|
/// rate update problems on the seller side)
|
|
Other,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
|
|
pub struct BlockchainNetwork {
|
|
#[serde(with = "crate::bitcoin::network")]
|
|
pub bitcoin: bitcoin::Network,
|
|
#[serde(with = "crate::monero::network")]
|
|
pub monero: monero::Network,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::monero;
|
|
|
|
#[test]
|
|
fn snapshot_test_serialize() {
|
|
let amount = monero::Amount::from_piconero(100_000u64);
|
|
let xmr = r#"{"Xmr":100000}"#.to_string();
|
|
let serialized = serde_json::to_string(&Response::Xmr(amount)).unwrap();
|
|
assert_eq!(xmr, serialized);
|
|
|
|
let error = r#"{"Error":"NoSwapsAccepted"}"#.to_string();
|
|
let serialized = serde_json::to_string(&Response::Error(Error::NoSwapsAccepted)).unwrap();
|
|
assert_eq!(error, serialized);
|
|
|
|
let error = r#"{"Error":{"AmountBelowMinimum":{"min":0,"buy":0}}}"#.to_string();
|
|
let serialized = serde_json::to_string(&Response::Error(Error::AmountBelowMinimum {
|
|
min: Default::default(),
|
|
buy: Default::default(),
|
|
}))
|
|
.unwrap();
|
|
assert_eq!(error, serialized);
|
|
|
|
let error = r#"{"Error":{"AmountAboveMaximum":{"max":0,"buy":0}}}"#.to_string();
|
|
let serialized = serde_json::to_string(&Response::Error(Error::AmountAboveMaximum {
|
|
max: Default::default(),
|
|
buy: Default::default(),
|
|
}))
|
|
.unwrap();
|
|
assert_eq!(error, serialized);
|
|
|
|
let error = r#"{"Error":{"BalanceTooLow":{"buy":0}}}"#.to_string();
|
|
let serialized = serde_json::to_string(&Response::Error(Error::BalanceTooLow {
|
|
buy: Default::default(),
|
|
}))
|
|
.unwrap();
|
|
assert_eq!(error, serialized);
|
|
|
|
let error = r#"{"Error":{"BlockchainNetworkMismatch":{"cli":{"bitcoin":"Mainnet","monero":"Mainnet"},"asb":{"bitcoin":"Testnet","monero":"Stagenet"}}}}"#.to_string();
|
|
let serialized =
|
|
serde_json::to_string(&Response::Error(Error::BlockchainNetworkMismatch {
|
|
cli: BlockchainNetwork {
|
|
bitcoin: bitcoin::Network::Bitcoin,
|
|
monero: monero::Network::Mainnet,
|
|
},
|
|
asb: BlockchainNetwork {
|
|
bitcoin: bitcoin::Network::Testnet,
|
|
monero: monero::Network::Stagenet,
|
|
},
|
|
}))
|
|
.unwrap();
|
|
assert_eq!(error, serialized);
|
|
|
|
let error = r#"{"Error":"Other"}"#.to_string();
|
|
let serialized = serde_json::to_string(&Response::Error(Error::Other)).unwrap();
|
|
assert_eq!(error, serialized);
|
|
}
|
|
}
|