Features
Transferring Assets
Last updated January 31, 2026
This guide shows how to transfer Core Assets between wallets on Solana using the Metaplex Core SDK. Send NFTs to other users with a single instruction.
What You'll Learn
- Transfer an Asset to a new owner
- Handle transfers for Assets in Collections
- Use Transfer Delegate for authorized transfers
- Understand transfer authority requirements
Summary
Transfer a Core Asset to a new owner using the transfer instruction. Only the current owner (or an authorized Transfer Delegate) can initiate a transfer.
- Call
transfer(umi, { asset, newOwner })with the recipient's address - For Collection Assets, include the
collectionparameter - Transfer Delegates can transfer on behalf of owners
- Transfers are free (only transaction fee applies)
Out of Scope
Token Metadata transfers (use mpl-token-metadata), batch transfers (loop through Assets), and marketplace sales (use escrow programs).
Quick Start
Jump to: Basic Transfer · Collection Transfer · Delegate Transfer
- Install:
npm install @metaplex-foundation/mpl-core @metaplex-foundation/umi - Fetch the Asset to verify ownership and collection membership
- Call
transfer(umi, { asset, newOwner }) - Verify with
fetchAsset()that ownership changed
Prerequisites
- Umi configured with a signer that owns the Asset (or is its Transfer Delegate)
- Asset address of the Asset to transfer
- Recipient address (public key) of the new owner The owner of a Core Asset can transfer ownership to another account by using the
transferinstruction to the MPL Core program.
Transferring a Core Asset
1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
2import { transfer } from '@metaplex-foundation/mpl-core'
3import { mplCore } from '@metaplex-foundation/mpl-core'
4import { publicKey } from '@metaplex-foundation/umi'
5
6// Initialize UMI
7const umi = createUmi('https://api.devnet.solana.com')
8 .use(mplCore())
9
10// Transfer an existing NFT asset to a new owner
11const result = await transfer(umi, {
12 asset: publicKey('AssetAddressHere...'),
13 newOwner: publicKey('RecipientAddressHere...'),
14}).sendAndConfirm(umi)
15
16console.log('Asset transferred:', result.signature)
Transferring a Core Asset in a Collection
If you are transferring an Asset which has a collection you will need to pass the collection address in. How to tell if an asset is in a Collection?
Transfer an Asset that is part of a Collection
import { publicKey } from '@metaplex-foundation/umi'
import { transferV1 } from '@metaplex-foundation/mpl-core'
const asset = publicKey('11111111111111111111111111111111')
await transferV1(umi, {
asset: asset.publicKey,
newOwner: newOwner.publicKey,
collection: colleciton.publicKey,
}).sendAndConfirm(umi)
What if I am the Transfer Delegate of an Asset?
If you are the Transfer Delegate of an Asset via the Transfer Delegate plugin then you can call the transferV1 function as you would if you were the owner of the Asset.
Common Errors
Authority mismatch
You're not the owner or Transfer Delegate of the Asset. Check ownership:
const asset = await fetchAsset(umi, assetAddress)
console.log(asset.owner) // Must match your signer
Asset is frozen
The Asset has a Freeze Delegate plugin and is currently frozen. The freeze authority must unfreeze it before transfer.
Missing collection parameter
For Assets in a Collection, you must pass the collection address. Check if the Asset has a collection:
const asset = await fetchAsset(umi, assetAddress)
if (asset.updateAuthority.type === 'Collection') {
console.log('Collection:', asset.updateAuthority.address)
}
Notes
- Transfers are free - no rent cost, only the transaction fee (~0.000005 SOL)
- The new owner receives full control of the Asset
- Transfer, Burn, and Freeze Delegates are revoked after a successful transfer
- Frozen Assets cannot be transferred until unfrozen
- Always fetch the Asset first to check collection membership
Quick Reference
Transfer Parameters
| Parameter | Required | Description |
|---|---|---|
asset | Yes | Asset address or fetched object |
newOwner | Yes | Recipient's public key |
collection | If in collection | Collection address |
authority | No | Defaults to signer (use for delegates) |
Who Can Transfer?
| Authority | Can Transfer? |
|---|---|
| Asset Owner | Yes |
| Transfer Delegate | Yes (revoked after) |
| Update Authority | No |
| Collection Authority | No |
FAQ
How do I know if an Asset is in a Collection?
Fetch the Asset and check its updateAuthority:
const asset = await fetchAsset(umi, assetAddress)
if (asset.updateAuthority.type === 'Collection') {
// Pass asset.updateAuthority.address as collection parameter
}
Can I transfer to myself?
Yes. Transferring to your own address is valid (useful for consolidating wallets or testing).
What happens to the Transfer Delegate after a transfer?
The Transfer Delegate plugin is automatically revoked when the transfer completes. The new owner must assign a new delegate if needed.
Can I cancel a transfer?
No. Transfers are atomic - once the transaction confirms, ownership has changed. There's no pending state to cancel.
Can I transfer multiple Assets at once?
Not in a single instruction. You can batch multiple transfer instructions in one transaction (up to transaction size limits), but each Asset requires its own transfer call.
Does transferring change the update authority?
No. Transfer only changes ownership. The update authority remains the same unless explicitly changed via the update instruction.
Glossary
| Term | Definition |
|---|---|
| Owner | The wallet that currently owns the Asset |
| Transfer Delegate | An account authorized to transfer on behalf of the owner |
| Frozen | An Asset state where transfers are blocked |
| New Owner | The recipient wallet receiving the Asset |
| Collection | The Collection an Asset belongs to (affects transfer requirements) |
