非代替性トークン(NFT)
NFT の作成方法
NFT を作成するには、次のことを行う必要があります:
- Arweave のようなIPFSに画像をアップロード
- jsonメタデータをArweaveなどのIPFSにアップロード
- metaplexを呼び出してNFTのアカウントを作成
Arweaveにアップロード
import fs from "fs";
import Arweave from "arweave";
(async () => {
  const arweave = Arweave.init({
    host: "arweave.net",
    port: 443,
    protocol: "https",
    timeout: 20000,
    logging: false,
  });
  // Upload image to Arweave
  const data = fs.readFileSync("./code/nfts/arweave-upload/lowres-dog.png");
  const transaction = await arweave.createTransaction({
    data: data,
  });
  transaction.addTag("Content-Type", "image/png");
  const wallet = JSON.parse(fs.readFileSync("wallet.json", "utf-8"))
  
  await arweave.transactions.sign(transaction, wallet);
  const response = await arweave.transactions.post(transaction);
  console.log(response);
  const id = transaction.id;
  const imageUrl = id ? `https://arweave.net/${id}` : undefined;
  console.log("imageUrl", imageUrl);
  // Upload metadata to Arweave
  const metadata = {
    name: "Custom NFT #1",
    symbol: "CNFT",
    description: "A description about my custom NFT #1",
    seller_fee_basis_points: 500,
    external_url: "https://www.customnft.com/",
    attributes: [
      {
        trait_type: "NFT type",
        value: "Custom",
      },
    ],
    collection: {
      name: "Test Collection",
      family: "Custom NFTs",
    },
    properties: {
      files: [
        {
          uri: imageUrl,
          type: "image/png",
        },
      ],
      category: "image",
      maxSupply: 0,
      creators: [
        {
          address: "CBBUMHRmbVUck99mTCip5sHP16kzGj3QTYB8K3XxwmQx",
          share: 100,
        },
      ],
    },
    image: imageUrl,
  };
  const metadataRequest = JSON.stringify(metadata);
  const metadataTransaction = await arweave.createTransaction({
    data: metadataRequest,
  });
  metadataTransaction.addTag("Content-Type", "application/json");
  await arweave.transactions.sign(metadataTransaction, wallet);
  console.log("metadata txid", metadataTransaction.id);
  console.log(await arweave.transactions.post(metadataTransaction));
})();
// 1. Upload image to Arweave
const data = fs.readFileSync("./code/nfts/arweave-upload/lowres-dog.png");
const transaction = await arweave.createTransaction({
  data: data,
});
transaction.addTag("Content-Type", "image/png");
const wallet = JSON.parse(fs.readFileSync("wallet.json", "utf-8"))
await arweave.transactions.sign(transaction, wallet);
const response = await arweave.transactions.post(transaction);
console.log(response);
const id = transaction.id;
const imageUrl = id ? `https://arweave.net/${id}` : undefined;
// 2. Upload metadata to Arweave
const metadataRequest = JSON.stringify(metadata);
const metadataTransaction = await arweave.createTransaction({
  data: metadataRequest,
});
metadataTransaction.addTag("Content-Type", "application/json");
await arweave.transactions.sign(metadataTransaction, wallet);
await arweave.transactions.post(metadataTransaction);
from arweave.arweave_lib import Wallet, Transaction, API_URL
import json
# Load your arweave wallet
your_ar_wallet = Wallet('wallet.json')
with open('./code/nfts/arweave-upload/lowres-dog.png', 'rb') as f:
    img_in_bytes = f.read()
# Upload image to Arweave
transaction = Transaction(your_ar_wallet, data=img_in_bytes)
transaction.add_tag('Content-Type', 'image/png')
transaction.sign()
transaction.send()
image_url = API_URL+"/"+transaction.id
# Define metadata
metadata = {
    "name": "Custom NFT #1",
    "symbol": "CNFT",
    "description": "A description about my custom NFT #1",
    "seller_fee_basis_points": 500,
    "external_url": "https://www.customnft.com/",
    "attributes": [
        {
            "trait_type": "NFT type",
            "value": "Custom"
        }
    ],
    "collection": {
        "name": "Test Collection",
        "family": "Custom NFTs",
    },
    "properties": {
        "files": [
            {
                "uri": image_url,
                "type": "image/png",
            },
        ],
        "category": "image",
        "maxSupply": 0,
        "creators": [
            {
                "address": "CBBUMHRmbVUck99mTCip5sHP16kzGj3QTYB8K3XxwmQx",
                "share": 100,
            },
        ],
    },
    "image": image_url,
}
# Upload metadata to Arweave
meta_transaction = Transaction(your_ar_wallet, data=json.dumps(metadata))
meta_transaction.add_tag('Content-Type', 'text/html')
meta_transaction.sign()
meta_transaction.send()
metadata_url = API_URL+"/"+meta_transaction.id
print(metadata_url)
#  1. Load your arweave wallet
your_ar_wallet = Wallet('wallet.json')
#  2. Upload image to Arweave
with open('./code/nfts/arweave-upload/lowres-dog.png', 'rb') as f:
    img_in_bytes = f.read()
transaction = Transaction(your_ar_wallet, data=img_in_bytes)
transaction.add_tag('Content-Type', 'image/png')
transaction.sign()
transaction.send()
image_url = API_URL+"/"+transaction.id
#  3. Upload metadata to Arweave
meta_transaction = Transaction(your_ar_wallet, data=json.dumps(metadata))
meta_transaction.add_tag('Content-Type', 'text/html')
meta_transaction.sign()
meta_transaction.send()
metadata_url = API_URL+"/"+meta_transaction.id
NFTをミント
画像とメタデータを既にアップロードしている場合は、次のコードを使用してNFTを作成できます。
import { Metaplex, keypairIdentity } from "@metaplex-foundation/js";
import {
  Connection,
  clusterApiUrl,
  Keypair,
  LAMPORTS_PER_SOL,
} from "@solana/web3.js";
import dotenv from "dotenv";
dotenv.config();
(async () => {
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  const keypair = Keypair.fromSecretKey(
    Buffer.from(JSON.parse(process.env.SOLANA_KEYPAIR!.toString()))
  );
  const metaplex = new Metaplex(connection);
  metaplex.use(keypairIdentity(keypair));
  const feePayerAirdropSignature = await connection.requestAirdrop(
    keypair.publicKey,
    LAMPORTS_PER_SOL
  );
  await connection.confirmTransaction(feePayerAirdropSignature);
  const mintNFTResponse = await metaplex.nfts().create({
    uri: "https://ffaaqinzhkt4ukhbohixfliubnvpjgyedi3f2iccrq4efh3s.arweave.net/KUAIIbk6p8oo4XHRcq0U__C2r0mwQaNl0gQow4Qp9yk",
    maxSupply: 1,
  });
  console.log(mintNFTResponse);
})();
const mintNFTResponse = await metaplex.nfts().create({
  uri: "https://ffaaqinzhkt4ukhbohixfliubnvpjgyedi3f2iccrq4efh3s.arweave.net/KUAIIbk6p8oo4XHRcq0U__C2r0mwQaNl0gQow4Qp9yk",
  maxSupply: 1,
});
Note
ウォレットとは異なる作成者で NFT を作成することはできません。 作成者の問題が発生した場合は、メタデータに作成者として記載されていることを確認してください。
NFTメタデータの取得方法
Metaplex NFTには、Arweaveに保存されているメタデータがあります。Arweave メタデータを取得するには、Metaplex PDAを取得してアカウントデータをデコードする必要があります。
import { Metaplex, keypairIdentity } from "@metaplex-foundation/js";
import { Connection, clusterApiUrl, Keypair, PublicKey } from "@solana/web3.js";
(async () => {
  const connection = new Connection(clusterApiUrl("mainnet-beta"));
  const keypair = Keypair.generate();
  const metaplex = new Metaplex(connection);
  metaplex.use(keypairIdentity(keypair));
  const mintAddress = new PublicKey(
    "Ay1U9DWphDgc7hq58Yj1yHabt91zTzvV2YJbAWkPNbaK"
  );
  const nft = await metaplex.nfts().findByMint({ mintAddress });
  console.log(nft.json);
  /*
  {
    name: 'SMB #139',
    symbol: 'SMB',
    description: 'SMB is a collection of 5000 randomly generated 24x24 pixels NFTs on the Solana Blockchain. Each SolanaMonkey is unique and comes with different type and attributes varying in rarity.',
    seller_fee_basis_points: 600,
    image: 'https://arweave.net/tZrNpbFUizSoFnyTqP4n2e1Tf7WvP3siUwFWKMMid_Q',
    external_url: 'https://solanamonkey.business/',
    collection: { name: 'SMB Gen2', family: 'SMB' },
    attributes: [
      { trait_type: 'Attributes Count', value: 2 },
      { trait_type: 'Type', value: 'Solana' },
      { trait_type: 'Clothes', value: 'Orange Shirt' },
      { trait_type: 'Ears', value: 'None' },
      { trait_type: 'Mouth', value: 'None' },
      { trait_type: 'Eyes', value: 'Cool Glasses' },
      { trait_type: 'Hat', value: 'None' }
    ],
    properties: {
      files: [ [Object], [Object] ],
      category: 'image',
      creators: [ [Object] ]
    }
  }
  */
})();
const connection = new Connection(clusterApiUrl("mainnet-beta"));
const keypair = Keypair.generate();
const metaplex = new Metaplex(connection);
metaplex.use(keypairIdentity(keypair));
const mintAddress = new PublicKey(
  "Ay1U9DWphDgc7hq58Yj1yHabt91zTzvV2YJbAWkPNbaK"
);
const nft = await metaplex.nfts().findByMint({ mintAddress });
console.log(nft.json);
NFTの所有者を取得する方法
NFTのミントキーを持っている場合、そのミントキーの最大のトークンアカウントを覗き見ることで、現在の所有者を見つけることができます。
NFTの供給量は1であり、分割できないことを覚えておいてください。つまり、ある時点で1つのトークンアカウントだけがそのトークンを保持し、そのミントキーの他のすべてのトークンアカウントの残高は0になります。
最大のトークン アカウントが特定されると、その所有者を取得できます。
import { Connection, PublicKey } from "@solana/web3.js";
(async () => {
  const connection = new Connection("https://api.mainnet-beta.solana.com");
  const tokenMint = "9ARngHhVaCtH5JFieRdSS5Y8cdZk2TMF4tfGSWFB9iSK";
  const largestAccounts = await connection.getTokenLargestAccounts(
    new PublicKey(tokenMint)
  );
  const largestAccountInfo = await connection.getParsedAccountInfo(
    largestAccounts.value[0].address
  );
  console.log(largestAccountInfo.value.data.parsed.info.owner);
  /*
    PublicKey {
        _bn: <BN: 6ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a9>
    }
     */
})();
const connection = new Connection("https://api.mainnet-beta.solana.com");
const tokenMint = "9ARngHhVaCtH5JFieRdSS5Y8cdZk2TMF4tfGSWFB9iSK";
const largestAccounts = await connection.getTokenLargestAccounts(
  new PublicKey(tokenMint)
);
const largestAccountInfo = await connection.getParsedAccountInfo(
  largestAccounts.value[0].address
);
console.log(largestAccountInfo.value.data.parsed.info.owner);
NFTミントアドレスを取得する方法
Candy Machineの公開鍵がわかっている場合は、次のコードを使用して、そのCandy Machineから生成されたすべての NFT ミント アドレスのリストを取得できます。次のmemcmpフィルターを使用できることに注意してください。これは、v1では最初の作成者が常にCandy Machineのアドレスであるためです。
Candy Machine V1
import { Connection, clusterApiUrl, PublicKey } from "@solana/web3.js";
import bs58 from "bs58";
const connection = new Connection(clusterApiUrl("mainnet-beta"));
const MAX_NAME_LENGTH = 32;
const MAX_URI_LENGTH = 200;
const MAX_SYMBOL_LENGTH = 10;
const MAX_CREATOR_LEN = 32 + 1 + 1;
const MAX_CREATOR_LIMIT = 5;
const MAX_DATA_SIZE =
  4 +
  MAX_NAME_LENGTH +
  4 +
  MAX_SYMBOL_LENGTH +
  4 +
  MAX_URI_LENGTH +
  2 +
  1 +
  4 +
  MAX_CREATOR_LIMIT * MAX_CREATOR_LEN;
const MAX_METADATA_LEN = 1 + 32 + 32 + MAX_DATA_SIZE + 1 + 1 + 9 + 172;
const CREATOR_ARRAY_START =
  1 +
  32 +
  32 +
  4 +
  MAX_NAME_LENGTH +
  4 +
  MAX_URI_LENGTH +
  4 +
  MAX_SYMBOL_LENGTH +
  2 +
  1 +
  4;
const TOKEN_METADATA_PROGRAM = new PublicKey(
  "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);
const candyMachineId = new PublicKey("ENTER_YOUR_CANDY_MACHINE_ID_HERE");
const getMintAddresses = async (firstCreatorAddress: PublicKey) => {
  const metadataAccounts = await connection.getProgramAccounts(
    TOKEN_METADATA_PROGRAM,
    {
      // The mint address is located at byte 33 and lasts for 32 bytes.
      dataSlice: { offset: 33, length: 32 },
      filters: [
        // Only get Metadata accounts.
        { dataSize: MAX_METADATA_LEN },
        // Filter using the first creator.
        {
          memcmp: {
            offset: CREATOR_ARRAY_START,
            bytes: firstCreatorAddress.toBase58(),
          },
        },
      ],
    }
  );
  return metadataAccounts.map((metadataAccountInfo) =>
    bs58.encode(metadataAccountInfo.account.data)
  );
};
getMintAddresses(candyMachineId);
const getMintAddresses = async (firstCreatorAddress: PublicKey) => {
  const metadataAccounts = await connection.getProgramAccounts(
    TOKEN_METADATA_PROGRAM,
    {
      // The mint address is located at byte 33 and lasts for 32 bytes.
      dataSlice: { offset: 33, length: 32 },
      filters: [
        // Only get Metadata accounts.
        { dataSize: MAX_METADATA_LEN },
        // Filter using the first creator.
        {
          memcmp: {
            offset: CREATOR_ARRAY_START,
            bytes: firstCreatorAddress.toBase58(),
          },
        },
      ],
    }
  );
  return metadataAccounts.map((metadataAccountInfo) =>
    bs58.encode(metadataAccountInfo.account.data)
  );
};
getMintAddresses(candyMachineId);
Candy Machine V2
Candy Machine v2 を使用している場合は、最初にcandy_machineと Candy Machinev2アドレスをシードとして使用する単純なPDAである「Candy Machine Creator」アドレスにアクセスする必要があります。
import { Connection, clusterApiUrl, PublicKey } from "@solana/web3.js";
import bs58 from "bs58";
const connection = new Connection(clusterApiUrl("mainnet-beta"));
const MAX_NAME_LENGTH = 32;
const MAX_URI_LENGTH = 200;
const MAX_SYMBOL_LENGTH = 10;
const MAX_CREATOR_LEN = 32 + 1 + 1;
const MAX_CREATOR_LIMIT = 5;
const MAX_DATA_SIZE =
  4 +
  MAX_NAME_LENGTH +
  4 +
  MAX_SYMBOL_LENGTH +
  4 +
  MAX_URI_LENGTH +
  2 +
  1 +
  4 +
  MAX_CREATOR_LIMIT * MAX_CREATOR_LEN;
const MAX_METADATA_LEN = 1 + 32 + 32 + MAX_DATA_SIZE + 1 + 1 + 9 + 172;
const CREATOR_ARRAY_START =
  1 +
  32 +
  32 +
  4 +
  MAX_NAME_LENGTH +
  4 +
  MAX_URI_LENGTH +
  4 +
  MAX_SYMBOL_LENGTH +
  2 +
  1 +
  4;
const TOKEN_METADATA_PROGRAM = new PublicKey(
  "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);
const CANDY_MACHINE_V2_PROGRAM = new PublicKey(
  "cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ"
);
const candyMachineId = new PublicKey("ENTER_YOUR_CANDY_MACHINE_ID_HERE");
const getMintAddresses = async (firstCreatorAddress: PublicKey) => {
  const metadataAccounts = await connection.getProgramAccounts(
    TOKEN_METADATA_PROGRAM,
    {
      // The mint address is located at byte 33 and lasts for 32 bytes.
      dataSlice: { offset: 33, length: 32 },
      filters: [
        // Only get Metadata accounts.
        { dataSize: MAX_METADATA_LEN },
        // Filter using the first creator.
        {
          memcmp: {
            offset: CREATOR_ARRAY_START,
            bytes: firstCreatorAddress.toBase58(),
          },
        },
      ],
    }
  );
  return metadataAccounts.map((metadataAccountInfo) =>
    bs58.encode(metadataAccountInfo.account.data)
  );
};
const getCandyMachineCreator = async (
  candyMachine: PublicKey
): Promise<[PublicKey, number]> =>
  PublicKey.findProgramAddress(
    [Buffer.from("candy_machine"), candyMachine.toBuffer()],
    CANDY_MACHINE_V2_PROGRAM
  );
(async () => {
  const candyMachineCreator = await getCandyMachineCreator(candyMachineId);
  getMintAddresses(candyMachineCreator[0]);
})();
const getCandyMachineCreator = async (
  candyMachine: PublicKey
): Promise<[PublicKey, number]> =>
  PublicKey.findProgramAddress(
    [Buffer.from("candy_machine"), candyMachine.toBuffer()],
    CANDY_MACHINE_V2_PROGRAM
  );
const candyMachineCreator = await getCandyMachineCreator(candyMachineId);
getMintAddresses(candyMachineCreator[0]);
ウォレットからすべての NFT を取得するには?
ウォレットからすべてのNFTを取得する場合、すべてのトークンアカウントを取得してから、どれがNFTであるかを解析する必要があります。 これはすべて、Metaplex JSライブラリのfindDataByOwnerを使用すれば可能です。
import { Metaplex, keypairIdentity } from "@metaplex-foundation/js";
import { Connection, clusterApiUrl, Keypair, PublicKey } from "@solana/web3.js";
(async () => {
  const connection = new Connection(clusterApiUrl("mainnet-beta"), "confirmed");
  const keypair = Keypair.generate();
  const metaplex = new Metaplex(connection);
  metaplex.use(keypairIdentity(keypair));
  const owner = new PublicKey("2R4bHmSBHkHAskerTHE6GE1Fxbn31kaD5gHqpsPySVd7");
  const allNFTs = await metaplex.nfts().findAllByOwner({ owner });
  console.log(allNFTs);
})();
const connection = new Connection(clusterApiUrl("mainnet-beta"), "confirmed");
const keypair = Keypair.generate();
const metaplex = new Metaplex(connection);
metaplex.use(keypairIdentity(keypair));
const owner = new PublicKey("2R4bHmSBHkHAskerTHE6GE1Fxbn31kaD5gHqpsPySVd7");
const allNFTs = await metaplex.nfts().findAllByOwner({ owner });
console.log(allNFTs);
Candy Machine v2
Metaplex JS SDKは、コードによるCandy Machine v2の作成と更新をサポートするようになりました。これにより、開発者はCandy Machine v2プログラムと対話し、Candy Machineを作成、更新、削除したり、そこからNFTを作成したりできます。
Candy Machineの作成方法
import {
  keypairIdentity,
  Metaplex,
  sol,
  toBigNumber,
} from "@metaplex-foundation/js";
import { Keypair, Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
const createCandyMachine = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const payer = Keypair.generate();
  // request airdrop
  const airdropSignature = await connection.requestAirdrop(
    payer.publicKey,
    2 * LAMPORTS_PER_SOL
  );
  console.log(`Airdrop signature - ${airdropSignature}`);
  // creating metaplex instance with payer as the authority
  const metaplex = Metaplex.make(connection).use(keypairIdentity(payer));
  // creating a candy machine
  const { candyMachine } = await metaplex.candyMachinesV2().create({
    sellerFeeBasisPoints: 5, // 0.05% royalties
    price: sol(0.0001), // 0.0001 SOL
    itemsAvailable: toBigNumber(5), // 5 items available
  });
  console.log(`Candy Machine ID - ${candyMachine.address.toString()}`);
};
createCandyMachine();
const { candyMachine } = await metaplex.candyMachinesV2().create({
  sellerFeeBasisPoints: 5, // 0.05% royalties
  price: sol(0.0001), // 0.0001 SOL
  itemsAvailable: toBigNumber(5), // 5 items available
});
/**
 * #1 Candy Machine ID - HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR
 */
Candy Machineの削除方法
import {
  Metaplex,
  keypairIdentity,
  sol,
  toBigNumber,
} from "@metaplex-foundation/js";
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
const deleteCandyMachine = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const payer = Keypair.generate();
  // request airdrop
  const airdropSignature = await connection.requestAirdrop(
    payer.publicKey,
    2 * LAMPORTS_PER_SOL
  );
  console.log(`Airdrop signature - ${airdropSignature}`);
  // creating metaplex instance with payer as the authority
  const metaplex = Metaplex.make(connection).use(keypairIdentity(payer));
  // creating a candy machine
  const { candyMachine } = await metaplex.candyMachinesV2().create({
    sellerFeeBasisPoints: 5, // 0.05% royalties
    price: sol(0.0001), // 0.0001 SOL
    itemsAvailable: toBigNumber(5), // 5 items available
  });
  console.log(`Candy Machine ID - ${candyMachine.address.toString()}`);
  // deleting the candy machine
  const { response } = await metaplex.candyMachinesV2().delete({
    candyMachine,
  });
  console.log(`Delete Candy Machine signature - ${response.signature}`);
};
deleteCandyMachine();
// creating a candy machine
const { candyMachine } = await metaplex.candyMachinesV2().create({
  sellerFeeBasisPoints: 5, // 0.05% royalties
  price: sol(0.0001), // 0.0001 SOL
  itemsAvailable: toBigNumber(5), // 5 items available
});
console.log(`Candy Machine ID - ${candyMachine.address.toString()}`);
// deleting the candy machine
const { response } = await metaplex.candyMachinesV2().delete({
  candyMachine,
});
authorityを介してCandy Machineを探す方法
authorityが特定の公開鍵であるすべてのCandy Machineを見つけるには、type パラメータをauthorityとしてfindAllBy関数を使用します。
import { Connection, PublicKey } from "@solana/web3.js";
import { Metaplex } from "@metaplex-foundation/js";
const findCandyMachineViaAuthority = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const metaplex = new Metaplex(connection);
  const authority = new PublicKey(
    "9pr8wNxphx2PhBRbHKuH7YhPs5zbDuxx62UcDiayXxrw"
  );
  const candyMachines = await metaplex.candyMachinesV2().findAllBy({
    type: "authority",
    publicKey: authority,
  });
  candyMachines.map((candyMachine, index) => {
    console.log(`#${index + 1} Candy Machine ID - ${candyMachine.address}`);
  });
  /**
   * #1 Candy Machine ID - HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR
   */
};
findCandyMachineViaAuthority();
const candyMachines = await metaplex.candyMachinesV2().findAllBy({
  type: "authority",
  publicKey: authority,
});
candyMachines.map((candyMachine, index) => {
  console.log(`#${index + 1} Candy Machine ID - ${candyMachine.address}`);
});
/**
 * #1 Candy Machine ID - HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR
 */
ウォレットアドレスを使用してCandy Machineを見つける方法
ウォレット アドレスを介してCandy Machine オブジェクトを取得するには、 type パラメータをwalletとしてfindAllBy関数を使用します。 Candy Machine のウォレット アドレスは、エクスプローラーの [Anchor data] タブから取得できます。
import { Connection, PublicKey } from "@solana/web3.js";
import { Metaplex } from "@metaplex-foundation/js";
const findCandyMachineViaWallet = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const metaplex = new Metaplex(connection);
  const wallet = new PublicKey("9pr8wNxphx2PhBRbHKuH7YhPs5zbDuxx62UcDiayXxrw");
  const candyMachines = await metaplex.candyMachinesV2().findAllBy({
    type: "wallet",
    publicKey: wallet,
  });
  candyMachines.map((candyMachine, index) => {
    console.log(`#${index + 1} Candy Machine ID - ${candyMachine.address}`);
  });
  /**
   * #1 Candy Machine ID - HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR
   */
};
findCandyMachineViaWallet();
const candyMachines = await metaplex.candyMachinesV2().findAllBy({
  type: "wallet",
  publicKey: wallet,
});
candyMachines.map((candyMachine, index) => {
  console.log(`#${index + 1} Candy Machine ID - ${candyMachine.address}`);
});
アドレスを使用してCandy Machineを探す方法
アドレスを使用してCandy Machineを見つけるには、findByAddress関数を使用する必要があります。
import { Connection, PublicKey } from "@solana/web3.js";
import { Metaplex } from "@metaplex-foundation/js";
const findCandyMachineViaAddress = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const metaplex = new Metaplex(connection);
  const candyMachineId = new PublicKey(
    "HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR"
  );
  const candyMachine = await metaplex.candyMachinesV2().findByAddress({
    address: candyMachineId,
  });
};
findCandyMachineViaAddress();
const candyMachine = await metaplex.candyMachinesV2().findByAddress({
  address: candyMachineId,
});
Candy MachineからミントされたNFTを見つける方法
import { Connection, PublicKey } from "@solana/web3.js";
import { Metaplex } from "@metaplex-foundation/js";
const findCandyMachineMintedNfts = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const metaplex = new Metaplex(connection);
  const candyMachineId = new PublicKey(
    "HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR"
  );
  const candyMachine = await metaplex.candyMachinesV2().findMintedNfts({
    candyMachine: candyMachineId,
  });
};
findCandyMachineMintedNfts();
const candyMachine = await metaplex.candyMachinesV2().findMintedNfts({
  candyMachine: candyMachineId,
});
Candy Machineにアイテムを挿入する方法
import { Connection, PublicKey } from "@solana/web3.js";
import { Metaplex } from "@metaplex-foundation/js";
const insertItems = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const metaplex = new Metaplex(connection);
  const candyMachineId = new PublicKey(
    "HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR"
  );
  await metaplex.candyMachines().insertItems({
    candyMachineId,
    items: [
      { name: "My NFT #1", uri: "https://example.com/nft1" },
      { name: "My NFT #2", uri: "https://example.com/nft2" },
      { name: "My NFT #3", uri: "https://example.com/nft3" },
    ],
  });
};
insertItems();
await metaplex.candyMachines().insertItems({
  candyMachineId,
  items: [
    { name: "My NFT #1", uri: "https://example.com/nft1" },
    { name: "My NFT #2", uri: "https://example.com/nft2" },
    { name: "My NFT #3", uri: "https://example.com/nft3" },
  ],
});
Candy MachineからNFTをミントする方法
デフォルトでは、作成された NFT の所有者はmetaplex.identity().publicKeyになります。NFT を他のウォレットに発行する場合は、その公開鍵をnewOwnerパラメータとともに渡します。
import { Connection, PublicKey } from "@solana/web3.js";
import { Metaplex } from "@metaplex-foundation/js";
const mintNft = async () => {
  const connection = new Connection(
    "https://api.devnet.solana.com/",
    "confirmed"
  );
  const metaplex = new Metaplex(connection);
  const candyMachineId = new PublicKey(
    "HSZxtWx6vgGWGsWu9SouXkHA2bAKCMtMZyMKzF2dvhrR"
  );
  // by default, the owner of the minted nft would be `metaplex.identity().publicKey`. if you want to mint the nft to some other wallet, pass that public key along with the `newOwner` parameter
  const candyMachine = await metaplex.candyMachinesV2().mint({
    candyMachine: candyMachineId,
    // newOwner: new PublicKey("some-other-public-key");
  });
};
mintNft();
// by default, the owner of the minted nft would be `metaplex.identity().publicKey`. if you want to mint the nft to some other wallet, pass that public key along with the `newOwner` parameter
const candyMachine = await metaplex.candyMachinesV2().mint({
  candyMachine: candyMachineId,
  // newOwner: new PublicKey("some-other-public-key");
});