spawn_wasm_erc721/
erc721.rs

1use std::collections::HashMap;
2use wasm_bindgen::prelude::*;
3use web_sys::console;
4
5/// ERC721 Token standardına uygun NFT yönetimi
6#[wasm_bindgen]
7pub struct ERC721 {
8    owner: String,
9    token_owner: HashMap<u64, String>, // Token ID -> Sahip Adresi
10    owned_tokens: HashMap<String, Vec<u64>>, // Kullanıcı Adresi -> Sahip Olduğu Tokenlar
11    approvals: HashMap<u64, String>, // Token ID -> Onaylı Adres
12}
13
14#[wasm_bindgen]
15impl ERC721 {
16    /// Yeni bir ERC721 kontratı oluşturur
17    #[wasm_bindgen(constructor)]
18    pub fn new(owner: String) -> ERC721 {
19        Self::log_event("ERC721 Created", &format!("Owner: {}", owner));
20        ERC721 {
21            owner,
22            token_owner: HashMap::new(),
23            owned_tokens: HashMap::new(),
24            approvals: HashMap::new(),
25        }
26    }
27
28    /// Token'ın sahibini döner
29    pub fn owner_of(&self, token_id: u64) -> Option<String> {
30        self.token_owner.get(&token_id).cloned()
31    }
32
33    /// Bir token'ı mint'ler ve sahibine atar (sadece kontrat sahibi yapabilir)
34    pub fn mint(&mut self, owner: String, token_id: u64) -> Result<(), String> {
35        if owner != self.owner {
36            Self::log_event("Minting Failed", "Unauthorized attempt");
37            return Err("Only the contract owner can mint new tokens".to_string());
38        }
39
40        if self.token_owner.contains_key(&token_id) {
41            Self::log_event("Minting Failed", &format!("Token ID {} already exists", token_id));
42            return Err("Token ID already exists".to_string());
43        }
44
45        self.token_owner.insert(token_id, owner.clone());
46        self.owned_tokens.entry(owner.clone()).or_insert(Vec::new()).push(token_id);
47        Self::log_event("Token Minted", &format!("Token ID: {}, Owner: {}", token_id, owner));
48        Ok(())
49    }
50
51    /// Token'ı başka bir kullanıcıya transfer eder
52    pub fn transfer(&mut self, from: String, to: String, token_id: u64) -> Result<(), String> {
53        let owner = self.token_owner.get(&token_id).ok_or("Token does not exist")?;
54
55        if owner != &from && !self.is_approved_or_owner(from.clone(), token_id) {
56            Self::log_event("Transfer Failed", "Unauthorized attempt");
57            return Err("Unauthorized transfer attempt".to_string());
58        }
59
60        self.remove_token_from_owner(from.clone(), token_id);
61        self.token_owner.insert(token_id, to.clone());
62        self.owned_tokens.entry(to.clone()).or_insert(Vec::new()).push(token_id);
63        Self::log_event("Token Transferred", &format!("Token ID: {}, From: {}, To: {}", token_id, from, to));
64        Ok(())
65    }
66
67    /// Token'ı başka bir kullanıcıya transfer edebilmesi için onay verir
68    pub fn approve(&mut self, owner: String, approved: String, token_id: u64) -> Result<(), String> {
69        let token_owner = self.token_owner.get(&token_id).ok_or("Token does not exist")?;
70
71        if token_owner != &owner {
72            Self::log_event("Approval Failed", "Unauthorized attempt");
73            return Err("Only the owner can approve".to_string());
74        }
75
76        self.approvals.insert(token_id, approved.clone());
77        Self::log_event("Approval Granted", &format!("Token ID: {}, Approved for: {}", token_id, approved));
78        Ok(())
79    }
80
81    /// Bir token'ın kime onaylı olduğunu döner
82    pub fn get_approved(&self, token_id: u64) -> Option<String> {
83        self.approvals.get(&token_id).cloned()
84    }
85
86    /// Token sahibinin onaylayıp onaylamadığını kontrol eder
87    pub fn is_approved_or_owner(&self, user: String, token_id: u64) -> bool {
88        let owner = self.token_owner.get(&token_id);
89        let approved = self.approvals.get(&token_id);
90
91        owner.map(|o| o == &user).unwrap_or(false) || approved.map(|a| a == &user).unwrap_or(false)
92    }
93
94    /// Kullanıcıya ait olan tüm token'ları listeler
95    pub fn tokens_of_owner(&self, owner: String) -> Vec<u64> {
96        self.owned_tokens.get(&owner).cloned().unwrap_or_else(Vec::new)
97    }
98
99    /// Olayları tarayıcı konsoluna loglar
100    fn log_event(event: &str, details: &str) {
101        console::log_2(&event.into(), &details.into());
102    }
103
104    /// Token sahibinden token'ı kaldırır (Transfer sırasında kullanılır)
105    fn remove_token_from_owner(&mut self, owner: String, token_id: u64) {
106        if let Some(tokens) = self.owned_tokens.get_mut(&owner) {
107            tokens.retain(|&id| id != token_id);
108        }
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    #[test]
117    fn test_mint_and_transfer() {
118        let mut erc721 = ERC721::new("owner".to_string());
119
120        // Mint token
121        assert!(erc721.mint("owner".to_string(), 1).is_ok());
122        assert_eq!(erc721.owner_of(1).unwrap(), "owner".to_string());
123
124        // Transfer token
125        assert!(erc721.transfer("owner".to_string(), "user1".to_string(), 1).is_ok());
126        assert_eq!(erc721.owner_of(1).unwrap(), "user1".to_string());
127
128        // Unauthorized transfer should fail
129        assert!(erc721.transfer("owner".to_string(), "user2".to_string(), 1).is_err());
130    }
131
132    #[test]
133    fn test_approval_and_transfer() {
134        let mut erc721 = ERC721::new("owner".to_string());
135
136        // Mint token
137        erc721.mint("owner".to_string(), 1).unwrap();
138
139        // Approve transfer
140        assert!(erc721.approve("owner".to_string(), "user1".to_string(), 1).is_ok());
141        assert_eq!(erc721.get_approved(1).unwrap(), "user1".to_string());
142
143        // Approved user can transfer
144        assert!(erc721.transfer("user1".to_string(), "user2".to_string(), 1).is_ok());
145        assert_eq!(erc721.owner_of(1).unwrap(), "user2".to_string());
146    }
147}