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