diff --git a/packages/desktop/components/popup/Popup.svelte b/packages/desktop/components/popup/Popup.svelte
index ce1f4e0a3e..a2eaece25e 100644
--- a/packages/desktop/components/popup/Popup.svelte
+++ b/packages/desktop/components/popup/Popup.svelte
@@ -42,6 +42,8 @@
import ManageVotingPowerPopup from './popups/ManageVotingPowerPopup.svelte'
import MintNativeTokenConfirmationPopup from './popups/MintNativeTokenConfirmationPopup.svelte'
import MintNativeTokenFormPopup from './popups/MintNativeTokenFormPopup.svelte'
+ import MintNftCollectionConfirmationPopup from './popups/MintNftCollectionConfirmationPopup.svelte'
+ import MintNftCollectionFormPopup from './popups/MintNftCollectionFormPopup.svelte'
import MintNftConfirmationPopup from './popups/MintNftConfirmationPopup.svelte'
import MintNftFormPopup from './popups/MintNftFormPopup.svelte'
import NodeAuthRequiredPopup from './popups/NodeAuthRequiredPopup.svelte'
@@ -122,6 +124,8 @@
[PopupId.MintNativeTokenForm]: MintNativeTokenFormPopup,
[PopupId.MintNftConfirmation]: MintNftConfirmationPopup,
[PopupId.MintNftForm]: MintNftFormPopup,
+ [PopupId.MintNftCollectionForm]: MintNftCollectionFormPopup,
+ [PopupId.MintNftCollectionConfirmation]: MintNftCollectionConfirmationPopup,
[PopupId.NodeAuthRequired]: NodeAuthRequiredPopup,
[PopupId.NodeInfo]: NodeInfoPopup,
[PopupId.ReceiveAddress]: ReceiveAddressPopup,
diff --git a/packages/desktop/components/popup/popups/MintNftCollectionConfirmationPopup.svelte b/packages/desktop/components/popup/popups/MintNftCollectionConfirmationPopup.svelte
new file mode 100644
index 0000000000..85179cca6e
--- /dev/null
+++ b/packages/desktop/components/popup/popups/MintNftCollectionConfirmationPopup.svelte
@@ -0,0 +1,149 @@
+
+
+
+
+
diff --git a/packages/desktop/components/popup/popups/MintNftCollectionFormPopup.svelte b/packages/desktop/components/popup/popups/MintNftCollectionFormPopup.svelte
new file mode 100644
index 0000000000..7a073721ee
--- /dev/null
+++ b/packages/desktop/components/popup/popups/MintNftCollectionFormPopup.svelte
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+ {#each Object.keys(optionalInputs) as key}
+
+ {/each}
+
+ {#if error}
+
+ {/if}
+
+
diff --git a/packages/desktop/components/popup/popups/MintNftConfirmationPopup.svelte b/packages/desktop/components/popup/popups/MintNftConfirmationPopup.svelte
index d9249aa596..8ae4113ceb 100644
--- a/packages/desktop/components/popup/popups/MintNftConfirmationPopup.svelte
+++ b/packages/desktop/components/popup/popups/MintNftConfirmationPopup.svelte
@@ -19,8 +19,20 @@
let storageDeposit: number = 0
let totalStorageDeposit: number = 0
- const { standard, type, uri, name, collectionName, royalties, issuerName, description, attributes, quantity } =
- $mintNftDetails || {}
+ const {
+ standard,
+ type,
+ uri,
+ name,
+ collectionName,
+ royalties,
+ issuerName,
+ description,
+ attributes,
+ quantity,
+ collectionId,
+ startIndex,
+ } = $mintNftDetails || {}
$: irc27Metadata = {
standard,
@@ -53,6 +65,7 @@
openPopup({
id: PopupId.MintNftForm,
overflow: true,
+ confirmClickOutside: true,
})
}
@@ -64,7 +77,7 @@
}
try {
- await mintNft(irc27Metadata, Number(quantity))
+ await mintNft(irc27Metadata, startIndex, quantity, collectionId)
closePopup()
} catch (err) {
handleError(err)
diff --git a/packages/desktop/components/popup/popups/MintNftFormPopup.svelte b/packages/desktop/components/popup/popups/MintNftFormPopup.svelte
index f7e9cad232..618973f5af 100644
--- a/packages/desktop/components/popup/popups/MintNftFormPopup.svelte
+++ b/packages/desktop/components/popup/popups/MintNftFormPopup.svelte
@@ -1,6 +1,5 @@
+
diff --git a/packages/desktop/features/developer-tools.features.ts b/packages/desktop/features/developer-tools.features.ts
index 50f71bea27..c066228d04 100644
--- a/packages/desktop/features/developer-tools.features.ts
+++ b/packages/desktop/features/developer-tools.features.ts
@@ -8,6 +8,9 @@ const developerToolsFeatures: IDeveloperFeatures = {
mintNft: {
enabled: true,
},
+ mintNftCollection: {
+ enabled: true,
+ },
mintNativeTokens: {
enabled: true,
},
diff --git a/packages/desktop/lib/auxiliary/popup/enums/popup-id.enum.ts b/packages/desktop/lib/auxiliary/popup/enums/popup-id.enum.ts
index 4ca6056575..38e48f658a 100644
--- a/packages/desktop/lib/auxiliary/popup/enums/popup-id.enum.ts
+++ b/packages/desktop/lib/auxiliary/popup/enums/popup-id.enum.ts
@@ -28,6 +28,8 @@ export enum PopupId {
MintNativeTokenForm = 'mintNativeTokenForm',
MintNftConfirmation = 'mintNftConfirmation',
MintNftForm = 'mintNftForm',
+ MintNftCollectionForm = 'mintNftCollectionForm',
+ MintNftCollectionConfirmation = 'mintNftCollectionConfirmation',
NodeAuthRequired = 'nodeAuthRequired',
NodeInfo = 'nodeInfo',
ReceiveAddress = 'receiveAddress',
diff --git a/packages/desktop/views/dashboard/developer/Developer.svelte b/packages/desktop/views/dashboard/developer/Developer.svelte
index 30af9695bf..dd885e7568 100644
--- a/packages/desktop/views/dashboard/developer/Developer.svelte
+++ b/packages/desktop/views/dashboard/developer/Developer.svelte
@@ -9,6 +9,7 @@
FaucetRequestButton,
MintNativeTokenButton,
MintNftButton,
+ MintNftCollectionButton,
TestDeepLinkButton,
} from './components'
import { DashboardRoute, dashboardRouter } from '@core/router'
@@ -30,6 +31,9 @@
{#if features.developerTools.mintNativeTokens.enabled}
{/if}
+ {#if features.developerTools.mintNftCollection.enabled}
+
+ {/if}
{#if features.developerTools.mintNft.enabled}
{/if}
diff --git a/packages/desktop/views/dashboard/developer/components/MintNftCollectionButton.svelte b/packages/desktop/views/dashboard/developer/components/MintNftCollectionButton.svelte
new file mode 100644
index 0000000000..c44e0cbbba
--- /dev/null
+++ b/packages/desktop/views/dashboard/developer/components/MintNftCollectionButton.svelte
@@ -0,0 +1,22 @@
+
+
+
diff --git a/packages/desktop/views/dashboard/developer/components/index.ts b/packages/desktop/views/dashboard/developer/components/index.ts
index 70d196eb86..1cd1180fcb 100644
--- a/packages/desktop/views/dashboard/developer/components/index.ts
+++ b/packages/desktop/views/dashboard/developer/components/index.ts
@@ -2,4 +2,5 @@ export { default as CreateAliasButton } from './CreateAliasButton.svelte'
export { default as FaucetRequestButton } from './FaucetRequestButton.svelte'
export { default as MintNativeTokenButton } from './MintNativeTokenButton.svelte'
export { default as MintNftButton } from './MintNftButton.svelte'
+export { default as MintNftCollectionButton } from './MintNftCollectionButton.svelte'
export { default as TestDeepLinkButton } from './TestDeepLinkButton.svelte'
diff --git a/packages/shared/src/lib/core/wallet/actions/index.ts b/packages/shared/src/lib/core/wallet/actions/index.ts
index ec51b33b01..b276c4d6ee 100644
--- a/packages/shared/src/lib/core/wallet/actions/index.ts
+++ b/packages/shared/src/lib/core/wallet/actions/index.ts
@@ -8,6 +8,7 @@ export * from './isTrackedNftAddress'
export * from './isTrackedTokenAddress'
export * from './mintNativeToken'
export * from './mintNft'
+export * from './mintNftCollection'
export * from './rejectActivity'
export * from './sendOutput'
export * from './updateL2BalanceWithoutActivity'
diff --git a/packages/shared/src/lib/core/wallet/actions/mintNft.ts b/packages/shared/src/lib/core/wallet/actions/mintNft.ts
index 598fa77661..df37f4f117 100644
--- a/packages/shared/src/lib/core/wallet/actions/mintNft.ts
+++ b/packages/shared/src/lib/core/wallet/actions/mintNft.ts
@@ -15,18 +15,33 @@ import { getTransactionOptions } from '../utils'
import { resetMintNftDetails } from '../stores'
import { getActiveNetworkId } from '@core/network'
-export async function mintNft(metadata: IIrc27Metadata, quantity: number): Promise {
+export async function mintNft(
+ metadata: IIrc27Metadata,
+ startIndex: number,
+ quantity: number,
+ collectionId?: string
+): Promise {
try {
const account = getSelectedAccount()
const networkId = getActiveNetworkId()
updateSelectedAccount({ isTransferring: true })
- const mintNftParams: MintNftParams = {
- issuer: account.depositAddress,
- immutableMetadata: Converter.utf8ToHex(JSON.stringify(metadata)),
+ const allNftParams: MintNftParams[] = []
+ for (let i = startIndex; i < startIndex + quantity; i++) {
+ const updatedMetadata = {
+ ...metadata,
+ name: metadata.name.replace('{id}', i.toString()),
+ description: metadata.description?.replace('{id}', i.toString()),
+ uri: metadata.uri.replace('{id}', i.toString()),
+ }
+ const mintNftParams: MintNftParams = {
+ address: account.depositAddress,
+ issuer: collectionId || account.depositAddress,
+ immutableMetadata: Converter.utf8ToHex(JSON.stringify(updatedMetadata)),
+ }
+ allNftParams.push(mintNftParams)
}
- const allNftParams: MintNftParams[] = Array(quantity).fill(mintNftParams)
// Mint NFT
const preparedTransaction = await account.prepareMintNfts(
diff --git a/packages/shared/src/lib/core/wallet/actions/mintNftCollection.ts b/packages/shared/src/lib/core/wallet/actions/mintNftCollection.ts
new file mode 100644
index 0000000000..088262ef45
--- /dev/null
+++ b/packages/shared/src/lib/core/wallet/actions/mintNftCollection.ts
@@ -0,0 +1,35 @@
+import { showNotification } from '@auxiliary/notification'
+import { getSelectedAccount, updateSelectedAccount } from '@core/account/stores'
+import { sendPreparedTransaction } from '@core/wallet/utils'
+import { localize } from '@core/i18n'
+import { IIrc27Metadata } from '@core/nfts'
+import { Converter } from '@core/utils'
+import { AliasOutputParams } from '@iota/sdk/out/types'
+import { getActiveNetworkId } from '@core/network/actions'
+import { processAndAddToActivities } from '@core/activity'
+
+export async function mintNftCollection(metadata: IIrc27Metadata): Promise {
+ try {
+ const account = getSelectedAccount()
+ const networkId = getActiveNetworkId()
+ updateSelectedAccount({ isTransferring: true })
+
+ const mintNftCollectionParams: AliasOutputParams = {
+ // issuer: account.depositAddress, // TODO: uncomment when added to iota-sdk
+ immutableMetadata: Converter.utf8ToHex(JSON.stringify(metadata)),
+ }
+
+ // Mint NFT
+ const preparedTransaction = await account.prepareCreateAliasOutput(mintNftCollectionParams)
+ const transaction = await sendPreparedTransaction(preparedTransaction)
+ showNotification({
+ variant: 'success',
+ text: localize('notifications.mintNft.success'),
+ })
+ await processAndAddToActivities(transaction, account, networkId)
+ } catch (err) {
+ return Promise.reject(err)
+ } finally {
+ updateSelectedAccount({ isTransferring: false })
+ }
+}
diff --git a/packages/shared/src/lib/core/wallet/interfaces/index.ts b/packages/shared/src/lib/core/wallet/interfaces/index.ts
index 8569b56f37..516e9f5e3c 100644
--- a/packages/shared/src/lib/core/wallet/interfaces/index.ts
+++ b/packages/shared/src/lib/core/wallet/interfaces/index.ts
@@ -2,6 +2,7 @@ export * from './account-subject.interface'
export * from './address-subject.interface'
export * from './contact-subject.interface'
export * from './mint-nft-details.interface'
+export * from './mint-nft-collection-details.interface'
export * from './mint-token-details.interface'
export * from './network-subject.interface'
export * from './participation.interface'
diff --git a/packages/shared/src/lib/core/wallet/interfaces/mint-nft-collection-details.interface.ts b/packages/shared/src/lib/core/wallet/interfaces/mint-nft-collection-details.interface.ts
new file mode 100644
index 0000000000..a6fce4641a
--- /dev/null
+++ b/packages/shared/src/lib/core/wallet/interfaces/mint-nft-collection-details.interface.ts
@@ -0,0 +1,3 @@
+import { IIrc27Metadata } from '@core/nfts'
+
+export interface IMintNftCollectionDetails extends Omit {}
diff --git a/packages/shared/src/lib/core/wallet/interfaces/mint-nft-details.interface.ts b/packages/shared/src/lib/core/wallet/interfaces/mint-nft-details.interface.ts
index b05ec8a577..8d66b288e2 100644
--- a/packages/shared/src/lib/core/wallet/interfaces/mint-nft-details.interface.ts
+++ b/packages/shared/src/lib/core/wallet/interfaces/mint-nft-details.interface.ts
@@ -1,5 +1,7 @@
import { IIrc27Metadata } from '@core/nfts'
export interface IMintNftDetails extends IIrc27Metadata {
+ collectionId?: string
quantity: number
+ startIndex: number
}
diff --git a/packages/shared/src/lib/core/wallet/stores/index.ts b/packages/shared/src/lib/core/wallet/stores/index.ts
index 1d872c4aba..eb3dfd58c0 100644
--- a/packages/shared/src/lib/core/wallet/stores/index.ts
+++ b/packages/shared/src/lib/core/wallet/stores/index.ts
@@ -1,3 +1,4 @@
+export * from './mint-nft-collection-details.store'
export * from './mint-nft-details.store'
export * from './mint-token-details.store'
export * from './send-flow-parameter.store'
diff --git a/packages/shared/src/lib/core/wallet/stores/mint-nft-collection-details.store.ts b/packages/shared/src/lib/core/wallet/stores/mint-nft-collection-details.store.ts
new file mode 100644
index 0000000000..6432c52b54
--- /dev/null
+++ b/packages/shared/src/lib/core/wallet/stores/mint-nft-collection-details.store.ts
@@ -0,0 +1,12 @@
+import { writable } from 'svelte/store'
+import { IMintNftCollectionDetails } from '../interfaces'
+
+export const mintNftCollectionDetails = writable(undefined)
+
+export function setMintNftCollectionDetails(payload: IMintNftCollectionDetails): void {
+ mintNftCollectionDetails.set(payload)
+}
+
+export function resetMintNftCollectionDetails(): void {
+ mintNftCollectionDetails.set(undefined)
+}
diff --git a/packages/shared/src/lib/features/interfaces/developer-features.interface.ts b/packages/shared/src/lib/features/interfaces/developer-features.interface.ts
index a7953609f0..e370f4aac2 100644
--- a/packages/shared/src/lib/features/interfaces/developer-features.interface.ts
+++ b/packages/shared/src/lib/features/interfaces/developer-features.interface.ts
@@ -3,6 +3,7 @@ import { IFeatureFlag } from './feature-flag.interface'
export interface IDeveloperFeatures extends IFeatureFlag {
faucet: IFeatureFlag
mintNft: IFeatureFlag
+ mintNftCollection: IFeatureFlag
mintNativeTokens: IFeatureFlag
alias: IFeatureFlag
refreshTokens: IFeatureFlag
diff --git a/packages/shared/src/locales/en.json b/packages/shared/src/locales/en.json
index 8807564d32..f561d50236 100644
--- a/packages/shared/src/locales/en.json
+++ b/packages/shared/src/locales/en.json
@@ -1159,7 +1159,7 @@
"errors": {
"invalidMimetype": "Invalid MimeType, check if the file type is supported",
"quantityTooSmall": "Quantity needs to be greater than 0",
- "quantityTooLarge": "Quantity needs to be smaller than 64",
+ "quantityTooLarge": "Quantity needs to be smaller than 127",
"emptyName": "Name is a required field",
"invalidURI": "Invalid URI, please provide a valid URI",
"notReachable": "URI not reachable, unable to check NFT type",
@@ -1366,7 +1366,8 @@
"switchAccount": "Switch account",
"syncAccounts": "Sync accounts",
"importToken": "Import {type} token",
- "syncTokens": "Force sync tokens"
+ "syncTokens": "Force sync tokens",
+ "mintNftCollection": "Mint NFT collection"
},
"general": {
"recipient": "Recipient",
@@ -1587,7 +1588,9 @@
"raffle": "Raffle",
"governance": "Governance",
"baseCoin": "Base Coin",
- "unverifiedContract": "Unverified Contract"
+ "unverifiedContract": "Unverified Contract",
+ "startIndex": "Start index",
+ "mintNftCollectionDescription": "Mint collection NFT in Alias Output"
},
"filters":{
"title": "Filters",
@@ -2071,7 +2074,8 @@
"description": "Optional parameter: A description of the NFT",
"attributes": "Optional parameter: An array of traits and values that define attributes of the NFT",
"uri": "To create a URI using custom media, first upload your file to IPFS via a storage service (e.g. https://nft.storage/)",
- "quantity": "Optional parameter: The quantity of copies minted with this metadata."
+ "quantity": "Optional parameter: The quantity of copies minted with this metadata.",
+ "startIndex": "Optional parameter: The start index of the NFTs to mint."
},
"governance": {
"removeProposalWarning": "You must stop voting for this proposal before removing it.",