Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/commands/bg/collection/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {
ruleSet
} from '@metaplex-foundation/mpl-core'
import type { TransactionSignature } from '@metaplex-foundation/umi'
import { generateSigner } from '@metaplex-foundation/umi'
import { Flags } from '@oclif/core'
import ora from 'ora'

import { TransactionCommand } from '../../../TransactionCommand.js'
import { generateExplorerUrl } from '../../../explorers.js'
import { mintKeypairFlag, resolveMintSigner } from '../../../lib/mint-keypair.js'
import umiSendAndConfirmTransaction from '../../../lib/umi/sendAndConfirm.js'
import { txSignatureToString } from '../../../lib/util.js'

Expand Down Expand Up @@ -38,6 +38,7 @@ The Bubblegum V2 plugin is required for collections that will contain compressed
description: 'Collection metadata URI',
required: true,
}),
'mint-keypair': mintKeypairFlag,
royalties: Flags.integer({
description: 'Royalty percentage for secondary sales (0-100)',
min: 0,
Expand All @@ -54,7 +55,7 @@ The Bubblegum V2 plugin is required for collections that will contain compressed

try {
// Generate collection address
const collection = generateSigner(umi)
const collection = await resolveMintSigner(umi, flags['mint-keypair'])

const plugins: CreateCollectionArgsPlugin[] = [
{
Expand Down
24 changes: 18 additions & 6 deletions src/commands/core/asset/create.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Flags } from '@oclif/core'
import { Umi, publicKey } from '@metaplex-foundation/umi'

import fs from 'node:fs'
import ora from 'ora'

import { generateSigner, publicKey, Umi } from '@metaplex-foundation/umi'
import { ExplorerType, generateCoreExplorerUrl, generateExplorerUrl } from '../../../explorers.js'
import createAssetFromArgs, { AssetCreationResult } from '../../../lib/core/create/createAssetFromArgs.js'
import { mintKeypairFlag, resolveMintSigner } from '../../../lib/mint-keypair.js'
import { Plugin, PluginData } from '../../../lib/types/pluginData.js'
import prepareJsonMetadata from '../../../lib/core/create/prepareJsonMetadata.js'
import uploadFile from '../../../lib/uploader/uploadFile.js'
Expand Down Expand Up @@ -33,6 +34,7 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>
- Use --owner to mint the asset directly to a specific wallet address (defaults to the signer)
- Use --plugins to interactively select and configure plugins
- Use --pluginsFile to provide plugin configuration from a JSON file
- Use --mint-keypair to specify a vanity keypair file for the asset address
`

static override examples = [
Expand Down Expand Up @@ -85,6 +87,7 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>
hidden: true,
}),
// Plugin configuration flags
'mint-keypair': mintKeypairFlag,
plugins: Flags.boolean({
name: 'plugins',
required: false,
Expand Down Expand Up @@ -116,7 +119,7 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>
return undefined
}

private async handleFileBasedCreation(umi: any, imagePath: string, jsonPath: string, collection?: string, owner?: string) {
private async handleFileBasedCreation(umi: any, imagePath: string, jsonPath: string, collection?: string, owner?: string, mintKeypairPath?: string) {
const imageSpinner = ora('Uploading image...').start()
const imageUri = await uploadFile(umi, imagePath).catch((err) => {
imageSpinner.fail(`Failed to upload image. ${err}`)
Expand All @@ -141,7 +144,10 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>

const pluginData = await this.getPluginData()
const assetSpinner = ora('Creating Asset...').start()
const assetSigner = generateSigner(umi)
const assetSigner = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
assetSpinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await createAssetFromArgs(umi, {
assetSigner,
Expand Down Expand Up @@ -262,7 +268,10 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>
const jsonUri = await this.createAndUploadMetadata(umi, wizardData)

const spinner = ora('Creating Asset...').start()
const assetSigner = generateSigner(umi)
const assetSigner = await resolveMintSigner(umi, flags['mint-keypair']).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await createAssetFromArgs(umi, {
assetSigner,
Expand All @@ -285,7 +294,7 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>
this.error('You must provide an image --image and JSON --offchain file')
}

return await this.handleFileBasedCreation(umi, flags.image, flags.offchain, flags.collection, flags.owner)
return this.handleFileBasedCreation(umi, flags.image, flags.offchain, flags.collection, flags.owner, flags['mint-keypair'])
} else {
// Create asset from name and uri flags
if (!flags.name) {
Expand All @@ -297,7 +306,10 @@ export default class AssetCreate extends TransactionCommand<typeof AssetCreate>

const pluginData = await this.getPluginData()
const spinner = ora('Creating Asset...').start()
const assetSigner = generateSigner(umi)
const assetSigner = await resolveMintSigner(umi, flags['mint-keypair']).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await createAssetFromArgs(umi, {
assetSigner,
Expand Down
25 changes: 19 additions & 6 deletions src/commands/core/collection/create.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createCollection } from '@metaplex-foundation/mpl-core'
import { generateSigner, PublicKey, Umi } from '@metaplex-foundation/umi'
import { PublicKey, Umi } from '@metaplex-foundation/umi'
import { Flags } from '@oclif/core'
import fs from 'node:fs'
import ora from 'ora'
import { mintKeypairFlag, resolveMintSigner } from '../../../lib/mint-keypair.js'
import { Plugin, PluginData } from '../../../lib/types/pluginData.js'
import { txSignatureToString } from '../../../lib/util.js'
import pluginConfigurator, { mapPluginDataToArray } from '../../../prompts/pluginInquirer.js'
Expand All @@ -29,6 +30,7 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core
Additional Options:
- Use --plugins to interactively select and configure plugins
- Use --pluginsFile to provide plugin configuration from a JSON file
- Use --mint-keypair to specify a vanity keypair file for the collection address
`

static override examples = [
Expand Down Expand Up @@ -70,6 +72,7 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core
hidden: true,
}),
// Plugin configuration flags
'mint-keypair': mintKeypairFlag,
plugins: Flags.boolean({
name: 'plugins',
required: false,
Expand Down Expand Up @@ -118,7 +121,7 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core
return pluginData
}

private async handleFileBasedCreation(umi: Umi, imagePath: string, jsonPath: string, explorer: ExplorerType) {
private async handleFileBasedCreation(umi: Umi, imagePath: string, jsonPath: string, explorer: ExplorerType, mintKeypairPath?: string) {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
const imageSpinner = ora('Uploading image...').start()
const imageResult = await uploadFile(umi, imagePath).catch((err) => {
imageSpinner.fail(`Failed to upload image. ${err}`)
Expand Down Expand Up @@ -157,7 +160,10 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core

const pluginData = await this.getPluginData()
const spinner = ora('Creating Collection...').start()
const collection = generateSigner(umi)
const collection = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const txBuilder = createCollection(umi, {
collection,
Expand Down Expand Up @@ -237,6 +243,7 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core
public async run(): Promise<unknown> {
const { flags } = await this.parse(CoreCollectionCreate)
const { umi, explorer } = this.context
const mintKeypairPath = flags['mint-keypair']

if (flags.wizard) {
this.log(
Expand All @@ -253,7 +260,10 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core
const { collectionName, metadataUri } = await this.createAndUploadMetadata(umi, wizardData)

const spinner = ora('Creating Collection...').start()
const collection = generateSigner(umi)
const collection = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const txBuilder = createCollection(umi, {
collection,
Expand All @@ -278,7 +288,7 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core
this.error('You must provide an image --image and JSON --offchain file')
}

return await this.handleFileBasedCreation(umi, flags.image, flags.offchain, explorer)
return this.handleFileBasedCreation(umi, flags.image, flags.offchain, explorer, mintKeypairPath)
} else {
// Create collection from name and uri flags
if (!flags.name) {
Expand All @@ -290,7 +300,10 @@ export default class CoreCollectionCreate extends TransactionCommand<typeof Core

const pluginData = await this.getPluginData()
const spinner = ora('Creating Collection...').start()
const collection = generateSigner(umi)
const collection = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const txBuilder = createCollection(umi, {
collection,
Expand Down
31 changes: 23 additions & 8 deletions src/commands/tm/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { TransactionCommand } from '../../TransactionCommand.js'
import { ExplorerType, generateExplorerUrl } from '../../explorers.js'
import uploadFile from '../../lib/uploader/uploadFile.js'
import uploadJson from '../../lib/uploader/uploadJson.js'
import { mintKeypairFlag, resolveMintSigner } from '../../lib/mint-keypair.js'
import umiSendAndConfirmTransaction from '../../lib/umi/sendAndConfirm.js'
import createTokenMetadataPrompt, { CreateTokenMetadataPromptResult, NftType } from '../../prompts/createTokenMetadataPrompt.js'
import { txSignatureToString } from '../../lib/util.js'
Expand Down Expand Up @@ -50,6 +51,7 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
- Use --collection to specify a collection ID for the NFT
- Use --type to specify NFT type: "pnft" (default) or "nft"
- Use --attributes to specify NFT attributes in format "trait1:value1,trait2:value2"
- Use --mint-keypair to specify a vanity keypair file for the NFT mint address
`

static override examples = [
Expand Down Expand Up @@ -124,14 +126,15 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
name: 'collection',
description: 'Collection ID'
}),
'mint-keypair': mintKeypairFlag,
type: Flags.string({
description: 'Type of NFT to create',
options: ['nft', 'pnft'],
default: 'pnft',
}),
}

private async handleFileBasedCreation(umi: Umi, imagePath: string, jsonPath: string, collection?: string, isProgrammable: boolean = true) {
private async handleFileBasedCreation(umi: Umi, imagePath: string, jsonPath: string, collection?: string, isProgrammable: boolean = true, mintKeypairPath?: string) {
const imageSpinner = ora('Uploading image...').start()
const imageUri = await uploadFile(umi, imagePath).catch((err) => {
imageSpinner.fail(`Failed to upload image. ${err}`)
Expand All @@ -156,7 +159,10 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
jsonSpinner.succeed(`JSON uploaded to ${jsonUri}`)

const nftSpinner = ora('Creating NFT...').start()
const nftSigner = generateSigner(umi)
const nftSigner = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
nftSpinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await this.createNftFromArgs(umi, {
nftSigner,
Expand Down Expand Up @@ -317,8 +323,7 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
}

private async createNftFromArgs(umi: Umi, input: NftInput) {
this.log(`[DEBUG] createNftFromArgs called with isProgrammable: ${input.isProgrammable}`)
const mint = input.nftSigner || generateSigner(umi)
const mint = input.nftSigner ?? generateSigner(umi)
const createNftIx = input.isProgrammable
? createProgrammableNft(umi, {
mint,
Expand All @@ -345,6 +350,7 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
public async run(): Promise<unknown> {
const { flags } = await this.parse(TmCreate)
const { umi, explorer } = this.context
const mintKeypairPath = flags['mint-keypair']

const formatResult = (result: { mint: string; signature: Uint8Array }) => {
const sig = txSignatureToString(result.signature)
Expand All @@ -371,7 +377,10 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
const jsonUri = await this.createAndUploadMetadata(umi, wizardData)

const spinner = ora('Creating NFT...').start()
const nftSigner = generateSigner(umi)
const nftSigner = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await this.createNftFromArgs(umi, {
nftSigner,
Expand All @@ -395,14 +404,17 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
this.error('You must provide --image when using --offchain')
}

const result = await this.handleFileBasedCreation(umi, flags.image, flags.offchain, flags.collection, flags.type === 'pnft')
const result = await this.handleFileBasedCreation(umi, flags.image, flags.offchain, flags.collection, flags.type === 'pnft', mintKeypairPath)
return formatResult(result)

} else if (flags.name && flags.uri) {
// URI flow: Use existing metadata URI (simplest case)
this.log(`Creating ${flags.type === 'pnft' ? 'Programmable NFT (pNFT)' : 'NFT'}...`)
const spinner = ora('Minting NFT...').start()
const nftSigner = generateSigner(umi)
const nftSigner = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await this.createNftFromArgs(umi, {
nftSigner,
Expand All @@ -425,7 +437,10 @@ export default class TmCreate extends TransactionCommand<typeof TmCreate> {
const metadataUri = await this.createMetadataFromFlags(umi, flags)

const spinner = ora('Creating NFT...').start()
const nftSigner = generateSigner(umi)
const nftSigner = await resolveMintSigner(umi, mintKeypairPath).catch((error) => {
spinner.fail(`Failed to load mint keypair: ${error}`)
throw error
})

const result = await this.createNftFromArgs(umi, {
nftSigner,
Expand Down
20 changes: 12 additions & 8 deletions src/commands/toolbox/token/create.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { createFungible } from '@metaplex-foundation/mpl-token-metadata'
import { createTokenIfMissing, findAssociatedTokenPda, mintTokensTo } from '@metaplex-foundation/mpl-toolbox'
import { generateSigner, percentAmount, Umi } from '@metaplex-foundation/umi'
import { percentAmount, Umi } from '@metaplex-foundation/umi'
import { Flags } from '@oclif/core'
import ora from 'ora'
import { TransactionCommand } from '../../../TransactionCommand.js'
import { ExplorerType, generateExplorerUrl } from '../../../explorers.js'
import umiSendAndConfirmTransaction from '../../../lib/umi/sendAndConfirm.js'
import imageUploader from '../../../lib/uploader/imageUploader.js'
import uploadJson from '../../../lib/uploader/uploadJson.js'
import { mintKeypairFlag, resolveMintSigner } from '../../../lib/mint-keypair.js'
import { RpcChain, txSignatureToString } from '../../../lib/util.js'
import { validateMintAmount, validateTokenName, validateTokenSymbol } from '../../../lib/validations.js'
import createTokenPrompt from '../../../prompts/createTokenPrompt.js'
Expand Down Expand Up @@ -97,6 +98,7 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
- Use --description to add a description to your token
- Use --image to add an image to your token metadata
- Use --speed-run to measure execution time
- Use --mint-keypair to specify a vanity keypair file for the token mint address
`

static override examples = [
Expand Down Expand Up @@ -145,6 +147,7 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
required: false,
exclusive: ['wizard'],
}),
'mint-keypair': mintKeypairFlag,
}

private async validateFlags(flags: {
Expand Down Expand Up @@ -222,7 +225,8 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
mintAmount: number;
},
explorer: ExplorerType,
startTime: number
startTime: number,
mintKeypairPath?: string,
) {
let imageUri = '';
if (input.image) {
Expand All @@ -240,14 +244,14 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
this.error('Failed to upload token metadata');
}

return await this.createToken(umi, {
return this.createToken(umi, {
name: input.name,
symbol: input.symbol,
description: input.description,
image: jsonUri,
decimals: input.decimals,
mintAmount: input.mintAmount,
}, explorer, startTime);
}, explorer, startTime, mintKeypairPath);
}

public async run(): Promise<unknown> {
Expand All @@ -271,7 +275,7 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
image: wizard.image,
decimals: wizard.decimals ?? 0,
mintAmount: wizard.mintAmount,
}, explorer, startTime);
}, explorer, startTime, flags['mint-keypair']);
} else {
const validatedFlags = await this.validateFlags(flags);
return await this.createTokenWithMetadata(umi, {
Expand All @@ -281,7 +285,7 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
image: flags.image,
decimals: validatedFlags.decimals,
mintAmount: validatedFlags.mint,
}, explorer, startTime);
}, explorer, startTime, flags['mint-keypair']);
}
} catch (error) {
if (flags['speed-run']) {
Expand All @@ -292,8 +296,8 @@ export default class ToolboxTokenCreate extends TransactionCommand<typeof Toolbo
}
}

private async createToken(umi: Umi, input: TokenInput, explorer: ExplorerType, startTime: number) {
const mint = generateSigner(umi)
private async createToken(umi: Umi, input: TokenInput, explorer: ExplorerType, startTime: number, mintKeypairPath?: string) {
const mint = await resolveMintSigner(umi, mintKeypairPath)
const createFunigbleIx = createFungible(umi, {
mint,
name: input.name,
Expand Down
Loading
Loading