diff --git a/.env.example b/.env.example
index 86d57a2..e98f503 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,4 @@
-APP_VERSION=0.4.6
+APP_VERSION=0.4.7
NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
NEXT_PUBLIC_SG721_CODE_ID=793
diff --git a/components/collections/actions/Action.tsx b/components/collections/actions/Action.tsx
index 68b0750..98cb7c3 100644
--- a/components/collections/actions/Action.tsx
+++ b/components/collections/actions/Action.tsx
@@ -114,8 +114,8 @@ export const CollectionActions = ({
const priceState = useNumberInputState({
id: 'update-mint-price',
name: 'updateMintPrice',
- title: 'Update Mint Price',
- subtitle: 'New minting price in STARS',
+ title: type === 'update_discount_price' ? 'Discount Price' : 'Update Mint Price',
+ subtitle: type === 'update_discount_price' ? 'New discount price in STARS' : 'New minting price in STARS',
})
const descriptionState = useInputState({
@@ -170,7 +170,7 @@ export const CollectionActions = ({
'batch_mint_for',
])
const showAirdropFileField = type === 'airdrop'
- const showPriceField = type === 'update_mint_price'
+ const showPriceField = isEitherType(type, ['update_mint_price', 'update_discount_price'])
const showDescriptionField = type === 'update_collection_info'
const showImageField = type === 'update_collection_info'
const showExternalLinkField = type === 'update_collection_info'
@@ -357,8 +357,8 @@ export const CollectionActions = ({
{showLimitField && }
{showTokenIdField && }
{showTokenIdListField && }
- {showNumberOfTokensField && }
- {showPriceField && }
+ {showNumberOfTokensField && }
+ {showPriceField && }
{showDescriptionField && }
{showImageField && }
{showExternalLinkField && }
diff --git a/components/collections/actions/actions.ts b/components/collections/actions/actions.ts
index 98bff3f..021e83c 100644
--- a/components/collections/actions/actions.ts
+++ b/components/collections/actions/actions.ts
@@ -13,6 +13,8 @@ export const ACTION_TYPES = [
'mint_token_uri',
'purge',
'update_mint_price',
+ 'update_discount_price',
+ 'remove_discount_price',
'mint_to',
'mint_for',
'batch_mint',
@@ -87,16 +89,21 @@ export const VENDING_ACTION_LIST: ActionListItem[] = [
name: 'Mint',
description: `Mint a token`,
},
- {
- id: 'purge',
- name: 'Purge',
- description: `Purge`,
- },
{
id: 'update_mint_price',
name: 'Update Mint Price',
description: `Update mint price`,
},
+ {
+ id: 'update_discount_price',
+ name: 'Update Discount Price',
+ description: `Update discount price`,
+ },
+ {
+ id: 'remove_discount_price',
+ name: 'Remove Discount Price',
+ description: `Remove discount price`,
+ },
{
id: 'mint_to',
name: 'Mint To',
@@ -182,6 +189,11 @@ export const VENDING_ACTION_LIST: ActionListItem[] = [
name: 'Burn Remaining Tokens',
description: 'Burn remaining tokens',
},
+ {
+ id: 'purge',
+ name: 'Purge',
+ description: `Purge`,
+ },
]
export interface DispatchExecuteProps {
@@ -205,6 +217,8 @@ export type DispatchExecuteArgs = {
| { type: Select<'mint_token_uri'>; tokenUri: string }
| { type: Select<'purge'> }
| { type: Select<'update_mint_price'>; price: string }
+ | { type: Select<'update_discount_price'>; price: string }
+ | { type: Select<'remove_discount_price'> }
| { type: Select<'mint_to'>; recipient: string }
| { type: Select<'mint_for'>; recipient: string; tokenId: number }
| { type: Select<'batch_mint'>; recipient: string; batchNumber: number }
@@ -242,6 +256,12 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
case 'update_mint_price': {
return vendingMinterMessages.updateMintPrice(txSigner, args.price)
}
+ case 'update_discount_price': {
+ return vendingMinterMessages.updateDiscountPrice(txSigner, args.price)
+ }
+ case 'remove_discount_price': {
+ return vendingMinterMessages.removeDiscountPrice(txSigner)
+ }
case 'mint_to': {
return vendingMinterMessages.mintTo(txSigner, args.recipient)
}
@@ -320,6 +340,12 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
case 'update_mint_price': {
return vendingMinterMessages(minterContract)?.updateMintPrice(args.price)
}
+ case 'update_discount_price': {
+ return vendingMinterMessages(minterContract)?.updateDiscountPrice(args.price)
+ }
+ case 'remove_discount_price': {
+ return vendingMinterMessages(minterContract)?.removeDiscountPrice()
+ }
case 'mint_to': {
return vendingMinterMessages(minterContract)?.mintTo(args.recipient)
}
diff --git a/config/favicons.json b/config/favicons.json
index 4cea67d..b7943a0 100644
--- a/config/favicons.json
+++ b/config/favicons.json
@@ -2,7 +2,7 @@
"path": "/assets/",
"appName": "StargazeStudio",
"appShortName": "StargazeStudio",
- "appDescription": "Stargaze Studio is built to provide useful smart contract interfaces that helps you build and deploy your own NFT collection in no time.",
+ "appDescription": "Stargaze Studio is built to provide useful smart contract interfaces that help you build and deploy your own NFT collection in no time.",
"developerName": "StargazeStudio",
"developerURL": "https://",
"background": "#FFC27D",
diff --git a/contracts/vendingMinter/contract.ts b/contracts/vendingMinter/contract.ts
index f159f44..8483fa3 100644
--- a/contracts/vendingMinter/contract.ts
+++ b/contracts/vendingMinter/contract.ts
@@ -48,6 +48,8 @@ export interface VendingMinterInstance {
withdraw: (senderAddress: string) => Promise
airdrop: (senderAddress: string, recipients: string[]) => Promise
burnRemaining: (senderAddress: string) => Promise
+ updateDiscountPrice: (senderAddress: string, price: string) => Promise
+ removeDiscountPrice: (senderAddress: string) => Promise
}
export interface VendingMinterMessages {
@@ -66,6 +68,8 @@ export interface VendingMinterMessages {
withdraw: () => WithdrawMessage
airdrop: (recipients: string[]) => CustomMessage
burnRemaining: () => BurnRemainingMessage
+ updateDiscountPrice: (price: string) => UpdateDiscountPriceMessage
+ removeDiscountPrice: () => RemoveDiscountPriceMessage
}
export interface MintMessage {
@@ -97,6 +101,26 @@ export interface UpdateMintPriceMessage {
funds: Coin[]
}
+export interface UpdateDiscountPriceMessage {
+ sender: string
+ contract: string
+ msg: {
+ update_discount_price: {
+ price: string
+ }
+ }
+ funds: Coin[]
+}
+
+export interface RemoveDiscountPriceMessage {
+ sender: string
+ contract: string
+ msg: {
+ remove_discount_price: Record
+ }
+ funds: Coin[]
+}
+
export interface SetWhitelistMessage {
sender: string
contract: string
@@ -326,6 +350,36 @@ export const vendingMinter = (client: SigningCosmWasmClient, txSigner: string):
return res.transactionHash
}
+ const updateDiscountPrice = async (senderAddress: string, price: string): Promise => {
+ const res = await client.execute(
+ senderAddress,
+ contractAddress,
+ {
+ update_discount_price: {
+ price: (Number(price) * 1000000).toString(),
+ },
+ },
+ 'auto',
+ '',
+ )
+
+ return res.transactionHash
+ }
+
+ const removeDiscountPrice = async (senderAddress: string): Promise => {
+ const res = await client.execute(
+ senderAddress,
+ contractAddress,
+ {
+ remove_discount_price: {},
+ },
+ 'auto',
+ '',
+ )
+
+ return res.transactionHash
+ }
+
const setWhitelist = async (senderAddress: string, whitelist: string): Promise => {
const res = await client.execute(
senderAddress,
@@ -552,6 +606,8 @@ export const vendingMinter = (client: SigningCosmWasmClient, txSigner: string):
mint,
purge,
updateMintPrice,
+ updateDiscountPrice,
+ removeDiscountPrice,
setWhitelist,
updateStartTime,
updateStartTradingTime,
@@ -633,6 +689,30 @@ export const vendingMinter = (client: SigningCosmWasmClient, txSigner: string):
}
}
+ const updateDiscountPrice = (price: string): UpdateDiscountPriceMessage => {
+ return {
+ sender: txSigner,
+ contract: contractAddress,
+ msg: {
+ update_discount_price: {
+ price: (Number(price) * 1000000).toString(),
+ },
+ },
+ funds: [],
+ }
+ }
+
+ const removeDiscountPrice = (): RemoveDiscountPriceMessage => {
+ return {
+ sender: txSigner,
+ contract: contractAddress,
+ msg: {
+ remove_discount_price: {},
+ },
+ funds: [],
+ }
+ }
+
const setWhitelist = (whitelist: string): SetWhitelistMessage => {
return {
sender: txSigner,
@@ -795,6 +875,8 @@ export const vendingMinter = (client: SigningCosmWasmClient, txSigner: string):
mint,
purge,
updateMintPrice,
+ updateDiscountPrice,
+ removeDiscountPrice,
setWhitelist,
updateStartTime,
updateStartTradingTime,
diff --git a/contracts/vendingMinter/messages/execute.ts b/contracts/vendingMinter/messages/execute.ts
index 391178f..d75f4e6 100644
--- a/contracts/vendingMinter/messages/execute.ts
+++ b/contracts/vendingMinter/messages/execute.ts
@@ -7,6 +7,8 @@ export const EXECUTE_TYPES = [
'mint',
'purge',
'update_mint_price',
+ 'update_discount_price',
+ 'remove_discount_price',
'set_whitelist',
'update_start_time',
'update_start_trading_time',
@@ -39,6 +41,16 @@ export const EXECUTE_LIST: ExecuteListItem[] = [
name: 'Update Mint Price',
description: `Update mint price`,
},
+ {
+ id: 'update_discount_price',
+ name: 'Update Discount Price',
+ description: `Update discount price`,
+ },
+ {
+ id: 'remove_discount_price',
+ name: 'Remove Discount Price',
+ description: `Remove discount price`,
+ },
{
id: 'set_whitelist',
name: 'Set Whitelist',
@@ -98,6 +110,8 @@ export type DispatchExecuteArgs = {
| { type: Select<'mint'> }
| { type: Select<'purge'> }
| { type: Select<'update_mint_price'>; price: string }
+ | { type: Select<'update_discount_price'>; price: string }
+ | { type: Select<'remove_discount_price'> }
| { type: Select<'set_whitelist'>; whitelist: string }
| { type: Select<'update_start_time'>; startTime: string }
| { type: Select<'update_start_trading_time'>; startTime?: string }
@@ -123,6 +137,12 @@ export const dispatchExecute = async (args: DispatchExecuteArgs) => {
case 'update_mint_price': {
return messages.updateMintPrice(txSigner, args.price)
}
+ case 'update_discount_price': {
+ return messages.updateDiscountPrice(txSigner, args.price)
+ }
+ case 'remove_discount_price': {
+ return messages.removeDiscountPrice(txSigner)
+ }
case 'set_whitelist': {
return messages.setWhitelist(txSigner, args.whitelist)
}
@@ -167,6 +187,12 @@ export const previewExecutePayload = (args: DispatchExecuteArgs) => {
case 'update_mint_price': {
return messages(contract)?.updateMintPrice(args.price)
}
+ case 'update_discount_price': {
+ return messages(contract)?.updateDiscountPrice(args.price)
+ }
+ case 'remove_discount_price': {
+ return messages(contract)?.removeDiscountPrice()
+ }
case 'set_whitelist': {
return messages(contract)?.setWhitelist(args.whitelist)
}
diff --git a/package.json b/package.json
index 74fead5..213d0ac 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "stargaze-studio",
- "version": "0.4.6",
+ "version": "0.4.7",
"workspaces": [
"packages/*"
],
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 1116be5..25dd566 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -748,12 +748,17 @@ const CollectionCreationPage: NextPage = () => {
mintingDetails.perAddressLimit > mintingDetails.numTokens
)
throw new Error('Invalid limit for tokens per address')
+ if (mintingDetails.numTokens < 100 && mintingDetails.perAddressLimit > 3)
+ throw new Error(
+ 'Invalid limit for tokens per address. Tokens per address limit cannot exceed 3 for collections with less than 100 tokens in total.',
+ )
if (
- mintingDetails.numTokens > 100 &&
- mintingDetails.numTokens < 100 * mintingDetails.perAddressLimit &&
- mintingDetails.perAddressLimit > mintingDetails.numTokens / 100
+ mintingDetails.numTokens >= 100 &&
+ mintingDetails.perAddressLimit > Math.ceil((mintingDetails.numTokens / 100) * 3)
)
- throw new Error('Invalid limit for tokens per address. The limit cannot exceed 1% of the total number of tokens.')
+ throw new Error(
+ 'Invalid limit for tokens per address. Tokens per address limit cannot exceed 3% of the total number of tokens in the collection.',
+ )
if (mintingDetails.startTime === '') throw new Error('Start time is required')
if (Number(mintingDetails.startTime) < new Date().getTime() * 1000000) throw new Error('Invalid start time')
}
diff --git a/pages/contracts/vendingMinter/execute.tsx b/pages/contracts/vendingMinter/execute.tsx
index de73e62..17787e2 100644
--- a/pages/contracts/vendingMinter/execute.tsx
+++ b/pages/contracts/vendingMinter/execute.tsx
@@ -55,8 +55,8 @@ const VendingMinterExecutePage: NextPage = () => {
const priceState = useNumberInputState({
id: 'price',
name: 'price',
- title: 'Price',
- subtitle: 'Enter the token price',
+ title: type === 'update_discount_price' ? 'Discount Price' : 'Price',
+ subtitle: type === 'update_discount_price' ? 'New discount price in STARS' : 'Enter the token price',
})
const contractState = useInputState({
@@ -86,7 +86,7 @@ const VendingMinterExecutePage: NextPage = () => {
const showLimitField = type === 'update_per_address_limit'
const showTokenIdField = type === 'mint_for'
const showRecipientField = isEitherType(type, ['mint_to', 'mint_for'])
- const showPriceField = type === 'update_mint_price'
+ const showPriceField = isEitherType(type, ['update_mint_price', 'update_discount_price'])
const messages = useMemo(() => contract?.use(contractState.value), [contract, wallet.address, contractState.value])
const payload: DispatchExecuteArgs = {
diff --git a/pages/index.tsx b/pages/index.tsx
index d208893..22c0ac6 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -15,8 +15,8 @@ const HomePage: NextPage = () => {
Looking for a fast and efficient way to build an NFT collection? Stargaze Studio is the solution.
- Stargaze Studio is built to provide useful smart contract interfaces that helps you build and deploy your own
- NFT collections in no time.
+ Stargaze Studio is built to provide useful smart contract interfaces that help you build and deploy your own NFT
+ collections in no time.