Gill 是一个新的 JavaScript 客户端库,用于与 Solana 区块链交互。
介绍 Gill:用于与 Solana 区块链交互的全新 JavaScript 客户端库。它基于 Anza 构建的现代 Solana JavaScript 库。它利用了 Web3 JS 第二版的速度和优雅性,并提供了一个轻量级且高度抽象的解决方案。它轻量、快速,并具有可摇树优化的架构。你可以使用它在 Node、Web、React Native 或几乎任何其他 JavaScript 环境中构建 Solana d-app。
由于 Solana Web3.js v2 在性能方面非常出色,具有可摇树优化的架构,但在你所做的每件事中,由于其更长的函数名称和超模块化的子包,感觉很冗长,因此 Gill 与 v2 完全兼容,并通过改进的开发者体验 (DevEx) 提供了更容易的采用曲线。
Gill 为 Web3.js v2、流行的 SPL 程序(如 System、Compute Budget、Memo、Token、Token22)以及生态系统程序(如 Metaplex 的 Token Metadata)提供了一个单一入口点。
Gill 提供 Transaction Builders(交易构建器),可以轻松地为常见的 Solana 任务组装随时可签名的交易,例如创建带有元数据的 Token、铸造 Token 和转移 Token。这些任务通常涉及一次与多个程序交互。
Gill 可用于在 Node、Web、React Native 或任何其他 JavaScript 环境中构建 Solana d-app。
Gill 提供了一个 debug mode(调试模式),你可以启用它来自动记录有助于解决交易问题的其他信息。你可以从代码运行的最常见位置启用它,包括在代码中、Node.js 后端、无服务器函数中,甚至直接在 Web 浏览器控制台中。
Gill 提供与 Solana Web3.js v2 (Solana Kit) 相同的功能,但具有改进的命名和简化的常见 Solana 任务方法。
通过使用 Gill,你可以完成以下操作:
生成随机密钥对 - 使用 generateKeyPairSigner 生成一个不可提取的密钥对,用于签署交易。不可提取的 意味着私钥无法从实例中检索,从而为密钥对提供增强的安全性。
生成随机可提取密钥对 - 使用 generateExtractableKeyPairSigner 生成可提取的密钥对。这些不太安全,因为它们允许提取密钥材料。
从文件加载钱包 - 使用 loadKeypairSignerFromFile 从文件系统钱包 JSON 文件加载密钥对签名者。默认情况下,此函数加载 Solana CLI 使用的文件中存储的钱包密钥对:~/.config/solana/id.json。它还会解析使用 ~ 字符表示用户主目录的相对路径。
从环境变量加载密钥对 - 使用 loadKeypairSignerFromEnvironment 从环境变量中存储的字节加载 keypairSigner,与标准 Solana 工具一致。
创建 Solana RPC 连接 - 使用 createSolanaClient 创建一个 Solana 客户端,其中包含你喜欢的 RPC 端点 URL 或标准 Solana 网络别名(例如,devnet、localnet、mainnet 等)。
要进行 RPC 调用,RPC 客户端需要你在 RPC 方法上调用 .send(),以将请求发送到你的 RPC 提供程序并接收响应。
创建交易 - 使用 createTransaction 方法轻松创建具有所有标准参数的交易。
签名和发送交易 - 在你拥有可签名的交易后,你可以使用 signTransactionMessageWithSigners 对其进行签名,使用 getSignatureFromTransaction 检索签名(甚至在将其发送到网络之前),并使用 sendAndConfirmTransaction 发送交易。
获取 Solana Explorer 链接 - 使用 getExplorerLink 方法为交易、帐户或区块生成 Solana Explorer 链接。
交易构建器 - 为了简化常见的 Solana 任务(如创建 Token、铸造 Token 和转移 SPL Token),Gill 引入了 Transaction Builders(交易构建器),以帮助轻松地为这些任务组装随时可签名的交易。
至此,我们已经了解了 Gill 是什么,为什么它对开发者有帮助,以及它可以完成的常见任务。现在,让我们看一个使用 Gill 和 Web3.js v2 创建 Token 的示例:
使用 Gill 创建“OPOS”Token -:
import {
  createSolanaClient,
  signTransactionMessageWithSigners,
  getSignatureFromTransaction,
  getExplorerLink,
  createKeyPairSignerFromBytes,
  getBase58Codec,
  generateKeyPairSigner
} from "gill";
import { buildCreateTokenTransaction, TOKEN_2022_PROGRAM_ADDRES } from "gill/programs/token";
const { rpc, sendAndConfirmTransaction } = createSolanaClient({
  urlOrMoniker: "devnet",
});
// get the latest blockhash
// 获取最新的区块哈希
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const keypairBase58feePayer = "your_secret_key";
const keypairBytesfeePayer = getBase58Codec().encode(keypairBase58feePayer);
const feepayersigner = await createKeyPairSignerFromBytes(keypairBytesfeePayer);
async function createTokenFunc() {
  const mint = await generateKeyPairSigner();
  // create tokens
  // 创建 Token
  const createTokenTx = await buildCreateTokenTransaction({
    feePayer: feepayersigner,
    latestBlockhash,
    mint: mint,  // Use mintKey here
    metadata: {
      isMutable: true, // if the `updateAuthority` can change this metadata in the future
      // 如果 `updateAuthority` 将来可以更改此元数据
      name: "Only Possible On Solana",
      symbol: "OPOS",
      uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/Climate/metadata.json",
    },
    decimals: 2,
    tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
  });
  const signedTransaction = await signTransactionMessageWithSigners(createTokenTx);
  const signature: string = getSignatureFromTransaction(signedTransaction);
  console.log(getExplorerLink({ transaction: signature }));
  // default commitment level of `confirmed`
  // 默认的 `确认` 承诺级别
  await sendAndConfirmTransaction(signedTransaction);
}
createTokenFunc().catch(console.error);
使用 Gill 创建“OPOS”Token:
import {
    airdropFactory,
    appendTransactionMessageInstructions,
    createSolanaRpc,
    createSolanaRpcSubscriptions,
    createTransactionMessage,
    generateKeyPairSigner,
    getSignatureFromTransaction,
    lamports,
    pipe,
    sendAndConfirmTransactionFactory,
    setTransactionMessageFeePayerSigner,
    setTransactionMessageLifetimeUsingBlockhash,
    signTransactionMessageWithSigners,
    some,
  } from "@solana/web3.js";
  import { getCreateAccountInstruction } from "@solana-program/system";
  import {
    getInitializeMintInstruction,
    getMintSize,
    TOKEN_2022_PROGRAM_ADDRESS,
    extension,
    getInitializeMetadataPointerInstruction,
    getInitializeTokenMetadataInstruction,
    tokenMetadataField,
    getUpdateTokenMetadataFieldInstruction,
  } from "@solana-program/token-2022";
  const rpc = createSolanaRpc("http://127.0.0.1:8899");
  const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");
  const feePayer = await generateKeyPairSigner();
  console.log(feePayer.address);
  const mint = await generateKeyPairSigner();
  await airdropFactory({ rpc, rpcSubscriptions })({
    recipientAddress: feePayer.address,
    lamports: lamports(1_000_000_000n),
    commitment: "confirmed",
  });
  const balance = await rpc.getBalance(feePayer.address).send();
  console.log("balance:", balance.value);
  const metadataPointerExtension = extension("MetadataPointer", {
    authority: some(feePayer.address),
    metadataAddress: some(mint.address),
  });
  const tokenMetadataExtension = extension("TokenMetadata", {
    updateAuthority: some(feePayer.address),
    mint: mint.address,
    name: "Only Possible On Solana",
    symbol: "OPOS",
    uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/Climate/metadata.json",
    additionalMetadata: new Map<string, string>([["description", "Only Possible On Solana"]]),
  });
  const spaceWithoutMetadata = BigInt(getMintSize([metadataPointerExtension]));
  const spaceWithMetadata = BigInt(getMintSize([metadataPointerExtension, tokenMetadataExtension]));
  const rent = await rpc.getMinimumBalanceForRentExemption(spaceWithMetadata).send();
  const createAccountInstruction = getCreateAccountInstruction({
    payer: feePayer,
    newAccount: mint,
    lamports: rent,
    space: spaceWithoutMetadata,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS,
  });
  const initializeMetadataPointerInstruction = getInitializeMetadataPointerInstruction({
    mint: mint.address,
    authority: feePayer.address,
    metadataAddress: mint.address,
  });
  const initializeMintInstruction = getInitializeMintInstruction({
    mint: mint.address,
    decimals: 2,
    mintAuthority: feePayer.address,
  });
  const initializeTokenMetadataInstruction = getInitializeTokenMetadataInstruction({
    metadata: mint.address,
    updateAuthority: feePayer.address,
    mint: mint.address,
    mintAuthority: feePayer,
    name: tokenMetadataExtension.name,
    symbol: tokenMetadataExtension.symbol,
    uri: tokenMetadataExtension.uri,
  });
  const updateTokenMetadataInstruction = getUpdateTokenMetadataFieldInstruction({
    metadata: mint.address,
    updateAuthority: feePayer,
    field: tokenMetadataField("Key", ["description"]),
    value: "Only Possible On Solana",
  });
  const instructions = [\
    createAccountInstruction,\
    initializeMetadataPointerInstruction,\
    initializeMintInstruction,\
    initializeTokenMetadataInstruction,\
    updateTokenMetadataInstruction,\
  ];
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
  const transactionMessage = pipe(
    createTransactionMessage({ version: 0 }),
    (message) => setTransactionMessageFeePayerSigner(feePayer, message),
    (message) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, message),
    (message) => appendTransactionMessageInstructions(instructions, message),
  );
  const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
  const transactionSignature = getSignatureFromTransaction(signedTransaction);
  await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction, {
    commitment: "confirmed",
    skipPreflight: true,
  });
  console.log("Transaction Signature:", `https://explorer.solana.com/tx/${transactionSignature}?cluster=custom`);
正如你所看到的,由于其交易构建器和比 Web3.js v2 更高级别的抽象,使用 Gill 创建 Token 非常容易。使用一个交易构建器和一些代码行,我们创建了一个 SPL Token。
现在我们了解了 Gill 是什么、为什么它很重要以及它如何增强 Web3.js v2 的开发者体验,现在是编写一个简单的 SPL Token 铸造和转移示例的时候了。开始吧!
众所周知,有很多方法可以铸造或创建 SPL Token。我们可以使用带有 Solana Web3.js 和 Solana 开发者助手的 JavaScript/TypeScript 来处理 SPL Token,或者用 Rust/Anchor 创建一个 Solana 程序来铸造 SPL Token。在本指南中,我们将使用 Gill 库来铸造 SPL Token。我们还将利用最快的方法,即利用 Gill 的预构建交易构建器方法来进行各种交易。
ts-node对于本项目,package.json 文件中的依赖项将如下所示:
"dependencies": {
    "esrun": "^3.2.26",
    "gill": "^0.6.0"
  },
  "devDependencies": {
    "@types/node": "^22.13.10",
    "ts-node": "^10.9.2",
    "typescript": "^5.8.2"
  }让我们设置一个新项目:
mkdir spl-token && cd spl-token将你的项目初始化为 Node.js 项目:
npm init -y安装所需的依赖项:
pnpm install gill esrun && pnpm install --save-dev @types/node typescript ts-node在你的项目目录中创建一个名为 spl-token.ts 的新文件:
echo > spl-token.ts太棒了!现在,让我们开始编码。
在你的 spl-token.ts 文件中,让我们首先导入必要的依赖项:
import {
    address,
    KeyPairSigner,
    getBase58Codec,
    getExplorerLink,
    createSolanaClient,
    generateKeyPairSigner,
    getSignatureFromTransaction,
    createKeyPairSignerFromBytes,
    signTransactionMessageWithSigners,
    setTransactionMessageLifetimeUsingBlockhash,
  } from "gill";
  import {
    buildCreateTokenTransaction,
    buildMintTokensTransaction,
    buildTransferTokensTransaction
  } from "gill/programs/token";我们正在从 Gill 库导入关键函数,以创建、铸造和转移 SPL Token。
  // create Rpc connection
  // 创建 Rpc 连接
  const { rpc, sendAndConfirmTransaction } = createSolanaClient({
    urlOrMoniker: "devnet",
  });
  // get slot
  // 获取插槽
  const slot = await rpc.getSlot().send();
  // get the latest blockhash
  // 获取最新的区块哈希
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();我们使用 Gill 的 createSolanaClient 方法来建立与 Devnet 的 RPC 连接。要调用任何 RPC 方法,我们需要在 RPC 方法上使用 .send() 将请求发送到 RPC 提供程序并接收响应。
 const keypairBase58alice = "your_wallet_secret_key";
 const keypairBytesalice = getBase58Codec().encode(keypairBase58alice);
 const aliceKeyPair = await createKeyPairSignerFromBytes(keypairBytesalice);
 // KeyPairs and addresses
 // 密钥对和地址
 const alice = aliceKeyPair.address;
 const bob = address("4d4zsfq4gtJixDGvisSdFjsY78uH7BypkwmkXL1D8RfT");
 const mint = await generateKeyPairSigner();
在这里,我们生成 Alice、Bob 和 Mint 的地址。对于 Alice,我们使用一个密钥对来生成她的地址。在本指南中,Alice 将在她自己的钱包中创建和铸造 Token,然后将铸造的 Token 发送到 Bob 的钱包。
接下来,让我们创建我们的 main(主) 函数,它将包含我们脚本的逻辑:
async function main(){
// Create token transaction
// 创建 Token 交易
// Mint token transaction
// 铸造 Token 交易
// Transfer tokens transaction
// 转移 Token 交易
}
main().catch(console.error);让我们将以下代码添加到主函数作为第一步:
const createTokenTx = await buildCreateTokenTransaction({
      feePayer: aliceKeyPair,
      latestBlockhash,
      mint: mint,  // Use mintKey here
      // 在此处使用 mintKey
      metadata: {
        isMutable: true, // if the `updateAuthority` can change this metadata in the future
        // 如果 `updateAuthority` 将来可以更改此元数据
        name: "Only Possible On Solana",
        symbol: "OPOS",
        uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/Climate/metadata.json",
      },
      decimals: 2,
    });
const signedTransaction = await signTransactionMessageWithSigners(createTokenTx);
const signature: string = getSignatureFromTransaction(signedTransaction);
console.log(getExplorerLink({ transaction: signatureformint }));
// default commitment level of `confirmed`
// 默认的 `确认` 承诺级别
await sendAndConfirmTransaction(signedTransaction);在这里,我们使用 Gill 的 buildCreateTokenTransaction tx 构建器来创建一个 SPL Token,指定 aliceKeypair 作为 feePayer,并为 Token 提供元数据。
接下来,我们使用 signTransactionMessageWithSigners 对交易进行签名,然后再将其发送到网络,类似于 Web3.js。然后,我们使用 getSignatureFromTransaction 获取签名,最后使用 sendAndConfirmTransaction 将交易发送到网络。
恭喜!我们的 OPOS Token 已经创建。请查看 Solana Explorer 链接以获取详细信息。
让我们将以下代码添加到主函数作为第二步:
const mintTokensTx = await buildMintTokensTransaction({
      feePayer: aliceKeyPair,
      latestBlockhash,
      mint,
      mintAuthority: aliceKeyPair,
      amount: 1000, // note: be sure to consider the mint's `decimals` value
      // 注意:请务必考虑 mint 的 `decimals` 值
      // if decimals=2 => this will mint 10.00 tokens
      // 如果 decimals=2 => 这将铸造 10.00 个 Token
      // if decimals=4 => this will mint 0.100 tokens
      // 如果 decimals=4 => 这将铸造 0.100 个 Token
      destination: alice,
      // use the correct token program for the `mint`
      // 使用正确的 Token 程序来处理 `mint`
      // tokenProgram, // default=TOKEN_PROGRAM_ADDRESS
      // 默认值=TOKEN_PROGRAM_ADDRESS
      // default cu limit set to be optimized, but can be overriden here
      // 默认的 cu 限制设置为优化,但可以在此处覆盖
      // computeUnitLimit?: number,
      // obtain from your favorite priority fee api
      // 从你最喜欢的优先费用 api 获取
      // computeUnitPrice?: number, // no default set
      // 没有设置默认值
    });
    const signedTransactionformint = await signTransactionMessageWithSigners(mintTokensTx);
    const signatureformint: string = getSignatureFromTransaction(signedTransactionformint);
    console.log(getExplorerLink({ transaction: signatureformint }));
    // default commitment level of `confirmed`
    // 默认的 `确认` 承诺级别
    await sendAndConfirmTransaction(signedTransactionformint);在这里,我们使用 Gill 的 buildMintTokensTransaction tx 构建器将 Token 铸造到 Alice 的地址,对交易进行签名,获取签名,并将交易发送到网络。
你无需担心关联的 Token 账户,因为在交易构建器中,如果目标所有者没有 mint 的关联 Token 账户 (ATA),则会自动为其创建一个。
恭喜!你已将 10 个 OPOS SPL Token 铸造到 Alice 的 Token 账户中。
让我们将以下代码添加到主函数作为第三步:
const transferTokensTx = await buildTransferTokensTransaction({
      feePayer: aliceKeyPair,
      latestBlockhash,
      mint,
      authority: aliceKeyPair,
      // sourceAta, // default=derived from the `authority`.
      // 默认值=从 `authority` 派生。
      /*
       * if the `sourceAta` is not derived from the `authority` (like for multi-sig wallets),
       * 如果 `sourceAta` 不是从 `authority` 派生的(例如对于多重签名钱包),
       * manually derive with `getAssociatedTokenAccountAddress()`
       * 使用 `getAssociatedTokenAccountAddress()` 手动派生
      */
      amount: 900, // note: be sure to consider the mint's `decimals` value
      // 注意:请务必考虑 mint 的 `decimals` 值
      // if decimals=2 => this will transfer 9.00 tokens
      // 如果 decimals=2 => 这将转移 9.00 个 Token
      // if decimals=4 => this will transfer 0.090 tokens
      // 如果 decimals=4 => 这将转移 0.090 个 Token
      destination: bob,
      // use the correct token program for the `mint`
      // 使用正确的 Token 程序来处理 `mint`
      //  tokenProgram, // default=TOKEN_PROGRAM_ADDRESS
      // 默认值=TOKEN_PROGRAM_ADDRESS
      // default cu limit set to be optimized, but can be overriden here
      // 默认的 cu 限制设置为优化,但可以在此处覆盖
      // computeUnitLimit?: number,
      // obtain from your favorite priority fee api
      // 从你最喜欢的优先费用 api 获取
      // computeUnitPrice?: number, // no default set
      // 没有设置默认值
    });
    const signedTransactionfortransfer = await signTransactionMessageWithSigners(transferTokensTx);
    const signaturefortransfer: string = getSignatureFromTransaction(signedTransactionfortransfer);
    console.log(getExplorerLink({ transaction: signaturefortransfer }));
    // default commitment level of `confirmed`
    // 默认的 `确认` 承诺级别
    await sendAndConfirmTransaction(signedTransactionfortransfer);我们使用 buildTransferTokensTransaction 方法将 SPL Token 从 Alice 转移到 Bob,然后签名、获取签名并将其发送到网络。关联的 Token 账户 (ATA) 也会为此 mint 自动为 Bob 的钱包创建。
恭喜!你已将 9 个 OPOS Token 从 Alice 的 Token 账户转移到 Bob 的 Token 账户。
在你的终端中,键入:
npx esrun ./index.ts成功执行后,你应该会看到每个操作的三个 Solana Explorer 链接的输出:创建、铸造和转移“OPOS”Token。
https://explorer.solana.com/tx/58KC1GPc1f8aCUox6Pst7YheYRCqrQY9Np2gP6LfqDP5ogQjP5Hy76opzmJ8EKW2PyMdoGh71MYGWHL6oYHLAvdD
https://explorer.solana.com/tx/4DXAFBfsAVCgZ3X3rwEZ72EN81JVWj2zpzsYERCu5xitf1aztuytn9og3cyNbNeR3t5KnaJgneNckFy6MGAoWLGr
https://explorer.solana.com/tx/4PkHW9dSbQicKcempBoD3VCe2xQhJidJ6gptXPNvq4LVRBzJYAQrN5AGcaVfu88NabrczkgV8FrF4x1sVxKB7xSHGill 是一个新的 JavaScript 客户端库,用于与 Solana 区块链交互。在这篇文章中,我们讨论了 Gill 是什么、为什么它对 Solana 开发者很重要,以及它如何帮助改善开发者体验。我们还探讨了它的关键特性,提供了将其与 Web3.js v2 进行比较的示例,并演示了如何使用 Gill 创建和铸造 SPL Token。
总的来说,你会发现 Gill 在使用 Web3.js v2 时提供了出色的开发者体验。
- 原文链接: dev.to/shivamsspirit/int...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!