1- use std:: time:: Duration ;
1+ use std:: { default , fmt :: Display , time:: Duration } ;
22
33use cosmwasm_schema:: cw_serde;
44use cosmwasm_std:: {
5- Addr , BankMsg , Binary , Coin , CosmosMsg , CustomMsg , Deps , DepsMut , Empty , Env , MessageInfo ,
6- Response , StdResult , SubMsg ,
5+ coin, Addr , BankMsg , Binary , Coin , CosmosMsg , CustomMsg , Deps , DepsMut , Empty , Env , MessageInfo , Response , StdResult , SubMsg , Timestamp
76} ;
87use cw721:: {
98 Expiration ,
@@ -18,6 +17,7 @@ use cw721::{
1817use crate :: {
1918 error:: ContractError ,
2019 msg:: AssetExtensionExecuteMsg ,
20+ plugin,
2121 state:: { AssetConfig , Reserve } ,
2222 traits:: { AssetContract , DefaultAssetContract } ,
2323} ;
@@ -129,6 +129,34 @@ pub enum Plugin {
129129 } ,
130130}
131131
132+ impl Display for Plugin {
133+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
134+ match self {
135+ Plugin :: ExactPrice { amount } => write ! ( f, "ExactPrice: {}" , amount) ,
136+ Plugin :: MinimumPrice { amount } => write ! ( f, "MinimumPrice: {}" , amount) ,
137+ Plugin :: RequiresProof { proof } => write ! ( f, "RequiresProof: {:?}" , proof) ,
138+ Plugin :: NotBefore { time } => write ! ( f, "NotBefore: {}" , time) ,
139+ Plugin :: NotAfter { time } => write ! ( f, "NotAfter: {}" , time) ,
140+ Plugin :: TimeLock { time } => write ! ( f, "TimeLock: {:?}" , time) ,
141+ Plugin :: Royalty {
142+ bps,
143+ recipient,
144+ on_primary,
145+ } => write ! (
146+ f,
147+ "Royalty: {} bps to {} on_primary: {}" ,
148+ bps, recipient, on_primary
149+ ) ,
150+ Plugin :: AllowedMarketplaces { marketplaces } => {
151+ write ! ( f, "AllowedMarketplaces: {:?}" , marketplaces)
152+ }
153+ Plugin :: AllowedCurrencies { denoms } => {
154+ write ! ( f, "AllowedCurrencies: {:?}" , denoms)
155+ }
156+ }
157+ }
158+ }
159+
132160impl Plugin {
133161 // TODO
134162 // break this out into functions for each plugin type
@@ -181,7 +209,10 @@ impl Plugin {
181209 Ok ( true )
182210 }
183211
184- pub fn run_raw_transfer_plugin < T , U : CustomMsg > ( & self , ctx : & mut PluginCtx < T , U > ) -> StdResult < bool > {
212+ pub fn run_raw_transfer_plugin < T , U : CustomMsg > (
213+ & self ,
214+ ctx : & mut PluginCtx < T , U > ,
215+ ) -> StdResult < bool > {
185216 match self {
186217 Plugin :: Royalty {
187218 bps,
@@ -197,6 +228,20 @@ impl Plugin {
197228 }
198229 Ok ( true )
199230 }
231+
232+ pub fn get_plugin_name ( & self ) -> & str {
233+ match self {
234+ Plugin :: ExactPrice { .. } => "ExactPrice" ,
235+ Plugin :: MinimumPrice { .. } => "MinimumPrice" ,
236+ Plugin :: RequiresProof { .. } => "RequiresProof" ,
237+ Plugin :: NotBefore { .. } => "NotBefore" ,
238+ Plugin :: NotAfter { .. } => "NotAfter" ,
239+ Plugin :: TimeLock { .. } => "TimeLock" ,
240+ Plugin :: Royalty { .. } => "Royalty" ,
241+ Plugin :: AllowedMarketplaces { .. } => "AllowedMarketplaces" ,
242+ Plugin :: AllowedCurrencies { .. } => "AllowedCurrencies" ,
243+ }
244+ }
200245}
201246
202247/// The concept of a plugin is to be able to hook into the execution flow when a certain action
@@ -346,6 +391,22 @@ pub trait PluggableAsset<
346391 env : & Env ,
347392 info : & MessageInfo ,
348393 ) -> PluginCtx < ' a , Context , TCustomResponseMsg > ;
394+
395+ fn save_plugin (
396+ & self ,
397+ deps : DepsMut ,
398+ env : & Env ,
399+ info : & MessageInfo ,
400+ plugins : & Vec < Plugin > ,
401+ ) -> StdResult < ( ) > ;
402+
403+ fn remove_plugin (
404+ & self ,
405+ deps : DepsMut ,
406+ env : & Env ,
407+ info : & MessageInfo ,
408+ plugins : & Vec < String > ,
409+ ) -> StdResult < ( ) > ;
349410}
350411
351412impl < TNftExtension , TNftExtensionMsg , TCollectionExtension , TCollectionExtensionMsg >
@@ -392,6 +453,7 @@ where
392453 token_id,
393454 recipient,
394455 } => self . on_buy_plugin ( token_id, recipient, ctx) ,
456+ _ => Ok ( true ) ,
395457 }
396458 }
397459
@@ -406,16 +468,16 @@ where
406468 let config = AssetConfig :: < TNftExtension > :: default ( ) ;
407469 let min_price_plugin = config
408470 . collection_plugins
409- . may_load ( ctx. deps . storage , " MinimumPrice" ) ?;
471+ . may_load ( ctx. deps . storage , Plugin :: MinimumPrice { amount : coin ( 0 , "" ) } . get_plugin_name ( ) ) ?;
410472 let not_before_plugin = config
411473 . collection_plugins
412- . may_load ( ctx. deps . storage , " NotBefore" ) ?;
474+ . may_load ( ctx. deps . storage , Plugin :: NotBefore { time : Expiration :: Never { } } . get_plugin_name ( ) ) ?;
413475 let not_after_plugin = config
414476 . collection_plugins
415- . may_load ( ctx. deps . storage , " NotAfter" ) ?;
477+ . may_load ( ctx. deps . storage , Plugin :: NotAfter { time : Expiration :: Never { } } . get_plugin_name ( ) ) ?;
416478 let allowed_currencies_plugin = config
417479 . collection_plugins
418- . may_load ( ctx. deps . storage , " AllowedCurrencies" ) ?;
480+ . may_load ( ctx. deps . storage , Plugin :: AllowedCurrencies { denoms : [ ] . into ( ) } . get_plugin_name ( ) ) ?;
419481 ctx. data . token_id = token_id. to_string ( ) ;
420482 ctx. data . ask_price = Some ( price. clone ( ) ) ;
421483 ctx. data . reservation = reservation. clone ( ) ;
@@ -449,10 +511,10 @@ where
449511 let config = AssetConfig :: < TNftExtension > :: default ( ) ;
450512 let allowed_marketplaces_plugin = config
451513 . collection_plugins
452- . may_load ( ctx. deps . storage , " AllowedMarketplaces" ) ?;
514+ . may_load ( ctx. deps . storage , Plugin :: AllowedMarketplaces { marketplaces : [ ] . into ( ) } . get_plugin_name ( ) ) ?;
453515 let allowed_currencies_plugin = config
454516 . collection_plugins
455- . may_load ( ctx. deps . storage , " AllowedCurrencies" ) ?;
517+ . may_load ( ctx. deps . storage , Plugin :: AllowedCurrencies { denoms : [ ] . into ( ) } . get_plugin_name ( ) ) ?;
456518 let royalty_plugin = config
457519 . collection_plugins
458520 . may_load ( ctx. deps . storage , "Royalty" ) ?;
@@ -496,10 +558,10 @@ where
496558 ctx. data . token_id = token_id. to_string ( ) ;
497559 let allowed_marketplaces_plugin = config
498560 . collection_plugins
499- . may_load ( ctx. deps . storage , " AllowedMarketplaces" ) ?;
561+ . may_load ( ctx. deps . storage , Plugin :: AllowedMarketplaces { marketplaces : [ ] . into ( ) } . get_plugin_name ( ) ) ?;
500562 let time_lock_plugin = config
501563 . collection_plugins
502- . may_load ( ctx. deps . storage , " TimeLock" ) ?;
564+ . may_load ( ctx. deps . storage , Plugin :: TimeLock { time : Duration :: from_secs ( 0 ) } . get_plugin_name ( ) ) ?;
503565 if let Some ( plugin) = allowed_marketplaces_plugin {
504566 plugin. run_asset_plugin ( ctx) ?;
505567 }
@@ -523,6 +585,36 @@ where
523585 data : DefaultXionAssetContext :: default ( ) ,
524586 }
525587 }
588+
589+ fn save_plugin (
590+ & self ,
591+ deps : DepsMut ,
592+ _env : & Env ,
593+ _info : & MessageInfo ,
594+ plugins : & Vec < Plugin > ,
595+ ) -> StdResult < ( ) > {
596+ for plugin in plugins {
597+ self . config
598+ . collection_plugins
599+ . save ( deps. storage , plugin. get_plugin_name ( ) , plugin) ?;
600+ }
601+ Ok ( ( ) )
602+ }
603+
604+ fn remove_plugin (
605+ & self ,
606+ deps : DepsMut ,
607+ _env : & Env ,
608+ _info : & MessageInfo ,
609+ plugins : & Vec < String > ,
610+ ) -> StdResult < ( ) > {
611+ for plugin in plugins {
612+ self . config
613+ . collection_plugins
614+ . remove ( deps. storage , plugin) ;
615+ }
616+ Ok ( ( ) )
617+ }
526618}
527619
528620/// These are default plugins that can be used out of the box.
@@ -771,7 +863,9 @@ pub mod default_plugins {
771863 }
772864 /// This plugin checks that raw transfers are enabled. If royalty info is set,
773865 /// transfers are disabled and all transfers must go through the buy flow.
774- pub fn is_transfer_enabled_plugin < T , U : CustomMsg > ( ctx : & mut PluginCtx < T , U > ) -> StdResult < bool > {
866+ pub fn is_transfer_enabled_plugin < T , U : CustomMsg > (
867+ ctx : & mut PluginCtx < T , U > ,
868+ ) -> StdResult < bool > {
775869 if ctx. royalty . collection_royalty_bps . is_some ( )
776870 && ctx. royalty . collection_royalty_recipient . is_some ( )
777871 {
0 commit comments