Features

Creating Assets

Last updated January 31, 2026

This guide shows how to create a Core Asset (NFT) on Solana using the Metaplex Core SDK. You'll upload off-chain metadata, create the on-chain Asset account, and optionally add it to a Collection or attach plugins.

What You'll Build

A Core Asset with:

  • Off-chain metadata (name, image, attributes) stored on Arweave
  • On-chain Asset account with ownership and metadata URI
  • Optional: Collection membership
  • Optional: Plugins (royalties, freeze, attributes)

Summary

Create a Core Asset by uploading metadata JSON to decentralized storage, then calling create() with the URI. Assets can be minted standalone or into Collections, and can include plugins at creation time.

  • Upload metadata JSON to Arweave/IPFS, get a URI
  • Call create() with name, URI, and optional plugins
  • For collections: pass the collection parameter
  • Costs ~0.0029 SOL per asset

Out of Scope

Token Metadata NFTs (use mpl-token-metadata), compressed NFTs (use Bubblegum), fungible tokens (use SPL Token), and NFT migration.

Quick Start

Jump to: Upload Metadata · Create Asset · With Collection · With Plugins

  1. Install: npm install @metaplex-foundation/mpl-core @metaplex-foundation/umi
  2. Upload metadata JSON to get a URI
  3. Call create(umi, { asset, name, uri })
  4. Verify on core.metaplex.com

Prerequisites

  • Umi configured with a signer and RPC connection
  • SOL for transaction fees (~0.003 SOL per asset)
  • Metadata JSON ready to upload (name, image, attributes)

The Creation Process

  1. Upload off-chain data. Store a JSON file containing name, description, image URL, and attributes. The file must be accessible via a public URI.
  2. Create on-chain Asset account. Call the create instruction with the metadata URI to mint the Asset.

Uploading Off-chain Data

Use any storage service (Arweave, IPFS, AWS) to upload your metadata JSON. Umi provides uploader plugins for common services. See the JSON Schema for all available metadata fields.

upload-metadata.ts
import { irysUploader } from '@metaplex-foundation/umi-uploader-irys'
// Configure an uploader (Irys, AWS, etc.)
umi.use(irysUploader())
// Upload image first
const [imageUri] = await umi.uploader.upload([imageFile])
// Upload metadata JSON
const uri = await umi.uploader.uploadJson({
name: 'My NFT',
description: 'This is my NFT',
image: imageUri,
attributes: [
{ trait_type: 'Background', value: 'Blue' },
],
})

Now that you have a URI, you can create the Asset.

Create an Asset

Use the create instruction to mint a new Core Asset.

1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
2import { create } from '@metaplex-foundation/mpl-core'
3import { mplCore } from '@metaplex-foundation/mpl-core'
4
5// Initialize UMI
6const umi = createUmi('https://api.devnet.solana.com')
7 .use(mplCore())
8
9// Create a new NFT asset
10const asset = await create(umi, {
11 name: 'My NFT',
12 uri: 'https://example.com/metadata.json'
13}).sendAndConfirm(umi)
14
15console.log('Asset created:', asset.publicKey)

Create an Asset into a Collection

To create an Asset as part of a Collection, pass the collection parameter. The Collection must already exist.

1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
2import { create, fetchCollection } from '@metaplex-foundation/mpl-core'
3import { mplCore } from '@metaplex-foundation/mpl-core'
4import { generateSigner, publicKey } from '@metaplex-foundation/umi'
5
6// Initialize UMI
7const umi = createUmi('https://api.devnet.solana.com')
8 .use(mplCore())
9
10const collectionAddress = publicKey('YOUR_COLLECTION_ADDRESS')
11
12// Fetch the existing collection
13const collection = await fetchCollection(umi, collectionAddress)
14
15// Generate a new keypair for the asset
16const assetSigner = generateSigner(umi)
17
18// Create asset in the collection
19await create(umi, {
20 asset: assetSigner,
21 collection,
22 name: 'Collection Item #1',
23 uri: 'https://example.com/item1.json',
24}).sendAndConfirm(umi)
25
26console.log('Asset created in collection:', assetSigner.publicKey)

See Collections for creating Collections.

Create an Asset with Plugins

Add plugins at creation time by passing them in the plugins array. This example adds the Royalties plugin:

1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
2import { create, ruleSet } from '@metaplex-foundation/mpl-core'
3import { mplCore } from '@metaplex-foundation/mpl-core'
4import { generateSigner, publicKey } from '@metaplex-foundation/umi'
5
6// Initialize UMI
7const umi = createUmi('https://api.devnet.solana.com')
8 .use(mplCore())
9
10const creator = publicKey('YOUR_CREATOR_ADDRESS')
11
12// Generate a new keypair for the asset
13const assetSigner = generateSigner(umi)
14
15// Create asset with Royalties plugin
16await create(umi, {
17 asset: assetSigner,
18 name: 'NFT with Royalties',
19 uri: 'https://example.com/metadata.json',
20 plugins: [
21 {
22 type: 'Royalties',
23 basisPoints: 500, // 5%
24 creators: [
25 { address: creator, percentage: 100 },
26 ],
27 ruleSet: ruleSet('None'),
28 },
29 ],
30}).sendAndConfirm(umi)
31
32console.log('Asset created with plugins:', assetSigner.publicKey)

Common Plugins

Here are a few commonly used plugins. See Plugins Overview for the full list.

Common Errors

Asset account already exists

The asset keypair was already used. Generate a new signer:

const assetSigner = generateSigner(umi) // Must be unique

Collection not found

The collection address doesn't exist or isn't a valid Core Collection. Verify the address and that you've created the Collection first.

Insufficient funds

Your payer wallet needs ~0.003 SOL for rent. Fund it with:

solana airdrop 1 <WALLET_ADDRESS> --url devnet

Notes

  • The asset parameter must be a new keypair - you cannot reuse an existing account
  • If minting to a different owner, pass the owner parameter
  • Plugins added at creation are cheaper than adding them after (one transaction vs two)
  • Use commitment: 'finalized' when creating assets in a script that immediately fetches them

Quick Reference

Program ID

NetworkAddress
MainnetCoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d
DevnetCoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d

Minimum Code

minimal-create.ts
import { generateSigner } from '@metaplex-foundation/umi'
import { create } from '@metaplex-foundation/mpl-core'
const asset = generateSigner(umi)
await create(umi, { asset, name: 'My NFT', uri: 'https://...' }).sendAndConfirm(umi)

Cost Breakdown

ItemCost
Asset account rent~0.0029 SOL
Transaction fee~0.000005 SOL
Total~0.003 SOL

FAQ

What's the difference between Core Assets and Token Metadata NFTs?

Core Assets use a single account and cost ~80% less. Token Metadata uses 3+ accounts (mint, metadata, token). Core is recommended for new projects.

Can I create multiple assets in one transaction?

No. Each create instruction creates one asset. For bulk minting, use Core Candy Machine or batch transactions.

Do I need to create a Collection first?

No. Assets can exist without a Collection. However, Collections enable collection-level royalties and operations.

How do I mint to a different wallet?

Pass the owner parameter:

await create(umi, { asset, name, uri, owner: recipientAddress })

What metadata format should I use?

Use the standard NFT metadata format with name, description, image, and optional attributes array. See JSON Schema.

Glossary

TermDefinition
AssetA Core on-chain account representing an NFT
URIThe URL pointing to off-chain metadata JSON
SignerA keypair that signs the transaction (asset must be a signer at creation)
CollectionA Core account that groups related Assets
PluginA modular extension adding behavior to an Asset
RentSOL required to keep an account alive on Solana
Previous
Rust SDK