use crate::helpers::with_metadata_hashable::WithMetadataHashable;
use crate::party::address_event::AddressEvent;
use crate::party::party_events::ConfirmedExternalStakeEvent;
use crate::structs::{CurrencyAmount, Hash, PortfolioRequest, PortfolioWeighting, SupportedCurrency, Transaction, UtxoId};
use itertools::Either::{Left, Right};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
pub struct PortfolioRequestEvents {
pub events: Vec<PortfolioRequestEventInstance>,
pub external_stake_balance_deltas: HashMap<SupportedCurrency, CurrencyAmount>,
pub stake_utxos: Vec<(UtxoId, ConfirmedExternalStakeEvent)>,
pub current_portfolio_imbalance: HashMap<SupportedCurrency, CurrencyAmount>,
pub current_rdg_allocations: HashMap<SupportedCurrency, CurrencyAmount>,
pub enriched_events: Option<HashMap<Hash, HashMap<SupportedCurrency, (f64, f64)>>>
}
impl PortfolioRequestEvents {
pub fn calculate_current_fulfillment_by_event(&self)
-> HashMap<Hash, HashMap<SupportedCurrency, (f64, f64)>> {
let mut all_events = vec![];
for e in self.events.iter() {
all_events.push((e.time, Left(e.clone())));
}
for e in self.stake_utxos.iter() {
let time = (e.1.ett.timestamp.unwrap() as i64, Right(e.1.clone()));
all_events.push(time);
}
all_events.sort_by(|a, b| a.0.cmp(&b.0));
let mut cur_fulfills: HashMap<SupportedCurrency, Vec<(Hash, (f64, f64))>> = HashMap::new();
let mut tx_hash_to_fulfilled_amounts = HashMap::new();
for (_, e) in all_events.iter() {
match e {
Left(e) => {
let starting_usd = e.value_at_time;
let value_usd_by_cur = e.fixed_currency_allocations.iter()
.map(|(k,v)| {
(k.clone(), v * starting_usd)
}).collect::<HashMap<SupportedCurrency, f64>>();
for (c, u) in value_usd_by_cur.into_iter() {
let x = cur_fulfills.entry(c.clone()).or_insert(vec![]);
x.push((e.tx.hash_or(), (0.0,u.clone())));
}
},
Right(e) => {
let amt = e.ett.currency_amount();
if let Some(p_usd) = e.ett.price_usd {
let mut usd_value = amt.to_fractional() * p_usd;
let cur = e.ett.currency;
if let Some(vec) = cur_fulfills.get_mut(&cur) {
vec.retain_mut(|(_hash, (cur_fulfilled, remaining))| {
if usd_value == 0.0 {
true
} else {
if remaining.clone() > usd_value {
*remaining -= usd_value;
*cur_fulfilled += usd_value;
usd_value = 0.0;
true
} else {
*cur_fulfilled += remaining.clone();
*remaining = 0.0;
usd_value -= remaining.clone();
false
}
}
});
}
}
}
}
}
for (c, v) in cur_fulfills.iter() {
for (hash, (fulfilled, remaining)) in v.iter() {
let entry = tx_hash_to_fulfilled_amounts.entry(hash.clone()).or_insert(HashMap::new());
entry.insert(c.clone(), (fulfilled.clone(), remaining.clone()));
}
}
tx_hash_to_fulfilled_amounts
}
}
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
pub struct PortfolioRequestEventInstance {
pub event: AddressEvent,
pub tx: Transaction,
pub time: i64,
pub portfolio_request: PortfolioRequest,
pub weightings: Vec<PortfolioWeighting>,
pub fixed_currency_allocations: HashMap<SupportedCurrency, f64>,
pub value_at_time: f64,
pub portfolio_rdg_amount: CurrencyAmount,
}
impl Default for PortfolioRequestEvents {
fn default() -> Self {
PortfolioRequestEvents {
events: vec![],
external_stake_balance_deltas: Default::default(),
stake_utxos: vec![],
current_portfolio_imbalance: Default::default(),
current_rdg_allocations: Default::default(),
enriched_events: None,
}
}
}