diff --git a/.gitignore b/.gitignore
index 5ce6a79..d4a938f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,6 @@ cache
.DS_Store
package-lock.json
.idea
-.next
\ No newline at end of file
+.next
+.env
+.local_keys
\ No newline at end of file
diff --git a/README.md b/README.md
index c546a47..19d718a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Solana中文大全
+# Solana 中文大全
@@ -7,17 +7,19 @@
-此仓库的代码会部署在 [solana-cn.com](https://solana-basic.surge.sh/) 域名下。
+此仓库的代码会部署在 [solana-cn.com](https://solana-cn.com/) 域名下。
## 任务认领
参与翻译,请参考 [issues](https://github.com/Fankouzu/solana-basic-ui/issues)。
阅读顺序:
+
- [翻译流程说明](https://github.com/Fankouzu/solana-basic-ui/issues/17)
- [翻译任务认领](https://github.com/Fankouzu/solana-basic-ui/issues/14)
## Pull Requests
+
如果你对文章内容存在疑问,请先阅读英文文档,查看是不是翻译问题。
如果属于翻译问题,请直接 PR 到本仓库;
@@ -27,7 +29,9 @@
此站点基于 [Vitepress](https://vitepress.dev/zh/) 构建,并部署在 [vercel.com](https://vercel.com)
## 本地调试
+
如下本地调试,请根据你的运行环境安装 [Node.js](https://nodejs.org),并进行如下操作:
+
```
# 克隆本仓库
git clone https://github.com/Fankouzu/solana-basic-ui.git
@@ -38,15 +42,17 @@ cd solana-basic-ui
# 安装依赖
npm install
```
+
执行完上述操作,即可进行本地调试:
+
```
npm run docs:dev
```
![Alt](https://repobeats.axiom.co/api/embed/dee699aaf19f40a044b9f5fa987add4eb3b6ec23.svg "Repobeats analytics image")
-
## 贡献者
+
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index cc44fd0..e4e1e25 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -22,9 +22,107 @@ function nav(): DefaultTheme.NavItem[] {
},
],
},
+ {
+ text: "社区教程",
+ items: [
+ {
+ text: "Solana Basic",
+ link: "/SolanaBasic/000",
+ activeMatch: "/SolanaBasic/",
+ },
+ {
+ text: "Solana Action & Blink",
+ link: "/SolanaAction/001",
+ activeMatch: "/SolanaAction/",
+ },
+ ],
+ },
+ {
+ text: "资源导航",
+ items: [
+ {
+ text: "浏览器",
+ link: "/SolanaResources/explorer",
+ activeMatch: "/SolanaResources/explorer",
+ },
+ {
+ text: "基础设施",
+ link: "/SolanaResources/infrastructure",
+ activeMatch: "/SolanaResources/infrastructure",
+ },
+ {
+ text: "信息查询",
+ link: "/SolanaResources/information",
+ activeMatch: "/SolanaResources/information",
+ },
+ {
+ text: "钱包",
+ link: "/SolanaResources/wallets",
+ activeMatch: "/SolanaResources/wallets",
+ },
+ {
+ text: "资产查询",
+ link: "/SolanaResources/assets",
+ activeMatch: "/SolanaResources/assets",
+ },
+ {
+ text: "Defi",
+ link: "/SolanaResources/defi",
+ activeMatch: "/SolanaResources/defi",
+ },
+ ],
+ },
];
}
+function sidebarSolanaResources(): DefaultTheme.SidebarItem[] {
+ return [
+ { text: "浏览器", link: "explorer" },
+ { text: "基础设施", link: "infrastructure" },
+ { text: "信息查询", link: "information" },
+ { text: "钱包", link: "wallets" },
+ { text: "资产查询", link: "assets" },
+ { text: "Defi", link: "defi" },
+ ];
+}
+function sidebarSolanaBasic(): DefaultTheme.SidebarItem[] {
+ return [
+ {
+ text: "第一阶段:账户与代币",
+ collapsed: false,
+ items: [
+ { text: "核心概念", link: "000" },
+ { text: "客户端安装", link: "001" },
+ { text: "代币基础", link: "002" },
+ { text: "非同质化代币", link: "003" },
+ ],
+ },
+ {
+ text: "第二阶段:脚本互动",
+ collapsed: false,
+ items: [
+ { text: "账户", link: "004" },
+ { text: "版本化交易", link: "005" },
+ { text: "包装SOL", link: "006" },
+ { text: "创建代币", link: "007" },
+ { text: "非同质化代币", link: "008" },
+ ],
+ },
+ {
+ text: "第三阶段:",
+ collapsed: false,
+ items: [
+ { text: "糖果机概述", link: "009" },
+ { text: "配置糖果机", link: "010" },
+ { text: "管理糖果机", link: "011" },
+ { text: "插入项目", link: "012" },
+ { text: "糖果卫士", link: "013" },
+ { text: "卫士组", link: "014" },
+ { text: "铸造", link: "015" },
+ ],
+ },
+ ];
+}
function sidebarSolanaDocumention(): DefaultTheme.SidebarItem[] {
return [
{
@@ -112,18 +210,16 @@ function sidebarSolanaDocumention(): DefaultTheme.SidebarItem[] {
{ text: "部署程序", link: "programs/deploying" },
{ text: "程序示例", link: "programs/examples" },
{ text: "常见问题", link: "programs/faq" },
- // { text: "使用C语言开发", link: "lang-c" },
- // { text: "使用Rust语言开发", link: "lang-rust" },
- // { text: "Solana的局限性", link: "limitations" },
+ { text: "使用C语言开发", link: "programs/lang-c" },
+ { text: "使用Rust语言开发", link: "programs/lang-rust" },
+ { text: "局限性", link: "programs/limitations" },
],
},
{
text: "更多",
collapsed: false,
base: "/SolanaDocumention/more/",
- items: [
- { text: "将 Solana 添加到您的交易所", link: "exchange" },
- ],
+ items: [{ text: "将 Solana 添加到您的交易所", link: "exchange" }],
},
];
}
@@ -155,6 +251,9 @@ function sidebarSolanaValidatorDocumentation(): DefaultTheme.SidebarItem[] {
collapsed: false,
items: [
{ text: "概述", link: "cli/cli" },
+ { text: "安装 Solana CLI", link: "cli/install" },
+ { text: "Solana CLI介绍", link: "cli/intro" },
+ { text: "参考和用法", link: "cli/usage" },
{
text: "命令行钱包",
collapsed: false,
@@ -203,10 +302,26 @@ function sidebarSolanaValidatorDocumentation(): DefaultTheme.SidebarItem[] {
text: "部署程序",
link: "cli/examples/deploy-a-program",
},
+ {
+ text: "持久化交易随机数",
+ link: "cli/examples/durable-nonce",
+ },
{
text: "离线交易签名",
link: "cli/examples/offline-signing",
},
+ {
+ text: "链下消息签名",
+ link: "cli/examples/sign-offchain-message",
+ },
+ {
+ text: "测试验证器",
+ link: "cli/examples/test-validator",
+ },
+ {
+ text: "发送与接收代币",
+ link: "cli/examples/transfer-tokens",
+ },
],
},
],
@@ -232,10 +347,23 @@ function sidebarSolanaValidatorDocumentation(): DefaultTheme.SidebarItem[] {
items: [
{ text: "Solana承诺状态", link: "consensus/commitments" },
{ text: "分叉生成", link: "consensus/fork-generation" },
+ { text: "管理分叉", link: "consensus/managing-forks" },
],
},
],
},
+ {
+ text: "运行验证器",
+ collapsed: false,
+ items: [
+ { text: "运行验证器", link: "operations/operations" },
+ {
+ text: "验证者节点 vs RPC节点",
+ link: "operations/validator-or-rpc-node",
+ },
+ { text: "准备工作", link: "operations/prerequisites" },
+ ],
+ },
],
},
];
@@ -258,6 +386,7 @@ function sidebarSolanaProgramLibrary(): DefaultTheme.SidebarItem[] {
],
},
{ text: "Token 兑换程序", link: "token-swap" },
+
{ text: "代币升级程序", link: "token-upgrade" },
{ text: "备忘录程序", link: "memo" },
{ text: "域名服务", link: "name-service" },
@@ -265,10 +394,18 @@ function sidebarSolanaProgramLibrary(): DefaultTheme.SidebarItem[] {
{
text: "质押池",
collapsed: false,
- items: [
- { text: "质押池介绍", link: "stake-pool/stake-pool" },
- ],
+ items: [{ text: "质押池介绍", link: "stake-pool/stake-pool" }],
},
+ { text: "单一验证节点质押池", link: "single-pool" },
+ { text: "转账钩子接口",
+ collapsed: false,
+ items: [
+ { text: "介绍", link: "transfer-hook-interface" },
+ { text: "规范", link: "transfer-hook-interface/specification" },
+ { text: "配置额外账户", link: "transfer-hook-interface/configuring-extra-accounts" },
+ { text: "示例", link: "transfer-hook-interface/examples" },
+ ]
+ }
];
}
// refer https://vitepress.dev/reference/site-config for details
@@ -293,6 +430,14 @@ export default defineConfig({
base: "/SolanaProgramLibrary/",
items: sidebarSolanaProgramLibrary(),
},
+ "/SolanaBasic/": {
+ base: "/SolanaBasic/",
+ items: sidebarSolanaBasic(),
+ },
+ "/SolanaResources/": {
+ base: "/SolanaResources/",
+ items: sidebarSolanaResources(),
+ },
},
footer: {
message:
diff --git a/docs/SolanaAction/001.md b/docs/SolanaAction/001.md
new file mode 100644
index 0000000..345780c
--- /dev/null
+++ b/docs/SolanaAction/001.md
@@ -0,0 +1,586 @@
+# Action and Blink
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 1.概念
+
+`Solana Actions` 是符合规范的 API,返回 Solana 区块链上的交易,供预 览、签名和在各种上下文中发送,包括二维码、按钮 + 小部件和互联网上的网站。 Actions 使开发人员能够轻松地将 Solana 生态系统中的操作集成到他们的环境中,允许你 执行区块链交易而无需导航到不同的应用程序或网页。
+
+`区块链链接`——或称 blinks——将任何 Solana Action 转化为可共享的、富含元 数据的链接。 Blinks 允许支持 Action 的客户端(浏览器扩展钱包、机器人)为用户显示 额外的功能。 在网站上,blink 可能会立即在钱包中触发交易预览,而无需访问去中心化 应用程序;在 Discord 中,机器人可能会将 blink 扩展为一组交互式按钮。 这将链上交 互的能力推向任何能够显示 URL 的网页表面。
+
+## 2.生命周期
+
+![lifecycle](/SolanaAction.png)
+
+## 3.创建一个简单的 Memo Action
+
+### 1. 创建环境
+
+通过 npx 创建一个 Next 运行环境:
+
+```sh
+npx create-next-app solana-action
+```
+
+输出:
+
+```sh
+➜ ~ npx create-next-app solana-action
+✔ Would you like to use TypeScript? … No / Yes
+✔ Would you like to use ESLint? … No / Yes
+✔ Would you like to use Tailwind CSS? … No / Yes
+✔ Would you like to use `src/` directory? … No / Yes
+✔ Would you like to use App Router? (recommended) … No / Yes
+✔ Would you like to customize the default import alias (@/*)? … No / Yes
+Creating a new Next.js app in ~/solana-action.
+
+Using npm.
+
+Initializing project with template: app-tw
+
+
+Installing dependencies:
+- react
+- react-dom
+- next
+
+Installing devDependencies:
+- typescript
+- @types/node
+- @types/react
+- @types/react-dom
+- postcss
+- tailwindcss
+- eslint
+- eslint-config-next
+
+npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+npm WARN deprecated @humanwhocodes/config-array@0.11.14: Use @eslint/config-array instead
+npm WARN deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
+npm WARN deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
+npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
+
+added 362 packages, and audited 363 packages in 2m
+
+137 packages are looking for funding
+ run `npm fund` for details
+
+found 0 vulnerabilities
+Initialized a git repository.
+
+Success! Created solana-action at ~/solana-action
+```
+
+安装 Solana web3 依赖和 Solana action 依赖
+
+```sh
+cd solana-action
+npm i @solana/web3.js @solana/actions
+```
+
+输出:
+
+```sh
+➜ ~ cd solana-action
+➜ solana-action git:(main) npm i @solana/web3.js @solana/actions
+
+added 76 packages, and audited 439 packages in 4m
+
+146 packages are looking for funding
+ run `npm fund` for details
+
+found 0 vulnerabilities
+```
+
+### 2.将一张 Solana Logo 图片复制到 public 目录
+
+![solana_devs](/solana_devs.jpg)
+
+![copy-logo-to-solana-action-public](/copy-logo-to-solana-action-public.png)
+
+### 3.创建 Solana action 的 route 程序文件
+
+创建目录
+
+```sh
+mkdir -p src/app/api/actions/memo/
+```
+
+创建 route 程序文件
+
+```sh
+vim src/app/api/actions/memo/route.ts
+```
+
+### 4.代码讲解
+
+:::tip
+首先我们创建一个链上 memo 的 action,通过一个简单的按钮实现向 Solana 链上存储一段 message:this is a simple memo message,用这个示例代码讲解 Solana action 主体结构,即在一个 URL 中兼容 GET 和 POST 两种请求格式,并且可以按照规范的格式响应 GET 请求和 POST 请求
+:::
+
+![solana-action-memo](/solana-action-memo.png)
+
+- 引入依赖库
+
+```js
+import {
+ ACTIONS_CORS_HEADERS,
+ ActionGetResponse,
+ ActionPostRequest,
+ ActionPostResponse,
+ MEMO_PROGRAM_ID,
+ createPostResponse,
+} from "@solana/actions";
+import {
+ ComputeBudgetProgram,
+ Connection,
+ PublicKey,
+ Transaction,
+ TransactionInstruction,
+ clusterApiUrl,
+} from "@solana/web3.js";
+```
+
+- 创建 GET 请求的返回
+
+
+GET请求返回格式规范
+
+在 Solana action 标准中,链接地址默认要通过 GET 请求返回一个元数据格式,这个返回要满足以下接口规范:
+
+```js
+export interface ActionGetResponse {
+ /** 图片的完整链接URL */
+ icon: string;
+ /** action的标题 */
+ title: string;
+ /** action的简介 */
+ description: string;
+ /** 按钮渲染后的标签文字 */
+ label: string;
+ /** 可选项:action按钮是否有效 */
+ disabled?: boolean;
+ /** 可选项:action的按钮数组 */
+ links?: {
+ actions: LinkedAction[],
+ };
+ /** 可选项:报错信息 */
+ error?: ActionError;
+}
+```
+
+- `icon`- 必须是描述操作的图像的绝对 HTTP 或 HTTPS URL。支持的图像格式为 SVG、PNG 或 WebP 图像。如果以上都不是,客户端必须将其拒绝为格式错误。
+
+- `title`- 操作标题的 UTF-8 字符串。
+
+- `description`- 一个 UTF-8 字符串,提供操作的简要描述。
+
+- `label`- UTF-8 字符串将显示在用于执行操作的按钮上。标签不应超过 5 个词组,并且应以动词开头,以强调要采取的操作。例如,"铸造 NFT"、"投票赞成"或"质押 1 SOL"。
+
+- `disabled`- 可选 boolean 值。如果存在,则应禁用与操作相关的所有按钮。此可选值为 false,因为不存在该值相当于 enabled=true。disabled 使用中的示例可能包括已完成铸造的 NFT 集合,或投票期已结束的治理提案。
+
+- `error`- 非致命错误的可选错误指示,旨在便于用户阅读并呈现给最终用户。如果设置,它不应阻止客户端解释操作或将其显示给用户。例如,错误可以与 disabled 显示原因(如业务限制、授权、状态或外部资源错误)一起使用。
+
+```js
+export interface ActionError {
+ /** 向用户展示的非致命错误信息字符串 */
+ message: string;
+}
+```
+
+- `links.actions`- 与此操作相关的附加操作的可选数组。每个链接操作仅被赋予一个标签(将在按钮上呈现)和一个关联的操作 URL(位于)href。不提供其他图标、标题或描述。例如,治理投票操作端点可能会为用户返回三个选项:"投票赞成"、"投票反对"和"弃权"。
+ - 如果没有`links.actions`提供,客户端应该使用根字符串呈现单个按钮 label,并向与初始 GET 请求相同的操作 URL 端点发出 POST 请求。
+ - 如果`links.actions`提供了任何内容,客户端应仅根据字段中列出的项目呈现按钮和输入字段 links.actions。客户端不应为根的内容呈现按钮 label。
+
+```js
+export interface LinkedAction {
+ /** 次action的URL */
+ href: string;
+ /** 按钮显示的文字标签 */
+ label: string;
+ /** 允许用户输入的参数 */
+ parameters?: [ActionParameter];
+}
+
+/** 允许用户输入的参数 */
+export interface ActionParameter {
+ /** 参数名称 */
+ name: string;
+ /** 在输入框显示的替换文本 */
+ label?: string;
+ /** 是否必填(默认:否) */
+ required?: boolean;
+}
+```
+
+
+
+示例代码:
+
+```js
+export const GET = (req: Request) => {
+ const payload: ActionGetResponse = {
+ icon: new URL("/solana_devs.jpg", new URL(req.url).origin).toString(),
+ title: "Memo Demo",
+ description: "This is a super simple Action",
+ label: "Memo Demo",
+ };
+ return Response.json(payload, {
+ headers: ACTIONS_CORS_HEADERS,
+ });
+};
+
+export const OPTIONS = GET;
+```
+
+- 创建 POST 请求的返回
+
+
+POST请求返回格式规范
+
+Solana action 要支持 POST 请求,并且 Blink 客户端需要按照以下格式将用户的公钥以 HTTP JSON 格式发送给 action 的 URL
+
+```json
+{
+ "account": ""
+}
+```
+
+其中,account 是发出请求的用户的公钥的 base58 编码表示形式。
+
+客户端应该使用 Accept-Encoding 标头,而 Action 服务应该使用 Content-Encoding 标头进行响应以进行 HTTP 压缩。
+
+返回格式:
+
+action 服务应使用 HTTP OK JSON 响应和以下格式来响应 POST 请求。
+
+```js
+export interface ActionPostResponse {
+ /** base64编码的交易数据 */
+ transaction: string;
+ /** 可选项:返回消息,例如描述交易细节 */
+ message?: string;
+}
+```
+
+
+
+示例代码:
+
+```js
+export const POST = async (req: Request) => {
+ try {
+ const body: ActionPostRequest = await req.json();
+
+ let account: PublicKey;
+ try {
+ account = new PublicKey(body.account);
+ } catch (err) {
+ return new Response("Invalid 'account' provided", {
+ status: 400,
+ headers: ACTIONS_CORS_HEADERS,
+ });
+ }
+
+ const transaction = new Transaction();
+
+ transaction.add(
+ // note: createPostResponse 至少需要 1 条非备忘录指令
+ ComputeBudgetProgram.setComputeUnitPrice({
+ microLamports: 1000,
+ }),
+ new TransactionInstruction({
+ programId: new PublicKey(MEMO_PROGRAM_ID),
+ data: Buffer.from("this is a simple memo message", "utf8"),
+ keys: [],
+ })
+ );
+
+ transaction.feePayer = account;
+
+ const connection = new Connection(
+ process.env.RPC_URL_MAINNET ?? clusterApiUrl("mainnet-beta")
+ );
+ transaction.recentBlockhash = (
+ await connection.getLatestBlockhash()
+ ).blockhash;
+ const payload: ActionPostResponse = await createPostResponse({
+ fields: {
+ transaction,
+ },
+ });
+
+ return Response.json(payload, { headers: ACTIONS_CORS_HEADERS });
+ } catch (err) {
+ return Response.json("An unknow error occurred", { status: 400 });
+ }
+};
+```
+
+- [完整代码在这里](https://github.com/Fankouzu/solana-action/blob/main/src/app/api/actions/memo/route.ts)
+
+将代码保存后就可以提交到 GitHub 了
+
+### 5.提交到 Github 仓库
+
+- 创建新仓库
+
+![create-new-repository](/create-new-repository.png)
+
+![new-repository](/new-repository.png)
+
+- 提交代码,按顺序允许以下三条命令
+
+```sh
+git remote add origin https://github.com/whaler-academy/solana-action.git
+git branch -M main
+git push -u origin main
+```
+
+输出:
+
+```sh
+Enumerating objects: 20, done.
+Counting objects: 100% (20/20), done.
+Delta compression using up to 8 threads
+Compressing objects: 100% (18/18), done.
+Writing objects: 100% (20/20), 56.17 KiB | 2.16 MiB/s, done.
+Total 20 (delta 0), reused 0 (delta 0), pack-reused 0
+To https://github.com/whaler-academy/solana-action.git
+ * [new branch] main -> main
+branch 'main' set up to track 'origin/main'.
+```
+
+### 6.部署到 vercel
+
+注册并登录[https://vercel.com/](https://vercel.com/)
+
+新建项目:
+
+![vercel-new-project](/vercel-new-project.png)
+
+导入仓库:
+
+![vercel-import](/vercel-import.png)
+
+部署项目:
+
+部署项目时输入自定义的二级域名,例如我的项目是 solana-action,部署之后可以通过 solana-action.vercel.com 访问
+
+![vercel-deploy](/vercel-deploy.png)
+
+完成:
+
+![vercel-finnish](/vercel-finnish.png)
+
+接下来你就可以用 URL 访问你的 Solana action 了
+
+
+
+返回结果应该是 JSON 格式:
+
+```json
+{
+ "icon": "https://solana-action.vercel.app/solana_devs.jpg",
+ "title": "Memo Demo",
+ "description": "This is a super simple Action",
+ "label": "Memo Demo"
+}
+```
+
+### 7.创建 Blink 链接
+
+编写和部署好 Solana action 之后我们可以通过创建自己的 Blink 链接,这个方法的方便之处是无需代码即可创建一个 Blink 链接收取 SOL,缺点是金额和文字都无法自定义
+
+打开输入刚才创建的 memo action 的 URL
+
+![dial-to-create-blink](/dial-to-create-blink.png)
+
+提交之后就可以看到创建好的 Blink 前端界面了,如果我们想要分享这个链接,只需要拷贝地址栏的链接,粘贴到 X 或者其他社交平台
+
+## 4.无需代码创建自己的捐款 Blink
+
+Solana action 的官方示例代码中提供了一个 action 链接,可以将链接中的收款地址替换成自己的收款地址完成一个允许其他人向自己发送 SOL 的 Blink 链接
+
+action 链接地址:
+
+
+
+例如:
+
+
+
+链接中的`CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG`为我的收款地址
+
+有了 action 链接我们就可以将 action 链接提交到创建自己的 Blink 了
+
+![blink-transfer-sol](/blink-transfer-sol.png)
+
+创建好的 Blink 链接为:
+
+
+
+这个由官方提供的 action 链接目前是在 dial.to 白名单中的,所以在 X 平台是可以直接以标签页形式展现出来的
+
+![twitter-blink-tab](/twitter-blink-tab.png)
+
+如果我们想自定义收款的文字和金额,接下来我们学习 Solana action 的高级应用
+
+## 5.定制一个 Donate 捐款 Blink
+
+在前面的课程内容中,我们看到发送 SOL 的官方的 Solana action 链接通过 GET 请求返回的 JSON 数据格式为:
+
+:::tip
+如果你连 GET 请求是什么都不了解,没关系,只需要将 这个地址输入到浏览器地址栏再回车即可!
+:::
+
+```json
+ "title": "Actions Example - Transfer Native SOL",
+ "icon": "https://solana-actions.vercel.app/solana_devs.jpg",
+ "description": "Transfer SOL to another Solana wallet",
+ "label": "Transfer",
+ "links": {
+ "actions": [
+ {
+ "label": "Send 1 SOL",
+ "href": "https://solana-actions.vercel.app/api/actions/transfer-sol?to=CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG&amount=1"
+ },
+ {
+ "label": "Send 5 SOL",
+ "href": "https://solana-actions.vercel.app/api/actions/transfer-sol?to=CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG&amount=5"
+ },
+ {
+ "label": "Send 10 SOL",
+ "href": "https://solana-actions.vercel.app/api/actions/transfer-sol?to=CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG&amount=10"
+ },
+ {
+ "label": "Send SOL",
+ "href": "https://solana-actions.vercel.app/api/actions/transfer-sol?to=CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG&amount={amount}",
+ "parameters": [
+ {
+ "name": "amount",
+ "label": "Enter the amount of SOL to send",
+ "required": true
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+现在我们需要让我们自己编写的 action 程序按照规范返回上面格式的内容就可以完成 action 的 GET 请求部分
+
+首先创建目录
+
+```sh
+mkdir -p src/app/api/actions/donate/
+```
+
+创建 route 程序文件
+
+```sh
+vim src/app/api/actions/donate/route.ts
+```
+
+GET 请求部分的源码
+
+```js
+const toPubkey = "CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG";
+
+export const GET = async (req: Request) => {
+ try {
+ const requestUrl = new URL(req.url);
+ const baseHref = new URL(
+ `/api/actions/donate?to=${toPubkey.toBase58()}`,
+ requestUrl.origin
+ ).toString();
+
+ const payload: ActionGetResponse = {
+ title: "向崔棉大师@MasterCui捐赠SOL",
+ icon: new URL("/avator.jpg", requestUrl.origin).toString(),
+ description: "支持第一个中文Solana action教程作者",
+ label: "Transfer", // 这个标签将被忽略
+ links: {
+ actions: [
+ {
+ label: `Send 0.01 SOL`, // 按钮文字
+ href: `${baseHref}&amount=0.01`,
+ },
+ {
+ label: `Send 0.05 SOL`, // 按钮文字
+ href: `${baseHref}&amount=0.05`,
+ },
+ {
+ label: `Send 0.1 SOL`, // 按钮文字
+ href: `${baseHref}&amount=0.1`,
+ },
+ {
+ label: "Send SOL", // 按钮文字
+ href: `${baseHref}&amount={amount}`, // 这个链接将拥有一个input输入框
+ parameters: [
+ {
+ name: "amount", // href中的参数名
+ label: "Enter the amount of SOL to send", // 输入框的替代文字
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ };
+
+ return Response.json(payload, {
+ headers: ACTIONS_CORS_HEADERS,
+ });
+ } catch (err) {
+ console.log(err);
+ let message = "An unknown error occurred";
+ if (typeof err == "string") message = err;
+ return new Response(message, {
+ status: 400,
+ headers: ACTIONS_CORS_HEADERS,
+ });
+ }
+};
+```
+
+这样的代码就可以按照规范显示出 3 个发送 SOL 的按钮,同时还会显示一个输入框,让用户可以自己定制发送 SOL 的数额
+
+[捐款 action 的完整代码在这里](https://github.com/Fankouzu/solana-action/blob/main/src/app/api/actions/donate/route.ts)
+
+修改好代码之后提交 GitHub
+
+```sh
+git add .
+git commit -m "add donate"
+git push
+```
+
+提交代码后 vercel 会自动部署前端,稍微等待几秒钟,修改就会在前端生效,这是你就拥有了一个新的捐款的 Solana action 链接:
+
+将链接提交到创建捐款的 Blink
+
+![blink-donate](/blink-donate.png)
+
+## 6.使用模版一键部署 Solana Action
+
+1. 注册[GitHub](https://github.com/)和[Vercel](https://vercel.com/)
+
+2. 打开[我的 GitHub 仓库](https://github.com/Fankouzu/solana-action) 点击 README 中的 Deploy 按钮
+ ![deploy-action-button](/deploy-action-button.png)
+3. 页面这是跳转到了 Vercel,在这里首先选择一个仓库名称,这个名称不影响运行,只要和自己的其它仓库名不重复即可,默认仓库名称为:my-blink-donate-action,不修改也可以,然后点击 Create 按钮
+ ![deploy-action-repo-name](/deploy-action-repo-name.png)
+4. 创建仓库之后接下来需要设置环境变量,这里包括收款地址,金额,卡片标题简介头像,设置好之后点击 Deploy 按钮
+ ![deploy-action-config](/deploy-action-config.png)
+5. 然后 Vercel 将自动运行部署,等待几分钟
+
+ - 部署中
+ ![deploy-action-deploying](/deploy-action-deploying.png)
+ - 部署成功
+ ![deploy-action-finnish](/deploy-action-finnish.png)
+
+6. 部署成功后,访问 `https://<你的仓库名>.vercel.com/api/actions/donate` 看到 json 返回结果就代表部署正确,并且核对你输入的环境变量
+ - [演示地址](https://my-blink-donate-action.vercel.app/api/actions/donate)
+7. 访问`https://dial.to/?action=solana-action%3Ahttps%3A%2F%2F<你的仓库名>.vercel.app%2Fapi%2Factions%2Fdonate` 可以看到你的 Blink 链接
+ - [演示地址](https://dial.to/?action=solana-action:https://my-blink-donate-action.vercel.app/api/actions/donate)
diff --git a/docs/SolanaBasic/000.md b/docs/SolanaBasic/000.md
new file mode 100644
index 0000000..8b4df42
--- /dev/null
+++ b/docs/SolanaBasic/000.md
@@ -0,0 +1,145 @@
+# 核心概念
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+:::tip 第一阶段账户与代币
+在第一阶段学习中,我们将学会通过命令行和 javascript 脚本创建账户,并且创建代币,同时学到 Solana 的特殊特性,通过代币账户来保存代币,这和以太坊智能合约的账本型合约有着本质的不同;并且我们还将了解到非同质化代币在 Solana 系统中的定义,即精度为 0 的代币都属于非同质化的代币;
+:::
+
+## Solana 开发流程
+
+- Solana 开发者工作流程是程序-客户(program-client)模型。程序开发的第一个工作流程允许您直接创建和部署自定义的 Rust、C 和 C++程序到区块链。一旦这些程序部署完成,任何知道如何与它们通信的人都可以使用它们。您可以使用任何可用的客户端 SDK(或 CLI)编写 dApps 来与这些程序通信,所有这些 SDK 都在底层使用 JSON RPC API。
+
+![solana-overview-client-program.png](/solana-overview-client-program.png)
+
+## 账户
+
+- 在 Solana 中,"Everything is an Account" 类似 Linux 世界里面把所有的资源都抽象成"文件"一样。
+- Solana 作为一个分布式区块链系统,所有的信息都存储在 Account 对象中,如合约(Solana 叫 Onchain Program), 账号信息,合约中存储的内容等都是存储在一个个 Account 对象中。
+- 在Solana中有三类账户:
+ - 数据账户,用来存储数据
+ - 程序账户,用来存储可执行程序
+ - 原生账户,指Solana上的原生程序,例如"System","Stake",以及"Vote"。
+- 数据账户又分为两类:
+ - 系统所有账户
+ - 程序派生账户(PDA)
+- 一个账户存储的完整字段列表:
+
+| 字段 | 描述 |
+|------------|------------------------------------------------|
+| lamports | 这个账户拥有的lamport(兰波特)数量 |
+| owner | 这个账户的所有者程序 |
+| executable | 这个账户成是否可以处理指令 |
+| data | 这个账户存储的数据的字节码 |
+| rent_epoch | 下一个需要付租金的epoch(代) |
+
+关于所有权,有几条重要的规则:
+
+- 只有账户的所有者才能改变账户中的数据,提取lamport
+- 任何人都可以向数据账户中存入lamport
+- 当账户中的数据被抹除之后,账户的所有者可以指定新的所有者
+
+程序账户不储存状态。
+
+例如,假设有一个计数程序,这个程序用来为一个计数器加数,你需要创建两个账户,一个用于存储程序的代码,
+另一个用于存储计数器本身。
+
+![account_example](/account_example.png)
+
+为了避免账户被删除,必须付租金。
+
+## 程序派生账户(PDA)
+
+程序派生账户(PDA)是为了让特定程序可以控制一些账户而设计出来的。使用PDA,程序可以通过编程方法为一些地址进行签名,而不一定用到私钥。
+
+- PDA是长度为32的字节串,看起来和公钥很像,但是并没有与之对应的私钥
+- `findProgramAddress`可以针对一个programId(程序id)和seeds(种子)唯一确定的生成一个PDA。这里的seeds(种子)是一组指定的字节串
+- 一个跳跃(一个字节)用于将候选PDA推离ed25519椭圆曲线
+- 程序通过传入种子和跳跃参数,调用[invoke_signed](https://docs.solana.com/developing/programming-model/calling-between-programs#program-signed-accounts)为PDA进行签名
+- PDA只能被用来派生出这个地址的程序所签名
+- 除了允许程序为不同的instruction签名之外,PDA还提供了一个像哈希表一样的接口,用于`建立账户索引`
+
+PDA是Solana程序开发的重要构成要素。有了PDA,程序可以为账户签名,同时保证没有外部用户能够产生针对同一个账户的有效签名。 除了为账户签名外,一些程序还可以修改自己派生出来的PDA里的数据。
+
+![Accounts matrix](/account-matrix.png)
+
+## 账号和签名
+
+- Solana 的签名系统使用的是 Ed25519 ,说人话就是: Ed25519 是一种计算快,安全性高,且生成的签名内容小的一种不对称加密算法。新一代公链几乎都支持这个算法。
+
+- 所以 Solana 的,我们用户理解的账号,就是一串 Ed25519 的私钥,各种钱包里面的助记词,会被转换成随机数种子, 再用随机数种子来生成一个私钥,所以助记词最终也是换算成私钥。所以用户账号的本质就是私钥,而用户账号的地址 则是这私钥对应的公钥,优于公钥是二进制的,为了可读性,将其进行 Base58 编码后的值,就是这个账号的地址。 如:HawRVHh7t4d3H3bitWHFt25WhhoDmbJMCfWdESQQoYEy
+
+- 把这里的公钥和私钥放一起,就是所谓的 Keypair,或者叫公私钥对。假设这里把私钥进行加密,并由用户来设置密码, 公钥作为这个私钥的索引。就实现了一个简单的钱包系统了。
+
+- 通过用户选择的公钥,加上密码,得到对应的私钥,再用私钥去操作的他的账号
+
+## 交易
+
+- 交易就是链外数据和链上数据产生的一次交互。比如发起一笔转账,在 StepN 里面发起一次 Claim 动作。 交易是对多个交易指令的打包,所以起内容主要就是各个交易指令,以及相应指令对应的发起人和签名。交易就是一连串的交易指令,以及需要签名的指令的签名内容。
+
+- 指令是Solana上最基本的操作单元
+- 每个指令都包含:
+ - `program_id`:所针对的程序的id
+ - `accounts`:需要读或写的全部账户组成的数组
+ - `instruction_data`:向指定程序所传输的数据的字节码
+- 多个指令可以被打包进入同一个交易当中
+- 每个交易都包含:
+ - `instructions`:一个或多个指令
+ - `blockhash`:最新的块哈希值
+ - `signatures`:一个或多个签名
+- 指令会被自动的按顺序执行
+- 如果一个指令的任何一部分失败,整个交易就会失败
+- 交易的大小限制在1232字节以内
+
+## 合约
+
+- 合约分为两类,一类是普通合约一类是系统合约,前者在 Solana 中称为"On Chain Program" 后者称为"Native Program" 其实本质都是类似其他公链上所说的合约。
+- 系统合约是由节点在部署的时候生成的,普通用户无法更新,他们像普通合约一样,可以被其他合约或者 RPC 进行调用
+ - 系统合约有
+ - System Program: 创建账号,转账等作用
+ - BPF Loader Program: 部署和更新合约
+ - Vote program: 创建并管理用户 POS 代理投票的状态和奖励
+- 一般我们说的合约都是普通合约,或者叫 "On Chain Program"。普通合约是由用户开发并部署,Solana 官方也有 一些官方开发的合约,如 Token、ATA 账号等合约。
+ - 当用户通过"BPF Loader Program"部署一个新合约的时候,新合约 Account 中的被标记为 true,表示他是一个可以 被执行的合约账号。不同于有些公链,Solana 上的合约是可以被更新的,也可以被销毁。并且当销毁的时候,用于存储 代码的账号所消耗的资源也会归还给部署者。
+
+## 合约与 Account
+
+- 在上面的 Account 介绍中,我们有个 owner 的成员,这个就表示这个 Account 是被哪个合约管理的,或者说哪个 合约可以对这个 Account 进行读写,类似 Linux 操作系统中,文件属于哪个用户。
+
+## 租约
+
+- Solana 的资金模型中,每个 Solana 账户在区块链上存储数据的费用称为“租金”。 这种基于时间和空间的费用来保持账户及其数据在区块链上的活动为节点提供相应的收入。
+
+- 所有 Solana 账户(以及计划)都需要保持足够高的 LAMPORT 余额,才能免除租金并保留在 Solana 区块链上。
+
+- 当帐户不再有足够的 LAMPORTS 来支付租金时,它将通过称为垃圾收集的过程从网络中删除。
+
+- 注意:租金与交易费用不同。 支付租金(或保存在账户中)以将数据存储在 Solana 区块链上。 而交易费用是为了处理网络上的指令而支付的。
+
+## 租金率
+
+- Solana 租金率是在网络范围内设置的,主要基于每年每字节设置的 LAMPORTS。 目前,租金率为静态金额并存储在 Rent 系统变量中。
+
+## SPL 代币
+
+- 在以太坊中,普通代币被一个叫 ERC20 的提案定了规范,可以认为普通代币合约统一叫做 ERC20 代币。
+
+那么 Solana 世界里的 ERC20 代币是什么呢?答案就是 SPL 代币。
+
+> The Solana Program Library (SPL) is a collection of on-chain programs targeting the Sealevel parallel runtime.
+
+SPL Token 是 " Solana Program Library"中的一个组成部分,叫做"Token Program",简称为 SPL Token。
+
+所有的代币都有这个合约来管理,该合约代码在
+
+## 代币信息
+
+- 不同于以太坊中,一个代币就是一个合约。SPL Token 中,一个代币,仅仅是一个归 Token 合约管理的普通的 Account 对象,这个对象里面的二进制数据定义了 这个代币的基本属性。
+
+![mint_wallet_account.png](/mint_wallet_account.png)
+
+## SPL Token Account
+
+- 那么每个用户的拥有的代币数量信息存在哪里呢?这个合约又定义了一个账号结构,来表示某个地址含有某个代币的数量。
+
+![spl_pda_account.png](/spl_pda_account.png)
diff --git a/docs/SolanaBasic/001.md b/docs/SolanaBasic/001.md
new file mode 100644
index 0000000..c8b3689
--- /dev/null
+++ b/docs/SolanaBasic/001.md
@@ -0,0 +1,164 @@
+# Solana 客户端安装
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+- 这一章节将要学到有关 `Solana` 客户端的安装过程,包括安装 solana 命令行 cli,和 rust 客户端,还有发布 Token 所需要的 `spl-token` 客户端;同时我们使用客户端创建本地密钥对,也就是本地钱包,在后面的课程中使用
+
+## 课程
+
+### 1.安装 Rust
+
+[参考](/SolanaDocumention/intro/dev#链上程序开发)
+
+:::tip INFO
+不同的操作系统在参考链接中可以找到不同的安装方法,本教程以 MacOS 为例
+:::
+
+链上程序开发包括用 Rust、C 或 C++编写程序。首先,您需要确保电脑上安装了 Rust。您可以使用以下命令执行此操作:
+
+```sh
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+### 2.安装 Solana 客户端
+
+[参考](/SolanaDocumention/intro/dev#链上程序开发)
+
+然后,您需要安装 Solana CLI 来编译和部署您的程序。您可以通过运行以下命令来安装 Solana CLI:
+
+```sh
+sh -c "$(curl -sSfL https://release.solana.com/stable/install)"
+solana --version
+```
+
+建议使用 Solana CLI 运行本地验证器来测试您的程序。要在安装 Solana CLI 后,运行本地验证器,请运行以下命令:
+
+```sh
+solana-test-validator
+```
+
+### 3.安装 SPL 客户端
+
+[参考](/SolanaProgramLibrary/token#相关教程)
+
+Solana 程序库 (SPL) 是针对 Sealevel 并行运行时的链上程序的集合。我们将要学习通过spl-token客户端命令创建代币
+
+```sh
+cargo install spl-token-cli
+```
+
+运行 spl-token --help 获取可用命令的完整描述。
+
+## 操作
+
+### 1.配置 RPC 节点
+
+您可以通过运行以下命令来查看 Solana CLI 当前对应的是哪个集群:
+
+[参考](/SolanaValidatorDocumentation/cli/examples/choose-a-cluster)
+
+```sh
+$ solana config get
+Config File: ${HOME}/.config/solana/cli/config.yml
+RPC URL: https://api.mainnet-beta.solana.com
+WebSocket URL: wss://api.mainnet-beta.solana.com/ (computed)
+Keypair Path: ${HOME}/.config/solana/id.json
+```
+
+使用 solana config set 命令来设定集群。任何未来的子命令都将在你设置的集群上发送或接收信息。
+
+例如想要连接到开发网集群,请运行:
+
+设置 RPC 节点地址:
+
+[参考](/SolanaDocumention/core/clusters)
+
+```sh
+solana config set --url https://api.devnet.solana.com
+```
+
+第三方节点:
+
+-
+
+### 2.创建密钥对
+
+通过以下命令可以创建一个新的密钥对钱包,并且保存在你的系统目录中,之后的 Solana 命令行 cli 将默认使用这个钱包地址
+[参考](/SolanaValidatorDocumentation/cli/cli)
+
+```sh
+$ solana-keygen new
+Generating a new keypair
+
+For added security, enter a BIP39 passphrase
+
+NOTE! This passphrase improves security of the recovery seed phrase NOT the
+keypair file itself, which is stored as insecure plain text
+
+BIP39 Passphrase (empty for none):
+
+Wrote new keypair to ${HOME}/.config/solana/id.json
+==============================================================================
+pubkey: 8wgMJeuPMYWJi5c2zvF8kffSbUvyaU9us1wgeJnrVzb4
+==============================================================================
+Save this seed phrase and your BIP39 passphrase to recover your new keypair:
+ankle sadness harbor traffic happy sleep culture quote cream nation that spray
+==============================================================================
+```
+
+查看自己的钱包地址:
+
+```sh
+solana address
+```
+
+创建一个新账户,但是不将密钥对保存在系统中,我们可以拿这个地址用于未来的测试中使用:
+
+```sh
+$ solana-keygen new --no-outfile
+Generating a new keypair
+
+For added security, enter a BIP39 passphrase
+
+NOTE! This passphrase improves security of the recovery seed phrase NOT the
+keypair file itself, which is stored as insecure plain text
+
+BIP39 Passphrase (empty for none):
+
+================================================================================
+pubkey: CrHB76Q9ckYJic4kt4ZqHV5wDJ9meDK8cMbDJhzfw1x9
+================================================================================
+Save this seed phrase and your BIP39 passphrase to recover your new keypair:
+local monitor diesel enhance visit tag interest diagram love okay aspect blossom
+================================================================================
+```
+
+### 3.配置钱包
+
+如果希望将密钥对的 json 文件保存在其他文件夹下,使用这个命令,修改默认配置中的密钥对文件路径
+
+[参考](/SolanaProgramLibrary/token#default-keypair)
+
+```sh
+solana config set --keypair ${HOME}/new-keypair.json
+```
+
+### 4.领取空投
+
+将Solana命令行的默认配置链接到devnet开发网节点后,可以领取测试币的空投,有了测试币我们就可以进行下面的课程内容了;
+
+[参考](/SolanaProgramLibrary/token#airdrop-sol)
+
+```sh
+solana airdrop 1
+```
+
+## 挑战
+
+通过solana cli命令行客户端完成以下挑战,具体方法可以通过运行`solana -h`获取帮助信息
+
+- 查询自己的sol余额
+- 获取当前区块高度
+- 发送sol到其他地址
diff --git a/docs/SolanaBasic/002.md b/docs/SolanaBasic/002.md
new file mode 100644
index 0000000..2922218
--- /dev/null
+++ b/docs/SolanaBasic/002.md
@@ -0,0 +1,220 @@
+# 代币基础
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+- 本章节讲述通过 `spl-token` 客户端在命令行中创建同质化 Token,铸造 Token,查询余额,转移代币,以及创建代币的元数据
+
+## 课程
+
+在课程开始之前,请确认 solana 客户端配置到了 devnet 开发网,同时牧人账户也已经领取到了空投的测试币
+
+查询余额:
+
+```sh
+$ solana balance
+10.34331731 SOL
+```
+
+### 1.创建同质化 Token
+
+[参考 1](/SolanaProgramLibrary/token#example-creating-your-own-fungible-token)
+
+[参考 2](/SolanaDocumention/core/tokens)
+
+要创建新代币(mint 帐户),请在终端中运行以下命令。
+
+```sh
+$ spl-token create-token
+Creating token BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ under program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
+
+Address: BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+Decimals: 9
+
+Signature: 5DPHNBYAMXVgqDJWhbJDCki4JABFhC3x6GyTUaviTTgyLBHGPUeJUiqKwbfjzKVttBQmhwW97eDttTCnMmz7PZqy
+```
+
+- `BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ`是代币的唯一标识符也是代币地址,同时也是一个数据地址,存储着代币的数据。
+- `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`是代币的程序,代币地址存储数据,代币程序为可执行程序,不存储数据。
+- `5DPHNBYAMXVgqDJWhbJDCki4JABFhC3x6GyTUaviTTgyLBHGPUeJUiqKwbfjzKVttBQmhwW97eDttTCnMmz7PZqy`是交易的签名,你可以通过交易签名在[区块链浏览器](https://solscan.io/tx/5DPHNBYAMXVgqDJWhbJDCki4JABFhC3x6GyTUaviTTgyLBHGPUeJUiqKwbfjzKVttBQmhwW97eDttTCnMmz7PZqy?cluster=devnet)中查询到这笔交易的详情
+- 在创建 Token 过程中,系统做了以下操作
+ - 调用系统程序创建一个具有足够空间容纳 mint 帐户数据的新帐户, 然后将所有权转移到代币程序。
+ - 调用代币程序将新账户的数据初始化为铸币账户
+
+通过 spl-token 最初创建的代币供应量为 0,我们通过命令查询一下这个 Token 的总供应量:
+
+```sh
+spl-token supply
+```
+
+例如:
+
+```sh
+$ spl-token supply BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+0
+```
+
+### 2.创建代币账户
+
+要持有特定代币的单位,您必须首先创建一个`代币账户`。 若要创建新的代币帐户,请使用以下命令:
+
+```sh
+spl-token create-account --owner
+```
+
+例如:
+
+```sh
+$ spl-token create-account BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+Creating account 5j2DQUJbSd6qd1bRBE2ygoAAFTaDHkovxYgubrQbUVwn
+Signature: 5vqjC8tZRES8FoucefdNvJMtpRM9WerWvMMy29QTJ6Uf6nE1zCZErWB34eBJaPrXE4iaWvBDuYJX7Mdjzb7fUyNM
+```
+
+- `5j2DQUJbSd6qd1bRBE2ygoAAFTaDHkovxYgubrQbUVwn`是为保存`create-account`命令中指定的代币单位而创建代币帐户的地址。
+- 调用系统程序创建一个具有足够空间用于代币帐户数据的新帐户,然后将所有权转移给代币程序。
+- 调用代币程序,将新账户的数据初始化为代币账户
+- 默认情况下,该`create-account`命令会创建一个[关联代币帐户](/SolanaDocumention/core/tokens#associated-token-account), 并将你的钱包地址作为代币帐户所有者。
+
+您可以使用以下命令创建具有不同所有者的代币帐户:
+
+```sh
+spl-token create-account --owner --fee-payer ${HOME}/.config/solana/id.json
+```
+
+例如:
+
+```sh
+$ spl-token create-account --owner CrHB76Q9ckYJic4kt4ZqHV5wDJ9meDK8cMbDJhzfw1x9 BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ --fee-payer ~/.config/solana/id.json
+Creating account B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb
+
+Signature: PmT3TeL2LDhEHw4e1YE8KRfNqCdvp8aRCoN3C5JLw8th1TsHEpcvhki8Hjbpgmy2up8xVbB7R24hqEwvMDtPy7f
+```
+
+### 3.铸造代币
+
+若要创建一定数量的代币,请使用以下命令:
+
+```sh
+spl-token mint [OPTIONS] [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS]
+```
+
+例如,运行以下命令:
+
+```sh
+spl-token mint BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ 100
+Minting 100 tokens
+ Token: BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+ Recipient: 5j2DQUJbSd6qd1bRBE2ygoAAFTaDHkovxYgubrQbUVwn
+Signature: 4iadCo13ktewsPUi92LpSCubkemYydQafufAZS5EVeATY3cuUDGEZbYbr8B4tpsiHuFNkcUTc5y2axthADthHcWq
+```
+
+- `BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ`是铸造代币的铸币账户的地址(增加总供应量)
+- `5j2DQUJbSd6qd1bRBE2ygoAAFTaDHkovxYgubrQbUVwn`是你的钱包代币账户的地址,代币单位正在被铸造到(增加金额)
+
+要将代币铸造到其他代币账户,请指定预期收件人代币账户的地址。例如,运行以下命令:
+
+```sh
+$ spl-token mint BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ 100 -- B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb
+Minting 100 tokens
+ Token: BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+ Recipient: B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb
+
+Signature: NpwYm5aNJUgBehCtxunLFtLxqzvDmv7YosBzMing6XLXsmWdtfbtbWsCgx16emLiD3Up2rpS4u9wAZy9MQ67XPn
+```
+
+- 注意这里的`Recipient`参数地址`B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb`是刚才我们为接收者地址`CrHB76Q9ckYJic4kt4ZqHV5wDJ9meDK8cMbDJhzfw1x9`创建的代币账户
+
+查询余额,我们通过以下命令可以查询当前默认账户在这个 Token 中的余额:
+
+```sh
+spl-token balance
+```
+
+例如:
+
+```sh
+spl-token balance BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+100
+```
+
+查询总供应量:
+
+```sh
+$ spl-token supply BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ
+200
+```
+
+### 4.转移代币
+
+若要在两个代币账户之间转移代币数量,请使用以下命令:
+
+```sh
+spl-token transfer [OPTIONS]
+```
+
+例如:
+
+```sh
+$ spl-token transfer BHaF2s4nowWz29w5T4XKrEqiULfay7SxP1YvjrfZzsnQ 10 B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb
+Transfer 10 tokens
+ Sender: 5j2DQUJbSd6qd1bRBE2ygoAAFTaDHkovxYgubrQbUVwn
+ Recipient: B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb
+
+Signature: 3sAEb7fRPjEUmJfuzH6zdy4y5skM4QELHFig8WN6G9VeUBXyC1qQXdc7ngo1nszLb2nnrufjCJvNYrfWuUNwj5Cd
+```
+
+- `5j2DQUJbSd6qd1bRBE2ygoAAFTaDHkovxYgubrQbUVwn`是发送者的代币账户
+- `B3oQUkgdqNSX1UsY1jTXnAx6NVPpLQwbRFRQ7gaTnVkb`是接收者的代币账户
+- 请务必了解,发送方和接收方都必须具有要传输的特定类型的代币的现有代币帐户。 发送方可以在交易中包含其他说明,以创建接收方的代币账户,该账户通常是关联代币账户。
+
+### 5.创建代币元数据
+
+代币扩展计划允许将其他可自定义的元数据(例如名称、符号、图像链接)直接存储在 Mint 帐户上。
+
+若要创建启用了元数据扩展的新代币,请使用以下命令:
+
+```sh
+$ spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb --enable-metadata
+Creating token GevvgkWZt79S7z1k6Qo8qKDmZaktVNjDMzVFZooTt3dc under program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
+To initialize metadata inside the mint, please run `spl-token initialize-metadata GevvgkWZt79S7z1k6Qo8qKDmZaktVNjDMzVFZooTt3dc `, and sign with the mint authority.
+
+Address: GevvgkWZt79S7z1k6Qo8qKDmZaktVNjDMzVFZooTt3dc
+Decimals: 9
+
+Signature: 3htk67A87D9YEevDvs6JZggQzABfJHTjBzgYM6NKRWLbtLJSriFhzYq2HCgA4GLVJNuVkeZ19kzKrizF8QiGzguF
+```
+
+- `GevvgkWZt79S7z1k6Qo8qKDmZaktVNjDMzVFZooTt3dc`是在启用元数据扩展的情况下创建的新代币的地址。
+
+一旦创建启用了元数据扩展的新代币后,请使用以下命令初始化元数据。
+
+```sh
+spl-token initialize-metadata
+```
+
+代币 URI 通常是指向要与代币关联的链下元数据的链接。你可以在 此处 找到 JSON 格式的示例。
+
+例如,运行以下命令会将额外的元数据直接存储在指定的铸币帐户上:
+
+```sh
+$ spl-token \
+initialize-metadata GevvgkWZt79S7z1k6Qo8qKDmZaktVNjDMzVFZooTt3dc \
+"TokenName" \
+"TokenSymbol" \
+"https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json"
+
+Signature: 5cB6G5SsosPdnnEVL6V5kkUzR41H1P12eiAzG5Xsa8X5hhFg4By421V27Me2YqfH5eBUf45ostMUsiw2rqSuddJZ
+```
+
+然后,您可以在资源管理器中查找铸币帐户的地址以检查元数据。例如,这是在 [SolanaFm](https://solscan.io/tx/5DPHNBYAMXVgqDJWhbJDCki4JABFhC3x6GyTUaviTTgyLBHGPUeJUiqKwbfjzKVttBQmhwW97eDttTCnMmz7PZqy?cluster=devnet) 资源管理器上启用元数据扩展时创建的代币。
+
+## 挑战
+
+通过 spl-token 命令行客户端完成以下挑战,具体方法可以通过运行`spl-token -h`获取帮助信息
+
+- 查询当前账户所持有的所有Token
+- 销毁 Token
+- 关闭铸造
+- 更新 metadata
diff --git a/docs/SolanaBasic/003.md b/docs/SolanaBasic/003.md
new file mode 100644
index 0000000..dabeef3
--- /dev/null
+++ b/docs/SolanaBasic/003.md
@@ -0,0 +1,159 @@
+# 创建非同质化代币
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+与 Ethereum 不同,在 solana 生态中,如果一个代币的精度为 0 就可以视为非同质化代币,而类似 ERC721 的代币合集型的 NFT 则是由一定数量的精度为 0 的 Solana token 组成,每一个 token 都拥有自己的地址,ERC721 一个合集拥有一个地址,每个 token 是合约中的一个 ID
+
+## 课程
+
+### 1.通过 cli 创建代币
+
+创建代币时,通过参数指定精度为 0
+
+```sh
+$ spl-token create-token --decimals 0
+Creating token BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk under program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
+
+Address: BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+Decimals: 0
+
+Signature: xfPoxtX2Xqe447CzeSzupbiCLjRpXQhcW8wiWvDCBu5sMjXmCZSxf6TXucXh96Zjr5jaFowp6N9HR4pF4fUYSLj
+```
+
+然后创建一个代币帐户来持有这种新类型的代币:
+
+```sh
+$ spl-token create-account BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+Creating account eyqCgSPMziLJnR7ovWhnN6qgykJtarnnYmyaGpqBogM
+
+Signature: 65mqmqeRPAFwDZLwvUQTAdX7pdH3dTJc4SmT5gCAaD7S4U1CS4KJ49MQsK2h3n7Tnz2Bcapi1cZdH3xe5XRm4KSU
+```
+
+现在只向账户中铸造一个代币
+
+```sh
+$ spl-token mint BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk 1 eyqCgSPMziLJnR7ovWhnN6qgykJtarnnYmyaGpqBogM
+Minting 1 tokens
+ Token: BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+ Recipient: eyqCgSPMziLJnR7ovWhnN6qgykJtarnnYmyaGpqBogM
+
+Signature: fevtHYeJhahogeZvyWqvMB8X9n8z9dAJRKktK1Ehct1z9TCJ8d79iZ5G72vnDzD3n3nqqZBNE86dQHYG12N1da8
+```
+
+最后禁用未来的铸造:
+
+```sh
+$ spl-token authorize BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk mint --disable
+Updating BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+ Current mint: CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG
+ New mint: disabled
+
+Signature: 3PYXmykjPVhnFqQdUA8qqHR9qAX91w2fAehtKy3oN5YFunog4TuJC8pbPBJ8moGdxfenSoE6R53C6J5DE4SRP1n4
+```
+
+现在该`eyqCgSPMziLJnR7ovWhnN6qgykJtarnnYmyaGpqBogM`帐户拥有唯一的`BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk`代币:
+
+```sh
+$ spl-token account-info BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+
+SPL Token Account
+ Address: eyqCgSPMziLJnR7ovWhnN6qgykJtarnnYmyaGpqBogM
+ Program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
+ Balance: 1
+ Decimals: 0
+ Mint: BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+ Owner: CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG
+ State: Initialized
+ Delegation: (not set)
+ Close authority: (not set)
+```
+
+```sh
+$ spl-token supply BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk
+1
+```
+
+### 2.通过 javascript 创建代币
+
+首先通过我们之前学过的 `createMint` 函数创建代币,最后一个参数精度为 0
+
+```js
+const mint = await createMint(
+ connection,
+ wallet,
+ wallet.publicKey,
+ wallet.publicKey,
+ 0
+);
+```
+
+然后创建一个代币帐户来持有这种新类型的代币:
+
+```js
+const associatedTokenAccount = await getOrCreateAssociatedTokenAccount(
+ connection,
+ wallet,
+ mint,
+ wallet.publicKey
+);
+```
+
+现在只向账户中铸造一个代币,最后一个参数的数量为 1 lamport:
+
+```js
+await mintTo(
+ connection,
+ wallet,
+ mint,
+ associatedTokenAccount.address,
+ wallet,
+ 1
+);
+```
+
+最后通过`createSetAuthorityInstruction`函数禁用未来的铸造,在这个函数中,第四个参数为新的铸造权限账户地址,如果设置为`null`则代表关闭未来的铸造:
+
+```js
+let transaction = new Transaction().add(
+ createSetAuthorityInstruction(
+ mint,
+ wallet.publicKey,
+ AuthorityType.MintTokens,
+ null
+ )
+);
+
+await web3.sendAndConfirmTransaction(connection, transaction, [wallet]);
+```
+
+查询账户状态:
+
+```js
+const accountInfo = await getAccount(
+ connection,
+ associatedTokenAccount.address
+);
+
+console.log(accountInfo.amount);
+// 1
+const mintInfo = await getMint(connection, mint);
+
+console.log(mintInfo);
+/*
+{
+ address: "BNptJhNKo6Cs9KrjxcdwKCpmXtnQgqR9J2QD1WHgJNPk",
+ mintAuthority: "CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG",
+ supply: 1,
+ decimals: 0,
+ isInitialized: true,
+ freezeAuthority: "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg"
+}
+ */
+```
+
+## 挑战
+
+- 通过区块链浏览器查询每一笔交易
+- 为非同质化代币创建metadata
diff --git a/docs/SolanaBasic/004.md b/docs/SolanaBasic/004.md
new file mode 100644
index 0000000..3bd8dd3
--- /dev/null
+++ b/docs/SolanaBasic/004.md
@@ -0,0 +1,109 @@
+# 账户
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+本章节将学会在本地目录安装`@solana/web3.js`依赖包,通过 js 脚本创建账号的过程,并且保存账号私钥用于后面的开发过程
+
+## 课程
+
+### 1.安装
+
+在本地系统中创建一个项目目录,之后安装 spl-token 的依赖,确保你的系统中已经安装好了[nodejs](https://nodejs.org)
+
+```sh
+npm init -y
+
+npm install @solana/web3.js @solana/spl-token
+```
+
+### 2.配置节点
+
+在你的脚本中你可以自定义节点地址,或者使用默认的开发网 devnet
+
+```js
+import { Connection, clusterApiUrl } from "@solana/web3.js";
+const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
+```
+
+### 3.创建密钥对
+
+[参考](/SolanaDocumention/clients/javascript-reference.html#系统程序)
+
+```js
+import { Keypair } from "@solana/web3.js";
+let keypair = Keypair.generate();
+```
+
+### 4.领取空投
+
+```js
+import {
+ Keypair,
+ Connection,
+ clusterApiUrl,
+ LAMPORTS_PER_SOL,
+} from "@solana/web3.js";
+let payer = Keypair.generate();
+
+const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
+
+const airdropSignature = await connection.requestAirdrop(
+ payer.publicKey,
+ LAMPORTS_PER_SOL
+);
+
+await connection.confirmTransaction(airdropSignature);
+```
+
+### 4.保存私钥
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/1.Account/3.Payer.ts)
+
+### 5.恢复密钥
+
+恢复密钥可以有两种形式,有的密钥保存为数组形式:
+
+```js
+const keypair = Keypair.fromSecretKey(
+ Uint8Array.from([
+ 174, 47, 154, 16, 202, 193, 206, 113, 199, 190, 53, 133, 169, 175, 31, 56,
+ 222, 53, 138, 189, 224, 216, 117, 173, 10, 149, 53, 45, 73, 251, 237, 246,
+ 15, 185, 186, 82, 177, 240, 148, 69, 241, 227, 167, 80, 141, 89, 240, 121,
+ 121, 35, 172, 247, 68, 251, 226, 218, 48, 63, 176, 109, 168, 89, 238, 135,
+ ])
+);
+```
+
+有的密钥保存为 Base58 形式:
+
+```js
+const keypair = Keypair.fromSecretKey(
+ bs58.decode(
+ "5MaiiCavjCmn9Hs1o3eznqDEhRwxo7pXiAYez7keQUviUkauRiTMD8DrESdrNjN8zd9mTmVhRvBJeg5vhyvgrAhG"
+ )
+);
+```
+
+### 6.生成助记词
+
+助记词属于 BIP39 协议,是在大多数区块链中通用的,同一套助记词可以用于比特币,以太坊以及 Solana,其根本原理是通过将随机数转换为英文单词的形式保存私钥
+
+```js
+const mnemonic = bip39.generateMnemonic();
+```
+
+### 7.恢复助记词
+
+```js
+const mnemonic =
+ "pill tomorrow foster begin walnut borrow virtual kick shift mutual shoe scatter";
+const seed = bip39.mnemonicToSeedSync(mnemonic, ""); // (mnemonic, password)
+const keypair = Keypair.fromSeed(seed.slice(0, 32));
+```
+
+## 挑战
+
+- 生成HD钱包
+- 生成自定义地址前缀
diff --git a/docs/SolanaBasic/005.md b/docs/SolanaBasic/005.md
new file mode 100644
index 0000000..bdafeb8
--- /dev/null
+++ b/docs/SolanaBasic/005.md
@@ -0,0 +1,176 @@
+# 版本化交易
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+本章节通过 js 脚本构建版本化交易,在这个过程中,你将学到通过创建`指令IX`,Solana 上交易内的步骤称为指令, 将指令打包成为交易,最终签署交易的整个过程
+
+## 课程
+
+### 0.计算账户费用
+
+在 Solana 上保持账户活跃会产生一项存储费用,称为 [租金/rent](/SolanaDocumention/core/fees.html#租金)。通过存入至少两年租金的金额,你可以使账户完全免除租金收取。对于费用的计算,你需要考虑你打算在账户中存储的数据量。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/CreateAccouMinimumBalanceForRentExemptionntIx.ts)
+
+```js
+const lamports = await connection.getMinimumBalanceForRentExemption(space);
+```
+
+通过命令行快速计算
+
+```sh
+$solana rent 1500
+Rent-exempt minimum: 0.01133088 SOL
+```
+
+### 1.创建 IX
+
+脚本中通过`SystemProgram.createAccount`函数,创建了一个指令 IX,这个指令的作用是调用系统程序创建一个账户,并且存入指定数量的 lamport 租金
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/CreateAccountIx.ts)
+
+```js
+// 创建账号IX
+// 使用 web3.js 辅助函数创建这个简单的指令
+const createAccountIx = SystemProgram.createAccount({
+ // `fromPubkey` - 该帐户需要签署交易
+ fromPubkey: payer.publicKey,
+ // `newAccountPubkey` - 在链上创建的账户地址
+ newAccountPubkey: Pubkey,
+ // 要存储在此帐户中的lamports
+ lamports: lamports + amount,
+ // 分配的总空间
+ space: space,
+ // 该帐户的owner程序id
+ programId: programId,
+});
+```
+
+### 2.创建版本化交易
+
+[定义](/SolanaDocumention/advanced/versions.html#版本化交易)
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/CreateVersionedTx.ts)
+
+```js
+// 创建版本化交易
+// 创建消息 (v0)
+const message = new TransactionMessage({
+ payerKey: payerKey, // 支付账户的公钥
+ recentBlockhash, // 获取最后的区块hash
+ instructions: txs, // 交易的指令数组
+}).compileToV0Message();
+```
+
+### 3.签署交易
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/SignTx.ts)
+
+```js
+// 签署交易
+// 使用我们所需的签名者(例如'Payer'和'keypair')签署交易,signers可以是多个签名人的keypair
+tx.sign(signers);
+```
+
+### 4.发送交易
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/SendVersionedTx.ts)
+
+```js
+// 发送交易
+const sig = await connection.sendTransaction(tx);
+// 输出交易签名:
+console.log(`交易签名:${sig}`);
+```
+
+### 5.发送简单交易
+
+将以上几步操作链接到一个完整的过程中,创建一个简单的交易,目的是在链上创建一个账户,并支付租金
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/1.SendSimpleTx.ts)
+
+```js
+// 创建账户Ix,签署交易,发送交易
+// 随机计算一个地址的keypair
+let to = Keypair.generate();
+// 创建账户的指令IX
+let createAccountIx = await CreateAccountIx(
+ payer,
+ to.publicKey,
+ connection,
+ SystemProgram.programId
+);
+// 创建版本化交易
+const tx = await CreateVersionedTx(payer.publicKey, connection, [
+ createAccountIx,
+]);
+// 使用支付账户和to账户签名交易
+const signedTx = await SignTx([payer, to], tx);
+// 发送版本化交易
+await SendVersionedTx(signedTx);
+```
+
+### 6.发送 SOL
+
+通过系统程序的 transfer 函数,我们可以向指定账户发送 sol,这一小节内容将演示通过`SystemProgram.transfer`函数创建发送 SOL 的指令
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/Transfer.ts)
+
+```js
+// 创建一个指令用于发送交易
+const transferToTestWalletIx = SystemProgram.transfer({
+ // 要发送的数量,以lamports为单位,加上空间租用成本
+ lamports: lamports + amount,
+ // `fromPubkey` - 该帐户需要签署交易
+ fromPubkey: payer.publicKey,
+ // `toPubkey` - 不需要签署交易
+ toPubkey: toPubkey,
+ // 该帐户的owner程序id为系统程序id
+ programId: SystemProgram.programId,
+});
+```
+
+### 6.发送复杂交易
+
+前面的简单交易,在一笔交易中只有一个指令,接下来我们创建一个复杂交易,在一笔交易中同时包含 3 个指令
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/2.VersionedTx/2.SendComplexTx.ts)
+
+```js
+// 创建账户Ix,两个发送交易
+// 随机计算一个地址的keypair
+let to = Keypair.generate();
+// 创建账户的指令IX
+let createAccountIx = await CreateAccountIx(
+ payer,
+ to.publicKey,
+ connection,
+ SystemProgram.programIdß
+);
+// 创建发送SOL的指令,发送到to地址2000lamport
+let transfer_1 = await Transfer(connection, payer, to.publicKey, 2_000);
+// 创建发送SOL的指令,发送到STATIC_PUBLICKEY地址1000000lamport
+let transfer_2 = await Transfer(connection, payer, STATIC_PUBLICKEY, 1_000_000);
+// 将三个指令IX打包创建版本化交易
+const tx = await CreateVersionedTx(payer.publicKey, connection, [
+ createAccountIx,
+ transfer_1,
+ transfer_2,
+]);
+// 使用支付账户和to账户签名交易
+const signedTx = await SignTx([payer, to], tx);
+// 发送版本化交易
+await SendVersionedTx(signedTx);
+```
+
+### 7.计算交易成本
+
+通过 message 计算
+
+```js
+// 计算交易费
+const fees = await connection.getFeeForMessage(tx.message);
+console.log(`Estimated SOL transfer cost: ${fees.value} lamports`);
+```
diff --git a/docs/SolanaBasic/006.md b/docs/SolanaBasic/006.md
new file mode 100644
index 0000000..75fd24b
--- /dev/null
+++ b/docs/SolanaBasic/006.md
@@ -0,0 +1,135 @@
+# 包装 SOL
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+Token 程序可用于包装 SOL。这样做允许 SOL 像任何其他 Token 程序令牌类型一样被处理,并且在与 Token 程序接口交互的其他程序调用时非常有用。
+
+包含包装的 SOL 的账户使用公钥与称为“Native Mint”的特定 Mint 相关联 So11111111111111111111111111111111111111112。
+
+## 课程
+
+### 1.创建关联 Token 账户(ATA 账户)
+
+创建 ATA 账户用于保存 wrapped SOL
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/ATA.ts)
+
+```js
+// 获取或者创建ATA
+const tokenAccount = await getOrCreateAssociatedTokenAccount(
+ connection, // 链接
+ payer, // 支付账户Keypair
+ mint, // mint账户公钥
+ owner, // ATA账户的所有者
+ allowOwnerOffCurve, // 允许所有者帐户成为 PDA(程序派生地址)
+ commitment, // 查询状态所需的承诺级别
+ confirmOptions, // 确认交易的选项
+ programId, // SPL Token 计划账户
+ associatedTokenProgramId // 关联Token程序账户
+);
+```
+
+### 2.创建 SyncNative 指令
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/CreateSyncNativeIx.ts)
+
+```js
+const ix = createSyncNativeInstruction(
+ account, // 用于同步 lampport 的本地帐户
+ programId // SPL Token 程序账户
+);
+```
+
+### 3.打包多个指令到一笔交易
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/AddTransaction.ts)
+
+```js
+// 向此交易添加一个或多个指令
+const tx = new Transaction().add(...items);
+```
+
+### 4.发送并确认交易
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/SendAndConfirmTx.ts)
+
+```js
+// 签名,发送并且确认交易
+const sig = await sendAndConfirmTransaction(
+ connection, // 链接
+ transaction, // 交易
+ signers // 签名人
+);
+```
+
+### 5.包装 SOL
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/1.WrapSOL.ts)
+
+```js
+// 创建Ata账户用来保存你的wrapped SOL
+const associatedTokenAccount = await Ata(
+ connection,
+ payer,
+ NATIVE_MINT,
+ payer.publicKey
+);
+// 将 SOL 转移到关联的代币账户并使用 SyncNative 更新wrapped SOL 余额
+const solTransferTransaction = AddTransaction(
+ // 第一个交易,发送sol
+ await Transfer(connection, payer, associatedTokenAccount, LAMPORTS_PER_SOL),
+ // 第二个交易,创建SyncNative指令
+ CreateSyncNativeIx(associatedTokenAccount)
+);
+// 发送和确认交易
+await SendAndConfirmTx(connection, solTransferTransaction, [payer]);
+```
+
+### 6.关闭账户
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/CloseAccount.ts)
+
+```js
+// 关闭账户
+await closeAccount(
+ connection, // 链接
+ payer, // 支付账户
+ account, // 账户地址
+ destination, // 接收已关闭账户剩余余额的账户
+ authority // 有权关闭账户的权限
+);
+```
+
+### 7.解包装 SOL
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/3.WrapSOL/2.UnWrapSOL.ts)
+
+```js
+// 查找用来保存你的wrapped SOL的Ata账户
+const associatedTokenAccount = await Ata(
+ connection,
+ payer,
+ NATIVE_MINT,
+ payer.publicKey
+);
+// 关闭账户,回收SOL
+await CloseAccount(
+ connection,
+ payer,
+ associatedTokenAccount,
+ payer.publicKey,
+ payer
+);
+```
+
+### 8.计算交易成本
+
+通过 Transaction 计算
+
+```js
+// 计算交易费
+const fees = await solTransferTransaction.getEstimatedFee(connection);
+console.log(`Estimated SOL transfer cost: ${fees} lamports`);
+```
diff --git a/docs/SolanaBasic/007.md b/docs/SolanaBasic/007.md
new file mode 100644
index 0000000..4f23bd4
--- /dev/null
+++ b/docs/SolanaBasic/007.md
@@ -0,0 +1,220 @@
+# 创建 Token
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+本章节将通过`@solana/spl-token`依赖包创建 spl Token,在创建 spl token 之后进行铸造,销毁,转移的操作
+
+## 课程
+
+### 1.创建 mint 账户
+
+不同于 Ethereum, Solana 系统中,每一个代币又叫 mint 账户,这个账户的地址是通过 Keypair 函数创建出来的,而 Ethereum 中个人地址创建的合约都是通过创建者地址和 nonce 计算出来的
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/CreateMint.ts)
+
+```js
+// 随机创建密钥对用作mint账户
+const mintKeypair = Keypair.generate();
+// 创建mint账户
+const mint = await createMint(
+ connection, // 链接
+ payer, // 支付账户
+ mintAuthority, // 铸造账户地址
+ freezeAuthority, // 冻结账户地址
+ decimals, // 小数点精度
+ mintKeypair, // 可选密钥对,默认为新的随机密钥对
+ undefined, // 确认交易的选项
+ programId // SPL Token程序账户
+);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/1.CreateMint.ts)
+
+```js
+// 创建mint账户
+const mint = await CreateMint(
+ connection,
+ payer,
+ payer.publicKey,
+ payer.publicKey,
+ 2, // 小数点精度
+ "Token"
+);
+// 获取铸造详情
+const mintInfo = await getMint(connection, mint);
+console.log(mintInfo);
+```
+
+### 2.铸造 Token
+
+在 Solana 系统中,个人账户持有 Token 必须通过关联 Token 的代币账户(ATA 账户)保存代币
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/MintTo.ts)
+
+```js
+const mintSig = await mintTo(
+ connection, // 网络链接
+ payer, // 支付账户
+ mint, // token地址
+ destination, // Ata地址
+ authority, // 铸造权限
+ amount // 数量
+);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/2.MintTokens.ts)
+
+```js
+// Ata地址
+const associatedTokenAccount = await Ata(
+ connection,
+ payer,
+ tokenMint,
+ payer.publicKey
+);
+// 2位精度,10000.00个
+const amountOfTokensToMint = 1_000_000_000_000_000;
+// 铸造方法
+await MintTo(
+ connection,
+ payer,
+ tokenMint,
+ associatedTokenAccount,
+ payer,
+ amountOfTokensToMint
+);
+```
+
+### 3.销毁 Token
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/Burn.ts)
+
+```js
+// 销毁Token
+const mintSig = await burn(
+ connection, // 网络链接
+ payer, // 支付账户
+ account, // Ata地址
+ mint, // token地址
+ owner, // 铸造权限
+ amount // 数量
+);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/3.Burn.ts)
+
+```js
+// Ata地址
+const associatedTokenAccount = await Ata(
+ connection,
+ payer,
+ tokenMint,
+ payer.publicKey
+);
+// 2位精度,10.00个
+const amountOfTokensToBurn = 1_000;
+// 销毁方法
+await Burn(
+ connection,
+ payer,
+ associatedTokenAccount,
+ tokenMint,
+ payer,
+ amountOfTokensToBurn
+);
+```
+
+### 4.销毁全部 Token
+
+在销毁全部 Token 后,执行前面学过的关闭账户指令,这样可以回收租金 Sol
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/4.BurnAll.ts)
+
+```js
+// Ata地址
+const associatedTokenAccount = await Ata(
+ connection,
+ payer,
+ tokenMint,
+ payer.publicKey
+);
+const balance = await getAccount(connection, associatedTokenAccount);
+// 销毁方法
+await Burn(
+ connection,
+ payer,
+ associatedTokenAccount,
+ tokenMint,
+ payer,
+ balance.amount
+);
+// 关闭账户,回收SOL
+await CloseAccount(
+ connection,
+ payer,
+ associatedTokenAccount,
+ payer.publicKey,
+ payer
+);
+```
+
+### 5.查询账户下所有 Token
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/5.GetTokenAccountsByOwner.ts)
+
+```js
+const tokenAccounts = await connection.getTokenAccountsByOwner(
+ payer.publicKey, // 查询的账户地址
+ {
+ programId: TOKEN_PROGRAM_ID, // Token程序id
+ }
+);
+```
+
+### 6.发送 Token
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/TransferToken.ts)
+
+```js
+// 发送Token
+const signature = await transfer(
+ connection, // 链接
+ payer, // 支付账户
+ source, // 发送源的ATA账户地址
+ destination, // 接收账户的ATA地址
+ owner, // Token的拥有者地址
+ amount // 发送数量
+);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/6.Transfer.ts)
+
+```js
+// 随机计算接收地址
+const toKeypair = Keypair.generate();
+// 获取或创建From ATA
+const fromTokenAccount = await Ata(
+ connection,
+ payer,
+ tokenMint,
+ payer.publicKey
+);
+// 获取或创建To ATA
+const toTokenAccount = await Ata(
+ connection,
+ payer,
+ tokenMint,
+ toKeypair.publicKey
+);
+// 发送Token
+await TransferToken(
+ connection,
+ payer,
+ fromTokenAccount,
+ toTokenAccount,
+ payer.publicKey,
+ 10
+);
+```
diff --git a/docs/SolanaBasic/008.md b/docs/SolanaBasic/008.md
new file mode 100644
index 0000000..873d5ed
--- /dev/null
+++ b/docs/SolanaBasic/008.md
@@ -0,0 +1,105 @@
+# 非同质化代币
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+- 非同质化代币 (NFT)在 Solana 上表示为 SPL 代币,具有关联的元数据帐户,精度为0,最大供应量为 1
+- 小数位为 0,因此无法分割
+- 供应量为 1,因此仅存在 1 个此类代币
+- 铸造1个代币后,销毁铸造权限确保供应量永远不会增发
+
+## 课程
+
+### 1. 创建 mint 账户
+
+```js
+// 创建Token,精度为0
+const mint = await createMint(
+ connection, // 链接
+ payer, // 支付账户
+ mintAuthority, // 铸造账户地址
+ freezeAuthority, // 冻结账户地址
+ 0 // 小数点精度
+);
+```
+
+### 2. 创建 ATA 账户
+
+```js
+// 创建ATA账户
+const associatedTokenAccount = await getOrCreateAssociatedTokenAccount(
+ connection, // 链接
+ payer, // 支付账户Keypair
+ mint, // mint账户公钥
+ owner // ATA账户的所有者
+);
+```
+
+### 3.铸造 1 个 Token
+
+```js
+const mintSig = await mintTo(
+ connection, // 网络链接
+ payer, // 支付账户
+ mint, // token地址
+ destination, // Ata地址
+ authority, // 铸造权限
+ 1 // 数量为1
+);
+```
+
+### 4. 删除设置权限
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/CreateSetAuthorityInstyIx.ts)
+
+```js
+const ix = createSetAuthorityInstruction(
+ tokenMint, // mint账户地址
+ payer.publicKey, // 原权限地址
+ AuthorityType.MintTokens, // 权限类型
+ null // 新权限地址
+);
+```
+
+### 5.完整过程
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/4.Token/7.NonFungibleToken.ts)
+
+```js
+// 创建Token,精度为0
+const tokenMint = await CreateMint(
+ connection, // 链接
+ payer, // 支付账户
+ payer.publicKey, // 铸造权限
+ payer.publicKey, // 冻结权限
+ 0 // NFT的小数点精度为0
+);
+// 创建ATA账户
+const associatedTokenAccount = await Ata(
+ connection,
+ payer,
+ tokenMint,
+ payer.publicKey
+);
+// 向ATA账户铸造1个Token
+await MintTo(
+ connection, // 链接
+ payer, // 支付账户
+ tokenMint, // mint账户
+ associatedTokenAccount, // ATA账户
+ payer, // 铸造权限
+ 1 // 数量为1
+);
+// 创建设置权限为空的指令交易
+let tx = AddTransaction(
+ CreateSetAuthorityIx(
+ tokenMint,
+ payer.publicKey,
+ AuthorityType.MintTokens,
+ null
+ )
+);
+// 发送交易
+await SendAndConfirmTx(connection, tx, [payer]);
+```
diff --git a/docs/SolanaBasic/009.md b/docs/SolanaBasic/009.md
new file mode 100644
index 0000000..d695397
--- /dev/null
+++ b/docs/SolanaBasic/009.md
@@ -0,0 +1,66 @@
+# 糖果机概述
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+- Metaplex Protocol Candy Machine 是 Solana 上公平 NFT 收藏品发行的领先铸造和分发程序。正如其名称所暗示的那样,您可以将 Candy Machine 视为一个临时结构,首先由创作者加载,然后由买家卸载。它允许创作者以安全且可定制的方式将其数字资产带上链。
+ ![candy-machine-photo](/candy-machine-photo.png)
+
+糖果机具有以下功能:
+
+- 接受 SOL、NFT 或任何 Solana 代币的付款。
+- 通过开始/结束日期、铸币限制、第三方签名者等来限制您的发布。
+- 通过可配置的机器人税和像 Captchas 这样的守门人保护您的启动免受机器人的攻击。
+- 将铸造限制为特定的 NFT/Token 持有者或精选的钱包列表。
+- 创建具有不同规则集的多个铸造组。
+- 在发布后披露您的 NFT,同时允许您的用户验证该信息。
+
+## 课程
+
+### 1.糖果机生命周期
+
+第一步是让创作者创建一个新的糖果机并按照自己的意愿进行配置。
+
+![candy-machine-lifecycle](/candy-machine-lifecycle.png)
+
+下一步是将物品放入糖果机中。
+
+![candy-machine-insertItem](/candy-machine-insertItem.png)
+
+每个 item 由两个参数组成:
+
+- `name` NFT 的名称
+- `uri` 指向 NFT 的元数据 URI,这意味着 JSON 元数据已通过链上(例如 Arweave、IPFS)或链下(例如 AWS、您自己的服务器)存储提供商上传。
+
+请注意,此时尚未创建任何真正的 NFT。我们只是在糖果机上加载了它所需的所有数据,以便在`创建 NFT 时按需创建`。这将我们带到了下一步。
+
+![candy-machine-createNFT](/candy-machine-createNFT.png)
+
+一旦糖果机加载完毕并满足所有预配置条件,用户就可以开始从中铸造 NFT。只有此时,NFT 才会在 Solana 区块链上创建。请注意,在铸造之前,一些用户可能需要执行其他验证步骤 — — 例如进行验证码或发送 Merkle 证明。
+
+一旦糖果机铸造出所有 NFT,它就完成了其使命,可以安全地删除它以释放区块链上的一些存储空间并收回一些租金。
+
+![candy-machine-delete](/candy-machine-delete.png)
+
+### 2.糖果卫士
+
+现在我们了解了糖果机的工作原理,让我们深入了解创作者可以保护和定制糖果机铸造过程的各种方法。
+
+创作者可以使用我们所谓的`Guards`为他们的 Candy Machine 添加各种功能。Metaplex Candy Machine 附带一个名为`Candy Guard`的附加 Solana 程序,该程序总共附带 `21 个`默认保护程序。通过使用附加程序,高级开发人员可以分叉默认的 Candy Guard 程序来创建自己的自定义保护程序,同时仍然能够依赖主 Candy Machine 程序。
+
+每个`Guards`都可以随意启用和配置,因此创建者可以选择所需的功能。禁用所有`Guards`相当于允许任何人随时免费铸造我们的 NFT,这可能不是我们想要的。因此,让我们看几个防护装置来创建一个更现实的例子。
+
+假设一台糖果机有以下保护装置:
+
+- `Sol 付款`:此项保护确保铸币钱包必须向配置的目标钱包支付配置数量的 SOL。
+- `开始日期`:此项保护确保铸造只能在配置的时间之后开始。
+- `铸币限制`:此项保护确保每个钱包铸币的数量不能超过配置的数量。
+- `机器人税`:这个保护有点特殊。它不保护任何东西,但它会改变失败铸币的行为,以防止机器人铸造糖果机。当这个保护被激活时,如果任何其他激活的保护未能验证铸币,它将向试图铸造的钱包收取少量配置的 SOL。
+
+我们最终得到的是一个受机器人保护的糖果机,它会收取 SOL,在特定时间启动,并且每个钱包只允许有限数量的薄荷糖。这是一个具体的例子。
+
+![candy-machine-guards](/candy-machine-guards.png)
+
+`Guards`拥有超过 21 种默认防护装置,并且能够创建自定义防护装置,因此创作者可以挑选自己喜欢的功能,并组成完美的糖果机。这个功能非常强大
+
diff --git a/docs/SolanaBasic/010.md b/docs/SolanaBasic/010.md
new file mode 100644
index 0000000..e2a03bb
--- /dev/null
+++ b/docs/SolanaBasic/010.md
@@ -0,0 +1,205 @@
+# 配置糖果机
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+- 本章节学习糖果机上所有可用的配置,我们将重点介绍影响糖果机本身的 NFT 配置,而不是影响铸造过程`guards`的配置
+
+## 课程
+
+### 1.权限
+
+- `authority`在创建新的糖果机时,你需要提供授权方的地址,以便以后能够更新糖果机、向其中插入物品、删除糖果机等。当使用我们的 SDK 时,糖果机总是会默认与`guards`关联,因此您不必担心这个铸币权限。
+
+### 2.所有 NFT 共享的设置
+
+许多 NFT 属性对于所有铸造的 NFT 都是相同的。因此,我们不必每次在糖果机中加载物品时都重复这些属性,而是在糖果机设置中设置一次即可。
+
+以下是所有铸造的 NFT 之间共享的属性列表:
+
+- `sellerFeeBasisPoints`卖家费用基点:应以基点为单位设定的二级销售版税。例如,250 意味着 2.50%版税
+- `symbol`符号:铸造 NFT 上使用的符号 — 例如“MYPROJECT”。这可以是最多 10 个字符的任何文本,也可以通过提供空文本来使其成为可选项。
+- `maxEditionSupply`最大版本供应量:从每个 NFT Item 中可以再次打印的版本数量(类似 ERC1155)。在大多数情况下,您需要将其设置为,0 以防止铸造的 NFT 被多次打印。请注意,您无法将其设置为`null`这意味着 Candy Machines 不支持无限版本。
+- `isMutable`是否可变:铸造的 NFT 是否应可变。除非有特殊原因,否则我们建议将其设置为`true`。您可以在将来随时使 NFT 不可变,但您不能再使不可变的 NFT 可变。
+- `creators`创造者:应在铸造的 NFT 上设置的创造者列表。
+ - `address`创造者地址
+ - `verified`是否验证
+ - `percentageShare`版税分配比例,例如 5 即 5%
+- `tokenStandard`代币标准:铸造 NFT 时使用的代币标准,目前仅支持两种代币标准 `NonFungible`和`ProgrammableNonFungible`
+- `ruleSet`规则集:如果糖果机使用`ProgrammableNonFungible`代币标准,它可以提供一个明确的规则集,该规则集将分配给每个铸造的可编程 NFT。如果没有提供规则集,它将默认使用 Collection NFT 上的规则集(如果有)。否则,将在没有规则集的情况下铸造可编程 NFT
+
+```js
+const candyMachineSettings = {
+ sellerFeeBasisPoints: percentAmount(33.3, 2),
+ symbol: "MYPROJECT",
+ maxEditionSupply: 0,
+ isMutable: true,
+ creators: [
+ { address: creatorA, percentageShare: 50, verified: false },
+ { address: creatorB, percentageShare: 50, verified: false },
+ ],
+ tokenStandard: TokenStandard.NonFungible,
+};
+```
+
+### 3.Metaplex 认证合集
+
+每台糖果机都必须与一个称为`Metaplex 认证合集`的特殊 NFT 相关联。此`Collection NFT`可以将铸造的 NFT 组合在一起 ,并在链上验证该信息。
+
+为了确保其他人无法在他们的糖果机上使用您的 `Collection NFT`,需要 Collection 的`更新权限`来签署任何更改糖果机上 Collection 的交易。因此,糖果机可以安全地自动验证所有铸造 NFT 的 Collection。
+
+```js
+// 创建合集更新权限keypair
+const collectionUpdateAuthority = generateSigner(umi);
+// 创建合集的mint账户keypair
+const collectionMint = generateSigner(umi);
+// 创建合集
+await createNft(umi, {
+ mint: collectionMint, // 合集的mint账户
+ authority: collectionUpdateAuthority, // 合集的更新权限
+ name: "My Collection NFT",
+ uri: "https://example.com/path/to/some/json/metadata.json",
+ sellerFeeBasisPoints: percentAmount(9.99, 2), // 9.99%
+ isCollection: true,
+}).sendAndConfirm(umi);
+
+// 将合集的更新权限配置到糖果机中
+const candyMachineSettings = {
+ collectionMint: collectionMint.publicKey,
+ collectionUpdateAuthority: collectionUpdateAuthority,
+};
+```
+
+### 4.Item 设置
+
+糖果机设置还包含有关其中已装入或将要装入的 Item 的信息。`itemsAvailable`属性属于该类别,并存储了糖果机将铸造的最大 NFT 数量。
+
+```js
+const candyMachineSettings = {
+ itemsAvailable: 500,
+};
+```
+
+除了`itemsAvailable`属性之外,还有两个属性定义 Item 在糖果机中的加载方式。您必须选择其中一个属性,另一个属性留空。这些属性是:
+
+- `configLineSettings`配置行设置
+- `hiddenSettings`隐藏设置
+
+#### `configLineSettings`配置行设置
+
+`configLineSettings`属性允许我们描述已插入或将要插入糖果机的 Item。通过提供 Item 名称和 URI 的精确长度以及提供一些共享前缀以缩短长度,它使我们能够将糖果机的大小保持在最小。`Config Line Settings`属性是一个包含以下属性的对象:
+
+- `prefixName`通用名称前缀:所有插入 Item 共享的名称前缀。此前缀最多可包含 32 个字符。
+- `nameLength`名称长度:每个插入 Item 的名称的最大长度(不包括名称前缀)。
+- `prefixUri`通用 URI 前缀:所有插入 Item 共享的 URI 前缀。此前缀最多可包含 200 个字符。
+- `uriLength`URI 长度:每个插入 Item 的 URI 的最大长度(不包括 URI 前缀)。
+- `isSequential`:`true`表示按顺序铸造 NFT,`false`表示按随机顺序。我们建议将其设置为`false`以防止买家预测下一个将铸造哪个 NFT。请注意,在创建新的糖果机时,我们的 SDK 将默认使用配置行设置,并将`是否按顺序`设置为`false`。
+
+为了更好地理解这些`Name`和`URI`属性,让我们来看一个例子。假设您要创建具有以下特征的糖果机:
+
+- 其內容包含 1000 項目。
+- 每个物品的名称是`My NFT Project #X`,其中 X 是从 1 开始的物品索引。
+- 每个 Item 的 JSON 元数据都已上传至 Arweave,因此它们的 URI 以`https://arweave.net/`开头,以最大长度为 43 个字符的唯一标识符结尾。
+
+在这个例子中,如果没有前缀,我们最终会得到:
+
+- 名称长度 = 20。`My NFT Project #`为 16 个字符,最高数字`1000`为 4 个字符。
+- URI 长度 = 63。其中`https://arweave.net/`为 20 个字符,唯一标识符为 43 个字符。
+
+当插入 1000 个 Item 时,仅存储 Item 信息就需要总共 83,000 个字符。但是,如果我们使用前缀,我们可以显著减少创建糖果机所需的空间,从而减少在区块链上创建它的成本。
+
+- Name Prefix = "My NFT Project #"
+- Name Length = 4
+- URI Prefix = "https://arweave.net/"
+- URI Length = 43
+
+1000 个 Item,我们现在只需要 47'000 个字符来存储我们的 Item。
+
+但这不是全部!您可以在名称或 URI 前缀中使用两个特殊变量来进一步减小该大小。这些变量是:
+
+- `$ID$`:替换成从 0 开始的 Item 索引。
+- `$ID+1$`:这将被从 1 开始的 Item 索引替换。
+
+在上面的例子中,我们可以利用`$ID+1$`变量作为名称前缀,这样我们就不需要在每个 Item 上设置它了。我们最终得到以下配置行设置:
+
+- Name Prefix = "My NFT Project #$ID+1$"
+- Name Length = 0
+- URI Prefix = "https://arweave.net/"
+- URI Length = 43
+
+我们的名称长度现在为零,并且我们将所需的字符减少到 43'000 个字符。
+
+最终代码片段:
+
+```js
+const candyMachineSettings = {
+ hiddenSettings: none(),
+ configLineSettings: some({
+ prefixName: "My NFT Project #$ID+1$",
+ nameLength: 0,
+ prefixUri: "https://arweave.net/",
+ uriLength: 43,
+ isSequential: false,
+ }),
+};
+```
+
+#### `hiddenSettings`隐藏设置
+
+准备 Item 的另一种方法是使用隐藏设置`hiddenSettings`。这是一种与配置行设置`configLineSettings`完全不同的方法,因为使用隐藏设置,您无需将任何物品插入糖果机,因为每个铸造的 NFT 都将共享相同的名称和相同的 URI。您可能想知道:为什么有人想这样做?这样做的原因是创建一个隐藏和显示的 NFT 掉落,在铸造所有 NFT 后显示它们。那么它是如何工作的呢?
+
+- 首先,创建者使用隐藏设置配置每个铸造的 NFT 的名称和 URI。URI 通常指向预告`teaser`JSON 元数据,明确表示即将发生揭露。
+- 然后,买家用相同的 URI 铸造所有这些 NFT,因此也具有相同的预告`teaser` JSON 元数据。
+- 最后,当所有 NFT 都被铸造出来后,创建者会更新每个铸造的 NFT 的 URI,以指向特定于该 NFT 的真实 URI。
+
+最后一步的问题在于,它允许创建者随意决定哪个买家获得哪个 NFT。为了避免这种情况,并允许买家验证 NFT 和 JSON 元数据之间的映射未被篡改,隐藏设置包含一个哈希属性,该属性应填充文件的 32 个字符哈希,该文件将 NFT 索引与其真实的 JSON 元数据进行映射。这样,在揭示之后,创建者可以将该文件公开给买家,并验证其哈希是否与隐藏设置中提供的哈希相对应。
+
+因此,我们最终得到隐藏设置属性的以下特性:
+
+- `Name`所有铸造的 NFT 的`隐藏`名称。最多可包含 32 个字符。
+- `URI`所有铸造的 NFT 的`隐藏`URI。最多可包含 200 个字符。
+- `Hash`将 NFT 索引与其真实 JSON 元数据映射的文件的 32 个字符哈希值,允许买家验证它没有被篡改。
+
+请注意,就像配置行设置`hiddenSettings`的前缀一样,隐藏设置的名称和 URI 可以使用特殊变量。提醒一下,这些变量是:
+
+- `$ID$`:替换成从 0 开始的 Item 索引。
+- `$ID+1$`:这将被从 1 开始的 Item 索引替换。
+
+另请注意,由于我们没有将任何物品放入糖果机,因此隐藏设置可以产生非常大的掉落。唯一的警告是,在铸造后,需要一个链下流程来更新每个 NFT 的名称和
+
+代码片段:
+
+```js
+// 要计算哈希值,您可以使用以下函数:
+import crypto from "crypto";
+
+const revealData = [
+ { name: "Nft #1", uri: "http://example.com/1.json" },
+ { name: "Nft #2", uri: "http://example.com/2.json" },
+ { name: "Nft #3", uri: "http://example.com/3.json" },
+];
+
+const string = JSON.stringify(revealData);
+const hashOfTheFileThatMapsUris = crypto
+ .createHash("sha256")
+ .update(string)
+ .digest();
+
+console.log(hashOfTheFileThatMapsUris);
+
+// 使用 Umi 时,你可以使用some和辅助函数分别通过和属性none告诉库是否使用配置行设置或隐藏设置。这两个设置只能使用一个,因此必须配置其中一个,并将另一个设置为。configLineSettingshiddenSettingsnone()
+
+// 以下代码片段展示了如何使用 Umi 库设置上述示例。
+
+import { some, none } from "@metaplex-foundation/umi";
+
+const candyMachineSettings = {
+ configLineSettings: none(),
+ hiddenSettings: some({
+ name: "My NFT Project #$ID+1$",
+ uri: "https://example.com/path/to/teaser.json",
+ hash: hashOfTheFileThatMapsUris,
+ }),
+};
+```
diff --git a/docs/SolanaBasic/011.md b/docs/SolanaBasic/011.md
new file mode 100644
index 0000000..f4511d3
--- /dev/null
+++ b/docs/SolanaBasic/011.md
@@ -0,0 +1,205 @@
+# 管理糖果机
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+在上一章节中,我们介绍了糖果机的各种设置。现在,让我们看看如何使用这些设置来创建和更新糖果机。我们还将学到如何获取现有的糖果机以及如何在它完成其使命后将其删除
+
+我们将经历糖果机的创建、读取、更新和删除步骤。我们开始吧!
+
+## 课程
+
+### 1.创建合集
+
+在创建糖果机之前,我们需要通过 Metaplex 的 SDK 创建一个 NFT 合集,糖果机必须与 Collection NFT 相关联,并且其更新权限必须授权此操作。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/1.CreateCollection.ts)
+
+```js
+// 随机创建collection mint账户keypair
+const collectionMint = generateSigner(umi);
+// 创建collection
+await createNft(umi, {
+ mint: collectionMint,
+ authority: signer,
+ name: "My Collection",
+ uri: "https://example.com/my-collection.json",
+ sellerFeeBasisPoints: percentAmount(5.5), // 5.5%
+ isCollection: true,
+}).sendAndConfirm(umi);
+```
+
+### 2.创建糖果机
+
+获得 Collection NFT 的账户地址之后,我们就可以创建糖果机了
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/2.CreateMachine.ts)
+
+```js
+// 创建糖果机账户keypair
+const candyMachine = generateSigner(umi);
+// 创建糖果机
+(
+ await create(umi, {
+ candyMachine: candyMachine, // 糖果机账户keypair
+ collectionMint: collectionMint, // Collection 合集地址
+ collectionUpdateAuthority: signer, // 合集更新权限
+ tokenStandard: TokenStandard.NonFungible, // Token类型
+ sellerFeeBasisPoints: percentAmount(9.99, 2), // 版税9.99%
+ itemsAvailable: 10, // 可插入的Item数量
+ creators: [
+ // 创建者
+ {
+ address: signer.publicKey, // 创建着地址
+ verified: true, // 是否验证
+ percentageShare: 100, // 版税占比100%
+ },
+ ],
+ configLineSettings: some({
+ // 配置行设置
+ prefixName: "My New NFT #$ID+1$", // 名称前缀
+ nameLength: 0, // 名称长度
+ prefixUri: "https://arweave.net/", // URI前缀
+ uriLength: 43, // URI长度
+ isSequential: false, // 随机排序
+ }),
+ })
+).sendAndConfirm(umi);
+```
+
+### 3.糖果机账户
+
+在创建糖果机之后,我们随时可以通过 SDK 的`fetchCandyMachine`函数获取糖果机当前状态
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/3.FetchCandyMachine.ts)
+
+```js
+const candyMachine = await fetchCandyMachine(umi, candyMachineAddress);
+console.log(candyMachine);
+```
+
+返回结果:
+
+```sh
+{
+ publicKey: 'AxHy37HkfL1yhyR9dSr6HtnNWum1swBC6gTkbXjWCqXH',
+ header: {
+ executable: false,
+ owner: 'CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR',
+ lamports: { basisPoints: 10175520n, identifier: 'SOL', decimals: 9 },
+ rentEpoch: 18446744073709551616n,
+ exists: true
+ },
+ discriminator: [
+ 51, 173, 177, 113,
+ 25, 241, 109, 189
+ ],
+ version: 1,
+ tokenStandard: 0,
+ features: [ 0, 0, 0, 0, 0, 0 ],
+ authority: 'CuiDdffKV38LjgRVtiA2QiMTKhnzkjX2LUxqSMbVnGjG',
+ mintAuthority: 'DBE4rMWcKwkH8WHdAd2hNr2QHa8breVjRZwpHuY1Yt6C',
+ collectionMint: '8jFyNfxQkoGAnBaX3KLsWbJgWE5JxDSN8i3H8ptDwm3C',
+ itemsRedeemed: 0n,
+ data: {
+ itemsAvailable: 10n,
+ symbol: '',
+ sellerFeeBasisPoints: { basisPoints: 999n, identifier: '%', decimals: 2 },
+ maxEditionSupply: 0n,
+ isMutable: true,
+ creators: [ [Object] ],
+ configLineSettings: { __option: 'Some', value: [Object] },
+ hiddenSettings: { __option: 'None' }
+ },
+ items: [],
+ itemsLoaded: 0,
+ ruleSet: { __option: 'None' }
+}
+```
+
+以上返回的信息中包含糖果机当前所有的状态,我们重点关注以下几个属性:
+
+- `itemsRedeemed`已兑换物品。这将跟踪从糖果机铸造的 NFT 数量。请注意,一旦此数字从 0 变为 1,大多数设置将不再可更新。
+- `version`账户版本。此枚举用于跟踪糖果机的账户版本。它用于确定哪些功能可用以及如何解释账户。请注意,不要将其与`糖果机 V3`混淆,后者指的是糖果机程序的第三个也是最新版本(包括糖果机核心和糖果守卫程序)。
+- `features`随着更多功能的引入,这有助于程序实现向后和向前的兼容性。
+
+### 4.更新权限
+
+一旦创建了糖果机,只要您是糖果机的管理员,您就可以稍后更新其大部分设置。在接下来的几节中,我们将了解如何更新这些设置,但首先,让我们看看如何更新糖果机的管理员和铸币管理员。
+
+- 要更新权限,需要传递当前权限作为签名者,以及新权限的地址。
+- 要更新铸币权限,您需要将当前权限和新铸币权限作为签名者传递。这是因为铸币权限主要用于将糖果守卫与糖果机关联起来。将铸币权限设为签名者可防止任何人使用其他人的糖果守卫,因为这可能会对原始糖果机产生副作用。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/4.SetAuthority.ts)
+
+```js
+const newAuthority = generateSigner(umi);
+await setCandyMachineAuthority(umi, {
+ candyMachine: candyMachine.publicKey,
+ authority: currentAuthority,
+ newAuthority: newAuthority.publicKey,
+})
+ .add(
+ setCandyGuardAuthority(umi, {
+ candyGuard: candyMachine.mintAuthority,
+ authority: currentAuthority,
+ newAuthority: newAuthority.publicKey,
+ })
+ )
+ .sendAndConfirm(umi);
+```
+
+### 5.更新共享属性
+
+您还可以更新糖果机所有铸造 NFT 之间共享的属性。如上一章节所述,这些属性包括:卖家费用基点、符号、最大版本供应量、是否可变和创建者。
+
+糖果机的物品设置也可以更新,但有一些限制。
+
+- 可以在`configLineSettings`配置行设置和`hiddenSettings`隐藏设置之间切换,如果不切换模式,也可以修改这些设置内部属性
+- 使用`configLineSettings`配置行设置时:
+ - 无法更新可用项目`itemsAvailable`属性。
+ - 名称长度`nameLength`和 URI 长度`uriLength`属性只能更新为较小的值,因为程序不会在更新期间调整 Candy Machine 帐户的大小。
+- 请注意,一旦铸造了第一个 NFT,这些属性就无法再更新。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/5.UpdateMachine.ts)
+
+```js
+// 创建一个新的Creator
+const newCreator = generateSigner(umi).publicKey;
+// 更新糖果机共享属性
+await updateCandyMachine(umi, {
+ candyMachine: candyMachine.publicKey,
+ data: {
+ ...candyMachine.data,
+ symbol: "NEW",
+ sellerFeeBasisPoints: percentAmount(5.5, 2),
+ creators: [{ address: newCreator, verified: false, percentageShare: 100 }],
+ hiddenSettings: none(),
+ configLineSettings: some({
+ type: "configLines",
+ prefixName: "My New NFT #$ID+1$",
+ nameLength: 0,
+ prefixUri: "https://arweave.net/",
+ uriLength: 43,
+ isSequential: true,
+ }),
+ },
+}).sendAndConfirm(umi);
+```
+
+### 6.删除糖果机
+
+一旦糖果机完全铸造完毕,它就完成了使命,可以安全处理掉了。这样,它的创建者就可以收回糖果机账户的存储成本,也可以收回糖果卫士账户的存储成本。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/6.DeleteMachine.ts)
+
+```js
+await deleteCandyMachine(umi, {
+ candyMachine: candyMachine.publicKey,
+}).sendAndConfirm(umi);
+
+await deleteCandyGuard(umi, {
+ candyGuard: candyMachine.mintAuthority,
+}).sendAndConfirm(umi);
+```
diff --git a/docs/SolanaBasic/012.md b/docs/SolanaBasic/012.md
new file mode 100644
index 0000000..7e4d46c
--- /dev/null
+++ b/docs/SolanaBasic/012.md
@@ -0,0 +1,69 @@
+# 插入项目
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+到目前为止,我们已经学会了如何创建和配置糖果机,但我们还没有看到如何在其中插入可以铸造成 NFT 的物品。因此,让我们在这个页面上解决这个问题。
+
+重要的是要记住,插入物品仅适用于使用配置行设置`configLineSettings`的糖果机。这是因为使用隐藏设置`hiddenSettings`从糖果机铸造的 NFT 都将共享相同的`隐藏`名称和 URI。
+
+## 课程
+
+### 1.上传 JSON 元数据
+
+要将物品放入糖果机,您需要为每个物品提供以下两个参数:
+
+- `name`:此 NFT Item 的名称。如果在配置行设置中提供了名称前缀,则您只能提供该前缀后面的名称部分。
+- `URI`:此 NFT Item 的 JSON 元数据的 URI。这里也排除了配置行设置中可能提供的 URI 前缀。
+
+如果您还没有准备好 NFT 的 URI,则首先需要逐个上传其 JSON 元数据。这可以使用链下解决方案(例如 AWS 或您自己的服务器)或链上解决方案(例如 Arweave 或 IPFS)。
+
+幸运的是,我们的 SDK 可以帮助您实现这一点。它们允许您上传 JSON 对象并检索其 URI。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/7.UploadMetadata.ts)
+
+```js
+import { createGenericFile } from "@metaplex-foundation/umi";
+import { irysUploader } from "@metaplex-foundation/umi-uploader-irys";
+
+// 加载irysUploader
+umi.use(irysUploader());
+// 读取图像文件
+const fileBuffer = fs.readFileSync(path.join("docs/public", "Whaler_logo.gif"));
+const file = createGenericFile(fileBuffer, "Whaler_logo.gif", {
+ contentType: "image/gif",
+});
+// 获取图像价格
+const uploadPrice = await umi.uploader.getUploadPrice([file]);
+// 上传图像
+const [imageUri] = await umi.uploader.upload([file]);
+// 上传json
+const uri = await umi.uploader.uploadJson({
+ name: "My NFT #1",
+ description: "My description",
+ image: imageUri,
+});
+```
+
+### 2.插入项目
+
+现在我们有了所有物品的名称和 URI,我们需要做的就是将它们插入我们的 Candy Machine 帐户。
+
+这是流程中的重要部分,当使用配置行设置`configLineSettings`时,只有在插入所有项目后才允许铸造。
+
+请注意,每个插入项目的名称和 URI 分别受配置行设置的名称长度和 URI 长度属性的约束。
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/8.AddConfigLines.ts)
+
+```js
+// 插入项目
+await addConfigLines(umi, {
+ candyMachine: candyMachine.publicKey,
+ index: candyMachine.itemsLoaded,
+ configLines: [
+ { name: "My NFT #1", uri: "https://example.com/nft1.json" },
+ { name: "My NFT #2", uri: "https://example.com/nft2.json" },
+ ],
+}).sendAndConfirm(umi);
+```
diff --git a/docs/SolanaBasic/013.md b/docs/SolanaBasic/013.md
new file mode 100644
index 0000000..e49742f
--- /dev/null
+++ b/docs/SolanaBasic/013.md
@@ -0,0 +1,113 @@
+# 糖果卫士
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+现在我们知道了糖果机的工作原理和如何装载它们,现在是时候讨论拼图的最后一块了:`Guard`。
+
+`Guard`模块是一段模块化代码,可以限制对糖果机铸币权限的访问,甚至可以为其添加新功能!
+
+有大量的`Guard`设置可供选择,每个`Guard`设置都可以随意激活和配置。
+
+我们将在本文档的后面介绍所有可用的保护,但让我们通过这里的几个例子来说明这一点。
+
+- 当启用`开始日期`保护时,在预设日期之前禁止铸造。还有一个`结束日期`保护,用于在给定日期之后禁止铸造。
+- 启用`Sol 支付`保护后,铸币钱包必须向配置的目标钱包支付配置的金额。或者可以使用特定集合的代币或 NFT 付款。
+- `代币门` (Token Gate)和`NFT 门` (NFT Gate)Guard 分别将铸造限制给特定的代币持有者和 NFT 持有者。
+- `允许列表`保护仅当钱包属于预定义钱包列表的一部分时才允许铸币。有点像铸币的嘉宾名单。
+
+如您所见,每个 Guard 只负责一项职责,这使得它们可组合。换句话说,您可以挑选所需的 Guard 来创建完美的糖果机。
+
+## 课程
+
+### 1.糖果卫士账号
+
+如果你还记得我们的 Candy Machine 账户的内容,你就不会在那里看到任何守卫的迹象。这是因为守卫住在另一个名为`Candy Guard`账户的账户中,该账户是由`Candy Guard`程序创建的。
+
+每个 Candy Machine 帐户通常应与其自己的`Candy Guard`帐户相关联,这将为其增加一层保护。
+
+实现方法是创建一个`Candy Guard`账户,并使其成为 Candy Machine 账户的`Mint Authority`。这样一来,就无法再直接从主`Candy Machine`程序(称为 Candy Machine Core 程序)进行铸造。相反,我们必须通过`Candy Guard`程序进行铸造,如果所有保护都成功解决,则将交给`Candy Machine Core`程序来完成铸造过程。
+
+![candy-guard-account](/candy-guard-account.png)
+
+请注意,由于 Candy Machine 和 Candy Guard 账户协同工作,我们的 SDK 将它们视为一个实体。当您使用我们的 SDK 创建 Candy Machine 时,默认情况下还会创建一个关联的 Candy Guard 账户。更新 Candy Machines 时也是如此,因为它们允许您同时更新防护装置。我们将在本页上看到一些具体示例。
+
+### 2.为什么是另一个程序?
+
+守卫不驻留在糖果机主程序中的原因是为了将访问控制逻辑与糖果机的主要职责(即铸造 NFT)分开。
+
+这使得防护装置不仅模块化,而且可扩展。任何人都可以创建和部署自己的 Candy Guard 程序来创建自定义防护装置,同时依靠 Candy Machine Core 程序完成其余所有工作。
+
+![candy-guard-another-program](/candy-guard-another-program.png)
+
+请注意,我们的 SDK 还提供注册您自己的 Candy Guard 程序及其自定义防护装置的方法,以便您可以利用其友好的 API 并轻松地与他人共享您的防护装置。
+
+### 3.所有可用 Guard
+
+现在我们了解了什么是 Guard,让我们看看我们可以使用哪些默认 Guard。
+
+- 地址门:将铸币限制在一个地址。
+- 允许列表:使用钱包地址列表来确定谁被允许铸造。
+- 机器人税:可配置的税,用于收取无效交易的费用。
+- 结束日期:确定结束铸币的日期。
+- 冻结 Sol 支付:设置 SOL 铸币价格,并设定冻结期。
+- 冻结代币支付:设置代币铸币价格,并设定冻结期。
+- Gatekeeper:通过 Gatekeeper 网络限制铸造,例如 Captcha 集成。
+- 铸币限制:指定每个钱包的铸币数量限制。
+- NFT 销毁:将铸币限制为指定收藏品的持有者,要求销毁 NFT。
+- Nft Gate:将铸币限制为指定收藏品的持有者。
+- Nft 支付:将铸币的价格设定为指定收藏品的 NFT。
+- 赎回金额:根据铸造的总金额确定铸造的结束时间。
+- SOL 支付:以 SOL 设定铸币的价格。
+- 开始日期:确定铸币的开始日期。
+- 第三方签名者:交易中需要额外的签名者。
+- 代币销毁:将铸币限制为指定代币的持有者,要求销毁代币。
+- 代币门:将铸币权限制为指定代币的持有者。
+- 代币支付:以代币数量设定铸币价格。
+
+### 4.创建一个带守卫的糖果机
+
+到目前为止,我们创建的糖果机尚未启用任何防护装置。现在我们知道了所有可用的防护装置,让我们看看如何设置启用一些防护装置的新型糖果机。
+
+具体实现取决于您使用的 SDK(见下文),但主要思想是通过提供所需的设置来启用防护。任何未设置的防护都将被禁用。
+
+```js
+import { some, sol, dateTime } from "@metaplex-foundation/umi";
+
+await create(umi, {
+ // ...
+ guards: {
+ botTax: some({ lamports: sol(0.01), lastInstruction: true }),
+ solPayment: some({ lamports: sol(1.5), destination: treasury }),
+ startDate: some({ date: dateTime("2023-04-04T16:00:00Z") }),
+ // All other guards are disabled...
+ },
+}).sendAndConfirm(umi);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/2.CreateMachine.ts)
+
+### 5.更新守卫
+
+你的 Guard 设置有误吗?你改变了铸币价格的想法吗?你需要稍微推迟铸币的开始时间吗?不用担心,可以按照创建时使用的相同设置轻松更新 Guard。
+
+您可以通过提供设置来启用新的防护装置,或者通过给它们空的设置来禁用当前的防护装置。
+
+您可以按照创建糖果机防护装置的方式更新它们。也就是说,通过在`guards`函数对象内提供它们的设置`updateCandyGuard`。任何设置为`none()`或未提供的防护装置都将被禁用。
+
+请注意,整个`guards`对象将被更新,这意味着它将覆盖所有现有的保护!
+
+```js
+import { some, sol, none } from "@metaplex-foundation/umi";
+
+const candyGuard = fetchCandyGuard(umi, candyMachine.mintAuthority);
+await updateCandyGuard(umi, {
+ candyGuard: candyGuard.publicKey,
+ guards: {
+ ...candyGuard.guards,
+ botTax: none(),
+ solPayment: some({ lamports: sol(3), destination: treasury }),
+ },
+});
+```
diff --git a/docs/SolanaBasic/014.md b/docs/SolanaBasic/014.md
new file mode 100644
index 0000000..b2a0ad3
--- /dev/null
+++ b/docs/SolanaBasic/014.md
@@ -0,0 +1,183 @@
+# 卫士组
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+在上一章节中,我们引入了保护机制,并使用它们来定义糖果机的访问控制。我们已经看到,使用保护机制,我们可以例如添加每枚糖果 1 SOL 的付款,并确保糖果在某个日期后开始铸造。但如果我们还想在第二个日期后收取 2 SOL 怎么办?如果我们想允许某些代币持有者免费或以折扣价铸造糖果怎么办?
+
+如果我们可以定义多组卫士,每组都有自己的要求,会怎么样?为此,我们创建了卫士组!
+
+## 课程
+
+### 1.运作方式
+
+还记得我们只需提供想要启用的`Guard`设置,就可以在任何糖果机上设置`Guard`吗?好吧,`Guard Group`的工作方式相同,只是您还必须为他们提供唯一的标签来识别它们。
+
+因此,每个`Guard Group`都具有以下属性:
+
+- 第一组:
+ - `label`:"早鸟"
+ - `guards`:
+ - SOL 付款:1 SOL
+ - 开始时间:下午 4 点
+ - 结束时间:下午 5 点
+ - 机器人税:0.001 SOL
+- 第二组:
+ - `label`:"公售"
+ - `guards`:
+ - SOL 付款:2 SOL
+ - 开始时间:下午 5 点
+ - 机器人税:0.001 SOL
+
+就这样,我们创建了一个定制的两层铸造流程!
+
+现在,每当有人尝试从我们的糖果机铸造糖果时,他们都必须明确告诉我们他们从哪个组铸造糖果。铸造糖果时询问组标签很重要,因为:
+
+- 它确保买家不会遇到意外的铸造行为。假设我们试图在第一个组的结束日期快结束时铸造 1 SOL,但到交易执行时,我们已经过了那个日期。如果我们不要求组标签,交易就会成功,我们会被收取 2 SOL,尽管我们预计只会被收取 1 SOL。
+- 它使得支持并行组成为可能。我们将在本页的后面部分详细讨论这一点。
+
+![candy-guard-group](/candy-guard-group.png)
+
+```js
+import { some, sol, dateTime } from "@metaplex-foundation/umi";
+
+const candyGuard = await fetchCandyGuard(umi, candyMachine.mintAuthority);
+await updateCandyGuard(umi, {
+ candyGuard: candyGuard.publicKey,
+ guards: candyGuard.guards,
+ groups: [
+ {
+ label: "early",
+ guards: {
+ solPayment: some({ lamports: sol(1), destination: treasury }),
+ startDate: some({ date: dateTime("2024-7-1T16:00:00Z") }),
+ endDate: some({ date: dateTime("2024-7-1T17:00:00Z") }),
+ botTax: some({ lamports: sol(0.001), lastInstruction: true }),
+ },
+ },
+ {
+ label: "public",
+ guards: {
+ solPayment: some({ lamports: sol(3), destination: treasury }),
+ startDate: some({ date: dateTime("2024-7-1T17:00:00Z") }),
+ botTax: some({ lamports: sol(0.001), lastInstruction: true }),
+ },
+ },
+ ],
+}).sendAndConfirm(umi);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/9.UpdateGuard.ts)
+
+### 2.默认卫士
+
+请注意,在上面的例子中,我们必须为两个组提供相同的`Bot Tax`保护。这可以通过利用在 Candy Machine 上设置的`全局 Guard`来简化。
+
+使用`Guard Group`时,糖果机的`全局 Guard`将充当默认 Guard!这意味着组将默认使用与`全局 Guard`相同的 Guard 设置,除非它们通过在组中明确启用它们来覆盖它们。
+
+以下是简要回顾:
+
+- 如果在`默认Guard`上启用了某个规则但未在`Guard Group`上启用这个规则,则使用`默认Guard`中定义的规则。
+- 如果在`默认Guard`和`Guard Group`都启用了规则,则使用`Guard Group`中定义的规则。
+- 如果`默认Guard`或`Guard Group`都没有启用的规则,则不会使用此规则。
+
+- `默认Guard`:
+ - 机器人税:0.001 SOL
+- 第一组:
+ - `label`:"早鸟"
+ - `guards`:
+ - SOL 付款:1 SOL
+ - 开始时间:下午 4 点
+ - 结束时间:下午 5 点
+- 第二组:
+ - `label`:"公售"
+ - `guards`:
+ - SOL 付款:2 SOL
+ - 开始时间:下午 5 点
+
+正如您所见,`默认Guard`有助于避免组内重复。
+
+![candy-guard-default](/candy-guard-default.png)
+
+请注意,即使使用`默认Guard`,铸造时也必须提供一个组。这意味着,当使用守卫组时,不能仅使用`默认Guard`进行铸造。
+
+```js
+import { some, sol, dateTime } from "@metaplex-foundation/umi";
+
+await create(umi, {
+ // ...
+ guards: {
+ botTax: some({ lamports: sol(0.001), lastInstruction: true }),
+ },
+ groups: [
+ {
+ label: "early",
+ guards: {
+ solPayment: some({ lamports: sol(1), destination: treasury }),
+ startDate: some({ date: dateTime("2024-7-1T16:00:00Z") }),
+ endDate: some({ date: dateTime("2024-7-1T17:00:00Z") }),
+ },
+ },
+ {
+ label: "late",
+ guards: {
+ solPayment: some({ lamports: sol(2), destination: treasury }),
+ startDate: some({ date: dateTime("2024-7-1T17:00:00Z") }),
+ },
+ },
+ ],
+}).sendAndConfirm(umi);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/9.UpdateGuard.ts)
+
+### 3.平行组
+
+在铸造时要求组标签的一个真正有趣的好处是能够在给定时间内拥有多个有效组。这消除了程序的任何歧义,并允许购买者选择他们想要尝试铸造的组。
+
+让我们用一个新的例子来说明这一点。假设我们有一个名为"无辜鸟"的 NFT 系列,我们想为任何持有"无辜鸟" NFT 的人提供 1 SOL 的折扣价,并向其他任何人收取 2 SOL。我们希望这两个组能够同时开始铸造 - 比如下午 4 点 - 并且我们还希望保护这两个组免受机器人的攻击。以下是我们可以配置防护的方法:
+
+- `默认Guard`:
+ - 开始时间:下午 4 点
+ - 机器人税:0.001 SOL
+- 第一组:
+ - `label`:"nft"
+ - `guards`:
+ - SOL 付款:1 SOL
+ - NFT 门:"无辜鸟"收藏品
+- 第二组:
+ - `label`:"公售"
+ - `guards`:
+ - SOL 付款:2 SOL
+
+如您所见,通过这些保护设置,两个组可以同时铸造。如果 NFT 持有者决定从"公售"组铸造,他们甚至可以支付全部 2 SOL。但是,如果可以的话,选择"nft"组对他们最有利。
+
+```js
+import { some, sol, dateTime } from "@metaplex-foundation/umi";
+
+await create(umi, {
+ // ...
+ guards: {
+ botTax: some({ lamports: sol(0.001), lastInstruction: true }),
+ startDate: some({ date: dateTime("2024-7-1T16:00:00Z") }),
+ },
+ groups: [
+ {
+ label: "early",
+ guards: {
+ solPayment: some({ amount: sol(1), destination: treasury }),
+ nftGate: some({
+ requiredCollection: innocentBirdCollectionNft.publicKey,
+ }),
+ },
+ },
+ {
+ label: "public",
+ guards: {
+ solPayment: some({ amount: sol(2), destination: treasury }),
+ },
+ },
+ ],
+}).sendAndConfirm(umi);
+```
diff --git a/docs/SolanaBasic/015.md b/docs/SolanaBasic/015.md
new file mode 100644
index 0000000..7097963
--- /dev/null
+++ b/docs/SolanaBasic/015.md
@@ -0,0 +1,178 @@
+# 铸造
+
+> 作者 崔棉大师 X:[@MasterCui](https://x.com/@MasterCui) Youtube: [崔棉大师](https://www.youtube.com/channel/UCv4y5qSUbJ8UC3CUmBPC_BA)
+
+## 知识点
+
+到目前为止,我们已经学习了如何创建和维护糖果机。我们已经了解了如何配置它们以及如何使用 Guard 和 Guard Group 设置复杂的铸造工作流程。现在是时候讨论拼图的最后一块了:铸造!
+
+## 课程
+
+### 1.基本铸币
+
+正如在 Candy Guards 页面中提到的,有两个程序负责从 Candy Machines 铸造 NFT:Candy Machine Core 程序(负责铸造 NFT)和 Candy Guard 程序,它在其之上添加了一个可配置的访问控制层,并可以分叉以提供自定义保护。
+
+因此,有两种方法可以从糖果机中铸造糖果:
+
+- 来自 Candy Guard 程序,该程序随后将铸币委托给 Candy Machine Core 程序。大多数情况下,您会希望这样做,因为它允许更复杂的铸币工作流程。您可能需要根据帐户中配置的保护将额外的剩余帐户和指令数据传递给铸币指令。幸运的是,我们的 SDK 通过要求一些额外的参数并为我们计算其余部分,使这变得简单。
+- 直接从 Candy Machine Core 程序中获取。在这种情况下,只有配置的铸币机构才能从中铸币,因此它需要签署交易。
+
+![candy-machine-mint](/candy-machine-mint.png)
+
+如果一切顺利,将根据糖果机中配置的参数创建一个 NFT。例如,如果给定的糖果机使用配置行设置并将"顺序"设置为 false,那么我们将随机获取下一个项目。
+
+```js
+import { mintV2 } from "@metaplex-foundation/mpl-candy-machine";
+import { setComputeUnitLimit } from "@metaplex-foundation/mpl-toolbox";
+import { transactionBuilder, generateSigner } from "@metaplex-foundation/umi";
+
+const nftMint = generateSigner(umi);
+await transactionBuilder()
+ .add(setComputeUnitLimit(umi, { units: 800_000 }))
+ .add(
+ mintV2(umi, {
+ candyMachine: candyMachine.publicKey,
+ nftMint,
+ collectionMint: collectionNft.publicKey,
+ collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
+ tokenStandard: candyMachine.tokenStandard,
+ })
+ )
+ .sendAndConfirm(umi);
+```
+
+[完整代码](https://github.com/Fankouzu/solana-basic-ui/tree/main/scripts/5.CandyMachine/10.Mint.ts)
+
+### 2.有守卫的铸币
+
+当使用 Guards 的糖果机铸造糖果时,您可能需要提供额外的 Guards 特定信息。
+
+如果您要手动构建铸币指令,则该信息将作为指令数据和剩余账户的混合提供。但是,使用我们的 SDK,每个在铸币时需要额外信息的 Guards 都会定义一组设置,我们称之为铸币设置。然后,这些铸币设置将被解析为程序所需的任何内容。
+
+需要通过 Guards 铸币的一个很好的例子是`使用 NFT 支付`规则,它需要 NFT 的铸币地址,我们应该使用 NFT 的铸币地址来支付铸币等费用。
+
+![candy-machine-mint-guard](/candy-machine-mint-guard.png)
+
+```js
+import {
+ some,
+ generateSigner,
+ transactionBuilder,
+} from "@metaplex-foundation/umi";
+import { create, mintV2 } from "@metaplex-foundation/mpl-candy-machine";
+import { setComputeUnitLimit } from "@metaplex-foundation/mpl-toolbox";
+
+// Create a Candy Machine with guards.
+const thirdPartySigner = generateSigner();
+await create(umi, {
+ // ...
+ guards: {
+ thirdPartySigner: some({ signer: thirdPartySigner.publicKey }),
+ mintLimit: some({ id: 1, limit: 3 }),
+ },
+}).sendAndConfirm(umi);
+
+// Mint from the Candy Machine.
+const nftMint = generateSigner(umi);
+await transactionBuilder()
+ .add(setComputeUnitLimit(umi, { units: 800_000 }))
+ .add(
+ mintV2(umi, {
+ candyMachine: candyMachine.publicKey,
+ nftMint,
+ collectionMint: collectionNft.publicKey,
+ collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
+ mintArgs: {
+ thirdPartySigner: some({ signer: thirdPartySigner }),
+ mintLimit: some({ id: 1 }),
+ },
+ })
+ )
+ .sendAndConfirm(umi);
+```
+
+### 3.有守卫组的铸造
+
+当使用保护组从糖果机铸造糖果时,我们必须通过提供其标签明确选择我们想要从哪个组铸造糖果。
+
+此外,可能还需要 Mint 设置,如上一节所述。但是,Mint 设置将应用于所选组的"已解决的守卫"。
+例如,想象一个糖果机有以下保护装置:
+
+- `默认Guard`:
+ - 机器人税:0.001 SOL
+ - 第三方签名者
+ - 开始时间:下午 5 点
+- 第一组:
+ - `label`:"nft"
+ - `guards`:
+ - 使用 NFT 支付
+ - 开始时间:下午 4 点
+- 第二组:
+ - `label`:"公售"
+ - `guards`:
+ - SOL 付款:2 SOL
+
+第一组的已解析守卫(标记为"nft")是:
+
+- 机器人税:来自默认 Guard。
+- 第三方签名者:来自默认 Guard。
+- NFT 付款:来自第一组。
+- 开始日期:从第一组开始,因为它覆盖了默认 Guard。
+
+因此,提供的 Mint Settings 必须与这些 Resolved Guards 相关。在上面的示例中,必须为 Third Party Signer Guard 和 NFT Payment Guard 提供 Mint Settings。
+
+![candy-machine-mint-group](/candy-machine-mint-group.png)
+
+```js
+// 创建第三方签名人keypair
+const thirdPartySigner = generateSigner();
+// 创建NFT
+await create(umi, {
+ // guard默认规则
+ guards: {
+ botTax: some({ lamports: sol(0.001), lastInstruction: true }),
+ thirdPartySigner: some({ signer: thirdPartySigner.publicKey }),
+ startDate: some({ date: dateTime("2024-7-1T17:00:00Z") }),
+ },
+ // group规则
+ groups: [
+ {
+ label: "nft",
+ guards: {
+ nftPayment: some({ requiredCollection, destination: nftTreasury }),
+ startDate: some({ date: dateTime("2024-7-1T16:00:00Z") }),
+ },
+ },
+ {
+ label: "public",
+ guards: {
+ solPayment: some({ lamports: sol(1), destination: solTreasury }),
+ },
+ },
+ ],
+}).sendAndConfirm(umi);
+
+// 创建NFT item的keypair账户
+const nftMint = generateSigner(umi);
+// 铸造
+await transactionBuilder()
+ .add(setComputeUnitLimit(umi, { units: 800_000 }))
+ .add(
+ mintV2(umi, {
+ candyMachine: candyMachine.publicKey,
+ nftMint,
+ collectionMint: collectionNft.publicKey,
+ collectionUpdateAuthority: collectionNft.metadata.updateAuthority,
+ group: some("nft"), // 组标签
+ mintArgs: {
+ thirdPartySigner: some({ signer: thirdPartySigner }), // 第三方签名
+ nftPayment: some({
+ mint: nftFromRequiredCollection.publicKey, // 用于支付的NFT
+ destination: nftTreasury, // 接收支付NFT的地址
+ tokenStandard: TokenStandard.NonFungible, // NFT标准
+ }),
+ },
+ })
+ )
+ .sendAndConfirm(umi);
+```
diff --git a/docs/SolanaDocumention/programs/lang-c.md b/docs/SolanaDocumention/programs/lang-c.md
index e69de29..66de187 100644
--- a/docs/SolanaDocumention/programs/lang-c.md
+++ b/docs/SolanaDocumention/programs/lang-c.md
@@ -0,0 +1,127 @@
+# 使用C语言开发
+
+Solana支持使用C和C++编写链上程序。
+
+## 项目结构
+
+C项目布局如下:
+
+```text
+/src/<程序名>
+/makefile
+```
+
+`makefile`应包含以下内容:
+
+```makefile
+OUT_DIR := <放置生成的共享对象的路径>
+include ~/.local/share/solana/install/active_release/bin/sdk/sbf/c/sbf.mk
+```
+
+sbf-sdk可能不在上述的位置,但如果你按照[构建方法](#how-to-build)设置环境,那么它应该会在正确的位置。
+
+## 构建方法
+
+首先设置环境:
+
+- 从 https://rustup.rs 安装最新的Rust稳定版
+- 安装最新的[Solana命令行工具](https://docs.solanalabs.com/cli/install)
+
+然后使用make进行构建:
+
+```shell
+make -C <程序目录>
+```
+
+## 测试方法
+
+Solana使用[Criterion](https://github.com/Snaipe/Criterion)测试框架,每次构建程序时都会执行测试 [构建方法](#how-to-build)。
+
+要添加测试,在源文件旁边创建一个名为 `test_<程序名>.c` 的新文件,并填充 Criterion 测试用例。有关如何编写测试用例的信息,请参阅[Criterion文档](https://criterion.readthedocs.io/en/master)。
+
+## 程序入口点
+
+程序导出一个已知的入口点方法,Solana 运行时在调用程序时查找并调用该方法。Solana 支持多个版本的 SBF 加载器,入口点可能因加载器而异。程序必须针对相同的加载器编写并部署。有关更多详细信息,请参阅 [FAQ](https://solana.com/docs/programs/faq.md#loaders)中关于加载器的部分。
+
+目前有两个支持的加载器:[SBF Loader](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader.rs#L17)和[SBF Loader deprecated](https://github.com/solana-labs/solana/blob/7ddf10e602d2ed87a9e3737aa8c32f1db9f909d8/sdk/program/src/bpf_loader_deprecated.rs#L14)。
+
+它们都具有相同的原始入口点定义,以下是运行时查找和调用的原始方法:
+
+```c
+extern uint64_t entrypoint(const uint8_t *input)
+```
+
+此入口点接受一个包含序列化程序参数(程序 ID、账户、指令数据等)的通用字节数组。要反序列化参数,每个加载器都包含自己的[辅助函数](#serialization)。
+
+### 序列化
+
+每个加载器提供一个辅助函数,将程序的输入参数反序列化为C类型:
+
+- [SBF Loader反序列化](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L304)
+- [SBF Loader deprecated反序列化](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/deserialize_deprecated.h#L25)
+
+一些程序可能希望自己进行反序列化,它们可以通过提供自己的[原始入口点](#program-entrypoint)实现。这些提供的反序列化函数会保留对序列化字节数组的引用,以便程序允许修改的变量(例如 lamports、账户数据)。如果程序实现自己的反序列化函数,它们需要确保程序希望提交的任何修改都必须写回输入字节数组。
+
+有关加载器如何序列化程序输入的详细信息,请参见[输入参数序列化](https://solana.com/docs/programs/faq#input-parameter-serialization)文档。
+
+## 数据类型
+
+加载器的反序列化辅助函数会填充[SolParameters](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/solana_sdk.h#L276)结构:
+
+```c
+/**
+ * 结构体:程序的入口点输入数据被反序列化到该结构体中。
+ */
+typedef struct {
+ SolAccountInfo* ka; /** 指向 SolAccountInfo 数组的指针,必须已经指向一个 SolAccountInfo 数组 */
+ uint64_t ka_num; /** `ka` 中 SolAccountInfo 条目的数量 */
+ const uint8_t *data; /** 指向指令数据的指针 */
+ uint64_t data_len; /** 指令数据的字节长度 */
+ const SolPubkey *program_id; /** 当前执行程序的 program_id */
+} SolParameters;
+
+```
+
+'ka'是指令引用的账户的有序数组,表示为[SolAccountInfo](https://github.com/solana-labs/solana/blob/8415c22b593f164020adc7afe782e8041d756ddf/sdk/sbf/c/inc/solana_sdk.h#L173)结构。数组中账户的位置表示其含义,例如,当转移 lamports 时,指令可以将第一个账户定义为源账户,将第二个账户定义为目标账户。
+
+`SolAccountInfo` 结构的成员是只读的,除了 `lamports` 和 `data`。根据“运行时强制策略”,程序可以修改这两者。当指令多次引用相同账户时,数组中可能会有重复的 `SolAccountInfo` 条目,但它们都指向原始输入字节数组。程序应谨慎处理这些情况,以避免对同一缓冲区进行重叠的读/写操作。如果程序实现自己的反序列化函数,则应适当处理重复账户。
+
+`data`是来自正在处理指令的[指令数据](https://solana.com/docs/core/transactions.md#instruction)的通用字节数组。
+
+`program_id`是当前执行程序的公钥。
+
+## 堆
+
+C程序可以通过系统调用[`calloc`](https://github.com/solana-labs/solana/blob/c3d2d2134c93001566e1e56f691582f379b5ae55/sdk/sbf/c/inc/solana_sdk.h#L245)分配内存,或在从虚拟地址x300000000开始的32KB堆区域上实现自己的堆。堆区域也被`calloc`使用,因此如果程序实现了自己的堆,则不调用`calloc`。
+
+## 日志
+
+运行时提供了两个系统调用,它们可以接受数据并将其记录到程序日志中。
+
+- [`sol_log(const char*)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L128)
+- [`sol_log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)`](https://github.com/solana-labs/solana/blob/d2ee9db2143859fa5dc26b15ee6da9c25cc0429c/sdk/sbf/c/inc/solana_sdk.h#L134)
+
+[调试debug](https://solana.com/docs/programs/debugging.md#logging)部分有更多关于使用程序日志的信息。
+
+## 计算预算
+
+使用系统调用`sol_remaining_compute_units()`返回一个`u64`,表示此交易剩余的计算单元数。
+
+使用系统调用[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d3a3a7548c857f26ec2cb10e270da72d373020ec/sdk/sbf/c/inc/solana_sdk.h#L140)记录包含程序在执行停止之前可以消耗的剩余计算单位数的消息。
+
+有关更多信息,请参见[计算预算](https://solana.com/docs/core/fees.md#compute-budget)文档。
+
+## ELF转储
+
+可以将 SBF 共享对象的内部内容转储到文本文件中,以便更深入地了解程序的组成及其在运行时可能执行的操作。转储将包含 ELF 信息以及所有符号的列表和实现它们的指令。一些 SBF 加载器的错误日志消息将引用发生错误的特定指令号。这些引用可以在 ELF 转储中查找,以识别出错的指令及其上下文。
+
+要创建转储文件:
+
+```shell
+cd <程序目录>
+make dump_<程序名>
+```
+
+## 示例
+
+[Solana程序库的github仓库](https://github.com/solana-labs/solana-program-library/tree/master/examples/c)包含一系列C语言示例。
diff --git a/docs/SolanaDocumention/programs/lang-rust.md b/docs/SolanaDocumention/programs/lang-rust.md
index e69de29..d7aa847 100644
--- a/docs/SolanaDocumention/programs/lang-rust.md
+++ b/docs/SolanaDocumention/programs/lang-rust.md
@@ -0,0 +1,284 @@
+# 使用Rust进行开发
+
+Solana支持使用[Rust](https://www.rust-lang.org/)编程语言编写链上程序。
+
+::: tip HELLO WORLD: 开始 SOLANA 开发
+
+要快速开始Solana开发并构建你的第一个Rust程序,请查看这些详细的快速入门指南:
+
+- [使用浏览器构建和部署你的第一个Solana程序](https://solana.com/content/guides/getstarted/hello-world-in-your-browser.md)。无需安装IDE。
+- [设置本地环境](https://solana.com/content/guides/getstarted/setup-local-development.md)并使用本地测试验证器。
+
+:::
+
+## 项目结构
+
+Solana Rust程序遵循典型的[Rust项目结构](https://doc.rust-lang.org/cargo/guide/project-layout.html):
+
+```text
+/inc/
+/src/
+/Cargo.toml
+```
+
+Solana Rust程序可以直接依赖于其他程序,以便在进行[跨程序调用](https://solana.com/docs/core/cpi.md)时访问指令帮助程序。这样做时,重要的是不要引入依赖程序的入口点函数标识,因为它们可能与程序自身的入口点冲突。为避免这种情况,程序应在`Cargo.toml`中定义一个`no-entrypoint`特性,并使用它来排除入口点。
+
+- [定义特性](https://github.com/solana-labs/solana-program-library/blob/fca9836a2c8e18fc7e3595287484e9acd60a8f64/token/program/Cargo.toml#L12)
+- [排除入口点](https://github.com/solana-labs/solana-program-library/blob/fca9836a2c8e18fc7e3595287484e9acd60a8f64/token/program/src/lib.rs#L12)
+
+然后,当其他程序将此程序作为依赖项包含时,应使用`no-entrypoint`特性。
+
+- [不包含入口点](https://github.com/solana-labs/solana-program-library/blob/fca9836a2c8e18fc7e3595287484e9acd60a8f64/token-swap/program/Cargo.toml#L22)
+
+## 项目依赖
+
+所有的Solana Rust程序必须引入[`solana-program`](https://crates.io/crates/solana-program) 包。
+
+Solana SBF程序有一些[限制](#restrictions),可能会阻止某些包作为依赖项的引入或需要特殊处理。
+
+例如:
+
+- 需要架构是官方工具链支持的子集的包。除非该包被分叉并添加SBF到那些架构检查中,否则没有解决办法。
+- 依赖于`rand`的包在Solana的确定性程序环境中不受支持。要包含依赖于`rand`的包,请参阅[依赖Rand](#depending-on-rand)。
+- 即使程序本身不包含堆栈溢出的代码,包也可能会导致堆栈溢出。有关更多信息,请参阅[堆栈](https://solana.com/docs/programs/faq.md#stack)。
+
+## 构建方法
+
+首先设置环境:
+
+- 从 https://rustup.rs/ 安装最新的Rust稳定版本
+- 安装最新的[Solana命令行工具](https://docs.solanalabs.com/cli/install)
+
+也可以使用普通的cargo build在主机上构建程序,用于单元测试:
+
+```shell
+cargo build
+```
+
+要为Solana SBF目标构建特定程序(如SPL Token),以便部署到集群:
+
+```shell
+cd <程序目录>
+cargo build-bpf
+```
+
+## 测试方法
+
+Solana程序可以用直接执行程序函数方法通过传统的`cargo test`机制进行单元测试,。
+
+为了帮助在更接近真实集群的环境中进行测试,开发人员可以使用[`program-test`](https://crates.io/crates/solana-program-test) 包来启动一个本地运行的实例,并允许测试在持续运行的情况下发送多个交易。
+
+有关更多信息,请参阅[系统变量示例测试](https://github.com/solana-labs/solana-program-library/blob/master/examples/rust/sysvar/tests/functional.rs),此示例展示了如何发送和处理包含系统变量账户的指令。
+
+## 程序入口点
+
+程序导出一个已知的入口点函数标识,Solana运行时在调用程序时会查找并调用该函数标识。Solana支持多个版本的BPF加载器,入口点在它们之间可能有所不同。程序必须为相同的加载器编写并部署。有关更多详细信息,请参阅[加载器FAQ部分](https://solana.com/docs/programs/faq.md#loaders)。
+
+目前有两个支持的加载器:[BPF Loader](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/bpf_loader.rs#L17)和[BPF Loader deprecated](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/bpf_loader_deprecated.rs#L14)
+
+它们都有相同的初始入口点定义,以下是运行时查找并调用的初始函数标识:
+
+```rust
+#[no_mangle]
+pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64;
+```
+
+这个入口点接受一个通用的字节数组,其中包含序列化的程序参数(程序id、账户、指令数据等)。要反序列化参数,每个加载器都包含自己的包装宏,该宏导出初始入口点,反序列化参数,调用用户定义的指令处理函数,并返回结果。
+
+你可以在这里找到入口点宏:
+
+- [BPF Loader的入口点宏](https://github.com/solana-labs/solana/blob/9b1199cdb1b391b00d510ed7fc4866bdf6ee4eb3/sdk/program/src/entrypoint.rs#L42)
+- [BPF Loader deprecated的入口点宏](https://github.com/solana-labs/solana/blob/9b1199cdb1b391b00d510ed7fc4866bdf6ee4eb3/sdk/program/src/entrypoint_deprecated.rs#L38)
+
+入口点宏调用的程序定义的指令处理函数必须采用以下形式:
+
+```rust
+pub type ProcessInstruction =
+ fn(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult;
+```
+
+### 参数反序列化
+
+每个加载器提供一个帮助函数,将程序的输入参数反序列化为Rust类型。入口点宏会自动调用反序列化帮助函数:
+
+- [BPF Loader反序列化](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L146)
+- [BPF Loader deprecated反序列化](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint_deprecated.rs#L57)
+
+一些程序可能希望自己执行反序列化,它们可以通过提供自己的[初始入口点](#program-entrypoint)实现来实现这一点。请注意,提供的反序列化函数会保留对序列化字节数组的引用,用于程序允许修改的变量(lamports、账户数据)。这样做的原因是返回时加载器会读取这些修改,以便提交。如果程序实现了自己的反序列化函数,它们需要确保程序希望提交的任何修改都写回到输入字节数组中。
+
+有关加载器如何序列化程序输入的详细信息,请参阅[输入参数序列化](https://solana.com/docs/programs/faq.md#input-parameter-serialization)文档。
+
+### 数据类型
+
+加载程序器的入口点宏使用以下参数调用程序定义的指令处理器函数:
+
+```rust
+program_id: &Pubkey,
+accounts: &[AccountInfo],
+instruction_data: &[u8]
+```
+
+程序id(program_id)是当前执行程序的公钥。
+
+账户(accounts)是指令引用其账户的有序切片,表示为[AccountInfo](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/account_info.rs#L12)结构。账户在数组中的位置表示其含义,例如在转移lamports时,指令会将第一个账户定义为源账户,第二个账户定义为目标账户。
+
+`AccountInfo`结构的成员是只读的,除了`lamports`和`data`。根据“运行时执行策略”,程序可以修改这两个成员。这两个成员都受Rust的`RefCell`构造保护,因此必须借用它们才能读取或写入。这样做的原因是它们都指向初始输入字节数组,但账户(accounts)切片中可能有多个条目指向同一个账户。使用`RefCell`可以确保程序不会通过多个`AccountInfo`结构对相同的底层数据进行重叠读/写。如果程序实现了自己的反序列化函数,则应小心处理重复账户。
+
+指令数据(instruction_data)是指令正在处理的[指令数据](https://solana.com/docs/core/transactions.md#instruction)的通用字节数组。
+
+## 堆
+
+Rust程序通过定义自定义[`global_allocator`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/entrypoint.rs#L72)直接实现堆。
+
+程序可以根据其特定需求实现自己的`global_allocator`。有关更多信息,请参阅[自定义堆示例](#examples)。
+
+## 局限性
+
+链上Rust程序支持大多数Rust的libstd、libcore和liballoc,以及许多第三方crate。
+
+由于这些程序在资源受限的单线程环境中运行,并且是确定性的,因此存在一些限制:
+
+- 不可访问
+ - `rand`
+ - `std::fs`
+ - `std::net`
+ - `std::future`
+ - `std::process`
+ - `std::sync`
+ - `std::task`
+ - `std::thread`
+ - `std::time`
+- 有限访问:
+ - `std::hash`
+ - `std::os`
+- Bincode在周期和调用深度上极其耗费计算资源,应避免使用。
+- 应避免字符串格式化,因为它也非常耗费计算资源。
+- 不支持`println!`、`print!`,应使用Solana的[日志工具](#日志)
+- 运行时对程序在处理一个指令期间可以执行的指令数量有限制。有关更多信息,请参阅[计算预算](https://solana.com/docs/core/fees.md#compute-budget)。
+
+## Rand依赖
+
+程序受限于确定性运行,因此不提供随机数。有时程序可能依赖于一个依赖 `rand` 的 crate,即使程序本身不使用任何随机数功能。如果程序依赖 `rand`,编译将失败,因为 Solana 不支持 `get-random`。错误通常如下所示:
+
+
+```shell
+error: target is not supported, for more information see: https://docs.rs/getrandom/#unsupported-targets
+ --> /Users/jack/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.1.14/src/lib.rs:257:9
+ |
+257 | / compile_error!("\
+258 | | target is not supported, for more information see: \
+259 | | https://docs.rs/getrandom/#unsupported-targets\
+260 | | ");
+ | |___________^
+```
+
+要解决此依赖问题,请在程序的`Cargo.toml`中添加以下依赖项:
+
+```toml
+getrandom = { version = "0.1.14", features = ["dummy"] }
+```
+
+或者如果依赖于getrandom v0.2,请添加:
+
+```toml
+getrandom = { version = "0.2.2", features = ["custom"] }
+```
+
+## 日志
+
+Rust的`println!`宏在计算上非常昂贵且不受支持。相反,提供了辅助宏[`msg!`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L33)。
+
+`msg!`有两种形式:
+
+```rust
+msg!("A string");
+```
+
+或
+
+```rust
+msg!(0_64, 1_64, 2_64, 3_64, 4_64);
+```
+
+两种形式都将结果输出到程序日志。如果程序想的话,可以使用`format!`模拟`println!`:
+
+```rust
+msg!("Some variable: {:?}", variable);
+```
+
+[调试](https://solana.com/docs/programs/debugging.md#logging)部分有更多关于使用程序日志的信息,此[Rust示例](#examples)中包含一个日志记录示例。
+
+## 异常处理
+
+Rust的`panic!`、`assert!`和内部异常结果默认打印到[程序日志](https://solana.com/docs/programs/debugging.md#logging)。
+
+```shell
+INFO solana_runtime::message_processor] Finalized account CGLhHSuWsp1gT4B7MY2KACqp9RUwQRhcUFfVSuxpSajZ
+INFO solana_runtime::message_processor] Call SBF program CGLhHSuWsp1gT4B7MY2KACqp9RUwQRhcUFfVSuxpSajZ
+INFO solana_runtime::message_processor] Program log: Panicked at: 'assertion failed: `(left == right)`
+ left: `1`,
+ right: `2`', rust/panic/src/lib.rs:22:5
+INFO solana_runtime::message_processor] SBF program consumed 5453 of 200000 units
+INFO solana_runtime::message_processor] SBF program CGLhHSuWsp1gT4B7MY2KACqp9RUwQRhcUFfVSuxpSajZ failed: BPF program panicked
+```
+
+### 自定义异常处理程序
+
+程序可以通过提供自己的实现来覆盖默认的异常处理程序。
+
+首先在程序的`Cargo.toml`中定义`custom-panic`特性
+
+```toml
+[features]
+default = ["custom-panic"]
+custom-panic = []
+```
+
+然后提供自定义的异常处理程序实现:
+
+```rust
+#[cfg(all(feature = "custom-panic", target_os = "solana"))]
+#[no_mangle]
+fn custom_panic(info: &core::panic::PanicInfo<'_>) {
+ solana_program::msg!("program custom panic enabled");
+ solana_program::msg!("{}", info);
+}
+```
+
+上述代码显示了默认实现,但开发人员可以用更适合自己需求的实现替换它。
+
+支持完整的异常消息的默认实现的一个副作用是,程序需要在共享对象中引入更多的Rust `libstd`,实现寻常程序已经引入了大量的`libstd`,可能不会注意到共享对象大小的显著增加。但那些明确尝试通过避免`libstd`来保持小的程序可能会受到很大的影响(约25kb)。为了避免这种影响,程序可以提供自己空实现的自定义异常处理程序。
+
+```rust
+#[cfg(all(feature = "custom-panic", target_os = "solana"))]
+#[no_mangle]
+fn custom_panic(info: &core::panic::PanicInfo<'_>) {
+ // 为了节省空间,不做任何操作
+}
+```
+
+## 计算预算
+
+使用系统调用`sol_remaining_compute_units()`返回一个`u64`,指示此交易剩余的计算单元数。
+
+使用系统调用[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L141)记录一条消息,包含程序在执行停止前可以消耗的剩余计算单元数。
+
+有关更多信息,请参阅[计算预算](https://solana.com/docs/core/fees.md#compute-budget)文档。
+
+## ELF转储
+
+可以将SBF共享对象内部转储到文本文件中,以更深入了解程序的组成及其在运行时可能做的事情。转储将包含ELF信息以及所有符号和实现它们的指令列表。某些BPF加载程序的错误日志消息将引用错误发生的特定指令号。这些引用可以在ELF转储中查找,以确定出错的指令及其上下文。
+
+要创建转储文件:
+
+```shell
+cd <程序目录>
+cargo build-bpf --dump
+```
+
+## 示例
+
+[Solana程序库GitHub仓库](https://github.com/solana-labs/solana-program-library/tree/master/examples/rust)包含一系列Rust示例。
+
+[Solana开发者程序示例GitHub仓库](https://github.com/solana-developers/program-examples)也包含一系列从初级到中级的Rust程序示例。
+
diff --git a/docs/SolanaDocumention/programs/limitations.md b/docs/SolanaDocumention/programs/limitations.md
index e69de29..dbfcb48 100644
--- a/docs/SolanaDocumention/programs/limitations.md
+++ b/docs/SolanaDocumention/programs/limitations.md
@@ -0,0 +1,55 @@
+# 局限性
+
+在 Solana 区块链上开发程序时,存在一些固有的局限性。以下是您可能遇到的一些常见局限性。
+
+## Rust库
+
+由于基于 Rust 的链上程序必须在资源受限的单线程环境中运行,且需要保持其确定性,因此在使用各种库时常有一些局限性。
+
+有关这些局限性的详细信息,请参阅[使用Rust开发 - 局限性](https://solana.com/docs/programs/lang-rust.md#restrictions)。
+
+## 计算预算
+
+为了防止滥用区块链的计算资源,每个交易都会分配一个[计算预算](https://solana.com/docs/terminology.md#compute-budget)。超出此计算预算将导致交易失败。
+
+有关计算预算的具体细节,请参阅[计算约束](https://solana.com/docs/core/fees.md#compute-budget)文档。
+
+## 调用栈深度 - `CallDepthExceeded`错误
+
+Solana程序被限制在快速运行,为了实现这一点,程序的调用栈深度被限制为最大**64帧**。
+
+当程序超出允许的调用栈深度限制时,它将收到`CallDepthExceeded`错误。
+
+## CPI调用深度 - `CallDepth`错误
+
+跨程序调用允许程序直接调用其他程序,但深度目前限制为`4`。
+
+当程序超出允许的[跨程序调用深度](https://solana.com/docs/core/cpi.md)时,它将收到`CallDepth`错误。
+
+## 浮点Rust类型支持
+
+程序支持 Rust 浮点操作的有限子集。如果程序尝试使用不支持的浮点操作,运行时将报告未解决的符号错误。
+
+浮点操作是通过软件库(特别是 LLVM 的浮点内建函数)执行的。由于是软件模拟,它们消耗的计算单元比整数操作更多。一般情况下,建议使用定点操作代替浮点操作。
+
+[Solana数学程序库](https://github.com/solana-labs/solana-program-library/tree/master/libraries/math)测试将反映出一些数学操作的性能。要运行测试,请同步仓库并运行:
+
+```shell
+cargo test-sbf -- --nocapture --test-threads=1
+```
+
+最近的结果显示,浮点操作相比于整数操作需要更多的指令。定点实现可能有所不同,但也会少于浮点操作:
+
+```text
+ u64 f32
+Multiply 8 176
+Divide 9 219
+```
+
+## 静态可写数据
+
+程序共享对象不支持可写共享数据。程序在多个并行执行中共享相同的只读代码和数据。这意味着开发者不应该在程序中包含任何静态可写或全局变量。未来可能会添加写时复制机制来支持可写数据。
+
+## 有符号除法
+
+SBF指令集不支持[有符号除法](https://www.kernel.org/doc/html/latest/bpf/bpf_design_QA.Html#q-why-there-is-no-bpf-sdiv-for-signed-divide-operation)。添加有符号除法指令是一个考虑因素。
diff --git a/docs/SolanaDocumention/terminology.md b/docs/SolanaDocumention/terminology.md
index 8e2c6bc..47e0f53 100644
--- a/docs/SolanaDocumention/terminology.md
+++ b/docs/SolanaDocumention/terminology.md
@@ -157,9 +157,9 @@ Solana程序,负责拥有和加载[BPF](https://solana.com/zh/docs/programs/fa
## lamport
价值0.000000001[sol](#sol)的[原生代币](#原生代币)的分量单位。
-:::tips INFO
+:::tip INFO
在计算预算中,[微lamports](https://github.com/solana-labs/solana/blob/ced8f6a512c61e0dd5308095ae8457add4a39e94/program-runtime/src/prioritization_fee.rs#L1-L2)用于计算[优先费用](#优先费用)。
-:::
+:::
## 领导者
当[验证者](#验证者)将[条目](#条目)附加到[账本](#账本)时的角色。
diff --git a/docs/SolanaProgramLibrary/single-pool.md b/docs/SolanaProgramLibrary/single-pool.md
new file mode 100644
index 0000000..784a25e
--- /dev/null
+++ b/docs/SolanaProgramLibrary/single-pool.md
@@ -0,0 +1,417 @@
+# 单一验证节点质押池
+
+为所有 Solana 验证者提供无需信任的流动性质押。
+
+| 信息 | 账户地址 |
+| -------------------- | --------------------------------------------- |
+| 单一验证者质押池程序 | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` |
+
+## 概述
+
+单一验证者质押池(single-validator stake pool)程序是一个 SPL 程序,提供零费用、无对手方风险和100%资本效率的流动性质押。
+
+该程序为每个投票账户定义了一个标准质押池,可以无权限地初始化,并在质押给其指定验证者的权益换取代币(tokens in exchange)。
+
+此程序是现有1多验证者质押池程序的精简版本,减少了约80%的代码,以降低执行风险。
+
+## 源代码
+
+单一验证者质押池程序的源代码可在[GitHub](https://github.com/solana-labs/solana-program-library/tree/master/single-pool/program) 上获取。
+
+## 安全审计
+
+单一验证者质押池程序经过三次审计,以确保资金的完全安全:
+
+* Zellic (2024-01-02)
+ - 审查提交哈希:[`ef44df9`](https://github.com/solana-labs/solana-program-library/commit/ef44df985e76a697ee9a8aabb3a223610e4cf1dc)
+ - 报告:https://github.com/solana-labs/security-audits/blob/master/spl/ZellicSinglePoolAudit-2024-01-02.pdf
+* Neodyme (2023-08-08)
+ - 审查提交哈希:[`735d729`](https://github.com/solana-labs/solana-program-library/commit/735d7292e35d35101750a4452d2647bdbf848e8b)
+ - 报告:https://github.com/solana-labs/security-audits/blob/master/spl/NeodymeSinglePoolAudit-2023-08-08.pdf
+* Zellic (2023-06-21)
+ - 审查提交哈希:[`9dbdc3b`](https://github.com/solana-labs/solana-program-library/commit/9dbdc3bdae31dda1dcb35346aab2d879deecf194)
+ - 报告:https://github.com/solana-labs/security-audits/blob/master/spl/ZellicSinglePoolAudit-2023-06-21.pdf
+
+## 接口
+
+单一验证者质押池程序是用 Rust 编写的,可以在 [crates.io](https://crates.io/crates/spl-single-pool) 和 [docs.rs](https://docs.rs/spl-single-pool)上获取。
+
+同时也提供了适用于 JavaScript 的接口: [Web3.js Classic](https://www.npmjs.com/package/@solana/spl-single-pool-classic) 和 [Web3.js Next](https://www.npmjs.com/package/@solana/spl-single-pool)。
+
+## 参考指南
+
+### 环境设置
+
+#### 使用 CLI
+
+与单一质押池程序交互的最简单方式是使用 `spl-single-pool` 命令行程序。在安装 [Rust](https://rustup.rs/)后,运行以下命令:
+
+```sh
+cargo install spl-single-pool-cli
+```
+
+运行 `spl-single-pool --help` 以获取可用命令的完整描述。
+
+##### 配置
+
+`spl-single-pool` 的配置与 `solana` 命令行工具共享。
+
+###### 当前配置
+
+```sh
+solana config get
+Config File: ${HOME}/.config/solana/cli/config.yml
+RPC URL: https://api.mainnet-beta.solana.com
+WebSocket URL: wss://api.mainnet-beta.solana.com/ (computed)
+Keypair Path: ${HOME}/.config/solana/id.json
+Commitment: confirmed
+```
+
+###### 集群 RPC URL
+
+查看 [Solana clusters](https://docs.solana.com/clusters) 获取关于 solana 特定集群 RPC URL 的详细信息。
+
+设置节点配置文件,连接 solana 开发网集群
+
+```sh
+solana config set --url https://api.devnet.solana.com
+```
+
+###### 默认密钥对
+
+如果您还没有密钥对的话,查看[Keypair conventions](https://docs.solana.com/cli/conventions#keypair-conventions) 以获取有关如何设置密钥对的信息。
+
+密钥对文件
+
+```sh
+solana config set --keypair ${HOME}/new-keypair.json
+```
+
+硬件钱包URL ([请查看URL规范](https://docs.solana.com/wallet-guide/hardware-wallets#specify-a-keypair-url))
+
+```sh
+solana config set --keypair usb://ledger/
+```
+
+`spl-single-pool` 通常使用默认密钥对作为费用支付者,从钱包中提取资金(例如,用于资助新的质押账户),并在需要时作为账户的签名权限。当需要代币账户时,它默认使用默认密钥对的关联账户。所有这些角色都可以通过命令行标志进行覆盖。
+
+#### 使用web3.js classic
+
+##### pnpm
+
+```bash
+$ pnpm install @solana/spl-single-pool-classic
+```
+
+##### Yarn
+
+```bash
+$ yarn add @solana/spl-single-pool-classic
+```
+
+##### npm
+
+```bash
+$ npm install @solana/spl-single-pool-classic
+```
+
+运行 `spl-single-pool --help` 以获取可用命令的完整说明。
+
+##### 配置
+
+您可以使用 `@solana/web3.js` 中的 `Connection` 连接到不同的集群
+
+```typescript
+import { Connection, clusterApiUrl } from '@solana/web3.js';
+const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
+```
+
+##### 密钥对
+
+您可以使用 `@solana/web3.js` 中的 [`Keypair`](https://solana-labs.github.io/solana-web3.js/classes/Keypair.html) 获取您的密钥对,或者让用户的钱包处理密钥对,并使用 [`wallet-adapter`](https://github.com/solana-labs/wallet-adapter) 中的 `sendTransaction` 方法进行交易。
+
+#### 使用web3.js next
+
+##### pnpm
+
+```bash
+$ pnpm install @solana/spl-single-pool
+```
+
+##### Yarn
+
+```bash
+$ yarn add @solana/spl-single-pool
+```
+
+##### npm
+
+```bash
+$ npm install @solana/spl-single-pool
+```
+
+##### 配置
+
+您可以使用 `@solana/web3.js` 中的 `createDefaultRpcTransport` 和 `createSolanaRpc` 连接到不同的集群。
+
+```typescript
+import { createDefaultRpcTransport, createSolanaRpc } from '@solana/web3.js';
+const transport = createDefaultRpcTransport({ url: 'https://api.devnet.solana.com' });
+const rpc = createSolanaRpc({ transport });
+```
+
+##### 密钥对
+
+Web3.js Next 使用 [`crypto.subtle`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle) 进行密钥管理。在本地开发中,可以使用 `crypto.subtle.importKey` 创建一个 `{ privateKey, publicKey }` 对象,以生成签名(私钥)和验证(公钥)密钥。 一般来说,最好让用户的钱包来管理密钥,因为系统的设计是为了确保密钥不会从安全存储中泄露。
+
+### 设置单一验证者质押池
+
+#### 创建质押池
+
+任何人都可以为给定的投票账户无许可地创建单一验证者质押池。这使得您可以在持有代币化形式的价值的同时,获得与直接质押相同的全部质押收益。它还允许您在市场上买卖小于最小委托量的质押。
+
+假设存在投票账户 `Ammgaa2iZfA745BmZMhkcS27uh87fEVDC6Gm2RXz5hrC`,我们在地址 `DkE6XFGbqSyYzRugLVSmmB42F9BQZ7mZU837e2Cti7kb` 创建一个质押池:
+
+::: code-group
+
+```sh [CLI]
+spl-single-pool manage initialize Ammgaa2iZfA745BmZMhkcS27uh87fEVDC6Gm2RXz5hrC
+```
+
+```typescript [WEB3.JS CLASSIC]
+const voteAccountAddress = new PublicKey('Ammgaa2iZfA745BmZMhkcS27uh87fEVDC6Gm2RXz5hrC');
+const transaction = await SinglePoolProgram.initialize(
+ connection,
+ voteAccountAddress,
+ feePayerAddress,
+);
+
+// 用费用支付者进行签名
+```
+
+```typescript [WEB3.JS NEXT]
+const voteAccountAddress = 'Ammgaa2iZfA745BmZMhkcS27uh87fEVDC6Gm2RXz5hrC' as VoteAccountAddress;
+const transaction = await SinglePoolProgram.initialize(
+ rpc,
+ voteAccountAddress,
+ feePayerAddress,
+);
+
+// 用费用支付者进行签名
+```
+
+:::
+
+#### 管理代币元数据
+
+默认情况下,当创建一个质押池时,它也会为与该池关联的铸币(mint)创建 Metaplex 代币元数据。如果由于某种原因,质押池创建者选择不创建这些元数据,任何人都可以无许可地创建默认元数据:
+
+::: code-group
+
+```sh [CLI]
+spl-single-pool manage create-token-metadata --pool DkE6XFGbqSyYzRugLVSmmB42F9BQZ7mZU837e2Cti7kb
+```
+
+```typescript [WEB3.JS CLASSIC]
+const transaction = await SinglePoolProgram.createTokenMetadata(poolAddress, feePayerAddress);
+
+// 用费用支付者进行签名
+```
+
+```typescript [WEB3.JS NEXT]
+const transaction = await SinglePoolProgram.createTokenMetadata(poolAddress, feePayerAddress);
+
+// 用费用支付者进行签名
+```
+
+:::
+
+默认代币元数据仅提供最基本信息,主要显示验证者投票账户的地址。然而,投票账户的所有者可以将元数据更改为任何他们希望的内容。他们通过使用投票账户的授权提取者签名来证明其身份;这是池中唯一需要权限的指令。
+
+::: code-group
+
+```sh [CLI]
+spl-single-pool manage update-token-metadata DkE6XFGbqSyYzRugLVSmmB42F9BQZ7mZU837e2Cti7kb "My Cool Pool" cPool "https://www.cool.pool/token.jpg"
+```
+
+```typescript [WEB3.JS CLASSIC]
+const transaction = await SinglePoolProgram.updateTokenMetadata(
+ voteAccountAddress,
+ authorizedWithdrawerAddress,
+ 'My Cool Pool',
+ 'cPool',
+ 'https://www.cool.pool/token.jpg',
+);
+
+// 用费用支付者和授权提取者进行签名。
+```
+
+```typescript [WEB3.JS NEXT]
+const transaction = await SinglePoolProgram.updateTokenMetadata(
+ voteAccountAddress,
+ authorizedWithdrawerAddress,
+ 'My Cool Pool',
+ 'cPool',
+ 'https://www.cool.pool/token.jpg',
+);
+
+// 用费用支付者和授权提取者进行签名。
+```
+
+:::
+
+URL 参数是可选的。
+
+### 使用单一验证者质押池
+
+#### 质押
+
+当创建一个质押池时,其质押账户会被委托给相应的投票账户。在该纪元内,可以将处于“激活”状态的权益存入其中。在此纪元之后,权益必须处于“活动”状态才能存入池中。也就是说,它必须委托给投票账户,并且只能在下一个纪元开始之后进行存款。
+
+假设质押账户 `9cc4cmLcZA89fYmcVPPTLmHPQ5gab3R6jMqj124abkSi` 处于活跃状态:
+
+::: code-group
+
+```sh [CLI]
+# 当提供了明确的质押账户地址时,CLI 可以自动确定质押池地址。
+
+spl-single-pool deposit 9cc4cmLcZA89fYmcVPPTLmHPQ5gab3R6jMqj124abkSi
+```
+
+```typescript [WEB3.JS CLASSIC]
+const transaction = await SinglePoolProgram.deposit({
+ connection,
+ pool: poolAddress,
+ userWallet,
+ userStakeAccount,
+});
+
+// 如果签名者不同,则使用费用支付者和质押账户提取权限进行签名。
+// userWallet 是一个便捷参数,用于将一个账户用作支付者、权限持有者和 lamport 接收者。
+```
+
+```typescript [WEB3.JS NEXT]
+const transaction = await SinglePoolProgram.deposit({
+ rpc,
+ pool: poolAddress,
+ userWallet,
+ userStakeAccount,
+});
+
+// 如果签名者不同,则使用费用支付者和质押账户提取权限进行签名。
+// userWallet 是一个便捷参数,用于将一个账户用作支付者、权限持有者和 lamport 接收者。
+```
+
+:::
+
+所有版本的 `deposit` 命令/交易在池代币的关联代币账户不存在且未提供辅助代币账户地址的情况下,都会自动创建该关联代币账户。
+
+该程序还为每个质押池提供一个便捷地址,称为默认存入地址。这允许用户在程序派生地址创建并委托质押,然后在下个周期存入质押,而无需生成或跟踪任何新的密钥对。用户在决定存入之前,始终保留对质押账户的完全控制权。
+
+- 使用 CLI
+
+```sh
+spl-single-pool create-default-stake --pool DkE6XFGbqSyYzRugLVSmmB42F9BQZ7mZU837e2Cti7kb 1000000000
+```
+
+一旦质押变为活跃状态,通常是在下一个纪元:
+
+```sh
+spl-single-pool deposit --pool DkE6XFGbqSyYzRugLVSmmB42F9BQZ7mZU837e2Cti7kb --default-stake-account
+```
+
+- 使用 WEB3.JS CLASSIC
+
+```typescript
+const transaction = await SinglePoolProgram.createAndDelegateUserStake(
+ connection,
+ voteAccountAddress,
+ userWallet,
+ 1000000000,
+);
+
+// 使用用户钱包签名
+```
+
+一旦质押变为活跃状态,通常是在下一个纪元:
+
+```typescript
+const transaction = await SinglePoolProgram.deposit({
+ connection,
+ pool: poolAddress,
+ userWallet,
+ depositFromDefaultAccount: true,
+});
+
+// 使用用户钱包签名
+```
+
+- 使用 WEB3.JS NEXT
+
+```typescript
+const transaction = await SinglePoolProgram.createAndDelegateUserStake(
+ rpc,
+ voteAccountAddress,
+ userWallet,
+ 1000000000n,
+);
+
+// 使用用户钱包签名,该钱包用作费用支付者,并作为种子账户的基础地址。
+```
+
+一旦质押变为活跃状态,通常是在下一个纪元:
+
+```typescript
+const transaction = await SinglePoolProgram.deposit({
+ rpc,
+ pool: poolAddress,
+ userWallet,
+ depositFromDefaultAccount: true,
+});
+
+// 使用用户钱包签名,该钱包用作费用支付者,并作为种子账户的基础地址。
+```
+
+#### 提取
+
+提取操作很简单,只需销毁代币即可收到其支持的质押金额。质押可以提取到已委托给相应投票账户的活跃质押账户,或提取到一个新质押账户,所有权限都会分配给用户钱包。
+
+在内部,所有版本的 `withdraw` 命令/交易都使用代币委托来完成销毁操作。这意味着用户无需为单一质押池程序提供钱包签名。
+
+::: code-group
+
+```sh [CLI]
+# 也可以传递 `--deactivate` 标志,以便方便地启动解除委托的过程。
+
+spl-single-pool withdraw --pool DkE6XFGbqSyYzRugLVSmmB42F9BQZ7mZU837e2Cti7kb 1000000000
+```
+
+```typescript [WEB3.JS CLASSIC]
+const withdrawAccount = new Keypair();
+const transaction = await SinglePoolProgram.withdraw({
+ connection,
+ pool: poolAddress,
+ userWallet,
+ userStakeAccount: withdrawAccount.publicKey,
+ tokenAmount: 1000000000,
+ createStakeAccount: true,
+});
+
+// 用费用支付者签名,如果正在创建新账户,还需要使用质押账户的密钥对进行签名。
+```
+
+```typescript [WEB3.JS NEXT]
+const { publicKey, privateKey } = await generateKeyPair();
+const transaction = await SinglePoolProgram.withdraw({
+ rpc,
+ pool: poolAddress,
+ userWallet,
+ userStakeAccount: publicKey,
+ tokenAmount: 1000000000n,
+ createStakeAccount: true,
+});
+
+// 用费用支付者签名,如果正在创建新账户,还需要使用质押账户的密钥对进行签名。
+```
+
+:::
diff --git a/docs/SolanaProgramLibrary/stake-pool/cli.md b/docs/SolanaProgramLibrary/stake-pool/cli.md
new file mode 100644
index 0000000..6cc6463
--- /dev/null
+++ b/docs/SolanaProgramLibrary/stake-pool/cli.md
@@ -0,0 +1,686 @@
+# 命令行界面
+
+以下是命令行工具的Stake Pool程序中可用的指令,以及使用示例。
+
+## 安装
+
+`spl-stake-pool`命令行工具可用于试验SPL代币。首先确保你安装了[Rust](https://rustup.rs/),然后运行:
+
+```bash
+$ cargo install spl-stake-pool-cli
+```
+
+运行 `spl-stake-pool --help` 查看所有可用命令的完整描述。
+
+## 配置
+
+`spl-stake-pool`配置与`solana`命令行工具共享。
+
+### 当前配置
+
+```bash
+$ solana config get
+Config File: ${HOME}/.config/solana/cli/config.yml
+RPC URL: https://api.mainnet-beta.solana.com
+WebSocket URL: wss://api.mainnet-beta.solana.com/ (computed)
+Keypair Path: ${HOME}/.config/solana/id.json
+```
+
+### 集群RPC URL
+
+参考[Solana集群](https://docs.solana.com/clusters)以获取特定于集群的RPC URL
+
+```bash
+$ solana config set --url https://api.devnet.solana.com
+```
+
+### 默认密钥对
+
+有关如何设置密钥对(如果还没有密钥对)的信息,请参阅[密钥对规定](https://docs.solana.com/cli/conventions#keypair-conventions)。
+
+密钥对文件
+
+```bash
+$ solana config set --keypair ${HOME}/new-keypair.json
+```
+
+参考[URL规范](https://docs.solana.com/wallet-guide/hardware-wallets#specify-a-keypair-url)设置硬件钱包URL。
+
+```bash
+$ solana config set --keypair usb://ledger/
+```
+
+### 本地运行
+
+如果你想在不等待质押激活和停用的情况下,来本地测试质押池,你可以使用`solana-test-validator`工具运行质押池,缩短纪元(epochs)的时间,并从开发网拉取当前程序。
+
+```bash
+$ solana-test-validator -c SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy -c EmiU8AQkB2sswTxVB6aCmsAJftoowZGGDXuytm6X65R3 --url devnet --slots-per-epoch 32
+$ solana config set --url http://127.0.0.1:8899
+```
+
+## 质押池管理器示例
+
+### 创建质押池
+
+质押池管理器(Stake Pool Manager)以高级别控制质押池,并以SPL代币形式收取费用。管理器在创建时设置费用。例如,创建一个3%费用和最多1000个验证者质押的池:
+
+```bash
+$ spl-stake-pool create-pool --epoch-fee-numerator 3 --epoch-fee-denominator 100 --max-validators 1000
+Creating reserve stake DVwDn4LTRztuai4QeenM6fyzgiwUGpVXVNZ1mgKE1Pyc
+Creating mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Creating associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Creating pool fee collection account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ
+Signature: qQwqahLuC24wPwVdgVXtd7v5htSSPDAH3JxFNmXCv9aDwjjqygQ64VMg3WdPCiNzc4Bn8vtS3qcnUVHVP5MbKgL
+Creating stake pool Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Signature: 5z6uH3EuPcujeWGpAjBtciSUR3TxtMBgWYU4ULagUso4QGzE9JenhYHwYthJ4b3rS57ByUNEXTr2BFyF5PjWC42Y
+```
+
+质押池的唯一标识符是 `Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR。`
+
+质押池的SPL代币铸造标识符是 `BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB`。质押池对铸造有完全控制权。
+
+质押池创建者的费用账户标识符是 `DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ`。在每个纪元里,当质押池中的质押账户获得奖励时,程序会将相当于该纪元收益3%的SPL池代币铸造到这个账户。如果没有观察到收益,就什么都不会存入。
+
+储备质押账户标识符是 `J5XB7mWpeaUZxZ6ogXT57qSCobczx27vLZYSgfSbZoBB`。此账户持有在验证者之间重新平衡时使用的额外质押。
+
+对于有1000个验证者的质押池,创建质押池的成本不到0.5 SOL。
+
+`create-pool`命令允许设置所有账户和密钥对为预先生成的值,包括:
+
+- 质押池,通过 `--pool-keypair` 标识
+- 验证者列表,通过 `--validator-list-keypair` 标识
+- 池子代币铸造厂,通过 `--mint-keypair` 标识
+- 池子储备质押账户,通过 `--reserve-keypair` 标识
+
+否则,这些将默认为新生成的密钥对。
+
+你可以随时运行 `spl-stake-pool create-pool -h` 来查看可用的选项。
+
+### 创建限制性质押池
+
+如果管理者希望将质押(质押和SOL)存款限制为特定的一个密钥,他们可以在创建时设置存款权限:
+
+```bash
+$ spl-stake-pool create-pool --epoch-fee-numerator 3 --epoch-fee-denominator 100 --max-validators 1000 --deposit-authority authority_keypair.json
+Creating reserve stake DVwDn4LTRztuai4QeenM6fyzgiwUGpVXVNZ1mgKE1Pyc
+Creating mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Creating associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Creating pool fee collection account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ
+Signature: qQwqahLuC24wPwVdgVXtd7v5htSSPDAH3JxFNmXCv9aDwjjqygQ64VMg3WdPCiNzc4Bn8vtS3qcnUVHVP5MbKgL
+Creating stake pool Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Deposits will be restricted to 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn only, this can be changed using the set-funding-authority command.
+Signature: 5z6uH3EuPcujeWGpAjBtciSUR3TxtMBgWYU4ULagUso4QGzE9JenhYHwYthJ4b3rS57ByUNEXTr2BFyF5PjWC42Y
+```
+
+正如输出所示,`set-funding-authority` 可以用来修改或删除存款权限。
+
+只要设置了存款权限,SOL和质押存款必须由 `4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn` 签名,因此其他人不能参与。如前所述,这个功能不禁止提款,所以任何有池子代币的人仍然可以从池中提款。
+
+### 设置管理者
+
+质押池管理者可以将他们的管理员权限传递给另一个账户。
+
+```bash
+$ spl-stake-pool set-manager Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --new-manager 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Signature: 39N5gkaqXuWm6JPEUWfenKXeG4nSa71p7iHb9zurvdZcsWmbjdmSXwLVYfhAVHWucTY77sJ8SkUNpVpVAhe4eZ53
+```
+
+同时,他们还可以更改每个纪元接收费用的SPL代币账户。所提供代币账户的铸造厂必须是SPL代币铸造厂,在我们的例子中是 `BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB`。
+
+```bash
+$ spl-stake-pool set-manager Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --new-fee-receiver HoCsh97wRxRXVjtG7dyfsXSwH9VxdDzC7GvAsBE1eqJz
+Signature: 4aK8yzYvPBkP4PyuXTcCm529kjEH6tTt4ixc5D5ZyCrHwc4pvxAHj6wcr4cpAE1e3LddE87J1GLD466aiifcXoAY
+```
+
+### 设置费用
+
+质押池管理者可以更新与质押池相关的任何费用,需要传入构成费用比例的分子和分母。
+
+对于10%的纪元费用,他们可以执行以下操作:
+
+```bash
+$ spl-stake-pool set-fee Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR epoch 10 100
+Signature: 5yPXfVj5cbKBfZiEVi2UR5bXzVDuc2c3ruBwSjkAqpvxPHigwGHiS1mXQVE4qwok5moMWT5RNYAMvkE9bnfQ1i93
+```
+
+为了保护质押池存款人免受恶意管理者的侵害,程序在跨越两个纪元的界限后才应用新的费用,提供了至少一个完整纪元的等待时间。
+
+例如,如果在第100个纪元费用是1%,管理者将其设置为10%,管理者仍然会因为在第100和101个纪元赚取的奖励而获得1%的费用。从第102个纪元开始,管理者将获得10%的费用。
+
+此外,为了防止恶意管理者立即将提款费用设置得非常高,从而使用户实际上无法提款,质押池程序目前每两个纪元界限强制执行最多增加1.5倍的限制。
+
+例如,如果当前的提款费用是2.5%,可设置的最高费用是3.75%,将在两个纪元界限后生效。
+
+费用类型可能的选项有`纪元费用`、`SOL提款`、`质押提款`、`SOL存款`和`质押存款`(epoch` 、 `sol-withdrawal` 、 `stake-withdrawal` 、 `sol-deposit 和 stake-deposit)。
+
+### 设置推荐费用
+
+质押池管理者可以随时更新存款上的推荐费,传入一个百分比金额。
+
+要设置80%的质押存款推荐费,他们可以执行以下操作:
+
+```bash
+$ spl-stake-pool set-referral-fee Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR stake 80
+Signature: 4vhaBEDhuKkVwMxy7TpyfHEk3Z5kGZKerD1AgajQBdiMRQLZuNZKVR3KQaqbUYZM7UyfRXgkZNdAeP1NfvmwKdqb
+```
+
+对于80%的推荐费,这意味着质押存款费用的20%归管理者所有,而80%归推荐人所有。
+
+### 设置质押者
+
+为了管理质押账户,质押池管理者或质押者可以设置质押池管理账户的质押者权限。
+
+```
+$ spl-stake-pool set-staker Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Signature: 39N5gkaqXuWm6JPEUWfenKXeG4nSa71p7iHb9zurvdZcsWmbjdmSXwLVYfhAVHWucTY77sJ8SkUNpVpVAhe4eZ53
+```
+
+现在,新的质押者可以执行任何正常的质押池操作,包括添加和移除验证者以及重新平衡质押。
+
+重要的安全提示:质押池程序仅向质押池质押者授予质押权限,并始终保留提款权限。因此,恶意的质押池质押者无法从质押池中窃取资金。
+
+注意:为了避免“打扰管理者”,质押者也可以重新分配他们的质押权限。
+
+### 设置资金权限
+
+为了限制谁可以与池子交互,质押池管理者可能需要在质押存款、SOL存款或SOL提款上要求特定的签名。这并不会使得池子变得私有,因为所有信息都是在链上公开的,但它限制了谁可以使用池子。
+
+例如,假设一个池子想要限制所有的SOL提款。
+
+```bash
+$ spl-stake-pool set-funding-authority Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR sol-withdraw AZ1PgxWSxw4ezX8gvpNgGsr39jJHCwtkaXr1mNMwWWeK
+Signature: 3gx7ckGNSL7gUUyxh4CU3RH3Lyt88hiCvYQ4QRKtnmrZHvAS93ebP6bf39WYGTeKDMVSJUuwBEmk9VFSaWtXsHVV
+```
+
+执行此命令后,`AZ1PgxWSxw4ezX8gvpNgGsr39jJHCwtkaXr1mNMwWWeK` 必须对所有的SOL提款进行签名,否则操作将失败。
+
+过了一段时间后,如果管理者希望启用SOL提款,他们可以移除这个限制:
+
+```bash
+$ spl-stake-pool set-funding-authority Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR sol-withdraw --unset
+Signature: 5kWeBqoxyvANMHCP4ydsZRf8QU4hMotLnKkFbTEdvqEVywo4F3MpZtay7D57FbjJZpdp72fc3vrbxJi9qDLfLCnD
+```
+
+现在,只要储备中还有足够的SOL,任何人都可以从质押池中提取SOL。
+
+资金权限相关选项有`sol-提款`、`sol-存款`和`质押存款`( `sol-withdraw`, `sol-deposit`, and `stake-deposit`)。
+
+注意:限制质押提款是不可能的。这将为恶意池管理者提供机会,实际上锁定用户资金。
+
+## 质押池质押者示例
+
+### 向池中添加验证者
+
+为了适应大量用户向质押池存款,质押池只为每个验证者管理一个质押账户。要向质押池添加新的验证者,质押者必须使用`add-validator`命令。
+
+用于向池中添加验证者的SOL来自质押池的储备账户。如果储备中的SOL不足,命令将失败。请确保使用`deposit-sol`命令将一些SOL转移到池中。
+
+假设质押池中有10 SOL,让我们向质押池添加一些随机验证者。
+
+```bash
+$ spl-stake-pool add-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk
+Adding stake account F8e8Ympp4MkDSPZdvRxdQUZXRkMBDdyqgHa363GShAPt, delegated to 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk
+Signature: 5tdpsx64mVcSHBK8vMbBzFDHnEZB6GUmVpqSXXE5hezMAzPYwZbJCBtAHakDAiuWNcrMongGrmwDaeywhVz4i8pi
+```
+
+为了最大程度地提高审查抵抗能力,我们希望将我们的SOL分散到尽可能多的验证者那里,因此让我们再添加一些。
+
+```bash
+$ spl-stake-pool add-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+Adding stake account 5AaobwjccyHnXhFCd24uiX6VqPjXE3Ry4o92fJjqqjAr, delegated to J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+Signature: 4xeve6gWuiffqBLAMcqa8s7dCMvBmSVdKbDu5WQhigLiXHdCjSNEwoZRexTZji786qgEjXg3nrUh4HcTt3RauZV5
+$ spl-stake-pool add-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Adding stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Signature: 4VJYHpPmWkP99TdgYUTgLYixmhqmqsEkWtg4j7zvGZFjYbnLgryu48aV6ub8bqDyULzKckUhb6tvcmZmMX5AFf5G
+```
+
+我们可以使用Solana命令行工具查看质押账户的状态。
+
+```bash
+$ solana stake-account 5AaobwjccyHnXhFCd24uiX6VqPjXE3Ry4o92fJjqqjAr
+Balance: 1.00228288 SOL
+Rent Exempt Reserve: 0.00228288 SOL
+Delegated Stake: 1 SOL
+Active Stake: 0 SOL
+Activating Stake: 1 SOL
+Stake activates starting from epoch: 5
+Delegated Vote Account Address: J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+Stake Authority: DS3AyFN9dF1ruNBcSeo8XXQR8UyVMhcCPcnjU5GnY18S
+Withdraw Authority: DS3AyFN9dF1ruNBcSeo8XXQR8UyVMhcCPcnjU5GnY18S
+```
+
+质押池创建了这些特殊的质押账户,其中1 SOL是所需的最低委托金额。质押和提款权限属于质押池提款权限,即从质押池地址派生的程序地址。
+
+我们还可以看到质押池的状态。
+
+```bash
+$ spl-stake-pool list Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Stake Pool: Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Pool Token Mint: BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Epoch Fee: 3/100 of epoch rewards
+Withdrawal Fee: none
+Stake Deposit Fee: none
+SOL Deposit Fee: none
+SOL Deposit Referral Fee: none
+Stake Deposit Referral Fee: none
+Reserve Account: EN4px2h4gFkYtsQUi4yeCYBrdRM4DoRxCVJyavMXEAm5 Available Balance: ◎6.99315136
+Vote Account: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ Balance: ◎1.002282880 Last Update Epoch: 4
+Vote Account: J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H Balance: ◎1.002282880 Last Update Epoch: 4
+Vote Account: 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk Balance: ◎1.002282880 Last Update Epoch: 4
+Total Pool Stake: ◎10.000000000
+Total Pool Tokens: 10.00000000
+Current Number of Validators: 3
+Max Number of Validators: 1000
+```
+
+为了便于阅读,该工具不会显示质押池无法触及的余额。储备质押账户 `EN4px2h4gFkYtsQUi4yeCYBrdRM4DoRxCVJyavMXEAm5` 实际上还有额外的0.002282881 SOL余额,但由于这是最低要求金额,所以命令行不会显示。
+
+### 移除验证者质押账户
+
+如果质押池质押者希望停止委托给投票账户,他们可以完全从质押池中移除该验证者的质押账户。
+
+和添加验证者一样,要移除的验证者质押账户必须恰好有1.00228288 SOL(1 SOL用于委托,0.00228288 SOL用于租金豁免)。
+
+如果情况不是这样,质押者必须先将质押金额减少到这个最小数额。假设委托给`J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H`的验证者质押账户总共委托了7.5 SOL。为了减少这个数额,质押者可以执行以下操作:
+
+```bash
+$ spl-stake-pool decrease-validator-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H 6.5
+Signature: ZpQGwT85rJ8Y9afdkXhKo3TVv4xgTz741mmZj2vW7mihYseAkFsazWxza2y8eNGY4HDJm15c1cStwyiQzaM3RpH
+```
+
+好的,让我们尝试移除验证者`J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H`,其对应的质押账户是`5AaobwjccyHnXhFCd24uiX6VqPjXE3Ry4o92fJjqqjAr`。
+
+```bash
+$ spl-stake-pool remove-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+Removing stake account 5AaobwjccyHnXhFCd24uiX6VqPjXE3Ry4o92fJjqqjAr, delegated to J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+Creating account to receive stake nHEEyey8KkgHuVRAUDzkH5Q4PkA4veSHuTxgG6C8L2G
+Signature: 4XprnR768Ch6LUvqUVLTjMCiqdYvtjNfECh4izErqwbsASTGjUBz7NtLZHAiraTqhs7b9PoSAazetdsgXa6J4wVu
+```
+
+与普通提款不同,验证者的质押账户将被停用,并在下一个纪元与储备账户合并。
+
+我们可以检查正在停用的质押账户:
+
+```bash
+$ solana stake-account nHEEyey8KkgHuVRAUDzkH5Q4PkA4veSHuTxgG6C8L2G
+Balance: 1.002282880 SOL
+Rent Exempt Reserve: 0.00228288 SOL
+Delegated Stake: 1.000000000 SOL
+Active Stake: 1.000000000 SOL
+Stake deactivates starting from epoch: 10
+Delegated Vote Account Address: J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+Stake Authority: 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Withdraw Authority: 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+```
+
+### 重新平衡质押池
+
+随着时间的推移,用户将向质押池管理的所有质押账户存款和提款,质押池的质押者可能希望重新平衡这些质押。
+
+例如,假设质押者希望对池中的每个验证者进行相同数量的委托。当他们查看池的状态时,他们看到:
+
+```bash
+$ spl-stake-pool list Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Stake Pool: Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Pool Token Mint: BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Epoch Fee: 3/100 of epoch rewards
+Withdrawal Fee: none
+Stake Deposit Fee: none
+SOL Deposit Fee: none
+SOL Deposit Referral Fee: none
+Stake Deposit Referral Fee: none
+Reserve Account: EN4px2h4gFkYtsQUi4yeCYBrdRM4DoRxCVJyavMXEAm5 Available Balance: ◎10.006848640
+Vote Account: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ Balance: ◎100.000000000 Last Update Epoch: 4
+Vote Account: J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H Balance: ◎10.000000000 Last Update Epoch: 4
+Vote Account: 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk Balance: ◎10.000000000 Last Update Epoch: 4
+Total Pool Stake: ◎130.006848640
+Total Pool Tokens: 130.00684864
+Current Number of Validators: 3
+Max Number of Validators: 1000
+```
+
+这可不太好!第一个质押账户,`EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ`,分配得太多了。根据他们的策略,质押者希望`100`SOL能够均匀分配,也就是每个账户`40`SOL。他们需要将`30`SOL移动到`J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H`和`38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk`。
+
+#### 减少验证者质押
+
+首先,他们需要减少委托给`EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ`的质押账户`3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx`上的金额,总共减少`60`SOL。
+
+他们减少那部分SOL的操作如下:
+
+```bash
+$ spl-stake-pool decrease-validator-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ 60
+Signature: ZpQGwT85rJ8Y9afdkXhKo3TVv4xgTz741mmZj2vW7mihYseAkFsazWxza2y8eNGY4HDJm15c1cStwyiQzaM3RpH
+```
+
+在内部,该指令将来自验证者质押账户`3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx`的60 SOL拆分并停用,转入一个临时质押账户,该账户完全由质押池拥有和管理。
+
+一旦在下一个纪元质押被停用,`update`命令将自动将临时质押账户合并到一个储备质押账户中,该账户也完全由质押池拥有和管理。
+
+#### 增加验证者质押
+
+现在储备质押账户有足够的资金来执行重新平衡,质押者可以增加其他两个验证者`J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H`和`38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk`的质押。
+
+他们向`J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H`增加了30 SOL:
+
+```bash
+$ spl-stake-pool increase-validator-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H 30
+Signature: 3GJACzjUGLPjcd9RLUW86AfBLWKapZRkxnEMc2yHT6erYtcKBgCapzyrVH6VN8Utxj7e2mtvzcigwLm6ZafXyTMw
+```
+
+并且他们增加了 30 SOL 到`38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk`:
+
+```bash
+$ spl-stake-pool increase-validator-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk 30
+Signature: 4zaKYu3MQ3as8reLbuHKaXN8FNaHvpHuiZtsJeARo67UKMo6wUUoWE88Fy8N4EYQYicuwULTNffcUD3a9jY88PoU
+```
+
+在内部,该指令也使用临时质押账户。这一次,质押池从储备质押中拆分为临时质押账户,然后将其激活到相应的验证者。
+
+一到两个纪元后,一旦临时质押激活,update命令会自动将临时质押合并到验证者质押账户中,留下一个完全重新平衡的质押池:
+
+```bash
+$ spl-stake-pool list Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Stake Pool: Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Pool Token Mint: BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Preferred Deposit Validator: 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk
+Epoch Fee: 3/100 of epoch rewards
+Withdrawal Fee: none
+Stake Deposit Fee: none
+SOL Deposit Fee: none
+SOL Deposit Referral Fee: none
+Stake Deposit Referral Fee: none
+Reserve Account: EN4px2h4gFkYtsQUi4yeCYBrdRM4DoRxCVJyavMXEAm5 Available Balance: ◎10.006848640
+Vote Account: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ Balance: ◎40.000000000 Last Update Epoch: 8
+Vote Account: J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H Balance: ◎40.000000000 Last Update Epoch: 8
+Vote Account: 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk Balance: ◎40.000000000 Last Update Epoch: 8
+Total Pool Stake: ◎130.006848640
+Total Pool Tokens: 130.00684864
+Current Number of Validators: 3
+Max Number of Validators: 1000
+```
+
+由于在重新平衡过程中累积的质押奖励,池子可能无法达到完美的平衡。这是完全正常的。
+
+### 设置首选的存款/提款验证者
+
+由于质押池可以接受对其任何质押账户的存款,并且允许从任何质押账户提款,它可能被恶意套利者利用,这些套利者希望每个纪元都能最大化收益。
+
+例如,如果一个质押池有1000个验证者,套利者可以向这些验证者中的任何一个质押。在时代的末尾,他们可以检查哪个验证者表现最佳,存入他们的质押,然后立即从表现最好的验证者那里提款。一旦奖励发放,他们可以取出他们宝贵的质押,并以高于原来数量的金额重新存入。
+
+为了减轻这种套利行为,质押池的质押者可以设置首选的提款或存款验证者。任何存款或提款都必须进入相应的质押账户,这使得在没有大量资金的情况下进行这种攻击变得不可能。
+
+让我们设置一个首选的存款验证者质押账户:
+
+```bash
+$ spl-stake-pool set-preferred-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR deposit --vote-account EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Signature: j6fbTqGJ8ehgKnSPns1adaSeFwg5M3wP1a32qYwZsQjymYoSejFUXLNGwvHSouJcFm4C78HUoC8xd7cvb5iActL
+```
+
+然后让我们将首选的提款验证者质押账户设置为同一个。
+
+```bash
+$ spl-stake-pool set-preferred-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR withdraw --vote-account EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Signature: 4MKdYLyFqU6H3311YZDeLtsoeGZMzswBHyBCRjHfkzuN1rB4LXJbPfkgUGLKkdbsxJvPRub7SqB1zNPTqDdwti2w
+```
+
+在任何时候,他们也可以选择取消设置首选验证者:
+
+```bash
+$ spl-stake-pool set-preferred-validator Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR withdraw --unset
+Signature: 5Qh9FA3EXtJ7nKw7UyxmMWXnTMLRKQqcpvfEsEyBtxSPqzPAXp2vFXnPg1Pw8f37JFdvyzYay65CtA8Z1ewzVkvF
+```
+
+在`list`命令中会标记出首选验证者:
+
+```bash
+$ spl-stake-pool list Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Stake Pool: Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Pool Token Mint: BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Preferred Deposit Validator: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Preferred Withdraw Validator: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+```
+
+## 用户示例
+
+### 列出验证者质押账户
+
+为了向质押池存款,用户首先必须向与质押池相关联的验证者质押账户之一委托一些质押。命令行实用工具有一个特殊的指令,来查找哪些投票账户已经与质押池关联。
+
+```bash
+$ spl-stake-pool list Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Stake Pool: Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Pool Token Mint: BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Preferred Deposit Validator: 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk
+Epoch Fee: 3/100 of epoch rewards
+Withdrawal Fee: none
+Stake Deposit Fee: none
+SOL Deposit Fee: none
+SOL Deposit Referral Fee: none
+Stake Deposit Referral Fee: none
+Reserve Account: EN4px2h4gFkYtsQUi4yeCYBrdRM4DoRxCVJyavMXEAm5 Available Balance: ◎10.006848640
+Vote Account: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ Balance: ◎35.000000000 Last Update Epoch: 8
+Vote Account: J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H Balance: ◎35.000000000 Last Update Epoch: 8
+Vote Account: 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk Balance: ◎35.000000000 Last Update Epoch: 8
+Total Pool Stake: ◎115.006848640
+Total Pool Tokens: 115.00684864
+Current Number of Validators: 3
+Max Number of Validators: 1000
+```
+
+### 存款SOL
+
+质押池直接从常规SOL钱包账户接受SOL存款,并作为交换铸造相应数量的池代币。
+
+```bash
+$ spl-stake-pool deposit-sol Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 100
+Using existing associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Signature: 23CptpZaq33njCpJPAvk8XS53xXwpfqF1sGxChk3VDB5mzz7XPKQqwsreun3iwZ6b51AyHqGBaUyc6tx9fqvF9JK
+```
+
+作为回报,质押池为我们铸造了新的池代币,代表我们在池中的所有权份额。我们可以使用SPL代币命令行工具再次检查我们的质押池账户。
+
+```bash
+$ spl-token balance BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+100.00000000
+```
+
+### 提款SOL
+
+质押池允许直接从储备中提取SOL到常规SOL钱包账户,作为交换,会燃烧提供的池代币。
+
+```bash
+$ spl-stake-pool withdraw-sol Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 7VXPpSxneL6JLj18Naw2gkukXtjBZfbmPh18cnoUCMD8 2
+Signature: 4bqZKUUrjVspqTGqGqX4zxnHnJB67WbeukKUZRmxJ2yFmr275CtHPjZNzQJD9Pe7Q6mSxnUpcVv9FUdAbGP9RyBc
+```
+
+质押池已经燃烧了2个池代币,作为交换,向地址`7VXPpSxneL6JLj18Naw2gkukXtjBZfbmPh18cnoUCMD8`发送了SOL。
+
+你可以检查池代币已经被燃烧的情况:
+
+```bash
+$ spl-token balance BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+98.00000000
+```
+
+并且你可以确认收款方已经被记入:
+
+```bash
+$ solana balance 7VXPpSxneL6JLj18Naw2gkukXtjBZfbmPh18cnoUCMD8
+2 SOL
+```
+
+### 质押存款
+
+质押池也接受来自活跃质押账户的存款,因此我们必须首先创建质押账户,并将它们委托给质押池管理的其中一个验证者。使用前一节中的`list`命令,我们看到`38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk`是一个有效的投票账户,因此让我们创建一个质押账户,并将我们的质押委托到那里。
+
+```bash
+$ solana-keygen new --no-passphrase -o stake-account.json
+Generating a new keypair
+Wrote new keypair to stake-account.json
+============================================================================
+pubkey: 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ
+============================================================================
+Save this seed phrase to recover your new keypair:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+============================================================================
+$ solana create-stake-account stake-account.json 10
+Signature: 5Y9r6MNoqJzVX8TWryAJbdp8i2DvintfxbYWoY6VcLEPgphK2tdydhtJTd3o3dF7QdM2Pg8sBFDZuyNcMag3nPvj
+$ solana delegate-stake 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ 38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk
+Signature: 2cDjHXSHjuadGQf1NQpPi43A8R19aCifsY16yTcictKPHcSAXN5TvXZ58nDJwkYs12tuZfTh5WVgAMSvptfrKdPP
+```
+
+两个纪元之后,当质押完全激活并且已经收到一个纪元奖励时,我们可以将质押存入质押池。
+
+```bash
+$ spl-stake-pool deposit-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ
+Depositing stake 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ into stake pool account F8e8Ympp4MkDSPZdvRxdQUZXRkMBDdyqgHa363GShAPt
+Using existing associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Signature: 45x2UtA1b49eBPtRHdkvA3k8JneZzfwjptNN1kKQZaPABYiJ4hSA8qwi7qLNN5b3Fr4Z6vXhJprrTCpkk3f8UqgD
+```
+
+命令行工具(CLI)默认使用费用支付者的[关联代币账户](https://spl.solana.com/associated-token-account)来处理质押池代币,以及作为存入质押账户的提款权限。
+
+或者,您可以自己创建一个SPL代币账户,并将其作为命令的`token-receiver`传递,并使用`withdraw-authority`标志指定质押账户上的提款权限。
+
+```bash
+$ spl-stake-pool deposit-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ --token-receiver 34XMHa3JUPv46ftU4dGHvemZ9oKVjnciRePYMcX3rjEF --withdraw-authority authority.json
+Depositing stake 97wBBiLVA7fUViEew8yV8R6tTdKithZDVz8LHLfF9sTJ into stake pool account F8e8Ympp4MkDSPZdvRxdQUZXRkMBDdyqgHa363GShAPt
+Signature: 4AESGZzqBVfj5xQnMiPWAwzJnAtQDRFK1Ha6jqKKTs46Zm5fw3LqgU1mRAT6CKTywVfFMHZCLm1hcQNScSMwVvjQ
+```
+
+作为回报,质押池为我们铸造了新的池代币,这些代币代表了我们在池中的所有权份额。我们可以使用SPL代币命令行工具来再次检查我们的质押池账户。
+
+```bash
+$ spl-token balance BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+10.00000000
+```
+
+#### 关于质押存款费用的说明
+
+质押池对于质押和SOL有各自的费用标准,因此从质押账户存款的总费用是根据租金豁免储备按SOL计算,以及委托部分按质押计算的。
+
+例如,如果质押池的质押存款费用是1%,SOL存款费用是5%,您存入的质押账户中有10 SOL的质押金和0.00228288 SOL的租金豁免,那么收取的总费用是:
+
+```tex
+total_fee = stake_delegation * stake_deposit_fee + rent_exemption * sol_deposit_fee
+total_fee = 10 * 1% + .00228288 * 5%
+total_fee = 0.100114144
+```
+
+### 更新
+
+每个纪元,网络都会向质押池管理的质押账户支付奖励,这增加了存款时铸造的池代币的价值。为了计算这些质押池代币的正确价值,我们必须每个纪元更新质押池管理的总价值。
+
+```bash
+$ spl-stake-pool update Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Signature: 2rtPNGKFSSnXFCb6MKG5wHp34dkB5hJWNhro8EU2oGh1USafAgzu98EgoRnPLi7ojQfmTpvXk4S7DWXYGu5t85Ka
+Signature: 5V2oCNvZCNJfC6QXHmR2UHGxVMip6nfZixYkVjFQBTyTf2Z9s9GJ9BjkxSFGvUsvW6zc2cCRv9Lqucu1cgHMFcVU
+```
+
+如果另一个用户已经为当前时代更新了质押池余额,我们将看到不同的输出。
+
+```bash
+$ spl-stake-pool update Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR
+Update not required
+```
+
+如果当前纪元没有人更新质押池,包括存款和提款在内的所有指令都将失败。更新指令是无需许可的,因此任何用户都可以在与质押池交互之前运行它。为了方便起见,命令行工具(CLI)在执行质押池的任何指令之前都会尝试进行更新。
+
+如果质押池的临时质押处于非预期状态,且合并操作无法进行,有一个选项可以仅更新质押池余额而不执行合并,即使用`--no-merge`标志。
+
+```bash
+$ spl-stake-pool update Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --no-merge
+Signature: 5cjdZG727uzwnEEG3vJ1vskA9WsXibaEHh7imXSb2S1cwEYK4Q3btr2GEeAV8EffK4CEQ2WM6PQxawkJAHoZ4jsQ
+Signature: EBHbSRstJ3HxKwYKak8vEwVMKr1UBxdbqs5KuX3XYt4ppPjhaziGEtvL2TJCm1HLokbrtMeTEv57Ef4xhByJtJP
+```
+
+紧接着,每当临时质押准备合并时,可以使用`--force`标志在同一时期强制进行另一次更新
+
+```bash
+$ spl-stake-pool update Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --force
+Signature: 5RneEBwJkFytBJaJdkvCTHFrG3QzE3SGf9vdBm9gteCcHV4HwaHzj3mjX1hZg4yCREQSgmo3H9bPF6auMmMFTSTo
+Signature: 1215wJUY7vj82TQoGCacQ2VJZ157HnCTvfsUXkYph3nZzJNmeDaGmy1nCD7hkhFfxnQYYxVtec5TkDFGGB4e7EvG
+```
+
+### 提取质押
+
+无论何时用户想要回收他们的SOL代币以及累积的奖励,他们都可以提供他们的池代币以换取一个激活的质押账户。
+
+让我们用5个池代币来兑换活跃的质押SOL。
+
+```bash
+$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5
+Withdrawing ◎5.000000000, or 5 pool tokens, from stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Creating account to receive stake 5GuAyPAt6577HoGhSVRNBv6aHohVtjQ8q7q5i3X1p4tB
+Signature: 5fzaKt5MU8bLjJRgNZyEktKsgweSQzFRpubCGKPeuk9shNQb4CtTkbgZ2X5MmC1VRDZ3YcCTPdtL9sFpXYfoqaeV
+```
+
+质押池收取了5个池代币,作为交换,用户收到了一个完全激活的质押账户,该账户已委托给地址 `EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ`。让我们再次检查质押账户的状态:
+
+```bash
+$ solana stake-account 5GuAyPAt6577HoGhSVRNBv6aHohVtjQ8q7q5i3X1p4tB
+Balance: 5.00228288 SOL
+Rent Exempt Reserve: 0.00228288 SOL
+Delegated Stake: 5 SOL
+Active Stake: 5 SOL
+Delegated Vote Account Address: EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Stake Authority: 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Withdraw Authority: 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+```
+
+注意:这个操作花费了用户一些资金,因为他们需要创建一个新的质押账户,并支付最低的租金免除费用,以便接收资金。这允许用户提取任何数量的质押池代币,即使这些代币不足以支付质押账户的租金免除。
+
+另外,用户可以通过使用`--stake-receiver`参数来指定一个现有的未初始化的质押账户,以接收他们的质押。
+
+```bash
+$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --amount 0.02 --vote-account EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ --stake-receiver CZF2z3JJoDmJRcVjtsrz1BKUUGNL3VPW5FPFqge1bzmQ
+Withdrawing ◎5.000000000, or 5 pool tokens, from stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Signature: 2xBPVPJ749AE4hHNCNYdjuHv1EdMvxm9uvvraWfTA7Urrvecwh9w64URCyLLroLQ2RKDGE2QELM2ZHd8qRkjavJM
+```
+
+默认情况下,withdraw命令会使用`代币持有者`(token-owner)关联的代币账户来获取池代币。可以使用`--pool-account`标志来指定SPL代币账户。
+
+```bash
+$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5 --pool-account 34XMHa3JUPv46ftU4dGHvemZ9oKVjnciRePYMcX3rjEF
+Withdrawing ◎5.000000000, or 5 pool tokens, from stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Creating account to receive stake CZF2z3JJoDmJRcVjtsrz1BKUUGNL3VPW5FPFqge1bzmQ
+Signature: 2xBPVPJ749AE4hHNCNYdjuHv1EdMvxm9uvvraWfTA7Urrvecwh9w64URCyLLroLQ2RKDGE2QELM2ZHd8qRkjavJM
+```
+
+默认情况下,withdraw命令会从池中最大的验证者质押账户中提取资金。也可以使用`--vote-account`标志来指定特定的投票账户进行提取。
+
+```bash
+$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR --amount 5 --vote-account EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Withdrawing ◎5.000000000, or 5 pool tokens, from stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Creating account to receive stake CZF2z3JJoDmJRcVjtsrz1BKUUGNL3VPW5FPFqge1bzmQ
+Signature: 2xBPVPJ749AE4hHNCNYdjuHv1EdMvxm9uvvraWfTA7Urrvecwh9w64URCyLLroLQ2RKDGE2QELM2ZHd8qRkjavJM
+```
+
+请注意,关联的验证者质押账户必须有足够的lamports来满足请求的池代币数量。
+
+#### 特殊情况:退出有拖欠者的池子
+
+使用储备质押,一个拖欠或恶意的质押者可以通过`decrease-validator-stake`操作将所有质押转移到储备中,这样池代币将不会获得奖励,而质押池用户也将无法提取他们的资金。
+
+为了解决这种情况,也可以从质押池的储备中提取资金,但前提是所有的验证者质押账户都必须至少有`1 SOL + 质押账户的租金免除金额`。
+
+```bash
+$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 5 --use-reserve
+Withdrawing ◎5.000000000, or 5 pool tokens, from stake account J5XB7mWpeaUZxZ6ogXT57qSCobczx27vLZYSgfSbZoBB
+Creating account to receive stake 51XdXiBSsVzeuY79xJwWAGZgeKzzgFKWajkwvWyrRiNE
+Signature: yQH9n7Go6iCMEYXqWef38ZYBPwXDmbwKAJFJ4EHD6TusBpusKsfNuT3TV9TL8FmxR2N9ExZTZwbD9Njc3rMvUcf
+```
+
+#### 特殊情况:从池中移除验证者
+
+由于用于将验证者添加到池中的资金来自外部存款,因此拖欠或恶意的质押者可能会使用户无法通过将所有资金保持在最低金额来回收他们的SOL。
+
+为了解决这种情况,也可以从质押池中移除验证者,但前提是所有的验证者质押账户都必须至少有`1 SOL + 质押账户的租金免除金额`。这意味着,如果验证者的质押账户中有足够的资金来覆盖租金免除,用户就可以从池中移除验证者,即使质押者试图通过保持最低金额来阻止用户回收资金。这样的机制可以保护用户的利益,确保他们能够从质押池中提取自己的份额。
+
+```bash
+$ spl-stake-pool withdraw-stake Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 1.00228288 SOL
+Withdrawing ◎1.00228288 or 1.00228288 pool tokens, from stake account J5XB7mWpeaUZxZ6ogXT57qSCobczx27vLZYSgfSbZoBB
+Creating account to receive stake 51XdXiBSsVzeuY79xJwWAGZgeKzzgFKWajkwvWyrRiNE
+Signature: yQH9n7Go6iCMEYXqWef38ZYBPwXDmbwKAJFJ4EHD6TusBpusKsfNuT3TV9TL8FmxR2N9ExZTZwbD9Njc3rMvUcf
+```
diff --git a/docs/SolanaProgramLibrary/stake-pool/fees.md b/docs/SolanaProgramLibrary/stake-pool/fees.md
new file mode 100644
index 0000000..87ac59a
--- /dev/null
+++ b/docs/SolanaProgramLibrary/stake-pool/fees.md
@@ -0,0 +1,89 @@
+# 费用
+
+质押池的运营商应该花时间理解每种费用的目的,并仔细考虑它们,以确保质押池不会被滥用。
+
+有五种不同的费用来源。
+
+### 纪元费用
+
+每个纪元(大约2天),池中的质押账户会获得通胀奖励,因此质押池会按获得奖励的比例,将池子代币铸造到管理者的费用账户中。
+
+例如,如果池子获得了10 SOL的奖励,并且费用设置为2%,管理者将获得价值0.2 SOL的池子代币。
+
+请注意,纪元费用是在正常验证者佣金评估后收取的。例如,如果一个验证者收取8%的佣金,质押池收取2%,而池中的质押在佣金前赚取了100 SOL,那么这个质押实际上会为池增加90.16 SOL。该验证者的总奖励将减少约9.84%。
+
+当纪元费用更新时,变更仅在两个纪元边界后生效。例如,如果在100纪元更新纪元费用,新的费用将仅从102纪元开始使用。
+
+### SOL提款费
+
+将所需提款金额的一部分发送给管理者。
+
+例如,如果用户希望提款100池子代币,费用设置为3%,3池子代币将归管理者所有,剩余的97代币将转换为SOL并发送给用户。
+
+当SOL提款费更新时,变更仅在两个纪元边界后生效。例如,如果在100纪元更新费用,新的费用将仅从102纪元开始使用。
+
+此外,费用增加限制为当前费用的1.5倍。例如,如果当前费用为2.5%,则可设置的最高费用为3.75%,这将在两个纪元边界后生效。
+
+### 质押提款费
+
+在为用户创建新的质押之前,将所需提款金额的一部分发送给管理者。
+
+例如,如果用户希望提款100池子代币,费用设置为0.5%,0.5池子代币将归管理者所有,剩余的99.5代币将转换为SOL然后作为已激活的质押账户发送给用户。
+
+当质押提款费更新时,变更仅在两个纪元边界后生效。例如,如果在100纪元更新费用,新的费用将仅从102纪元开始使用。
+
+此外,费用增加限制为当前费用的1.5倍。例如,如果当前费用为2.5%,则可设置的最高费用为3.75%,这将在两个纪元边界后生效。
+
+### SOL存款费
+
+将整个SOL存款转换为池子代币,然后将池子代币的一部分发送给管理者,其余部分发送给用户。
+
+例如,如果用户存入100 SOL,转换为90池子代币,费用为1%,那么用户将收到89.1池子代币,管理者将收到0.9池子代币。
+
+### 质押存款费
+
+将质押账户的委托加上租金豁免转换为池子代币,将其中一部分发送给管理者,其余部分发送给用户。质押账户的租金豁免部分按照SOL存款率转换,而质押按照质押存款率转换。
+
+例如,假设池子代币与SOL的汇率为1:1,SOL存款率为10%,质押存款率为5%。如果用户存入一个质押账户,其中质押了100 SOL和0.00228288 SOL用于租金豁免。来自质押的费用价值5池子代币,来自租金豁免的费用价值0.000228288池子代币,因此用户收到95.002054592池子代币,管理者收到5.000228288池子代币。
+
+## 推荐费(佣金)
+
+对于合作伙伴应用程序,管理者可以在存款上设置推荐费。在SOL或质押存款期间,质押池将池子代币费用的百分比重新分配给另一个地址作为推荐费。
+
+这个选项对钱包提供商特别有吸引力。当钱包集成质押池时,钱包开发者将有机会在用户存入质押池时赚取额外的代币。质押池管理者可以利用这个功能建立战略合作伙伴关系,并吸引更多人使用质押池!
+
+## 最佳实践
+
+除了货币化之外,费用是避免对质押池进行经济攻击并保持其运行的关键工具。为此,质押池CLI将防止管理者创建没有费用的池,除非他们还提供`--yolo`标志。
+
+### 纪元
+
+如果一个有1000个验证者的质押池每个纪元运行一次重新平衡脚本,质押者需要发送大约200笔交易来更新质押池余额,然后多达1000笔交易来增加或减少每个验证者的质押。
+
+在撰写本文时,当前交易费用为每个签名 5,000 lamports ,因此这1200笔交易的最低成本为 6,000,000 lamports ,或0.006 SOL。为了收支平衡,质押池管理者每个纪元必须赚取0.006 SOL的费用。
+
+例如,假设我们有一个质押了10,000 SOL的质押池,其质押赚取6% APY / ~3.3基点每个纪元的收益,每个纪元大约产生3.3 SOL的奖励。这个质押池的最低收支平衡纪元费用为0.18%。
+
+### 质押存款/提款
+
+如果质押池没有存款或提款费,恶意的池子代币持有者可以轻易地从质押池中窃取价值。
+
+在最简单的攻击中,每个纪元的末尾,恶意的池子代币持有者找到池中表现最好的验证者,提取相当于他们所有池子代币的活跃质押,等待纪元滚动,赚取最大的质押奖励,然后立即重新存入质押池。
+
+实际上,恶意存款人总是委托给质押池中表现最好的验证者,而从未真正向该验证者承诺质押。除此之外,恶意存款人绕过了任何纪元费用。
+
+为了使这种攻击不可行,质押池管理者可以设置存款或提款费。如果质押池的整体表现为6% APY / ~3.3基点每个纪元,而最佳验证者的表现为6.15% APY / ~3.37基点每个纪元,那么最低的质押存款/提款费将是0.07基点。
+
+为了完全安全,如果池中的一个违约验证者降低了性能,管理者可能希望提高更多。
+
+### SOL存款/提款
+
+如果质押池的SOL存款/提款费为0,则恶意的SOL持有者可以执行类似的攻击,从池中提取更多价值。
+
+如果他们将SOL存入质押池,提取池中顶级验证者的质押账户,等待纪元滚动,然后将该质押重新存入池中,然后提取SOL,他们基本上在没有任何时间承诺的情况下免费赚取了即时奖励。与此同时,质押池的性能下降了,因为存入的流动SOL没有赚取奖励。
+
+例如,如果质押池中表现最好的验证者赚取6.15% APY / ~3.37基点每个纪元,那么最低的SOL存款/提款费应该是3.37基点。
+
+### 最后的思考
+
+前几节中概述的攻击是任何人都可以轻易执行的最简单的攻击,只需通过每个 epoch 运行几次几个个脚本即可。对于零费用或非常低费用的质押池,可能有更复杂的攻击,因此请确保用费用保护您的存款人!
diff --git a/docs/SolanaProgramLibrary/stake-pool/operation.md b/docs/SolanaProgramLibrary/stake-pool/operation.md
new file mode 100644
index 0000000..090695d
--- /dev/null
+++ b/docs/SolanaProgramLibrary/stake-pool/operation.md
@@ -0,0 +1,146 @@
+# 操作
+
+质押池是赚取质押奖励的另一种方法。这个链上程序将SOL汇集在一起,由质押者进行质押,允许SOL持有者质押并赚取奖励,而无需管理质押。
+
+## 质押
+
+SOL代币持有者可以通过将代币质押给一个或多个验证者来赚取奖励并帮助保护网络。质押代币的奖励基于当前的通胀率、网络上质押的SOL总数以及个别验证者的在线时间和佣金(费用)。
+
+有关质押和质押编程的更多信息,请访问:
+
+- https://solana.com/staking
+- https://docs.solana.com/staking/stake-programming
+
+## 背景
+
+Solana的编程模型和本文档中使用的Solana术语的定义,请访问:
+
+- https://docs.solana.com/apps
+- https://docs.solana.com/terminology
+
+## 激励机制
+
+本文档旨在为质押池系统的主要参与者提供信息:
+
+- 管理者:创建和管理质押池,赚取费用,可以更新费用、质押者和管理者
+- 质押者:向池中添加和移除验证者,重新平衡验证者之间的质押,可以更新质押者
+- 用户:向现有的质押池提供流动或质押SOL
+
+在当前的迭代中,质押池接受活跃的质押或SOL,因此存款可能来自活跃的质押或SOL钱包。提款可以返回质押池账户中的一个完全活跃的质押账户,或者来自储备的SOL。
+
+这意味着质押池管理者和质押者必须熟悉创建和委托质押,这比发送和接收SPL代币和SOL更为高级的操作。有关质押操作的更多信息,请访问:
+
+- https://docs.solana.com/cli/delegate-stake
+- https://docs.solana.com/cli/manage-stake-accounts
+
+为了吸引更多的用户,鼓励质押池管理者通过[Token Swap](https://spl.solana.com/token-swap)等AMM为他们池子的代币提供市场。
+
+或者,质押池管理者可以与钱包和质押账户提供商合作,进行直接的SOL存款。
+
+## 操作
+
+一个质押池管理者创建了一个质押池。此时,用户可以立即通过`deposit-sol`指令参与,将资金转移到储备中以换取池子代币。
+
+使用这些SOL存款,质押者通过使用`add-validator`将“验证者质押账户”添加到池子中,从而包括将从池子中接收委托的验证者。在这个命令中,质押池使用储备资金创建一个新的质押账户并将其委托给所需的验证者。
+
+此时,用户也可以将质押账户存入池子中。为此,他们必须将质押账户委托给质押池中的一个验证者。如果质押池有一个首选的存款验证者,用户必须将他们的质押委托给该验证者的投票账户。
+
+一旦质押在下一个纪元边界(最多2天)激活,用户就可以使用`deposit-stake`指令将他们的质押存入池中。
+
+作为他们存款(SOL或质押)的交换,用户收到代表他们在池中的分数所有权的SPL代币。池中赚取的奖励的一部分作为一个纪元费用归池管理者所有。
+
+随着时间的推移,随着池中的质押累积奖励,用户的分数所有权将比他们最初的存款更有价值。
+
+当他们希望退出池时,用户可以使用`withdraw-sol`指令从质押池的储备中以质押池子代币换取SOL。请注意,如果质押池的储备中没有足够的SOL,此操作将失败,这很正常,如果质押池管理者将池中的所有SOL都进行了质押。
+
+或者,他们可以使用`withdraw-stake`指令以他们的SPL池子代币换取已激活的质押账户。用户将立即得到一个SOL质押账户。在任何情况下,始终可以提取质押。
+
+注意:当提取质押时,如果用户想要提取质押账户中的SOL,他们必须首先停用质押账户并等待到下一个纪元边界(最多2天)。一旦质押不活跃,他们可以自由提取SOL。
+
+质押池质押者可以添加和移除验证者,或通过降低对验证者质押的份额,等待一个纪元将其移动到质押池的储备账户中,然后在另一个验证者上增加质押,来重新平衡池。
+
+质押者添加新验证者的操作需要1.00228288 SOL来在验证者上创建质押账户,因此质押池储备需要流动性。
+
+### 资金限制
+
+为了给管理者更多的控制权,质押池允许通过三种不同的“资金授权”对进入池中的资金进行存款和提款限制:
+
+- SOL存款
+- 质押存款
+- SOL提款
+
+如果设置了这些属性,则该权限账户(authority)必须对关联的指令进行签名。。
+
+例如,如果管理者设置了一个质押存款授权,那么该地址必须签署每个质押存款指令。
+
+这在几种情况下也很有用:
+
+- 控制谁可以向质押池存款
+- 禁止某种形式的存款。例如,管理者只希望有SOL存款,因此他们设置了一个质押存款授权,使得只有在该授权签署交易的情况下才能存入质押账户。
+- 维护模式。如果池需要时间来重置费用或以其他方式,管理者可以通过设置存款授权暂时限制新存款。
+
+注意:为了确保用户资金的安全,始终允许提款。
+
+## 资金安全
+
+质押池程序的主要目标之一是始终允许池子代币持有者随时提取他们的资金。
+
+为此,让我们来看看质押池系统中的三种类别的质押账户:
+
+- 验证者质押:活跃的质押账户,池中每个验证者一个
+- 临时质押:正在激活或停用的质押账户,在停用后合并到储备中,或在激活后合并到验证者质押中,每个验证者一个
+- 储备质押:不活跃的质押,被质押者用于重新平衡
+
+此外,质押者可能会设定一个“首选提取账户”,强制用户从特定的质押账户提款。这是为了防止恶意存款者将质押池作为验证者之间的免费转换。
+
+在处理提款时,优先顺序如下:
+
+- 首选提款的验证者质押账户(如果设置)
+- 验证者质押账户
+- 临时质押账户
+- 储备质押账户
+- 完全移除验证者质押账户
+
+如果有首选提款验证者,并且该验证者质押账户有任何SOL,用户必须从该账户提款。
+
+如果该账户为空,或者没有设置首选提款验证者质押账户,那么用户必须从任何验证者质押账户中提款。
+
+如果所有验证者质押账户都为空,这可能会发生如果质押池质押者一次性减少所有验证者上的质押,那么用户必须从任何临时质押账户中提款。
+
+如果所有临时质押账户都为空,那么用户必须从储备中提款或完全移除验证者质押账户。
+
+通过这种方式,用户的资金永远不会处于风险中,始终可以赎回。
+
+## 附录
+
+### 活跃质押
+
+如前所述,质押池与活跃质押配合使用,以保持质押池代币的可替代性。由于质押的时间成本,完全激活的质押并不等同于非活动、激活或停用的质押。
+
+### 临时质押账户
+
+每个验证者都会得到一个临时质押账户,因此质押者一次只能对验证者执行一个动作。不可能同时增加和减少对验证者的质押。质押者必须等到现有的临时质押账户在一个`update`指令中合并后才能执行新动作。
+
+### 储备质押账户
+
+每个质押池都初始化了一个未委托的储备质押账户,用于在重新平衡过程中持有未委托的质押。当质押者减少对验证者的质押时,并在经历一个纪元后,更新操作会将减少的质押合并到储备中。相反,每当质押者增加对验证者的质押时,就会从储备质押账户中提取lamports。
+
+### 验证者列表账户
+
+每个质押池都包含两个数据账户:质押池和验证者列表。
+
+质押池包含有关池子的总体信息,包括费用、池子代币铸造、管理金额等。
+
+验证者列表包含有关池中每个验证者质押账户的特定信息。这些信息包括池在验证者上质押的SOL金额,以及在验证者上激活/停用的SOL金额。
+
+每个质押池都必须有自己的验证者列表账户,否则初始化时会失败。
+
+### 交易大小
+
+Solana交易处理器有两个重要的限制:
+
+- 整体交易的大小,限制在大约 1 MTU /数据包
+- 每个指令的计算预算
+
+一个质押池可能管理数百个质押账户,因此不可能在一条指令中更新质押池的总价值。幸运的是,命令行工具将会拆分交易,以避免大型池子遇到这个问题。
+
diff --git a/docs/SolanaProgramLibrary/stake-pool/quickstart.md b/docs/SolanaProgramLibrary/stake-pool/quickstart.md
new file mode 100644
index 0000000..9188e7c
--- /dev/null
+++ b/docs/SolanaProgramLibrary/stake-pool/quickstart.md
@@ -0,0 +1,178 @@
+# 快速开始指南
+
+本指南适用于希望立即开始运行质押池的管理者。
+
+## 前提条件
+
+本指南需要 Solana CLI 工具套件和 Stake Pool CLI 工具。
+
+- [安装 Solana 工具](https://docs.solana.com/cli/install-solana-cli-tools)
+- [安装 Stake Pool CLI](https://spl.solana.com/stake-pool/cli)
+
+你还必须拥有一个包含 SOL 的账户。假设你使用的是通过 `solana-keygen new` 在默认位置创建的默认密钥对。请注意,如果需要,可以在每个命令中覆盖默认密钥对。
+
+如果你在本地使用 `solana-test-validator`,默认密钥对会自动启动并拥有 500,000,000 SOL。
+
+如果你在 开发网 或 测试网 上运行,可以使用 `solana airdrop 1` 来空投资金。
+
+如果你在 主网beta版 上运行,则必须通过其他方式(如从交易所或朋友等处)购买资金。
+
+## 示例脚本
+
+本指南使用 [GitHub 上的示例脚本](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/cli/scripts) 来快速轻松地运行所有内容。
+
+你将看到以下脚本:
+
+- `setup-test-validator.sh`:设置带有验证者投票账户的本地测试验证者
+- `setup-stake-pool.sh`:创建具有硬编码参数的新质押池
+- `add-validators.sh`:向质押池添加验证者
+- `deposit.sh`:进行质押和 SOL 存款
+- `rebalance.sh`:重新平衡质押池
+- `withdraw.sh`:进行一些提款
+
+本指南将使用大多数这些脚本在本地网络上设置质押池。
+
+## (可选)步骤 0:设置本地网络以进行测试
+
+所有这些脚本都可以在 开发网、测试网 或 主网beta版 上运行,但为了进行更多实验,我们将使用 `setup-test-validator.sh` 设置一个带有一些验证者投票账户的本地验证者。
+
+该脚本接受要创建的投票账户数量和输出验证者投票账户的文件路径,例如:
+
+```bash
+$ ./setup-test-validator.sh 10 local_validators.txt
+```
+
+这大约需要 10 秒钟,最终会输出一个包含 base58 编码公钥列表的文件。这些代表本地网络上的验证者投票账户,例如:
+
+```bash
+EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+J3xu64PWShcMen99kU3igxtwbke2Nwfo8pkZNRgrq66H
+38DYMkwYCvsj8TC6cNaEvFHHVDYeWDp1qUgMgyjNqZXk
+7q371UZcYJTMmFPeijUJ6RBr6jHE9t4mDd2gnDs7wpje
+7ffftyketRJrmCcczhSnWatxB32SzAG3dhDpnyRdm91d
+HtqJXQNWr4E1qxftAxxqNnHbpSYnokayHSxurzS9vKKF
+4e6EmSSmExdRM6tF1osYiAq9HxXN5oVvDqS78FcT6F4P
+DrT6VGqqJT1GRVaZmuEjNim4ie7ecmNixjiycd67jyJy
+71vNo5HBuAtejbcQYp9CdBeT7npVdbJqjmuWbXbNeudq
+7FMebvnWnWN45KF5Fa3Y7kAJZReKU6WLzribtWDJybax
+```
+
+注意:如果另一个 `solana-test-validator` 已经在运行,这将会失败。
+
+### 本地网络的重要注意事项
+
+如果你使用的是 32 个槽位的纪元,那么在使用某个质押池命令时,则很有可能在使用其中一个质押池命令时传递一个纪元,导致其失败并显示:`Custom program error: 0x11`。这是完全正常的,并且在其他网络上不会发生。你只需重新运行命令。
+
+由于测试验证者网络上没有投票活动,你需要在使用 `solana delegate-stake` 时使用 `--force` 标志,例如:
+
+```bash
+$ solana delegate-stake --force stake.json CzDy6uxLTko5Jjcdm46AozMmrARY6R2aDBagdemiBuiT
+```
+
+## 步骤 1:创建质押池
+
+我们的下一个脚本是 `setup-stake-pool.sh`。在其中,你会看到一个很大的区域可以在其中修改你的质押池参数。这些参数用于创建新的质押池,并包括:
+
+- 纪元(epoch)费用,以两个不同的标志表示,分子和分母
+- 提款费用,以两个不同的标志表示,分子和分母
+- 存款费用,以两个不同的标志表示,分子和分母
+- 推荐费用(佣金),以 0 到 100 之间的数字表示(包括 0 和 100)
+- 最大验证者数量(目前最高可能是 2,950)
+- (可选)存款授权,用于受限制的池
+
+虽然费用在此时似乎不太有趣或有欺骗性,但请考虑运行质押池的成本,以及潜在的恶意行为者,如果您的权益池没有费用,他们可能会滥用您的权益池。
+
+这些参数中的每一个在池子创建后都是可修改的,因此不必担心被锁定在任何选择中。
+
+修改参数以满足你的需求。费用尤其重要,以避免滥用,因此请花时间审查和计算最适合你的池子的费用。
+
+仔细阅读[费用](https://spl.solana.com/stake-pool/fees)以获取有关费用和最佳实践的更多信息。
+
+在我们的示例中,我们将使用 0.3% 的费用、50% 的推荐费用,选择不设置存款授权,并拥有最大数量的验证
+
+```bash
+$ ./setup-stake-pool.sh 15
+Creating pool
++ spl-stake-pool create-pool --epoch-fee-numerator 3 --epoch-fee-denominator 1000 --withdrawal-fee-numerator 3 --withdrawal-fee-denominator 1000 --deposit-fee-numerator 3 --deposit-fee-denominator 1000 --referral-fee 50 --max-validators 2350 --pool-keypair keys/stake-pool.json --validator-list-keypair keys/validator-list.json --mint-keypair keys/mint.json --reserve-keypair keys/reserve.json
+Creating reserve stake 4tvTkLB4X7ahUYZ2NaTohkG3mud4UBBvu9ZEGD4Wk9mt
+Creating mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB
+Creating associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Creating pool fee collection account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ
+Signature: 51yf2J6dSGAx42KPs2oTMTV4ufEm1ncAHyLPQ6PNf4sbeMHGqno7BGn2tHkUnrd7PRXiWBbGzCWpJNevYjmoLgn2
+Creating stake pool Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR with validator list 86VZZCuqiz7sDJpFKjQy9c9dZQN9vwDKbYgY8pcwHuaF
+Signature: 47QHcWMEa5Syg13C3SQRA4n88Y8iLx1f39wJXQAStRUxpt2VD5t6pYgAdruNRHUQt1ZBY8QwbvEC1LX9j3nPrAzn
+Depositing SOL into stake pool
+Update not required
+Using existing associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Signature: 4jnS368HcofZ1rUpsGZtmSK9kVxFzJRndSX5VS7eMV3kVgzyg9efA4mcgd2C6BoSNksTmTonRGXTVM1WMywFpiKq
+```
+
+你的质押池现在已经存在了!对于最大数量的验证者,此阶段的成本约为 2.02 SOL,加上存入池中的 15 SOL 以换取池代币。
+
+## 步骤 2:向池中存入 SOL
+
+现在池子已经存在,让我们存入一些 SOL 以换取一些池代币。
+
+SOL 可能是最具吸引力的存款形式,因为它对每个人来说都是最容易使用的。通常,这可能通过 DeFi 应用或钱包完成,但在我们的示例中,我们将直接从命令行进行操作。
+
+在创建池子时,我们已经存入了 15 SOL,但现在让我们再向池中存入 10 SOL:
+
+```bash
+$ spl-stake-pool deposit-sol Zg5YBPAk8RqBR9kaLLSoN5C8Uv7nErBz1WC63HTsCPR 10
+Using existing associated token account DgyZrAq88bnG1TNRxpgDQzWXpzEurCvfY2ukKFWBvADQ to receive stake pool tokens of mint BoNneHKDrX9BHjjvSpPfnQyRjsnc9WFH71v8wrgCd7LB, owned by 4SnSuUtJGKvk2GYpBwmEsWG53zTurVM8yXGsoiZQyMJn
+Signature: 4AJv6hSznYoMGnaQvjWXSBjKqtjYpjBx2MLezmRRjWRDa8vUaBLQfPNGd3kamZNs1JeWSvnzczwtzsMD5WkgKamA
+```
+
+## 步骤 3:向池中添加验证者
+
+现在池中已经有了一些 SOL,我们需要向其中添加验证者。
+
+使用 `add-validators.sh` 脚本,我们将把在步骤 0 中创建的每个验证者添加到质押池中。如果你在其他网络上运行,可以创建一个包含验证者投票账户的文件。
+
+```bash
+$ ./add-validators.sh keys/stake-pool.json local_validators.txt
+Adding validator stake accounts to the pool
+Adding stake account 3k7Nwu9jUSc6SNG11wzufKYoZXRFgxWamheGLYWp5Rvx, delegated to EhRbKi4Vhm1oUCGWHiLEMYZqDrHwEd7Jgzgi26QJKvfQ
+Signature: 5Vm2n3umPXFzQgDiaib1B42k7GqsNYHZWrauoe4DUyFszczB7Hjv9r1DKWKrypc8KDiUccdWmJhHBqM1fdP6WiCm
+Signature: 3XtmYu9msqnMeKJs9BopYjn5QTc5hENMXXiBwvEw6HYzU5w6z1HUkGwNW24io4Vu9WRKFFN6SAtrfkZBLK4fYjv4
+... (something similar repeated 9 more times)
+```
+
+此操作将从储备中移动 1.00228288 SOL 到给定验证者的质押账户。这意味着您要添加的每个验证者都需要超过 1 个 SOL。
+
+## 步骤 4:向池中质押
+
+现在你的池中已有验证者,它可以接受质押账户供您管理。存款有两种可能来源:SOL 或质押账户。在步骤 2 中,我们直接存入了 SOL,所以现在我们将存入质押账户。
+
+此选项对已经拥有质押账户的用户特别有吸引力,他们可能希望换取质押池代币,或者希望进一步分散他们的质押。
+`deposit.sh` 脚本展示了如何使用 CLI 来实现这一点。
+
+创建新的质押,将给定数量的资金存入池中的每个质押账户,使用质押池和验证者文件。
+
+```bash
+$ ./deposit.sh keys/stake-pool.json local_validators.txt 10
+```
+
+## 步骤 5:重新平衡池中的质押
+
+随着时间的推移,当人们将 SOL 存入储备时,或者随着验证者性能的变化,你可能需要重新分配质押。最佳方式是通过一个自动化系统来收集关于质押池和网络的信息,并决定分配给每个验证者的质押数量。
+
+Solana 基金会为其委托计划维护了一个开源机器人,可以为你的质押池进行适配。源码是 [stake-o-matic GitHub仓库](https://github.com/solana-labs/stake-o-matic/tree/master/bot) 的一部分。
+
+此外,还有一个正在开发中的 Python 质押池机器人,可以在 [stake-pool-py on GitHub](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/py) 中找到。
+
+在我们的示例中,我们将运行一个简单的池重新平衡器,它会按给定数量增加列表中每个验证者的质押。没有任何检查或逻辑来确保这是有效的。
+
+```bash
+$ ./rebalance.sh keys/stake-pool.json local_validators.txt 100
+```
+
+## 步骤 6:从质押池中提款
+
+最后,如果用户想从质押池中提款,他们可以选择从储备中提取 SOL(如果储备中有足够的 SOL),或者从池中的某个质押账户中提取。
+
+`withdraw.sh` 脚本根据质押池、验证者文件和金额,从池中的每个质押账户中移除质押和 SOL。
+
+```bash
+$ ./withdraw.sh keys/stake-pool.json local_validators.txt 100
+```
diff --git a/docs/SolanaProgramLibrary/transfer-hook-interface.md b/docs/SolanaProgramLibrary/transfer-hook-interface.md
new file mode 100644
index 0000000..48a33d1
--- /dev/null
+++ b/docs/SolanaProgramLibrary/transfer-hook-interface.md
@@ -0,0 +1,11 @@
+# 转账钩子接口
+
+转账钩子接口(Transfer Hook Interface)是 Solana 程序库中引入的几个接口之一,任何 Solana 程序都可以实现该接口。
+
+在转账过程中,Token-2022会使用此接口调用铸币配置的转账钩子程序,如[转账钩子扩展指南](https://spl.solana.com/token-2022/extensions#transfer-hook)中所述。此外,SPL的GitHub仓库中还提供了一个[参考实现](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/example),详细介绍了如何在自己的程序中实现该接口。
+
+转账钩子接口旨在允许代币创建者在代币转账中“挂钩”(附带)额外的功能。代币程序通过接口定义的指令调用转账钩子程序来进行 CPI(跨程序调用)调用转账钩子程序。然后转账钩子程序可以执行任何自定义功能。
+
+对于Token-2022,代币创建者使用铸币扩展来配置转账钩子程序,这个扩展告诉Token-2022在进行转账时应调用哪个程序。
+
+通过这个接口,程序可以组成高度可定制的转账功能,并且可以与许多其他程序兼容,特别是实现了SPL Token接口的代币。
diff --git a/docs/SolanaProgramLibrary/transfer-hook-interface/configuring-extra-accounts.md b/docs/SolanaProgramLibrary/transfer-hook-interface/configuring-extra-accounts.md
new file mode 100644
index 0000000..e9b2fd2
--- /dev/null
+++ b/docs/SolanaProgramLibrary/transfer-hook-interface/configuring-extra-accounts.md
@@ -0,0 +1,119 @@
+# 配置额外账户
+
+正如前面提到的,实现转账钩子接口的程序可以为代币转账提供额外的自定义功能。然而,这些功能可能需要转账指令中不存在的额外账户(例如源账户、铸币账户、目标账户等)。
+
+转账钩子接口规范的一部分是验证账户,这是一个存储转账钩子程序所需的额外账户配置的账户。
+
+## 验证账户
+
+验证账户是从转账钩子程序派生的PDA(程序派生地址),其种子如下:
+
+```tex
+"extra-account-metas" +
+```
+
+可以看出,一个验证账户映射到一个铸币账户。这意味着您可以按每个铸币账户定制所需的额外账户!
+
+验证账户使用[类型-长度-值](https://en.wikipedia.org/wiki/Type%E2%80%93length%E2%80%93value)(TLV)编码来存储额外账户的配置:
+
+- **类型:** 指令识别符,此处为 `Execute`
+- **长度:** 后续数据缓冲区的总长度,此处为一个 `u32`
+- **数据:** 数据其本身,包含额外账户配置的数据
+
+当转账钩子程序希望从验证账户反序列化额外账户配置时,可以找到8字节的 `Execute` 指令识别符,然后读取长度,并使用该长度反序列化数据。
+
+数据本身是固定大小的配置对象列表,序列化为字节块。由于条目是固定长度的,我们可以使用自定义的“切片”结构,通过将长度除以固定长度来确定条目的数量。
+
+这种自定义切片结构称为 `PodSlice`,是 Solana 程序库中的 [Pod 库](https://github.com/solana-labs/solana-program-library/tree/master/libraries/pod) 的一部分。Pod 库提供了一些实现 `bytemuck` `Pod` 特性(trait) 的固定长度类型,以及 `PodSlice`。
+
+另一个用于处理类型-长度-值(TLV)编码数据的 SPL 库是 [Type-Length-Value](https://github.com/solana-labs/solana-program-library/tree/master/libraries/type-length-value) 库,它广泛用于管理 TLV 编码的数据结构。
+
+## 动态账户解析
+
+当客户端构建代币程序的转账指令时,他们必须确保指令包含所有必需的账户,特别是验证账户中指定的额外必需账户。
+
+这些额外账户必须被**解析**,另一个用于解析转账钩子额外账户的库是 [TLV Account Resolution](https://github.com/solana-labs/solana-program-library/tree/master/libraries/tlv-account-resolution)(TLV 帐户解析库)。
+
+使用TLV 帐户解析库,转账钩子程序可以实现额外必需账户的**动态解析**。这意味着任何特定客户端或程序都不需要知道转账钩子所需的具体账户。相反,它们可以从验证账户的数据中自动解析。
+
+实际上,转账钩子接口在接口 crate 的[链上](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/interface/src/onchain.rs)和[链下](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/interface/src/offchain.rs)模块中提供了执行此账户解析的帮助函数。
+
+账户解析功能通过存储额外账户配置的方式,以及如何用于派生实际的 Solana 地址和角色(签名者、可写等)来实现。
+
+## `ExtraAccountMeta` 结构体
+
+作为 TLV 帐户解析库的成员,[`ExtraAccountMeta`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/tlv-account-resolution/src/account.rs#L75) 结构体允许账户配置序列化为长度为35字节的固定长度数据格式。
+
+```rust
+pub struct ExtraAccountMeta {
+ /// 区分这是标准 `AccountMeta` 还是 PDA
+ pub discriminator: u8,
+ /// `address_config` 字段可以是账户的公钥,
+ /// 或用于从提供的输入派生公钥的种子
+ pub address_config: [u8; 32],
+ /// 账户是否应签名
+ pub is_signer: PodBool,
+ /// 账户是否可写
+ pub is_writable: PodBool,
+}
+
+```
+
+正如结构文档所述,, 一个 `ExtraAccountMeta` 可以存储三种类型帐户的配置::
+
+| 识别符 | 账户类型 |
+| :-------------- | :--------------------------------------------------------- |
+| `0` | 静态地址账户 |
+| `1` | 转账钩子程序本身的PDA |
+| `(1 << 7) + i ` | 其他程序衍生的PDA,程序的索引`i`为该程序在账户列表中的索引 |
+
+`1 << 7` 是 `u8` 的最高位,或 `128` 。如果从中派生此 PDA 的程序位于 的 `Execute` 帐户列表的索引 `9` 处,则此帐户配置的识别符为 `128 + 9 = 137` 。稍后将详细介绍确定此索引位置的确定。
+
+### 静态地址账户
+
+静态地址的附加账户使用 `ExtraAccountMeta` 序列化相当直接。在这种情况下,识别符(discriminator)简单地设为 `0`,而 `address_config`(地址配置) 则是 32 字节的公钥。
+
+### 转账钩子程序的PDAs
+
+可能会问:“如何在32字节中存储所有PDA种子?”实际上,不需要。相反,您可以告诉账户解析功能在哪里找到所需的种子。
+
+为此,转账钩子程序可以使用 `Seed` 枚举来描述种子及其位置。除了文字之外,这些种子配置仅包含少量字节。
+
+`Seed` 枚举支持以下类型的种子,可用于创建`address_config`的字节数组:
+
+- **字面值(Literal)**: 编码为字节的字面种子。
+- **指令数据(Instruction Data)**: 指令数据的一个切片,由`index`(偏移量)和`length`(长度)指定。
+- **账户密钥(AccountKey)**: 账户列表中某个账户的地址,以字节形式表示,指定该账户在账户列表中的`index`
+- **账户数据(Account Data)**: 某账户数据的一个切片,通过`account_index`指定该账户在账户列表中的位置,以及`data_index`和`length`定义要提取的字节范围。
+
+下面是一个将一组`Seed` 条目打包进一个32字节的 `address_config` 的示例:
+
+```rust
+let seed1 = Seed::Literal { bytes: vec![1; 8] };
+let seed2 = Seed::InstructionData {
+ index: 0,
+ length: 4,
+};
+let seed3 = Seed::AccountKey { index: 0 };
+let address_config: [u8; 32] = Seed::pack_into_address_config(
+ &[seed1, seed2, seed3]
+)?;
+```
+
+### 其他程序的PDAs
+
+存储其他程序PDA地址的种子配置与上述相同。然而,此账户的地址必须在账户列表中,其索引是构建正确识别符并解析正确PDA所需的。
+
+```rust
+let program_index = 7;
+let seeds = &[seed1, seed2, seed3];
+let is_signer = false;
+let is_writable = true;
+
+let extra_meta = ExtraAccountMeta::new_external_pda_with_seeds(
+ program_index,
+ seeds,
+ is_signer,
+ is_writable,
+)?;
+```
diff --git a/docs/SolanaProgramLibrary/transfer-hook-interface/examples.md b/docs/SolanaProgramLibrary/transfer-hook-interface/examples.md
new file mode 100644
index 0000000..866b413
--- /dev/null
+++ b/docs/SolanaProgramLibrary/transfer-hook-interface/examples.md
@@ -0,0 +1,180 @@
+# 示例
+
+更多的示例可以在[转账钩子(Transfer Hook)示例测试](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/example/tests/functional.rs)以及[TLV 账户解析(Account Resolution)测试](https://github.com/solana-labs/solana-program-library/blob/master/libraries/tlv-account-resolution/src/state.rs)中找到。
+
+## 链上初始化额外账户元数据
+
+[`ExtraAccountMetaList`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/tlv-account-resolution/src/state.rs#L167)结构体设计用于实现与额外账户配置工作的高度集成。
+
+使用 `ExtraAccountMetaList::init(..)` 方法,你可以通过提供缓冲区的可变引用和 `ExtraAccountMeta` 的切片来初始化缓冲区中的序列化 ExtraAccountMeta 配置。泛型 `T` 是指应分配额外账户配置的指令。在我们的例子中,这将是转账钩子接口中的[`spl_transfer_hook_interface::instruction::ExecuteInstruction`](https://github.com/solana-labs/solana-program-library/blob/eb32c5e72c6d917e732bded9863db7657b23e428/token/transfer-hook/interface/src/instruction.rs#L68)。
+
+> 注意:SPL Transfer Hook 接口中的所有指令都实现了 [`SplDiscriminate`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/discriminator/src/discriminator.rs#L9)特征(trait ),该特征提供一个常量 8 字节的识别符,可用于创建 TLV 数据条目。
+
+```rust
+pub fn process_initialize_extra_account_meta_list(
+ program_id: &Pubkey,
+ accounts: &[AccountInfo],
+ extra_account_metas: &[ExtraAccountMeta],
+) -> ProgramResult {
+ let account_info_iter = &mut accounts.iter();
+
+ let validation_info = next_account_info(account_info_iter)?;
+ let mint_info = next_account_info(account_info_iter)?;
+ let authority_info = next_account_info(account_info_iter)?;
+ let _system_program_info = next_account_info(account_info_iter)?;
+
+ // 检查验证账户
+ let (expected_validation_address, bump_seed) =
+ get_extra_account_metas_address_and_bump_seed(mint_info.key, program_id);
+ if expected_validation_address != *validation_info.key {
+ return Err(ProgramError::InvalidSeeds);
+ }
+
+ // 创建账户
+ let bump_seed = [bump_seed];
+ let signer_seeds = collect_extra_account_metas_signer_seeds(mint_info.key, &bump_seed);
+ let length = extra_account_metas.len();
+ let account_size = ExtraAccountMetaList::size_of(length)?;
+ invoke_signed(
+ &system_instruction::allocate(validation_info.key, account_size as u64),
+ &[validation_info.clone()],
+ &[&signer_seeds],
+ )?;
+ invoke_signed(
+ &system_instruction::assign(validation_info.key, program_id),
+ &[validation_info.clone()],
+ &[&signer_seeds],
+ )?;
+
+ // 写入数据
+ let mut data = validation_info.try_borrow_mut_data()?;
+ ExtraAccountMetaList::init::(&mut data, extra_account_metas)?;
+
+ Ok(())
+}
+
+```
+
+调用 `ExtraAccountMetaList::init::(..)` 可变帐户数据后,该帐户现在存储了 `Execute` 指令的所有序列化额外帐户配置!
+
+## 解析链下额外账户元数据
+
+在构建指令时,无论是直接用于您的转账钩子程序还是用于将 CPI(跨程序调用)到您的转账钩子程序的另一个程序,您必须包含所有必需的账户,包括额外的账户。
+
+以下是一个示例,展示了转账钩子接口[链下辅助函数](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/token/transfer-hook/interface/src/offchain.rs#L50)中所含逻辑。
+
+```rust
+// 您需要提供一个“账户数据函数”,这是一个函数,可以根据给定的 `Pubkey` 返回 `AccountDataResult` 中的账户数据。
+// 这很可能基于像 `getAccountInfo` 这样的 RPC 调用。
+
+// 加载验证状态数据
+let validate_state_pubkey = get_extra_account_metas_address(mint_pubkey, program_id);
+let validate_state_data = fetch_account_data_fn(validate_state_pubkey)
+ .await?
+ .ok_or(ProgramError::InvalidAccountData)?;
+
+// 首先创建一个 `ExecuteInstruction`
+let mut execute_instruction = execute(
+ program_id,
+ source_pubkey,
+ mint_pubkey,
+ destination_pubkey,
+ authority_pubkey,
+ &validate_state_pubkey,
+ amount,
+);
+
+// 为 `ExecuteInstruction` 解析所有额外必需账户
+ExtraAccountMetaList::add_to_instruction::(
+ &mut execute_instruction,
+ fetch_account_data_fn,
+ &validate_state_data,
+)
+.await?;
+
+// 仅添加从验证状态解析的额外账户
+instruction
+ .accounts
+ .extend_from_slice(&execute_instruction.accounts[5..]);
+
+// 添加程序 ID 和验证状态账户
+instruction
+ .accounts
+ .push(AccountMeta::new_readonly(*program_id, false));
+instruction
+ .accounts
+ .push(AccountMeta::new_readonly(validate_state_pubkey, false));
+
+```
+
+从示例中可以看出,记住这些额外账户是针对哪个指令的这一重要概念非常关键。即使您可能正在为其他程序构建指令,如果该程序要 CPI 到您的转账钩子程序,它也需要包含正确的账户。
+
+此外,为了成功执行动态账户解析,需要提供与验证账户中配置的指令相匹配的正确指令——在这里是指转账钩子接口的`ExecuteInstruction`。因此,我们首先创建一个`ExecuteInstruction`,然后为该指令解析额外账户,最后将这些账户添加到我们当前的指令中。
+
+## CPI 的链上解析额外账户元数据
+
+在执行一个希望 CPI 到您的转账钩子程序的程序期间,即使额外必需账户是通过链下账户解析提供的,执行程序仍然需要知道如何构建带有正确账户的 CPI 指令!
+
+以下是一个示例,展示了转账钩子接口[链上辅助函数](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/token/transfer-hook/interface/src/onchain.rs#L67)中所包含的逻辑。
+
+```rust
+// 从 `AccountInfo` 列表中找到验证账户并加载其数据
+let validate_state_pubkey = get_extra_account_metas_address(mint_info.key, program_id);
+let validate_state_info = account_infos
+ .iter()
+ .find(|&x| *x.key == validate_state_pubkey)
+ .ok_or(TransferHookError::IncorrectAccount)?;
+
+// 找到转账钩子程序 ID
+let program_info = account_infos
+ .iter()
+ .find(|&x| x.key == program_id)
+ .ok_or(TransferHookError::IncorrectAccount)?;
+
+// 首先创建一个 `ExecuteInstruction`
+let mut execute_instruction = instruction::execute(
+ program_id,
+ source_info.key,
+ mint_info.key,
+ destination_info.key,
+ authority_info.key,
+ &validate_state_pubkey,
+ amount,
+);
+let mut execute_account_infos = vec![
+ source_info,
+ mint_info,
+ destination_info,
+ authority_info,
+ validate_state_info.clone(),
+];
+
+// 为 `ExecuteInstruction` 解析所有额外必需账户
+ExtraAccountMetaList::add_to_cpi_instruction::(
+ &mut execute_instruction,
+ &mut execute_account_infos,
+ &validate_state_info.try_borrow_data()?,
+ account_infos,
+)?;
+
+// 仅添加从验证状态解析的额外账户
+cpi_instruction
+ .accounts
+ .extend_from_slice(&execute_instruction.accounts[5..]);
+cpi_account_infos.extend_from_slice(&execute_account_infos[5..]);
+
+// 添加程序 ID 和验证状态账户
+cpi_instruction
+ .accounts
+ .push(AccountMeta::new_readonly(*program_id, false));
+cpi_instruction
+ .accounts
+ .push(AccountMeta::new_readonly(validate_state_pubkey, false));
+cpi_account_infos.push(program_info.clone());
+cpi_account_infos.push(validate_state_info.clone());
+
+```
+
+虽然这个例子可能看起来比链下例子更冗长,但实际上它执行的是完全相同的步骤,只是带有一个指令和一个账户信息列表,因为 CPI 需要这两者。
+
+`ExtraAccountMetaList::add_to_instruction(..)` 和 `ExtraAccountMetaList::add_to_cpi_instruction(..)` 两个方法之间的主要区别在于,后者方法会在添加解析的 `AccountMeta` 到指令的同时找到账户信息列表中的相应 `AccountInfo`,并将其添加到 `cpi_account_infos` 中,以确保所有解析的账户密钥都存在于 `AccountInfo` 列表中。
diff --git a/docs/SolanaProgramLibrary/transfer-hook-interface/specification.md b/docs/SolanaProgramLibrary/transfer-hook-interface/specification.md
new file mode 100644
index 0000000..0384fb7
--- /dev/null
+++ b/docs/SolanaProgramLibrary/transfer-hook-interface/specification.md
@@ -0,0 +1,49 @@
+# 规范
+
+转账钩子(Transfer Hook)接口规范包括两个可选指令和一个必需指令。
+
+每个转账钩子接口的指令在其指令数据的开头,都使用一个特定的 8 字节识别符。
+
+## 指令:`Execute`(执行)
+
+`Execute`(执行)指令是任何希望实现该接口的程序所必需的,这也是自定义转账功能所在的指令。
+
+- **识别符:**字符串字面量` "spl-transfer-hook-interface" `的前 8 字节哈希值
+- **数据:**
+ - `amount: u64` - 转账金额
+- **金额:**
+ - 1 `[]`: 源代币账户
+ - 2 `[]`: Mint 地址
+ - 3 `[]`: 目标代币账户
+ - 4 `[]`: 源代币授权账户
+ - 5 `[]`: 验证账户
+ - `n` 其他附加账户,写入验证账户中
+
+**验证账户**是转账钩子接口中的关键组成部分,在[下一节](https://spl.solana.com/transfer-hook-interface/configuring-extra-accounts)中有更详细的介绍。简而言之,它是一个存储配置数据的账户,可以反序列化以确定转账钩子程序所需的其他账户。
+
+接口的以下两个指令处理这些配置。
+
+## (可选) 指令: `InitializeExtraAccountMetaList`
+
+这条指令顾名思义:它初始化验证账户以存储`Execute`指令所需的额外[`AccountMeta`](https://docs.rs/solana-program/latest/solana_program/instruction/struct.AccountMeta.html)配置列表。
+
+- **识别符:** 字符串字面量` "spl-transfer-hook-interface" `的前 8 字节哈希值
+- **数据:**
+ - `extra_account_metas: Vec` - 需要写入验证账户的额外账户配置列表
+- **账号:**
+ - 1 `[writable]`(可写): 验证账户
+ - 2 `[]`: Mint 地址
+ - 3 `[signer]`(签名者): Mint 权限持有者
+ - 4 `[]`: 系统程序 (System program)
+
+## (可选) 指令: `UpdateExtraAccountMetaList`
+
+`UpdateExtraAccountMetaList` 指令允许链上程序更新其 `Execute` 所需账户列表。通过实施此指令,开发人员可以更新存储在验证账户中的所需额外账户列表。
+
+- **识别符:** 字符串字面量` "spl-transfer-hook-interface" `的前 8 字节哈希值
+- **数据:**
+ - `extra_account_metas: Vec` - 需要写入验证账户的额外账户配置列表
+- **账号:**
+ - 1 `[writable]`(可写): 验证账户
+ - 2 `[]`: Mint 地址
+ - 3 `[signer]`(签名者): 铸造权限持有者
diff --git a/docs/SolanaResources/assets.md b/docs/SolanaResources/assets.md
new file mode 100644
index 0000000..2897590
--- /dev/null
+++ b/docs/SolanaResources/assets.md
@@ -0,0 +1,6 @@
+# 资产查询
+
+- [Sonar](https://sonar.watch/) Solana 生態系最完整的資產瀏覽器
+- [Step](https://app.step.finance/en/dashboard) 會同時統計DeFi 和NFT 資產價值
+- [Nansen](https://portfolio.nansen.ai/) 原Apeboard,現被Nansen 收購
+- [Pulsar](https://app.pulsar.finance/portfolio) 最新支援的資產瀏覽器
diff --git a/docs/SolanaResources/defi.md b/docs/SolanaResources/defi.md
new file mode 100644
index 0000000..1cb8c86
--- /dev/null
+++ b/docs/SolanaResources/defi.md
@@ -0,0 +1,51 @@
+# Defi
+
+## 现货交易与借贷协议
+
+|协议|类别|介绍|
+| ----------- | ----------- |----------- |
+|[Jupiter](https://jup.ag/)|交易聚合器|TiSolana 代幣交易聚合器、Perp 交易tle|
+|[Meteora](https://www.meteora.ag/)|稳定币Dex|动态手续费与流动性挖矿|
+|[Birdeye](https://birdeye.so/?chain=solana)|代币信息聚合|研究价格走势的优秀Dapp,交易通过Jup|
+|[Orca](https://www.orca.so/)|AMM DEX|Solana 最大AMM、提供集中流动性交易池|
+|[Ray](https://raydium.io/)|AMM DEX|Solana 第二大AMM、提供集中流动性交易池|
+|[Saber](https://app.saber.so/swap)|稳定币Dex|古老的稳定币去中心化交易所|
+|[Solend](https://solend.fi/)|借贷协议|Solana 上最古老的借贷协议|
+|[Marginfi](https://www.mfi.gg/)|借贷协议|新锐借贷协议|
+|[Lulo](https://flexlend.fi/)|借贷协议聚合器|整合各大收益來源的聚合器|
+
+## 流动性挖矿与衍生品
+
+|协议|类别|介绍|
+| --- | --- | --- |
+|[Kamino](https://kamino.finance/)|流动性挖矿|Hubble团队,专注在Orca/Ray的最大收益矿池|
+|[Hawksight](https://www.hawksight.co/)|流动性挖矿|聚合Solana流动性挖矿的一站式解決方案|
+|[Francium](https://francium.io/)|杠杆挖矿|最大的杠杆挖矿,开始往EVM探索|
+|[Tulip](https://tulip.garden/#home)|杠杆挖矿|第二大的杠杆挖矿|
+|[Drift](https://www.drift.trade/)|永续合约DEX|vAMM模型|
+|[Zeta](https://www.zeta.markets/)|永续合约DEX|合约杠杆可高达20倍|
+|[Mango](https://mango.markets/)|永续合约DEX|全仓模式,V4正在开发中|
+|[Flash Trade](https://www.flash.trade/#)|永续合约DEX|新锐Perp trade协议,有三个LP池子|
+|[Mango boost](https://boost.mango.markets/)|杠杆挖矿|芒果社群开发的JLP杠杆工具|
+
+## 流动性质押
+
+|协议|类别|介绍|
+| --- | --- | --- |
+|[Marinade](https://marinade.finance/)|流动性质押|Solana 最大的流动性质押协议|
+|[Jito](https://www.jito.network/)|流动性质押|流动性质押+MEV 收益|
+|[Sanctum](https://www.sanctum.so/)|流动性质押|流动性质押协议|
+|[UXD](https://uxd.fi/)|算法稳定币|类似FRAX 100%USDC 背书|
+|[Hubble](https://hubbleprotocol.io/)|超額抵押稳定币|深度整合各種DeFi 协议|
+
+## 其它协议
+
+|协议|类别|介绍|
+| --- | --- | --- |
+|[Wormhole/Portal](https://www.portalbridge.com/#/transfer)|跨鏈橋|Jump 支持的頂級跨鏈橋|
+|[Mayan](https://mayan.finance/)|跨鏈橋|基於蟲洞 Auction base 的跨鏈橋|
+|[deBridge](https://debridge.finance/)|跨鏈橋|支援多鏈的跨鏈橋|
+|[Bonfida](https://bonfida.org/en)|域名系統|.sol 是人類可讀域名,方便轉錢|
+|[Alldomains](https://alldomains.id/)|域名系統|.abc .bonk 等等域名,非常有趣|
+|[Cega](https://app.cega.fi/)|期權|奇異期權 (同時在ETH和ARB也有)|
+|[PsyFinance](https://app.psyfi.io/vaults)|借貸协议/期權|期權項目 也有開放借貸功能 [SDX Market](https://app.sdx.markets/trade)|
\ No newline at end of file
diff --git a/docs/SolanaResources/explorer.md b/docs/SolanaResources/explorer.md
new file mode 100644
index 0000000..27d8f7e
--- /dev/null
+++ b/docs/SolanaResources/explorer.md
@@ -0,0 +1,9 @@
+# Solana浏览器
+
+- [官网浏览器](https://explorer.solana.com/)
+- [Solscan](https://solscan.io/)
+- [Solana Beach](https://solanabeach.io/)
+- [Solana FM](https://solana.fm/)
+- [EPOCH浏览器](https://solstake.io/#/app)
+- [铭文浏览器](https://www.libreplex.io/)
+- [K线浏览器](https://birdeye.so/)
\ No newline at end of file
diff --git a/docs/SolanaResources/information.md b/docs/SolanaResources/information.md
new file mode 100644
index 0000000..255c069
--- /dev/null
+++ b/docs/SolanaResources/information.md
@@ -0,0 +1,20 @@
+# 信息查询
+
+## 官网
+
+- [Solana 官網](https://solana.com/ecosystem)
+
+## 信息看板
+
+- [Defillama](https://defillama.com/chain/Solana)
+- [Dune](https://dune.com/browse/dashboards?q=solana)
+- [Nasen](https://pro.nansen.ai/multichain/solana)
+- [Vyper network](https://alpha.vybenetwork.com/)
+
+## Solana 協議收入資訊站
+
+- [Flipside](https://science.flipsidecrypto.xyz/solana-project-earnings/)
+
+## 地址的 SOL 手續費花費
+
+- [Solfee](https://www.solfees.fyi/)
\ No newline at end of file
diff --git a/docs/SolanaResources/infrastructure.md b/docs/SolanaResources/infrastructure.md
new file mode 100644
index 0000000..fbd993a
--- /dev/null
+++ b/docs/SolanaResources/infrastructure.md
@@ -0,0 +1,19 @@
+# 基础设施
+
+## DAO 基礎建設
+
+- [Realms](https://realms.today/)
+- [Tribeca](https://tribeca.so/)
+
+## 多簽錢包
+
+- [Squad](https://squads.so/)
+- [Snowflake](https://snowflake.so/#/)
+- [MeanFi](https://meanfi.com/)
+
+## 实用工具
+
+- [Solfees](https://www.solfees.fyi/)
+- [Solanatools](https://solanatools.vercel.app/)
+- [SPL-token](https://www.spl-token-ui.com/)
+- [StreamFlow](https://streamflow.finance/)
\ No newline at end of file
diff --git a/docs/SolanaResources/wallets.md b/docs/SolanaResources/wallets.md
new file mode 100644
index 0000000..11031b2
--- /dev/null
+++ b/docs/SolanaResources/wallets.md
@@ -0,0 +1,6 @@
+# 钱包
+
+- [Phantom](https://phantom.app/) 插件(支援Ledger)、手機App
+- [Solflare](https://solflare.com/) 插件(支援Ledger\keystone)、手機App
+- [Backpack](https://www.backpack.app/) 插件錢包、手機App
+- [Bonk bot](https://t.me/bonkbot_bot?start=ref_kowei) Telegram Bot衝土狗的錢包
diff --git a/docs/SolanaValidatorDocumentation/cli/examples/delegate-staking.md b/docs/SolanaValidatorDocumentation/cli/examples/delegate-staking.md
index 96d5827..1bd9328 100644
--- a/docs/SolanaValidatorDocumentation/cli/examples/delegate-staking.md
+++ b/docs/SolanaValidatorDocumentation/cli/examples/delegate-staking.md
@@ -2,7 +2,7 @@
[收到SOL](https://docs.solanalabs.com/cli/examples/transfer-tokens)后,您可以考虑通过将质押委托给验证者节点来使用它。质押就是我们所说的质押账户中的代币。Solana 根据委托给他们的质押量来衡量验证者节点的投票,这让这些节点在确定区块链中下一个有效的交易块时拥有更大的影响力。然后,Solana 会定期生成新的 SOL 来奖励质押者和验证者节点。您委托的质押越多,您获得的奖励就越多。
-:::tips INFO
+:::tip INFO
要了解有关质押的概述,请首先阅读 [质押和通胀常见问题解答](https://solana.com/staking).
:::
diff --git a/docs/SolanaValidatorDocumentation/cli/examples/durable-nonce.md b/docs/SolanaValidatorDocumentation/cli/examples/durable-nonce.md
new file mode 100644
index 0000000..a20086f
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/examples/durable-nonce.md
@@ -0,0 +1,224 @@
+# Solana CLI 中的持久化交易随机数
+
+持久交易随机数(Durable Transaction Nonces)是一种绕过交易的短暂 `recent_blockhash` 生命周期的机制。它们被一个 Solana 程序实现,可以在[提案](https://docs.solanalabs.com/implemented-proposals/durable-tx-nonces)中阅读其机制。
+
+## 使用示例
+
+可以在 [CLI 参考](https://docs.solanalabs.com/cli/usage) 中找到持久随机数的 CLI 命令用法详细信息。
+
+### 随机数权限方
+
+随机数账户的权限可以选择分配给另一个账户。这样,新权限继承了前一个权限的对随机数账户的完全控制,包括账户创建者。此功能使得可以创建更复杂的账户所有权安排和不与密钥对关联的派生账户地址。使用 `--nonce-authority ` 参数来指定该账户并支持以下命令:
+
++ `create-nonce-account`
++ `new-nonce`
++ `withdraw-from-nonce-account`
++ `authorize-nonce-account`
+
+### 随机数账户创建
+
+持久交易随机数的功能是使用一个账户来存储下一个随机数值。持久随机数账户必须是[租金豁免](https://docs.solanalabs.com/implemented-proposals/rent#two-tiered-rent-regime)的,因此需要存有最低余额。
+
+首先生成新的密钥对,然后在链上创建帐户来创建随机数帐户
+
++ 命令
+
+```bash
+solana-keygen new -o nonce-keypair.json
+solana create-nonce-account nonce-keypair.json 1
+```
+
++ 输出
+
+```bash
+2SymGjGV4ksPdpbaqWFiDoBz8okvtiik4KE9cnMQgRHrRLySSdZ6jrEcpPifW4xUpp4z66XM9d9wM48sA7peG2XL
+```
+
+> 要是密钥对全程离线,请转而使用[纸钱包](https://docs.solanalabs.com/cli/wallets/paper)密钥对生成[指令](https://docs.solanalabs.com/cli/wallets/paper#seed-phrase-generation)。
+
+> [完整的使用文档](https://docs.solanalabs.com/cli/usage#solana-create-nonce-account)
+
+### 查询储存的随机数值
+
+创建持久随机数交易,需要将存储的随机数值作为 `--blockhash` 参数的值进行签名和提交。使用以下命令获取当前存储的随机数值:
+
++ 命令
+
+```bash
+solana nonce nonce-keypair.json
+```
+
++ 输出
+
+```bash
+8GRipryfxcsxN8mAGjy8zbFo9ezaUsh47TsPzmZbuytU
+```
+
+> [完整的使用文档](https://docs.solanalabs.com/cli/usage#solana-get-nonce)
+
+### 推进储存的随机数值
+
+尽管通常在有更好用的交易之外不需要使用,但是可以通过以下的方法来推进储存的随机数值:
+
++ 命令
+
+```bash
+solana new-nonce nonce-keypair.json
+```
+
++ 输出
+
+```bash
+44jYe1yPKrjuYDmoFTdgPjg8LFpYyh1PFKJqm5SC1PiSyAL8iw1bhadcAX1SL7KDmREEkmHpYvreKoNv6fZgfvUK
+```
+
+> [完整使用文档](https://docs.solanalabs.com/cli/usage#solana-new-nonce)
+
+### 展示随机数账户
+
+以更人性化的格式查看随机数帐户
+
++ 命令
+
+```bash
+solana nonce-account nonce-keypair.json
+```
+
++ 输出
+
+```bash
+balance: 0.5 SOL
+minimum balance required: 0.00136416 SOL
+nonce: DZar6t2EaCFQTbUP4DHKwZ1wT8gCPW2aRfkVWhydkBvS
+```
+
+> [完整的使用文档](https://docs.solanalabs.com/cli/usage#solana-nonce-account)
+
+### 从随机数账户中提款
+
+使用以下命令从随机数账户中提款:
+
++ 命令
+
+```bash
+solana withdraw-from-nonce-account nonce-keypair.json ~/.config/solana/id.json 0.5
+```
+
++ 输出
+
+```bash
+3foNy1SBqwXSsfSfTdmYKDuhnVheRnKXpoPySiUDBVeDEs6iMVokgqm7AqfTjbk7QBE8mqomvMUMNQhtdMvFLide
+```
+
+> 通过提取全部余额来关闭随机数帐户
+
+> [完整的使用文档](https://docs.solanalabs.com/cli/usage#solana-withdraw-from-nonce-account)
+
+### 为随机数账户分配新权限人
+
+为创建后的随机数账户重新分配权限,请使用:
+
++ 命令
+
+```bash
+solana authorize-nonce-account nonce-keypair.json nonce-authority.json
+```
+
++ 输出
+
+```bash
+3F9cg4zN9wHxLGx4c3cUKmqpej4oa67QbALmChsJbfxTgTffRiL3iUehVhR9wQmWgPua66jPuAYeL1K2pYYjbNoT
+```
+
+> [完整的使用文档](https://docs.solanalabs.com/cli/usage#solana-authorize-nonce-account)
+
+## 其他支持持久随机数的命令
+
+要在其他 CLI 子命令中使用持久随机数,需要两个参数:
+
++ `--nonce` ,指定存储随机数值的账户
++ `--nonce-authority` ,用于指定一个可选的[随机数权限账户](https://docs.solanalabs.com/cli/examples/durable-nonce#nonce-authority)
+
+到目前为止,以下子命令支持此功能:
+
+- [`pay`](https://docs.solanalabs.com/cli/usage#solana-pay)
+- [`delegate-stake`](https://docs.solanalabs.com/cli/usage#solana-delegate-stake)
+- [`deactivate-stake`](https://docs.solanalabs.com/cli/usage#solana-deactivate-stake)
+
+### 使用持久随机数支付示例
+
+这里我们演示 Alice 使用持久随机数向 Bob 支付 1 SOL。对于所有支持持久随机数的子命令,过程都是相同的。
+
+**- 创建账户**
+
+首先,我们需要为Alice、Alice的随机数账户和Bob创建一些账户。
+
+```bash
+$ solana-keygen new -o alice.json
+$ solana-keygen new -o nonce.json
+$ solana-keygen new -o bob.json
+```
+
+**- 为 Alice 的账户充值**
+
+Alice 需要一些资金来创建一个随机数账户并发送给 Bob。给她空投一些SOL
+
+```bash
+$ solana airdrop -k alice.json 1
+1 SOL
+```
+
+**- 创建 Alice 的随机数账户**
+
+现在 Alice 需要一个随机数账户,创建一个。
+
+> 在这里,不使用单独的 [随机数权限](https://docs.solanalabs.com/cli/examples/durable-nonce#nonce-authority) ,因此 `alice.json` 对随机数账户拥有完全权限。
+
+```bash
+$ solana create-nonce-account -k alice.json nonce.json 0.1
+3KPZr96BTsL3hqera9up82KAU462Gz31xjqJ6eHUAjF935Yf8i1kmfEbo6SVbNaACKE5z6gySrNjVRvmS8DcPuwV
+```
+
+**- 第一次尝试向 Bob 支付失败**
+
+Alice 尝试支付 Bob,但签名时间过长。指定的 blockhash 过期,交易失败。
+
+```bash
+$ solana transfer -k alice.json --blockhash expiredDTaxfagttWjQweib42b6ZHADSx94Tw8gHx11 bob.json 0.01
+[2020-01-02T18:48:28.462911000Z ERROR solana_cli::cli] Io(Custom { kind: Other, error: "Transaction \"33gQQaoPc9jWePMvDAeyJpcnSPiGUAdtVg8zREWv4GiKjkcGNufgpcbFyRKRrA25NkgjZySEeKue5rawyeH5TzsV\" failed: None" })
+Error: Io(Custom { kind: Other, error: "Transaction \"33gQQaoPc9jWePMvDAeyJpcnSPiGUAdtVg8zREWv4GiKjkcGNufgpcbFyRKRrA25NkgjZySEeKue5rawyeH5TzsV\" failed: None" })
+```
+
+**- 随机数账户来补救!**
+
+Alice 重试交易,这次指定她的随机数账户和存储在那里的 blockhash。
+
+> 记住,在这个例子里,`alice.json` 是随机数权限账户。
+
+```bash
+$ solana nonce-account nonce.json
+balance: 0.1 SOL
+minimum balance required: 0.00136416 SOL
+nonce: F7vmkY3DTaxfagttWjQweib42b6ZHADSx94Tw8gHx3W7
+```
+
+```bash
+$ solana transfer -k alice.json --blockhash F7vmkY3DTaxfagttWjQweib42b6ZHADSx94Tw8gHx3W7 --nonce nonce.json bob.json 0.01
+HR1368UKHVZyenmH7yVz5sBAijV6XAPeWbEiXEGVYQorRMcoijeNAbzZqEZiH8cDB8tk65ckqeegFjK8dHwNFgQ
+```
+
+**- 成功!**
+
+交易成功!Bob 收到了来自 Alice 的 0.01 SOL,并且 Alice 的存储随机数前进到了一个新值。
+
+```bash
+$ solana balance -k bob.json
+0.01 SOL
+```
+
+```bash
+$ solana nonce-account nonce.json
+balance: 0.1 SOL
+minimum balance required: 0.00136416 SOL
+nonce: 6bjroqDcZgTv6Vavhqf81oBHTv3aMnX19UTB51YhAZnN
+```
diff --git a/docs/SolanaValidatorDocumentation/cli/examples/sign-offchain-message.md b/docs/SolanaValidatorDocumentation/cli/examples/sign-offchain-message.md
new file mode 100644
index 0000000..f044050
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/examples/sign-offchain-message.md
@@ -0,0 +1,73 @@
+# 使用 Solana CLI 进行链下消息签名
+
+链下消息签名是一种使用 Solana 钱包对非交易消息进行签名的方法。此功能可用于验证用户身份或提供钱包所有权的证明。
+
+## 签名链下消息
+
+要签署任意链下消息,请运行以下命令:
+
+```bash
+solana sign-offchain-message
+```
+
+消息将被编码并使用 CLI 的默认私钥签名,签名结果将输出。如果你想使用其他密钥签名,只需使用 `-k/--keypair` 选项:
+
+```bash
+solana sign-offchain-message -k
+```
+
+默认情况下,构建消息的版本为0,这是当前唯一支持的版本。当其他版本可用时,您可以使用 `--version` 选项覆盖默认值:
+
+```bash
+solana sign-offchain-message -k --version
+```
+
+消息格式根据版本和消息文本自动确定。
+
+版本 `0` 头部指定了三种消息格式,以便在消息的兼容性和组合之间做出权衡:
+
+| ID | 编码方式 | 最大长度 | 硬件钱包支持 |
+| :--: | :--------------: | :------: | :----------: |
+| 0 | 受限制的 ASCII * | 1212 | 是 |
+| 1 | UTF-8 | 1212 | 仅盲签名 |
+| 2 | UTF-8 | 65515 | 否 |
+
+\* 是指 [`isprint(3)` ](https://linux.die.net/man/3/isprint) 返回 true 的那些字符,即 `0x20..=0x7e`。
+
+格式 `0` 和 `1` 是针对硬件钱包支持设计的,因为硬件钱包的 RAM 用于存储有效载荷,并且字体字符支持有限。
+
+要使用 Ledger 硬件钱包签署链下消息,请确保你的 Ledger 运行最新的固件版本以及 Solana Ledger 应用程序版本 1.3.0 或更高版本。在 Ledger 解锁且 Solana Ledger 应用程序打开后,运行:
+
+```bash
+solana sign-offchain-message -k usb://ledger
+```
+
+有关如何设置和使用账本设备的更多信息,请查阅[此链接](https://docs.solanalabs.com/cli/wallets/hardware/ledger)。
+
+请注意,UTF-8 编码的消息需要在 Solana Ledger App 中启用 `Allow blind sign` (允许盲签名)选项。此外,由于 Ledger 设备缺乏 UTF-8 支持,在这种情况下仅会显示消息的哈希值。
+
+如果 `Display mode`(展示模式)设置为 `Expert`(专家模式) ,Ledger 将显示有关要签名的消息的技术信息。
+
+## 验证链下消息签名
+
+要验证链下消息签名,请运行以下命令:
+
+```bash
+solana verify-offchain-signature
+```
+
+CLI 会使用默认的签名者公钥。您可以使用 `--signer` 选项来指定其他的密钥:
+
+```bash
+solana verify-offchain-signature --signer
+```
+
+如果签名邮件的版本与默认版本不同,则需要显式指定匹配版本:
+
+```bash
+solana verify-offchain-signature --version
+```
+
+## 协议规范
+
+为了确保链下消息不是有效的交易,它们被编码为固定的前缀: `\xffsolana offchain` ,其中选择第一个字节,使其作为当今交易 `MessageHeader` 中的第一个字节隐含非法。有关有效载荷格式和其他注意事项的更多详细信息,请参阅[提案](More details about the payload format and other considerations are available in the [proposal](https://github.com/solana-labs/solana/blob/master/docs/src/proposals/off-chain-message-signing.md).)。
diff --git a/docs/SolanaValidatorDocumentation/cli/examples/test-validator.md b/docs/SolanaValidatorDocumentation/cli/examples/test-validator.md
new file mode 100644
index 0000000..c8ef3f5
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/examples/test-validator.md
@@ -0,0 +1,146 @@
+# Solana 测试验证器
+
+在开发的早期阶段,通常需要针对一个比公共网络提供更多配置选项且限制更少的集群进行开发。这可以通过 `solana-test-validator` 二进制文件轻松实现,它能在开发者的工作站上启动一个功能齐全的单节点集群。
+
+## 优势
+
++ 无RPC速率限制
++ 无空投限制
++ 直接部署[链上程序](https://solana.com/docs/programs)(`--bpf-program ...`)
++ 从公共集群克隆账户,包括程序(使用 `--clone ...`)
++ 从文件加载账户
++ 可配置的交易历史保留(`--limit-ledger-size ...`)
++ 可配置的纪元长度(`--slots-per-epoch ...`)
++ 跳转到任意的插槽(`--warp-slot ...`)
+
+## 安装
+
+`solana-test-validator` 二进制文件随 Solana CLI 工具套件一同提供。在开始前,请先[安装](https://docs.solanalabs.com/cli/install)。
+
+## 运行
+
+首先查看配置选项:
+
+```bash
+solana-test-validator --help
+```
+
+然后启动测试验证者节点
+
+```bash
+solana-test-validator
+```
+
+默认情况下,运行时会打印基本状态信息。详细信息见[附录1](https://docs.solanalabs.com/cli/examples/test-validator#appendix-i-status-output)。
+
+```bash
+Ledger location: test-ledger
+Log: test-ledger/validator.log
+Identity: EPhgPANa5Rh2wa4V2jxt7YbtWa3Uyw4sTeZ13cQjDDB8
+Genesis Hash: 4754oPEMhAKy14CZc8GzQUP93CB4ouELyaTs4P8ittYn
+Version: 1.6.7
+Shred Version: 13286
+Gossip Address: 127.0.0.1:1024
+TPU Address: 127.0.0.1:1027
+JSON RPC URL: http://127.0.0.1:8899
+⠈ 00:36:02 | Processed Slot: 5142 | Confirmed Slot: 5142 | Finalized Slot: 5110 | Snapshot Slot: 5100 | Transactions: 5142 | ◎499.974295000
+```
+
+让 `solana-test-validator` 在其的终端中保持运行。当不再需要它时,可以通过`Ctrl-C` 停止。
+
+## 交互
+
+打开一个新的终端,使用 Solana CLI 工具套件中的其他二进制文件或您自己的客户端软件与[正在运行的](https://docs.solanalabs.com/cli/examples/test-validator#running) `solana-test-validator` 实例进行交互。
+
+**将 CLI 工具套件配置为默认目标本地集群**
+
+```bash
+solana config set --url http://127.0.0.1:8899
+```
+
+**验证 CLI 工具套件配置**
+
+```bash
+solana genesis-hash
+```
+
++ **注意:**结果应与 `solana-test-validator` 状态输出中的 `Genesis Hash:` (创世区块哈希)字段匹配。
+
+**检查钱包余额**
+
+```bash
+solana balance
+```
+
++ **注意:**如果显示错误 `No such file or directory (os error 2)`,表示默认钱包尚不存在。使用 `solana-keygen new` 命令创建它。
++ **注意:**如果钱包的 SOL 余额为零,可以通过 `solana airdrop 10` 命令来空投一些本地网络 SOL 。
+
+**执行基本的转账交易**
+
+```bash
+solana transfer EPhgPANa5Rh2wa4V2jxt7YbtWa3Uyw4sTeZ13cQjDDB8 1
+```
+
+**监视链上程序中的 `msg!()` 输出**
+
+```bash
+solana logs
+```
+
++ **注意:**此命令需要在目标交易执行时运行。且在一个单独的终端中运行它。
+
+## 附录1:状态输出
+
+```bash
+Ledger location: test-ledger
+```
+
+* 账本存储目录的文件路径。这个目录可能会变得很大。可以使用 `--limit-ledger-size ...` 存储较少的交易历史记录,或者使用 `--ledger ...` 重新设置它。
+
+```bash
+Log: test-ledger/validator.log
+```
+
++ 验证器文本日志文件的文件路径。也可以通过传递 `--log` 来流式传输日志。在这种情况下,状态输出将被禁止。
+
+```bash
+Identity: EPhgPANa5Rh2wa4V2jxt7YbtWa3Uyw4sTeZ13cQjDDB8
+```
+
++ 验证者在 [gossip 网络](https://docs.solanalabs.com/validator/gossip#gossip-overview)中的身份标识。
+
+```bash
+Version: 1.6.7
+```
+
++ 软件的版本
+
+```bash
+Gossip Address: 127.0.0.1:1024
+TPU Address: 127.0.0.1:1027
+JSON RPC URL: http://127.0.0.1:8899
+```
+
++ 分别代表 [Gossip](https://docs.solanalabs.com/validator/gossip#gossip-overview) ,[交易处理单元](https://docs.solanalabs.com/validator/tpu)和 [JSON RPC](https://solana.com/docs/rpc) 服务的网络地址。
+
+```bash
+⠈ 00:36:02 | Processed Slot: 5142 | Confirmed Slot: 5142 | Finalized Slot: 5110 | Snapshot Slot: 5100 | Transactions: 5142 | ◎499.974295000
+```
+
++ 会话运行时间、三个区块[确认等级](https://solana.com/docs/rpc#configuring-state-commitment)的当前插槽、高度为上次快照的插槽高度、交易计数、[投票权限](https://docs.solanalabs.com/operations/guides/vote-accounts#vote-authority)余额。
+
+## 附录2:运行时功能
+
+默认情况下,测试验证器在所有[运行时功能](https://solana.com/docs/core/runtime#features)激活的情况下运行。
+
+您可以使用 [Solana 命令行工具](https://docs.solanalabs.com/cli/install)验证这一点:
+
+```bash
+solana feature status -ul
+```
+
+由于这可能并不总是需要的,特别是在测试打算部署到主网的程序时,CLI 提供了一个选项来停用特定功能:
+
+```bash
+solana-test-validator --deactivate-feature --deactivate-feature
+```
diff --git a/docs/SolanaValidatorDocumentation/cli/examples/transfer-tokens.md b/docs/SolanaValidatorDocumentation/cli/examples/transfer-tokens.md
new file mode 100644
index 0000000..5cd1524
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/examples/transfer-tokens.md
@@ -0,0 +1,129 @@
+# 使用 Solana CLI 发送与接收代币
+
+本页说明如何使用命令行工具(如[纸质钱包](https://docs.solanalabs.com/cli/wallets/paper)、[文件系统钱包](https://docs.solanalabs.com/cli/wallets/file-system)或[硬件钱包](https://docs.solanalabs.com/cli/wallets/hardware/))接收和发送 SOL 代币。在开始之前,请确保您已创建一个钱包并有访问其地址(公钥)和签名密钥对的权限。查看我们[关于不同类型钱包的密钥对输入规范](https://docs.solanalabs.com/cli/intro#keypair-conventions)。
+
+## 测试你的钱包
+
+在与别人分享公钥以前,您可能想要验证一下该密钥有效,并且您确实拥有相应的私钥。
+
+在本示例中,我们将在您的第一个钱包之外创建第二个钱包,然后将一些代币转移到该钱包。这将确认您可以在选择的钱包类型上发送和接收代币。。
+
+此测试示例使用我们的开发测试网,称为开发网(devnet)。开发网上发行的代币没有价值,所以如果丢失了也不用担心。
+
+### **从空投一些代币以开始**
+
+首先,在 开发网上给自己*空投*一些测试代币。
+
+```shell
+solana airdrop 1 --url https://api.devnet.solana.com
+```
+
+将 `` 替换为您的 base58 编码的公钥/钱包地址。
+
+将返回一个包含交易签名的响应。如果地址的余额没有按预期变化,请运行以下命令以获取可能出错的更多信息:
+
+```shell
+solana confirm -v
+```
+
+### **检查您的余额**
+
+通过检查账户余额确认空投成功。输出应为 `1 SOL`:
+
+```bash
+solana balance --url https://api.devnet.solana.com
+```
+
+### **创建第二个钱包地址**
+
+我们需要一个新的地址来接收我们的代币。创建第二个密钥对并记录其公钥::
+
+```shell
+solana-keygen new --no-passphrase --no-outfile
+```
+
+输出将在文本 `pubkey:` 后包含地址。复制该地址。我们将在下一步中使用它。
+
+```shell
+pubkey: GKvqsuNcnwWqPzzuhLmGi4rzzh55FhJtGizkhHaEJqiV
+```
+
+您也可以以任何形式(如[纸质钱包](https://docs.solanalabs.com/cli/wallets/paper#creating-multiple-paper-wallet-addresses)、[文件系统钱包](https://docs.solanalabs.com/cli/wallets/file-system#creating-multiple-file-system-wallet-addresses)或者[硬件钱包](https://docs.solanalabs.com/cli/wallets/hardware/#multiple-addresses-on-a-single-hardware-wallet))创建第二个(或更多的)钱包。
+
+### **用第一个钱包中向第二个钱包转账**
+
+接下来,通过转移代币证明您拥有空投的代币。Solana 集群只有在您使用与交易中的发送方公钥相对应的私钥对签名时,才会接受转移。
+
+```shell
+solana transfer --from 0.5 --allow-unfunded-recipient --url https://api.devnet.solana.com --fee-payer
+```
+
+将 `` 替换为第一个钱包中密钥对的路径,并将 `` 替换为第二个钱包的地址。
+
+使用 `solana balance` 确认更新后的余额:
+
+```shell
+solana balance --url http://api.devnet.solana.com
+```
+
+其中 `` 是您的密钥对公钥或接收者的公钥。
+
+### **转移代币的完整测试示例**
+
+```shell
+$ solana-keygen new --outfile my_solana_wallet.json # Creating my first wallet, a file system wallet
+Generating a new keypair
+For added security, enter a passphrase (empty for no passphrase):
+Wrote new keypair to my_solana_wallet.json
+==========================================================================
+pubkey: DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK # Here is the address of the first wallet
+==========================================================================
+Save this seed phrase to recover your new keypair:
+width enhance concert vacant ketchup eternal spy craft spy guard tag punch # If this was a real wallet, never share these words on the internet like this!
+==========================================================================
+
+$ solana airdrop 1 DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK --url https://api.devnet.solana.com # Airdropping 1 SOL to my wallet's address/pubkey
+Requesting airdrop of 1 SOL from 35.233.193.70:9900
+1 SOL
+
+$ solana balance DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK --url https://api.devnet.solana.com # Check the address's balance
+1 SOL
+
+$ solana-keygen new --no-outfile # Creating a second wallet, a paper wallet
+Generating a new keypair
+For added security, enter a passphrase (empty for no passphrase):
+====================================================================
+pubkey: 7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv # Here is the address of the second, paper, wallet.
+====================================================================
+Save this seed phrase to recover your new keypair:
+clump panic cousin hurt coast charge engage fall eager urge win love # If this was a real wallet, never share these words on the internet like this!
+====================================================================
+
+$ solana transfer --from my_solana_wallet.json 7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv 0.5 --allow-unfunded-recipient --url https://api.devnet.solana.com --fee-payer my_solana_wallet.json # Transferring tokens to the public address of the paper wallet
+3gmXvykAd1nCQQ7MjosaHLf69Xyaqyq1qw2eu1mgPyYXd5G4v1rihhg1CiRw35b9fHzcftGKKEu4mbUeXY2pEX2z # This is the transaction signature
+
+$ solana balance DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5CNSKK --url https://api.devnet.solana.com
+0.499995 SOL # The sending account has slightly less than 0.5 SOL remaining due to the 0.000005 SOL transaction fee payment
+
+$ solana balance 7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv --url https://api.devnet.solana.com
+0.5 SOL # The second wallet has now received the 0.5 SOL transfer from the first wallet
+
+```
+
+## 接收代币
+
+要接收代币,您需要一个地址供他人发送代币。在 Solana 中,钱包地址是密钥对的公钥。生成密钥对的方法多种多样。您选择的方法将取决于如何存储密钥对。密钥对存储在钱包中。接收代币之前,您需要[创建一个钱包](https://docs.solanalabs.com/cli/wallets/)。完成后,您应该为每个生成的密钥对获得一个公钥。公钥是一个长的 base58 字符串,其长度从 32 到 44 个字符不等。
+
+## 发送代币
+
+如果您已经持有 SOL 并希望向他人发送代币,您将需要密钥对的路径、对方的 base58 编码公钥和转账金额。收集这些信息后,您可以使用 `solana transfer` 命令转账:
+
+```shell
+solana transfer --from --fee-payer
+```
+
+通过 `solana balance` 来检查更新后的余额:
+
+``` shell
+solana balance
+```
diff --git a/docs/SolanaValidatorDocumentation/cli/install.md b/docs/SolanaValidatorDocumentation/cli/install.md
new file mode 100644
index 0000000..f4e0b09
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/install.md
@@ -0,0 +1,213 @@
+# 安装 Solana CLI
+
+可以根据您习惯的工作流程,在您的计算机上安装Solana工具:
+
+- [使用Solana的安装工具(最简单的选项)](https://docs.solanalabs.com/cli/install#use-solanas-install-tool)
+- [下载预构建的二进制文件](https://docs.solanalabs.com/cli/install#download-prebuilt-binaries)
+- [从源代码构建](https://docs.solanalabs.com/cli/install#build-from-source)
+- [使用 Homebrew](https://docs.solanalabs.com/cli/install#use-homebrew)
+
+## 使用Solana的安装工具
+
+### MacOS 和 Linux
+
+- 打开您习惯的终端应用程序
+- 通过运行以下命令在您的计算机上安装 Solana 版本 v1.18.15:
+
+```bash
+sh -c "$(curl -sSfL https://release.solana.com/v1.18.15/install)"
+```
+
+- 您可以将 `v1.18.16` 替换为与所需版本的软件版本匹配的版本标记,也可以使用以下任一标记渠道名称: `stable` 、 `beta` 或 `edge` 。
+- 以下输出表示更新成功:
+
+```bash
+downloading v1.18.15 installer
+Configuration: /home/solana/.config/solana/install/config.yml
+Active release directory: /home/solana/.local/share/solana/install/active_release
+* Release version: v1.18.15
+* Release URL: https://github.com/solana-labs/solana/releases/download/v1.18.15/solana-release-x86_64-unknown-linux-gnu.tar.bz2
+Update successful
+```
+
+- 根据不同系统,安装程序消息的末尾可能会提示您
+
+```bash
+Please update your PATH environment variable to include the solana programs:
+```
+
+- 如果收到上述消息,请将建议的命令复制并粘贴到其下方进行更新`PATH`
+- 通过运行以下命令确认您已安装所需的版本`solana`:
+
+```bash
+solana --version
+```
+
+- 安装成功后, `solana-install update`可用于随时将 Solana 软件进行版本更新。
+
+------
+
+### Windows
+
+- 以管理员身份打开命令提示符 ( `cmd.exe` )
+ - 在 Windows 搜索栏中搜索命令提示符。当命令提示符应用出现时,右键单击并选择“以管理员身份打开”。如果弹出窗口提示您“是否要允许此应用对设备进行更改?”,请单击“是”。
+- 复制并粘贴以下命令,然后按 Enter 键将 Solana 安装程序下载到临时目录中:
+
+```bash
+cmd /c "curl https://release.solana.com/v1.18.15/solana-install-init-x86_64-pc-windows-msvc.exe --output C:\solana-install-tmp\solana-install-init.exe --create-dirs"
+```
+
+- 复制并粘贴以下命令,然后按 Enter 键安装最新版本的 Solana。如果您看到系统弹出安全窗口,请选择允许程序运行。
+
+```bash
+C:\solana-install-tmp\solana-install-init.exe v1.18.15
+```
+
+- 安装程序完成后,按 Enter。
+- 关闭命令提示符窗口,然后以普通用户身份打开新的命令提示符窗口
+ - 在搜索栏中搜索“命令提示符”,然后左键单击命令提示符应用程序图标,无需以管理员身份运行)
+- 通过输入以下命令确认您已安装所需的`solana`版本:
+
+```bash
+solana --version
+```
+
+- 安装成功后, `solana-install update`可用于随时将 Solana 软件进行版本更新
+
+## 下载预构建的二进制文件
+
+如果您不想使用`solana-install`来管理安装,可以手动下载并安装二进制文件。
+
+### Linux
+
+在https://github.com/solana-labs/solana/releases/latest下载二进制文件**solana-release-x86_64-unknown-linux-gnu.tar.bz2**,然后解压归档文件:
+
+```bash
+tar jxf solana-release-x86_64-unknown-linux-gnu.tar.bz2
+cd solana-release/
+export PATH=$PWD/bin:$PATH
+```
+
+### MacOS
+
+在https://github.com/solana-labs/solana/releases/latest下载二进制文件**solana-release-x86_64-apple-darwin.tar.bz2**,然后解压归档文件:
+
+```bash
+tar jxf solana-release-x86_64-apple-darwin.tar.bz2
+cd solana-release/
+export PATH=$PWD/bin:$PATH
+```
+
+### Windows
+
+- 在https://github.com/solana-labs/solana/releases/latest, 下载二进制文件**solana-release-x86_64-pc-windows-msvc.tar.bz2**, 然后使用Winzip或类似工具提取存档:
+- 打开命令提示符并导航到解压二进制文件的目录,然后运行:
+
+```bash
+cd solana-release/
+set PATH=%cd%/bin;%PATH%
+```
+
+## 从源代码开始构建
+
+如果您无法使用预构建的二进制文件,或者更喜欢从源代码构建,请按照以下步骤操作,确保您的系统已安装必要的前提条件。
+
+### 前提条件
+
+在从源代码生成之前,请确保安装:
+
+#### 对于 Debian 和其他 Linux 发行版:
+
+Rust语言:在 https://www.rust-lang.org/tools/install 选中“安装 Rust”,推荐使用以下命令:
+
+```bash
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+安装构建依赖项:
+
+- 基本构建工具
+- 软件包配置
+- Udev 和 LLM 及 libclang
+- 协议缓冲区
+
+```bash
+apt-get install \
+ build-essential \
+ pkg-config \
+ libudev-dev llvm libclang-dev \
+ protobuf-compiler
+```
+
+#### 对于其他 Linux 发行版:
+
+将`apt`替换为发行版的包管理器(例如, `yum` , `dnf` , `pacman` ),并根据需要调整包名称。
+
+#### 对于 macOS:
+
+安装 Homebrew(如果尚未安装),请在 https://brew.sh/ 选中“安装 Hombrew”,推荐使用以下命令:
+
+```bash
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+```
+
+
+使用 Homebrew 安装必要的工具和库:
+
+```bash
+brew install rust pkg-config libudev protobuf llvm coreutils
+```
+
+按照 brew install 命令末尾给出的有关 `PATH` 配置的说明进行操作。
+
+#### 对于 Windows:
+
+
+Rust语言:在 https://www.rust-lang.org/tools/install 选中“安装 Rust”,推荐使用以下命令:
+
+```bash
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+- 在[Visual Studio downloads page](https://visualstudio.microsoft.com/downloads/)下载并安装适用于 Visual Studio 的生成工具(2019 或更高版本)。请确保安装中包含 C++ 生成工具。
+- 安装 LLVM:在[official LLVM download page](https://releases.llvm.org/download.html)下载并安装 LLVM。
+- 安装 Protocol Buffers Compiler (protoc):在 [GitHub releases page of Protocol Buffers](https://github.com/protocolbuffers/protobuf/releases)下载`protoc` ,并将其添加到 `PATH` .
+
+::: tip INFO
+
+Windows 10 或 11 上的用户可能需要安装适用于 Linux 的 Windows 子系统 (WSL) 才能从源代码生成。WSL 提供现有 Windows 安装中运行的 Linux 环境。这样,您可以运行常规 Linux 软件,包括 Solana CLI 的 Linux 版本。
+
+安装后,在 Windows 终端运行 `wsl` ,然后继续执行上面的 Debian 和其他 Linux 发行版。
+
+:::
+
+### 从源代码构建
+
+安装好必备必备条件后,继续从源代码构建 Solana,在[Solana's GitHub releases page](https://github.com/solana-labs/solana/releases/latest)下载源代码文件。解压代码并使用以下命令构建二进制文件:
+
+```bash
+./scripts/cargo-install-all.sh .
+export PATH=$PWD/bin:$PATH
+```
+
+然后,您可以运行以下命令以获得与预构建二进制文件相同的结果:
+
+```bash
+solana-install init
+```
+
+## 使用 Homebrew
+
+此选项要求您在 MacOS 或 Linux 计算机上安装[Homebrew](https://brew.sh/) 包管理器。
+
+### MacOS 和 Linux
+
+- 按照以下说明进行操作: https://formulae.brew.sh/formula/solana
+
+[Homebrew formulae](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/solana.rb) 在每次`solana`发布后都会更新,但也可能存在 Homebrew 版本过时的情况。
+
+- 通过输入以下命令确认您已 `solana` 安装所需的版本:
+
+```bash
+solana --version
+```
diff --git a/docs/SolanaValidatorDocumentation/cli/intro.md b/docs/SolanaValidatorDocumentation/cli/intro.md
new file mode 100644
index 0000000..25c9cee
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/intro.md
@@ -0,0 +1,59 @@
+# Solana CLI介绍
+
+在运行任何 Solana CLI 命令之前,让我们了解一下在所有命令中会看到的一些约定。首先,Solana CLI 实际上是为每个您可能想执行的操作提供的一组不同命令。您可以通过运行以下命令查看所有可能命令的列表:
+
+```bash
+solana --help
+```
+
+要详细了解如何使用特定命令,请运行:
+
+```bash
+solana --help
+```
+
+
+将文本 `` 替换为要了解详细信息的命令名称。
+
+该命令的用法信息通常包含 `` 、 `` 或 `` 等词。每个词都是您可以用来执行命令的文本类型的占位符。例如,您可以将 `42` 或 `100.42` 等数字替换 `` 为 。您可以用您公钥的 base58 编码(例如 `9grmKMwTiZwUHSExjtbFzHLPTdWoXgcg1bZkhvwTrTww` )替换 ``
+
+## 密钥对的规定
+
+使用 CLI 工具的许多命令需要提供 `` 的值。您应该为 `` 使用的值取决于[您创建的命令行钱包 ](https://docs.solanalabs.com/cli/wallets/)的类型。
+
+例如,CLI 帮助显示显示任何钱包地址(也称为 keypair 的公钥)的方式是:
+
+```bash
+solana-keygen pubkey
+```
+
+下面,我们展示了根据您的钱包类型应如何在 `` 中填写内容。
+
+## 纸钱包
+
+在纸钱包中,keypair 是从创建钱包时输入的种子词和可选密码短语中安全派生的。要在示例或帮助文档中使用 `` 文本时使用纸钱包 keypair,请输入 `prompt://` 方案,并且程序将在您运行命令时提示您输入种子词。
+要显示纸钱包的钱包地址:
+
+```bash
+solana-keygen pubkey prompt://
+```
+
+## 文件系统钱包
+
+
+对于文件系统钱包,密钥对存储在您的计算机上的文件中。将`` 替换为密钥对(keypair)文件的完整文件路径。
+
+例如,如果文件系统密钥对文件位置为 `/home/solana/my_wallet.json` ,要显示地址请执行命令:
+
+```bash
+solana-keygen pubkey /home/solana/my_wallet.json
+```
+
+## 硬件钱包
+
+如果您选择了硬件钱包,请使用您的密钥对 URL,例如 `usb://ledger?key=0` .
+
+```bash
+solana-keygen pubkey usb://ledger?key=0
+```
+
diff --git a/docs/SolanaValidatorDocumentation/cli/usage.md b/docs/SolanaValidatorDocumentation/cli/usage.md
new file mode 100644
index 0000000..8dbc978
--- /dev/null
+++ b/docs/SolanaValidatorDocumentation/cli/usage.md
@@ -0,0 +1,3899 @@
+# Solana CLI 参考和用法
+
+[solana-cli crate](https://crates.io/crates/solana-cli)为Solana提供了一个命令行界面工具
+
+## 例子
+
+### 获取公钥(Get Pubkey)
+
+```bash
+// Command
+$ solana-keygen pubkey
+
+// Return
+
+```
+
+### 空投SOL/Lamports
+
+```bash
+// Command
+$ solana airdrop 1
+
+// Return
+"1 SOL"
+```
+
+### 获取余额(Get Balance)
+
+```bash
+// Command
+$ solana balance
+
+// Return
+"3.00050001 SOL"
+```
+
+### 确认交易(Confirm Transaction)
+
+```bash
+// Command
+$ solana confirm
+
+// Return
+"Confirmed" / "Not found" / "Transaction failed with error "
+```
+
+### 部署程序(Deploy program)
+
+```bash
+// Command
+$ solana program deploy
+
+// Return
+
+```
+
+## 用法
+
+### solana-cli
+
+```bash
+solana-cli 1.18.16 (src:bfacaf61; feat:4215500110, client:SolanaLabs)
+Blockchain, Rebuilt for Scale
+
+USAGE:
+ solana [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+SUBCOMMANDS:
+ account Show the contents of an account
+ address Get your public key
+ address-lookup-table Address lookup table management
+ airdrop Request SOL from a faucet
+ authorize-nonce-account Assign account authority to a new entity
+ balance Get your balance
+ block Get a confirmed block
+ block-height Get current block height
+ block-production Show information about block production
+ block-time Get estimated production time of a block
+ catchup Wait for a validator to catch up to the cluster
+ close-vote-account Close a vote account and withdraw all funds remaining
+ cluster-date Get current cluster date, computed from genesis creation time and network
+ time
+ cluster-version Get the version of the cluster entrypoint
+ completion Generate completion scripts for various shells
+ config Solana command-line tool configuration settings
+ confirm Confirm transaction by signature
+ create-address-with-seed Generate a derived account address with a seed. For program derived
+ addresses (PDAs), use the find-program-derived-address command instead
+ create-nonce-account Create a nonce account
+ create-stake-account Create a stake account
+ create-stake-account-checked Create a stake account, checking the withdraw authority as a signer
+ create-vote-account Create a vote account
+ deactivate-stake Deactivate the delegated stake from the stake account
+ decode-transaction Decode a serialized transaction
+ delegate-stake Delegate stake to a vote account
+ epoch Get current epoch
+ epoch-info Get information about the current epoch
+ feature Runtime feature management
+ fees Display current cluster fees (Deprecated in v1.8.0)
+ find-program-derived-address Generate a program derived account address with a seed
+ first-available-block Get the first available block in the storage
+ genesis-hash Get the genesis hash
+ gossip Show the current gossip network nodes
+ help Prints this message or the help of the given subcommand(s)
+ inflation Show inflation information
+ largest-accounts Get addresses of largest cluster accounts
+ leader-schedule Display leader schedule
+ live-slots Show information about the current slot progression
+ logs Stream transaction logs
+ merge-stake Merges one stake account into another
+ new-nonce Generate a new nonce, rendering the existing nonce useless
+ nonce Get the current nonce value
+ nonce-account Show the contents of a nonce account
+ ping Submit transactions sequentially
+ program Program management
+ program-v4 Program V4 management
+ redelegate-stake Redelegate active stake to another vote account
+ rent Calculate rent-exempt-minimum value for a given account data field length.
+ resolve-signer Checks that a signer is valid, and returns its specific path; useful for
+ signers that may be specified generally, eg. usb:~~ledger
+ sign-offchain-message Sign off-chain message
+ slot Get current slot
+ split-stake Duplicate a stake account, splitting the tokens between the two
+ stake-account Show the contents of a stake account
+ stake-authorize Authorize a new signing keypair for the given stake account
+ stake-authorize-checked Authorize a new signing keypair for the given stake account, checking the
+ authority as a signer
+ stake-history Show the stake history
+ stake-minimum-delegation Get the stake minimum delegation amount
+ stake-set-lockup Set Lockup for the stake account
+ stake-set-lockup-checked Set Lockup for the stake account, checking the new authority as a signer
+ stakes Show stake account information
+ supply Get information about the cluster supply of SOL
+ transaction-count Get current transaction count
+ transaction-history Show historical transactions affecting the given address from newest to
+ oldest
+ transfer Transfer funds between system accounts
+ upgrade-nonce-account One-time idempotent upgrade of legacy nonce versions in order to bump them
+ out of chain blockhash domain.
+ validator-info Publish~get Validator info on Solana
+ validators Show summary information about the current validators
+ verify-offchain-signature Verify off-chain message signature
+ vote-account Show the contents of a vote account
+ vote-authorize-voter Authorize a new vote signing keypair for the given vote account
+ vote-authorize-voter-checked Authorize a new vote signing keypair for the given vote account, checking
+ the new authority as a signer
+ vote-authorize-withdrawer Authorize a new withdraw signing keypair for the given vote account
+ vote-authorize-withdrawer-checked Authorize a new withdraw signing keypair for the given vote account,
+ checking the new authority as a signer
+ vote-update-commission Update the vote account's commission
+ vote-update-validator Update the vote account's validator identity
+ wait-for-max-stake Wait for the max stake of any one node to drop below a percentage of total.
+ withdraw-from-nonce-account Withdraw SOL from the nonce account
+ withdraw-from-vote-account Withdraw lamports from a vote account into a specified account
+ withdraw-stake Withdraw the unstaked SOL from the stake account
+```
+
+### solana-account
+
+```bash
+solana-account
+Show the contents of an account
+
+USAGE:
+ solana account [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --lamports Display balance in lamports instead of SOL
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ -o, --output-file Write the account data to this file
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Account contents to show. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+```
+
+### solana-address
+
+```bash
+solana-address
+Get your public key
+
+USAGE:
+ solana address [FLAGS] [OPTIONS]
+
+FLAGS:
+ --confirm-key Confirm key on device; only relevant if using remote wallet
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+```
+
+### solana-address-lookup-table
+
+```bash
+solana-address-lookup-table
+Address lookup table management
+
+USAGE:
+ solana address-lookup-table [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+SUBCOMMANDS:
+ close Permanently closes a lookup table
+ create Create a lookup table
+ deactivate Permanently deactivates a lookup table
+ extend Append more addresses to a lookup table
+ freeze Permanently freezes a lookup table
+ get Display information about a lookup table
+ help Prints this message or the help of the given subcommand(s)
+```
+
+### Solana-airdrop
+
+```bash
+solana-airdrop
+Request SOL from a faucet
+
+USAGE:
+ solana airdrop [FLAGS] [OPTIONS] [RECIPIENT_ADDRESS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ The airdrop amount to request, in SOL
+ Account of airdrop recipient. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+```
+
+### solana-authorize-nonce-account
+
+```bash
+solana-authorize-nonce-account
+Assign account authority to a new entity
+
+USAGE:
+ solana authorize-nonce-account [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment
+ Return information at the selected commitment level [possible values: processed, confirmed, finalized]
+
+ --with-compute-unit-price
+ Set compute unit price for transaction, in increments of 0.000001 lamports per compute unit.
+
+ -C, --config
+ Configuration file to use [default: ~.config~solana~cli~config.yml]
+
+ -u, --url
+ URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta, testnet, devnet, localhost]
+
+ -k, --keypair Filepath or URL to a keypair
+ --with-memo Specify a memo string to include in the transaction.
+ --nonce-authority
+ Provide the nonce authority keypair to use when signing a nonced transaction
+
+ --output
+ Return information in specified output format [possible values: json, json-compact]
+
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Nonce account. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+ Account to be granted authority of the nonce account. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+```
+
+### solana-balance
+
+```bash
+solana-balance
+Get your balance
+
+USAGE:
+ solana balance [FLAGS] [OPTIONS] [ACCOUNT_ADDRESS]
+
+FLAGS:
+ -h, --help Prints help information
+ --lamports Display balance in lamports instead of SOL
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Account balance to check. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+```
+
+### solana-block
+
+```bash
+solana-block
+Get a confirmed block
+
+USAGE:
+ solana block [FLAGS] [OPTIONS] [SLOT]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+
+```
+
+### solana-block-height
+
+```bash
+solana-block-height
+Get current block height
+
+USAGE:
+ solana block-height [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+```
+
+### solana-block-production
+
+```bash
+solana-block-production
+Show information about block production
+
+USAGE:
+ solana block-production [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ --epoch Epoch to show block production for [default: current epoch]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --slot-limit Limit results to this many slots from the end of the epoch [default: full
+ epoch]
+ --ws WebSocket URL for the solana cluster
+```
+
+### solana-block-time
+
+```bash
+solana-block-time
+Get estimated production time of a block
+
+USAGE:
+ solana block-time [FLAGS] [OPTIONS] [SLOT]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Slot number of the block to query
+```
+
+### solana-catchup
+
+```bash
+solana-catchup
+Wait for a validator to catch up to the cluster
+
+USAGE:
+ solana catchup [FLAGS] [OPTIONS] [ARGS]
+
+FLAGS:
+ --follow Continue reporting progress even after the validator has caught up
+ -h, --help Prints help information
+ --log Don't update the progress inplace; instead show updates with its own new lines
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --our-localhost Guess Identity pubkey and validator rpc node assuming local (possibly
+ private) validator [default: 8899]
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Identity of the validator. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+ JSON RPC URL for validator, which is useful for validators with a private RPC service
+```
+
+### solana-close-vote-account
+
+```bash
+solana-close-vote-account
+Close a vote account and withdraw all funds remaining
+
+USAGE:
+ solana close-vote-account [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --authorized-withdrawer Authorized withdrawer [default: cli config keypair]
+ --commitment
+ Return information at the selected commitment level [possible values: processed, confirmed, finalized]
+
+ --with-compute-unit-price
+ Set compute unit price for transaction, in increments of 0.000001 lamports per compute unit.
+
+ -C, --config
+ Configuration file to use [default: ~.config~solana~cli~config.yml]
+
+ --fee-payer
+ Specify the fee-payer account. This may be a keypair file, the ASK keyword
+ or the pubkey of an offline signer, provided an appropriate --signer argument
+ is also passed. Defaults to the client keypair.
+ -u, --url
+ URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta, testnet, devnet, localhost]
+
+ -k, --keypair Filepath or URL to a keypair
+ --with-memo Specify a memo string to include in the transaction.
+ --output
+ Return information in specified output format [possible values: json, json-compact]
+
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Vote account to be closed. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+ The recipient of all withdrawn SOL. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+```
+
+### solana-cluster-date
+
+```bash
+solana-cluster-date
+Get current cluster date, computed from genesis creation time and network time
+
+USAGE:
+ solana cluster-date [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+```
+
+### solana-cluster-version
+
+```bash
+solana-cluster-version
+Get the version of the cluster entrypoint
+
+USAGE:
+ solana cluster-version [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+```
+
+### solana-completion
+
+```bash
+solana-completion
+Generate completion scripts for various shells
+
+USAGE:
+ solana completion [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ -s, --shell [default: bash] [possible values: bash, fish, zsh, powershell, elvish]
+ --ws WebSocket URL for the solana cluster
+```
+
+### solana-config
+
+```bash
+solana-config
+Solana command-line tool configuration settings
+
+USAGE:
+ solana config [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+SUBCOMMANDS:
+ export-address-labels Export the current address labels
+ get Get current config settings
+ help Prints this message or the help of the given subcommand(s)
+ import-address-labels Import a list of address labels
+ set Set a config setting
+```
+
+### solana-confirm
+
+```bash
+solana-confirm
+Confirm transaction by signature
+
+USAGE:
+ solana confirm [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ The transaction signature to confirm
+
+Note: This will show more detailed information for finalized transactions with verbose mode (-v~--verbose).
+
+Account modes:
+ |srwx|
+ s: signed
+ r: readable (always true)
+ w: writable
+ x: program account (inner instructions excluded)
+```
+
+### solana-create-address-with-seed
+
+```bash
+solana-create-address-with-seed
+Generate a derived account address with a seed. For program derived addresses (PDAs), use the find-program-derived-
+address command instead
+
+USAGE:
+ solana create-address-with-seed [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment Return information at the selected commitment level [possible values:
+ processed, confirmed, finalized]
+ -C, --config Configuration file to use [default: ~.config~solana~cli~config.yml]
+ --from From (base) key, [default: cli config keypair]. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+ -u, --url URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta,
+ testnet, devnet, localhost]
+ -k, --keypair Filepath or URL to a keypair
+ --output Return information in specified output format [possible values: json, json-
+ compact]
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ The seed. Must not take more than 32 bytes to encode as utf-8
+ The program_id that the address will ultimately be used for,
+ or one of NONCE, STAKE, and VOTE keywords
+```
+
+### solana-create-nonce-account
+
+```bash
+solana-create-nonce-account
+Create a nonce account
+
+USAGE:
+ solana create-nonce-account [FLAGS] [OPTIONS]
+
+FLAGS:
+ -h, --help Prints help information
+ --no-address-labels Do not use address labels in the output
+ --skip-seed-phrase-validation Skip validation of seed phrases. Use this if your phrase does not use the BIP39
+ official English word list
+ --use-quic Use QUIC when sending transactions.
+ --use-udp Use UDP when sending transactions.
+ -V, --version Prints version information
+ -v, --verbose Show additional information
+
+OPTIONS:
+ --commitment
+ Return information at the selected commitment level [possible values: processed, confirmed, finalized]
+
+ --with-compute-unit-price
+ Set compute unit price for transaction, in increments of 0.000001 lamports per compute unit.
+
+ -C, --config
+ Configuration file to use [default: ~.config~solana~cli~config.yml]
+
+ -u, --url
+ URL for Solana's JSON RPC or moniker (or their first letter): [mainnet-beta, testnet, devnet, localhost]
+
+ -k, --keypair Filepath or URL to a keypair
+ --with-memo Specify a memo string to include in the transaction.
+ --nonce-authority
+ Assign noncing authority to this other entity. Address is one of:
+ * a base58-encoded public key
+ * a path to a keypair file
+ * a hyphen; signals a JSON-encoded keypair on stdin
+ * the 'ASK' keyword; to recover a keypair via its seed phrase
+ * a hardware wallet keypair URL (i.e. usb:~~ledger)
+ --output
+ Return information in specified output format [possible values: json, json-compact]
+
+ --seed
+ Seed for address generation; if specified, the resulting account will be at a derived address of the
+ NONCE_ACCOUNT pubkey
+ --ws WebSocket URL for the solana cluster
+
+ARGS:
+ Keypair of the nonce account to fund
+ The amount to load the nonce account with, in SOL; accepts keyword ALL
+```
+
+### solana-create-stake-account
+
+```bash
+solana-create-stake-account
+Create a stake account
+
+USAGE:
+ solana create-stake-account [FLAGS] [OPTIONS]