gill是一个用于与Solana区块链交互的JavaScript/TypeScript客户端库。它构建于Anza的@solana/kit之上,并与之兼容。gill提供了创建Solana RPC连接、进行RPC调用、创建和签署交易、模拟和确认交易等功能,以及用于常见任务的交易构建器,例如创建带有元数据的token、向目标钱包铸造token、向目标钱包转移token。
<h1 align="center"> gill </h1>
<p align="center"> 用于与 Solana 区块链交互的 javascript/typescript 客户端库 </p>
<p align="center"> <a href="https://github.com/DecalLabs/gill/actions/workflows/publish-packages.yml"><img src="https://img.shields.io/github/actions/workflow/status/DecalLabs/gill/publish-packages.yml?logo=GitHub&label=tests" /></a> <a href="https://www.npmjs.com/package/gill"><img src="https://img.shields.io/npm/v/gill?logo=npm&color=377CC0" /></a> <a href="https://www.npmjs.com/package/gill"><img src="https://img.shields.io/npm/dm/gill?color=377CC0" /></a> </p>
<p align="center"> <img width="600" alt="gill" src="https://raw.githubusercontent.com/DecalLabs/gill/refs/heads/master/docs/public/cover.png" /> </p>
欢迎使用 gill
,这是一个用于与 Solana 区块链交互的 JavaScript/TypeScript 客户端库。你可以使用它在 Node、web、React Native 或几乎任何其他 JavaScript 环境中构建 Solana 应用程序。
Gill 构建于 Anza 构建的 Solana 现代 javascript 库之上,称为 @solana/kit(以前称为“web3.js v2”)。通过在底层使用相同的类型和函数,gill
与 kit
兼容。请参阅 用 gill 替换 Kit。
有关使用 gill 与 web3js v2 的比较,请查看 比较示例。
使用你选择的包管理器安装 gill
:
npm install gill
pnpm add gill
yarn add gill
@solana/kit
库中的所有导入都可以直接替换为 gill
以实现完全相同的功能。此外,还可以解锁仅包含在 Gill 中的附加功能,例如 createSolanaTransaction
。
只需安装 gill 并替换你的导入
在
/examples
目录中查找使用gill
的示例代码片段集合,包括 基本操作 和常见的 token 操作。
你还可以找到一些 NodeJS 特定的辅助程序,例如:
你可以找到用于常见任务的 交易构建器,包括:
有关故障排除和调试 Solana 交易,请参阅下面的 调试模式。
你还可以查阅 Anza 的 JavaScript 客户端 的文档,以获取更多信息和有用的资源。
对于大多数“签名”操作,你需要一个 KeyPairSigner
实例,该实例可用于签署交易和消息。
要生成一个随机的 KeyPairSigner
:
import { generateKeyPairSigner } from "gill";
const signer: KeyPairSigner = await generateKeyPairSigner();
注意:这些签名者是不可提取的,这意味着无法从实例中获取密钥材料。 这是一种更安全的做法,强烈建议使用,而不是可提取的密钥对,除非你确实需要 出于某种原因能够保存密钥对。
可提取的密钥对不太安全,除非你确实需要出于某种原因保存密钥,否则不应使用。 由于在保存这些密钥对时有一些有用的用例,因此 gill 包含一个单独的显式函数来生成 这些可提取的密钥对。
要生成一个随机的、可提取的 KeyPairSigner
:
import { generateExtractableKeyPairSigner } from "gill";
const signer: KeyPairSigner = await generateExtractableKeyPairSigner();
警告:使用 可提取的 密钥对本质上不太安全,因为它们允许提取密钥材料。 显然。因此,应谨慎使用它们,并且仅当你有明确的原因需要 提取密钥材料(例如,如果你要将密钥保存到文件)。
为任何 RPC URL 或标准 Solana 网络别名(即 devnet
、localnet
、mainnet
等)创建 Solana rpc
和 rpcSubscriptions
客户端。
import { createSolanaClient } from "gill";
const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
urlOrMoniker: "mainnet",
});
使用 Solana 别名将连接到公共 RPC 端点。这些端点受速率限制,不应在生产应用程序中使用。应用程序应找到自己的 RPC 提供商以及他们提供的 URL。
要为你的本地测试验证器创建一个 RPC 客户端:
import { createSolanaClient } from "gill";
const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
urlOrMoniker: "localnet",
});
要为自定义 RPC 提供商或服务创建一个 RPC 客户端:
import { createSolanaClient } from "gill";
const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
urlOrMoniker: "https://private-solana-rpc-provider.com",
});
在你拥有 Solana rpc
连接后,你可以直接在其上进行所有 JSON RPC 方法 调用。
import { createSolanaClient } from "gill";
const { rpc } = createSolanaClient({ urlOrMoniker: "devnet" });
// 获取 slot
const slot = await rpc.getSlot().send();
// 获取最新的 blockhash
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
rpc
客户端要求你在 RPC 方法上调用.send()
,以便实际将请求发送到你的 RPC 提供商并获取响应。
你还可以在 RPC 调用中包含自定义配置设置,例如使用 JavaScript
AbortController,方法是将其传递到 send()
中:
import { createSolanaClient } from "gill";
const { rpc } = createSolanaClient({ urlOrMoniker: "devnet" });
// 创建一个新的 AbortController。
const abortController = new AbortController();
// 当用户离开当前页面时中止请求。
function onUserNavigateAway() {
abortController.abort();
}
// 仅当用户离开页面时,才会中止请求。
const slot = await rpc.getSlot().send({ abortSignal: abortController.signal });
快速创建 Solana 交易:
注意:
feePayer
可以是Address
或TransactionSigner
。
import { createTransaction } from "gill";
const transaction = createTransaction({
version,
feePayer,
instructions,
// 强烈建议设置计算预算值,以便最大限度地提高交易着陆率
// computeUnitLimit: number,
// computeUnitPrice: number,
});
要在设置最新 blockhash 的同时创建交易:
import { createTransaction } from "gill";
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const transaction = createTransaction({
version,
feePayer,
instructions,
latestBlockhash,
// 强烈建议设置计算预算值,以便最大限度地提高交易着陆率
// computeUnitLimit: number,
// computeUnitPrice: number,
});
如果你的交易已经通过 createTransaction
设置了最新的 blockhash 生存期:
import { createTransaction, signTransactionMessageWithSigners } from "gill";
const transaction = createTransaction(...);
const signedTransaction = await signTransactionMessageWithSigners(transaction);
如果你的交易没有通过 createTransaction
设置最新的 blockhash 生存期,你必须在签署操作之前(或期间)设置最新的
blockhash 生存期:
import {
createTransaction,
createSolanaClient,
signTransactionMessageWithSigners,
setTransactionMessageLifetimeUsingBlockhash,
} from "gill";
const { rpc } = createSolanaClient(...);
const transaction = createTransaction(...);
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const signedTransaction = await signTransactionMessageWithSigners(
setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, transaction),
);
要在区块链上模拟一笔交易,你可以使用从 createSolanaClient()
初始化的 simulateTransaction()
函数。
import { ... } from "gill";
const { simulateTransaction } = createSolanaClient({
urlOrMoniker: "mainnet",
});
const transaction = createTransaction(...);
const simulation = await simulateTransaction(transaction)
提供给 simulateTransaction()
的交易可以是已签名或未签名的。
要将交易发送到区块链并确认,你可以使用从 createSolanaClient()
初始化的 sendAndConfirmTransaction
函数。
import { ... } from "gill";
const { sendAndConfirmTransaction } = createSolanaClient({
urlOrMoniker: "mainnet",
});
const transaction = createTransaction(...);
const signedTransaction = await signTransactionMessageWithSigners(transaction);
const signature: string = getSignatureFromTransaction(signedTransaction);
console.log(getExplorerLink({ transaction: signature }));
// 默认提交级别为“已确认”
await sendAndConfirmTransaction(signedTransaction)
如果你希望更精细地控制 sendAndConfirmTransaction
功能的配置,你可以包含配置设置:
await sendAndConfirmTransaction(signedTransaction, {
commitment: "confirmed",
skipPreflight: true,
maxRetries: 10n,
...
});
在你拥有由 feePayer
签名的交易(部分签名或完全签名)后,你可以按如下方式获取交易签名:
import { getSignatureFromTransaction } from "gill";
const signature: string = getSignatureFromTransaction(signedTransaction);
console.log(signature);
// 示例输出:4nzNU7YxPtPsVzeg16oaZvLz4jMPtbAzavDfEFmemHNv93iYXKKYAaqBJzFCwEVxiULqTYYrbjPwQnA1d9ZCTELg
注意:在交易由费用支付者签名后,它将具有交易签名(也称为交易 ID)。 这是因为 Solana 交易 ID 是交易
signatures
数组中的第一个项目。因此,客户端 应用程序有可能在甚至发送到网络进行确认之前就知道签名。
为任何集群上的交易、帐户或区块制作 Solana Explorer 链接。
如果在
getExplorerLink
函数中未提供cluster
,则默认为mainnet
。
要获取交易签名(也称为交易 ID)的 Explorer 链接:
import { getExplorerLink } from "gill";
const link: string = getExplorerLink({
transaction: "4nzNU7YxPtPsVzeg16oaZvLz4jMPtbAzavDfEFmemHNv93iYXKKYAaqBJzFCwEVxiULqTYYrbjPwQnA1d9ZCTELg",
});
如果你有部分签名或完全签名的交易,你甚至可以在将交易发送到网络之前获取 Explorer 链接:
import {
getExplorerLink,
getSignatureFromTransaction
signTransactionMessageWithSigners,
} from "gill";
const signedTransaction = await signTransactionMessageWithSigners(...);
const link: string = getExplorerLink({
transaction: getSignatureFromTransaction(signedTransaction),
});
要获取 Solana 的 devnet 上帐户的 Explorer 链接:
import { getExplorerLink } from "gill";
const link: string = getExplorerLink({
cluster: "devnet",
account: "nick6zJc6HpW3kfBm4xS2dmbuVRyb5F3AnUvj5ymzR5",
});
要获取本地测试验证器上帐户的 Explorer 链接:
import { getExplorerLink } from "gill";
const link: string = getExplorerLink({
cluster: "localnet",
account: "11111111111111111111111111111111",
});
要获取区块的 Explorer 链接:
import { getExplorerLink } from "gill";
const link: string = getExplorerLink({
cluster: "mainnet",
block: "242233124",
});
要计算帐户的最低租金余额(也称为数据存储押金):
import { getMinimumBalanceForRentExemption } from "gill";
// 当未提供 `space` 参数时:默认为 `0`
const rent: bigint = getMinimumBalanceForRentExemption();
// 预期值:890_880n
// 与相同
// getMinimumBalanceForRentExemption(0);
// 与相同,但这需要网络调用
// const rent = await rpc.getMinimumBalanceForRentExemption(0n).send();
import { getMinimumBalanceForRentExemption } from "gill";
const rent: bigint = getMinimumBalanceForRentExemption(50 /* 50 字节 */);
// 预期值:1_238_880n
// 与相同,但这需要网络调用
// const rent = await rpc.getMinimumBalanceForRentExemption(50n).send();
注意:目前,帐户的最低租金金额是基于 Solana 运行时中的静态值计算的。 虽然你可以在你的 连接上使用
getMinimumBalanceForRentExemption
RPC 调用来获取此值,但这将导致网络调用并受到 延迟的影响。
gill
包具有特定的导入,用于 NodeJS 服务器后端和/或有权访问 Node 特定 API 的无服务器环境(例如通过 node:fs
访问文件系统)。
import { ... } from "gill/node"
import { loadKeypairSignerFromFile } from "gill/node";
// 默认文件路径:~/.config/solana/id.json
const signer = await loadKeypairSignerFromFile();
console.log("address:", signer.address);
从文件系统钱包 json 文件加载 KeyPairSigner
,例如从
Solana CLI 输出的文件(即数字的 JSON 数组)。
默认情况下,加载的密钥对文件是 Solana CLI 的默认密钥对:~/.config/solana/id.json
要从特定文件路径加载签名者:
import { loadKeypairSignerFromFile } from "gill/node";
const signer = await loadKeypairSignerFromFile("/path/to/your/keypair.json");
console.log("address:", signer.address);
有关保存到 env 文件,请参阅
saveKeypairSignerToEnvFile
。
将可提取的 KeyPairSigner
保存到本地 json 文件(例如 keypair.json
)。
import { ... } from "gill/node";
const extractableSigner = generateExtractableKeyPairSigner();
await saveKeypairSignerToFile(extractableSigner, filePath);
有关如何从本地文件系统加载密钥对,请参阅 loadKeypairSignerFromFile
。
从环境变量进程中存储的字节加载 KeyPairSigner
(例如 process.env[variableName]
)
import { loadKeypairSignerFromEnvironment } from "gill/node";
// 从存储在 `process.env[variableName]` 的字节加载签名者
const signer = await loadKeypairSignerFromEnvironment(variableName);
console.log("address:", signer.address);
将可提取的 KeyPairSigner
保存到本地环境变量文件(例如 .env
)。
import { ... } from "gill/node";
const extractableSigner = generateExtractableKeyPairSigner();
// 默认值:envPath = `.env`(在你当前的工作目录中)
await saveKeypairSignerToEnvFile(extractableSigner, variableName, envPath);
有关如何从环境变量加载密钥对,请参阅 loadKeypairSignerFromEnvironment
。
从环境变量进程中存储的字节加载 KeyPairSigner
(例如 process.env[variableName]
)
import { loadKeypairSignerFromEnvironmentBase58 } from "gill/node";
// 从存储在 `process.env[variableName]` 的base58密钥对加载签名者
const signer = await loadKeypairSignerFromEnvironmentBase58(variableName);
console.log("address:", signer.address);
为了简化常见交易的创建,gill 包括各种“交易构建器”,以帮助轻松组装 这些任务的随时可以签名的交易,这些交易通常一次与多个程序交互。
由于每个交易构建器都限定于单个任务,因此它们可以轻松抽象出各种样板代码, 同时还有助于创建优化的交易,包括:
所有自动填充的信息也可以手动覆盖,以确保你始终可以实现 你期望的功能。
由于这些交易构建器可能不适合所有人,因此 gill 为每个 用于构建相应交易的组件公开了一个相关的“指令构建器”功能。开发人员也可以完全放弃这些构建器 抽象并手动构建相同的功能。
构建一个可以使用元数据创建 token 的交易,可以使用 原始 token 或 token 扩展(token22) 程序。
TOKEN_PROGRAM_ADDRESS
,默认)创建的 token 将使用 Metaplex 的 Token Metadata
程序进行链上元数据TOKEN_2022_PROGRAM_ADDRESS
)创建的 token 将使用元数据指针
扩展相关指令构建器:getCreateTokenInstructions
import { buildCreateTokenTransaction } from "gill/programs/token";
const createTokenTx = await buildCreateTokenTransaction({
feePayer: signer,
latestBlockhash,
mint,
// mintAuthority, // default=与 `feePayer` 相同
metadata: {
isMutable: true, // 如果 `updateAuthority` 将来可以更改此元数据
name: "Only Possible On Solana",
symbol: "OPOS",
uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/Climate/metadata.json",
},
// updateAuthority, // default=与 `feePayer` 相同
decimals: 2, // default=9,
tokenProgram, // default=TOKEN_PROGRAM_ADDRESS, 也支持 token22
// 设置默认 cu 限制以进行优化,但可以在此处覆盖
// computeUnitLimit?: number,
// 从你最喜欢的优先级费用 api 获取
// computeUnitPrice?: number, // 未设置默认值
});
构建一个将新 token 铸造到 destination
钱包地址(提高 token 的整体供应量)的交易。
mint
本身使用的正确的 tokenProgram
destination
所有者没有为 mint
创建关联的 token 帐户 (ata),则将自动为他们创建amount
时,请确保考虑到 mint
的 decimals
相关指令构建器:getMintTokensInstructions
import { buildMintTokensTransaction } from "gill/programs/token";
const mintTokensTx = await buildMintTokensTransaction({
feePayer: signer,
latestBlockhash,
mint,
mintAuthority: signer,
amount: 1000, // 注意:请务必考虑 mint 的 `decimals` 值
// 如果 decimals=2 => 这将铸造 10.00 个 token
// 如果 decimals=4 => 这将铸造 0.100 个 token
destination,
// 为 `mint` 使用正确的 token 程序
tokenProgram, // default=TOKEN_PROGRAM_ADDRESS
// 设置默认 cu 限制以进行优化,但可以在此处覆盖
// computeUnitLimit?: number,
// 从你最喜欢的优先级费用 api 获取
// computeUnitPrice?: number, // 未设置默认值
});
构建一个将 token 从 source
(即从 sourceAta
到
destinationAta
)转移到 destination
钱包地址的交易。
mint
本身使用的正确的 tokenProgram
destination
所有者没有为 mint
创建关联的 token 帐户 (ata),则将自动为他们创建amount
时,请确保考虑到 mint
的 decimals
相关指令构建器:getTransferTokensInstructions
import { buildTransferTokensTransaction } from "gill/programs/token";
const transferTokensTx = await buildTransferTokensTransaction({
feePayer: signer,
latestBlockhash,
mint,
authority: signer,
// sourceAta, // default=从 `authority` 派生。
/**
* 如果 `sourceAta` 不是从 `authority` 派生的(例如对于多重签名钱包),
* 使用 `getAssociatedTokenAccountAddress()` 手动派生
*/
amount: 900, // 注意:请务必考虑 mint 的 `decimals` 值
// 如果 decimals=2 => 这将转移 9.00 个 token
// 如果 decimals=4 => 这将转移 0.090 个 token
destination: address(...),
// 为 `mint` 使用正确的 token 程序
tokenProgram, // default=TOKEN_PROGRAM_ADDRESS
// 设置默认 cu 限制以进行优化,但可以在此处覆盖
// computeUnitLimit?: number,
// 从你最喜欢的优先级费用 api 获取
// computeUnitPrice?: number, // 未设置默认值
});
在 gill
中,你可以启用“调试模式”以自动记录其他信息,这些信息将有助于
对你的交易进行故障排除。
默认情况下,调试模式处于禁用状态,以最大限度地减少应用程序的其他日志。但凭借其灵活的调试 控制器,你可以从代码运行的最常见位置启用它。包括你的代码本身、NodeJS 后端、无服务器函数,甚至 Web 浏览器控制台本身。
gill
中存在的一些现有调试日志示例:
mucho inspect
或 Solana Explorer 的
交易检查器要启用调试模式,请将以下任何一项设置为 true
或 1
:
process.env.GILL_DEBUG
global.__GILL_DEBUG__
window.__GILL_DEBUG__
(即在 Web 浏览器的控制台中)要在你的应用程序中设置所需的日志输出级别,请设置以下其中一项的值(默认值:
info
):
process.env.GILL_DEBUG_LEVEL
global.__GILL_DEBUG_LEVEL__
window.__GILL_DEBUG_LEVEL__
(即在 Web 浏览器的控制台中)支持的日志级别(按优先级顺序):
debug
(最低)info
(默认)warn
error
Gill 还导出了它在内部使用的相同调试函数,使你可以实现与
你的 Solana 交易,并使用与 gill
相同的控制器。
isDebugEnabled()
- 检查是否启用了调试模式debug()
- 如果达到设置的日志级别,则打印调试消息import { debug, isDebugEnabled } from "gill";
if (isDebugEnabled()) {
// 你的自定义逻辑
}
// 如果启用了“info”或更高级别的日志级别,则记录此消息
debug("custom message");
// 如果启用了“debug”或更高级别的日志级别,则记录此消息
debug("custom message", "debug");
// 如果启用了“warn”或更高级别的日志级别,则记录此消息
debug("custom message", "warn");
// 如果启用了“warn”或更高级别的日志级别,则记录此消息
debug("custom message", "warn");
使用 gill
,你还可以导入一些最常用的程序客户端。这些客户端也
完全可进行 tree-shaking,因此如果你不在项目中导入它们,它们将在构建时被 JavaScript 打包程序(即 Webpack)删除。
要导入任何这些程序客户端:
import { ... } from "gill/programs";
import { ... } from "gill/programs/token";
注意:某些客户端重新导出的客户端程序客户端具有命名冲突。因此,它们可能会在
gill/programs
的子路径下重新导出。例如,gill/programs/token
。
gill
中包含的程序客户端是:
@solana-program/system
重新导出@solana-program/compute-budget
重新导出@solana-program/memo
重新导出@solana-program/token-2022
重新导出,它是与原始 Token 程序的完全向后兼容的
客户端@solana-program/address-lookup-table
重新导出如果在 gill/programs
或其子路径中未导出其中一个现有客户端,你当然可以
手动将它们的兼容客户端添加到你的存储库。
注意:由于 Token 扩展程序客户端与原始 Token 程序客户端完全兼容,因此
gill
仅发布@solana-program/token-2022
客户端和TOKEN_PROGRAM_ADDRESS
,以便从 库中删除所有冗余代码。要使用原始 Token 程序,只需将
TOKEN_PROGRAM_ADDRESS
作为任何 指令的程序地址传递即可
从 solana-program GitHub 组织(以前称为 Solana 程序库 (SPL)),你可以找到各种其他特定程序的客户端库。安装它们各自的 包以与 gill 结合使用:
如果你想使用此库轻松地与任何自定义程序交互,你可以使用 Codama 来使用其 IDL 生成兼容的 JavaScript/TypeScript 客户端。你可以将生成的客户端存储在你的存储库中,也可以将其作为 NPM 包发布,以便其他人轻松使用。
- 原文链接: github.com/DecalLabs/gil...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!