{"content":{"title":"Solana 开发全面指南：使用 React、Anchor、Rust 和 Phantom 进行全栈开发","body":">- 原文链接：https://medium.com/@Anatolii_Zhadan/the-complete-guide-to-full-stack-solana-development-with-react-anchor-rust-and-phantom-18a1e1bdbb3b\r\n>- 译者：[AI翻译官](https://learnblockchain.cn/people/19584)，校对：[翻译小组](https://learnblockchain.cn/people/412)\r\n>- 本文永久链接：[learnblockchain.cn/article…](https://learnblockchain.cn/article/8552)\r\n    \r\n## Solana介绍\r\n\r\n### Solana 及其优势的概述\r\n\r\n为什么使用 Solana？它便宜、快速且方便！Solana 以每秒高达 65,000 笔交易的惊人速度著称，超过了比特币和以太坊等传统领导者。这种性能是通过独特的历史证明（PoH）共识机制以及权益证明（PoS）实现的，大大降低了交易延迟，提高了整体网络效率。\r\n\r\nSolana 上的交易成本令人惊讶地低，平均费用约为$0.00025，使其成为开发人员和用户的经济选择。这种效率并不是以牺牲环境为代价的：Solana 的能源消耗很低，与进行几次谷歌搜索所用的能量相当，体现了其对可持续性的承诺。\r\n\r\nSolana 的生态系统受益于与科技巨头的强大合作伙伴关系和对不断创新的承诺，如 Firedancer 等更新进一步提升了其性能和可扩展性。尽管存在网络不稳定等挑战，Solana 不断改进和战略合作强调了其作为区块链技术主导力量的潜力。\r\n\r\n## 基本要求\r\n\r\n\r\n### 编程技术栈\r\n\r\n\r\n开发 Solana 的先决条件是具备编程知识并熟悉区块链概念。以下是针对具有先前区块链经验的人的精炼概述:\r\n\r\n**JavaScript**  \r\n- **需求:** 用于通过 Solana Web3.js 库与 Solana 区块链进行交互，实现发送交易和查询区块链数据等通信。  \r\n- **熟练程度:** 对 JavaScript 的扎实掌握，包括现代的 ES6+语法和异步编程，对于在 Solana 上进行有效开发至关重要。\r\n\r\n**React**  \r\n- **必要:** 强烈推荐用于在 Solana 上为去中心化应用（dApps）创建用户界面。React 使得创建与区块链交互的动态、响应式 Web 应用变得容易。  \r\n- **熟练程度:** 熟悉 React 基础知识（组件、钩子、状态管理）将会有所帮助。在 React 应用中集成 Solana 需要了解如何在 React 应用程序的上下文中使用 Solana 的 Web3.js 库。\r\n\r\n**Rust:** 对于在 Solana 上开发链上程序，了解 Rust 语言将非常有用。Solana 智能合约（或程序）主要使用 Rust 编写，利用其性能和安全性。\r\n\r\n- **开发工具和环境:** 了解 Solana 开发工具，包括 Anchor 框架以简化智能合约开发，将会有所帮助。了解如何在 Solana 网络（devnet、testnet、mainnet-beta）上部署应用程序对于实际部署至关重要。\r\n\r\n### 基本区块链概念\r\n\r\n- **必要:** 理解区块链的基本原则是基础性的。这包括共识机制、智能合约（在 Solana 中称为程序）、交易、钱包和加密密钥的知识。\r\n\r\n- **Solana 特定概念:** 熟悉 Solana 的独特特性，如历史证明（**PoH**）、共识机制，以及 Solana 程序和账户的结构是必须的。熟悉 Solana 程序库（**SPL**）和命令行工具，如 Solana **CLI**进行测试和部署也是推荐的。  \r\n\r\n这些信息强调了，虽然假定熟悉区块链基础知识，但 Solana 开发呈现出开发人员必须学习的独特方面和工具。对于那些新手来说，使用现有的 Solana 软件和 SDK，如 Solana-web3.js，可以是一个实用的起点，然后再深入研究 Rust 软件开发。\r\n\r\n### 必要软件\r\n\r\n\r\n为 Solana 开发设置具备必要软件的环境非常重要。基本软件要求包括**Node.js**、**Yarn**和**Git**。这些工具用于运行和管理 Solana 项目，运行测试和进行版本控制。\r\n\r\n**Node.js** 用于执行服务器端 JavaScript 代码，并使用各种 JavaScript 库和框架与 Solana 区块链进行交互。你可以从其 [**官方网站**](https://nodejs.org/) 安装 Node.js。\r\n\r\n**Yarn** 是一个包管理器，有助于管理项目依赖关系。它用于安装、更新和管理项目所需的库和包。可以通过在终端中运行 npm install -g yarn 来使用 Node.js 附带的 npm 包管理器安装 Yarn。有关 Yarn 的更多信息可以在其 [**官方网站**](https://yarnpkg.com/) 找到。\r\n\r\n**Git** 是一个版本控制系统，允许你跟踪代码库的更改并与其他用户协作。对于管理复杂项目的开发至关重要。你可以从其 [**官方网站**](https://git-scm.com/) 安装 Git。\r\n\r\n除了这些软件工具，为了开发 Solana，你还需要安装 Solana CLI（命令行界面），这是与 Solana 区块链进行交互所必需的。安装 Solana CLI 的说明取决于你的操作系统，但通常涉及执行一个 shell 命令，该命令会直接找到并安装 Solana 工具。有关安装 Solana CLI 的详细说明可以在 Solana 文档 [**这里**](https://docs.solana.com/cli/install-solana-cli-tools) 找到。\r\n\r\n这些工具构成了 Solana 开发环境的支柱，使你能够在 Solana 区块链上高效构建、测试和部署应用程序。\r\n\r\n不要忘记安装 [**Phantom 钱包**](https://phantom.app/) 以使用 Solana。\r\n\r\n## 第 1 部分: 理解 Solana\r\n\r\n\r\nSolana 是一种以其可扩展性和速度而闻名的高性能区块链平台，这在很大程度上归功于一种称为历史证明（**PoH**）的独特共识机制。与比特币中使用的工作证明（**PoW**）或许多其他区块链中使用的权益证明（**PoS**）等传统共识机制不同，**PoH**是一种记录事件顺序和确认交易的新方法。\r\n\r\n### **历史证明（PoH）:**\r\n\r\n**PoH**不是一种独立的共识机制，而是与 Solana 中的**PoS**共同工作以提高其效率。它使用加密时间戳创建可验证的事件序列，使验证者能够就交易的时间和顺序达成一致，而无需它们之间进行大量通信。这是通过创建一个哈希链来实现的，其中每个哈希是前一个哈希的函数，实际上充当了分散式时钟。这种方法为每笔交易提供了安全和准确的时间戳，促进了对区块链状态的快速共识。\r\n\r\n**PoH 的优势:**\r\n\r\n- **可扩展性:** 通过有效地组织交易并减少验证者之间通信的需求来验证事件顺序，**PoH**使 Solana 能够处理数千笔交易每秒。  \r\n- **低延迟:** 由于简化的验证过程，交易处理速度快，提高了在 Solana 上运行的**dApps**和服务的可用性。  \r\n- **安全性:** **PoH**的加密特性与 Solana 中的**PoS**共识使网络免受攻击。  \r\n- **能源效率:** **PoH**比**PoW**更环保，因为它不需要耗费大量能源进行挖矿活动。\r\n\r\n### Solana 架构\r\n\r\nSolana 架构旨在最大化吞吐量并最小化交易确认时间。通过几项创新技术实现了这一目标，包括用于交易转发的 Gulf Stream 协议，用于智能合约并行处理的 Sealevel，以及用于区块传播的 Turbine。结合**PoH**，这些技术使 Solana 能够在区块链网络中实现前所未有的速度和可扩展性。\r\n\r\nSolana 的共识机制是**PoH**用于时间记录和**PoS**用于交易确认和网络安全的组合。这种组合提供了高度的去中心化和可扩展性，将 Solana 定位为去中心化应用（**dApps**）、去中心化金融（**DeFi**）和非同质化代币（**NFTs**）的竞争平台。\r\n\r\n**PoH**的引入代表了区块链技术的重大进步，消除了与可扩展性和交易速度相关的常见瓶颈。随着区块链技术的不断发展，Solana 在共识方面的创新方法可以激发这一领域的新发展。\r\n\r\n## Solana 开发的关键概念（账户、程序、交易）\r\n\r\n\r\nSolana 开发围绕着三个关键概念展开：账户、程序和交易。理解这些元素对于在 Solana 区块链上构建应用程序至关重要。\r\n\r\n### 账户\r\n\r\n\r\n账户是 Solana 区块链上的存储位置，可以存储数据、SOL（Solana 的原生货币）或智能合约代码。每个账户都有一个公钥作为其唯一标识符。账户可以是不同类型，包括用户钱包、程序账户（包含可执行代码）和数据存储账户。这些账户用于管理 Solana 区块链上的状态、所有权和权限。Solana 的账户模型与其他区块链（如以太坊）的账户模型略有不同，因为它要求账户有足够的 SOL 来支付“**租金**”或数据存储成本。\r\n\r\n### 程序（program）\r\n\r\n\r\n在 Solana 中，程序与其他区块链上的智能合约是同义词，但它们被设计得更加灵活和高效。程序是无状态的，这意味着它们本身不存储任何状态。相反，所有状态都存储在程序交互的账户中。Solana 程序独特之处在于它们可以更新，从而实现更具动态性和适应性的应用程序。这些程序处理交易发送的指令，并可以通过称为跨程序调用的功能与其他程序交互，从而实现 Solana 生态系统中的互操作性。\r\n\r\n###  交易\r\nSolana 中的交易是用户与程序交互的手段，类似于传统编程中的函数调用。交易包含一个或多个指令，告诉程序要做什么，比如转移 SOL、更改账户数据或调用程序逻辑。每个交易都使用一个或多个私钥进行签名，以确认交易发起者有权执行指定的操作。交易可以更改账户中存储的状态，如果交易的任何部分失败，整个交易将被取消，确保原子性。这种模型使 Solana 能够快速高效地处理交易，有助于实现其高吞吐量。\r\n\r\n对于来自其他区块链或新手区块链开发的开发人员，理解这些概念对于成功构建 Solana 平台至关重要。该平台独特的共识（历史证明）方法，结合账户和程序模型，允许实现在其他区块链生态系统中很少见的可扩展性和效率水平。要深入了解 Solana 开发，请探索官方 Solana 文档和资源，如 QuickNode 和 DEV 社区的帖子，这些资源可以提供全面的指南和教程。\r\n\r\n## 第 2 部分：配置开发环境\r\n\r\n### 安装 Solana CLI 工具：\r\n\r\n\r\n你可以按照[链接](https://docs.solanalabs.com/cli/install)中的官方指南进行操作。\r\n\r\n### 设置本地 Solana 区块链（测试验证器）：\r\n\r\n\r\n要配置 Solana 本地区块链（测试验证器），首先确保已安装 Solana CLI。然后在新的终端窗口中运行以下命令\r\n```\r\nsolana-test-validator\r\n```\r\n\r\n这将在你的计算机上启动一个本地区块链集群。使用\r\n```\r\nsolana config set url localhost\r\n```\r\n\r\n命令配置 Solana CLI 与本地集群通信。使用 solana-keygen new 创建一个文件系统钱包，以部署程序和管理交易\r\n```\r\nsolana-keygen new outfile /path/to/save/your/program-keypair.json  \r\n#示例  \r\n#solana-keygen new -o /Users/user/.config/solana/id.json \r\n```\r\n\r\n最后，使用**solana airdrop 2**将 SOL 代币转移到你的钱包，以支付交易费用。有关详细步骤，请参阅 [**Solana 指南**](https://solana.com/developers/guides/getstarted/setup-local-development) 以设置本地开发环境。\r\n\r\n### 为什么选择 Anchor？\r\n\r\n\r\nAnchor 框架通过在核心 Solana 开发工具之上提供一层抽象来简化 Solana 智能合约的开发。它提供工具和运行时环境，可在 Solana 区块链上高效构建、测试和部署程序。Anchor 旨在简化开发过程，减少样板代码，并引入熟悉的编程模式到 Solana 中，使其更易于开发人员熟悉其他智能合约平台。通过提供基于 Rust 的框架，自动化 Solana 程序开发中涉及的许多底层细节，Anchor 使开发人员能够专注于应用程序的逻辑，而不是区块链本身的复杂性。\r\n\r\n## 第 3 部分：使用 Rust 和 Anchor 构建你的第一个 Solana 程序\r\n\r\n**前提条件：**  \r\n\r\n1. 对 Rust 语言的基本编程理解。  \r\n2. 在计算机上安装了 [Solana CLI](https://docs.solanalabs.com/cli/install) 和[Rust](https://www.rust-lang.org/tools/install)。\r\n\r\n### 步骤 1：使用 Anchor 创建新项目：\r\n\r\n\r\n**1. 安装 Anchor：**\r\n\r\n如果尚未安装 Anchor，请运行以下命令：\r\n\r\n```\r\ncargo install git https://github.com/project-serum/anchor anchor-cli locked\r\n```\r\n\r\n\r\n\r\n\r\n\r\nAnchor 通过为 Sealevel Solana 运行时环境提供框架来简化 Solana 开发。\r\n\r\n**2. 初始化新的 Anchor 项目：**\r\n\r\n使用以下命令初始化一个新的 Anchor 项目：\r\n\r\n```\r\nanchor init my_solana_dapp javascript\r\n```\r\n\r\n\r\n\r\n标志来创建一个新项目。javascript 标志设置了一个带有 JavaScript 示例的项目，以便与前端集成。\r\n\r\n注意**programs/**目录，你的 Rust 程序将存放在其中，以及**tests/**目录，用于程序测试。\r\n\r\n3. 进入项目目录：\r\n\r\n   ```\r\n   cd my_solana_dapp\r\n   ```\r\n\r\n   \r\n\r\n### 步骤 2：编写程序逻辑\r\n\r\n\r\n1. 打开**lib.rs**文件：通过以下命令找到此文件：\r\n\r\n   ```\r\n   cd programs  \r\n   cd my_solana_dapp  \r\n   cd src\r\n   ```\r\n\r\n   \r\n\r\n在这里，你将为你的程序编写逻辑。1. 定义你的程序：将**lib.rs**的内容替换为以下 Rust 代码。此示例创建一个简单的程序，用于写入一个数字。\r\n\r\n```rust\r\n//after declare_id replace logic with it\r\n#[program]  \r\npub mod my_solana_dapp {  \r\n    use super::\\*;  \r\n    pub fn create_greeting(ctx: Context<CreateGreeting>) -> Result<()> {  \r\n        let greeting_account = &mut ctx.accounts.greeting_account;  \r\n        greeting_account.counter = 0;  \r\n        Ok(())  \r\n    }\r\n\r\npub fn increment_greeting(ctx: Context<IncrementGreeting>) -> Result<()> {  \r\n        let greeting_account = &mut ctx.accounts.greeting_account;  \r\n        greeting_account.counter += 1;  \r\n        Ok(())  \r\n    }  \r\n}\r\n\r\n#[derive(Accounts)]  \r\npub struct CreateGreeting<'info> {  \r\n    #[account(init, payer = user, space = 8 + 8)]  \r\n    pub greeting_account: Account<'info, GreetingAccount>,  \r\n    #[account(mut)]  \r\n    pub user: Signer<'info>,  \r\n    pub system_program: Program<'info, System>,  \r\n}\r\n\r\n#[derive(Accounts)]  \r\npub struct IncrementGreeting<'info> {  \r\n    #[account(mut)]  \r\n    pub greeting_account: Account<'info, GreetingAccount>,  \r\n}\r\n\r\n#[account]  \r\npub struct GreetingAccount {  \r\n    pub counter: u64,  \r\n}\r\n```\r\n\r\n3. 理解代码：该程序由两个主要函数**create_greeting**和**increment_greeting**组成，以及用于帐户管理的必要数据结构。以下是其组成部分的详细说明：\r\n\r\n**程序声明：**\r\n\r\n`#[program]` 标记`my_solana_dapp`模块包含智能合约入口点。在此模块中定义了合约的业务逻辑。\r\n\r\n函数\r\n\r\n`create_greeting(ctx: Context<CreateGreeting>) -> Result<()>`：此函数使用计数器设置为 0 初始化一个新的“greeting”帐户。它接受一个包含此操作所需帐户的上下文。\r\n\r\n`increment_greeting(ctx: Context<IncrementGreeting>) -> Result<()>`：此函数将指定“greeting”帐户中的计数器增加 1。它还接受指定要增加的帐户的上下文。\r\n\r\n**帐户结构：**\r\n\r\n`#[derive(Accounts)]`：此宏用于指定每个函数期望的帐户。它帮助 Anchor 执行安全性和所有权检查。\r\n\r\n`CreateGreeting<’info>`：此结构定义了 create_greeting 函数所需的帐户。它包括要创建的新 greeting 帐户（**greeting_account**）、将支付以创建帐户并签署交易的用户（**user**）以及需要在 Solana 上创建帐户的系统程序的引用。\r\n\r\n`IncrementGreeting<’info>`：此结构定义了 increment_greeting 函数所需的帐户，即将增加计数器的 greeting 帐户。\r\n\r\n`GreetingAccount`：这是由该程序管理的 greeting 帐户的数据结构。它包含一个字段，即计数器，用于跟踪问候已被增加的次数。\r\n\r\n**关键概念：**\r\n\r\n**帐户初始化：**create_greeting 函数演示了如何使用 Anchor 在 Solana 上初始化新帐户。**#[account(init, payer = user, space = 8 + 8)]**属性指定应初始化**account_greeting**，用户将支付以创建帐户，并且帐户需要足够的空间来存储帐户鉴别器（**8 字节**由 Anchor 自动添加以消除歧义）和计数器字段（**8 字节**用于**u64**）。\r\n\r\n**签名者和权限：**在**CreateGreeting**中，用户标记为**#[account(mut)]**，表示他们是交易的签名者，他们的帐户可以更改（用于交易支付和帐户创建）。\r\n\r\n简单状态管理：该程序演示了 Solana 中的基本状态管理模式，其中状态（**counter**）存储在一个帐户（**GreetingAccount**）中，并且交易使用程序函数修改该状态。\r\n\r\n此代码提供了一个与区块链上的帐户交互的 Solana 程序的基本但完整的示例，以执行简单的状态更改，演示了在 Solana 区块链和 Anchor 框架的背景下进行帐户创建、交易签名和状态管理原则。\r\n\r\n你可以通过此[链接](https://www.soldev.app/course/intro-to-anchor)了解更多信息。\r\n\r\n### 步骤 3 ：构建程序\r\n\r\n**构建你的项目：**\r\n\r\n运行 anchor build 命令：\r\n\r\n```bash\r\nanchor build\r\n```\r\n\r\n此命令将编译你的 Rust 程序为可部署在 Solana 区块链上的 BPF（Berkeley Packet Filter）字节码。\r\n\r\n**查找你的程序 ID：**\r\n\r\n构建后，在`target/idl/my_solana_dapp.json`中找到你的程序 ID，或者运行以下命令查找：\r\n\r\n```bash\r\nsolana address -k target/deploy/my_solana_dapp-keypair.json\r\n```\r\n\r\n编译和部署程序到本地 Solana 网络：\r\n\r\n**先决条件：**\r\n\r\n\r\n*   本地 Solana 测试验证器正在运行。\r\n*   已安装 Anchor 和 Solana CLI 工具。\r\n\r\n **程序编译：**\r\n\r\n\r\n如果你在上一节中遵循了构建步骤，则你的程序已经编译完成。确保你的 Solana LAN（测试验证器）正在运行。\r\n\r\n **部署程序：**\r\n\r\n\r\n1.  **启动 Solana 测试验证器（如果尚未运行）：**\r\n\r\n```bash\r\nsolana-test-validator\r\n```\r\n\r\n2. **配置 Solana CLI 以使用本地网络：**\r\n\r\n运行：\r\n\r\n```bash\r\nsolana config set - url localhost\r\n```\r\n\r\n3. **部署程序：**\r\n\r\n转到你的项目目录并运行此命令：\r\n\r\n```bash\r\nanchor deploy\r\n```\r\n\r\n此命令将部署你编译的程序到 Solana 本地网络。部署成功后，Anchor 将显示 program ID。\r\n\r\nAnchor 会更新你项目的`Anchor.toml` 和 JavaScript 文件，其中包含已部署 program ID，简化了与前端的集成。\r\n\r\n4. **验证部署：**\r\n\r\n你可以通过运行以下命令验证部署：\r\n\r\n```bash\r\nsolana program show <PROGRAM_ID>\r\n\r\n/* 输出示例：  \r\n> solana program show CC3EongBFU71ru4LRdUe3wNg5ULLLnCnJLhRhbUcP93oProgram Id: CC3EongBFU71ru4LRdUe3wNg5ULLLnCnJLhRhbUcP93o  \r\nOwner: BPFLoaderUpgradeab1e11111111111111111111111  \r\nProgramData Address: 6nnAVBvmJHJyN4keECcZDswfF6zzeLAEs2qZGWMcuhFj  \r\nAuthority: 9HGR7nJ2VQ4T23SyHA7BhqrShj9MokwNKdgTh1en61fC  \r\nLast Deployed In Slot: 8777  \r\nData Length: 200840 (0x31088) bytes  \r\nBalance: 1.39905048 SOL\r\n*/\r\n```\r\n\r\n请将**<PROGRAM_ID>**替换为你的程序 ID。如果成功部署，此命令将显示有关你的程序的详细信息。\r\n\r\n**结论：**\r\n\r\n\r\n你现在已经使用 Rust 和 Anchor 创建并部署了一个简单的 Solana 程序。尝试更复杂的逻辑和交互将有助于你更好地理解 Solana 的功能。\r\n\r\n## 第 4 部分：使用 React 和 Anchor 与前端集成：\r\n\r\n\r\n设置 React 应用程序：\r\n\r\n\r\n只需删除**/app**目录，并使用以下命令创建一个新的 React 应用程序：\r\n\r\n```bash\r\nnpx create-react-app app\r\n\r\n\r\n#after it  \r\n\r\ncd app/  \r\nnpm install @solana/web3.js @project-serum/anchor @solana/wallet-adapter-react \\\\  \r\n@solana/wallet-adapter-react-ui @solana/wallet-adapter-wallets \\\\  \r\n@solana/wallet-adapter-base  \r\nnpm install @solana/wallet-adapter-react @solana/wallet-adapter-phantom @solana/web3.js\r\n```\r\n\r\n **先决条件：**\r\n\r\n1. 安装 Node.js。\r\n2. 导航至项目的 **app/** 目录。\r\n\r\n **依赖安装：**\r\n\r\n\r\n使用 Phantom 钱包连接到本地主机区块链\r\n\r\n![图片 1](https://img.learnblockchain.cn/attachments/migrate/1719582810185)\r\n\r\n![图片 2](https://img.learnblockchain.cn/attachments/migrate/1719582810181)\r\n\r\n![图片 3](https://img.learnblockchain.cn/attachments/migrate/1719582810188)\r\n\r\n![图片 4](https://img.learnblockchain.cn/attachments/migrate/1719582810189)\r\n\r\n**Phantom 集成：**\r\n\r\n使用 [@solana/wallet-adapter-react](https://www.npmjs.com/package/@solana/wallet-adapter-react) 库连接到 Phantom。如果你使用 Anchor 初始化项目，则此操作应已包含在你的设置中。  \r\n发送交易并与 Solana 程序交互\r\n\r\n**修改前端：**\r\n\r\n\r\n修改 **app/src/App.js** 以连接到 Solana 程序并发送交易：  \r\n使用 Anchor 构建生成的 IDL（接口描述语言）文件与你的程序进行交互。只需将其从 **target/idl** 目录移动到你的 **app** 目录中的 src。  \r\n实现函数以连接你的钱包、创建问候账户并增加问候计数器：\r\n\r\n```javascript\r\nimport { useState } from \"react\";\r\nimport { useAnchorWallet } from \"@solana/wallet-adapter-react\";\r\nimport { Connection, PublicKey, SystemProgram, Keypair } from \"@solana/web3.js\";\r\nimport { Program, AnchorProvider } from \"@project-serum/anchor\";\r\nimport { useWallet } from \"@solana/wallet-adapter-react\";\r\nimport {\r\n  WalletMultiButton,\r\n  WalletDisconnectButton,\r\n} from \"@solana/wallet-adapter-react-ui\";\r\nimport idl from \"./my_solana_dapp.json\"; // 你的 JSON IDL 文件路径\r\nconst programID = new PublicKey(idl.metadata.address);\r\nconst network = \"http://127.0.0.1:8899\"; // 根据你的环境进行调整：本地、devnet 或 mainnet-beta\r\nconst opts = { preflightCommitment: \"processed\" };\r\n\r\nconst App = () => {\r\n  const wallet = useAnchorWallet();\r\n  const { connected } = useWallet();\r\n  const [greetingAccountPublicKey, setGreetingAccountPublicKey] =\r\n    useState(null);\r\n  const [error, setError] = useState(\"\");\r\n\r\n  const getProvider = () => {\r\n    if (!wallet) return null;\r\n    const connection = new Connection(network, opts.preflightCommitment);\r\n    return new AnchorProvider(connection, wallet, opts.preflightCommitment);\r\n  };\r\n\r\n  const createGreeting = async () => {\r\n    setError(\"\");\r\n    if (!connected) {\r\n      setError(\"钱包未连接。\");\r\n      return;\r\n    }\r\n    const provider = getProvider();\r\n    if (!provider) {\r\n      setError(\"提供程序不可用。\");\r\n      return;\r\n    }\r\n    const program = new Program(idl, programID, provider);\r\n    try {\r\n      const greetingAccount = Keypair.generate();\r\n      await program.rpc.createGreeting({\r\n        accounts: {\r\n          greetingAccount: greetingAccount.publicKey,\r\n          user: provider.wallet.publicKey,\r\n          systemProgram: SystemProgram.programId,\r\n        },\r\n        signers: [greetingAccount],\r\n      });\r\n      console.log(\"问候账户已创建！\");\r\n      setGreetingAccountPublicKey(greetingAccount.publicKey.toString());\r\n    } catch (err) {\r\n      console.error(\"创建问候账户时出错：\", err);\r\n      setError(\"无法创建问候账户。请重试。\");\r\n    }\r\n  };\r\n\r\n  const incrementGreeting = async () => {\r\n    setError(\"\");\r\n    if (!connected) {\r\n      setError(\"钱包未连接。\");\r\n      return;\r\n    }\r\n    if (!greetingAccountPublicKey) {\r\n      setError(\"问候账户未创建或公钥未设置。\");\r\n      return;\r\n    }\r\n    const provider = getProvider();\r\n    if (!provider) {\r\n      setError(\"提供程序不可用。\");\r\n      return;\r\n    }\r\n    const program = new Program(idl, programID, provider);\r\n    try {\r\n      await program.rpc.incrementGreeting({\r\n        accounts: {\r\n          greetingAccount: new PublicKey(greetingAccountPublicKey),\r\n          user: provider.wallet.publicKey,\r\n        },\r\n        signers: [],\r\n      });\r\n      console.log(\"问候已增加！\");\r\n    } catch (err) {\r\n      console.error(\"增加问候时出错：\", err);\r\n      setError(\"无法增加问候。请重试。\");\r\n    }\r\n  };\r\n\r\n  return (\r\n    <div>\r\n      <WalletMultiButton />\r\n      <WalletDisconnectButton />\r\n      <button onClick={createGreeting}>创建问候</button>\r\n      {greetingAccountPublicKey && (\r\n        <button onClick={incrementGreeting}>增加问候</button>\r\n      )}\r\n      {error && <p style={{ color: \"red\" }}>{error}</p>}\r\n    </div>\r\n  );\r\n};\r\n\r\nexport default App;\r\n```\r\n\r\n和 index.js:\r\n\r\n```javascript\r\nimport React from \"react\";\r\nimport { createRoot } from \"react-dom/client\";\r\nimport \"./index.css\";\r\nimport App from \"./App\";\r\nimport {\r\n  ConnectionProvider,\r\n  WalletProvider,\r\n} from \"@solana/wallet-adapter-react\";\r\nimport { PhantomWalletAdapter } from \"@solana/wallet-adapter-phantom\";\r\nimport { clusterApiUrl } from \"@solana/web3.js\";\r\nimport \"@solana/wallet-adapter-react-ui/styles.css\";\r\nimport { WalletModalProvider } from \"@solana/wallet-adapter-react-ui\";\r\nconst wallets = [new PhantomWalletAdapter()];\r\nconst rootElement = document.getElementById(\"root\");\r\nconst root = createRoot(rootElement);\r\n\r\nroot.render(\r\n  <React.StrictMode>\r\n    <ConnectionProvider endpoint=\"http://127.0.0.1:8899\">\r\n      {\" \"}\r\n      {/* 使用你期望的网络 */}\r\n      <WalletProvider wallets={wallets} autoConnect>\r\n        <WalletModalProvider>\r\n          <App />\r\n        </WalletModalProvider>\r\n      </WalletProvider>\r\n    </ConnectionProvider>\r\n  </React.StrictMode>\r\n);\r\n```\r\n\r\n现在我们需要在本地主机网络的钱包中空投一些 SOL：\r\n\r\n```\r\nsolana airdrop 10 3EEQVdGGCqiY4CEHiZ3S9CiTnGqE8mztUfFFZmTjYq4V  \r\n#solana airdrop 金额 钱包地址\r\n```\r\n\r\n\r\n\r\n现在如果我们运行应用程序：\r\n```\r\nnpm run\r\n```\r\n\r\n我们将看到：\r\n\r\n![Solana 连钱包](https://img.learnblockchain.cn/pics/20240628222148.png)\r\n\r\n\r\n\r\n现在通过点击“**选择钱包**”我们可以连接钱包并点击“**Create Greeting**”\r\n\r\n![img](https://img.learnblockchain.cn/pics/20240628222135.png)\r\n\r\n\r\n\r\n问候已创建，现在我们可以通过点击“Increment Greeting”:来增加它：\r\n\r\n![Solana 前端与合约交互](https://img.learnblockchain.cn/pics/20240628222252.png)\r\n\r\n\r\n\r\n所以我们的应用程序正在运行！\r\n\r\n## 第 5 部分：测试和部署\r\n\r\n\r\n在测试中，我们有文件 my_solana_dapp.js，并在此处插入以下代码：\r\n\r\n```rust\r\nuse anchor_lang::prelude::*;\r\nuse anchor_lang::solana_program::system_program;\r\nuse my_solana_dapp::{self, *};\r\nuse anchor_lang::ToAccountInfo;\r\nuse anchor_lang::solana_program::pubkey::Pubkey;\r\n#[tokio::test]\r\nasync fn test_create_and_increment_greeting() {\r\n    let program_test = anchor_lang::solana_program_test!(my_solana_dapp);\r\n    program_test.start().await;\r\n\r\n    // 创建测试环境\r\n    let (mut banks_client, payer, recent_blockhash) = program_test.banks_client().await;\r\n\r\n    // 派生一个新帐户作为问候账户\r\n    let greeting_account = Keypair::new();\r\n\r\n    // 创建问候账户\r\n    {\r\n        let create_greeting_ix = instruction::create_greeting(\r\n            &my_solana_dapp::id(),\r\n            &greeting_account.pubkey(),\r\n            &payer.pubkey(),\r\n        );\r\n```\r\n\r\n```rust\r\nlet mut transaction = Transaction::new_with_payer(\r\n            &[create_greeting_ix],\r\n            Some(&payer.pubkey()),\r\n        );\r\n        transaction.sign(&[&payer, &greeting_account], recent_blockhash);\r\n        banks_client.process_transaction(transaction).await.unwrap();\r\n    }\r\n\r\n// Increment Greeting Account\r\n    {\r\n        let increment_greeting_ix = instruction::increment_greeting(\r\n            &my_solana_dapp::id(),\r\n            &greeting_account.pubkey(),\r\n        );\r\n\r\nlet mut transaction = Transaction::new_with_payer(\r\n            &[increment_greeting_ix],\r\n            Some(&payer.pubkey()),\r\n        );\r\n        transaction.sign(&[&payer], recent_blockhash);\r\n        banks_client.process_transaction(transaction).await.unwrap();\r\n    }\r\n\r\n// Fetch the updated greeting account\r\n    let greeting_account_data: GreetingAccount = banks_client\r\n        .get_account(greeting_account.pubkey())\r\n        .await\r\n        .expect(\"get_account\")\r\n        .expect(\"account not found\")\r\n        .try_into()\r\n        .expect(\"account deserialization\");\r\n\r\n// Verify the counter has been incremented\r\n    assert_eq!(greeting_account_data.counter, 1);\r\n}\r\n```\r\n并运行命令：\r\n\r\n```\r\n> anchor test\r\nFinished release [optimized] target(s) in 0.12s\r\n```\r\n\r\n\r\n\r\n\r\n\r\n### 部署应用程序到开发网络和主网络：\r\n\r\n\r\n使用 Anchor 时，这是一个旨在简化 Solana 开发的框架，部署到**devnet**和**mainnet**的过程变得更加流畅，为开发人员提供了强大的抽象和工具。以下是基于 Anchor 部署 Solana 应用程序的完整指南。\r\n\r\n**准备部署：**\r\n\r\n确保你的应用程序经过充分测试和优化。使用 Anchor 测试系统测试你的程序逻辑和脚本。在部署到任何网络之前，安全审计和性能优化至关重要。\r\n\r\n**配置 Anchor 进行部署：**\r\n\r\n1. **自定义 Anchor.toml：** 你的**Anchor.toml**文件包含不同网络（**localnet**、**devnet**和**mainnet**）的配置。检查每个设置，确保它们指向正确的 RPC 端点并具有适当的钱包配置。\r\n\r\n2. 构建项目：在部署之前，使用 Anchor 构建项目，以确保所有构件都是最新的：\r\n\r\n```\r\nanchor build\r\n```\r\n\r\n\r\n\r\n此步骤将你的 Rust 程序编译为可执行的 BPF 字节码。\r\n\r\n**部署到 devnet：**\r\n\r\n在**devnet**上部署允许你在类似于**mainnet**的环境中测试你的应用程序，而不会冒真实资产的风险。\r\n\r\n1. **在 Anchor.toml 中部署到 devnet：** 确保**Anchor.toml**文件中的默认配置指向**devnet**。\r\n\r\n2. **填充你的钱包：** 如有必要，使用 faucet 向你的钱包添加测试**SOL**。默认情况下，Anchor 使用**Anchor.toml**文件中配置的钱包或 Solana CLI 钱包。\r\n\r\n3. **使用 Anchor 部署：** 使用以下命令将你的程序部署到 devnet：\r\n\r\n```\r\nanchor deploy - provider.cluster devnet\r\n```\r\n\r\n\r\n\r\nAnchor 通过选择正确的 Solana CLI 配置并将你的程序部署到指定网络来自动化此过程。记住此命令输出的程序 ID，以便未来通信。\r\n\r\n**转移到主网络：**\r\n\r\n在验证你的应用程序在 devnet 上正常工作后，下一步是转移到核心网络。\r\n\r\n1. **在 Anchor.toml 中切换到 mainnet：** 更新你的**Anchor.toml**以指向主网设置。这包括更改 RPC URL 和可能用于部署的钱包。\r\n\r\n2. **确保你有足够的主网 SOL：** 部署到**mainnet**需要真正的**SOL**。确保你的钱包中有足够的**SOL**以支付部署和交易成本。\r\n\r\n3. **使用 Anchor 进行主网部署：** 使用以下命令执行主网部署：\r\n\r\n```\r\nanchor deploy - provider.cluster mainnet\r\n```\r\n\r\n\r\n\r\n此命令将你的程序部署到**mainnet**。与以前一样，注意程序 ID，以便与你的 DApp 进行实时交互。\r\n\r\n**部署后：**\r\n\r\n部署后，密切监视你的应用程序性能和用户交互。使用 Solana Explorer 和 Anchor 的日志记录功能等工具进行故障排除和优化。与用户社区互动，获取反馈和支持，以改进你的 DApp。\r\n\r\n## 完成\r\n\r\n\r\n通过本指南，你现在对使用 Anchor 在 Solana 上开发并与 React 前端集成有了基本了解。这种组合将为你准备好进入去中心化应用程序开发的激动人心世界。请记住，区块链之旅是持续的，充满学习和创新。感谢阅读，祝你在开发之旅中好运。让我们一起构建未来，一步一个区块链。祝编码愉快！\r\n\r\n关注我：[LinkedIn](https://www.linkedin.com/in/anatolii-zhadan/)\r\n\r\n> 我是 [AI 翻译官](https://learnblockchain.cn/people/19584)，为大家转译优秀英文文章，如有翻译不通的地方，在[这里](https://github.com/lbc-team/Pioneer/blob/master/translations/8552.md)修改，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/21209","address":null},"history":null,"timestamp":1719584936,"version":1}