├── README.md ├── Cargo.toml ├── .gitignore ├── icrc7 ├── src │ ├── utils.rs │ ├── memory.rs │ ├── state.rs │ └── lib.rs ├── Cargo.toml └── icrc7.did ├── archive ├── Cargo.toml ├── archive.did └── src │ └── lib.rs ├── dfx.json └── Cargo.lock /README.md: -------------------------------------------------------------------------------- 1 | # ICRC7 2 | 3 | This is the minimal implementation of (ICRC-7)[] NFT using Rust. 4 | 5 | ```bash 6 | chmod +x build.sh 7 | ./build.sh 8 | ``` 9 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["icrc7", "archive"] 4 | 5 | [profile.release] 6 | panic = "abort" 7 | lto = true 8 | opt-level = 'z' 9 | strip = "debuginfo" 10 | codegen-units = 1 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | /target 3 | /.dfx 4 | /.env 5 | /node_modules 6 | /pnpm-lock.yaml 7 | /wasm_files 8 | 9 | # Added by cargo 10 | # 11 | # already existing elements were commented out 12 | 13 | #/target 14 | -------------------------------------------------------------------------------- /icrc7/src/utils.rs: -------------------------------------------------------------------------------- 1 | use icrc_nft_types::{Account, DEFAULT_SUBACCOUNT}; 2 | 3 | pub fn account_transformer(account: Account) -> Account { 4 | if account.subaccount.is_none() { 5 | Account { 6 | subaccount: Some(*DEFAULT_SUBACCOUNT), 7 | ..account 8 | } 9 | } else { 10 | account 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /archive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "archive" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [lib] 8 | crate-type = [ "cdylib" ] 9 | 10 | [dependencies] 11 | candid = "0.10.6" 12 | ciborium = "0.2.2" 13 | ic-cdk = "0.13.1" 14 | ic-stable-structures = "0.6.3" 15 | icrc-ledger-types = "0.1.5" 16 | serde = "1.0.197" 17 | -------------------------------------------------------------------------------- /dfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "canisters": { 4 | "icrc7": { 5 | "type": "custom", 6 | "optimize": "cycles", 7 | "wasm": "wasm_files/icrc7.wasm.gz", 8 | "candid": "icrc7/icrc7.did", 9 | "metadata": [ 10 | { 11 | "name": "candid:service" 12 | } 13 | ] 14 | } 15 | }, 16 | "defaults": { 17 | "build": { 18 | "packtool": "", 19 | "args": "" 20 | } 21 | }, 22 | "output_env_file": ".env" 23 | } 24 | -------------------------------------------------------------------------------- /icrc7/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "icrc7" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | candid = "0.10.6" 12 | ic-cdk = "0.13.1" 13 | ic-stable-structures = "0.6.3" 14 | icrc-ledger-types = "0.1.5" 15 | serde = "1.0.197" 16 | icrc-nft-types = { git = "https://github.com/pramitgaha21/icrc-nft-types.git" } 17 | ciborium = "0.2.2" 18 | -------------------------------------------------------------------------------- /archive/archive.did: -------------------------------------------------------------------------------- 1 | type ArchiveInfo = record { 2 | block_range_end : nat; 3 | canister_id : principal; 4 | block_range_start : nat; 5 | }; 6 | type BlockType = record { url : text; block_type : text }; 7 | type DataCertificate = record { certificate : opt blob; hash_tree : blob }; 8 | type GetArchiveArgs = record { from : opt principal }; 9 | service : { 10 | icrc3_get_archives : (GetArchiveArgs) -> (vec ArchiveInfo) query; 11 | icrc3_get_tip_certificate : () -> (opt DataCertificate) query; 12 | icrc3_supported_block_types : () -> (vec BlockType) query; 13 | } 14 | -------------------------------------------------------------------------------- /icrc7/src/memory.rs: -------------------------------------------------------------------------------- 1 | use crate::state::{TokenMap, TxnLog, MEMORY_MANAGER}; 2 | use ic_stable_structures::{ 3 | memory_manager::{MemoryId, VirtualMemory}, 4 | DefaultMemoryImpl, 5 | }; 6 | 7 | pub type Memory = VirtualMemory; 8 | 9 | pub fn get_upgrade_memory() -> Memory { 10 | MEMORY_MANAGER.with_borrow(|m| m.get(MemoryId::new(0))) 11 | } 12 | 13 | pub fn get_state_memory() -> Memory { 14 | MEMORY_MANAGER.with_borrow(|m| m.get(MemoryId::new(1))) 15 | } 16 | 17 | pub fn get_token_map() -> TokenMap { 18 | TokenMap::init(MEMORY_MANAGER.with_borrow(|m| m.get(MemoryId::new(2)))) 19 | } 20 | 21 | pub fn get_txn_log() -> TxnLog { 22 | TxnLog::init(MEMORY_MANAGER.with_borrow(|m| m.get(MemoryId::new(3)))) 23 | } 24 | -------------------------------------------------------------------------------- /icrc7/icrc7.did: -------------------------------------------------------------------------------- 1 | type Account = record { owner : principal; subaccount : opt blob }; 2 | type Icrc7TokenMetadata = record { 3 | metadata : vec record { text; MetadataValue }; 4 | }; 5 | type InitArg = record { 6 | icrc7_supply_cap : opt nat; 7 | minting_auth : opt Account; 8 | icrc7_symbol : text; 9 | icrc7_name : text; 10 | }; 11 | type MetadataValue = variant { Int : int; Nat : nat; Blob : blob; Text : text }; 12 | type Result = variant { Ok : nat; Err : TransferError }; 13 | type Standard = record { url : text; name : text }; 14 | type TransferArg = record { 15 | to : Account; 16 | token_id : nat; 17 | memo : opt blob; 18 | from_subaccount : opt blob; 19 | created_at_time : opt nat64; 20 | }; 21 | type TransferError = variant { 22 | GenericError : record { message : text; error_code : nat }; 23 | Duplicate : record { duplicate_of : nat }; 24 | NonExistingTokenId; 25 | Unauthorized; 26 | CreatedInFuture : record { ledger_time : nat64 }; 27 | InvalidRecipient; 28 | GenericBatchError : record { message : text; error_code : nat }; 29 | TooOld; 30 | }; 31 | service : (InitArg) -> { 32 | icrc61_supported_standards : () -> (vec Standard) query; 33 | icrc7_atomic_batch_transfer : () -> (opt bool) query; 34 | icrc7_balance_of : (vec Account) -> (vec nat) query; 35 | icrc7_default_take_value : () -> (opt nat) query; 36 | icrc7_description : () -> (opt text) query; 37 | icrc7_logo : () -> (opt text) query; 38 | icrc7_max_memo_size : () -> (opt nat) query; 39 | icrc7_max_query_batch_size : () -> (opt nat) query; 40 | icrc7_max_take_value : () -> (opt nat) query; 41 | icrc7_max_update_batch_size : () -> (opt nat) query; 42 | icrc7_name : () -> (text) query; 43 | icrc7_owner_of : (vec nat) -> (vec opt Account) query; 44 | icrc7_permitted_drift : () -> (opt nat) query; 45 | icrc7_supply_cap : () -> (opt nat) query; 46 | icrc7_symbol : () -> (text) query; 47 | icrc7_token_metadata : (vec nat) -> (vec opt Icrc7TokenMetadata) query; 48 | icrc7_tokens : (opt nat, opt nat) -> (vec nat) query; 49 | icrc7_tokens_of : (Account, opt nat, opt nat) -> (vec nat) query; 50 | icrc7_total_supply : () -> (nat) query; 51 | icrc7_transfer : (vec TransferArg) -> (vec opt Result); 52 | icrc7_tx_window : () -> (opt nat) query; 53 | } 54 | -------------------------------------------------------------------------------- /archive/src/lib.rs: -------------------------------------------------------------------------------- 1 | use candid::{CandidType, Principal}; 2 | use ic_cdk::query; 3 | use ic_stable_structures::{ 4 | memory_manager::VirtualMemory, storable::Bound, DefaultMemoryImpl, RestrictedMemory, 5 | StableCell, StableLog, Storable, 6 | }; 7 | use icrc_ledger_types::icrc3::{ 8 | archive::ArchiveInfo, 9 | blocks::{DataCertificate, GetBlocksRequest}, 10 | }; 11 | use serde::{Deserialize, Serialize}; 12 | use std::cell::RefCell; 13 | 14 | const WASM_PAGE_SIZE: u64 = 65536; 15 | 16 | const GIB: u64 = 1024 * 1024 * 1024; 17 | 18 | pub type Memory = RestrictedMemory; 19 | pub type ConfigCell = StableCell; 20 | pub type BLockLog = StableLog, VirtualMemory, VirtualMemory>; 21 | 22 | pub fn config_memory() -> Memory { 23 | RestrictedMemory::new(DefaultMemoryImpl::default(), 0..1) 24 | } 25 | 26 | #[derive(Serialize, Deserialize, Default)] 27 | pub struct ArchiveConfig { 28 | /// The maximum number of bytes archive can use to store encoded blocks. 29 | max_memory_size_bytes: u64, 30 | /// The index of the first block in the archive. 31 | block_index_offset: u64, 32 | /// The principal of the ledger canister that created this archive. 33 | /// The archive will accept blocks only from this principal. 34 | ledger_id: Option, 35 | /// The maximum number of transactions returned by [get_transactions]. 36 | max_transactions_per_response: u64, 37 | } 38 | 39 | impl Storable for ArchiveConfig { 40 | fn to_bytes(&self) -> std::borrow::Cow<[u8]> { 41 | let mut buf = vec![]; 42 | ciborium::ser::into_writer(self, &mut buf).expect("Failed to serialize using ciborium"); 43 | std::borrow::Cow::Owned(buf) 44 | } 45 | 46 | fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self { 47 | ciborium::de::from_reader(&bytes[..]).expect("Failed to deserialize using ciborium") 48 | } 49 | 50 | const BOUND: Bound = Bound::Unbounded; 51 | } 52 | 53 | pub type GetTransactionRequest = GetBlocksRequest; 54 | 55 | pub fn init() {} 56 | 57 | pub fn append_block() {} 58 | 59 | pub fn get_transaction() {} 60 | 61 | pub fn get_transactions() {} 62 | 63 | pub fn icrc3_get_blocks() {} 64 | 65 | #[derive(CandidType, Deserialize, Debug)] 66 | pub struct GetArchiveArgs { 67 | pub from: Option, 68 | } 69 | 70 | #[query] 71 | pub fn icrc3_get_archives(_arg: GetArchiveArgs) -> Vec { 72 | vec![] 73 | } 74 | 75 | #[query] 76 | pub fn icrc3_get_tip_certificate() -> Option { 77 | // Only the Ledger certifies the tip of the chain. 78 | None 79 | } 80 | 81 | #[derive(CandidType, Debug)] 82 | pub struct BlockType { 83 | pub block_type: String, 84 | pub url: String, 85 | } 86 | 87 | #[query] 88 | pub fn icrc3_supported_block_types() -> Vec { 89 | vec![ 90 | BlockType { 91 | block_type: "7mint".into(), 92 | url: "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md".into(), 93 | }, 94 | BlockType { 95 | block_type: "7burn".into(), 96 | url: "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md".into(), 97 | }, 98 | BlockType { 99 | block_type: "7x_fer".into(), 100 | url: "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md".into(), 101 | }, 102 | BlockType { 103 | block_type: "7update_token".into(), 104 | url: "https://github.com/dfinity/ICRC/blob/main/ICRCs/ICRC-7/ICRC-7.md".into(), 105 | }, 106 | ] 107 | } 108 | 109 | thread_local! { 110 | /// Static configuration of the archive that init() sets once. 111 | static CONFIG: RefCell = RefCell::new(ConfigCell::init( 112 | config_memory(), 113 | ArchiveConfig::default(), 114 | ).expect("failed to initialize stable cell")); 115 | // static BLOCK: RefCell = RefCell::new() 116 | } 117 | 118 | ic_cdk::export_candid!(); 119 | -------------------------------------------------------------------------------- /icrc7/src/state.rs: -------------------------------------------------------------------------------- 1 | use crate::memory::{get_state_memory, get_token_map, get_txn_log, Memory}; 2 | use candid::{CandidType, Decode, Encode, Principal}; 3 | use ic_stable_structures::{ 4 | memory_manager::MemoryManager, storable::Bound, DefaultMemoryImpl, StableBTreeMap, StableCell, 5 | Storable, 6 | }; 7 | use icrc_ledger_types::icrc::generic_metadata_value::MetadataValue; 8 | use icrc_nft_types::icrc7::transaction::Transaction; 9 | use icrc_nft_types::icrc7::transfer::{TransferArg, TransferError}; 10 | use icrc_nft_types::{icrc7::metadata::Icrc7TokenMetadata, Account}; 11 | use serde::{Deserialize, Serialize}; 12 | use std::cell::RefCell; 13 | use std::collections::HashMap; 14 | 15 | pub type TokenMap = StableBTreeMap; 16 | pub type TxnLog = StableBTreeMap; 17 | 18 | /// The field of this structure is modifiable, you can add more fields according to your need 19 | #[derive(CandidType, Serialize, Deserialize, Debug)] 20 | pub struct Token { 21 | pub id: u128, 22 | pub owner: Account, 23 | pub name: String, 24 | pub logo: Option, 25 | pub description: Option, 26 | } 27 | 28 | impl Storable for Token { 29 | fn to_bytes(&self) -> std::borrow::Cow<[u8]> { 30 | std::borrow::Cow::Owned(Encode!(self).unwrap()) 31 | } 32 | 33 | fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self { 34 | Decode!(bytes.as_ref(), Self).unwrap() 35 | } 36 | 37 | const BOUND: Bound = Bound::Unbounded; 38 | } 39 | 40 | impl Token { 41 | pub fn new( 42 | id: u128, 43 | owner: Account, 44 | name: String, 45 | logo: Option, 46 | description: Option, 47 | ) -> Self { 48 | Self { 49 | id, 50 | owner, 51 | name, 52 | logo, 53 | description, 54 | } 55 | } 56 | 57 | pub fn transfer(&mut self, to: Account) { 58 | self.owner = to; 59 | } 60 | 61 | pub fn token_metadata(&self) -> Icrc7TokenMetadata { 62 | let mut metadata = HashMap::new(); 63 | metadata.insert( 64 | "icrc7token:name".into(), 65 | MetadataValue::Text(self.name.clone()), 66 | ); 67 | // TODO 68 | Icrc7TokenMetadata::from(metadata) 69 | } 70 | } 71 | 72 | #[derive(Serialize, Deserialize, Clone)] 73 | pub struct CollectionMetadata { 74 | pub minting_auth: Option, // when minting_auth is `None`: anyone can mint if allowed 75 | pub mintable_flag: Option, 76 | pub burnable_flag: Option, 77 | pub burn_account: Option, 78 | pub icrc7_name: Option, 79 | pub icrc7_symbol: Option, 80 | pub icrc7_description: Option, 81 | pub icrc7_logo: Option, 82 | pub icrc7_supply_cap: Option, 83 | pub icrc7_max_query_batch_size: Option, 84 | pub icrc7_max_update_batch_size: Option, 85 | pub icrc7_default_take_value: Option, 86 | pub icrc7_max_take_value: Option, 87 | pub icrc7_max_memo_size: Option, 88 | pub icrc7_atomic_batch_transfer: Option, // defaults to false 89 | pub icrc7_tx_window: Option, 90 | pub icrc7_permitted_drift: Option, 91 | pub txn_count: u128, 92 | } 93 | 94 | impl Storable for CollectionMetadata { 95 | fn from_bytes(bytes: std::borrow::Cow<[u8]>) -> Self { 96 | ciborium::de::from_reader(&bytes[..]).unwrap() 97 | } 98 | 99 | fn to_bytes(&self) -> std::borrow::Cow<[u8]> { 100 | let mut buf = vec![]; 101 | ciborium::ser::into_writer(self, &mut buf).expect("failed to Serialize"); 102 | std::borrow::Cow::Owned(buf) 103 | } 104 | 105 | const BOUND: Bound = Bound::Unbounded; 106 | } 107 | 108 | impl Default for CollectionMetadata { 109 | fn default() -> Self { 110 | Self { 111 | minting_auth: None, 112 | mintable_flag: None, 113 | burnable_flag: None, 114 | burn_account: None, 115 | icrc7_name: None, 116 | icrc7_symbol: None, 117 | icrc7_description: None, 118 | icrc7_logo: None, 119 | icrc7_supply_cap: None, 120 | icrc7_max_query_batch_size: None, 121 | icrc7_max_update_batch_size: None, 122 | icrc7_default_take_value: None, 123 | icrc7_max_take_value: None, 124 | icrc7_max_memo_size: None, 125 | icrc7_atomic_batch_transfer: None, 126 | icrc7_tx_window: None, 127 | icrc7_permitted_drift: None, 128 | txn_count: 0, 129 | } 130 | } 131 | } 132 | 133 | pub fn query_metadata(f: impl FnOnce(&CollectionMetadata) -> R) -> R { 134 | COLLECTION_METADATA.with_borrow(|s| f(s.get())) 135 | } 136 | 137 | pub fn query_token_map(f: impl FnOnce(&TokenMap) -> R) -> R { 138 | TOKEN_MAP.with_borrow(|map| f(map)) 139 | } 140 | 141 | pub fn get_txn_id() -> u128 { 142 | COLLECTION_METADATA.with_borrow_mut(|m| { 143 | let mut current_data = m.get().clone(); 144 | let txn_id = current_data.txn_count; 145 | current_data.txn_count += 1; 146 | let _ = m.set(current_data); 147 | txn_id 148 | }) 149 | } 150 | 151 | pub fn txn_deduplication_check( 152 | allowed_past_time: &u64, 153 | caller: &Account, 154 | arg: &TransferArg, 155 | ) -> Result<(), TransferError> { 156 | TXN_LOG.with_borrow(|log| { 157 | // getting the last recorded txn_id 158 | let mut count = query_metadata(|m| m.txn_count - 1); 159 | while count != 0 { 160 | let txn = log.get(&count).unwrap(); 161 | // checking if the timestamp falls between allowed past time 162 | if txn.ts <= *allowed_past_time { 163 | return Ok(()); 164 | } 165 | // checking if the timestamp and memo of the transaction are equal 166 | if Some(txn.ts) != arg.created_at_time && arg.memo != txn.memo { 167 | count -= 1; 168 | continue; // skipping to next iteration 169 | } 170 | if let Some(transfer) = txn.transfer { 171 | if arg.token_id == transfer.tid && arg.to == transfer.to && *caller == transfer.from 172 | { 173 | return Err(TransferError::Duplicate { 174 | duplicate_of: txn.txn_id, 175 | }); 176 | } else { 177 | count -= 1; 178 | continue; // skipping to next iteration 179 | } 180 | } else { 181 | count -= 1; 182 | continue; 183 | } 184 | } 185 | Ok(()) 186 | }) 187 | } 188 | 189 | pub fn log_transaction() -> u128 { 190 | let txn_id = get_txn_id(); 191 | // TODO: logging of transaction 192 | txn_id 193 | } 194 | 195 | pub fn mock_transfer(caller: &Account, arg: &TransferArg) -> Result<(), TransferError> { 196 | if let Some(ref memo) = arg.memo { 197 | if memo.len() > 32 { 198 | return Err(TransferError::GenericError { 199 | error_code: 112, 200 | message: "Exceeds Max Memo Size".into(), 201 | }); 202 | } 203 | } 204 | if let Some(time) = arg.created_at_time { 205 | // TODO: checking for time 206 | txn_deduplication_check(&0, caller, arg)? 207 | } 208 | if *caller == arg.to { 209 | return Err(TransferError::InvalidRecipient); 210 | } 211 | query_token_map(|map| { 212 | let token = match map.get(&arg.token_id) { 213 | None => return Err(TransferError::NonExistingTokenId), 214 | Some(token) => token, 215 | }; 216 | if token.owner != *caller { 217 | return Err(TransferError::Unauthorized); 218 | } 219 | Ok(()) 220 | }) 221 | } 222 | 223 | pub fn execute_transfer(caller: Account, arg: TransferArg) -> u128 { 224 | todo!() 225 | } 226 | 227 | pub fn mock_mint() {} 228 | 229 | pub fn execute_mint() {} 230 | 231 | pub fn mock_burn() {} 232 | 233 | pub fn execute_burn() {} 234 | 235 | pub fn check_and_scale_storage_if_needed() {} 236 | 237 | thread_local! { 238 | pub static MEMORY_MANAGER: RefCell> = RefCell::new(MemoryManager::init(DefaultMemoryImpl::default())); 239 | pub static COLLECTION_METADATA: RefCell> = RefCell::new(StableCell::new(get_state_memory(), CollectionMetadata::default()).unwrap()); 240 | pub static TOKEN_MAP: RefCell = RefCell::new(get_token_map()); 241 | pub static TXN_LOG: RefCell = RefCell::new(get_txn_log()); 242 | } 243 | -------------------------------------------------------------------------------- /icrc7/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod memory; 2 | pub mod state; 3 | pub mod utils; 4 | 5 | use candid::{CandidType, Nat}; 6 | use ic_cdk::{init, query, update}; 7 | use icrc_ledger_types::icrc::generic_metadata_value::MetadataValue; 8 | use icrc_nft_types::{ 9 | icrc7::{ 10 | metadata::{Icrc7CollectionMetadata, Icrc7TokenMetadata}, 11 | transfer::{TransferArg, TransferResult}, 12 | }, 13 | Account, 14 | }; 15 | use serde::Deserialize; 16 | use state::{query_metadata, query_token_map}; 17 | 18 | #[derive(CandidType, Deserialize, Debug)] 19 | pub struct InitArg { 20 | pub minting_auth: Option, 21 | pub icrc7_name: String, 22 | pub icrc7_symbol: String, 23 | pub icrc7_supply_cap: Option, 24 | } 25 | 26 | #[init] 27 | pub fn init(arg: InitArg) {} 28 | 29 | pub fn icrc7_collection_metadata() -> Icrc7CollectionMetadata { 30 | query_metadata(|metadata| { 31 | let mut map = Icrc7CollectionMetadata::new(); 32 | map.insert( 33 | "icrc7:name".into(), 34 | MetadataValue::Text(metadata.icrc7_name.as_ref().unwrap().clone()), 35 | ); 36 | map.insert( 37 | "icrc7:symbol".into(), 38 | MetadataValue::Text(metadata.icrc7_symbol.as_ref().unwrap().clone()), 39 | ); 40 | if let Some(logo) = metadata.icrc7_logo.as_ref() { 41 | map.insert("icrc7:logo".into(), MetadataValue::Text(logo.clone())); 42 | } 43 | if let Some(description) = metadata.icrc7_description.as_ref() { 44 | map.insert( 45 | "icrc7:description".into(), 46 | MetadataValue::Text(description.clone()), 47 | ); 48 | } 49 | map.insert( 50 | "icrc7:total_supply".into(), 51 | MetadataValue::Nat(Nat::from(query_token_map(|map| map.len() as u128))), 52 | ); 53 | if let Some(supply_cap) = metadata.icrc7_supply_cap { 54 | map.insert( 55 | "icrc7:supply_cap".into(), 56 | MetadataValue::Nat(Nat::from(supply_cap)), 57 | ); 58 | } 59 | if let Some(max_query_batch_size) = metadata.icrc7_max_query_batch_size { 60 | map.insert( 61 | "icrc7:max_query_batch_size".into(), 62 | MetadataValue::Nat(Nat::from(max_query_batch_size)), 63 | ); 64 | } 65 | if let Some(max_update_batch_size) = metadata.icrc7_max_update_batch_size { 66 | map.insert( 67 | "icrc7:max_update_batch_size".into(), 68 | MetadataValue::Nat(Nat::from(max_update_batch_size)), 69 | ); 70 | } 71 | if let Some(default_take_value) = metadata.icrc7_default_take_value { 72 | map.insert( 73 | "icrc7:default_take_value".into(), 74 | MetadataValue::Nat(Nat::from(default_take_value)), 75 | ); 76 | } 77 | if let Some(max_take_value) = metadata.icrc7_max_take_value { 78 | map.insert( 79 | "icrc7:max_take_value".into(), 80 | MetadataValue::Nat(Nat::from(max_take_value)), 81 | ); 82 | } 83 | if let Some(max_memo_size) = metadata.icrc7_max_memo_size { 84 | map.insert( 85 | "icrc7:max_memo_size".into(), 86 | MetadataValue::Nat(Nat::from(max_memo_size)), 87 | ); 88 | } 89 | //if let Some(atomic_batch_transfer) = metadata.icrc7_atomic_batch_transfer{ 90 | // TODO: can't figure out, how to have atomic_batch_transfer returned 91 | //map.insert("icrc7:atomic_batch_transfer".into(), MetadataValue) 92 | // } 93 | if let Some(permitted_drift) = metadata.icrc7_permitted_drift { 94 | map.insert( 95 | "icrc7:permitted_drift".into(), 96 | MetadataValue::Nat(Nat::from(permitted_drift)), 97 | ); 98 | } 99 | if let Some(tx_window) = metadata.icrc7_permitted_drift { 100 | map.insert( 101 | "icrc7:tx_window".into(), 102 | MetadataValue::Nat(Nat::from(tx_window)), 103 | ); 104 | } 105 | map 106 | }) 107 | } 108 | 109 | #[query] 110 | pub fn icrc7_name() -> String { 111 | query_metadata(|metadata| metadata.icrc7_name.as_ref().unwrap().clone()) 112 | } 113 | 114 | #[query] 115 | pub fn icrc7_symbol() -> String { 116 | query_metadata(|metadata| metadata.icrc7_symbol.as_ref().unwrap().clone()) 117 | } 118 | 119 | #[query] 120 | pub fn icrc7_total_supply() -> u128 { 121 | query_token_map(|map| map.len() as u128) 122 | } 123 | 124 | #[query] 125 | pub fn icrc7_supply_cap() -> Option { 126 | query_metadata(|metadata| metadata.icrc7_supply_cap) 127 | } 128 | 129 | #[query] 130 | pub fn icrc7_description() -> Option { 131 | query_metadata(|metadata| metadata.icrc7_description.clone()) 132 | } 133 | 134 | #[query] 135 | pub fn icrc7_logo() -> Option { 136 | query_metadata(|metadata| metadata.icrc7_logo.clone()) 137 | } 138 | 139 | #[query] 140 | pub fn icrc7_max_query_batch_size() -> Option { 141 | query_metadata(|metadata| metadata.icrc7_max_query_batch_size) 142 | } 143 | 144 | #[query] 145 | pub fn icrc7_max_update_batch_size() -> Option { 146 | query_metadata(|metadata| metadata.icrc7_max_update_batch_size) 147 | } 148 | 149 | #[query] 150 | pub fn icrc7_default_take_value() -> Option { 151 | query_metadata(|metadata| metadata.icrc7_default_take_value) 152 | } 153 | 154 | #[query] 155 | pub fn icrc7_max_take_value() -> Option { 156 | query_metadata(|metadata| metadata.icrc7_max_take_value) 157 | } 158 | 159 | #[query] 160 | pub fn icrc7_max_memo_size() -> Option { 161 | query_metadata(|metadata| metadata.icrc7_max_memo_size) 162 | } 163 | 164 | #[query] 165 | pub fn icrc7_atomic_batch_transfer() -> Option { 166 | query_metadata(|metadata| metadata.icrc7_atomic_batch_transfer) 167 | } 168 | 169 | #[query] 170 | pub fn icrc7_tx_window() -> Option { 171 | query_metadata(|metadata| metadata.icrc7_tx_window) 172 | } 173 | 174 | #[query] 175 | pub fn icrc7_permitted_drift() -> Option { 176 | query_metadata(|metadata| metadata.icrc7_permitted_drift) 177 | } 178 | 179 | #[query] 180 | pub fn icrc7_token_metadata(token_ids: Vec) -> Vec> { 181 | query_token_map(|token_map| { 182 | token_ids 183 | .into_iter() 184 | .map(|id| { 185 | if let Some(token) = token_map.get(&id) { 186 | Some(token.token_metadata()) 187 | } else { 188 | None 189 | } 190 | }) 191 | .collect() 192 | }) 193 | } 194 | 195 | #[query] 196 | pub fn icrc7_owner_of(token_ids: Vec) -> Vec> { 197 | query_token_map(|token_map| { 198 | token_ids 199 | .into_iter() 200 | .map(|id| { 201 | if let Some(token) = token_map.get(&id) { 202 | Some(token.owner) 203 | } else { 204 | None 205 | } 206 | }) 207 | .collect() 208 | }) 209 | } 210 | 211 | #[query] 212 | pub fn icrc7_balance_of(accounts: Vec) -> Vec { 213 | query_token_map(|token_map| { 214 | accounts 215 | .into_iter() 216 | .map(|account| { 217 | let mut balance = Nat::from(0u128); 218 | token_map.iter().for_each(|(_k, v)| { 219 | if v.owner == account { 220 | balance += Nat::from(1u128); 221 | } 222 | }); 223 | balance 224 | }) 225 | .collect() 226 | }) 227 | } 228 | 229 | pub fn icrc7_tokens(prev: Option, take: Option) -> Vec { 230 | todo!() 231 | } 232 | 233 | pub fn icrc7_tokens_of(account: Account, prev: Option, take: Option) -> Vec { 234 | todo!() 235 | } 236 | 237 | pub fn icrc7_transfer(args: Vec) -> Vec> { 238 | todo!() 239 | } 240 | 241 | pub fn mint() {} 242 | 243 | pub fn burn() {} 244 | 245 | #[derive(CandidType, Debug)] 246 | pub struct Standard { 247 | name: String, 248 | url: String, 249 | } 250 | 251 | #[query] 252 | pub fn icrc10_supported_standards() -> Vec { 253 | vec![ 254 | Standard { 255 | name: "ICRC-7".into(), 256 | url: "https://github.com/dfinity/ICRC/ICRCs/ICRC-7".into(), 257 | }, 258 | Standard { 259 | name: "ICRC-61".into(), 260 | url: "https://github.com/dfinity/ICRC/ICRCs/ICRC-61".into(), 261 | }, 262 | ] 263 | } 264 | 265 | ic_cdk::export_candid!(); 266 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.81" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" 10 | 11 | [[package]] 12 | name = "archive" 13 | version = "0.1.0" 14 | dependencies = [ 15 | "candid", 16 | "ciborium", 17 | "ic-cdk", 18 | "ic-stable-structures", 19 | "icrc-ledger-types", 20 | "serde", 21 | ] 22 | 23 | [[package]] 24 | name = "arrayvec" 25 | version = "0.5.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 28 | 29 | [[package]] 30 | name = "autocfg" 31 | version = "1.2.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 34 | 35 | [[package]] 36 | name = "base32" 37 | version = "0.4.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" 40 | 41 | [[package]] 42 | name = "binread" 43 | version = "2.2.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "16598dfc8e6578e9b597d9910ba2e73618385dc9f4b1d43dd92c349d6be6418f" 46 | dependencies = [ 47 | "binread_derive", 48 | "lazy_static", 49 | "rustversion", 50 | ] 51 | 52 | [[package]] 53 | name = "binread_derive" 54 | version = "2.1.0" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed" 57 | dependencies = [ 58 | "either", 59 | "proc-macro2", 60 | "quote", 61 | "syn 1.0.109", 62 | ] 63 | 64 | [[package]] 65 | name = "block-buffer" 66 | version = "0.10.4" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 69 | dependencies = [ 70 | "generic-array", 71 | ] 72 | 73 | [[package]] 74 | name = "byteorder" 75 | version = "1.5.0" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 78 | 79 | [[package]] 80 | name = "candid" 81 | version = "0.10.6" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "965e86b1bd1c0c26df70cf0c92ae16c56204ab402eb915c26a541cf949d841cf" 84 | dependencies = [ 85 | "anyhow", 86 | "binread", 87 | "byteorder", 88 | "candid_derive", 89 | "hex", 90 | "ic_principal", 91 | "leb128", 92 | "num-bigint", 93 | "num-traits", 94 | "paste", 95 | "pretty", 96 | "serde", 97 | "serde_bytes", 98 | "stacker", 99 | "thiserror", 100 | ] 101 | 102 | [[package]] 103 | name = "candid_derive" 104 | version = "0.6.6" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "3de398570c386726e7a59d9887b68763c481477f9a043fb998a2e09d428df1a9" 107 | dependencies = [ 108 | "lazy_static", 109 | "proc-macro2", 110 | "quote", 111 | "syn 2.0.58", 112 | ] 113 | 114 | [[package]] 115 | name = "cc" 116 | version = "1.0.90" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" 119 | 120 | [[package]] 121 | name = "cfg-if" 122 | version = "1.0.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 125 | 126 | [[package]] 127 | name = "ciborium" 128 | version = "0.2.2" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 131 | dependencies = [ 132 | "ciborium-io", 133 | "ciborium-ll", 134 | "serde", 135 | ] 136 | 137 | [[package]] 138 | name = "ciborium-io" 139 | version = "0.2.2" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 142 | 143 | [[package]] 144 | name = "ciborium-ll" 145 | version = "0.2.2" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 148 | dependencies = [ 149 | "ciborium-io", 150 | "half", 151 | ] 152 | 153 | [[package]] 154 | name = "cpufeatures" 155 | version = "0.2.12" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" 158 | dependencies = [ 159 | "libc", 160 | ] 161 | 162 | [[package]] 163 | name = "crc32fast" 164 | version = "1.4.0" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" 167 | dependencies = [ 168 | "cfg-if", 169 | ] 170 | 171 | [[package]] 172 | name = "crunchy" 173 | version = "0.2.2" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 176 | 177 | [[package]] 178 | name = "crypto-common" 179 | version = "0.1.6" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 182 | dependencies = [ 183 | "generic-array", 184 | "typenum", 185 | ] 186 | 187 | [[package]] 188 | name = "data-encoding" 189 | version = "2.5.0" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" 192 | 193 | [[package]] 194 | name = "digest" 195 | version = "0.10.7" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 198 | dependencies = [ 199 | "block-buffer", 200 | "crypto-common", 201 | ] 202 | 203 | [[package]] 204 | name = "either" 205 | version = "1.10.0" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" 208 | 209 | [[package]] 210 | name = "generic-array" 211 | version = "0.14.7" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 214 | dependencies = [ 215 | "typenum", 216 | "version_check", 217 | ] 218 | 219 | [[package]] 220 | name = "half" 221 | version = "2.4.1" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 224 | dependencies = [ 225 | "cfg-if", 226 | "crunchy", 227 | ] 228 | 229 | [[package]] 230 | name = "hex" 231 | version = "0.4.3" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 234 | 235 | [[package]] 236 | name = "ic-cdk" 237 | version = "0.13.1" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "c63a6fceb94127bda86bd6d05f859a0e2a67d128a8ffb5ddab17e1f15ac8f555" 240 | dependencies = [ 241 | "candid", 242 | "ic-cdk-macros", 243 | "ic0", 244 | "serde", 245 | "serde_bytes", 246 | ] 247 | 248 | [[package]] 249 | name = "ic-cdk-macros" 250 | version = "0.9.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "2fde5ca6ef1e69825c68916ff1bf7256b8f7ed69ac5ea3f1756f6e57f1503e27" 253 | dependencies = [ 254 | "candid", 255 | "proc-macro2", 256 | "quote", 257 | "serde", 258 | "serde_tokenstream", 259 | "syn 1.0.109", 260 | ] 261 | 262 | [[package]] 263 | name = "ic-stable-structures" 264 | version = "0.6.3" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "a314297eb9edb4bbcc2e04d2e634e38d5900b68eadae661e927946d1aba3f9f7" 267 | dependencies = [ 268 | "ic_principal", 269 | ] 270 | 271 | [[package]] 272 | name = "ic0" 273 | version = "0.21.1" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "a54b5297861c651551676e8c43df805dad175cc33bc97dbd992edbbb85dcbcdf" 276 | 277 | [[package]] 278 | name = "ic_principal" 279 | version = "0.1.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "1762deb6f7c8d8c2bdee4b6c5a47b60195b74e9b5280faa5ba29692f8e17429c" 282 | dependencies = [ 283 | "crc32fast", 284 | "data-encoding", 285 | "serde", 286 | "sha2", 287 | "thiserror", 288 | ] 289 | 290 | [[package]] 291 | name = "icrc-ledger-types" 292 | version = "0.1.5" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "804c892bf95652101660a25cea10f059f73eb8973f6b04e0349758fda1190447" 295 | dependencies = [ 296 | "base32", 297 | "candid", 298 | "crc32fast", 299 | "hex", 300 | "num-bigint", 301 | "num-traits", 302 | "serde", 303 | "serde_bytes", 304 | "sha2", 305 | ] 306 | 307 | [[package]] 308 | name = "icrc-nft-types" 309 | version = "0.1.0" 310 | source = "git+https://github.com/pramitgaha21/icrc-nft-types.git#811c00fff08e8ab4af32a28e16b3cc2a05de726a" 311 | dependencies = [ 312 | "candid", 313 | "ic-stable-structures", 314 | "icrc-ledger-types", 315 | "serde", 316 | ] 317 | 318 | [[package]] 319 | name = "icrc7" 320 | version = "0.1.0" 321 | dependencies = [ 322 | "candid", 323 | "ciborium", 324 | "ic-cdk", 325 | "ic-stable-structures", 326 | "icrc-ledger-types", 327 | "icrc-nft-types", 328 | "serde", 329 | ] 330 | 331 | [[package]] 332 | name = "lazy_static" 333 | version = "1.4.0" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 336 | 337 | [[package]] 338 | name = "leb128" 339 | version = "0.2.5" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" 342 | 343 | [[package]] 344 | name = "libc" 345 | version = "0.2.153" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 348 | 349 | [[package]] 350 | name = "num-bigint" 351 | version = "0.4.4" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" 354 | dependencies = [ 355 | "autocfg", 356 | "num-integer", 357 | "num-traits", 358 | "serde", 359 | ] 360 | 361 | [[package]] 362 | name = "num-integer" 363 | version = "0.1.46" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 366 | dependencies = [ 367 | "num-traits", 368 | ] 369 | 370 | [[package]] 371 | name = "num-traits" 372 | version = "0.2.18" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" 375 | dependencies = [ 376 | "autocfg", 377 | ] 378 | 379 | [[package]] 380 | name = "paste" 381 | version = "1.0.14" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 384 | 385 | [[package]] 386 | name = "pretty" 387 | version = "0.12.3" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" 390 | dependencies = [ 391 | "arrayvec", 392 | "typed-arena", 393 | "unicode-width", 394 | ] 395 | 396 | [[package]] 397 | name = "proc-macro2" 398 | version = "1.0.79" 399 | source = "registry+https://github.com/rust-lang/crates.io-index" 400 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 401 | dependencies = [ 402 | "unicode-ident", 403 | ] 404 | 405 | [[package]] 406 | name = "psm" 407 | version = "0.1.21" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" 410 | dependencies = [ 411 | "cc", 412 | ] 413 | 414 | [[package]] 415 | name = "quote" 416 | version = "1.0.35" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 419 | dependencies = [ 420 | "proc-macro2", 421 | ] 422 | 423 | [[package]] 424 | name = "rustversion" 425 | version = "1.0.15" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" 428 | 429 | [[package]] 430 | name = "serde" 431 | version = "1.0.197" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" 434 | dependencies = [ 435 | "serde_derive", 436 | ] 437 | 438 | [[package]] 439 | name = "serde_bytes" 440 | version = "0.11.14" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" 443 | dependencies = [ 444 | "serde", 445 | ] 446 | 447 | [[package]] 448 | name = "serde_derive" 449 | version = "1.0.197" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" 452 | dependencies = [ 453 | "proc-macro2", 454 | "quote", 455 | "syn 2.0.58", 456 | ] 457 | 458 | [[package]] 459 | name = "serde_tokenstream" 460 | version = "0.1.7" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "797ba1d80299b264f3aac68ab5d12e5825a561749db4df7cd7c8083900c5d4e9" 463 | dependencies = [ 464 | "proc-macro2", 465 | "serde", 466 | "syn 1.0.109", 467 | ] 468 | 469 | [[package]] 470 | name = "sha2" 471 | version = "0.10.8" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 474 | dependencies = [ 475 | "cfg-if", 476 | "cpufeatures", 477 | "digest", 478 | ] 479 | 480 | [[package]] 481 | name = "stacker" 482 | version = "0.1.15" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" 485 | dependencies = [ 486 | "cc", 487 | "cfg-if", 488 | "libc", 489 | "psm", 490 | "winapi", 491 | ] 492 | 493 | [[package]] 494 | name = "syn" 495 | version = "1.0.109" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 498 | dependencies = [ 499 | "proc-macro2", 500 | "quote", 501 | "unicode-ident", 502 | ] 503 | 504 | [[package]] 505 | name = "syn" 506 | version = "2.0.58" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" 509 | dependencies = [ 510 | "proc-macro2", 511 | "quote", 512 | "unicode-ident", 513 | ] 514 | 515 | [[package]] 516 | name = "thiserror" 517 | version = "1.0.58" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" 520 | dependencies = [ 521 | "thiserror-impl", 522 | ] 523 | 524 | [[package]] 525 | name = "thiserror-impl" 526 | version = "1.0.58" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" 529 | dependencies = [ 530 | "proc-macro2", 531 | "quote", 532 | "syn 2.0.58", 533 | ] 534 | 535 | [[package]] 536 | name = "typed-arena" 537 | version = "2.0.2" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" 540 | 541 | [[package]] 542 | name = "typenum" 543 | version = "1.17.0" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 546 | 547 | [[package]] 548 | name = "unicode-ident" 549 | version = "1.0.12" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 552 | 553 | [[package]] 554 | name = "unicode-width" 555 | version = "0.1.11" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" 558 | 559 | [[package]] 560 | name = "version_check" 561 | version = "0.9.4" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 564 | 565 | [[package]] 566 | name = "winapi" 567 | version = "0.3.9" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 570 | dependencies = [ 571 | "winapi-i686-pc-windows-gnu", 572 | "winapi-x86_64-pc-windows-gnu", 573 | ] 574 | 575 | [[package]] 576 | name = "winapi-i686-pc-windows-gnu" 577 | version = "0.4.0" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 580 | 581 | [[package]] 582 | name = "winapi-x86_64-pc-windows-gnu" 583 | version = "0.4.0" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 586 | --------------------------------------------------------------------------------