From c27d7558ef427e97e19fa8e4faaedbe9c58d074c Mon Sep 17 00:00:00 2001 From: theghostmac Date: Tue, 27 Feb 2024 07:47:51 +0100 Subject: [PATCH 1/4] feat(cw721): Extend Cw721Contract with more token management functions - Implement advanced token management features in Cw721Contract, including token approval, revocation, and query functionalities. - Enhance token indexing and storage mechanisms to support efficient approval handling and token owner management. Author: MacBobby Chibuzor --- contracts/cw721-base/src/state.rs | 47 ++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/contracts/cw721-base/src/state.rs b/contracts/cw721-base/src/state.rs index 48bca6bf5..1f9a09db1 100644 --- a/contracts/cw721-base/src/state.rs +++ b/contracts/cw721-base/src/state.rs @@ -2,8 +2,9 @@ use schemars::JsonSchema; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::marker::PhantomData; +use std::ops::Add; -use cosmwasm_std::{Addr, BlockInfo, CustomMsg, StdResult, Storage}; +use cosmwasm_std::{Addr, BlockInfo, CustomMsg, StdError, StdResult, Storage}; use cw721::{ContractInfoResponse, Cw721, Expiration}; use cw_storage_plus::{Index, IndexList, IndexedMap, Item, Map, MultiIndex}; @@ -98,6 +99,50 @@ where self.token_count.save(storage, &val)?; Ok(val) } + + // Adds an approval for a token, ensuring not to duplicate or exceed a max number of approvals. + pub fn add_approval(&self, storage: &mut dyn Storage, token_id: &'a str, approval: Approval) -> StdResult<()> { + self.tokens.update(storage, token_id, |token_info_option| match token_info_option { + Some(mut token_info) => { + // Ensure the approval does not already exist + if !token_info.approvals.iter().any(|a| a.spender == approval.spender) { + token_info.approvals.push(approval); + } + Ok(token_info) + }, + None => Err(StdError::not_found("TokenInfo")), + })?; + Ok(()) + } + + + // Revokes an approval for a token. + pub fn revoke_approval(&self, storage: &mut dyn Storage, token_id: &'a str, spender: &Addr) -> StdResult<()> { + self.tokens.update(storage, token_id, |token_info_option| match token_info_option { + Some(mut token_info) => { + token_info.approvals.retain(|a| &a.spender != spender); + Ok(token_info) + }, + None => Err(StdError::not_found("TokenInfo")), + })?; + Ok(()) + } + + // Queries all current approvals for a token, excluding expired ones. +pub fn query_approvals(&self, storage: &dyn Storage, token_id: &'a str, block_info: &BlockInfo) -> StdResult> { + // Attempt to load the token info. If it does not exist, return an empty vector. + match self.tokens.load(storage, token_id) { + Ok(token_info) => { + // Filter out expired approvals + let current_approvals = token_info.approvals.into_iter().filter(|a| !a.is_expired(block_info)).collect(); + Ok(current_approvals) + }, + Err(_) => { + // If there's no token info, return an empty list of approvals + Ok(vec![]) + }, + } +} } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] From 24954009c34ee369288a9cba8dd168bacd00edee Mon Sep 17 00:00:00 2001 From: theghostmac Date: Tue, 27 Feb 2024 07:51:45 +0100 Subject: [PATCH 2/4] feat(cw721): Extend Cw721Contract with more token management functions - Implement advanced token management features in Cw721Contract, including token approval, revocation, and query functionalities. - Enhance token indexing and storage mechanisms to support efficient approval handling and token owner management. Author: MacBobby Chibuzor --- contracts/cw721-base/src/state.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/cw721-base/src/state.rs b/contracts/cw721-base/src/state.rs index 1f9a09db1..75d836eff 100644 --- a/contracts/cw721-base/src/state.rs +++ b/contracts/cw721-base/src/state.rs @@ -2,7 +2,6 @@ use schemars::JsonSchema; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::marker::PhantomData; -use std::ops::Add; use cosmwasm_std::{Addr, BlockInfo, CustomMsg, StdError, StdResult, Storage}; From 343b13706efe1722f4001f0736f03091b28f617b Mon Sep 17 00:00:00 2001 From: theghostmac Date: Tue, 27 Feb 2024 08:00:34 +0100 Subject: [PATCH 3/4] [style] apply cargo fmt for consistent code formatting --- contracts/cw721-base/src/state.rs | 92 ++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/contracts/cw721-base/src/state.rs b/contracts/cw721-base/src/state.rs index 75d836eff..6c6ceb0bb 100644 --- a/contracts/cw721-base/src/state.rs +++ b/contracts/cw721-base/src/state.rs @@ -100,49 +100,79 @@ where } // Adds an approval for a token, ensuring not to duplicate or exceed a max number of approvals. - pub fn add_approval(&self, storage: &mut dyn Storage, token_id: &'a str, approval: Approval) -> StdResult<()> { - self.tokens.update(storage, token_id, |token_info_option| match token_info_option { - Some(mut token_info) => { - // Ensure the approval does not already exist - if !token_info.approvals.iter().any(|a| a.spender == approval.spender) { - token_info.approvals.push(approval); + pub fn add_approval( + &self, + storage: &mut dyn Storage, + token_id: &'a str, + approval: Approval, + ) -> StdResult<()> { + self.tokens.update( + storage, + token_id, + |token_info_option| match token_info_option { + Some(mut token_info) => { + // Ensure the approval does not already exist + if !token_info + .approvals + .iter() + .any(|a| a.spender == approval.spender) + { + token_info.approvals.push(approval); + } + Ok(token_info) } - Ok(token_info) + None => Err(StdError::not_found("TokenInfo")), }, - None => Err(StdError::not_found("TokenInfo")), - })?; + )?; Ok(()) } - // Revokes an approval for a token. - pub fn revoke_approval(&self, storage: &mut dyn Storage, token_id: &'a str, spender: &Addr) -> StdResult<()> { - self.tokens.update(storage, token_id, |token_info_option| match token_info_option { - Some(mut token_info) => { - token_info.approvals.retain(|a| &a.spender != spender); - Ok(token_info) + pub fn revoke_approval( + &self, + storage: &mut dyn Storage, + token_id: &'a str, + spender: &Addr, + ) -> StdResult<()> { + self.tokens.update( + storage, + token_id, + |token_info_option| match token_info_option { + Some(mut token_info) => { + token_info.approvals.retain(|a| &a.spender != spender); + Ok(token_info) + } + None => Err(StdError::not_found("TokenInfo")), }, - None => Err(StdError::not_found("TokenInfo")), - })?; + )?; Ok(()) } - + // Queries all current approvals for a token, excluding expired ones. -pub fn query_approvals(&self, storage: &dyn Storage, token_id: &'a str, block_info: &BlockInfo) -> StdResult> { - // Attempt to load the token info. If it does not exist, return an empty vector. - match self.tokens.load(storage, token_id) { - Ok(token_info) => { - // Filter out expired approvals - let current_approvals = token_info.approvals.into_iter().filter(|a| !a.is_expired(block_info)).collect(); - Ok(current_approvals) - }, - Err(_) => { - // If there's no token info, return an empty list of approvals - Ok(vec![]) - }, + pub fn query_approvals( + &self, + storage: &dyn Storage, + token_id: &'a str, + block_info: &BlockInfo, + ) -> StdResult> { + // Attempt to load the token info. If it does not exist, return an empty vector. + match self.tokens.load(storage, token_id) { + Ok(token_info) => { + // Filter out expired approvals + let current_approvals = token_info + .approvals + .into_iter() + .filter(|a| !a.is_expired(block_info)) + .collect(); + Ok(current_approvals) + } + Err(_) => { + // If there's no token info, return an empty list of approvals + Ok(vec![]) + } + } } } -} #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct TokenInfo { From 09199cbff84decebded9fae37efa6accdb1127cd Mon Sep 17 00:00:00 2001 From: theghostmac Date: Tue, 27 Feb 2024 08:28:52 +0100 Subject: [PATCH 4/4] [style] apply cargo fmt for consistent code formatting --- contracts/cw721-base/src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/cw721-base/src/state.rs b/contracts/cw721-base/src/state.rs index 6c6ceb0bb..025b5b50e 100644 --- a/contracts/cw721-base/src/state.rs +++ b/contracts/cw721-base/src/state.rs @@ -139,7 +139,7 @@ where token_id, |token_info_option| match token_info_option { Some(mut token_info) => { - token_info.approvals.retain(|a| &a.spender != spender); + token_info.approvals.retain(|a| a.spender != spender); Ok(token_info) } None => Err(StdError::not_found("TokenInfo")),