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
use ibc_types::core::channel::{ChannelId, PortId};
use penumbra_asset::asset;

/// IBC token represents a token that was created through IBC.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IbcToken {
    channel_id: ChannelId,
    port_id: PortId,
    original_denom: String,

    base_denom: asset::Metadata,
}

impl IbcToken {
    pub fn new(channel_id: &ChannelId, port_id: &PortId, denom: &str) -> Self {
        let transfer_path = format!("{port_id}/{channel_id}/{denom}");

        let base_denom = asset::REGISTRY
            .parse_denom(&transfer_path)
            .expect("IBC denom is invalid");

        IbcToken {
            channel_id: channel_id.clone(),
            port_id: port_id.clone(),
            original_denom: denom.to_string(),

            base_denom,
        }
    }

    /// Get the base denomination for this IBC token.
    pub fn denom(&self) -> asset::Metadata {
        self.base_denom.clone()
    }

    /// Get the default display denomination for this IBC token.
    pub fn default_unit(&self) -> asset::Unit {
        self.base_denom.default_unit()
    }

    /// get the asset ID for this IBC token.
    pub fn id(&self) -> asset::Id {
        self.base_denom.id()
    }

    /// get the IBC transfer path of the IBC token.
    ///
    /// this takes the format of `port_id/channel_id/denom`.
    pub fn transfer_path(&self) -> String {
        format!(
            "{}/{}/{}",
            self.port_id, self.channel_id, self.original_denom
        )
    }
}

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

    #[test]
    fn test_derive_ibc_denom() {
        let expected_transfer_path = "transfer/channel-31/uatom";
        let ibctoken = IbcToken::new(&ChannelId::new(31), &PortId::transfer(), "uatom");
        println!("denom: {}, id: {}", ibctoken.denom(), ibctoken.id());
        assert_eq!(expected_transfer_path, ibctoken.transfer_path());
    }
}