Skip to main content

qualia_client_core/wallet/
semantic_tokens.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub struct SemanticTokenMetadata {
5    pub token_ticker: String,
6    pub token_name: String,
7    pub token_document_url: String,
8    pub token_document_hash: String,
9    pub decimals: u8,
10}
11
12pub fn generate_slp_op_return(metadata: &SemanticTokenMetadata) -> Vec<u8> {
13    let mut payload = Vec::new();
14
15    payload.push(0x6a); // OP_RETURN
16    payload.extend_from_slice(b"\x04SLP\x00"); // LOKAD ID
17    payload.extend_from_slice(b"\x01\x01"); // Token Type
18    payload.extend_from_slice(b"\x07GENESIS");
19
20    let ticker_bytes = metadata.token_ticker.as_bytes();
21    payload.push(ticker_bytes.len() as u8);
22    payload.extend_from_slice(ticker_bytes);
23
24    let name_bytes = metadata.token_name.as_bytes();
25    payload.push(name_bytes.len() as u8);
26    payload.extend_from_slice(name_bytes);
27
28    let url_bytes = metadata.token_document_url.as_bytes();
29    payload.push(url_bytes.len() as u8);
30    payload.extend_from_slice(url_bytes);
31
32    let hash_bytes = hex::decode(&metadata.token_document_hash).unwrap_or_else(|_| vec![0; 32]);
33    payload.push(hash_bytes.len() as u8);
34    payload.extend_from_slice(&hash_bytes);
35
36    payload.extend_from_slice(&[0x01, metadata.decimals]);
37
38    payload
39}
40
41pub fn generate_slp_send_op_return(token_id: &str, amounts: &[u64]) -> Vec<u8> {
42    let mut payload = Vec::new();
43    payload.push(0x6a); // OP_RETURN
44    payload.extend_from_slice(b"\x04SLP\x00"); // LOKAD ID
45    payload.extend_from_slice(b"\x01\x01"); // Token Type
46    payload.extend_from_slice(b"\x04SEND");
47
48    let token_id_bytes = hex::decode(token_id).unwrap_or_else(|_| vec![0; 32]);
49    payload.push(token_id_bytes.len() as u8);
50    payload.extend_from_slice(&token_id_bytes);
51
52    for &amount in amounts {
53        payload.push(0x08);
54        payload.extend_from_slice(&amount.to_be_bytes());
55    }
56
57    payload
58}
59
60pub fn generate_alp_send_op_return(token_id: &str, amounts: &[u64]) -> Vec<u8> {
61    let mut payload = Vec::new();
62    payload.push(0x6a); // OP_RETURN
63    payload.extend_from_slice(b"\x04ALP\x00"); // LOKAD ID
64    payload.extend_from_slice(b"\x01\x01"); // Token Type
65    payload.extend_from_slice(b"\x04SEND");
66
67    let token_id_bytes = hex::decode(token_id).unwrap_or_else(|_| vec![0; 32]);
68    payload.push(token_id_bytes.len() as u8);
69    payload.extend_from_slice(&token_id_bytes);
70
71    for &amount in amounts {
72        payload.push(0x08);
73        payload.extend_from_slice(&amount.to_be_bytes());
74    }
75
76    payload
77}
78
79pub fn generate_semantic_metadata_cbor(
80    subject_did: &str,
81    properties: serde_json::Value,
82) -> Result<Vec<u8>, String> {
83    let doc = serde_json::json!({
84        "@context": "https://qualia.io/contexts/semantic-tokens-v1.jsonld",
85        "@id": subject_did,
86        "@type": "SemanticToken",
87        "properties": properties
88    });
89
90    let mut buffer = Vec::new();
91    ciborium::into_writer(&doc, &mut buffer).map_err(|e| e.to_string())?;
92    Ok(buffer)
93}