diff --git a/contracts/minters/base-minter/src/contract.rs b/contracts/minters/base-minter/src/contract.rs index 7e4dac351..cd917a6c3 100644 --- a/contracts/minters/base-minter/src/contract.rs +++ b/contracts/minters/base-minter/src/contract.rs @@ -49,6 +49,11 @@ pub fn instantiate( // assume the mint price is the minimum mint price // 100% is fair burned mint_price: factory_params.params.min_mint_price, + uri_scheme: factory_params + .params + .uri_scheme + .unwrap_or("ipfs".to_owned()) + .to_string(), extension: Empty {}, }; @@ -116,6 +121,7 @@ pub fn execute_mint_sender( ) -> Result { let config = CONFIG.load(deps.storage)?; let collection_address = COLLECTION_ADDRESS.load(deps.storage)?; + let token_uri = token_uri.trim().to_owned(); // This is a 1:1 minter, minted at min_mint_price // Should mint and then list on the marketplace for secondary sales @@ -130,9 +136,10 @@ pub fn execute_mint_sender( )); }; - let parsed_token_uri = Url::parse(&token_uri)?; - if parsed_token_uri.scheme() != "ipfs" { - return Err(ContractError::InvalidTokenURI {}); + if Url::parse(&token_uri)?.scheme() != config.uri_scheme { + return Err(ContractError::InvalidTokenURI { + expected_scheme: config.uri_scheme, + }); } let mut res = Response::new(); diff --git a/contracts/minters/base-minter/src/error.rs b/contracts/minters/base-minter/src/error.rs index 885c5dec3..248935667 100644 --- a/contracts/minters/base-minter/src/error.rs +++ b/contracts/minters/base-minter/src/error.rs @@ -27,8 +27,8 @@ pub enum ContractError { #[error("InvalidMintPrice")] InvalidMintPrice {}, - #[error("InvalidTokenURI")] - InvalidTokenURI {}, + #[error("InvalidTokenURI (must be an {expected_scheme} URI)")] + InvalidTokenURI { expected_scheme: String }, #[error("Invalid reply ID")] InvalidReplyID {}, diff --git a/contracts/minters/open-edition-minter/src/contract.rs b/contracts/minters/open-edition-minter/src/contract.rs index 09b39193c..3ae509230 100644 --- a/contracts/minters/open-edition-minter/src/contract.rs +++ b/contracts/minters/open-edition-minter/src/contract.rs @@ -56,6 +56,11 @@ pub fn instantiate( // set default status so it can be queried without failing STATUS.save(deps.storage, &Status::default())?; + let uri_scheme = factory_params + .uri_scheme + .unwrap_or("ipfs".to_owned()) + .to_string(); + match msg.init_msg.nft_data.nft_data_type { // If off-chain metadata -> Sanitize base token uri NftMetadataType::OffChainMetadata => { @@ -65,10 +70,19 @@ pub fn instantiate( .token_uri .as_ref() .map(|uri| uri.trim().to_string()) - .map_or_else(|| Err(ContractError::InvalidBaseTokenURI {}), Ok)?; - - if Url::parse(&base_token_uri)?.scheme() != "ipfs" { - return Err(ContractError::InvalidBaseTokenURI {}); + .map_or_else( + || { + Err(ContractError::InvalidBaseTokenURI { + expected_scheme: uri_scheme.clone(), + }) + }, + Ok, + )?; + + if Url::parse(&base_token_uri)?.scheme() != uri_scheme { + return Err(ContractError::InvalidBaseTokenURI { + expected_scheme: uri_scheme, + }); } msg.init_msg.nft_data.token_uri = Some(base_token_uri); @@ -127,6 +141,7 @@ pub fn instantiate( nft_data: msg.init_msg.nft_data, }, mint_price: msg.init_msg.mint_price, + uri_scheme, }; CONFIG.save(deps.storage, &config)?; @@ -696,6 +711,7 @@ fn query_config(deps: Deps) -> StdResult { start_time: config.extension.start_time, mint_price: config.mint_price, factory: config.factory.to_string(), + uri_scheme: config.uri_scheme, }) } diff --git a/contracts/minters/open-edition-minter/src/error.rs b/contracts/minters/open-edition-minter/src/error.rs index b8b7233e7..25222a743 100644 --- a/contracts/minters/open-edition-minter/src/error.rs +++ b/contracts/minters/open-edition-minter/src/error.rs @@ -88,8 +88,8 @@ pub enum ContractError { #[error("Instantiate sg721 error")] InstantiateSg721Error {}, - #[error("Invalid base token URI (must be an IPFS URI)")] - InvalidBaseTokenURI {}, + #[error("Invalid base token URI (must be an {expected_scheme} URI)")] + InvalidBaseTokenURI { expected_scheme: String }, #[error("address not on whitelist: {addr}")] NotWhitelisted { addr: String }, diff --git a/contracts/minters/open-edition-minter/src/msg.rs b/contracts/minters/open-edition-minter/src/msg.rs index 5adc46f0e..fe8832639 100644 --- a/contracts/minters/open-edition-minter/src/msg.rs +++ b/contracts/minters/open-edition-minter/src/msg.rs @@ -52,6 +52,7 @@ pub struct ConfigResponse { pub start_time: Timestamp, pub mint_price: Coin, pub factory: String, + pub uri_scheme: String, } #[cw_serde] diff --git a/contracts/minters/vending-minter-wl-flex/src/contract.rs b/contracts/minters/vending-minter-wl-flex/src/contract.rs index e510c891e..ed7b2dd09 100644 --- a/contracts/minters/vending-minter-wl-flex/src/contract.rs +++ b/contracts/minters/vending-minter-wl-flex/src/contract.rs @@ -72,14 +72,20 @@ pub fn instantiate( // set default status so it can be queried without failing STATUS.save(deps.storage, &Status::default())?; + let uri_scheme = factory_params + .uri_scheme + .unwrap_or("ipfs".to_owned()) + .to_string(); + // sanitize base token uri - let mut base_token_uri = msg.init_msg.base_token_uri.trim().to_string(); - // Check that base_token_uri is a valid IPFS uri - let parsed_token_uri = Url::parse(&base_token_uri)?; - if parsed_token_uri.scheme() != "ipfs" { - return Err(ContractError::InvalidBaseTokenURI {}); + let url = Url::parse(&msg.init_msg.base_token_uri.trim().to_string())?; + if url.scheme() != uri_scheme { + return Err(ContractError::InvalidBaseTokenURI { + expected_scheme: uri_scheme, + }); } - base_token_uri = parsed_token_uri.to_string(); + + let base_token_uri = url.to_string(); let genesis_time = Timestamp::from_nanos(GENESIS_MINT_START_TIME); // If start time is before genesis time return error @@ -147,6 +153,7 @@ pub fn instantiate( discount_price: None, }, mint_price: msg.init_msg.mint_price, + uri_scheme, }; CONFIG.save(deps.storage, &config)?; diff --git a/contracts/minters/vending-minter-wl-flex/src/error.rs b/contracts/minters/vending-minter-wl-flex/src/error.rs index 5defd6e75..59d39e329 100644 --- a/contracts/minters/vending-minter-wl-flex/src/error.rs +++ b/contracts/minters/vending-minter-wl-flex/src/error.rs @@ -80,8 +80,8 @@ pub enum ContractError { #[error("Instantiate sg721 error")] InstantiateSg721Error {}, - #[error("Invalid base token URI (must be an IPFS URI)")] - InvalidBaseTokenURI {}, + #[error("Invalid base token URI (must be an {expected_scheme} URI)")] + InvalidBaseTokenURI { expected_scheme: String }, #[error("address not on whitelist: {addr}")] NotWhitelisted { addr: String }, diff --git a/contracts/minters/vending-minter/src/contract.rs b/contracts/minters/vending-minter/src/contract.rs index da484f29d..7cf8c4daa 100644 --- a/contracts/minters/vending-minter/src/contract.rs +++ b/contracts/minters/vending-minter/src/contract.rs @@ -87,14 +87,20 @@ pub fn instantiate( }); } + let uri_scheme = factory_params + .uri_scheme + .unwrap_or("ipfs".to_owned()) + .to_string(); + // sanitize base token uri - let mut base_token_uri = msg.init_msg.base_token_uri.trim().to_string(); - // Check that base_token_uri is a valid IPFS uri - let parsed_token_uri = Url::parse(&base_token_uri)?; - if parsed_token_uri.scheme() != "ipfs" { - return Err(ContractError::InvalidBaseTokenURI {}); + let url = Url::parse(&msg.init_msg.base_token_uri.trim().to_string())?; + if url.scheme() != uri_scheme { + return Err(ContractError::InvalidBaseTokenURI { + expected_scheme: uri_scheme, + }); } - base_token_uri = parsed_token_uri.to_string(); + + let base_token_uri = url.to_string(); let genesis_time = Timestamp::from_nanos(GENESIS_MINT_START_TIME); // If start time is before genesis time return error @@ -162,6 +168,7 @@ pub fn instantiate( discount_price: None, }, mint_price: msg.init_msg.mint_price, + uri_scheme, }; CONFIG.save(deps.storage, &config)?; diff --git a/contracts/minters/vending-minter/src/error.rs b/contracts/minters/vending-minter/src/error.rs index 5defd6e75..59d39e329 100644 --- a/contracts/minters/vending-minter/src/error.rs +++ b/contracts/minters/vending-minter/src/error.rs @@ -80,8 +80,8 @@ pub enum ContractError { #[error("Instantiate sg721 error")] InstantiateSg721Error {}, - #[error("Invalid base token URI (must be an IPFS URI)")] - InvalidBaseTokenURI {}, + #[error("Invalid base token URI (must be an {expected_scheme} URI)")] + InvalidBaseTokenURI { expected_scheme: String }, #[error("address not on whitelist: {addr}")] NotWhitelisted { addr: String }, diff --git a/e2e/src/helpers/helper.rs b/e2e/src/helpers/helper.rs index 299d06a14..eaa411c72 100644 --- a/e2e/src/helpers/helper.rs +++ b/e2e/src/helpers/helper.rs @@ -50,6 +50,7 @@ pub fn instantiate_factory( }, mint_fee_bps: 1000, // 10% max_trading_offset_secs: (60 * 60) * 24, + uri_scheme: None, extension: ParamsExtension { max_token_limit: MAX_TOKENS, max_per_address_limit: 50, diff --git a/e2e/src/helpers/open_edition_minter_helpers.rs b/e2e/src/helpers/open_edition_minter_helpers.rs index 566ea7d66..970815305 100644 --- a/e2e/src/helpers/open_edition_minter_helpers.rs +++ b/e2e/src/helpers/open_edition_minter_helpers.rs @@ -54,6 +54,7 @@ pub fn instantiate_factory( }, mint_fee_bps: 1000, // 10% max_trading_offset_secs: (60 * 60) * 24, + uri_scheme: None, extension: ParamsExtension { max_per_address_limit: 50, airdrop_mint_fee_bps: 0, diff --git a/packages/sg2/src/lib.rs b/packages/sg2/src/lib.rs index 5dfd77520..2827c6f64 100644 --- a/packages/sg2/src/lib.rs +++ b/packages/sg2/src/lib.rs @@ -18,5 +18,6 @@ pub struct MinterParams { pub min_mint_price: Coin, pub mint_fee_bps: u64, pub max_trading_offset_secs: u64, + pub uri_scheme: Option, pub extension: T, } diff --git a/packages/sg4/src/lib.rs b/packages/sg4/src/lib.rs index bae3139ab..13a10515d 100644 --- a/packages/sg4/src/lib.rs +++ b/packages/sg4/src/lib.rs @@ -7,6 +7,7 @@ pub struct MinterConfig { pub factory: Addr, pub collection_code_id: u64, pub mint_price: Coin, + pub uri_scheme: String, pub extension: T, } diff --git a/test-suite/src/common_setup/msg.rs b/test-suite/src/common_setup/msg.rs index 00f58c4c0..5031a5586 100644 --- a/test-suite/src/common_setup/msg.rs +++ b/test-suite/src/common_setup/msg.rs @@ -18,6 +18,7 @@ pub struct MinterSetupParams<'a> { pub factory_code_id: u64, pub sg721_code_id: u64, pub init_msg: Option, + pub uri_scheme: Option, } pub struct MinterCollectionResponse { pub minter: Option, @@ -73,6 +74,7 @@ pub struct OpenEditionMinterSetupParams<'a> { pub minter_code_id: u64, pub factory_code_id: u64, pub sg721_code_id: u64, + pub uri_scheme: Option, pub init_msg: Option, pub custom_params: Option, } @@ -92,4 +94,5 @@ pub struct OpenEditionMinterCustomParams<'a> { pub denom: Option<&'a str>, pub mint_fee_bps: Option, pub airdrop_mint_price_amount: Option, + pub uri_scheme: Option, } diff --git a/test-suite/src/common_setup/setup_minter/base_minter/mock_params.rs b/test-suite/src/common_setup/setup_minter/base_minter/mock_params.rs index 443b7a9a7..98a8ef761 100644 --- a/test-suite/src/common_setup/setup_minter/base_minter/mock_params.rs +++ b/test-suite/src/common_setup/setup_minter/base_minter/mock_params.rs @@ -17,6 +17,7 @@ pub fn mock_params() -> BaseMinterParams { mint_fee_bps: MINT_FEE_BPS, max_trading_offset_secs: 60 * 60 * 24 * 7, extension: None, + uri_scheme: Some("ipfs".to_owned()), } } diff --git a/test-suite/src/common_setup/setup_minter/base_minter/setup.rs b/test-suite/src/common_setup/setup_minter/base_minter/setup.rs index 8c121fe8f..55f423fc6 100644 --- a/test-suite/src/common_setup/setup_minter/base_minter/setup.rs +++ b/test-suite/src/common_setup/setup_minter/base_minter/setup.rs @@ -130,6 +130,7 @@ pub fn configure_base_minter( collection_params_vec: Vec, minter_instantiate_params_vec: Vec, code_ids: CodeIds, + uri_scheme: Option, ) -> Vec { let mut minter_collection_info: Vec = vec![]; for (index, collection_param) in collection_params_vec.iter().enumerate() { @@ -144,6 +145,7 @@ pub fn configure_base_minter( sg721_code_id: code_ids.sg721_code_id, start_time: minter_instantiate_params_vec[index].start_time, init_msg: minter_instantiate_params_vec[index].init_msg.clone(), + uri_scheme: uri_scheme.clone(), }; let minter_collection_res = setup_minter_contract(setup_params); minter_collection_info.push(minter_collection_res); diff --git a/test-suite/src/common_setup/setup_minter/open_edition_minter/minter_params.rs b/test-suite/src/common_setup/setup_minter/open_edition_minter/minter_params.rs index 187b5efda..9dfc8dd39 100644 --- a/test-suite/src/common_setup/setup_minter/open_edition_minter/minter_params.rs +++ b/test-suite/src/common_setup/setup_minter/open_edition_minter/minter_params.rs @@ -18,25 +18,25 @@ pub fn minter_params_open_edition( start_time: Option, end_time: Option, nft_data: Option, + uri_scheme: Option, custom_params: Option, ) -> OpenEditionMinterInstantiateParams { let start_time = start_time.unwrap_or(Timestamp::from_nanos(GENESIS_MINT_START_TIME + 100)); let end_time = end_time.unwrap_or(Timestamp::from_nanos(GENESIS_MINT_START_TIME + 10_000)); + let uri_scheme = uri_scheme.unwrap_or("ipfs".to_owned()); OpenEditionMinterInstantiateParams { start_time: Some(start_time), end_time: Some(end_time), per_address_limit: Some(init_msg.per_address_limit), - nft_data: Some( - nft_data.unwrap_or(NftData { - nft_data_type: NftMetadataType::OffChainMetadata, - extension: None, - token_uri: Some( - "ipfs://bafybeiavall5udkxkdtdm4djezoxrmfc6o5fn2ug3ymrlvibvwmwydgrkm/1.jpg" - .to_string(), - ), - }), - ), + nft_data: Some(nft_data.unwrap_or(NftData { + nft_data_type: NftMetadataType::OffChainMetadata, + extension: None, + token_uri: Some(format!( + "{}://bafybeiavall5udkxkdtdm4djezoxrmfc6o5fn2ug3ymrlvibvwmwydgrkm/1.jpg", + uri_scheme + )), + })), init_msg: Some(init_msg), params_extension: Some(params_extension), custom_params, @@ -53,6 +53,17 @@ pub fn default_nft_data() -> NftData { } } +pub fn nft_data_with_uri_scheme(uri_scheme: String) -> NftData { + NftData { + nft_data_type: NftMetadataType::OffChainMetadata, + extension: None, + token_uri: Some(format!( + "{}://bafybeiavall5udkxkdtdm4djezoxrmfc6o5fn2ug3ymrlvibvwmwydgrkm/1.jpg", + uri_scheme + )), + } +} + pub fn init_msg( nft_data: NftData, per_address_limit_minter: Option, diff --git a/test-suite/src/common_setup/setup_minter/open_edition_minter/mock_params.rs b/test-suite/src/common_setup/setup_minter/open_edition_minter/mock_params.rs index b473aca6b..0f68e2197 100644 --- a/test-suite/src/common_setup/setup_minter/open_edition_minter/mock_params.rs +++ b/test-suite/src/common_setup/setup_minter/open_edition_minter/mock_params.rs @@ -72,6 +72,7 @@ pub fn mock_params_proper() -> OpenEditionMinterParams { min_mint_price: coin(MIN_MINT_PRICE_OPEN_EDITION, NATIVE_DENOM), mint_fee_bps: MINT_FEE_FAIR_BURN, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme: Some("ipfs".to_owned()), extension: ParamsExtension { max_per_address_limit: 10, airdrop_mint_fee_bps: 100, @@ -86,6 +87,7 @@ pub fn mock_params_proper() -> OpenEditionMinterParams { // Pass custom params to change minter values pub fn mock_params_custom(custom_params: OpenEditionMinterCustomParams) -> OpenEditionMinterParams { let denom = custom_params.denom.unwrap_or(NATIVE_DENOM); + let uri_scheme = custom_params.uri_scheme.clone(); let mint_fee_bps = custom_params.mint_fee_bps.unwrap_or(MINT_FEE_FAIR_BURN); let airdrop_mint_price_amount = custom_params .airdrop_mint_price_amount @@ -98,6 +100,7 @@ pub fn mock_params_custom(custom_params: OpenEditionMinterCustomParams) -> OpenE min_mint_price: coin(MIN_MINT_PRICE_OPEN_EDITION, denom), mint_fee_bps, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme, extension: ParamsExtension { max_per_address_limit: 10, airdrop_mint_fee_bps: 100, @@ -122,6 +125,7 @@ pub fn mock_params_custom_min_mint_price( min_mint_price, mint_fee_bps: MINT_FEE_FAIR_BURN, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme: Some("ipfs".to_owned()), extension: ParamsExtension { max_per_address_limit: 10, airdrop_mint_fee_bps: 100, diff --git a/test-suite/src/common_setup/setup_minter/open_edition_minter/setup.rs b/test-suite/src/common_setup/setup_minter/open_edition_minter/setup.rs index d40ea30a6..9a1c25a94 100644 --- a/test-suite/src/common_setup/setup_minter/open_edition_minter/setup.rs +++ b/test-suite/src/common_setup/setup_minter/open_edition_minter/setup.rs @@ -60,6 +60,7 @@ pub fn setup_open_edition_minter_contract( let end_time = setup_params.end_time; let init_msg = setup_params.init_msg.clone(); let nft_data = setup_params.init_msg.unwrap().nft_data; + let uri_scheme = setup_params.uri_scheme; let custom_params = setup_params.custom_params; @@ -68,6 +69,7 @@ pub fn setup_open_edition_minter_contract( params = custom_params; }; params.code_id = minter_code_id; + params.uri_scheme = uri_scheme; let factory_addr = router.instantiate_contract( factory_code_id, @@ -181,6 +183,7 @@ pub fn configure_open_edition_minter( collection_params_vec: Vec, minter_instantiate_params_vec: Vec, code_ids: CodeIds, + uri_scheme: Option, ) -> Vec { let mut minter_collection_info: Vec = vec![]; for (index, collection_param) in collection_params_vec.iter().enumerate() { @@ -203,6 +206,7 @@ pub fn configure_open_edition_minter( init_msg: minter_instantiate_params_vec[index].init_msg.clone(), end_time: minter_instantiate_params_vec[index].end_time.to_owned(), custom_params: minter_instantiate_params_vec[index].custom_params.clone(), + uri_scheme: uri_scheme.clone(), }; let minter_collection_res = setup_open_edition_minter_contract(setup_params); minter_collection_info.push(minter_collection_res); diff --git a/test-suite/src/common_setup/setup_minter/vending_minter/mock_params.rs b/test-suite/src/common_setup/setup_minter/vending_minter/mock_params.rs index 3339e0248..676abca94 100644 --- a/test-suite/src/common_setup/setup_minter/vending_minter/mock_params.rs +++ b/test-suite/src/common_setup/setup_minter/vending_minter/mock_params.rs @@ -59,6 +59,7 @@ pub fn mock_params(mint_denom: Option) -> VendingMinterParams { ), mint_fee_bps: MINT_FEE_FAIR_BURN, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme: Some("ipfs".to_owned()), extension: ParamsExtension { max_token_limit: MAX_TOKEN_LIMIT, max_per_address_limit: MAX_PER_ADDRESS_LIMIT, diff --git a/test-suite/src/common_setup/setup_minter/vending_minter/setup.rs b/test-suite/src/common_setup/setup_minter/vending_minter/setup.rs index d9d16f3b8..af6573069 100644 --- a/test-suite/src/common_setup/setup_minter/vending_minter/setup.rs +++ b/test-suite/src/common_setup/setup_minter/vending_minter/setup.rs @@ -115,6 +115,7 @@ pub fn configure_minter( collection_params_vec: Vec, minter_instantiate_params_vec: Vec, code_ids: CodeIds, + uri_scheme: Option, ) -> Vec { let mut minter_collection_info: Vec = vec![]; for (index, collection_param) in collection_params_vec.iter().enumerate() { @@ -129,6 +130,7 @@ pub fn configure_minter( sg721_code_id: code_ids.sg721_code_id, start_time: minter_instantiate_params_vec[index].start_time, init_msg: minter_instantiate_params_vec[index].init_msg.clone(), + uri_scheme: uri_scheme.clone(), }; let minter_collection_res = setup_minter_contract(setup_params); minter_collection_info.push(minter_collection_res); diff --git a/test-suite/src/common_setup/templates.rs b/test-suite/src/common_setup/templates.rs index f5c23cf72..ef2e45876 100644 --- a/test-suite/src/common_setup/templates.rs +++ b/test-suite/src/common_setup/templates.rs @@ -40,6 +40,7 @@ pub fn vending_minter_template(num_tokens: u32) -> MinterTemplateResponse MinterTemplateRes vec![collection_params], vec![minter_params], code_ids, + None, ); MinterTemplateResponse { router: app, @@ -224,6 +231,7 @@ pub fn vending_minter_updatable_with_app( vec![collection_params], vec![minter_params], code_ids, + None, ); MinterTemplateResponse { router: app, @@ -247,6 +255,7 @@ pub fn vending_minter_with_updatable_and_start_time( vec![collection_params], vec![minter_params], code_ids, + None, ); MinterTemplateResponse { router: app, @@ -268,6 +277,7 @@ pub fn base_minter_with_sg721nt(num_tokens: u32) -> MinterTemplateResponse MinterTemplateResponse, +) -> Result, anyhow::Result> { + let mut app = custom_mock_app(); + let (creator, buyer) = setup_accounts(&mut app); + let collection_params = mock_collection_params_1(None); + let code_ids = open_edition_minter_code_ids(&mut app); + let minter_params = minter_params_open_edition( + params_extension, + init_msg, + None, + None, + None, + uri_scheme.clone(), + None, + ); + + let minter_collection_response = configure_open_edition_minter( + &mut app, + creator.clone(), + vec![collection_params], + vec![minter_params], + code_ids, + uri_scheme, ); Ok(MinterTemplateResponse { router: app, @@ -446,6 +510,7 @@ pub fn base_minter_with_sudo_update_params_template( vec![collection_params], vec![minter_params], code_ids.clone(), + None, ); MinterTemplateResponseCodeIds { router: app, @@ -470,6 +535,7 @@ pub fn vending_minter_template_with_code_ids_template( vec![collection_params], vec![minter_params], code_ids.clone(), + None, ); MinterTemplateResponseCodeIds { router: app, @@ -504,9 +570,10 @@ pub fn open_edition_minter_with_two_sg721_collections_burn_mint( None, None, None, + None, ); let minter_params_2 = - minter_params_open_edition(params_extension, init_msg, None, None, None, None); + minter_params_open_edition(params_extension, init_msg, None, None, None, None, None); let code_ids = open_edition_minter_code_ids(&mut router); let minter_collection_response = configure_open_edition_minter( &mut router, @@ -514,6 +581,7 @@ pub fn open_edition_minter_with_two_sg721_collections_burn_mint( vec![collection_params, collection_params_2], vec![minter_params, minter_params_2], code_ids, + None, ); Ok(MinterTemplateResponse { router, @@ -537,6 +605,7 @@ pub fn open_edition_minter_ibc_template( None, None, None, + None, Some(custom_minter_params), ); @@ -546,6 +615,7 @@ pub fn open_edition_minter_ibc_template( vec![collection_params], vec![minter_params], code_ids.clone(), + None, ); Ok(MinterTemplateResponseCodeIds { router: app, diff --git a/test-suite/src/open_edition_minter/tests.rs b/test-suite/src/open_edition_minter/tests.rs index 009f57211..e8cae780a 100644 --- a/test-suite/src/open_edition_minter/tests.rs +++ b/test-suite/src/open_edition_minter/tests.rs @@ -6,3 +6,4 @@ mod frozen_factory; mod ibc_asset_mint; mod update_mint_price; mod update_start_and_end_time; +mod uri_scheme; diff --git a/test-suite/src/open_edition_minter/tests/ibc_asset_mint.rs b/test-suite/src/open_edition_minter/tests/ibc_asset_mint.rs index 1d4e05f3f..8a65be444 100644 --- a/test-suite/src/open_edition_minter/tests/ibc_asset_mint.rs +++ b/test-suite/src/open_edition_minter/tests/ibc_asset_mint.rs @@ -45,6 +45,7 @@ fn check_custom_create_minter_denom() { min_mint_price: init_msg.mint_price.clone(), mint_fee_bps: MINT_FEE_FAIR_BURN, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme: Some("ipfs".to_owned()), extension: ParamsExtension { max_per_address_limit: 10, airdrop_mint_fee_bps: 100, @@ -121,6 +122,7 @@ fn one_hundred_percent_burned_ibc_minter() { min_mint_price: init_msg.mint_price.clone(), mint_fee_bps: 10000, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme: Some("ipfs".to_owned()), extension: ParamsExtension { max_per_address_limit: 10, airdrop_mint_fee_bps: 100, @@ -202,6 +204,7 @@ fn zero_mint_fee() { min_mint_price: init_msg.mint_price.clone(), mint_fee_bps: 0, max_trading_offset_secs: 60 * 60 * 24 * 7, + uri_scheme: Some("ipfs".to_owned()), extension: ParamsExtension { max_per_address_limit: 10, airdrop_mint_fee_bps: 100, diff --git a/test-suite/src/open_edition_minter/tests/uri_scheme.rs b/test-suite/src/open_edition_minter/tests/uri_scheme.rs new file mode 100644 index 000000000..2a1b7983b --- /dev/null +++ b/test-suite/src/open_edition_minter/tests/uri_scheme.rs @@ -0,0 +1,101 @@ +use cosmwasm_std::{Coin, Uint128}; +use open_edition_factory::state::ParamsExtension; +use sg_std::{GENESIS_MINT_START_TIME, NATIVE_DENOM}; + +use open_edition_minter::msg::ConfigResponse; +use open_edition_minter::msg::QueryMsg; + +use crate::common_setup::setup_accounts_and_block::setup_block_time; +use crate::common_setup::setup_minter::common::constants::DEV_ADDRESS; +use crate::common_setup::setup_minter::open_edition_minter::minter_params::{ + init_msg, nft_data_with_uri_scheme, +}; +use crate::common_setup::templates::open_edition_minter_custom_uri_scheme; + +const MINT_PRICE: u128 = 100_000_000; + +#[test] +fn check_expected_uri_scheme_in_minter_config() { + let params_extension = ParamsExtension { + max_per_address_limit: 10, + airdrop_mint_fee_bps: 100, + airdrop_mint_price: Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(MINT_PRICE), + }, + dev_fee_address: DEV_ADDRESS.to_string(), + }; + + let per_address_limit_minter = Some(2); + let exp_uri_scheme = "https".to_owned(); + + let init_msg = init_msg( + nft_data_with_uri_scheme(exp_uri_scheme.clone()), + per_address_limit_minter, + None, + None, + None, + ); + + let vt = open_edition_minter_custom_uri_scheme( + params_extension, + init_msg, + Some(exp_uri_scheme.clone()), + ) + .unwrap(); + + let (mut router, ..) = (vt.router, vt.accts.creator, vt.accts.buyer); + let minter_addr = vt.collection_response_vec[0].minter.clone().unwrap(); + + // Set to a valid mint time + setup_block_time(&mut router, GENESIS_MINT_START_TIME + 101, None); + + // Check the Config + let query_config_msg = QueryMsg::Config {}; + let res: ConfigResponse = router + .wrap() + .query_wasm_smart(minter_addr.clone(), &query_config_msg) + .unwrap(); + + assert_eq!(res.uri_scheme, exp_uri_scheme); +} + +#[test] +fn check_error_on_unexpected_token_uri_scheme() { + let params_extension = ParamsExtension { + max_per_address_limit: 10, + airdrop_mint_fee_bps: 100, + airdrop_mint_price: Coin { + denom: NATIVE_DENOM.to_string(), + amount: Uint128::new(MINT_PRICE), + }, + dev_fee_address: DEV_ADDRESS.to_string(), + }; + + let per_address_limit_minter = Some(2); + let exp_uri_scheme = "https".to_owned(); + let invalid_uri_scheme = "ipfs".to_owned(); + + let init_msg = init_msg( + nft_data_with_uri_scheme(invalid_uri_scheme), + per_address_limit_minter, + None, + None, + None, + ); + + let vt = open_edition_minter_custom_uri_scheme( + params_extension, + init_msg, + Some(exp_uri_scheme.clone()), + ) + .unwrap(); + + let (_router, _creator, _buyer) = (vt.router, vt.accts.creator, vt.accts.buyer); + + let error = vt.collection_response_vec[0].error.as_ref(); + let error_str = format!("{:?}", error); + + assert!(error.is_some()); + assert!(error_str.contains(&format!("must be an {} URI", exp_uri_scheme))); +} diff --git a/test-suite/src/vending_minter/tests/address_limit.rs b/test-suite/src/vending_minter/tests/address_limit.rs index 8472edf0b..57a945137 100644 --- a/test-suite/src/vending_minter/tests/address_limit.rs +++ b/test-suite/src/vending_minter/tests/address_limit.rs @@ -265,6 +265,7 @@ fn check_invalid_update_per_address_limit() { vec![collection_params], vec![minter_params], code_ids, + None, ); let err = minter_collection_response[0].error.as_ref(); assert!(err.is_none()); diff --git a/test-suite/src/vending_minter/tests/splits.rs b/test-suite/src/vending_minter/tests/splits.rs index 23326b97a..c234a3cf1 100644 --- a/test-suite/src/vending_minter/tests/splits.rs +++ b/test-suite/src/vending_minter/tests/splits.rs @@ -82,6 +82,7 @@ fn mint_and_split() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); setup_block_time(&mut app, GENESIS_MINT_START_TIME + 1, None); diff --git a/test-suite/src/vending_minter/tests/trading_time.rs b/test-suite/src/vending_minter/tests/trading_time.rs index 8d0436c3d..0e2f38662 100644 --- a/test-suite/src/vending_minter/tests/trading_time.rs +++ b/test-suite/src/vending_minter/tests/trading_time.rs @@ -106,6 +106,7 @@ fn test_invalid_start_time() { vec![collection_params.clone()], vec![minter_params], code_ids, + None, ); let err = minter_collection_response[0] @@ -133,6 +134,7 @@ fn test_invalid_start_time() { vec![collection_params.clone()], vec![minter_params], code_ids.clone(), + None, ); let err = minter_collection_response[0] @@ -159,6 +161,7 @@ fn test_invalid_start_time() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); assert_eq!(minter_addr.to_string(), "contract3"); @@ -215,6 +218,7 @@ fn invalid_trading_time_during_init() { vec![collection_params], vec![minter_params], code_ids, + None, ); let err = minter_collection_response[0].error.as_deref(); let expected_error = ContractError::InvalidStartTradingTime( diff --git a/test-suite/src/vending_minter/tests/trading_time_updatable.rs b/test-suite/src/vending_minter/tests/trading_time_updatable.rs index ac3680c31..13812536d 100644 --- a/test-suite/src/vending_minter/tests/trading_time_updatable.rs +++ b/test-suite/src/vending_minter/tests/trading_time_updatable.rs @@ -112,6 +112,7 @@ fn test_invalid_start_time() { vec![collection_params.clone()], vec![minter_params], code_ids, + None, ); let err = minter_collection_response[0] @@ -139,6 +140,7 @@ fn test_invalid_start_time() { vec![collection_params.clone()], vec![minter_params], code_ids.clone(), + None, ); let err = minter_collection_response[0] @@ -165,6 +167,7 @@ fn test_invalid_start_time() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); assert_eq!(minter_addr.to_string(), "contract3"); @@ -221,6 +224,7 @@ fn invalid_trading_time_during_init() { vec![collection_params], vec![minter_params], code_ids, + None, ); let err = minter_collection_response[0].error.as_deref(); let expected_error = ContractError::InvalidStartTradingTime( diff --git a/test-suite/src/vending_minter/tests/whitelist.rs b/test-suite/src/vending_minter/tests/whitelist.rs index d79d55ac5..6cac4c4a6 100644 --- a/test-suite/src/vending_minter/tests/whitelist.rs +++ b/test-suite/src/vending_minter/tests/whitelist.rs @@ -59,6 +59,7 @@ fn invalid_whitelist_instantiate() { vec![collection_params], vec![minter_params], code_ids, + None, ); let err = minter_collection_response[0].error.as_ref(); @@ -149,6 +150,7 @@ fn whitelist_mint_count_query() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); let collection_addr = minter_collection_response[0].collection.clone().unwrap(); @@ -358,6 +360,7 @@ fn whitelist_already_started() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); let whitelist_addr = setup_whitelist_contract(&mut router, &creator, None, None); @@ -393,6 +396,7 @@ fn whitelist_can_update_before_start() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); let whitelist_addr = setup_whitelist_contract(&mut router, &creator, None, None); @@ -433,6 +437,7 @@ fn whitelist_access_len_add_remove_expiration() { vec![collection_params], vec![minter_params], code_ids, + None, ); let minter_addr = minter_collection_response[0].minter.clone().unwrap(); let sg721_addr = minter_collection_response[0].collection.clone().unwrap(); diff --git a/test-suite/src/vending_minter/tests/zero_mint_price.rs b/test-suite/src/vending_minter/tests/zero_mint_price.rs index 824976503..bd498c6f2 100644 --- a/test-suite/src/vending_minter/tests/zero_mint_price.rs +++ b/test-suite/src/vending_minter/tests/zero_mint_price.rs @@ -52,6 +52,7 @@ fn zero_mint_price() { sg721_code_id: code_ids.sg721_code_id, start_time: minter_params.start_time, init_msg: minter_params.init_msg, + uri_scheme: None, }; let minter_code_id = setup_params.minter_code_id; @@ -142,6 +143,7 @@ fn zero_wl_mint_price() { sg721_code_id: code_ids.sg721_code_id, start_time: minter_params.start_time, init_msg: minter_params.init_msg, + uri_scheme: None, }; let minter_code_id = setup_params.minter_code_id; @@ -239,6 +241,7 @@ fn zero_wl_mint_errs_with_min_mint_factory() { sg721_code_id: code_ids.sg721_code_id, start_time: minter_params.start_time, init_msg: minter_params.init_msg, + uri_scheme: None, }; let minter_code_id = setup_params.minter_code_id;