見出し画像

Core NFT Assetを作成する方法

こちらは、Metaplexの「MPL Coreプロトコル」を使用して、Solanaブロックチェーン上に次世代のデジタルアセットNFT(Core Asset)を作成するガイドです。MPL Core Assetsは、シンプルな設計と独自のプラグインシステムにより、クリエイターと所有者の両方にとって、より大きな創造性と幅広いダイナミックな体験を提供し、Solana上の次世代NFTプロジェクトの波を生み出します。

前提条件

  • お好みのコードエディタ(Visual Studio Codeを推奨)

  • Node 18.x.x以上

初期セットアップ

このガイドでは、単一のファイルスクリプトに基づいてJavaScriptを使用し、NFT Core Assetの作成を行います。必要に応じて、関数の修正や移動が必要になる場合があります。

初期化

まず、(任意で)新しいプロジェクトを初期化します。お好みのパッケージマネージャー(npm、yarn、pnpm、bun)を使用し、プロンプトが表示されたら必要な詳細を入力してください。

npm init

必要なパッケージ

このガイドで使用する必要なパッケージをインストールします。

@metaplex-foundation/umi
@metaplex-foundation/umi-bundle-defaults
@metaplex-foundation/mpl-core
@metaplex-foundation/umi-uploader-irys

npm i @metaplex-foundation/umi
npm i @metaplex-foundation/umi-bundle-defaults
npm i @metaplex-foundation/mpl-core
npm i @metaplex-foundation/umi-uploader-irys;

インポートとラッパー関数

ここでは、このガイド特有の必要なインポートをすべて定義し、コードを実行するためのラッパー関数を作成します。

import { create, mplCore } from '@metaplex-foundation/mpl-core'
import {
  createGenericFile,
  generateSigner,
  signerIdentity,
  sol,
} from '@metaplex-foundation/umi'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { irysUploader } from '@metaplex-foundation/umi-uploader-irys'
import { base58 } from '@metaplex-foundation/umi/serializers'
import fs from 'fs'
import path from 'path'

// Create the wrapper function
const createNft = async () => {
  ///
  ///
  ///  all our code will go in here
  ///
  ///
}

// run the wrapper function
createNft()

Umiのセットアップ

この例では「generatedSigner()」を使用してUmiをセットアップする手順を説明します。Reactでこの例を試したい場合は「React - Umi w/ Wallet Adapter」ガイドを参考にUmiをセットアップする必要があります。このガイドでは、ウォレットのセットアップ以外に、fileStorageキーとwallet adapterについても説明します。

新しいウォレットの生成

const umi = createUmi('https://api.devnet.solana.com')
  .use(mplCore())
  .use(
    irysUploader({
      // mainnet address: "https://node1.irys.xyz"
      // devnet address: "https://devnet.irys.xyz"
      address: 'https://devnet.irys.xyz',
    })
  )

const signer = generateSigner(umi)

umi.use(signerIdentity(signer))

// This will airdrop SOL on devnet only for testing.
console.log('Airdropping 1 SOL to identity')
await umi.rpc.airdrop(umi.identity.publickey)

既存のウォレットの使用

const umi = createUmi('https://api.devnet.solana.com')
  .use(mplCore())
  .use(irysUploader())

// Generate a new keypair signer.
const signer = generateSigner(umi)

// You will need to us fs and navigate the filesystem to
// load the wallet you wish to use via relative pathing.
const walletFile = fs.readFileSync('./keypair.json')
  

// Convert your walletFile onto a keypair.
let keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(walletFile));

// Load the keypair into umi.
umi.use(keypairIdentity(umiSigner));

NFTの作成

画像のアップロード

まず最初に行うべきことは、NFTを表現し、認識可能にする画像をアップロードすることです。これはjpeg、png、またはgif形式で可能です。

Umiには、Arweave、NftStorage、AWS、ShdwDriveなどのストレージソリューションにアップロードできるダウンロード可能なストレージプラグインが付属しています。このガイドの冒頭で「irysUploader()」プラグインをインストールしました。これはArweaveブロックチェーンにコンテンツを保存するものなので、ここではこれを使用します。

💡 ローカルスクリプト/Node.js
この例では、Irysを使用してArweaveにアップロードするローカルスクリプト/Node.jsのアプローチを使用しています。別のストレージプロバイダーにファイルをアップロードしたり、ブラウザからアップロードしたりする場合は、別のアプローチを取る必要があります。「fs」のインポートと使用は、ブラウザ環境では機能しません。

// use `fs` to read file via a string path.

const imageFile = fs.readFileSync('./assets/my-image.jpg')

// Use `createGenericFile` to transform the file into a `GenericFile` type
// that umi can understand. Make sure you set the mimi tag type correctly
// otherwise Arweave will not know how to display your image.

const umiImageFile = createGenericFile(imageFile, 'my-image.jpeg', {
  tags: [{ name: 'Content-Type', value: 'image/jpeg' }],
})

// Here we upload the image to Arweave via Irys and we get returned a uri
// address where the file is located. You can log this out but as the
// uploader can takes an array of files it also returns an array of uris.
// To get the uri we want we can call index [0] in the array.

const imageUri = await umi.uploader.upload([umiImageFile]).catch((err) => {
  throw new Error(err)
})

console.log(imageUri[0])

メタデータのアップロード

有効で機能する画像URIを取得したら、トークンのメタデータの作業に取り掛かることができます。
fungible tokenのオフチェーンメタデータの標準は以下の通りです。

const metadata = {
  name: 'My NFT',
  description: 'This is an NFT on Solana',
  image: imageUri[0],
  external_url: 'https://example.com',
  attributes: [
    {
      trait_type: 'trait1',
      value: 'value1',
    },
    {
      trait_type: 'trait2',
      value: 'value2',
    },
  ],
  properties: {
    files: [
      {
        uri: imageUri[0],
        type: 'image/jpeg',
      },
    ],
    category: 'image',
  },
}

ここに含まれるフィールドは以下の通りです。

name
トークンの名前。

description
NFTの説明。

image
これは以前アップロードした 「imageUri(または画像のオンラインロケーション)」に設定されます。

animation_url
これはアップロードした 「animation_url(または動画/glbファイルのオンラインロケーション)」に設定されます。

external_url
これは任意の外部アドレスにリンクします。通常はプロジェクトのウェブサイトです。

attributes
{trait_type: "value", "value": "value1"}のようなオブジェクトを使用します。

image
これは以前アップロードした 「imageUri(または画像のオンラインロケーション)」に設定されます。

properties
「files」フィールドを含み、{uri: string, type: mimeType}の  [] array  を受け取ります。また、「image」「audio」「video」「vfx」「html」 に設定できる category フィールドも含まれます。

// Call upon umi's `uploadJson()` function to upload our metadata to Arweave via Irys.

const metadataUri = await umi.uploader.uploadJson(metadata).catch((err) => {
  throw new Error(err)
})

すべてが計画通りに進んでいれば、エラーが発生しなかった場合、JSONファイルのURIが metadataUri に保存されているはずです。

Core Asset NFTのミント

ここからは、mpl-core パッケージの create 関数を使用して、Core Asset NFTを作成することができます。

const assetSigner = generateSigner(umi)

const tx = await create(umi, {
  asset: nftSigner,
  name: 'My NFT',
  uri: metadataUri,
}).sendAndConfirm(umi)

ログの詳細を出力する

  // Log out the signature and the links to the transaction and the NFT.
  console.log('\nNFT Created')
  console.log('View Transaction on Solana Explorer')
  console.log(`https://explorer.solana.com/tx/${signature}?cluster=devnet`)
  console.log('\n')
  console.log('View NFT on Metaplex Explorer')
  console.log(`https://core.metaplex.com/explorer/${nftSigner.publicKey}?env=devnet`)

フルコード 例

import { create } from '@metaplex-foundation/mpl-core'
import {
  createGenericFile,
  generateSigner,
  signerIdentity,
  sol,
} from '@metaplex-foundation/umi'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { base58 } from '@metaplex-foundation/umi/serializers'
import fs from 'fs'
import path from 'path'

const createNft = async () => {
  //
  // ** Setting Up Umi **
  //

  const umi = createUmi('https://api.devnet.solana.com')
    .use(mplCore())
    .use(
      irysUploader({
        // mainnet address: "https://node1.irys.xyz"
        // devnet address: "https://devnet.irys.xyz"
        address: 'https://devnet.irys.xyz',
      })
    )

  const signer = generateSigner(umi)

  umi.use(signerIdentity(signer))

  // Airdrop 1 SOL to the identity
  // if you end up with a 429 too many requests error, you may have to use
  // the filesystem wallet method or change rpcs.
  console.log('Airdropping 1 SOL to identity')
  await umi.rpc.airdrop(umi.identity.publicKey, sol(1))

  //
  // ** Upload an image to Arweave **
  //

  // use `fs` to read file via a string path.
  // You will need to understand the concept of pathing from a computing perspective.

  const imageFile = fs.readFileSync(
    path.join('./image.png')
  )

  // Use `createGenericFile` to transform the file into a `GenericFile` type
  // that umi can understand. Make sure you set the mimi tag type correctly
  // otherwise Arweave will not know how to display your image.

  const umiImageFile = createGenericFile(imageFile, 'image.png', {
    tags: [{ name: 'Content-Type', value: 'image/png' }],
  })

  // Here we upload the image to Arweave via Irys and we get returned a uri
  // address where the file is located. You can log this out but as the
  // uploader can takes an array of files it also returns an array of uris.
  // To get the uri we want we can call index [0] in the array.
  console.log('Uploading Image...')
  const imageUri = await umi.uploader.upload([umiImageFile]).catch((err) => {
    throw new Error(err)
  })

  console.log('imageUri: ' + imageUri[0])

  //
  // ** Upload Metadata to Arweave **
  //

  const metadata = {
    name: 'My NFT',
    description: 'This is an NFT on Solana',
    image: imageUri[0],
    external_url: 'https://example.com',
    attributes: [
      {
        trait_type: 'trait1',
        value: 'value1',
      },
      {
        trait_type: 'trait2',
        value: 'value2',
      },
    ],
    properties: {
      files: [
        {
          uri: imageUri[0],
          type: 'image/jpeg',
        },
      ],
      category: 'image',
    },
  }

  // Call upon umi's `uploadJson` function to upload our metadata to Arweave via Irys.

  console.log('Uploading Metadata...')
  const metadataUri = await umi.uploader.uploadJson(metadata).catch((err) => {
    throw new Error(err)
  })

  //
  // ** Creating the NFT **
  //

  // We generate a signer for the NFT
  const nftSigner = generateSigner(umi)

  console.log('Creating NFT...')
  const tx = await create(umi, {
    asset: nftSigner,
    name: 'My NFT',
    uri: metadataUri,
  }).sendAndConfirm(umi)

  // Finally we can deserialize the signature that we can check on chain.
  const signature = base58.deserialize(tx.signature)[0]

  // Log out the signature and the links to the transaction and the NFT.
  console.log('\nNFT Created')
  console.log('View Transaction on Solana Explorer')
  console.log(`https://explorer.solana.com/tx/${signature}?cluster=devnet`)
  console.log('\n')
  console.log('View NFT on Metaplex Explorer')
  console.log(`https://core.metaplex.com/explorer/${nftSigner.publicKey}?env=devnet`)
}

createNft()

この記事が気に入ったらサポートをしてみませんか?