Skip to content

Commit

Permalink
Merge pull request #512 from TheCharlatan/offerHistory
Browse files Browse the repository at this point in the history
Offer history
  • Loading branch information
zkao authored Jul 3, 2022
2 parents 482985f + 8349f79 commit e690a39
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 34 deletions.
2 changes: 2 additions & 0 deletions shell/_swap-cli
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ _arguments "${_arguments_options[@]}" \
;;
(list-offers)
_arguments "${_arguments_options[@]}" \
'-s+[]:SELECT:(open Open inprogress in_progress ended Ended all All)' \
'--select=[]:SELECT:(open Open inprogress in_progress ended Ended all All)' \
'-d+[Data directory path]:DATA_DIR:_files -/' \
'--data-dir=[Data directory path]:DATA_DIR:_files -/' \
'-T+[Use Tor]:TOR_PROXY:_hosts' \
Expand Down
2 changes: 2 additions & 0 deletions shell/_swap-cli.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ Register-ArgumentCompleter -Native -CommandName 'swap-cli' -ScriptBlock {
break
}
'swap-cli;list-offers' {
[CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 's')
[CompletionResult]::new('--select', 'select', [CompletionResultType]::ParameterName, 'select')
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'Data directory path')
[CompletionResult]::new('--data-dir', 'data-dir', [CompletionResultType]::ParameterName, 'Data directory path')
[CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Use Tor')
Expand Down
10 changes: 9 additions & 1 deletion shell/swap-cli.bash
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,20 @@ _swap-cli() {
return 0
;;
swap__cli__list__offers)
opts="-h -d -v -T -m -x --help --data-dir --verbose --tor-proxy --msg-socket --ctl-socket"
opts="-s -h -d -v -T -m -x --select --help --data-dir --verbose --tor-proxy --msg-socket --ctl-socket"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--select)
COMPREPLY=($(compgen -W "open Open inprogress in_progress ended Ended all All" -- "${cur}"))
return 0
;;
-s)
COMPREPLY=($(compgen -W "open Open inprogress in_progress ended Ended all All" -- "${cur}"))
return 0
;;
--data-dir)
COMPREPLY=($(compgen -f "${cur}"))
return 0
Expand Down
4 changes: 2 additions & 2 deletions src/cli/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ impl Exec for Command {
}

// TODO: only list offers matching list of OfferIds
Command::ListOffers => {
runtime.request(ServiceId::Farcasterd, Request::ListOffers)?;
Command::ListOffers { select } => {
runtime.request(ServiceId::Farcasterd, Request::ListOffers(select.into()))?;
runtime.report_response_or_fail()?;
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
mod command;
mod opts;

pub use opts::{Command, Opts};
pub use opts::{Command, OfferSelector, Opts};
43 changes: 41 additions & 2 deletions src/cli/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,17 @@ pub enum Command {
#[clap(aliases = &["ls"])]
ListSwaps,

// TODO: only list offers matching list of OfferIds
/// Lists public offers created by daemon
#[clap(aliases = &["lo"])]
ListOffers,
ListOffers {
#[clap(
short,
long,
default_value = "open",
possible_values = &["open", "Open", "inprogress", "in_progress", "ended", "Ended", "all", "All"],
)]
select: OfferSelector,
},

/// Gives information on an open offer
#[clap(aliases = &["oi"])]
Expand Down Expand Up @@ -236,6 +243,38 @@ pub enum Command {
},
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, From)]
pub enum OfferSelector {
#[display("Open")]
Open,
#[display("In Progress")]
InProgress,
#[display("Ended")]
Ended,
#[display("All")]
All,
}

impl FromStr for OfferSelector {
type Err = OfferSelectorParseError;
fn from_str(input: &str) -> Result<OfferSelector, Self::Err> {
match input {
"open" | "Open" => Ok(OfferSelector::Open),
"in_progress" | "inprogress" => Ok(OfferSelector::InProgress),
"ended" | "Ended" => Ok(OfferSelector::Ended),
"all" | "All" => Ok(OfferSelector::All),
_ => Err(OfferSelectorParseError::Invalid),
}
}
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum OfferSelectorParseError {
/// The provided value can't be parsed as an offer selector
Invalid,
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum AmountOfAssetParseError {
Expand Down
2 changes: 1 addition & 1 deletion src/databased/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ impl Runtime {
self.database.set_offer_status(&offer, &status)?;
}

Request::RetrieveOffers(selector) => {
Request::ListOffers(selector) => {
let offer_status_pairs = self.database.get_offers(selector)?;
endpoints.send_to(
ServiceBus::Ctl,
Expand Down
100 changes: 75 additions & 25 deletions src/farcasterd/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
// along with this software.
// If not, see <https://opensource.org/licenses/MIT>.

use crate::farcasterd::runtime::request::CheckpointEntry;
use crate::farcasterd::runtime::request::MadeOffer;
use crate::farcasterd::runtime::request::TookOffer;
use crate::farcasterd::runtime::request::{ProgressEvent, SwapProgress};
use crate::farcasterd::runtime::request::{
CheckpointEntry, MadeOffer, OfferStatus, OfferStatusPair, OfferStatusSelector, ProgressEvent,
SwapProgress, TookOffer,
};
use crate::{
clap::Parser,
error::SyncerError,
Expand Down Expand Up @@ -170,7 +170,7 @@ pub struct Runtime {
public_offers: HashSet<PublicOffer<BtcXmr>>,
arb_addrs: HashMap<PublicOfferId, bitcoin::Address>,
acc_addrs: HashMap<PublicOfferId, monero::Address>,
consumed_offers: HashMap<OfferId, (SwapId, ServiceId)>,
consumed_offers: HashMap<PublicOffer<BtcXmr>, (SwapId, ServiceId)>,
node_ids: HashMap<OfferId, PublicKey>, // Only populated by maker. TODO is it possible? HashMap<SwapId, PublicKey>
peerd_ids: HashMap<OfferId, ServiceId>, // Only populated by maker.
wallet_token: Token,
Expand Down Expand Up @@ -337,7 +337,7 @@ impl Runtime {
if swapid != &swap_id {
Some((k, (swap_id, service_id)))
} else {
offerid = Some(k);
offerid = Some(k.offer.id());
None
}
})
Expand Down Expand Up @@ -410,8 +410,8 @@ impl Runtime {
Ok(())
}

fn consumed_offers_contains(&self, offerid: &OfferId) -> bool {
self.consumed_offers.contains_key(offerid)
fn consumed_offers_contains(&self, offer: &PublicOffer<BtcXmr>) -> bool {
self.consumed_offers.contains_key(offer)
}

fn _send_walletd(
Expand Down Expand Up @@ -723,6 +723,27 @@ impl Runtime {

Request::SwapOutcome(success) => {
let swapid = get_swap_id(&source)?;
if let Some(public_offer) =
self.consumed_offers
.iter()
.find_map(|(public_offer, (o_swap_id, _))| {
if *o_swap_id == swapid {
Some(public_offer)
} else {
None
}
})
{
endpoints.send_to(
ServiceBus::Ctl,
ServiceId::Farcasterd,
ServiceId::Database,
Request::SetOfferStatus(OfferStatusPair {
offer: public_offer.clone(),
status: OfferStatus::Ended(success.clone()),
}),
)?;
}
self.clean_up_after_swap(&swapid, endpoints)?;
self.stats.incr_outcome(&success);
match success {
Expand Down Expand Up @@ -767,13 +788,23 @@ impl Runtime {
}
};
if self.public_offers.remove(&public_offer) {
endpoints.send_to(
ServiceBus::Ctl,
ServiceId::Farcasterd,
ServiceId::Database,
Request::SetOfferStatus(OfferStatusPair {
offer: public_offer.clone(),
status: OfferStatus::InProgress,
}),
)?;

trace!(
"launching swapd with swap_id: {}",
swap_id.bright_yellow_bold()
);

self.consumed_offers
.insert(public_offer.offer.id(), (swap_id, peer.clone()));
.insert(public_offer.clone(), (swap_id, peer.clone()));
self.stats.incr_initiated();
launch_swapd(
self,
Expand Down Expand Up @@ -860,20 +891,35 @@ impl Runtime {
)?;
}

// TODO: only list offers matching list of OfferIds
Request::ListOffers => {
let pub_offers = self
.public_offers
.iter()
.filter(|k| !self.consumed_offers_contains(&k.offer.id()))
.cloned()
.collect();
endpoints.send_to(
ServiceBus::Ctl,
ServiceId::Farcasterd, // source
source, // destination
Request::OfferList(pub_offers),
)?;
Request::ListOffers(offer_status_selector) => {
match offer_status_selector {
OfferStatusSelector::Open => {
let pub_offers = self
.public_offers
.iter()
.filter(|k| !self.consumed_offers_contains(k))
.cloned()
.collect();
endpoints.send_to(
ServiceBus::Ctl,
ServiceId::Farcasterd, // source
source, // destination
Request::OfferList(pub_offers),
)?;
}
OfferStatusSelector::InProgress => {
let pub_offers = self.consumed_offers.keys().cloned().collect();
endpoints.send_to(
ServiceBus::Ctl,
ServiceId::Farcasterd,
source,
Request::OfferList(pub_offers),
)?;
}
_ => {
endpoints.send_to(ServiceBus::Ctl, source, ServiceId::Database, request)?;
}
};
}

Request::RevokeOffer(public_offer) => {
Expand Down Expand Up @@ -1096,7 +1142,7 @@ impl Runtime {
let public_offer = offer.to_public_v1(node_id, public_addr.into());
let pub_offer_id = public_offer.id();
let serialized_offer = public_offer.to_string();
if !self.public_offers.insert(public_offer) {
if !self.public_offers.insert(public_offer.clone()) {
let msg = s!("This Public offer was previously registered");
error!("{}", msg.err());
return Err(Error::Other(msg));
Expand All @@ -1110,6 +1156,10 @@ impl Runtime {
self.arb_addrs.insert(pub_offer_id, arbitrating_addr);
self.acc_addrs
.insert(pub_offer_id, monero::Address::from_str(&accordant_addr)?);
endpoints.send_to(ServiceBus::Ctl, ServiceId::Farcasterd, ServiceId::Database, Request::SetOfferStatus(OfferStatusPair {
offer: public_offer,
status: OfferStatus::Open,
}))?;
endpoints.send_to(
ServiceBus::Ctl,
ServiceId::Farcasterd, // source
Expand Down Expand Up @@ -1141,7 +1191,7 @@ impl Runtime {
peer_secret_key,
}) => {
if self.public_offers.contains(&public_offer)
|| self.consumed_offers_contains(&public_offer.offer.id())
|| self.consumed_offers_contains(&public_offer)
{
let msg = format!(
"{} already exists or was already taken, ignoring request",
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub mod request;
use crate::ServiceId;
pub use client::Client;
pub use reply::Reply;
#[cfg(feature = "shell")]
pub use request::OfferStatusSelector;
pub use request::Request;

use microservices::esb::BusId;
Expand Down
27 changes: 25 additions & 2 deletions src/rpc/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#![allow(clippy::clone_on_copy)]

use crate::cli::OfferSelector;
use crate::swapd::CheckpointSwapd;
use crate::syncerd::SweepBitcoinAddress;
use crate::walletd::{
Expand Down Expand Up @@ -453,10 +454,9 @@ pub enum Request {
#[display("list_tasks()")]
ListTasks,

// TODO: only list offers matching list of OfferIds
#[api(type = 104)]
#[display("list_offers()")]
ListOffers,
ListOffers(OfferStatusSelector),

// #[api(type = 105)]
// #[display("list_offer_ids()")]
Expand Down Expand Up @@ -757,6 +757,29 @@ pub enum OfferStatusSelector {
All,
}

impl From<OfferSelector> for OfferStatusSelector {
fn from(offer_selector: OfferSelector) -> OfferStatusSelector {
match offer_selector {
OfferSelector::Open => OfferStatusSelector::Open,
OfferSelector::InProgress => OfferStatusSelector::InProgress,
OfferSelector::Ended => OfferStatusSelector::Ended,
OfferSelector::All => OfferStatusSelector::All,
}
}
}

impl FromStr for OfferStatusSelector {
type Err = ();
fn from_str(input: &str) -> Result<OfferStatusSelector, Self::Err> {
match input {
"open" | "Open" => Ok(OfferStatusSelector::Open),
"in_progress" | "inprogress" => Ok(OfferStatusSelector::Open),
"ended" | "Ended" => Ok(OfferStatusSelector::Ended),
_ => Err(()),
}
}
}

#[derive(Clone, Debug, Eq, PartialEq, Display, StrictEncode, StrictDecode)]
#[cfg_attr(
feature = "serde",
Expand Down

0 comments on commit e690a39

Please sign in to comment.