Skip to main content

ergo_lib_c_core/
token.rs

1//! Token types
2
3use std::convert::TryFrom;
4
5use ergo_lib::{
6    ergo_chain_types::{Base16DecodedBytes, Digest32},
7    ergotree_ir::chain,
8};
9
10use crate::{
11    ergo_box::ConstBoxIdPtr,
12    json::TokenJsonEip12,
13    util::{const_ptr_as_ref, mut_ptr_as_mut},
14    Error,
15};
16
17/// Token id (32 byte digest)
18#[derive(PartialEq, Eq, Debug, Clone)]
19pub struct TokenId(pub(crate) chain::token::TokenId);
20pub type TokenIdPtr = *mut TokenId;
21pub type ConstTokenIdPtr = *const TokenId;
22
23/// Create token id from ergo box id (32 byte digest)
24pub unsafe fn token_id_from_box_id(
25    box_id_ptr: ConstBoxIdPtr,
26    token_id_out: *mut TokenIdPtr,
27) -> Result<(), Error> {
28    let box_id = const_ptr_as_ref(box_id_ptr, "box_id_ptr")?;
29    let token_id_out = mut_ptr_as_mut(token_id_out, "token_id_out")?;
30    *token_id_out = Box::into_raw(Box::new(TokenId(chain::token::TokenId::from(box_id.0))));
31    Ok(())
32}
33
34/// Parse token id (32 byte digest) from base16-encoded string
35pub unsafe fn token_id_from_str(str: &str, token_id_out: *mut TokenIdPtr) -> Result<(), Error> {
36    let token_id_out = mut_ptr_as_mut(token_id_out, "token_id_out")?;
37    let base_16_decoded_bytes = Base16DecodedBytes::try_from(str.to_string())?;
38
39    let token_id = Digest32::try_from(base_16_decoded_bytes)
40        .map(|dig| dig.into())
41        .map(TokenId)?;
42    *token_id_out = Box::into_raw(Box::new(token_id));
43    Ok(())
44}
45
46/// Base16 encoded string
47pub unsafe fn token_id_to_str(token_id_ptr: ConstTokenIdPtr) -> Result<String, Error> {
48    let token_id = const_ptr_as_ref(token_id_ptr, "token_id_ptr")?;
49    Ok(token_id.0.into())
50}
51
52/// Token amount with bound checks
53#[derive(PartialEq, Eq, Debug, Clone)]
54pub struct TokenAmount(pub(crate) chain::token::TokenAmount);
55pub type TokenAmountPtr = *mut TokenAmount;
56pub type ConstTokenAmountPtr = *const TokenAmount;
57
58/// Create from i64 with bounds check
59pub unsafe fn token_amount_from_i64(
60    amount: i64,
61    token_amount_out: *mut TokenAmountPtr,
62) -> Result<(), Error> {
63    let token_amount_out = mut_ptr_as_mut(token_amount_out, "token_amount_out")?;
64    let inner = chain::token::TokenAmount::try_from(amount as u64)?;
65    *token_amount_out = Box::into_raw(Box::new(TokenAmount(inner)));
66    Ok(())
67}
68
69/// Get value as signed 64-bit long
70pub unsafe fn token_amount_as_i64(token_amount_ptr: ConstTokenAmountPtr) -> Result<i64, Error> {
71    let token_amount = const_ptr_as_ref(token_amount_ptr, "token_amount_ptr")?;
72    Ok(i64::from(token_amount.0))
73}
74
75/// Token represented with token id paired with its amount
76#[derive(PartialEq, Eq, Debug, Clone, derive_more::From, derive_more::Into)]
77pub struct Token(pub(crate) chain::token::Token);
78pub type TokenPtr = *mut Token;
79pub type ConstTokenPtr = *const Token;
80
81/// Create a token with given token id and amount
82pub unsafe fn token_new(
83    token_id_ptr: ConstTokenIdPtr,
84    token_amount_ptr: ConstTokenAmountPtr,
85    token_out: *mut TokenPtr,
86) -> Result<(), Error> {
87    let token_id = const_ptr_as_ref(token_id_ptr, "token_id_ptr")?;
88    let token_amount = const_ptr_as_ref(token_amount_ptr, "token_amount_ptr")?;
89    let token_out = mut_ptr_as_mut(token_out, "token_out")?;
90    *token_out = Box::into_raw(Box::new(Token(chain::token::Token {
91        token_id: token_id.0,
92        amount: token_amount.0,
93    })));
94    Ok(())
95}
96
97/// Get token id
98pub unsafe fn token_get_id(
99    token_ptr: ConstTokenPtr,
100    token_id_out: *mut TokenIdPtr,
101) -> Result<(), Error> {
102    let token = const_ptr_as_ref(token_ptr, "token_ptr")?;
103    let token_id_out = mut_ptr_as_mut(token_id_out, "token_id_out")?;
104    *token_id_out = Box::into_raw(Box::new(TokenId(token.0.token_id)));
105    Ok(())
106}
107
108/// Get token amount
109pub unsafe fn token_get_amount(
110    token_ptr: ConstTokenPtr,
111    token_amount_out: *mut TokenAmountPtr,
112) -> Result<(), Error> {
113    let token = const_ptr_as_ref(token_ptr, "token_ptr")?;
114    let token_amount_out = mut_ptr_as_mut(token_amount_out, "token_amount_out")?;
115    *token_amount_out = Box::into_raw(Box::new(TokenAmount(token.0.amount)));
116    Ok(())
117}
118
119/// JSON representation according to EIP-12 <https://github.com/ergoplatform/eips/pull/23>
120pub unsafe fn token_to_json_eip12(token_ptr: ConstTokenPtr) -> Result<String, Error> {
121    let token = const_ptr_as_ref(token_ptr, "token_ptr")?;
122    let t_dapp: TokenJsonEip12 = token.0.clone().into();
123    let s = serde_json::to_string(&t_dapp)?;
124    Ok(s)
125}