<h1 align="center">gill:Solana区块链的JavaScript/TypeScript客户端库

  • DecalLabs
  • 发布于 2025-07-02 11:52
  • 阅读 33

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">&lt;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">&lt;img src="https://img.shields.io/npm/v/gill?logo=npm&color=377CC0" /></a> <a href="https://www.npmjs.com/package/gill">&lt;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”)。通过在底层使用相同的类型和函数,gillkit 兼容。请参阅 用 gill 替换 Kit

有关使用 gill 与 web3js v2 的比较,请查看 比较示例

安装

使用你选择的包管理器安装 gill

npm install gill
pnpm add gill
yarn add gill

用 gill 替换 Kit

@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();

警告:使用 可提取的 密钥对本质上不太安全,因为它们允许提取密钥材料。 显然。因此,应谨慎使用它们,并且仅当你有明确的原因需要 提取密钥材料(例如,如果你要将密钥保存到文件)。

创建 Solana RPC 连接

为任何 RPC URL 或标准 Solana 网络别名(即 devnetlocalnetmainnet 等)创建 Solana rpcrpcSubscriptions 客户端。

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 调用

在你拥有 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 可以是 AddressTransactionSigner

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 链接

为任何集群上的交易、帐户或区块制作 Solana Explorer 链接。

如果在 getExplorerLink 函数中未提供 cluster,则默认为 mainnet

获取交易的 Solana Explorer 链接

要获取交易签名(也称为交易 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 Explorer 链接

要获取 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",
});

获取区块的 Solana Explorer 链接

要获取区块的 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 调用来获取此值,但这将导致网络调用并受到 延迟的影响。

Node 特定的导入

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

从 base58 环境变量加载密钥对

从环境变量进程中存储的字节加载 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 的交易,可以使用 原始 tokentoken 扩展(token22) 程序。

  • 使用原始 token 程序(TOKEN_PROGRAM_ADDRESS,默认)创建的 token 将使用 Metaplex 的 Token Metadata 程序进行链上元数据
  • 使用 token 扩展程序(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 铸造到目标钱包

构建一个将新 token 铸造到 destination 钱包地址(提高 token 的整体供应量)的交易。

  • 确保你设置了 mint 本身使用的正确的 tokenProgram
  • 如果 destination 所有者没有为 mint 创建关联的 token 帐户 (ata),则将自动为他们创建
  • 在此交易中设置 amount 时,请确保考虑到 mintdecimals

相关指令构建器: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 转移到目标钱包

构建一个将 token 从 source(即从 sourceAtadestinationAta)转移到 destination 钱包地址的交易。

  • 确保你设置了 mint 本身使用的正确的 tokenProgram
  • 如果 destination 所有者没有为 mint 创建关联的 token 帐户 (ata),则将自动为他们创建
  • 在此交易中设置 amount 时,请确保考虑到 mintdecimals

相关指令构建器: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 中存在的一些现有调试日志示例:

  • 在你发送交易时记录它们的 Solana Explorer 链接
  • 记录 base64 交易字符串以通过以下方式进行故障排除 mucho inspect 或 Solana Explorer 的 交易检查器

如何启用调试模式

要启用调试模式,请将以下任何一项设置为 true1

  • 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 中包含的程序客户端是:

如果在 gill/programs 或其子路径中未导出其中一个现有客户端,你当然可以 手动将它们的兼容客户端添加到你的存储库。

注意:由于 Token 扩展程序客户端与原始 Token 程序客户端完全兼容,因此 gill 仅发布 @solana-program/token-2022 客户端和 TOKEN_PROGRAM_ADDRESS,以便从 库中删除所有冗余代码。

要使用原始 Token 程序,只需将 TOKEN_PROGRAM_ADDRESS 作为任何 指令的程序地址传递即可

其他兼容的程序客户端

solana-program GitHub 组织(以前称为 Solana 程序库 (SPL)),你可以找到各种其他特定程序的客户端库。安装它们各自的 包以与 gill 结合使用:

从 IDL 生成程序客户端

如果你想使用此库轻松地与任何自定义程序交互,你可以使用 Codama 来使用其 IDL 生成兼容的 JavaScript/TypeScript 客户端。你可以将生成的客户端存储在你的存储库中,也可以将其作为 NPM 包发布,以便其他人轻松使用。

  • 原文链接: github.com/DecalLabs/gil...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
DecalLabs
DecalLabs
江湖只有他的大名,没有他的介绍。