From 889fbbf7fe1a1d0992fae4308cd866143131c2aa Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Apr 2026 16:57:31 +0000 Subject: [PATCH 1/2] Add 'core collection add' command to add an existing asset to a collection Uses mpl-core's updateV2 instruction to set an asset's update authority to a collection, enabling post-creation collection assignment. https://claude.ai/code/session_01QjTrbKjMEQZoKDSzdmM7vV --- src/commands/core/collection/add.ts | 70 +++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/commands/core/collection/add.ts diff --git a/src/commands/core/collection/add.ts b/src/commands/core/collection/add.ts new file mode 100644 index 0000000..9fdb67f --- /dev/null +++ b/src/commands/core/collection/add.ts @@ -0,0 +1,70 @@ +import { baseUpdateAuthority, fetchAsset, fetchCollection, update } from '@metaplex-foundation/mpl-core' +import { publicKey } from '@metaplex-foundation/umi' +import { Args } from '@oclif/core' +import ora from 'ora' + +import { generateExplorerUrl } from '../../../explorers.js' +import { TransactionCommand } from '../../../TransactionCommand.js' +import umiSendAndConfirmTransaction from '../../../lib/umi/sendAndConfirm.js' +import { txSignatureToString } from '../../../lib/util.js' + +export default class CollectionAdd extends TransactionCommand { + static override description = 'Add an existing MPL Core Asset to a Collection' + + static override examples = [ + '<%= config.bin %> <%= command.id %> ', + ] + + static override args = { + collectionId: Args.string({ description: 'Collection to add the asset to', required: true }), + assetId: Args.string({ description: 'Asset to add to the collection', required: true }), + } + + public async run(): Promise { + const { args } = await this.parse(CollectionAdd) + const { umi, explorer, chain } = this.context + + const spinner = ora('Fetching asset and collection...').start() + + try { + const asset = await fetchAsset(umi, publicKey(args.assetId)) + const collection = await fetchCollection(umi, publicKey(args.collectionId)) + + if (asset.updateAuthority.type === 'Collection') { + spinner.fail('Asset is already in a collection') + this.error(`Asset ${args.assetId} already belongs to collection ${asset.updateAuthority.address}`) + } + + spinner.text = 'Adding asset to collection...' + + const txBuilder = update(umi, { + asset, + newUpdateAuthority: baseUpdateAuthority('Collection', [collection.publicKey]), + newCollection: collection.publicKey, + }) + + const result = await umiSendAndConfirmTransaction(umi, txBuilder) + const signature = txSignatureToString(result.transaction.signature as Uint8Array) + const explorerUrl = generateExplorerUrl(explorer, chain, signature, 'transaction') + + spinner.succeed(`Asset added to collection`) + this.logSuccess(`-------------------------------- + Asset: ${args.assetId} + Collection: ${args.collectionId} + Signature: ${signature} + Explorer: ${explorerUrl} +--------------------------------`) + + return { + asset: args.assetId, + collection: args.collectionId, + signature, + explorer: explorerUrl, + } + } catch (error) { + if (!spinner.isSpinning) throw error + spinner.fail('Failed to add asset to collection') + throw error + } + } +} From 589fd709f9c9172eab94510a0ad2ea38abe32b93 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Apr 2026 18:33:23 +0000 Subject: [PATCH 2/2] Rename args to 'collection' and 'asset' to match peer commands --- src/commands/core/collection/add.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/commands/core/collection/add.ts b/src/commands/core/collection/add.ts index 9fdb67f..84640bc 100644 --- a/src/commands/core/collection/add.ts +++ b/src/commands/core/collection/add.ts @@ -12,12 +12,12 @@ export default class CollectionAdd extends TransactionCommand <%= command.id %> ', + '<%= config.bin %> <%= command.id %> ', ] static override args = { - collectionId: Args.string({ description: 'Collection to add the asset to', required: true }), - assetId: Args.string({ description: 'Asset to add to the collection', required: true }), + collection: Args.string({ description: 'Collection to add the asset to', required: true }), + asset: Args.string({ description: 'Asset to add to the collection', required: true }), } public async run(): Promise { @@ -27,12 +27,12 @@ export default class CollectionAdd extends TransactionCommand