penumbra_sdk_ibc/
ibc_token.rs1use ibc_types::core::channel::{ChannelId, PortId};
2use penumbra_sdk_asset::asset;
3
4#[derive(Clone, Debug, PartialEq, Eq)]
6pub struct IbcToken {
7 channel_id: ChannelId,
8 port_id: PortId,
9 original_denom: String,
10
11 base_denom: asset::Metadata,
12}
13
14impl IbcToken {
15 pub fn new(channel_id: &ChannelId, port_id: &PortId, denom: &str) -> Self {
16 let transfer_path = format!("{port_id}/{channel_id}/{denom}");
17
18 let base_denom = asset::REGISTRY
19 .parse_denom(&transfer_path)
20 .expect("IBC denom is invalid");
21
22 IbcToken {
23 channel_id: channel_id.clone(),
24 port_id: port_id.clone(),
25 original_denom: denom.to_string(),
26
27 base_denom,
28 }
29 }
30
31 pub fn denom(&self) -> asset::Metadata {
33 self.base_denom.clone()
34 }
35
36 pub fn default_unit(&self) -> asset::Unit {
38 self.base_denom.default_unit()
39 }
40
41 pub fn id(&self) -> asset::Id {
43 self.base_denom.id()
44 }
45
46 pub fn transfer_path(&self) -> String {
50 format!(
51 "{}/{}/{}",
52 self.port_id, self.channel_id, self.original_denom
53 )
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_derive_ibc_denom() {
63 let expected_transfer_path = "transfer/channel-31/uatom";
64 let ibctoken = IbcToken::new(&ChannelId::new(31), &PortId::transfer(), "uatom");
65 println!("denom: {}, id: {}", ibctoken.denom(), ibctoken.id());
66 assert_eq!(expected_transfer_path, ibctoken.transfer_path());
67 }
68}