1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//! Shared types between XPS Gateawy and client (libxmtp)

pub mod error;

use ethers::types::{Address, Bytes as EthersBytes, Signature};
use ethers::types::{H256, U256};
use ethers::utils::format_units;
use std::fmt;

use serde::{Deserialize, Serialize};
use std::fmt::Display;

/// Address of the did:ethr Registry on Sepolia
pub const DID_ETH_REGISTRY: &str = "0xd1D374DDE031075157fDb64536eF5cC13Ae75000";
// Address of the Conversation on Sepolia
pub const CONVERSATION: &str = "0x15aE865d0645816d8EEAB0b7496fdd24227d1801";

/// A message sent to a conversation
#[derive(Serialize, Deserialize)]
pub struct Message {
    // Unique identifier for a conversation
    #[serde(rename = "conversationId")]
    pub conversation_id: [u8; 32],
    /// message content in bytes
    pub payload: EthersBytes,
    // Sender's identity
    pub identity: Address,
    // Signature by sender
    pub signature: Signature,
}

pub type Bytes = Vec<u8>;

/// GrantInstallationResult represents the result of a grant installation operation in the DID registry.
///
/// This struct encapsulates the outcome of an attempt to grant an installation,
/// providing details about the operation's status, a descriptive message, and the
/// transaction identifier associated with the blockchain transaction.
///
/// # Fields
/// * `status` - One of [`Status::Success`] or [`Status::Failed`], indicating the outcome of the
/// operation.
/// * `message` - A `String` providing more detailed information about the operation. This
///   can be a success message, error description, or any other relevant information.
/// * `transaction` - A `String` representing the unique identifier of the transaction on the
///   blockchain. This can be used to track the transaction in a blockchain explorer.
///
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct GrantInstallationResult {
    pub status: Status,
    pub message: String,
    pub transaction: Option<H256>,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum Unit {
    Eth,
    Other(String),
}

/// WalletBalance used as the return value for the balance rpc endpoint.
#[derive(Serialize, Deserialize, Clone)]
pub struct WalletBalance {
    /// The balance for the wallet
    #[serde(rename = "balance")]
    pub balance: U256,
    /// The unit used for the balance
    #[serde(rename = "unit")]
    pub unit: Unit,
}

impl Display for WalletBalance {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.unit {
            Unit::Eth => {
                let ether_balance =
                    format_units(self.balance, 18) // 18 decimal places for Ether
                    .unwrap_or_else(|_| "failed to convert balance".to_string());
                write!(f, "{} ETH", ether_balance)
            }
            Unit::Other(unit_name) => write!(f, "{} {}", self.balance, unit_name),
        }
    }
}

// Assuming you have a Display implementation for Unit as well
impl Display for Unit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Unit::Eth => write!(f, "ETH"),
            Unit::Other(value) => write!(f, "{}", value),
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct SendMessageResult {
    pub status: Status,
    pub message: String,
    pub transaction: String,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct KeyPackageResult {
    /// Status of the operation
    pub status: Status,
    /// A message relating to the operation
    pub message: String,
    /// A list of key packages
    pub installation: Vec<Bytes>,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum Status {
    Success,
    Failed,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Status::Success => write!(f, "success"),
            Status::Failed => write!(f, "failed"),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_status_display() {
        assert_eq!(format!("{}", Status::Success), "success");
        assert_eq!(format!("{}", Status::Failed), "failed");
    }

    #[test]
    fn test_wallet_balance_display() {
        assert_eq!(
            format!(
                "{}",
                WalletBalance {
                    balance: U256::from(123456789),
                    unit: Unit::Eth
                }
            ),
            "0.000000000123456789 ETH"
        );
        assert_eq!(
            format!(
                "{}",
                WalletBalance {
                    balance: U256::from(987654321),
                    unit: Unit::Eth
                }
            ),
            "0.000000000987654321 ETH"
        );
        assert_eq!(
            format!(
                "{}",
                WalletBalance {
                    balance: U256::from(500),
                    unit: Unit::Other("BTC".to_string())
                }
            ),
            "500 BTC"
        );
    }

    #[test]
    fn test_unit_display() {
        assert_eq!(format!("{}", Unit::Eth), "ETH");
        assert_eq!(format!("{}", Unit::Other("ABC".to_string())), "ABC");
    }
}