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
use soroban_native_sdk_macros::contracttype;
use stellar_strkey::ed25519;

use crate::{host::Host, HostError};
use soroban_env_common::{Env, EnvBase, StorageType, SymbolSmall, TryFromVal, TryIntoVal};

use crate::native_contract::base_types::String;

use super::{asset_info::read_asset_info, public_types::AssetInfo};

const METADATA_KEY: &str = "METADATA";

#[derive(Clone)]
#[contracttype]
pub struct TokenMetadata {
    pub decimal: u32,
    pub name: String,
    pub symbol: String,
}

pub const DECIMAL: u32 = 7;

pub fn set_metadata(e: &Host) -> Result<(), HostError> {
    let name_and_symbol: (String, String) = match read_asset_info(e)? {
        AssetInfo::Native => {
            let n = String::try_from_val(e, &e.string_new_from_slice("native")?)?;
            (n.clone(), n)
        }
        AssetInfo::AlphaNum4(asset) => {
            let symbol: String = asset.asset_code;
            let mut name = symbol.copy_to_rust_string(e)?;
            name.push(':');
            let k = ed25519::PublicKey(asset.issuer.to_array()?);
            name.push_str(k.to_string().as_str());
            (
                String::try_from_val(e, &e.string_new_from_slice(name.as_str())?)?,
                symbol,
            )
        }
        AssetInfo::AlphaNum12(asset) => {
            let symbol: String = asset.asset_code;
            let mut name = symbol.copy_to_rust_string(e)?;
            name.push(':');
            let k = ed25519::PublicKey(asset.issuer.to_array()?);
            name.push_str(k.to_string().as_str());
            (
                String::try_from_val(e, &e.string_new_from_slice(name.as_str())?)?,
                symbol,
            )
        }
    };

    let metadata = TokenMetadata {
        decimal: DECIMAL,
        name: name_and_symbol.0,
        symbol: name_and_symbol.1,
    };

    let key = SymbolSmall::try_from_str(METADATA_KEY)?;
    e.put_contract_data(
        key.try_into_val(e)?,
        metadata.try_into_val(e)?,
        StorageType::Instance,
        ().into(),
    )?;
    Ok(())
}

pub fn read_name(e: &Host) -> Result<String, HostError> {
    let key = SymbolSmall::try_from_str(METADATA_KEY)?;
    let metadata: TokenMetadata = e
        .get_contract_data(key.try_into_val(e)?, StorageType::Instance)?
        .try_into_val(e)?;
    Ok(metadata.name)
}

pub fn read_symbol(e: &Host) -> Result<String, HostError> {
    let key = SymbolSmall::try_from_str(METADATA_KEY)?;
    let metadata: TokenMetadata = e
        .get_contract_data(key.try_into_val(e)?, StorageType::Instance)?
        .try_into_val(e)?;
    Ok(metadata.symbol)
}