新消息:Helius 收购 Light Protocol
使用 Gill 开发 Solana 智能合约
博客/开发

如何使用 Gill 构建 Solana 应用

正在构建 @useDecal,曾任职于 @SolanaFndnX 上的 Nick FrostbutterLinkedIn 上的 Nick Frostbutter
阅读需 9 分钟

Gill 是最新的基于 JavaScript/TypeScript 的 Solana 开发者工具库。它最初由 Decal 联合创始人 Nick Frostbutter 在 Solana Foundation 开发者关系团队任职期间开发,旨在显著改善 JavaScript 应用的开发者体验。

Gill 既包含可提高开发效率的轻度约定式抽象,也提供底层原语,让开发者可以灵活选择自己的实现方式。

这些轻量级抽象减少了与 Solana 进行常见交互时涉及的许多复杂性和样板代码。当开发者需要(或希望)更精细地控制应用逻辑时,底层原语则提供了“逃生舱口”。

本文将介绍“gill 库”的基础知识、库中包含的内容、如何开始使用 gill,以及它与 @solana/kit(原名“web3.js v2”)之间的区别。

Gill 是什么?

Gill 是一个现代 TypeScript 库,可用于在任何基于 JavaScript 的环境中开发 Solana 应用,涵盖浏览器、服务器和移动端。

gill 库面向各种经验水平的 Solana 开发者,从初学者到资深开发者都适用。它在同一个包中同时提供高层抽象和底层原语,开发者可在需要时,或抽象层尚未支持相关功能时,轻松使用更高级的功能。 

最棒的是? 

Gill 完全支持 tree-shaking,因此打包工具会自动移除代码库中未使用的原语或抽象。

Gill 的首要目标是改善开发者体验:简化常见的 Solana 开发任务并移除样板代码,同时不牺牲开发者按需深入底层的能力。开发者不应只能在高层抽象或底层原语中二选一,而应能根据实际情况轻松选择最合适的方式。

安装 Gill

Gill 可以安装到任何基于 JavaScript 或 TypeScript 的项目中,包括 NodeJS/Bun、浏览器、React Native,以及几乎所有其他 JavaScript 环境。

代码
npm install gill

gill 库提供完善的 TypeScript 支持,在大多数应用中无需额外配置即可使用。不过,你的具体项目配置可能需要调整,才能更好地与 gill 配合。有关详情,请参阅 gill 的 TypeScript 支持文档。

Gill 与 @solana/kit 对比

gill 库直接构建在 @solana/kit 之上。后者是由 Anza 开发的新型底层 JavaScript 原语,旨在以更高性能取代旧版 @solana/web3.js。

Kit 仅提供这些底层原语,开发者不得不手动构建一切,导致应用体积膨胀并充斥冗长的样板代码。

这正是 gill 的用武之地。

Gill 通过一个统一且兼容的接口,同时提供与 Kit 相同的底层原语,以及用于简化常见任务的轻度约定式抽象。gill 全面简化了开发流程,让开发者可以把更多时间用于应用的业务逻辑,而不是编写冗长的样板代码。

Gill 与 Kit 代码示例对比

以下代码片段展示了如何在保持相同功能的同时简化代码(甚至可能增加更多功能)。几乎所有应用都需要完成两项任务:建立与区块链的连接,以及创建交易。

使用 @solana/kit 创建区块链连接的方法如下:

代码
import {
  devnet,
  createSolanaRpc,
  createSolanaRpcSubscriptions,
  sendAndConfirmTransactionFactory,
} from "@solana/kit";

const rpc = createSolanaRpc(devnet("https://api.devnet.solana.com"));

const rpcSubscriptions = createSolanaRpcSubscriptions(
  devnet("wss://api.devnet.solana.com"),
);

const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
  rpc,
  rpcSubscriptions,
});

使用 gill 的 createSolanaClient 函数,可以更简单地实现相同逻辑:

代码
import { createSolanaClient } from "gill";

const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
  urlOrMoniker: "devnet",
});

现在,你可以使用上述任一库所创建的 rpc 对象发起简单的 RPC 请求:

代码
// get the latest blockhash from your RPC provider
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

在 @solana/kit 中,创建一个包含 memo 指令并带有基础优化(使用计算预算指令)的简单交易,方法如下:

代码
import {
  pipe,
  createTransactionMessage,
  setTransactionMessageFeePayerSigner,
  appendTransactionMessageInstructions,
  setTransactionMessageLifetimeUsingBlockhash,
} from "@solana/kit";
import { getAddMemoInstruction } from "@solana-program/memo";
import {
  getSetComputeUnitLimitInstruction,
  getSetComputeUnitPriceInstruction,
} from "@solana-program/compute-budget";

const transaction = pipe(
  createTransactionMessage({ version: "legacy" }),
  (tx) => setTransactionMessageFeePayerSigner(signer, tx),
  (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  (tx) =>
    appendTransactionMessageInstructions(
      [
        getAddMemoInstruction({
          memo: "gm world!",
        }),
        getSetComputeUnitLimitInstruction({ units: 5000 }),
        getSetComputeUnitPriceInstruction({ microLamports: 1000 }),
      ],
      tx,
    ),
);

使用 gill,可以大幅简化相同逻辑:

代码
import { createTransaction } from "gill";
import { getAddMemoInstruction } from "gill/programs";

const transaction = createTransaction({
  version: "legacy",
  feePayer: signer,
  instructions: [
    getAddMemoInstruction({
      memo: "gm world!",
    }),
  ],
  latestBlockhash,
  computeUnitLimit: 5000,
  computeUnitPrice: 1000,
});

如需更全面地比较这两个库,请查看 gill 文档中的 gill 与 @solana/kit 对比。

从 Kit 迁移到 Gill 需要哪些步骤?

对于任何使用 @solana/kit 库的应用,迁移到 gill 包非常简单:

  1. 安装 gill
  2. 将所有 @solana/kit 导入替换为 gill
  3. 卸载 @solana/kit

由于 gill 还直接包含最常用的 Solana Program Library (SPL) 客户端,你也可以将这些包的导入替换为 gill。Gill 包含以下 SPL 客户端,可直接通过 gill/programs 导入路径访问:

  • @solana-program/system
  • @solana-program/memo
  • @solana-program/compute-budget
  • @solana-program/address-lookup-table
  • @solana-program/token-2022(请参阅下方有关代币程序客户端的说明)

如需使用单个 gill 包访问这些 SPL 程序客户端:

  1. 将上面列出的 @solana-program/* 包导入替换为 gill/programs
  2. 卸载上面列出的 @solana-program/* 包。

更新导入后,你的应用可以立即开始使用“gill core”库。现在,你可以利用任何可用的 gill 抽象,轻松重构掉冗长的 Kit 样板代码,例如创建区块链连接和交易。

Gill 包含哪些组件?

gill 库可以分为几个关键组件:

  • 核心功能(又称“gill core”)
  • 特定于服务器运行时的辅助工具(即 NodeJS 和 Bun)
  • 程序客户端
  • 交易构建器
  • 调试模式

Node.js 辅助函数

gill 包包含多个特定于 JavaScript 服务器运行时的实用工具。虽然它们包含在 gill 包中,但使用了单独的导入路径,以改善 tree-shaking。这些实用工具可用于轻松从文件或 ENV 变量加载密钥对,以及将密钥对保存到文件。

代码
import { ... } from "gill/node"

要从本地文件系统轻松加载密钥对文件(例如 Solana CLI 密钥对),可以使用:

代码
import { loadKeypairSignerFromFile } from "gill/node";

// default file path: ~/.config/solana/id.json
const signer = await loadKeypairSignerFromFile();
console.log("address:", signer.address);

你也可以从 ENV 变量加载 base58 编码的密钥对:

代码
import { loadKeypairSignerFromEnvironmentBase58 } from "gill/node";

// loads signer from base58 keypair stored at `process.env[variableName]`
const signer = await loadKeypairSignerFromEnvironmentBase58(variableName);
console.log("address:", signer.address);

交易构建器

常见交易通常需要同时与多个程序交互。为简化这类交易的创建过程,gill 提供了多种“交易构建器”,帮助你轻松组装可供签名的交易。

由于每个交易构建器都专注于单一任务,因此既能轻松隐藏各类样板代码,也有助于创建经过优化的交易。

gill 提供的部分交易构建器包括:

  • buildCreateTokenTransaction - 创建带元数据的代币
  • buildMintTokensTransaction - 向目标钱包铸造代币
  • buildTransferTokensTransaction - 向目标钱包转移代币

每个交易构建器都配有一个“指令构建器”,让开发者能够更灵活地使用这些 gill 抽象。

调试模式

你可以在 gill 中启用“调试模式”,自动记录额外信息,以便排查交易问题。

调试模式默认关闭,以尽量减少应用产生的额外日志。借助灵活的控制方式,你可以在代码最常运行的位置启用调试模式,包括代码本身、NodeJS 后端、无服务器函数,甚至 Web 浏览器控制台。

要启用调试模式,请将以下任意一项设置为 true 或 1:

  • process.env.GILL_DEBUG
  • global.__GILL_DEBUG__
  • window.__GILL_DEBUG__(例如在 Web 浏览器的控制台中)
  • 或手动设置任意调试日志级别(请参阅文档)

有关更多信息,请查看 gill 的调试模式文档。

使用 Gill 构建应用的配套开发者工具

@gillsdk/react

gill 库中还直接包含另一个包:@gillsdk/react。它是一组 React hooks,旨在大幅改善基于 React 的前端应用的开发者体验。该包还构建在流行的响应式库 TanStack Query 之上,因此现有应用可以更轻松地使用它。

@gillsdk/react 包目前仍处于早期阶段,并在积极开发中。它现在为 Solana 应用提供了多个实用的 React hooks:

  • useAccount - 获取某个地址的账户信息
  • useBalance - 获取账户余额(以 lamports 为单位)
  • useLatestBlockhash - 获取最新区块哈希
  • useSignatureStatuses - 获取签名状态
  • useProgramAccounts - 获取程序账户(GPA)
  • useTokenMint - 获取已解码代币的 Mint 账户
  • useTokenAccount - 获取指定 Mint 和所有者(或 ATA)的代币账户

Codama

Codama 是一个工具,可让开发者使用 Solana 程序的 IDL 生成客户端库(例如 JavaScript、Rust),供其他应用使用。Codama 将构建 Solana 指令涉及的所有复杂工作简化为一个 IDL、一个配置文件和一个函数导入。

Gill 和 Codama 可通过 gill 的 createCodamaConfig 函数轻松集成。gill 的维护者也在积极进一步改进 gill<>Codama 集成,包括在 Codama CLI 中提供直接支持!

默认情况下,Codama 生成的 TypeScript 程序客户端会使用 @solana/kit,但你可以在 Solana 程序的 Codama 配置文件中轻松更新这一设置。借助 createCodamaConfig 函数,可以非常轻松地在 Codama 配置中升级为使用 gill。

下面是一个 codama.js 文件示例,它会生成一个使用 gill 的 Solana 程序 TypeScript 客户端:

代码
import { createCodamaConfig } from "gill";

export default createCodamaConfig({
  idl: "program/idl.json",
  clientJs: "clients/js/src/generated",
});

你可以在 gill 文档中找到使用 Codama 生成 Solana 程序客户端的完整指南。

Gill 的未来

gill 库前景光明,还有许多工作有待完成。官方 gill 文档网站刚刚上线,该库的月下载量也即将达到 20,000 次。

你可以在 GitHub Projects 页面了解 gill 当前路线图的更多信息。目前的重点项目包括:

  • 直接支持 Solana Pay 规范
  • 原生集成数字资产标准(DAS)API 规范
  • 改进对基于代币扩展的代币的支持
  • 改进对地址查找表的支持
  • 提供更全面的文档

gill 库中包含的 @gillsdk/react 包仍处于早期阶段(目前有九个不同的 React hooks)。该包仍在持续开发,旨在让开发者能轻松为基于 React 的应用添加响应式功能,包括支持所有常用的 Solana RPC 方法,并与 wallet-ui 实现更紧密的集成。

趣闻:目前已有计划将 gill 直接集成到 Anchor 框架中,让开发者能在应用内更轻松地利用 gill 的优化和开发者体验改进。说不定,gill 会成为 Anchor v2 的默认选择。:shhh:

如何为 Gill 做贡献

gill 库是开源项目(MIT 许可证),欢迎贡献者参与!如果你有兴趣为这个库做贡献,可以查看任何未解决的 issue,并考虑亲自处理其中一个。

如果你想为这个库建议新功能或改进,请在开始为 PR 编写代码之前,先提交一个 issue,与维护者展开讨论。

其他资源

可通过以下链接获取有关 gill 的更多信息和资源:

订阅 Helius

及时了解 Solana 开发的最新动态,并在我们发布新内容时收到更新