
NFT Solana: Memodifikasi NFT Terkompresi (2023)
NFT Solana: Mengapa Modifikasi Diperlukan
Sebagai developer di Solana, berinteraksi dengan NFT terkompresi dapat terasa sangat sulit. Kini, hal tersebut dapat diatasi berkat kemampuan untuk memodifikasi atau mengubah NFT terkompresi melalui program Bubblegum.
Saat NFT terkompresi dicetak, bukti Merkle harus disertakan bersama instruksi transaksi untuk melakukan perubahan apa pun pada NFT tersebut (misalnya, transfer atau pembakaran). Bagi yang belum mengetahuinya, bukti Merkle adalah kumpulan hash yang dapat membuktikan bahwa leaf merupakan bagian dari tree.
Dalam panduan ini, kita akan membahas:
- Pentingnya modifikasi pada NFT terkompresi.
- Menyiapkan modifikasi pembakaran dan transfer untuk NFT terkompresi.
- Menjelaskan pentingnya Digital Asset Standard (DAS) API.
NFT Solana: Prasyarat
Sebelum memulai, pastikan Anda memiliki:
- Pemahaman dasar tentang JavaScript/TypeScript.
- Pengetahuan dasar tentang NFT terkompresi.
- Git yang sudah terinstal.
- npm atau yarn.
- Salinan repositori contoh yang tersedia di sini.
NFT Solana: Penyiapan Lingkungan
- Kloning repositori contoh kami:
git clone- Buka folder proyek:
cd compression-examples- Instal npm:
npm install- Buat file .env di direktori root:
API_KEY=YOUR_API_KEY
SECRET_KEY=YOUR_WALLET_SECRET_KEYDi dalamnya, masukkan kunci Helius API Anda dan kunci rahasia wallet pembayar. Pastikan wallet ini memiliki Solana untuk mendanai transaksi.
NFT Solana: Modifikasi
Modifikasi mengharuskan Anda memperoleh bukti terkini untuk instruksi, beserta kepemilikan, otoritas, dan hash kompresi aset saat ini. Anda perlu mengambil data ini dari Digital Asset Standard (DAS) API, yang menyederhanakan interaksi dengan aset terkompresi.
Daftar modifikasi yang saat ini tersedia melalui Bubblegum adalah:
- Cetak
- Transfer
- Bakar
- Delegasikan, Batalkan Delegasi
- Tebus, Batalkan Penebusan
- Dekompresi
- Verifikasi Kreator, Tetapkan dan Verifikasi Kreator
- Verifikasi Koleksi, Tetapkan dan Verifikasi Koleksi
Untuk berinteraksi dengan aset terkompresi, Anda perlu memastikan bahwa Anda mendapatkan:
- getAssetProof - Mengambil bukti untuk komputasi.
- getAsset - Mengambil hash kreator, hash data, nonce leaf, serta pemilik/delegasi leaf saat ini.
- getBubblegumAuthorityPDA - Alamat yang diturunkan dari program berdasarkan ID tree.
Dalam contoh ini, kita akan membahas pembakaran dan transfer NFT terkompresi yang akan kita cetak.
NFT: Transfer
Modifikasi transfer memungkinkan Anda memindahkan NFT terkompresi dari wallet satu pemilik ke wallet pemilik lainnya. Penjualan dan listing NFT terkompresi menggunakan instruksi ini untuk menampilkan penjualan di marketplace.
Untuk menyiapkannya di repositori yang ada, kita akan membuka file utils.ts dan melihat fungsi transferAsset.
Kita perlu memasukkan hal-hal berikut:
- Koneksi - Koneksi RPC Solana.
- Pemilik saat ini - Kunci publik pemilik NFT saat ini.
- Pemilik baru NFT - Kunci publik pemilik baru.
- ID aset - Memungkinkan kita memperoleh detail terkini tentang aset tertentu yang Anda masukkan.
Dalam contoh fungsi transferAsset di bawah ini, kita dapat melihat bahwa awalnya kita meminta bukti aset dan menyiapkan sesuatu yang disebut proofPath. Ini adalah permintaan ke DAS API yang mengembalikan bukti untuk aset yang ingin Anda transfer, lalu Anda menghitungnya agar dapat diteruskan ke instruksi transaksi.
export const transferAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
newOwner: Keypair,
assetId: string
) => {
console.log(
`Transfering asset ${assetId} from ${owner.publicKey.toBase58()} to ${newOwner.publicKey.toBase58()}.
This will depend on indexer api calls to fetch the necessary data.`
);
let assetProof = await connectionWrapper.getAssetProof(assetId);
if (!assetProof?.proof || assetProof.proof.length === 0) {
throw new Error("Proof is empty");
}
let proofPath = assetProof.proof.map((node: string) => ({
pubkey: new PublicKey(node),
isSigner: false,
isWritable: false,
}));
console.log("Successfully got proof path from RPC.");
// Additional code...
};Bukti aset perlu dikembalikan karena Anda harus mendapatkan status terkini dari aset terkompresi. Hal ini diperlukan untuk setiap transfer NFT terkompresi. Anda menghitungnya di proofPath agar dapat diteruskan ke instruksi transaksi yang akan segera kita lihat.
Setelah memiliki jalur bukti, kita dapat menggunakan getAsset pada DAS API untuk mendapatkan nonce leaf, delegasi leaf, hash data, dan hash kreator.
Kita dapat menyiapkannya seperti di bawah ini:
export const transferAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
newOwner: Keypair,
assetId: string
) => {
// Previous code //
// Calling getAsset from DAS
const rpcAsset = await connectionWrapper.getAsset(assetId);
console.log(
"Successfully got asset from RPC. Current owner: " +
rpcAsset.ownership.owner
);
if (rpcAsset.ownership.owner !== owner.publicKey.toBase58()) {
throw new Error(
`NFT is not owned by the expected owner. Expected ${owner.publicKey.toBase58()} but got ${
rpcAsset.ownership.owner
}.`
);
}
// Leaf nonce from getAsset call.
const leafNonce = rpcAsset.compression.leaf_id;
// Locating Tree Authority.
const treeAuthority = await getBubblegumAuthorityPDA(
new PublicKey(assetProof.tree_id)
);
// Leaf Owner/Delegate from getAsset call.
const leafDelegate = rpcAsset.ownership.delegate
? new PublicKey(rpcAsset.ownership.delegate)
: new PublicKey(rpcAsset.ownership.owner);
);
};Anda dapat melihat bahwa permintaan getAsset dibuat untuk mendapatkan pemilik/delegasi dan nonce leaf. Kita juga menentukan otoritas tree hanya dengan menggunakan ID tree (yang didapatkan dari permintaan assetProof).
Setelah semuanya ditentukan, kita dapat mulai membuat instruksi transaksi.
export const transferAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
newOwner: Keypair,
assetId: string
) => {
// Previous code //
// Transfer Instruction.
let transferIx = createTransferInstruction(
{
treeAuthority, // Tree authority
leafOwner: new PublicKey(rpcAsset.ownership.owner), // Current NFT owner
leafDelegate: leafDelegate, // Leaf delegate/owner returned
newLeafOwner: newOwner.publicKey, // New wallet to transfer our NFT.
merkleTree: new PublicKey(assetProof.tree_id), // Merkle tree public key.
logWrapper: SPL_NOOP_PROGRAM_ID, // NOOP program ID.
compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID, // Compression Program ID.
anchorRemainingAccounts: proofPath, // Proofs computed to pass in
},
{
root: bufferToArray(bs58.decode(assetProof.root)), // Root from getAssetProof returned
dataHash: bufferToArray(
bs58.decode(rpcAsset.compression.data_hash.trim()) // Data Hash from getAsset
),
creatorHash: bufferToArray(
bs58.decode(rpcAsset.compression.creator_hash.trim()) // Creator Hash from getAsset
),
nonce: leafNonce, // Leaf nonce from getAsset
index: leafNonce,
}
);
};Untuk melakukannya pada aset yang ditransfer, Anda perlu memasukkan semua variabel yang kita dapatkan dari getAsset, getAssetProof, dan SDK Metaplex: delegasi/pemilik leaf, hash data, root, dan nonce leaf.
Anda juga akan melihat bahwa kita memasukkan beberapa ID program. Ini adalah kunci publik untuk program kompresi dan noop yang diimpor di bagian atas file. Sebagai alternatif, Anda dapat memasukkannya sebagai kunci publik.
Setelah semuanya siap, kita dapat menyiapkan pengiriman instruksi transaksi:
export const transferAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
newOwner: Keypair,
assetId: string
) => {
// Previous code //
const tx = new Transaction().add(transferIx);
tx.feePayer = owner.publicKey;
try {
const sig = await sendAndConfirmTransaction(
connectionWrapper,
tx,
[owner],
{
commitment: "confirmed",
skipPreflight: true,
}
);
return sig;
} catch (e) {
console.error("Failed to transfer compressed asset", e);
throw e;
}
};Dalam kode di atas, kita menentukan transaksi menggunakan tx dan menambahkan tipe Transaction untuk transferIx dari solana/web3.js .
Kemudian, kita mengirimkannya dengan memasukkan:
- Koneksi Solana
- Instruksi Transaksi
- Pembayar
- Komitmen
Sekarang kita dapat mengirimkan transaksi ini dengan menjalankan:
npm run e2eFungsi ini akan mencetak NFT terkompresi beserta koleksinya, lalu mentransfernya ke wallet yang ditentukan.
Catat ID aset karena kita akan menggunakannya untuk modifikasi pembakaran.
Berikut adalah keseluruhan fungsi transferAsset:
export const transferAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
newOwner: Keypair,
assetId: string
) => {
console.log(
`Transfering asset ${assetId} from ${owner.publicKey.toBase58()} to ${newOwner.publicKey.toBase58()}.
This will depend on indexer api calls to fetch the necessary data.`
);
let assetProof = await connectionWrapper.getAssetProof(assetId);
if (!assetProof?.proof || assetProof.proof.length === 0) {
throw new Error("Proof is empty");
}
let proofPath = assetProof.proof.map((node: string) => ({
pubkey: new PublicKey(node),
isSigner: false,
isWritable: false,
}));
console.log("Successfully got proof path from RPC.");
const rpcAsset = await connectionWrapper.getAsset(assetId);
console.log(
"Successfully got asset from RPC. Current owner: " +
rpcAsset.ownership.owner
);
if (rpcAsset.ownership.owner !== owner.publicKey.toBase58()) {
throw new Error(
`NFT is not owned by the expected owner. Expected ${owner.publicKey.toBase58()} but got ${
rpcAsset.ownership.owner
}.`
);
}
const leafNonce = rpcAsset.compression.leaf_id;
const treeAuthority = await getBubblegumAuthorityPDA(
new PublicKey(assetProof.tree_id)
);
const leafDelegate = rpcAsset.ownership.delegate
? new PublicKey(rpcAsset.ownership.delegate)
: new PublicKey(rpcAsset.ownership.owner);
let transferIx = createTransferInstruction(
{
treeAuthority,
leafOwner: new PublicKey(rpcAsset.ownership.owner),
leafDelegate: leafDelegate,
newLeafOwner: newOwner.publicKey,
merkleTree: new PublicKey(assetProof.tree_id),
logWrapper: SPL_NOOP_PROGRAM_ID,
compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
anchorRemainingAccounts: proofPath,
},
{
root: bufferToArray(bs58.decode(assetProof.root)),
dataHash: bufferToArray(
bs58.decode(rpcAsset.compression.data_hash.trim())
),
creatorHash: bufferToArray(
bs58.decode(rpcAsset.compression.creator_hash.trim())
),
nonce: leafNonce,
index: leafNonce,
}
);
const tx = new Transaction().add(transferIx);
tx.feePayer = owner.publicKey;
try {
const sig = await sendAndConfirmTransaction(
connectionWrapper,
tx,
[owner],
{
commitment: "confirmed",
skipPreflight: true,
}
);
return sig;
} catch (e) {
console.error("Failed to transfer compressed asset", e);
throw e;
}
};NFT: Pembakaran
Membakar cNFT akan menghapus NFT dari Merkle tree. Hal ini memungkinkan berbagai kasus penggunaan, seperti membakar aset untuk mendapatkan hadiah, menghapus aset spam, atau memenuhi kebutuhan khusus. Cara ini digunakan dalam pencetakan Tensor, ketika 10 cNFT dibakar agar 1 cNFT baru dapat dicetak.
Untuk membakar NFT terkompresi, kita perlu memasukkan hal-hal berikut:
- Koneksi - Koneksi RPC Solana.
- Pemilik saat ini - Kunci publik pemilik NFT saat ini.
- ID aset - Memungkinkan kita memperoleh detail terkini tentang aset tertentu yang Anda masukkan.
Kita dapat melihatnya di utils.ts pada burnAsset:
export const burnAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
assetId?: string
) => {
let assetProof = await connectionWrapper.getAssetProof(assetId);
const rpcAsset = await connectionWrapper.getAsset(assetId);
const leafNonce = rpcAsset.compression.leaf_id;
let proofPath = assetProof.proof.map((node: string) => ({
pubkey: new PublicKey(node),
isSigner: false,
isWritable: false,
}));
const treeAuthority = await getBubblegumAuthorityPDA(
new PublicKey(assetProof.tree_id)
);
const leafDelegate = rpcAsset.ownership.delegate
? new PublicKey(rpcAsset.ownership.delegate)
: new PublicKey(rpcAsset.ownership.owner);
// Remaining code //
}Proses ini sama seperti transferAsset karena menggunakan getAssetProof untuk mendapatkan root dan ID tree. Anda juga memanggil getAsset untuk mendapatkan hash kreator, hash data, nonce leaf, dan pemilik saat ini.
Dengan demikian, Anda dapat dengan mudah mengetahui nilai apa saja yang perlu didapatkan di sini untuk memodifikasi aset terkompresi Anda.
Sekarang, kita dapat menyiapkan instruksi transaksi di bawah kode ini:
export const burnAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
assetId?: string
) => {
// Previous code //
// Burn transaction instruction //
const burnIx = createBurnInstruction(
{
treeAuthority,
leafOwner: new PublicKey(rpcAsset.ownership.owner),
leafDelegate,
merkleTree: new PublicKey(assetProof.tree_id),
logWrapper: SPL_NOOP_PROGRAM_ID,
compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
anchorRemainingAccounts: proofPath,
},
{
root: bufferToArray(bs58.decode(assetProof.root)),
dataHash: bufferToArray(
bs58.decode(rpcAsset.compression.data_hash.trim())
),
creatorHash: bufferToArray(
bs58.decode(rpcAsset.compression.creator_hash.trim())
),
nonce: leafNonce,
index: leafNonce,
}
);
// Later code... //
};Setelah menyiapkannya untuk pembakaran, kita dapat mengirimkan transaksi dengan cara yang sangat mirip dengan instruksi transfer:
export const burnAsset = async (
connectionWrapper: WrappedConnection,
owner: Keypair,
assetId?: string
) => {
// Previous code //
const tx = new Transaction().add(burnIx);
tx.feePayer = owner.publicKey;
try {
const sig = await sendAndConfirmTransaction(
connectionWrapper,
tx,
[owner],
{
commitment: "confirmed",
skipPreflight: true,
}
);
return sig;
} catch (e) {
console.error("Failed to burn compressed asset", e);
throw e;
}
}Kemudian, kita mengirimkannya dengan memasukkan:
- Koneksi Solana
- Instruksi Transaksi
- Pembayar
- Komitmen
Setelah fungsi ini dijalankan, aset dengan ID yang Anda berikan akan dibakar. Tindakan ini akan menghapus data aset dari tree dan menerapkan flag burnt=true pada aset terkompresi. Secara default, aset yang telah dibakar ini akan tetap dikembalikan saat Anda menggunakan DAS API.
Sekarang, Anda dapat menjalankan perintah berikut di terminal:
npm run burn -- --assetId=NFT Solana: Kesimpulan
NFT terkompresi menawarkan cara yang dinamis untuk berinteraksi dengan ekosistem NFT di Solana. Melalui bukti Merkle yang diperoleh dari DAS API dan instruksi transaksi yang akurat, developer dapat memodifikasi dan berinteraksi dengan aset digital unik ini. Dengan memahami detail modifikasi transfer dan pembakaran, developer dapat membangun aplikasi yang lebih andal.
Artikel Terkait
Berlangganan Helius
Ikuti perkembangan terbaru dalam pengembangan Solana dan dapatkan pembaruan saat kami memublikasikan postingan


