1

Previously, we could get a TransactionInstruction using createCreateMetadataAccountV3Instruction and add the instruction to a transaction.

export declare function createCreateMetadataAccountV3Instruction(accounts: CreateMetadataAccountV3InstructionAccounts, args: CreateMetadataAccountV3InstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction;

The latest version (3.1.0) of @metaplex-foundation/mpl-token-metadata seems to be completely different and uses Umi. Has anyone figured out how to use this new version and is it required to also install Umi?

export declare function createMetadataAccountV3(context: Pick<Context, 'eddsa' | 'identity' | 'payer' | 'programs'>, input: CreateMetadataAccountV3InstructionAccounts & CreateMetadataAccountV3InstructionArgs): TransactionBuilder;

Basically trying to figure out how to do something like the following:

const instruction = createMetadataAccountV3(...)
const transaction = new Transaction().add(instruction);

How to get a TransactionInstruction from TransactionBuilder, and how to you set up the Umi context?

1 Answer 1

2

It was the last day of the Hyperdrive Hackathon and I was stuck exactly at this problem. Since, I have worked with the previous versions of mpl-token-metadata, I was assured that I will be able to build this part in minutes but Umi came as the surprise and took a good two hours of mine. :D

After playing with Umi for a couple of hours, I was able to figure it out. Not the cleanest of the solutions but it worked. You can improve it as you like:

//Imports
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { createMetadataAccountV3, CreateMetadataAccountV3InstructionAccounts, CreateMetadataAccountV3InstructionArgs } from '@metaplex-foundation/mpl-token-metadata'
import { clusterApiUrl, PublicKey, Keypair, Transaction, Connection, sendAndConfirmTransaction } from '@solana/web3.js';
import { fromWeb3JsPublicKey, toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters'

//Connection and Umi instance
const endpoint = clusterApiUrl("devnet");
const umi = createUmi(endpoint)
const connection = new Connection(endpoint);
const keypair: Keypair = Keypair.fromSecretKey(Uint8Array.from(secret));

//Constants
const mplProgramId = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
const mint = new PublicKey("8Lw2vWmtXbHGj6PYEnRXtFwrnjz2sS7CtoRdHGRq9ndA");
const [metadata] = PublicKey.findProgramAddressSync([
    Buffer.from("metadata"),
    mplProgramId.toBytes(),
    mint.toBytes()
], mplProgramId);

//Metadata Account IX Args
const args: CreateMetadataAccountV3InstructionArgs = {
    data: {
        name: "My Token",
        symbol: "TOKN",
        uri: "",
        sellerFeeBasisPoints: 0,
        collection: null,
        creators: [
            {address: fromWeb3JsPublicKey(keypair.publicKey), verified: true, share: 100}
        ],
        uses: null
    },
    isMutable: true,
    collectionDetails: null
}

//The tx builder expects the type of mint authority and signer to be `Signer`, so built a dummy Signer instance
const signer = {
    publicKey: fromWeb3JsPublicKey(keypair.publicKey),
    signTransaction: null,
    signMessage: null,
    signAllTransactions: null
}

//Metadata account IX Accounts
const accounts: CreateMetadataAccountV3InstructionAccounts = {
    metadata: fromWeb3JsPublicKey(metadata),
    mint: fromWeb3JsPublicKey(mint), 
    payer: signer,
    mintAuthority: signer,
    updateAuthority: fromWeb3JsPublicKey(keypair.publicKey)
}

//Arguments merged to match the parameter required by the method
const fullArgs = {...accounts, ...args}

const metadataBuilder = createMetadataAccountV3(umi, fullArgs);

(async() => {
    const ix: any = metadataBuilder.getInstructions()[0];
    ix.keys = ix.keys.map(key => {
        const newKey = {...key};
        newKey.pubkey = toWeb3JsPublicKey(key.pubkey);
        return newKey;
    });

    const tx = new Transaction().add(ix);
    const sig = await sendAndConfirmTransaction(connection, tx, [keypair]);

    console.log(sig)
})()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.