{"content":{"title":"如何使用 TypeScript 更新 Solana NFT 元数据","body":"## 概述 \r\n\r\n你是否正在为你的 NFT 收藏更新特征？修改版税/创作者以反映团队的变化？提升你的 PFP 收藏的艺术质量？无论出于何种原因，更新你创建的 NFT 的元数据，是任何 NFT 开发者都应具备的一个实用工具。\r\n\r\n#### 你将要做的 \r\n\r\n在本指南中，你将使用 Solana Web3 库和 Metaplex JS SDK，从终端更新 Solana devnet 上一个 NFT 的元数据。我们将涵盖三个步骤来更新你的 NFT 的元数据：\r\n\r\n1. 获取现有的 NFT\r\n2. 上传新元数据\r\n3. 更新 NFT\r\n\r\n#### 你将需要 \r\n\r\n- 安装 [Nodejs](https://nodejs.org/en/)（版本 16.15 或更高）\r\n\r\n- 具备 Typescript 经验，并安装最新版本的 [ts-node](https://www.npmjs.com/package/ts-node)（你可以通过在终端输入 **npm update -g typescript ts-node** 来更新到最新版本）\r\n\r\n\r\n在你开始之前\r\n\r\n确保你已在 Solana 的 devnet 上铸造了一个 NFT，并能访问权限钱包。你可以通过跟随这个 [指南：如何使用 Typescript 在 Solana 上铸造 NFT](https://www.quicknode.com/guides/solana-development/how-to-mint-an-nft-on-solana-using-typescript) 创建一个（[源代码](https://github.com/quiknode-labs/qn-guide-examples/blob/main/solana/mint-nft/app.ts)）。\r\n\r\n🚨 **确保在你 NFT 的配置中选择** _**mutable: true**_ **。只有可变的 NFT 元数据可以被更新。**\r\n\r\n## 设置你的项目 \r\n\r\n在终端中创建一个新的项目目录：\r\n\r\n```codeBlockLines_e6Vv\r\nmkdir update-metadata\r\ncd update-metadata\r\n\r\n```\r\n\r\n为你的应用创建一个文件 **app.ts**：\r\n\r\n```codeBlockLines_e6Vv\r\necho > app.ts\r\n\r\n```\r\n\r\n使用\"yes\"标志初始化你的项目，以使用新包的默认值：\r\n\r\n```codeBlockLines_e6Vv\r\nyarn init --yes\r\n#或者\r\nnpm init --yes\r\n\r\n```\r\n\r\n创建一个 **tsconfig.json**，启用 .json 导入：\r\n\r\n```codeBlockLines_e6Vv\r\ntsc -init --resolveJsonModule true\r\n\r\n```\r\n\r\n#### 安装 Solana Web3 依赖 \r\n\r\n我们需要添加 Solana Web3 和 SPL Token 库用于本练习。此外，我们将使用 [Metaplex 的 JS SDK](https://docs.metaplex.com/sdks/js/)。在你的终端中输入：\r\n\r\n```codeBlockLines_e6Vv\r\nyarn add @solana/web3.js@1 @metaplex-foundation/js\r\n#或者\r\nnpm install @solana/web3.js@1 @metaplex-foundation/js\r\n\r\n```\r\n\r\n#### 添加你的钱包和空投 SOL \r\n\r\n要跟随本指南，你需要具有相同的 [Solana 文件系统钱包](https://docs.solana.com/wallet-guide/file-system-wallet)（密钥对写入 **guideSecret.json** 文件），它是你 NFT 的权限方。如果你还没有 NFT 或 NFT 的权限钱包，请按照我们的 [指南：如何使用 Typescript 在 Solana 上铸造 NFT](https://www.quicknode.com/guides/solana-development/how-to-mint-an-nft-on-solana-using-typescript) 创建一个（[源代码](https://github.com/quiknode-labs/qn-guide-examples/blob/main/solana/mint-nft/app.ts)）。\r\n\r\n确保将你的钱包保存到项目目录中，命名为 **guideSecret.json**（你可以直接从 **mint-nft** 项目的目录中复制）。如果你需要 devnet SOL，请通过在下面输入你的钱包地址请求一些：\r\n\r\n🪂 请求 Devnet SOL\r\n\r\n空投 1 SOL (Devnet)\r\n\r\n设置后，你的环境应该看起来像这样：\r\n\r\n![](https://img.learnblockchain.cn/2025/02/25/1-9d04c962accf3a660453d790d67be746.png)\r\n\r\n## 设置你的应用 \r\n\r\n#### 导入必要的依赖 \r\n\r\n打开 **app.ts**，并在 _第1行_ 粘贴以下导入：\r\n\r\n```codeBlockLines_e6Vv\r\nimport { Connection, Keypair, PublicKey } from \"@solana/web3.js\";\r\nimport { Metaplex, keypairIdentity, bundlrStorage, Nft, Sft } from \"@metaplex-foundation/js\";\r\nimport secret from './guideSecret.json';\r\n\r\n```\r\n\r\n简化调试的日志\r\n\r\n现在你可以访问 RPC 端点的日志，帮助你更有效地排除问题。如果你遇到 RPC 调用问题，只需查看 QuickNode 仪表板上的日志，即可快速识别并解决问题。了解更多关于日志历史限制的信息请见 [我们的定价页面](https://www.quicknode.com/pricing#features)\r\n\r\n除了我们在前一步创建的钱包外，我们还导入了一些来自 Solana Web3 和 Metaplex JS 库的必要方法和类。\r\n\r\n#### 设置你的 QuickNode 端点 \r\n\r\n要在 Solana 上构建，你需要一个 API 端点与网络连接。你可以使用公共节点或部署和管理自己的基础设施；然而，如果你希望获得更快的响应时间，你可以将繁重的工作交给我们。\r\n\r\nQuickNode 现在接受 Solana 支付 🚀\r\n\r\n你现在可以 **用 USDC 在 Solana 上支付 QuickNode计划**。作为首个接受 Solana 付款的多链提供商，我们现在为开发者简化了这一过程——无论你是创建新账户还是管理现有账户。 [在这里了解更多关于使用 Solana 支付的信息](https://blog.quicknode.com/quicknode-now-accepts-solana-payments/)。\r\n\r\n看看为什么超过 50% 的 Solana 项目选择 QuickNode，你可以在 [这里注册一个免费账户](https://www.quicknode.com/signup?utm_source=internal&utm_campaign=guides&utm_content=how-to-update-solana-nft-metadata-using-typescript)。我们将使用一个 Solana Devnet 节点。\r\n\r\n复制 HTTP 提供程序链接：\r\n\r\n![](https://img.learnblockchain.cn/2025/02/25/2-383fb9313c992b3a4d2ab7551336fa9c.png)\r\n\r\n在 **app.ts** 中的导入语句下，声明你的 RPC，并建立 _Connection_ 到 Solana：\r\n\r\n```codeBlockLines_e6Vv\r\nconst QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';\r\nconst SOLANA_CONNECTION = new Connection(QUICKNODE_RPC);\r\n\r\n```\r\n\r\n#### 声明变量 \r\n\r\n你需要声明一些变量以运行你的脚本：\r\n\r\n- 你的源钱包（从你的私钥派生的密钥对）。\r\n- 你想要更新的 NFT 的铸造地址。\r\n- 一个 Metaplex 实例。\r\n- 你的新元数据。\r\n\r\n在 **SOLANA_CONNECTION** 下方添加以下声明，以建立我们将使用的钱包和我们将要更新的 NFT：\r\n\r\n```codeBlockLines_e6Vv\r\nconst WALLET = Keypair.fromSecretKey(new Uint8Array(secret));\r\nconst MINT_ADDRESS = '6cuiqk2VubzAgtUvFjBvosjCJUWG81EvW1F28qtX4EDn';\r\n\r\n```\r\n\r\n> 确保你包括的 NFT 的权限设置为你的 **WALLET**，并且该 NFT 是可变的。\r\n\r\n通过在 **Metaplex.make()** 中调用我们的 **SOLANA_CONNECTION** 来建立一个新的 Metaplex 实例。我们的实例将使用我们刚创建的 Keypair 和 **bundlrStorage**（用于使用 Solana 向 Arweave 上传文件的选项）：\r\n\r\n```codeBlockLines_e6Vv\r\nconst METAPLEX = Metaplex.make(SOLANA_CONNECTION)\r\n    .use(keypairIdentity(WALLET))\r\n    .use(bundlrStorage({\r\n        address: 'https://devnet.bundlr.network',\r\n        providerUrl: QUICKNODE_RPC,\r\n        timeout: 60000,\r\n    }));\r\n\r\n```\r\n\r\n通过包含我们的网络连接、钱包和存储路由，API 将使我们轻松地向 Solana 网络提交交易。\r\n\r\n#### 定义 NFT 元数据 \r\n\r\n我们将创建一个包含新元数据的 **NEW_METADATA** 对象。创建一个新的常量 **NEW_METADATA**，并包括以下属性：\r\n\r\n```codeBlockLines_e6Vv\r\nconst NEW_METADATA = {\r\n    imgType: 'image/png',\r\n    imgName: 'QuickPix New MetaName',\r\n    description: 'New description!',\r\n    attributes: [\\\r\n        {trait_type: 'Speed', value: 'Quicker'},\\\r\n        {trait_type: 'Type', value: 'Pixelated'},\\\r\n        {trait_type: 'Background', value: 'QuickNode Blue 2'}\\\r\n    ]\r\n};\r\n\r\n```\r\n\r\n随意用你自己的值替换名称、描述和属性。\r\n\r\n> 注意：你必须在这里包含所有特征（即使某些未更改），因为这些都将上传以替换现有元数据（例如，注意我们在这里包含了图像类型——即使它不会被改变，我们仍然必须在上传时再次包含它）。\r\n\r\n#### 创建并调用主函数 \r\n\r\n创建一个异步函数 **main**，用于执行所有步骤，并在下一行调用它：\r\n\r\n```codeBlockLines_e6Vv\r\nasync function main() {\r\n    console.log(`正在更新 NFT 的元数据: ${MINT_ADDRESS}}`);\r\n}\r\n\r\nmain();\r\n\r\n```\r\n\r\n这不会做太多，但你应该能够运行代码以确保此时没有错误：\r\n\r\n```codeBlockLines_e6Vv\r\nts-node app\r\n\r\n```\r\n\r\n你应该在控制台中看到一条日志，说明你即将更新我们 NFT 的元数据——那么我们开始吧！如果你遇到错误或有疑问，请在 [Discord](https://discord.gg/quicknode) 上给我们留言，我们将乐意提供帮助。\r\n\r\n## 获取 NFT \r\n\r\n在我们可以编辑 NFT 之前，我们必须先获取它。Metaplex 的 JS SDK 通过 **nfts().findByMint()** 使这变得简单。在你的 **main()** 函数中添加：\r\n\r\n```codeBlockLines_e6Vv\r\n    //步骤1 - 获取现有 NFT\r\n    console.log(`步骤1 - 获取现有 NFT`);\r\n    const nft = await METAPLEX.nfts().findByMint({ mintAddress: new PublicKey(MINT_ADDRESS) });\r\n    if (!nft || !nft.json?.image) {throw new Error(\"无法找到现有 NFT 或图像 URI！\")}\r\n    console.log(`   找到了 NFT！`)\r\n\r\n```\r\n\r\n**findByMint()** 方法应该返回一个 _Nft_ 类型的对象。如果查询没有返回值或关联图像，我们将抛出一个错误并终止脚本。否则，我们将记录 NFT 已找到的信息。\r\n\r\n## 上传元数据 \r\n\r\n接下来，我们需要将新的元数据上传到 Arweave，以获取可以与 NFT 关联的 URI。我们将使用在我们的 [指南：如何使用 Typescript 在 Solana 上铸造 NFT](https://www.quicknode.com/guides/solana-development/how-to-mint-an-nft-on-solana-using-typescript) 中创建的相同 **uploadMetadata()** 函数。创建一个新的函数 **uploadMetadata**，接受 5 个参数：imgUri，imgType，nftName，description 和 attributes：\r\n\r\n```codeBlockLines_e6Vv\r\nasync function uploadMetadata(imgUri: string, imgType: string, nftName: string, description: string, attributes: {trait_type: string, value: string}[]) {\r\n    console.log(`步骤2 - 上传元数据`);\r\n\r\n}\r\n\r\n```\r\n\r\n接下来，调用 **nfts().uploadMetadata()**。我们需要按照以下方式传递我们的参数：\r\n\r\n```codeBlockLines_e6Vv\r\n    const { uri } = await METAPLEX\r\n        .nfts()\r\n        .uploadMetadata({\r\n            name: nftName,\r\n            description: description,\r\n            image: imgUri,\r\n            attributes: attributes,\r\n            properties: {\r\n                files: [\\\r\n                    {\\\r\n                        type: imgType,\\\r\n                        uri: imgUri,\\\r\n                    },\\\r\n                ]\r\n            }\r\n        });\r\n    console.log('   元数据 URI:',uri);\r\n    return uri;\r\n\r\n```\r\n\r\n现在在 **main()** 中调用我们的函数。在 **uploadImage** 之后，使用 **NEW_METADATA** 填充参数调用 **uploadMetadata**：\r\n\r\n```codeBlockLines_e6Vv\r\n    //步骤2 - 上传元数据\r\n    const newUri = await uploadMetadata(nft.json.image, NEW_METADATA.imgType, NEW_METADATA.imgName, NEW_METADATA.description, NEW_METADATA.attributes);\r\n\r\n```\r\n\r\n如果你想测试你的函数，你可以记录 **newUri**，然后运行 **ts-node app**。当你准备好时，让我们更新这个 NFT 的元数据！\r\n\r\n## 更新 NFT 元数据 \r\n\r\n与我们之前的函数一样，Metaplex API 简化了这个过程，允许我们通过单个方法 **nfts().update()** 来更新 NFT。为了运行此方法，我们必须传递在第一步中获取的 **nft** 对象，以及我们的 **newUri**。\r\n\r\n在 **uploadMetadata()** 函数之后，在 **main()** 之前创建一个新的异步函数 **updateNft()**：\r\n\r\n```codeBlockLines_e6Vv\r\nasync function updateNft(nft:Nft|Sft, metadataUri: string, newName: string) {\r\n    console.log(`步骤3 - 更新 NFT`);\r\n}\r\n\r\n```\r\n\r\n最后，在我们的函数内部，调用 **nfts().update()**，传递我们的 **metadataUri** 和其他函数参数，并记录结果：\r\n\r\n```codeBlockLines_e6Vv\r\n    await METAPLEX\r\n        .nfts()\r\n        .update({\r\n            name: newName,\r\n            nftOrSft: nft,\r\n            uri: metadataUri\r\n        }, { commitment: 'finalized' });\r\n    console.log(`   成功！🎉`);\r\n    console.log(`   更新的 NFT: https://explorer.solana.com/address/${nft.address}?cluster=devnet`);\r\n\r\n```\r\n\r\n此函数使用 Metaplex Metadata Program 更新代币的链上元数据。请注意，与 **create()** 方法不同，**update()** 方法不返回任何值。\r\n\r\n> 如果你需要使用新的 NFT 对象，你需要运行 **const updatedNft = await metaplex.nfts().refresh(nft);** （为了我们的目的，我们现在不需要这样做，所以不使用它）。\r\n\r\n现在你所需要做的就是在 **main()** 中调用此函数，将 **CONFIG** 中的参数传递给它：\r\n\r\n```codeBlockLines_e6Vv\r\n    //步骤3 - 更新 NFT\r\n    updateNft(nft, newUri, NEW_METADATA.imgName);\r\n\r\n```\r\n\r\n## 🚀 运行你的代码！ \r\n\r\n你已经准备好了！如果你想与我们的代码进行对照，整个工作簿可在 GitHub 上找到 [这里](https://github.com/quiknode-labs/qn-guide-examples/blob/main/solana/mint-nft/updateMetadata.ts)。\r\n\r\n当你准备好时，在终端中输入：\r\n\r\n```codeBlockLines_e6Vv\r\nts-node app\r\n\r\n```\r\n\r\n是的！你看到类似这样的内容吗？\r\n\r\n![](https://img.learnblockchain.cn/2025/02/25/3-b867509262fd9426a2d4f1e11d9837a8.png)\r\n\r\n续写链接到 Solana Explorer。如果你向下滚动，你应该能够看到链上元数据，以及新的名称和我们上传的元数据的链接：\r\n\r\n![](https://img.learnblockchain.cn/2025/02/25/4-96d3da599db8756435e6aae454d8ccda.png)\r\n\r\n做得很好。\r\n\r\n## 下一步与总结 \r\n\r\n你现在有一个方便且可重复使用的脚本，可以直接从终端更新 NFT 元数据！我们非常想知道你计划如何使用它以及你正在进行的 NFT 项目。请在 [Discord](https://discord.gg/quicknode) 或 [Twitter](https://twitter.com/QuickNode) 上分享你的项目！\r\n\r\n#### 我们 ❤️ 反馈！ \r\n\r\n如果你对本指南有任何反馈或问题，请 [告诉我们](https://airtable.com/shrKKKP7O1Uw3ZcUB?prefill_Guide+Name=How%20to%20Update%20Solana%20NFT%20Metadata%20Using%20TypeScript)。我们很乐意听到你的声音！\r\n\r\n## 资源 \r\n\r\n- [Metaplex 的 JavaScript SDK](https://docs.metaplex.com/sdks/js/)\r\n- [指南：如何使用 TypeScript 在 Solana 上铸造 NFT](https://www.quicknode.com/guides/solana-development/how-to-mint-an-nft-on-solana-using-typescript)\r\n\r\n>- 原文链接： [quicknode.com/guides/sol...](https://www.quicknode.com/guides/solana-development/nfts/how-to-update-solana-nft-metadata-using-typescript)\r\n>- 登链社区 AI 助手，为大家转译优秀英文文章，如有翻译不通的地方，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/25306","address":null},"history":null,"timestamp":1740447421,"version":1}