chik-sdk-test 0.20.0

A wallet simulator and related tooling for testing Chik wallet code.
Documentation
use std::net::SocketAddr;

use chik_protocol::Bytes32;
use indexmap::{IndexMap, IndexSet};

#[derive(Debug, Default, Clone)]
pub(crate) struct Subscriptions {
    puzzle_subscriptions: IndexMap<SocketAddr, IndexSet<Bytes32>>,
    coin_subscriptions: IndexMap<SocketAddr, IndexSet<Bytes32>>,
}

impl Subscriptions {
    pub(crate) fn add_coin_subscriptions(&mut self, peer: SocketAddr, coin_ids: IndexSet<Bytes32>) {
        self.coin_subscriptions
            .entry(peer)
            .or_default()
            .extend(coin_ids);
    }

    pub(crate) fn add_puzzle_subscriptions(
        &mut self,
        peer: SocketAddr,
        puzzle_hashes: IndexSet<Bytes32>,
    ) {
        self.puzzle_subscriptions
            .entry(peer)
            .or_default()
            .extend(puzzle_hashes);
    }

    pub(crate) fn remove_coin_subscriptions(
        &mut self,
        peer: SocketAddr,
        coin_ids: &[Bytes32],
    ) -> Vec<Bytes32> {
        let mut removed = Vec::new();

        if let Some(subscriptions) = self.coin_subscriptions.get_mut(&peer) {
            for coin_id in coin_ids {
                if subscriptions.swap_remove(coin_id) {
                    removed.push(*coin_id);
                }
            }
            if subscriptions.is_empty() {
                self.coin_subscriptions.swap_remove(&peer);
            }
        }

        removed
    }

    pub(crate) fn remove_puzzle_subscriptions(
        &mut self,
        peer: SocketAddr,
        puzzle_hashes: &[Bytes32],
    ) -> Vec<Bytes32> {
        let mut removed = Vec::new();

        if let Some(subscriptions) = self.puzzle_subscriptions.get_mut(&peer) {
            for puzzle_hash in puzzle_hashes {
                if subscriptions.swap_remove(puzzle_hash) {
                    removed.push(*puzzle_hash);
                }
            }
            if subscriptions.is_empty() {
                self.puzzle_subscriptions.swap_remove(&peer);
            }
        }

        removed
    }

    pub(crate) fn remove_all_coin_subscriptions(&mut self, peer: SocketAddr) -> Vec<Bytes32> {
        self.coin_subscriptions
            .swap_remove(&peer)
            .unwrap_or_default()
            .into_iter()
            .collect()
    }

    pub(crate) fn remove_all_puzzle_subscriptions(&mut self, peer: SocketAddr) -> Vec<Bytes32> {
        self.puzzle_subscriptions
            .swap_remove(&peer)
            .unwrap_or_default()
            .into_iter()
            .collect()
    }

    pub(crate) fn subscription_count(&self, peer: SocketAddr) -> usize {
        self.coin_subscriptions.get(&peer).map_or(0, IndexSet::len)
            + self
                .puzzle_subscriptions
                .get(&peer)
                .map_or(0, IndexSet::len)
    }

    pub(crate) fn peers(&self) -> IndexSet<SocketAddr> {
        self.coin_subscriptions
            .keys()
            .chain(self.puzzle_subscriptions.keys())
            .copied()
            .collect()
    }

    pub(crate) fn coin_subscriptions(&self, peer: SocketAddr) -> Option<&IndexSet<Bytes32>> {
        self.coin_subscriptions.get(&peer)
    }

    pub(crate) fn puzzle_subscriptions(&self, peer: SocketAddr) -> Option<&IndexSet<Bytes32>> {
        self.puzzle_subscriptions.get(&peer)
    }
}